1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-26 09:28:05 +11:00

Compare commits

..

8 Commits

Author SHA1 Message Date
Virgil Dupras
7410891ad1 lib/expr: fix unary minus
For some reason, I've mistakenly disabled tests in test_expr without noticing
and I also broke "-123" parsing. Fixed.
2019-12-23 20:53:31 -05:00
Virgil Dupras
6d88c3a754 parseExprDE --> parseExpr 2019-12-23 19:13:44 -05:00
Virgil Dupras
5301200d6f basic: parseExpr --> parseExprDE 2019-12-23 19:01:03 -05:00
Virgil Dupras
476178ee7c zasm: parseExpr --> parseExprDE 2019-12-23 18:44:55 -05:00
Virgil Dupras
025b90909f Update bootstrap bin 2019-12-23 16:03:23 -05:00
Virgil Dupras
aef96c5e96 Add missing common.asm test harness file 2019-12-23 16:02:26 -05:00
Virgil Dupras
cc754e12aa parseExpr --> parseExprDE: easy ones
Those replacements were trivially equivalent. For the other ones, an
examination of the context is necessary.
2019-12-23 15:59:55 -05:00
Virgil Dupras
a034f63e23 test: begin adding common test harnessing code
This should make tests a bit more convenient to write and debug.

Moreover, begin de de-IX-ization of parseExpr. I have, in a local WIP, a
parseExpr implemented using a recursive descent algo, it passes all tests, but
it unfortunately assembles a faulty zasm. I have to find the expressions that
it doesn't parse properly.

But before I do that, I prefer to commit these significant improvements I've
been making to tests harness in parallel of this development.
2019-12-23 15:41:25 -05:00
16 changed files with 230 additions and 219 deletions

View File

@ -224,7 +224,6 @@ basPRINT:
ex de, hl ex de, hl
call parseExpr call parseExpr
jr nz, .parseError jr nz, .parseError
push ix \ pop de
ld hl, SCRATCHPAD ld hl, SCRATCHPAD
call fmtDecimalS call fmtDecimalS
call printstr call printstr
@ -254,7 +253,6 @@ basGOTO:
ex de, hl ex de, hl
call parseExpr call parseExpr
ret nz ret nz
push ix \ pop de
call bufFind call bufFind
jr nz, .notFound jr nz, .notFound
push ix \ pop de push ix \ pop de
@ -317,7 +315,7 @@ basINPUT:
call rdSep call rdSep
call stdioReadLine call stdioReadLine
call parseExpr call parseExpr
ld (VAR_TBL), ix ld (VAR_TBL), de
call printcrlf call printcrlf
cp a ; ensure Z cp a ; ensure Z
ret ret

View File

@ -42,7 +42,6 @@ parseTruth:
.simple: .simple:
call parseExpr call parseExpr
jr nz, .end jr nz, .end
push ix \ pop de
ld a, d ld a, d
or e or e
jr .success jr .success
@ -132,12 +131,12 @@ parseTruth:
; place their corresponding values in HL and DE. ; place their corresponding values in HL and DE.
.parseLeftRight: .parseLeftRight:
; let's start with HL ; let's start with HL
push de ; --> lvl 1
call parseExpr call parseExpr
pop hl ; <-- lvl 1, orig DE
ret nz ret nz
push ix ; --> lvl 1. save (HL) value in stack. push de ; --> lvl 1. save HL value in stack.
ex de, hl ; Now, for DE. (DE) is now in HL
call parseExpr call parseExpr ; DE in place
ret nz pop hl ; <-- lvl 1. restore saved HL
push ix \ pop de
pop hl ; <-- lvl 1. restore.
ret ret

View File

@ -85,11 +85,13 @@ rdWord:
; Read word from HL in SCRATCHPAD and then intepret that word as an expression. ; Read word from HL in SCRATCHPAD and then intepret that word as an expression.
; Put the result in IX. ; Put the result in IX.
; Z for success. ; Z for success.
; TODO: put result in DE
rdExpr: rdExpr:
ld de, SCRATCHPAD ld de, SCRATCHPAD
call rdWord call rdWord
push hl push hl
ex de, hl ex de, hl
call parseExpr call parseExpr
push de \ pop ix
pop hl pop hl
ret ret

View File

@ -52,10 +52,9 @@ varTryAssign:
call rdWord call rdWord
ex de, hl ex de, hl
; Now, evaluate that expression now in (HL) ; Now, evaluate that expression now in (HL)
call parseExpr ; --> number in IX call parseExpr ; --> number in DE
jr nz, .exprErr jr nz, .exprErr
pop af ; <-- lvl 4 pop af ; <-- lvl 4
push ix \ pop de ; send number to DE
call varAssign call varAssign
xor a ; ensure Z xor a ; ensure Z
.end: .end:

View File

@ -11,19 +11,18 @@
; ;
; *** Code *** ; *** Code ***
; ;
; Parse expression in string at (HL) and returns the result in IX.
; Parse expression in string at (HL) and returns the result in DE.
; **This routine mutates (HL).** ; **This routine mutates (HL).**
; We expect (HL) to be disposable: we mutate it to avoid having to make a copy. ; We expect (HL) to be disposable: we mutate it to avoid having to make a copy.
; Sets Z on success, unset on error. ; Sets Z on success, unset on error.
; TODO: the IX output register is a bit awkward. Nearly everywhere, I need
; to push \ pop that thing. See if we could return the result in DE
; instead.
parseExpr: parseExpr:
push de push ix
push hl push hl
call _parseExpr call _parseExpr
push ix \ pop de
pop hl pop hl
pop de pop ix
ret ret
_parseExpr: _parseExpr:
@ -97,25 +96,29 @@ _findAndSplit:
; parse expression on the left (HL) and the right (DE) and put the results in ; parse expression on the left (HL) and the right (DE) and put the results in
; HL (left) and DE (right) ; HL (left) and DE (right)
_resolveLeftAndRight: _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) ld a, (hl)
or a or a
jr z, .skip jr z, .noleft
; Parse left operand in (HL) ; Parse left operand in (HL)
push de ; --> lvl 1
call parseExpr call parseExpr
pop hl ; <-- lvl 1, orig DE
ret nz ; return immediately if error ret nz ; return immediately if error
.skip: .parseright:
; Now we have parsed everything to the left and we have its result in ; 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 ; DE. 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. ; the + operator. Let's save DE somewhere and parse this.
ex de, hl ; right expr now in HL push de ; --> lvl 1
push ix ; --> lvl 1 ; right expr in (HL)
call parseExpr call parseExpr ; DE is set
pop hl ; <-- lvl 1. left pop hl ; <-- lvl 1. left value
push ix \ pop de ; right
ret ; Z is parseExpr's result ret ; Z is parseExpr's result
.noleft:
; special case: is (HL) zero? If yes, it means that our left operand
; is empty. consider it as 0
ex de, hl ; (DE) goes in (HL) for .parseright
ld de, 0
jr .parseright
; Routines in here all have the same signature: they take two numbers, DE (left) ; Routines in here all have the same signature: they take two numbers, DE (left)
; and IX (right), apply the operator and put the resulting number in DE. ; and IX (right), apply the operator and put the resulting number in DE.

View File

@ -643,14 +643,15 @@ _readK8:
jr _readExpr jr _readExpr
_readDouble: _readDouble:
push ix push de
call parseExpr call parseExpr
jr nz, .end jr nz, .end
push ix \ pop bc ld b, d
ld c, e
; BC is already set. For good measure, let's set A to BC's MSB ; BC is already set. For good measure, let's set A to BC's MSB
ld a, b ld a, b
.end: .end:
pop ix pop de
ret ret
_readk7: _readk7:
@ -663,13 +664,12 @@ _readk7:
; truncation checks might falsely fail. ; truncation checks might falsely fail.
call zasmIsFirstPass call zasmIsFirstPass
jr z, .end jr z, .end
; IX contains an absolute value. Turn this into a -64/+63 relative ; DE contains an absolute value. Turn this into a -64/+63 relative
; value by subtracting PC from it. However, before we do that, let's ; value by subtracting PC from it. However, before we do that, let's
; add 0x7f to it, which we'll remove later. This will simplify bounds ; add 0x7f to it, which we'll remove later. This will simplify bounds
; checks. (we use 7f instead of 3f because we deal in bytes here, not ; checks. (we use 7f instead of 3f because we deal in bytes here, not
; in words) ; in words)
push ix \ pop hl ld hl, 0x7f
ld de, 0x7f
add hl, de ; Carry cleared add hl, de ; Carry cleared
ex de, hl ex de, hl
call zasmGetPC ; --> HL call zasmGetPC ; --> HL
@ -706,6 +706,7 @@ _readR4:
; read a rXX argument and return register number in A. ; read a rXX argument and return register number in A.
; Set Z for success. ; Set Z for success.
_readR5: _readR5:
push de
push ix push ix
ld a, (hl) ld a, (hl)
call upcase call upcase
@ -714,43 +715,44 @@ _readR5:
inc hl inc hl
call parseDecimal call parseDecimal
jr nz, .end jr nz, .end
push ix \ pop de
ld a, 31 ld a, 31
call _IX2A call _DE2A
.end: .end:
pop ix pop ix
pop de
ret ret
; Put IX's LSB into A and, additionally, ensure that the new value is <= ; Put DE's LSB into A and, additionally, ensure that the new value is <=
; than what was previously in A. ; than what was previously in A.
; Z for success. ; Z for success.
_IX2A: _DE2A:
push ix \ pop hl cp e
cp l jp c, unsetZ ; A < E
jp c, unsetZ ; A < L ld a, d
ld a, h
or a or a
ret nz ; should be zero ret nz ; should be zero
ld a, l ld a, e
; Z set from "or a" ; Z set from "or a"
ret ret
; Read expr and return success only if result in under number given in A ; Read expr and return success only if result in under number given in A
; Z for success ; Z for success
_readExpr: _readExpr:
push ix push de
push bc push bc
ld b, a ld b, a
call parseExpr call parseExpr
jr nz, .end jr nz, .end
ld a, b ld a, b
call _IX2A call _DE2A
jr nz, .end jr nz, .end
or c or c
ld c, a ld c, a
cp a ; ensure Z cp a ; ensure Z
.end: .end:
pop bc pop bc
pop ix pop de
ret ret
; Parse one of the following: X, Y, Z, X+, Y+, Z+, -X, -Y, -Z. ; Parse one of the following: X, Y, Z, X+, Y+, Z+, -X, -Y, -Z.

View File

@ -40,6 +40,7 @@ dirHandlers:
.dw handleBIN .dw handleBIN
handleDB: handleDB:
push de
push hl push hl
.loop: .loop:
call readWord call readWord
@ -49,18 +50,19 @@ handleDB:
jr z, .stringLiteral jr z, .stringLiteral
call parseExpr call parseExpr
jr nz, .badarg jr nz, .badarg
push ix \ pop hl ld a, d
ld a, h
or a ; cp 0 or a ; cp 0
jr nz, .overflow ; not zero? overflow jr nz, .overflow ; not zero? overflow
ld a, l ld a, e
call ioPutB call ioPutB
jr nz, .ioError jr nz, .ioError
.stopStrLit: .stopStrLit:
call readComma call readComma
jr z, .loop jr z, .loop
cp a ; ensure Z cp a ; ensure Z
.end:
pop hl pop hl
pop de
ret ret
.ioError: .ioError:
ld a, SHELL_ERR_IO_ERROR ld a, SHELL_ERR_IO_ERROR
@ -74,9 +76,8 @@ handleDB:
.overflow: .overflow:
ld a, ERR_OVFL ld a, ERR_OVFL
.error: .error:
call unsetZ or a ; unset Z
pop hl jr .end
ret
.stringLiteral: .stringLiteral:
ld a, (hl) ld a, (hl)
@ -89,6 +90,7 @@ handleDB:
jr .stringLiteral jr .stringLiteral
handleDW: handleDW:
push de
push hl push hl
.loop: .loop:
call readWord call readWord
@ -96,17 +98,18 @@ handleDW:
ld hl, scratchpad ld hl, scratchpad
call parseExpr call parseExpr
jr nz, .badarg jr nz, .badarg
push ix \ pop hl ld a, e
ld a, l
call ioPutB call ioPutB
jr nz, .ioError jr nz, .ioError
ld a, h ld a, d
call ioPutB call ioPutB
jr nz, .ioError jr nz, .ioError
call readComma call readComma
jr z, .loop jr z, .loop
cp a ; ensure Z cp a ; ensure Z
.end:
pop hl pop hl
pop de
ret ret
.ioError: .ioError:
ld a, SHELL_ERR_IO_ERROR ld a, SHELL_ERR_IO_ERROR
@ -117,9 +120,8 @@ handleDW:
.badarg: .badarg:
ld a, ERR_BAD_ARG ld a, ERR_BAD_ARG
.error: .error:
call unsetZ or a ; unset Z
pop hl jr .end
ret
handleEQU: handleEQU:
call zasmIsLocalPass ; Are we in local pass? Then ignore all .equ. call zasmIsLocalPass ; Are we in local pass? Then ignore all .equ.
@ -149,7 +151,6 @@ handleEQU:
call parseExpr call parseExpr
jr nz, .badarg jr nz, .badarg
ld hl, DIREC_SCRATCHPAD ld hl, DIREC_SCRATCHPAD
push ix \ pop de
; Save value in "@" special variable ; Save value in "@" special variable
ld (DIREC_LASTVAL), de ld (DIREC_LASTVAL), de
call symRegisterConst ; A and Z set call symRegisterConst ; A and Z set
@ -179,14 +180,17 @@ handleEQU:
jp readWord jp readWord
handleORG: handleORG:
push de
call readWord call readWord
jr nz, .badfmt jr nz, .badfmt
call parseExpr call parseExpr
jr nz, .badarg jr nz, .badarg
push ix \ pop hl ex de, hl
ld (DIREC_LASTVAL), hl ld (DIREC_LASTVAL), hl
call zasmSetOrg call zasmSetOrg
cp a ; ensure Z cp a ; ensure Z
.end:
pop de
ret ret
.badfmt: .badfmt:
ld a, ERR_BAD_FMT ld a, ERR_BAD_FMT
@ -194,31 +198,28 @@ handleORG:
.badarg: .badarg:
ld a, ERR_BAD_ARG ld a, ERR_BAD_ARG
.error: .error:
call unsetZ or a ; unset Z
ret jr .end
handleFIL: handleFIL:
call readWord call readWord
jr nz, .badfmt jr nz, .badfmt
call parseExpr call parseExpr
jr nz, .badarg jr nz, .badarg
push bc ; --> lvl 1 ld a, d
push ix \ pop bc
ld a, b
cp 0xd0 cp 0xd0
jr nc, .overflow jr nc, .overflow
.loop: .loop:
ld a, b ld a, d
or c or e
jr z, .loopend jr z, .loopend
xor a xor a
call ioPutB call ioPutB
jr nz, .ioError jr nz, .ioError
dec bc dec de
jr .loop jr .loop
.loopend: .loopend:
cp a ; ensure Z cp a ; ensure Z
pop bc ; <-- lvl 1
ret ret
.ioError: .ioError:
ld a, SHELL_ERR_IO_ERROR ld a, SHELL_ERR_IO_ERROR
@ -230,11 +231,11 @@ handleFIL:
ld a, ERR_BAD_ARG ld a, ERR_BAD_ARG
jp unsetZ jp unsetZ
.overflow: .overflow:
pop bc ; <-- lvl 1
ld a, ERR_OVFL ld a, ERR_OVFL
jp unsetZ jp unsetZ
handleOUT: handleOUT:
push de
push hl push hl
; Read our expression ; Read our expression
call readWord call readWord
@ -244,10 +245,9 @@ handleOUT:
ld hl, scratchpad ld hl, scratchpad
call parseExpr call parseExpr
jr nz, .badarg jr nz, .badarg
push ix \ pop hl ld a, d
ld a, h
out (ZASM_DEBUG_PORT), a out (ZASM_DEBUG_PORT), a
ld a, l ld a, e
out (ZASM_DEBUG_PORT), a out (ZASM_DEBUG_PORT), a
jr .end jr .end
.badfmt: .badfmt:
@ -256,9 +256,10 @@ handleOUT:
.badarg: .badarg:
ld a, ERR_BAD_ARG ld a, ERR_BAD_ARG
.error: .error:
call unsetZ or a ; unset Z
.end: .end:
pop hl pop hl
pop de
ret ret
handleINC: handleINC:

View File

@ -146,7 +146,7 @@ parseIXY:
; any argspec (A == 0 means arg is empty). A return value of 0xff means an ; any argspec (A == 0 means arg is empty). A return value of 0xff means an
; error. ; error.
; ;
; If the parsed argument is a number constant, 'N' is returned and IX contains ; If the parsed argument is a number constant, 'N' is returned and DE contains
; the value of that constant. ; the value of that constant.
parseArg: parseArg:
call strlen call strlen
@ -154,13 +154,8 @@ parseArg:
ret z ; empty string? A already has our result: 0 ret z ; empty string? A already has our result: 0
push bc push bc
push de
push hl push hl
; We always initialize IX to zero so that non-numerical args end up with
; a clean zero.
ld ix, 0
ld de, argspecTbl ld de, argspecTbl
; DE now points the the "argspec char" part of the entry, but what ; DE now points the the "argspec char" part of the entry, but what
; we're comparing in the loop is the string next to it. Let's offset ; we're comparing in the loop is the string next to it. Let's offset
@ -181,7 +176,7 @@ parseArg:
; (HL) has no parens ; (HL) has no parens
call .maybeParseExpr call .maybeParseExpr
jr nz, .nomatch jr nz, .nomatch
; We have a proper number in no parens. Number in IX. ; We have a proper number in no parens. Number in DE.
ld a, 'N' ld a, 'N'
jr .end jr .end
.withParens: .withParens:
@ -208,23 +203,20 @@ parseArg:
.parseNumberInParens: .parseNumberInParens:
call .maybeParseExpr call .maybeParseExpr
jr nz, .nomatch jr nz, .nomatch
; We have a proper number in parens. Number in IX ; We have a proper number in parens. Number in DE
; is '-' in B? if yes, we need to negate the low part of IX ; is '-' in B? if yes, we need to negate the low part of DE
ld a, b ld a, b
cp '-' cp '-'
jr nz, .dontNegateIX jr nz, .dontNegateDE
; we need to negate the low part of IX ; we need to negate the low part of DE
; TODO: when parsing routines properly support unary negative numbers, ; TODO: when parsing routines properly support unary negative numbers,
; We could replace this complicated scheme below with a nice hack where ; We could replace this complicated scheme below with a nice hack where
; we start parsing our displacement number at the '+' and '-' char. ; we start parsing our displacement number at the '+' and '-' char.
; HL isn't needed anymore and can be destroyed. ld a, e
push ix \ pop hl
ld a, l
neg neg
ld l, a ld e, a
push hl \ pop ix .dontNegateDE:
.dontNegateIX:
ld a, c ; M, x, or y ld a, c ; M, x, or y
jr .end jr .end
.nomatch: .nomatch:
@ -235,9 +227,13 @@ parseArg:
; found the matching argspec row. Our result is one byte left of DE. ; found the matching argspec row. Our result is one byte left of DE.
dec de dec de
ld a, (de) ld a, (de)
; When we have non-numerical args, we set DE to zero to have a clean
; result.
ld de, 0
.end: .end:
pop hl pop hl
pop de
pop bc pop bc
ret ret
@ -247,6 +243,7 @@ parseArg:
; harmless, but in some cases it causes false failures. For example, ; harmless, but in some cases it causes false failures. For example,
; a "-" operator can cause is to falsely overflow and generate ; a "-" operator can cause is to falsely overflow and generate
; truncation error. ; truncation error.
ld de, 0 ; in first pass, return a clean zero
call zasmIsFirstPass call zasmIsFirstPass
ret z ret z
jp parseExpr jp parseExpr
@ -817,27 +814,18 @@ spitUpcode:
ld (INS_UPCODE+2), a ld (INS_UPCODE+2), a
ret ret
; Parse argument in (HL) and place it in (DE) ; Parse argument in (HL) and place it in (IX)
; DE is not preserved
; Sets Z on success, reset on error. ; Sets Z on success, reset on error.
processArg: processArg:
call parseArg call parseArg
cp 0xff cp 0xff
jr z, .error jr z, .error
ld (de), a ld (ix), a
; When A is a number, IX is set with the value of that number. Because ; When A is a number, DE is set with the value of that number. Because
; We don't use the space allocated to store those numbers in any other ; We don't use the space allocated to store those numbers in any other
; occasion, we store IX there unconditonally, LSB first. ; occasion, we store DE there unconditonally, LSB first.
inc de ld (ix+1), e
ex (sp), ix ; (SP) is kept in IX and will be restored ld (ix+2), d
ex (sp), hl ; old HL is on (SP)
ld a, l
ld (de), a
inc de
ld a, h
ld (de), a
ex (sp), hl ; restore old HL from (SP)
ex (sp), ix ; restore old (SP) from IX
cp a ; ensure Z cp a ; ensure Z
ret ret
.error: .error:
@ -860,14 +848,14 @@ parseInstruction:
ld (INS_CURARG2), a ld (INS_CURARG2), a
call readWord call readWord
jr nz, .nomorearg jr nz, .nomorearg
ld de, INS_CURARG1 ld ix, INS_CURARG1
call processArg call processArg
jr nz, .end ; A is set to error, Z is unset jr nz, .end ; A is set to error, Z is unset
call readComma call readComma
jr nz, .nomorearg jr nz, .nomorearg
call readWord call readWord
jr nz, .badfmt jr nz, .badfmt
ld de, INS_CURARG2 ld ix, INS_CURARG2
call processArg call processArg
jr nz, .end ; A is set to error, Z is unset jr nz, .end ; A is set to error, Z is unset
.nomorearg: .nomorearg:

View File

@ -6,9 +6,15 @@
* until it halts. The return code is the value of the register A at halt time. * until it halts. The return code is the value of the register A at halt time.
*/ */
static void iowr_stderr(uint8_t val)
{
fputc(val, stderr);
}
int main() int main()
{ {
Machine *m = emul_init(); Machine *m = emul_init();
m->iowr[0] = iowr_stderr;
// read stdin in mem // read stdin in mem
int i = 0; int i = 0;
int c = getchar(); int c = getchar();
@ -22,6 +28,7 @@ int main()
return 1; return 1;
} }
emul_loop(); emul_loop();
if (m->cpu.R1.wr.HL)
return m->cpu.R1.br.A; return m->cpu.R1.br.A;
} }

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,62 @@
; *** requirements ***
; ascii.h
; core
; stdio
; lib/ari
; lib/fmt
testNum: .db 1
STDIO_PUTC:
out (0), a
cp a
ret
STDIO_GETC:
jp unsetZ
assertZ:
ret z
ld hl, .msg
call printstr
jp fail
.msg:
.db "Z not set", CR, LF, 0
assertNZ:
ret nz
ld hl, .msg
call printstr
jp fail
.msg:
.db "Z set", CR, LF, 0
; Assert that HL == DE
assertEQW:
ld a, h
cp d
jr nz, .fail
ld a, l
cp e
ret z
.fail:
call printHexPair
call printcrlf
ex de, hl
call printHexPair
call printcrlf
ld hl, .msg
call printstr
jp fail
.msg:
.db "HL != DE", CR, LF, 0
nexttest:
ld a, (testNum)
inc a
ld (testNum), a
ret
fail:
ld a, (testNum)
halt

View File

@ -11,7 +11,7 @@ APPS="${BASE}/apps"
chk() { chk() {
echo "Running test $1" echo "Running test $1"
if ! ${ZASM} "${KERNEL}" "${APPS}" < $1 | ${RUNBIN}; then if ! ${ZASM} "${KERNEL}" "${APPS}" common.asm < $1 | ${RUNBIN}; then
echo "failed with code ${PIPESTATUS[1]}" echo "failed with code ${PIPESTATUS[1]}"
exit 1 exit 1
fi fi
@ -22,7 +22,7 @@ if [ ! -z $1 ]; then
exit 0 exit 0
fi fi
for fn in *.asm; do for fn in test_*.asm; do
chk "${fn}" chk "${fn}"
done done

View File

@ -1,5 +1,6 @@
jp test jp test
.inc "ascii.h"
.inc "core.asm" .inc "core.asm"
.inc "str.asm" .inc "str.asm"
.inc "lib/util.asm" .inc "lib/util.asm"
@ -8,6 +9,9 @@ jp test
.equ EXPR_PARSE parseLiteral .equ EXPR_PARSE parseLiteral
.inc "lib/expr.asm" .inc "lib/expr.asm"
.inc "basic/parse.asm" .inc "basic/parse.asm"
.inc "lib/fmt.asm"
.inc "stdio.asm"
.inc "common.asm"
test: test:
ld sp, 0xffff ld sp, 0xffff
@ -55,21 +59,21 @@ testParseThruth:
.true: .true:
call parseTruth call parseTruth
jp nz, fail call assertZ
or a or a
jp z, fail call assertNZ
jp nexttest jp nexttest
.false: .false:
call parseTruth call parseTruth
jp nz, fail call assertZ
or a or a
jp nz, fail call assertZ
jp nexttest jp nexttest
.error: .error:
call parseTruth call parseTruth
jp z, fail call assertNZ
jp nexttest jp nexttest
.t1: .db "42", 0 .t1: .db "42", 0
@ -88,17 +92,4 @@ testParseThruth:
.f6: .db "2<=1", 0 .f6: .db "2<=1", 0
.e1: .db "foo", 0 .e1: .db "foo", 0
testNum: .db 1 STDIO_RAMSTART:
nexttest:
ld a, (testNum)
inc a
ld (testNum), a
ret
fail:
ld a, (testNum)
halt
; used as RAM
sandbox:

View File

@ -5,8 +5,14 @@
jp test jp test
.inc "ascii.h"
.inc "core.asm"
.inc "lib/ari.asm"
.inc "lib/fmt.asm"
.inc "stdio.asm"
.inc "common.asm"
dummyLabel: dummyLabel:
testNum: .db 1
.equ dummyLabel 0x42 .equ dummyLabel 0x42
@ -37,37 +43,25 @@ test:
call nexttest call nexttest
; Test that .equ can override label ; Test that .equ can override label
ld a, 0x42 ld de, 0x42
ld hl, dummyLabel ld hl, dummyLabel
cp l call assertEQW
jp nz, fail
call nexttest call nexttest
; test that "@" is updated by a .org directive ; test that "@" is updated by a .org directive
ld hl, AFTER_ORG ld hl, AFTER_ORG
ld de, 0x1234 ld de, 0x1234
or a ; clear carry call assertEQW
sbc hl, de
jp nz, fail
call nexttest call nexttest
; test that AND affects the Z flag ; test that AND affects the Z flag
ld a, 0x69 ld a, 0x69
and 0x80 and 0x80
jp nz, fail call assertZ
call nexttest call nexttest
; success ; success
xor a xor a
halt halt
nexttest: STDIO_RAMSTART:
ld a, (testNum)
inc a
ld (testNum), a
ret
fail:
ld a, (testNum)
halt

View File

@ -9,10 +9,12 @@
jp test jp test
.inc "ascii.h"
.inc "core.asm" .inc "core.asm"
.inc "str.asm" .inc "str.asm"
.inc "lib/util.asm" .inc "lib/util.asm"
.inc "lib/ari.asm" .inc "lib/ari.asm"
.inc "lib/fmt.asm"
.inc "zasm/util.asm" .inc "zasm/util.asm"
.inc "zasm/const.asm" .inc "zasm/const.asm"
.inc "lib/parse.asm" .inc "lib/parse.asm"
@ -21,6 +23,9 @@ jp test
.inc "zasm/symbol.asm" .inc "zasm/symbol.asm"
.equ EXPR_PARSE parseNumberOrSymbol .equ EXPR_PARSE parseNumberOrSymbol
.inc "lib/expr.asm" .inc "lib/expr.asm"
.equ STDIO_RAMSTART SYM_RAMEND
.inc "stdio.asm"
.inc "common.asm"
; Pretend that we aren't in first pass ; Pretend that we aren't in first pass
zasmIsFirstPass: zasmIsFirstPass:
@ -29,8 +34,6 @@ zasmIsFirstPass:
zasmGetPC: zasmGetPC:
ret ret
testNum: .db 1
s1: .db "2+2", 0 s1: .db "2+2", 0
s2: .db "0x4001+0x22", 0 s2: .db "0x4001+0x22", 0
s3: .db "FOO+BAR", 0 s3: .db "FOO+BAR", 0
@ -44,29 +47,22 @@ sBAR: .db "BAR", 0
test: test:
ld sp, 0xffff ld sp, 0xffff
; New-style tests
call testParseExpr
; Old-style tests, not touching them now. ; Old-style tests, not touching them now.
ld hl, s1 ld hl, s1
call parseExpr call parseExpr
jp nz, fail call assertZ
push ix \ pop hl ld hl, 4
ld a, h call assertEQW
or a
jp nz, fail
ld a, l
cp 4
jp nz, fail
call nexttest call nexttest
ld hl, s2 ld hl, s2
call parseExpr call parseExpr
jp nz, fail call assertZ
push ix \ pop hl ld hl, 0x4023
ld a, h call assertEQW
cp 0x40
jp nz, fail
ld a, l
cp 0x23
jp nz, fail
call nexttest call nexttest
; before the next test, let's set up FOO and BAR symbols ; before the next test, let's set up FOO and BAR symbols
@ -82,54 +78,32 @@ test:
ld hl, s3 ld hl, s3
call parseExpr call parseExpr
jp nz, fail call assertZ
push ix \ pop hl ld hl, 0x4020
ld a, h call assertEQW
cp 0x40
jp nz, fail
ld a, l
cp 0x20
jp nz, fail
call nexttest call nexttest
ld hl, s4 ld hl, s4
call parseExpr call parseExpr
jp nz, fail call assertZ
push ix \ pop hl ld hl, 0x60
ld a, h call assertEQW
or a
jp nz, fail
ld a, l
cp 0x60
jp nz, fail
call nexttest call nexttest
ld hl, s5 ld hl, s5
call parseExpr call parseExpr
jp nz, fail call assertZ
push ix \ pop hl ld hl, 0x3ffd
ld a, h call assertEQW
cp 0x3f
jp nz, fail
ld a, l
cp 0xfd
jp nz, fail
call nexttest call nexttest
ld hl, s6 ld hl, s6
call parseExpr call parseExpr
jp nz, fail call assertZ
push ix \ pop hl ld hl, 0x4080
ld a, h call assertEQW
cp 0x40
jp nz, fail
ld a, l
cp 0x80
jp nz, fail
call nexttest call nexttest
; New-style tests
call testParseExpr
; success ; success
xor a xor a
halt halt
@ -151,20 +125,18 @@ testParseExpr:
call .testEQ call .testEQ
ld iy, .t8 ld iy, .t8
call .testEQ call .testEQ
ld iy, .t9
call .testEQ
ret ret
.testEQ: .testEQ:
push iy \ pop hl push iy \ pop hl
inc hl \ inc hl inc hl \ inc hl
call parseExpr call parseExpr
jp nz, fail call assertZ
push ix \ pop de ld l, (iy)
ld a, e ld h, (iy+1)
cp (iy) call assertEQW
jp nz, fail
ld a, d
cp (iy+1)
jp nz, fail
jp nexttest jp nexttest
.t1: .t1:
@ -191,13 +163,6 @@ testParseExpr:
.t8: .t8:
.dw 0xffff .dw 0xffff
.db "-1", 0 .db "-1", 0
.t9:
nexttest: .dw 10
ld a, (testNum) .db "2*3+4", 0
inc a
ld (testNum), a
ret
fail:
ld a, (testNum)
halt