basic: add support for signed integers

This commit is contained in:
Virgil Dupras 2019-11-23 14:56:23 -05:00
parent 43b450ca30
commit a680fd3328
7 changed files with 71 additions and 5 deletions

View File

@ -104,3 +104,8 @@ Symbols have a different meaning depending on the application. In zasm, it's
labels and constants. In basic, it's variables.
Expressions can't contain spaces.
Expressions can have an empty left operand. It will then be considered as 0.
This allows signed integers, for example, `-42` to be expressed as expected.
That form doesn't work well everywhere and is mostly supported for BASIC. In
zasm, you're safer with `0-42`.

View File

@ -47,10 +47,12 @@ by typing a whitespace.
### Numbers, expressions and variables
Only 16-bit integers (unsigned for now) are supported in this BASIC. When
printed, they're printed in decimal form. When expressing number literals, you
can do so either in multiple forms. . See "Number literals" in `apps/README.md`
for details.
Numbers are stored in memory as 16-bit integers (little endian) and numbers
being represented by BASIC are expressed as signed integers, in decimal form.
Line numbers, however, are expressed and treated as unsigned integers: You can,
if you want, put something on line "-1", but it will be the equivalent of line
65535. When expressing number literals, you can do so either in multiple forms.
See "Number literals" in `apps/README.md` for details.
Expressions are accepted wherever a number is expected. For example,
`print 2+3` will print `5`. See "Expressions" in `apps/README.md`.

View File

@ -192,7 +192,7 @@ basPRINT:
jr nz, .parseError
push ix \ pop de
ld hl, SCRATCHPAD
call fmtDecimal
call fmtDecimalS
call printstr
pop hl ; <-- lvl 1
.chkAnother:

View File

@ -97,8 +97,16 @@ _findAndSplit:
; parse expression on the left (HL) and the right (DE) and put the results in
; HL (left) and DE (right)
_resolveLeftAndRight:
; special case: is (HL) zero? If yes, it means that our left operand
; is empty. consider it as 0
ld ix, 0 ; pre-set to 0
ld a, (hl)
or a
jr z, .skip
; Parse left operand in (HL)
call parseExpr
ret nz ; return immediately if error
.skip:
; Now we have parsed everything to the left and we have its result in
; IX. What we need to do now is the same thing on (DE) and then apply
; the + operator. Let's save IX somewhere and parse this.

View File

@ -1,4 +1,25 @@
; Same as fmtDecimal, but DE is considered a signed number
fmtDecimalS:
bit 7, d
jr z, fmtDecimal ; unset, not negative
; Invert DE. spit '-', unset bit, then call fmtDecimal
push de
ld a, '-'
ld (hl), a
inc hl
ld a, d
cpl
ld d, a
ld a, e
cpl
ld e, a
inc de
call fmtDecimal
dec hl
pop de
ret
; Format the number in DE into the string at (HL) in a decimal form.
; Null-terminated. DE is considered an unsigned number.
fmtDecimal:

View File

@ -149,6 +149,8 @@ testParseExpr:
call .testEQ
ld iy, .t7
call .testEQ
ld iy, .t8
call .testEQ
ret
.testEQ:
@ -186,6 +188,9 @@ testParseExpr:
.t7:
.dw 0xcfb8
.db "0x99f7{3", 0
.t8:
.dw 0xffff
.db "-1", 0
nexttest:
ld a, (testNum)

View File

@ -11,6 +11,7 @@ test:
ld sp, 0xffff
call testFmtDecimal
call testFmtDecimalS
; success
xor a
@ -55,6 +56,30 @@ testFmtDecimal:
.dw 0xffff
.db "65535", 0
testFmtDecimalS:
ld ix, .t1
call .test
ld ix, .t2
call .test
ret
.test:
ld e, (ix)
ld d, (ix+1)
ld hl, sandbox
call fmtDecimalS
ld hl, sandbox
push ix \ pop de
inc de \ inc de
call strcmp
jp nz, fail
jp nexttest
.t1:
.dw 1234
.db "1234", 0
.t2:
.dw 0-1234
.db "-1234", 0
nexttest:
ld a, (testNum)
inc a