Move BASIC fixtures into the editable language corpus
All checks were successful
akbasic CI Build / cmake_build (push) Successful in 3m34s
akbasic CI Build / coverage (push) Successful in 4m4s
akbasic CI Build / sanitizers (push) Successful in 6m59s
akbasic CI Build / akgl_build (push) Successful in 7m57s
akbasic CI Build / mutation_test (push) Successful in 23m28s

Move every program and expectation out of tests/reference and register the unified tests/language corpus as local cases. Remove the old immutable-corpus protections from build, maintenance, and documentation paths.

Co-authored-by: andrew <andrew@aklabs.net>
This commit is contained in:
2026-08-04 16:21:59 -04:00
parent fac84acdaa
commit 8a02674af5
96 changed files with 69 additions and 168 deletions

16
tests/language/README.md Normal file
View File

@@ -0,0 +1,16 @@
# The language test corpus
The `.bas` files in this directory and their sibling `.txt` files are the editable language
corpus. CMake registers every program as an individual `local_*` CTest case and compares its
output with the sibling expectation.
The corpus includes cases carried over from the deprecated Go implementation as well as cases
written for this interpreter. Their provenance is useful when investigating a regression, but it
does not make any case immutable or turn the old implementation into a specification.
**Change a program and its expectation deliberately and in the same commit.** If the changed
output represents an intentional language decision, record the reason in `TODO.md` or the
relevant documentation. If it is an accidental change, fix the interpreter instead.
The `examples/` subdirectory contains complete BASIC programs used as worked examples. It is
part of the same corpus and follows the same `.bas`/`.txt` pairing rule.

View File

@@ -0,0 +1,7 @@
10 PRINT 2.0 + 2.0
20 PRINT 2.0 * 2.0
30 PRINT 4.0 / 2.0
40 PRINT 4.0 - 2.0
50 PRINT 1.0 / 0.5
60 PRINT 12.0 / 4.0
70 PRINT 1.20 / 0.4

View File

@@ -0,0 +1,7 @@
4.000000
4.000000
2.000000
2.000000
2.000000
3.000000
3.000000

View File

@@ -0,0 +1,5 @@
10 PRINT 2 + 2
20 PRINT 2 * 2
30 PRINT 4 / 2
40 PRINT 4 - 2

View File

@@ -0,0 +1,4 @@
4
4
2
2

View File

@@ -0,0 +1,6 @@
10 DIM A#(8, 8)
20 PRINT LEN(A#)
30 A#(0,7) = 31337
40 A#(1,7) = 65535
50 PRINT A#(0,7)
60 PRINT A#(1,7)

View File

@@ -0,0 +1,3 @@
64
31337
65535

View File

@@ -0,0 +1,3 @@
10 DIM A#(3)
20 PRINT A#(4)
30 PRINT "FAILURE"

View File

@@ -0,0 +1,2 @@
? 20 : RUNTIME ERROR Variable index access out of bounds at dimension 0: 4 (max 2)

View File

@@ -0,0 +1,9 @@
10 DIM A#(3)
20 A#(0) = 100
30 A#(1) = 101
40 A#(2) = 102
50 IF LEN(A#) <> 3 THEN PRINT "LEN(A#) != 3 : " + LEN(A#) + " FAILURE"
60 IF A#(0) <> 100 THEN PRINT "A#(0) != 100 : " + A#(0) + " FAILURE"
70 IF A#(1) <> 101 THEN PRINT "A#(1) != 101 : " + A#(1) + " FAILURE"
80 IF A#(2) <> 102 THEN PRINT "A#(2) != 102 : " + A#(2) + " FAILURE"
90 PRINT "SUCCESS"

View File

@@ -0,0 +1 @@
SUCCESS

View File

@@ -0,0 +1,2 @@
10 print "HELLO"
20 print mod(12, 5)

View File

@@ -0,0 +1,2 @@
HELLO
2

View File

@@ -0,0 +1,29 @@
10 DIM A#(5)
15 ITERATIONS# = 0
20 A#(0) = 5
21 A#(1) = 2
22 A#(2) = 4
23 A#(3) = 1
24 A#(4) = 3
25 PRINT "BEFORE SORTING: "
26 FOR I# = 0 TO 4
27 PRINT A#(I#)
28 NEXT I#
30 CHANGED# = 0
32 ITERATIONS# = ITERATIONS# + 1
35 FOR I# = 0 TO 3
45 J# = I#+1
46 REM PRINT "COMPARING INDEXES " + I# + " (" + A#(I#) + ") AND " + J# + "
50 IF A#(I#) <= A#(J#) THEN GOTO 100
55 REM PRINT "SWAPPING INDEXES " + I# + " AND " + J#
60 TMP# = A#(I#)
70 A#(I#) = A#(J#)
80 A#(J#) = TMP#
85 CHANGED# = CHANGED# + 1
100 NEXT I#
110 IF CHANGED# <> 0 THEN GOTO 30
115 PRINT "AFTER SORTING:"
120 FOR I# = 0 TO 4
130 PRINT A#(I#)
140 NEXT I#
145 PRINT "SORTED IN " + ITERATIONS# + " ITERATIONS"

View File

@@ -0,0 +1,13 @@
BEFORE SORTING:
5
2
4
1
3
AFTER SORTING:
1
2
3
4
5
SORTED IN 4 ITERATIONS

View File

@@ -0,0 +1,10 @@
10 N# = 5
20 RESULT# = 1
30 GOSUB 100
40 PRINT "FACTORIAL(5) IS " + RESULT#
50 QUIT
100 IF N# <= 1 THEN RETURN
110 RESULT# = RESULT# * N#
120 N# = N# - 1
130 GOSUB 100
140 RETURN

View File

@@ -0,0 +1 @@
FACTORIAL(5) IS 120

View File

@@ -0,0 +1,7 @@
10 SOURCE$ = "HELLO"
20 STRLEN# = LEN(SOURCE$) - 1
30 REV$ = ""
40 FOR I# = STRLEN# TO 0 STEP -1
50 REV$ = REV$ + MID(SOURCE$, I#, 1)
60 NEXT I#
70 PRINT "REVERSED: " + REV$

View File

@@ -0,0 +1 @@
REVERSED: OLLEH

View File

@@ -0,0 +1,4 @@
10 FOR I# = 1 TO 4
20 PRINT I#
30 NEXT I#
40 QUIT

View File

@@ -0,0 +1,4 @@
1
2
3
4

View File

@@ -0,0 +1,13 @@
10 REM This shows the waitingForCommand utility in the BasicEnvironment
11 REM We have a FOR loop here with a condition where the loop should
12 REM not execute at all. But because the checking of the conditional is
13 REM delayed until the bottom of the loop, we run the risk of the
14 REM runtime executing every line between FOR ... NEXT even though it
15 REM shouldn't. waitingForCommand prevents this from occurring
20 FOR I# = 1 TO 1
30 PRINT "waitingForCommand FAILS if this is seen"
40 NEXT I#
50 FOR I# = 1 TO 2
60 PRINT "waitingForCommand PASS if this is seen"
70 NEXT I#
80 QUIT

View File

@@ -0,0 +1,2 @@
waitingForCommand PASS if this is seen
waitingForCommand PASS if this is seen

View File

@@ -0,0 +1,3 @@
10 GOTO 30
20 PRINT "FAILURE"
30 PRINT "SUCCESS"

View File

@@ -0,0 +1 @@
SUCCESS

View File

@@ -0,0 +1,11 @@
10 A# = 1
20 IF A# == 1 THEN GOTO 30 ELSE GOTO 40
30 PRINT "A# IS 1"
35 GOTO 50
45 PRINT "A# IS NOT 1"
50 IF A# == 2 THEN GOTO 60 ELSE GOTO 80
60 PRINT "A# IS 2"
65 PRINT A#
70 GOTO 90
80 PRINT "A# IS NOT 2"
90 PRINT "DONE"

View File

@@ -0,0 +1,3 @@
A# IS 1
A# IS NOT 2
DONE

View File

@@ -0,0 +1,10 @@
10 FOR I# = 1 TO 4
15 PRINT "OUTER : I# IS " + I#
20 FOR J# = 2 TO 3
23 PRINT "INNER : I# IS " + I#
25 PRINT "INNER : J# IS " + J#
30 PRINT "INNER : I# * J# IS " + (I# * J#)
40 NEXT J#
50 NEXT I#
60 PRINT "DONE"
70 QUIT

View File

@@ -0,0 +1,29 @@
OUTER : I# IS 1
INNER : I# IS 1
INNER : J# IS 2
INNER : I# * J# IS 2
INNER : I# IS 1
INNER : J# IS 3
INNER : I# * J# IS 3
OUTER : I# IS 2
INNER : I# IS 2
INNER : J# IS 2
INNER : I# * J# IS 4
INNER : I# IS 2
INNER : J# IS 3
INNER : I# * J# IS 6
OUTER : I# IS 3
INNER : I# IS 3
INNER : J# IS 2
INNER : I# * J# IS 6
INNER : I# IS 3
INNER : J# IS 3
INNER : I# * J# IS 9
OUTER : I# IS 4
INNER : I# IS 4
INNER : J# IS 2
INNER : I# * J# IS 8
INNER : I# IS 4
INNER : J# IS 3
INNER : I# * J# IS 12
DONE

View File

@@ -0,0 +1,11 @@
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
12 REM the outer loop should NOT execute. Therefore, neither loop should execute.
20 FOR I# = 1 TO 0
25 FOR J# = 2 TO 4
30 PRINT "waitingForCommand FAILS if this is seen"
32 QUIT
35 NEXT J#
40 NEXT I#
50 PRINT "SUCCESS"
80 QUIT

View File

@@ -0,0 +1 @@
SUCCESS

View File

@@ -0,0 +1,6 @@
10 DEF SQR(X#) = X# * X#
20 DEF MUL(X#, Y#) = X# * Y#
30 A# = SQR(3)
40 B# = MUL(A#, 4)
50 IF A# <> 9 THEN PRINT "SQR FAIL" ELSE PRINT "SQR PASS"
60 IF B# <> 36 THEN PRINT "MUL FAIL" ELSE PRINT "MUL PASS"

View File

@@ -0,0 +1,2 @@
SQR PASS
MUL PASS

View File

@@ -0,0 +1 @@
10 PRINT ATN(3)

View File

@@ -0,0 +1 @@
1.249046

View File

@@ -0,0 +1,3 @@
10 PRINT "97 : " + CHR(97)
20 PRINT "65 : " + CHR(65)
30 PRINT "64 : " + CHR(64)

View File

@@ -0,0 +1,3 @@
97 : a
65 : A
64 : @

View File

@@ -0,0 +1 @@
10 PRINT COS(90)

View File

@@ -0,0 +1 @@
-0.448074

View File

@@ -0,0 +1 @@
10 PRINT HEX(255)

View File

@@ -0,0 +1 @@
ff

View File

@@ -0,0 +1,3 @@
10 X$ = "HELLO"
20 Y$ = "LLO"
30 PRINT INSTR(X$, Y$)

View File

@@ -0,0 +1 @@
2

View File

@@ -0,0 +1 @@
10 PRINT LEFT("HELLO", 2)

View File

@@ -0,0 +1 @@
HE

View File

@@ -0,0 +1,5 @@
10 A$ = "HELLO"
20 STRLEN# = LEN(A$)
30 IF STRLEN# == 5 THEN GOTO 50
40 PRINT "FAILURE"
50 PRINT "SUCCESS"

View File

@@ -0,0 +1 @@
SUCCESS

View File

@@ -0,0 +1 @@
10 PRINT LOG(3.14)

View File

@@ -0,0 +1 @@
1.144223

View File

@@ -0,0 +1,3 @@
10 A$ = "HELLO"
20 B$ = MID(A$, 2, 3)
30 PRINT B$

View File

@@ -0,0 +1 @@
LLO

View File

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

View File

@@ -0,0 +1,3 @@
1
2
0

View File

@@ -0,0 +1,8 @@
10 A# = 255
20 B# = POINTER(A#)
30 IF PEEK(B#) == 255 THEN GOTO 50
40 PRINT "FAILURE: PEEK != 255"
50 POKE B#, 127
60 IF PEEK(B#) == 127 THEN GOTO 80
70 PRINT "FAILURE : POKE DID NOT SET 127"
80 PRINT "SUCCESS"

View File

@@ -0,0 +1 @@
SUCCESS

View File

@@ -0,0 +1 @@
10 PRINT RAD(90)

View File

@@ -0,0 +1 @@
1.570796

View File

@@ -0,0 +1,2 @@
10 PRINT RIGHT("HELLO", 3)
20 PRINT RIGHT("HELLO", 7)

View File

@@ -0,0 +1,2 @@
LLO
HELLO

View File

@@ -0,0 +1,4 @@
10 X# = -1
20 PRINT SGN(X#)
30 PRINT SGN(0)
40 PRINT SGN(1)

View File

@@ -0,0 +1,3 @@
-1
0
1

View File

@@ -0,0 +1,4 @@
10 A# = 8
20 B# = SHL(A#, 2)
30 PRINT B#
40 PRINT SHL(8, 2)

View File

@@ -0,0 +1,2 @@
32
32

View File

@@ -0,0 +1,4 @@
10 A# = 32
20 B# = SHR(A#, 2)
30 PRINT B#
40 PRINT SHR(32, 2)

View File

@@ -0,0 +1,2 @@
8
8

View File

@@ -0,0 +1 @@
10 PRINT SIN(90)

View File

@@ -0,0 +1 @@
0.893997

View File

@@ -0,0 +1 @@
10 PRINT "BASIC IS" + SPC(16) + "FUN"

View File

@@ -0,0 +1 @@
BASIC IS FUN

View File

@@ -0,0 +1,2 @@
10 X% = -123.456
20 PRINT STR(X%)

View File

@@ -0,0 +1 @@
-123.456000

View File

@@ -0,0 +1 @@
10 PRINT TAN(90)

View File

@@ -0,0 +1 @@
-1.995200

View File

@@ -0,0 +1,3 @@
10 PRINT VAL("32")
20 PRINT VAL("123.456")
30 PRINT VAL("-256")

View File

@@ -0,0 +1,3 @@
32.000000
123.456000
-256.000000

View File

@@ -0,0 +1,2 @@
10 PRINT XOR(50, 10)
20 PRINT XOR(25, 5)

View File

@@ -0,0 +1,2 @@
56
28

View File

@@ -0,0 +1,9 @@
5 DEF ADDTWO(A#, B#) = A# + B#
10 DEF ADDTWOSR(A#, B#)
20 C# = A# + B#
30 RETURN C#
40 REM PRINT ADDTWO(3, 5)
45 D# = ADDTWO(3, 5)
50 PRINT D#
55 E# = ADDTWOSR(3, 5)
60 PRINT E#

View File

@@ -0,0 +1,2 @@
8
8

5
tests/language/label.bas Normal file
View File

@@ -0,0 +1,5 @@
10 I# = 0
20 LABEL DOITAGAIN
30 I# = I# + 1
40 IF I# <> 3 THEN GOTO DOITAGAIN
50 PRINT "DONE"

1
tests/language/label.txt Normal file
View File

@@ -0,0 +1 @@
DONE

View File

@@ -0,0 +1,4 @@
10 READ A$, B#
20 DATA "HELLO", 12345
30 PRINT A$
40 PRINT B#

View File

@@ -0,0 +1,2 @@
HELLO
12345