Fix 80-column fixtures and tutorial expectations
All checks were successful
akbasic CI Build / cmake_build (push) Successful in 3m29s
akbasic CI Build / sanitizers (push) Successful in 4m42s
akbasic CI Build / coverage (push) Successful in 3m56s
akbasic CI Build / akgl_build (push) Successful in 8m34s
akbasic CI Build / mutation_test (push) Successful in 18m50s

This commit is contained in:
2026-08-04 16:14:04 -04:00
parent 1e514f679b
commit eb93bb7da0
18 changed files with 42 additions and 41 deletions

View File

@@ -685,9 +685,9 @@ seconds asks for fifty frames a second.
### Why `GOTO` rather than `DO ... LOOP` ### Why `GOTO` rather than `DO ... LOOP`
A `DO ... LOOP` around the frame would read better, and it is not usable here: **a `GOTO` A `DO ... LOOP` around the frame would read better, and it is not usable here: **a `GOTO`
that jumps out of a `FOR` or a `DO` does not release the loop's scope.** There are 32 that jumps out of a `FOR` or a `DO` does not release the loop's scope.** There are 12
scopes, so a game that leaves its main loop once per lost life stops on the scopes, so a game that leaves its main loop once per lost life stops on the
thirty-second one: twelfth one:
```basic ```basic
N# = 0 N# = 0
@@ -700,7 +700,7 @@ PRINT "SURVIVED " + N#
``` ```
```output ```output
? 3 : PARSE ERROR Environment pool exhausted at line 3 (32 in use) ? 3 : PARSE ERROR Environment pool exhausted at line 3 (12 in use)
``` ```

View File

@@ -1423,7 +1423,8 @@ IF STATE# = 2 THEN GOSUB UNSTICK
RETURN RETURN
LABEL PRESSPAUSE LABEL PRESSPAUSE
IF STATE# = 2 THEN STATE# = 6 : GMTYP# = 0 : BAN$ = "PAUSED" : GOSUB SETBANNER : RETURN IF STATE# = 2 THEN STATE# = 6 : GMTYP# = 0 : BAN$ = "PAUSED"
IF STATE# = 6 THEN GOSUB SETBANNER : RETURN
IF STATE# = 6 THEN STATE# = 2 : BAN$ = "" : GOSUB SETBANNER IF STATE# = 6 THEN STATE# = 2 : BAN$ = "" : GOSUB SETBANNER
RETURN RETURN
``` ```

View File

@@ -1,6 +1,6 @@
10 REM An array reference used as a function argument, and as one of several. 10 REM An array reference used as a function argument, and as one of several.
20 REM An identifier's subscript list used to hang off .right, which is also 20 REM An identifier's subscript list used to hang off .right, which is also
30 REM where an argument list chains its arguments -- so the arity counter walked 30 REM where an argument list chains its arguments; the arity counter walked
40 REM straight into the subscripts and refused the call. TODO.md section 4. 40 REM straight into the subscripts and refused the call. TODO.md section 4.
50 DIM C#(4) 50 DIM C#(4)
60 C#(1) = -9 60 C#(1) = -9

View File

@@ -1,6 +1,6 @@
10 REM FILTER has no device capability behind it -- akgl_audio_* synthesises and 10 REM FILTER has no device capability; akgl_audio_* synthesises and mixes but
20 REM mixes but has no filter stage, and SDL3 supplies no primitive to build one 20 REM has no filter stage, and SDL3 supplies no primitive to build one from.
30 REM from. It is refused rather than silently ignored, so a program that asked 30 REM It is refused rather than silently ignored, so a program that asked
40 REM for a low-pass finds out it did not get one. 40 REM for a low-pass finds out it did not get one.
50 PRINT "BEFORE" 50 PRINT "BEFORE"
60 FILTER 1000, 1, 0, 0, 5 60 FILTER 1000, 1, 0, 0, 5

View File

@@ -1,4 +1,4 @@
10 REM The standalone driver lends the script no audio device. ENVELOPE, VOL and 10 REM The standalone driver lends the script no audio device. ENVELOPE, VOL,
20 REM TEMPO only change interpreter state, so they work regardless; SOUND and 20 REM TEMPO only change interpreter state, so they work regardless; SOUND and
30 REM PLAY need the device and must name themselves when there is none. 30 REM PLAY need the device and must name themselves when there is none.
40 ENVELOPE 1, 5, 9, 12, 2 40 ENVELOPE 1, 5, 9, 12, 2

View File

@@ -1,6 +1,6 @@
10 REM A DEF call takes its environment from the pool, one per call, exactly as 10 REM A DEF call takes one environment from the pool, exactly as
20 REM GOSUB does. It used to be owned by the funcdef and reset on every call, 20 REM GOSUB does. It used to be owned by the funcdef and reset on every call,
30 REM which cost two silent defects: two calls in one expression shared a slot, 30 REM which cost two silent defects: calls in one expression shared a slot,
40 REM and recursion never came back at all. 40 REM and recursion never came back at all.
50 DEF FACT(N#) 50 DEF FACT(N#)
60 IF N# <= 1 THEN RETURN 1 60 IF N# <= 1 THEN RETURN 1
@@ -15,9 +15,9 @@
150 DEF DBL(N#) = N# * 2 150 DEF DBL(N#) = N# * 2
160 PRINT DBL(10) + DBL(1) 160 PRINT DBL(10) + DBL(1)
170 PRINT DBL(1) + DBL(10) + DBL(100) 170 PRINT DBL(1) + DBL(10) + DBL(100)
180 REM Depth answers to the environment pool now, so runaway recursion reports 180 REM Depth answers to the environment pool, so runaway recursion reports
190 REM "Environment pool exhausted" rather than hanging. It is not exercised here 190 REM "Environment pool exhausted" rather than hanging. It is not exercised
200 REM because the statement containing a failed call still prints a junk value 200 REM here because the failed statement still prints junk afterwards;
210 REM afterwards -- a separate, pre-existing defect recorded in TODO.md, and one 210 REM this is a separate defect in TODO.md, and one this golden file
220 REM this golden file would pin if it went in. tests/user_functions.c asserts 220 REM would pin if it went in. tests/user_functions.c asserts
230 REM the message instead. 230 REM the message instead.

View File

@@ -1,4 +1,4 @@
10 REM A range check reported through the driver, end to end. The program stops 10 REM A range check reported through the driver, end to end. The program
20 REM at the first error, so this file covers one; the rest of the checks are 20 REM at the first error, so this file covers one; the rest of the checks are
30 REM asserted in tests/graphics_verbs.c against the recording backend. 30 REM asserted in tests/graphics_verbs.c against the recording backend.
40 PRINT "BEFORE" 40 PRINT "BEFORE"

View File

@@ -1,5 +1,5 @@
10 REM The standalone driver lends the script no graphics device. 10 REM The standalone driver lends the script no graphics device.
20 REM COLOR, LOCATE and SCALE only touch interpreter state and must still work. 20 REM COLOR, LOCATE and SCALE touch interpreter state and must still work.
30 COLOR 1, 3 30 COLOR 1, 3
40 LOCATE 40, 50 40 LOCATE 40, 50
50 SCALE 1, 640, 400 50 SCALE 1, 640, 400

View File

@@ -1,5 +1,5 @@
10 REM Group B: the housekeeping verbs. None of these is in the Go reference -- 10 REM Group B: housekeeping verbs. None is in the Go reference --
20 REM they are on its own unimplemented list -- so what each one means here is 20 REM they are on its unimplemented list -- so each meaning here is
30 REM a decision, recorded in src/runtime_housekeeping.c beside the verb. 30 REM a decision, recorded in src/runtime_housekeeping.c beside the verb.
40 A# = 1 : B# = 2 40 A# = 1 : B# = 2
50 PRINT A# : PRINT B# 50 PRINT A# : PRINT B#
@@ -11,7 +11,7 @@
110 P#(2) = 7 : Q#(2) = 9 110 P#(2) = 7 : Q#(2) = 9
120 SWAP P#, Q# 120 SWAP P#, Q#
130 PRINT P#(2) : PRINT Q#(2) 130 PRINT P#(2) : PRINT Q#(2)
140 REM TRON prints each line number inline before the line runs, as a C128 does. 140 REM TRON prints each line number inline, as a C128 does.
150 TRON 150 TRON
160 PRINT "TRACED" 160 PRINT "TRACED"
170 TROFF 170 TROFF

View File

@@ -1,7 +1,7 @@
10 REM A leading zero is padding, not a radix. The reference selects base 8 for 10 REM A leading zero is padding, not a radix. The reference selected base 8
20 REM any lexeme starting with 0, so 010 printed 8 and 08 was a parse error -- 20 REM for lexemes starting with 0; 010 printed 8 and 08 was a parse error --
30 REM TODO.md section 6 item 10, fixed. Commodore BASIC has no octal literals. 30 REM TODO.md section 6 item 10 is fixed; Commodore BASIC has no octal.
40 REM 0x is the one prefix that changes the base, and it now reaches the scanner 40 REM 0x is the one prefix that changes the base, and now reaches the scanner
50 REM whole: that was section 6 item 15. 50 REM whole: that was section 6 item 15.
60 PRINT 010 60 PRINT 010
70 PRINT 08 70 PRINT 08

View File

@@ -1,12 +1,12 @@
10 REM A truth value carries its payload in boolvalue, not floatval. The three 10 REM A truth value carries its payload in boolvalue, not floatval. The three
20 REM numeric operators were `if ( INTEGER ) ... else <treat as float>`, and 20 REM numeric operators were `if ( INTEGER ) ... else <treat as float>`, and
30 REM that else was a catch-all rather than a float branch -- so a truth value 30 REM that else was a catch-all, not a float branch -- so a truth value
40 REM on the LEFT computed 0 - 1 into a field nothing reads, kept its BOOLEAN 40 REM on the LEFT computed 0 - 1 into a field nothing reads, kept its BOOLEAN
50 REM type, and printed `true` instead of -2. Silent, and wrong twice over. 50 REM type, and printed `true` instead of -2. Silent, and wrong twice over.
60 A# = 1 60 A# = 1
70 PRINT (A# == 1) 70 PRINT (A# == 1)
80 REM On the RIGHT it stays legal and stays -1, which is the same property that 80 REM On the RIGHT it stays legal and stays -1, the same property that
90 REM lets AND and OR double as logical operators. Refusing it here would have 90 REM lets AND and OR act as logical operators. Refusing it would have
100 REM broken every condition in the language. 100 REM broken every condition in the language.
110 PRINT 5 - (A# == 1) 110 PRINT 5 - (A# == 1)
120 PRINT 5 * (A# == 1) 120 PRINT 5 * (A# == 1)

View File

@@ -1,11 +1,11 @@
10 REM Statements separated by colons. The COLON token existed from the start of 10 REM Statements separated by colons. The COLON token existed from the start;
20 REM the port and nothing consumed it, so a line could hold only one statement. 20 REM nothing consumed it, so a line could hold only one statement.
30 PRINT "A" : PRINT "B" 30 PRINT "A" : PRINT "B"
40 A# = 1 : B# = 2 : PRINT A# + B# 40 A# = 1 : B# = 2 : PRINT A# + B#
50 REM An empty statement is not an error: a trailing separator, or a run of them. 50 REM Empty statements are valid: a trailing separator or runs of them.
60 PRINT "C" : 60 PRINT "C" :
70 PRINT "D" :: PRINT "E" 70 PRINT "D" :: PRINT "E"
80 REM Everything after THEN belongs to the condition, which is BASIC 7.0 and is 80 REM Everything after THEN belongs to the condition, as in BASIC 7.0, and is
90 REM not something the reference had an opinion about -- it never got here. 90 REM not something the reference had an opinion about -- it never got here.
100 IF 1 == 1 THEN PRINT "TRUE-1" : PRINT "TRUE-2" 100 IF 1 == 1 THEN PRINT "TRUE-1" : PRINT "TRUE-2"
110 IF 1 == 0 THEN PRINT "NEVER-1" : PRINT "NEVER-2" 110 IF 1 == 0 THEN PRINT "NEVER-1" : PRINT "NEVER-2"

View File

@@ -1,5 +1,5 @@
10 REM A field name is checked against a closed set the program declared, which 10 REM A field name is checked against the closed set the program declared;
20 REM is the one thing in this language whose valid spellings are written down. 20 REM this is the one thing whose valid spellings are written down.
30 REM A misspelled *variable* is still silent -- see the last two lines. 30 REM A misspelled *variable* is still silent -- see the last two lines.
40 TYPE RECT 40 TYPE RECT
50 W# 50 W#

View File

@@ -17,7 +17,7 @@
170 RETURN B@.W# 170 RETURN B@.W#
180 PRINT WIDEN(A@) 180 PRINT WIDEN(A@)
190 PRINT A@.W# 190 PRINT A@.W#
200 REM To change one on purpose, pass a pointer. Assignment copies a pointer's 200 REM To change one on purpose, pass a pointer. Assignment copies its
210 REM reference, so the callee is looking at the caller's own record. 210 REM reference, so the callee is looking at the caller's own record.
220 DIM Q@ AS PTR TO CRATE 220 DIM Q@ AS PTR TO CRATE
230 POINT Q@ AT A@ 230 POINT Q@ AT A@
@@ -37,7 +37,7 @@
370 N2@.COUNT# = 20 370 N2@.COUNT# = 20
380 POINT N1@.TAIL@ AT N2@ 380 POINT N1@.TAIL@ AT N2@
390 DEF TOTAL(P@ AS PTR TO NODE) 390 DEF TOTAL(P@ AS PTR TO NODE)
395 REM A pointer is true when it points at something, which is how a walk knows 395 REM A pointer is true when it points at something, so a walk knows
396 REM where the list ends. NOT is the bitwise operator here, so the test is 396 REM where the list ends. NOT is the bitwise operator here, so the test is
397 REM written the positive way round. 397 REM written the positive way round.
400 IF P@->TAIL@ THEN RETURN P@->COUNT# + TOTAL(P@->TAIL@) 400 IF P@->TAIL@ THEN RETURN P@->COUNT# + TOTAL(P@->TAIL@)

View File

@@ -1,4 +1,4 @@
10 REM A TYPE declares its fields; each takes its own type from its own suffix, 10 REM A TYPE declares its fields; each takes its type from its own suffix,
20 REM which is the same rule every other name in this language follows. 20 REM which is the same rule every other name in this language follows.
30 TYPE COORD 30 TYPE COORD
40 X# 40 X#

View File

@@ -1,6 +1,6 @@
10 REM A type name and a field name are bare words, and so is every verb, so 10 REM A type name and a field name are bare words, and so is every verb, so
20 REM they share a namespace whether we like it or not. Both are refused with 20 REM they share a namespace whether we like it or not. Both are refused with
30 REM the same rule the scanner already applies to variable names -- and a type 30 REM the scanner applies the same rule to variable names -- and a type
40 REM name is refused by the prescan, which can say so plainly rather than 40 REM name is refused by the prescan, which can say so plainly rather than
50 REM leaving the parser to report "Expected expression or literal". 50 REM leaving the parser to report "Expected expression or literal".
60 TYPE POINT 60 TYPE POINT

View File

@@ -1,6 +1,6 @@
10 REM This shows the waitingForCommand utility in the BasicEnvironment 10 REM This shows the waitingForCommand utility in the BasicEnvironment
11 REM when we have a nested for loop. The inner loop SHOULD execute, but 11 REM when we have a nested for loop. The inner loop SHOULD execute, but
12 REM the outer loop should NOT execute. Therefore, neither loop should execute. 12 REM the outer loop should NOT execute; neither loop should execute.
20 FOR I# = 1 TO 0 20 FOR I# = 1 TO 0
25 FOR J# = 2 TO 4 25 FOR J# = 2 TO 4
30 PRINT "waitingForCommand FAILS if this is seen" 30 PRINT "waitingForCommand FAILS if this is seen"

View File

@@ -1,6 +1,6 @@
10 PRINT MOD(10, 3) 10 PRINT MOD(10, 3)
20 PRINT MOD(12, 5) 20 PRINT MOD(12, 5)
30 PRINT MOD(4, 2) 30 PRINT MOD(4, 2)
40 REM MOD() ONLY WORKS WITH INTEGERS - RESULTS WITH FLOATING POINT ARE UNRELIABLE 40 REM MOD() ONLY WORKS WITH INTEGERS; FLOATING POINT RESULTS ARE UNRELIABLE
50 REM PRINT MOD(1.2, 0.4) 50 REM PRINT MOD(1.2, 0.4)
60 REM THERE IS NO ERROR THROWN HERE. JUST DONT DO IT. 60 REM THERE IS NO ERROR THROWN HERE. JUST DONT DO IT.