1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-24 02:38:05 +11:00

basic: allow multiple commands on the same line

This commit is contained in:
Virgil Dupras 2019-12-12 10:51:13 -05:00
parent 5d33d165a2
commit 51c977f2ed
4 changed files with 69 additions and 19 deletions

View File

@ -88,13 +88,22 @@ etc.) always to so in variable `A`.
Another is that whenever a number is expected, expressions, including the ones Another is that whenever a number is expected, expressions, including the ones
with variables in it, work fine. 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 ### Commands
There are two types of commands: normal and direct-only. The latter can only There are two types of commands: normal and direct-only. The latter can only
be invoked in direct mode, not through a code listing. 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 `list`: Direct-only. Prints all lines in the code listing, prefixing them
with their associated line number. with their associated line number.

View File

@ -46,7 +46,7 @@ basLDBAS:
call parseDecimal call parseDecimal
jr nz, .notANumber jr nz, .notANumber
push ix \ pop de push ix \ pop de
call toSep call toSepOrEnd
call rdSep call rdSep
call bufAdd call bufAdd
pop hl ; <-- lvl 1 pop hl ; <-- lvl 1

View File

@ -41,14 +41,14 @@ basLoop:
call parseDecimal call parseDecimal
jr z, .number jr z, .number
ld de, basCmds1 ld de, basCmds1
call basCallCmd call basCallCmds
jr z, basLoop jr z, basLoop
; Error ; Error
call basERR call basERR
jr basLoop jr basLoop
.number: .number:
push ix \ pop de push ix \ pop de
call toSep call toSepOrEnd
call rdSep call rdSep
call bufAdd call bufAdd
jp nz, basERR jp nz, basERR
@ -110,6 +110,27 @@ basCallCmd:
call rdSep call rdSep
jp (ix) 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: basERR:
ld hl, .sErr ld hl, .sErr
call printstr call printstr
@ -154,7 +175,7 @@ basRUN:
call bufStr call bufStr
ld de, basCmds2 ld de, basCmds2
push ix ; --> lvl 1 push ix ; --> lvl 1
call basCallCmd call basCallCmds
pop ix ; <-- lvl 1 pop ix ; <-- lvl 1
jp nz, .err jp nz, .err
call .maybeGOTO call .maybeGOTO
@ -258,10 +279,11 @@ basIF:
ret z ret z
; expr is true, execute next ; expr is true, execute next
; (HL) back to beginning of args, skip to next arg ; (HL) back to beginning of args, skip to next arg
call toSep call toSepOrEnd
call rdSep call rdSep
ret nz
ld de, basCmds2 ld de, basCmds2
jp basCallCmd jp basCallCmds
basINPUT: basINPUT:
; If our first arg is a string literal, spit it ; If our first arg is a string literal, spit it

View File

@ -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: isSep:
cp ' ' cp ' '
ret z ret z
cp 0x09 cp 0x09
ret z
cp ','
ret ret
; Expect at least one whitespace (0x20, 0x09) at (HL), and then advance HL ; Expect at least one whitespace (0x20, 0x09) at (HL), and then advance HL
@ -23,8 +29,8 @@ rdSep:
ld a, (hl) ld a, (hl)
call isSep call isSep
jr z, .loop jr z, .loop
or a ; cp 0 call isSepOrEnd
jp z, .fail jp z, .fail ; unexpected EOL. fail
cp a ; ensure Z cp a ; ensure Z
ret ret
.fail: .fail:
@ -33,12 +39,27 @@ rdSep:
ret ret
; Advance HL to the next separator or to the end of string. ; Advance HL to the next separator or to the end of string.
toSep: toSepOrEnd:
ld a, (hl) ld a, (hl)
call isSep call isSepOrEnd
ret z ret z
inc hl 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) ; 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. ; DE is preserved, but HL is advanced to the end of the read word.
@ -47,9 +68,7 @@ rdWord:
push de push de
.loop: .loop:
ld a, (hl) ld a, (hl)
call isSep call isSepOrEnd
jr z, .stop
or a
jr z, .stop jr z, .stop
ld (de), a ld (de), a
inc hl inc hl