basic: allow multiple commands on the same line
This commit is contained in:
parent
5d33d165a2
commit
51c977f2ed
@ -88,13 +88,22 @@ etc.) always to so in variable `A`.
|
||||
Another is that whenever a number is expected, expressions, including the ones
|
||||
with variables in it, work fine.
|
||||
|
||||
### One-liners
|
||||
|
||||
The `:` character, when not inside a `""` literal, allows you to cram more than
|
||||
one instruction on the same line.
|
||||
|
||||
Things are special with `if`. All commands following a `if` are bound to that
|
||||
`if`'s condition. `if 0 foo:bar` doesn't execute `bar`.
|
||||
|
||||
Another special thing is `goto`. A `goto` followed by `:` will have the commands
|
||||
following the `:` before the goto occurs.
|
||||
|
||||
### Commands
|
||||
|
||||
There are two types of commands: normal and direct-only. The latter can only
|
||||
be invoked in direct mode, not through a code listing.
|
||||
|
||||
`bye`: Direct-only. Quits BASIC
|
||||
|
||||
`list`: Direct-only. Prints all lines in the code listing, prefixing them
|
||||
with their associated line number.
|
||||
|
||||
|
@ -46,7 +46,7 @@ basLDBAS:
|
||||
call parseDecimal
|
||||
jr nz, .notANumber
|
||||
push ix \ pop de
|
||||
call toSep
|
||||
call toSepOrEnd
|
||||
call rdSep
|
||||
call bufAdd
|
||||
pop hl ; <-- lvl 1
|
||||
|
@ -41,14 +41,14 @@ basLoop:
|
||||
call parseDecimal
|
||||
jr z, .number
|
||||
ld de, basCmds1
|
||||
call basCallCmd
|
||||
call basCallCmds
|
||||
jr z, basLoop
|
||||
; Error
|
||||
call basERR
|
||||
jr basLoop
|
||||
.number:
|
||||
push ix \ pop de
|
||||
call toSep
|
||||
call toSepOrEnd
|
||||
call rdSep
|
||||
call bufAdd
|
||||
jp nz, basERR
|
||||
@ -110,6 +110,27 @@ basCallCmd:
|
||||
call rdSep
|
||||
jp (ix)
|
||||
|
||||
; Call a series of ':'-separated commands in (HL) using cmd table in (DE).
|
||||
; Stop processing as soon as one command unsets Z.
|
||||
basCallCmds:
|
||||
; Commands are not guaranteed at all to preserve HL and DE, so we
|
||||
; preserve them ourselves here.
|
||||
push hl ; --> lvl 1
|
||||
push de ; --> lvl 2
|
||||
call basCallCmd
|
||||
pop de ; <-- lvl 2
|
||||
pop hl ; <-- lvl 1
|
||||
ret nz
|
||||
call toEnd
|
||||
ret z ; no more cmds
|
||||
; we met a ':', we have more cmds
|
||||
inc hl
|
||||
call basCallCmds
|
||||
; move the the end of the string so that we don't run cmds following a
|
||||
; ':' twice.
|
||||
call strskip
|
||||
ret
|
||||
|
||||
basERR:
|
||||
ld hl, .sErr
|
||||
call printstr
|
||||
@ -154,7 +175,7 @@ basRUN:
|
||||
call bufStr
|
||||
ld de, basCmds2
|
||||
push ix ; --> lvl 1
|
||||
call basCallCmd
|
||||
call basCallCmds
|
||||
pop ix ; <-- lvl 1
|
||||
jp nz, .err
|
||||
call .maybeGOTO
|
||||
@ -258,10 +279,11 @@ basIF:
|
||||
ret z
|
||||
; expr is true, execute next
|
||||
; (HL) back to beginning of args, skip to next arg
|
||||
call toSep
|
||||
call toSepOrEnd
|
||||
call rdSep
|
||||
ret nz
|
||||
ld de, basCmds2
|
||||
jp basCallCmd
|
||||
jp basCallCmds
|
||||
|
||||
basINPUT:
|
||||
; If our first arg is a string literal, spit it
|
||||
|
@ -1,10 +1,16 @@
|
||||
; Sets Z is A is ' ' or '\t' (whitespace), or ',' (arg sep)
|
||||
; Whether A is a separator or end-of-string (null or ':')
|
||||
isSepOrEnd:
|
||||
or a
|
||||
ret z
|
||||
cp ':'
|
||||
ret z
|
||||
; continue to isSep
|
||||
|
||||
; Sets Z is A is ' ' or '\t' (whitespace)
|
||||
isSep:
|
||||
cp ' '
|
||||
ret z
|
||||
cp 0x09
|
||||
ret z
|
||||
cp ','
|
||||
ret
|
||||
|
||||
; Expect at least one whitespace (0x20, 0x09) at (HL), and then advance HL
|
||||
@ -23,8 +29,8 @@ rdSep:
|
||||
ld a, (hl)
|
||||
call isSep
|
||||
jr z, .loop
|
||||
or a ; cp 0
|
||||
jp z, .fail
|
||||
call isSepOrEnd
|
||||
jp z, .fail ; unexpected EOL. fail
|
||||
cp a ; ensure Z
|
||||
ret
|
||||
.fail:
|
||||
@ -33,12 +39,27 @@ rdSep:
|
||||
ret
|
||||
|
||||
; Advance HL to the next separator or to the end of string.
|
||||
toSep:
|
||||
toSepOrEnd:
|
||||
ld a, (hl)
|
||||
call isSep
|
||||
call isSepOrEnd
|
||||
ret z
|
||||
inc hl
|
||||
jr toSep
|
||||
jr toSepOrEnd
|
||||
|
||||
; Advance HL to the end of the line, that is, either a null terminating char
|
||||
; or the ':'.
|
||||
; Sets Z if we met a null char, unset if we met a ':'
|
||||
toEnd:
|
||||
ld a, (hl)
|
||||
or a
|
||||
ret z
|
||||
cp ':'
|
||||
jr z, .havesep
|
||||
inc hl
|
||||
jr toEnd
|
||||
.havesep:
|
||||
inc a ; unset Z
|
||||
ret
|
||||
|
||||
; Read (HL) until the next separator and copy it in (DE)
|
||||
; DE is preserved, but HL is advanced to the end of the read word.
|
||||
@ -47,9 +68,7 @@ rdWord:
|
||||
push de
|
||||
.loop:
|
||||
ld a, (hl)
|
||||
call isSep
|
||||
jr z, .stop
|
||||
or a
|
||||
call isSepOrEnd
|
||||
jr z, .stop
|
||||
ld (de), a
|
||||
inc hl
|
||||
|
Loading…
Reference in New Issue
Block a user