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>
213 lines
4.3 KiB
Markdown
213 lines
4.3 KiB
Markdown
# 2. Getting started
|
|
|
|
## The prompt
|
|
|
|
Run `basic` with no arguments and you get a prompt:
|
|
|
|
```sh norun
|
|
$ ./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:
|
|
|
|
```basic repl
|
|
PRINT 2 + 2
|
|
```
|
|
|
|
```output
|
|
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](#line-numbers) below.
|
|
|
|
## Your first program
|
|
|
|
```basic repl
|
|
10 PRINT "WHAT IS YOUR NAME"
|
|
20 INPUT "> " N$
|
|
30 PRINT "HELLO, " + N$
|
|
RUN
|
|
ADA
|
|
```
|
|
|
|
```output
|
|
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:
|
|
|
|
```basic repl
|
|
10 PRINT "FIRST"
|
|
30 PRINT "THIRD"
|
|
20 PRINT "SECOND"
|
|
LIST
|
|
```
|
|
|
|
```output
|
|
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:
|
|
|
|
```basic
|
|
PRINT "COUNTING:"
|
|
FOR I# = 1 TO 3
|
|
PRINT I# * I#
|
|
NEXT I#
|
|
PRINT "DONE"
|
|
```
|
|
|
|
```output
|
|
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](04-control-flow.md#labels). Numbers you never wrote are not numbers you
|
|
can branch to, and saying so is the one thing the interpreter is strict about:
|
|
|
|
```basic
|
|
PRINT "A"
|
|
GOTO 2
|
|
```
|
|
|
|
```output
|
|
? 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:
|
|
|
|
```basic
|
|
10 A# = 1 : B# = 2 : PRINT A# + B#
|
|
```
|
|
|
|
```output
|
|
3
|
|
```
|
|
|
|
There is one important limit: **block structures do not work inside a single line.**
|
|
|
|
```basic
|
|
10 FOR I# = 1 TO 3 : PRINT I# : NEXT I#
|
|
20 PRINT "DONE"
|
|
```
|
|
|
|
```output
|
|
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:
|
|
|
|
```basic
|
|
10 FOR I# = 1 TO 3
|
|
20 PRINT I#
|
|
30 NEXT I#
|
|
```
|
|
|
|
```output
|
|
1
|
|
2
|
|
3
|
|
```
|
|
|
|
The same applies to `DO`/`LOOP`.
|
|
|
|
## Running a file
|
|
|
|
```sh setup=program
|
|
$ ./build/basic program.bas
|
|
```
|
|
|
|
```output
|
|
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:
|
|
|
|
```sh
|
|
$ echo '10 PRINT "HI"
|
|
RUN' | ./build/basic
|
|
```
|
|
|
|
```output
|
|
READY
|
|
HI
|
|
READY
|
|
```
|
|
|
|
## Saving and loading
|
|
|
|
```basic repl
|
|
10 PRINT "HI"
|
|
DSAVE "myprogram.bas"
|
|
NEW
|
|
DLOAD "myprogram.bas"
|
|
LIST
|
|
```
|
|
|
|
```output
|
|
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.
|