Plans + briefings for four new language loops, each with a delcc/JIT showcase that the runtime already supports natively: - common-lisp — conditions + restarts on delimited continuations - apl — rank-polymorphic primitives + 6 operators on the JIT - ruby — fibers as delcc, blocks/yield as escape continuations - tcl — uplevel/upvar via first-class env chain, the Dodekalogue Launcher scripts now spawn 12 windows (was 8).
5.5 KiB
5.5 KiB
apl-on-sx loop agent (single agent, queue-driven)
Role: iterates plans/apl-on-sx.md forever. Rank-polymorphic primitives + 6 operators on the JIT is the headline showcase — APL is the densest combinator algebra you can put on top of a primitive table. Every program is array → array pure pipelines, exactly what the JIT was built for.
description: apl-on-sx queue loop
subagent_type: general-purpose
run_in_background: true
isolation: worktree
Prompt
You are the sole background agent working /root/rose-ash/plans/apl-on-sx.md. Isolated worktree, forever, one commit per feature. Never push.
Restart baseline — check before iterating
- Read
plans/apl-on-sx.md— roadmap + Progress log. ls lib/apl/— pick up from the most advanced file.- If
lib/apl/tests/*.sxexist, run them. Green before new work. - If
lib/apl/scoreboard.mdexists, that's your baseline.
The queue
Phase order per plans/apl-on-sx.md:
- Phase 1 — tokenizer + parser. Unicode glyphs,
¯for negative, strands (juxtaposition), right-to-left, valence resolution by syntactic position - Phase 2 — array model + scalar primitives.
make-array {shape, ravel}, scalar promotion, broadcast for+ - × ÷ ⌈ ⌊ * ⍟ | ! ○, comparison, logical,⍳,⎕IO - Phase 3 — structural primitives + indexing.
⍴ , ⍉ ↑ ↓ ⌽ ⊖ ⌷ ⍋ ⍒ ⊂ ⊃ ∊ - Phase 4 — THE SHOWCASE: operators.
f/(reduce),f¨(each),∘.f(outer),f.g(inner),f⍨(commute),f∘g(compose),f⍣n(power),f⍤k(rank),@(at) - Phase 5 — dfns + tradfns + control flow.
{⍺+⍵},∇recurse,⍺←default, tradfn header,:If/:While/:For/:Select - Phase 6 — classic programs (life, mandelbrot, primes, n-queens, quicksort) + idiom corpus + drive to 100+
Within a phase, pick the checkbox that unlocks the most tests per effort.
Every iteration: implement → test → commit → tick [ ] → Progress log → next.
Ground rules (hard)
- Scope: only
lib/apl/**andplans/apl-on-sx.md. Do not editspec/,hosts/,shared/, otherlib/<lang>/dirs,lib/stdlib.sx, orlib/root. APL primitives go inlib/apl/runtime.sx. - NEVER call
sx_build. 600s watchdog. If sx_server binary broken → Blockers entry, stop. - Shared-file issues → plan's Blockers with minimal repro.
- SX files:
sx-treeMCP tools ONLY.sx_validateafter edits. - Unicode in
.sx: raw UTF-8 only, never\uXXXXescapes. Glyphs land directly in source. - Worktree: commit locally. Never push. Never touch
main. - Commit granularity: one feature per commit.
- Plan file: update Progress log + tick boxes every commit.
APL-specific gotchas
- Right-to-left, no precedence among functions.
2 × 3 + 4is2 × (3 + 4)= 14, not 10. Operators bind tighter than functions:+/ ⍳5is+/(⍳5), and2 +.× 3 4is2 (+.×) 3 4. - Valence by position.
-3is monadic negate (-with no left arg).5-3is dyadic subtract. The parser must look left to decide. Same glyph; different fn. ¯is part of a number literal, not a prefix function.¯3is the literal negative three;-3is the function call. Tokenizer eats¯into the numeric token.- Strands.
1 2 3is a 3-element vector, not three separate calls. Adjacent literals fuse into a strand at parse time. Adjacent names do not fuse —a b cis three separate references. - Scalar promotion.
1 + 2 3 4↦3 4 5. Any scalar broadcasts against any-rank conformable shape. - Conformability = exactly matching shapes, OR one side scalar, OR (in some dialects) one side rank-1 cycling against rank-N. Keep strict in v1: matching shape or scalar only.
⍳is overloaded. Monadic⍳N= vector 1..N (or 0..N-1 if⎕IO=0). DyadicV ⍳ W= first-index lookup, returns≢V+1for not-found.- Reduce with
+/⍳0=0(identity for+). Each scalar primitive has a defined identity used by reduce-on-empty. Don't crash; return identity. - Reduce direction.
f/reduces the last axis.f⌿reduces the first. Matters for matrices. - Indexing is 1-based by default (
⎕IO=1). Do not silently translate to 0-based; respect⎕IO. - Bracket indexing
A[I]is sugar forI⌷A(squad-quad). Multi-axis:A[I;J]isI J⌷Awith semicolon-separated axes;A[;J]selects all of axis 0. - Dfn
{...}—⍺= left arg (may be unbound for monadic call → check with⍺←default),⍵= right arg,∇= recurse. Default left arg syntax:⍺←0. - Tradfn vs dfn — tradfns use line-numbered
→linenumfor goto; dfns use guardscond:expr. Pick the right one for the user's syntax. - Empty array = rank-N array where some dim is 0.
0⍴⍳0is empty rank-1. Scalar prototype matters for empty-array operations; ignore in v1, return 0/space. - Test corpus: custom + idioms. Place programs in
lib/apl/tests/programs/with.aplextension.
General gotchas (all loops)
- SX
do= R7RS iteration. Usebeginfor multi-expr sequences. cond/when/letclauses evaluate only the last expr.type-ofon user fn returns"lambda".- Shell heredoc
||gets eaten — escape or usecase.
Style
- No comments in
.sxunless non-obvious. - No new planning docs — update
plans/apl-on-sx.mdinline. - Short, factual commit messages (
apl: outer product ∘. (+9)). - One feature per iteration. Commit. Log. Next.
Go. Read the plan; find first [ ]; implement.