Files
akbasic/docs/11-verb-reference.md
Tachikoma f7e8d4b82b
All checks were successful
akbasic CI Build / cmake_build (push) Successful in 3m32s
akbasic CI Build / coverage (push) Successful in 4m7s
akbasic CI Build / sanitizers (push) Successful in 4m42s
akbasic CI Build / akgl_build (push) Successful in 8m12s
akbasic CI Build / mutation_test (push) Successful in 23m3s
Implement generators: GEN, EMIT, END GEN, FOR EACH and DO EACH (issue 57)
Adds generator support per the plan in issue 57:

- environment.h: isGenerator/generatorFn on a GEN call's own environment,
  isEachLoop and forGeneratorEnv on a FOR EACH/DO EACH loop's own
  environment.
- runtime.c: splits akbasic_runtime_prev_environment() into
  akbasic_runtime_detach_environment() (return to parent without releasing)
  and akbasic_runtime_release_environment() (give variables and the pool
  slot back, on any environment); prev_environment() is now the two in
  sequence. akbasic_runtime_call_function() refuses to call a GEN like an
  ordinary function.
- verbs.c/verbs.h/scanner: new keywords GEN, EMIT, EACH, IN and the compound
  verb "END GEN" (built by a new akbasic_parse_end(), the same trick
  akbasic_parse_print() uses for PRINT #).
- parser_commands.c: akbasic_parse_gen() (modelled on multi-line DEF),
  akbasic_parse_end(), and EACH branches in akbasic_parse_for()/
  akbasic_parse_do().
- runtime_generator.c (new): akbasic_cmd_gen, akbasic_cmd_emit,
  akbasic_cmd_end_gen, and the invoke/pump/release machinery FOR EACH, DO
  EACH, NEXT and LOOP share. EMIT walks up to the nearest isGenerator
  ancestor rather than assuming it is standing directly in the GEN's own
  call frame, because a GEN body may nest its own FOR/DO/GOSUB around an
  EMIT -- the issue's own ROOMOBJECTS example does exactly that.
- runtime_commands.c/runtime_structure.c: EACH branches in cmd_for/cmd_do,
  matching EACH branches in cmd_next/cmd_loop, and forGeneratorEnv release
  on every path that can abandon a live generator (EXIT, a NEXT that pops
  for a mismatched loop variable).

Deviates from the plan in one place: FunctionDef gained an isGenerator flag
(not in the plan's field list) because refusing a GEN called like a
function has to happen before anything is pushed. Relying on EMIT's own
isGenerator check for that case doesn't work: akbasic_runtime_call_function()
drives its own step loop the same way akbasic_runtime_pump_generator() does,
and a BASIC-level error inside that loop is swallowed by process_line_run()
as reported-but-not-propagated, so the call would silently "succeed" with a
meaningless return value instead of failing.

Also: a zero-argument parameter list is not supported by the DEF/GEN
parameter parser this reuses (a pre-existing limitation, not
generator-specific); every generator in the tests takes at least one
parameter as a result.

Tests: tests/generators.c (pool exhaustion under repeated EXIT, calling a
GEN like a function, EMIT outside a GEN, self-recursion, sibling/nested
invocations) and tests/language/flowcontrol/generators_*.bas -- the
issue's own ROOMOBJECTS example in both loop shapes, an empty generator,
non-numeric EMIT, nested/interleaved invocations, and three error-path
golden cases. Docs: control-flow chapter 4 gets a GEN/EMIT/FOR EACH/DO EACH
section, the verb reference gets GEN/EMIT/END GEN entries and updated
FOR/DO/NEXT/LOOP/EXIT rows, and architecture chapter 14 documents the
detach/release split and the two-environment generator invocation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 10:02:43 -04:00

10 KiB

11. Verb reference

Every statement, alphabetically. This list is generated from the interpreter's own dispatch table, so it cannot drift out of step with what the program actually accepts.

A verb marked Refused parses and then reports why it cannot run — see Chapter 13 for the reasoning in each case.

Verb Form What it does
APPEND APPEND n, "name" Open a file on channel n for writing at its end.
AUTO AUTO n Number lines automatically in steps of n. AUTO 0 turns it off.
BACKUP BACKUP Refused. Duplicates one disk onto another; there are no disks.
BEGIN IF c THEN BEGIN Start a block that runs to BEND, so an IF can span lines.
BEND BEND End a BEGIN block.
BLOAD BLOAD "name", addr, len Read a file into memory. The length is required.
BOOT BOOT Refused. Loads and runs a boot sector; there is none.
BOX BOX src, x1, y1, x2, y2 [,angle] Outline a rectangle, optionally rotated.
BSAVE BSAVE "name", from, to Write a range of memory to a file.
CATALOG CATALOG Refused. The other name for DIRECTORY.
CHAR CHAR col, x, y, "text" Put text at a character cell. Needs a sink with a cursor. Terminates the row where it stops, so it erases whatever followed.
CIRCLE CIRCLE src, x, y, rx, ry [,...] Draw an ellipse, arc or polygon.
CLR CLR Drop every variable and function, keeping the program.
COLLECT COLLECT Refused. Validates a disk's block allocation map.
COLLISION COLLISION type [,target] Call a subroutine when sprites collide. No target disarms it.
COLOR COLOR src, index Bind a colour source to a palette index, 1 to 16.
CONCAT CONCAT "a", "b" Append file a to file b.
CONT CONT Resume a program stopped by STOP.
COPY COPY "a", "b" Copy file a to file b.
DATA DATA v [, ...] Declare values for READ. Collected before the program runs.
DCLEAR DCLEAR Close every open channel. The half of a drive reset that means something.
DCLOSE DCLOSE [n] Close channel n, or every channel.
DEF DEF NAME(args) = expr Define a function. Multi-line definitions end in RETURN.
DELETE DELETE [n][-n] Delete lines, with the same range forms as LIST.
DIALOG DIALOG ["text"] Show a text panel across the bottom of the screen. No argument takes it down. See Chapter 19.
DIM DIM A#(n [,...]) Make an array. Subscripts start at zero; n is the count.
DIMAS DIM S@ AS T, DIM P@ AS PTR TO T Make a structure, or a strict pointer to one. See Chapter 16.
DIRECTORY DIRECTORY Refused. Not written yet; the standard-library wrapper it waited on has landed.
DLOAD DLOAD "name" Load a program from a file.
DO `DO [WHILE c UNTIL c], DO EACH V IN gen(args)`
DOPEN DOPEN n, "name" [,W] Open a file on channel n. W opens it for writing.
DRAW DRAW src, x, y [TO x, y ...] Plot a point or draw a polyline.
DSAVE DSAVE "name" Save the program to a file.
DVERIFY DVERIFY "name" The other name for VERIFY.
EMIT EMIT expr Yield one value from a GEN body. Only valid inside one; see Chapter 4.
END END Stop the program. Does not arm CONT.
END GEN END GEN Close a GEN body, the way RETURN closes a multi-line DEF.
ENVELOPE ENVELOPE n, a, d, s, r Define one of PLAY's ten envelope presets.
EXIT EXIT Leave the innermost FOR, FOR EACH, DO or DO EACH loop.
FETCH FETCH count, from, to Copy bytes. The same as STASH; there is no expansion RAM.
FILTER FILTER ... Refused. There is no filter stage in the audio backend.
FOR FOR V = a TO b [STEP c], FOR EACH V IN gen(args) Start a counted loop, ended by NEXT. EACH consumes a GEN instead; see Chapter 4.
GEN GEN NAME(args) ... END GEN Define a generator: a subroutine that yields more than once via EMIT, consumed by FOR EACH/DO EACH. See Chapter 4.
GET GET V Take a keystroke if one is waiting, without stopping.
GETKEY GETKEY V Wait for a keystroke, holding the program but not the host.
GETMENU GETMENU n, V% Wait for a menu choice, holding the program but not the host. Assigns the entry number. See Chapter 19.
GOSUB GOSUB line Call a subroutine, returning on RETURN.
GOTO GOTO line Jump to a line or a label.
GRAPHIC `GRAPHIC mode CLR`
GSHAPE GSHAPE A$, x, y Stamp a region saved by SSHAPE.
HEADER HEADER "name" Refused. Formats a disk.
HELP HELP Re-list the line the last error happened on.
HUD HUD n [,anchor, "text"] Pin a line of text to a corner or the centre. No text retires the slot; no arguments retire them all. See Chapter 19.
IF IF c THEN s [ELSE s] Branch. Everything after THEN belongs to the condition.
INPUT INPUT ["prompt"] V Read a line from the user.
INPUT# INPUT #n, V Read a line from a channel.
KEY KEY [n, "text"] Define a function-key macro, or list them all.
LABEL LABEL NAME Mark this line with a name any branch can use.
LET LET V = expr Assign. Optional; assignment needs no verb.
LIST LIST [n][-n] List the program, or part of it.
LOAD LOAD "name" The other name for DLOAD.
LOCATE LOCATE x, y Move the pixel cursor.
LOOP `LOOP [WHILE c UNTIL c]`
MENU MENU [n [,"item", ...]] Show a menu the player picks from. No entries retires it; no arguments retire them all. See Chapter 19.
MOVSPR MOVSPR n, ... Move a sprite. Four forms; see Chapter 8.
NEW NEW Erase the program and every variable.
NEXT NEXT V End a FOR loop and advance its counter, or resume a FOR EACH for its next value.
ON `ON e GOTO GOSUB t [,...]`
PAINT PAINT src, x, y Flood-fill the region containing a point.
PLAY PLAY "notes" Queue notes. Does not block.
POINT POINT P@ AT s@ Aim a strict pointer at a structure. See Chapter 16.
POKE POKE addr, byte Write a byte to a real address.
PRINT PRINT [expr] Print a value and a newline.
PRINT# PRINT #n, expr Write a line to a channel.
PUDEF PUDEF "chars" Redefine what PRINT USING pads and punctuates with.
QUIT QUIT End the interpreter.
READ READ V [,...] Fill variables from the next DATA items.
RECORD RECORD n, r [,pos] Position a channel at record r. Records are lines.
RENAME RENAME "a", "b" Rename a file.
RENUMBER RENUMBER [start [,step [,from]]] Renumber lines, rewriting every branch to match.
RESTORE RESTORE [line] Reset the READ cursor, optionally to a line.
RESUME `RESUME [NEXT line]`
RETURN RETURN [expr] Return from a GOSUB or a multi-line DEF.
RUN RUN [line] Run the program, optionally from a line.
SAVE SAVE "name" The other name for DSAVE.
SCALE SCALE on [,xmax, ymax] Turn user coordinates on or off.
SCNCLR SCNCLR Clear the text screen.
SCRATCH SCRATCH "name" Delete a file.
SLEEP SLEEP seconds Pause. Holds the program, not the host.
SOLID SOLID [id [,x1, y1, x2, y2]] Register static collision geometry a sprite can hit. No rectangle retires it; no arguments retires them all. See Chapter 8.
SOUND SOUND v, freq, dur [,...] Play a tone on a voice. Does not block.
SPRCOLOR SPRCOLOR [c1] [,c2] Set the two shared multicolour registers.
SPRHIT SPRHIT n, kind [,x1, y1, x2, y2] Give a sprite a collision shape. Kind 0 none, 1 box, 2 circle, 3 or 4 capsule. No rectangle fits the frame. See Chapter 8.
SPRITE SPRITE n [,on] [,col] [,...] Configure a sprite. Omitted arguments are left alone.
SPRSAV SPRSAV source, n Give sprite n a picture. Three source forms; see Chapter 8.
SSHAPE SSHAPE A$, x1, y1 [,x2, y2] Save a screen region; A$ receives a handle.
STASH STASH count, from, to Copy bytes. The same as FETCH.
STOP STOP Stop the program; CONT resumes it.
SWAP SWAP A, B Exchange two variables of the same type.
SYS SYS addr Refused. There is no 6502 and no ROM to call.
TEMPO TEMPO n How fast PLAY releases its queue.
TRAP TRAP [target] Send errors to a handler. No target disarms it.
TROFF TROFF Turn line tracing off.
TRON TRON Turn line tracing on; each line prints its number in brackets.
TYPE TYPE NAMEEND TYPE Declare a record, its fields one per line. See Chapter 16.
UISTYLE UISTYLE [fill, edge, ink [,pad [,radius]]] The one look every widget draws with. No arguments restores the default. See Chapter 19.
VERIFY VERIFY "name" Compare the program in memory against a file.
VOL VOL n Set the overall volume, 0 to 15.
WAIT WAIT addr, mask [,xor] Poll a byte until it matches. Holds the program.
WIDTH `WIDTH 1 2`
WINDOW WINDOW l, t, r, b [,clear] Constrain the text area. Needs a sink with a grid.

Words that are not verbs

AND, ELSE, NOT, OR, REM, STEP, THEN, TO, UNTIL, USING and WHILE are reserved, but none of them is a statement on its own — each is consumed by the verb it belongs to.

Deliberately absent

BANK, FAST, MONITOR and SPRDEF have no table entry at all. The first three are incompatible with a modern machine — there is no bank switching, no CPU speed to control, and no machine-language monitor to drop into. SPRDEF is an interactive full-screen editor rather than a programmable verb.