Chapter 2 gets the rule and the refusal, chapter 4 gets the payoff for LABEL, chapter 9 says DSAVE writes the numbers it handed out and to RENUMBER first if you want gaps, chapter 10 shows a host loading numberless source, chapter 13 gets the QuickBASIC-shaped divergence, and chapter 14's source[] passage gets its second half. Chapter 14 said "two prescans" and listed two; there were three before this and there are four now, so it lists all four and says which of them reports against the right line. TODO.md section 6 records four things found on the way and deliberately not fixed: set_label() filing into the active scope rather than the root, three prescans reporting the wrong line number, duplicate written line numbers still replacing silently, and renumber.c's file-scope scratch arrays. examples/embed.c runs the same program twice, numbered and not, so the example compiles the feature rather than describing it. Its header pointed at ./build/examples/embed, which is not where the binary lands. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4.3 KiB
2. Getting started
The prompt
Run basic with no arguments and you get a prompt:
$ ./build/basic
READY
READY is printed whenever the interpreter is waiting for you, which is at startup
and after a program stops.
At the prompt, anything you type with a line number is stored as part of a program, and anything you type without one runs immediately:
PRINT 2 + 2
4
That rule is the prompt's, and only the prompt's. A program in a file does not need line numbers at all — see Line numbers below.
Your first program
10 PRINT "WHAT IS YOUR NAME"
20 INPUT "> " N$
30 PRINT "HELLO, " + N$
RUN
ADA
WHAT IS YOUR NAME
> HELLO, ADA
READY
The last line of the first block is not part of the program — it is what you type when
INPUT asks.
Type LIST to see it back, RUN to run it again, and NEW to throw it away.
Line numbers
Lines are stored under their numbers and run in numeric order, so the gaps are what let you insert later:
10 PRINT "FIRST"
30 PRINT "THIRD"
20 PRINT "SECOND"
LIST
10 PRINT "FIRST"
20 PRINT "SECOND"
30 PRINT "THIRD"
Typing a line number with nothing after it deletes that line. DELETE 20-40 removes a
range, and RENUMBER tidies the whole program up — it rewrites every GOTO and
GOSUB to match, so it will not break your branches.
AUTO 10 turns on automatic numbering so you do not have to type them; AUTO 0 turns
it off again.
A program in a file does not need them
Numbers are what tells the prompt a program line from a statement to run now. A file has no such problem, so a program loaded from one — or handed to the library as a string by a host — may leave them out entirely:
PRINT "COUNTING:"
FOR I# = 1 TO 3
PRINT I# * I#
NEXT I#
PRINT "DONE"
COUNTING:
1
4
9
DONE
Lines with no number are given the next one going, so they still run in the order you wrote them, and a blank line costs nothing. You can mix the two: a numbered line sets where the next unnumbered one goes.
A program written this way branches by LABEL, which is what makes it worth doing —
see Chapter 4. Numbers you never wrote are not numbers you
can branch to, and saying so is the one thing the interpreter is strict about:
PRINT "A"
GOTO 2
? 2 : PARSE ERROR Line 2: branch to line 2, which the program did not number. Branch by LABEL, or RENUMBER first
LIST shows the numbers it handed out, so you can still edit a loaded program at the
prompt, and DSAVE writes them into the file. They come out one apart, with no gaps to
insert into — RENUMBER before you save if you want the gaps back.
Several statements on one line
Statements are separated by colons:
10 A# = 1 : B# = 2 : PRINT A# + B#
3
There is one important limit: block structures do not work inside a single line.
10 FOR I# = 1 TO 3 : PRINT I# : NEXT I#
20 PRINT "DONE"
DONE
prints nothing at all. The loop body is skipped entirely, because the interpreter skips
forward a line at a time looking for the NEXT and never finds one on the line it is
already past. Write loops across several lines:
10 FOR I# = 1 TO 3
20 PRINT I#
30 NEXT I#
1
2
3
The same applies to DO/LOOP.
Running a file
$ ./build/basic program.bas
HELLO FROM A FILE
The file is read, stored, and run. It is exactly the same as typing the program in and saving yourself the trouble.
You can also pipe a program in:
$ echo '10 PRINT "HI"
RUN' | ./build/basic
READY
HI
READY
Saving and loading
10 PRINT "HI"
DSAVE "myprogram.bas"
NEW
DLOAD "myprogram.bas"
LIST
10 PRINT "HI"
That is a whole round trip: save it, throw it away with NEW, load it back, and LIST
shows it again.
SAVE and LOAD are the same verbs under their other names. VERIFY "myprogram.bas"
compares what is in memory against the file and prints OK if they match.
Stopping
QUIT ends the interpreter. STOP stops a program and returns you to the prompt,
where CONT resumes it from where it stopped. END also stops the program, but does
not arm CONT.
In the SDL build, closing the window stops the program too.