zasm: fix expr returning wrong values on first pass

To run a parseExpr on first pass would always return a false success
with dummy value because symbols are configured to always succeed on
first pass. This would make expressions like ".fill 0x38-$" so bad
things to labels because "0x38-$" wouldn't return the same thing on
first and second pass.

Revert to parsing literals and symbols after having scanned for
expressions and add a special case specifically for char literals (which
is why we scanned for literals and symbols first in the first place).
This commit is contained in:
Virgil Dupras 2019-05-20 10:46:27 -04:00
parent e18f9b53a9
commit c40bc329d5
3 changed files with 24 additions and 6 deletions

View File

@ -118,6 +118,7 @@ handleFIL:
call ioPutC call ioPutC
djnz .loop djnz .loop
pop bc pop bc
ret
handleINC: handleINC:
call readWord call readWord

View File

@ -2,11 +2,6 @@
; 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.
parseExpr: parseExpr:
; Before we evaluate an expression, we first try for a regular number or
; symbol. We do this because parsing expressions can mess up some values
; with its splitting logic. For example '-' is going to end up '\0'.
call parseNumberOrSymbol
ret z
push de push de
push hl push hl
call _parseExpr call _parseExpr
@ -24,7 +19,7 @@ _parseExpr:
ld a, '*' ld a, '*'
call _findAndSplit call _findAndSplit
jp z, _applyMult jp z, _applyMult
ret ; failure jp parseNumberOrSymbol
; Given a string in (HL) and a separator char in A, return a splitted string, ; Given a string in (HL) and a separator char in A, return a splitted string,
; that is, the same (HL) string but with the found A char replaced by a null ; that is, the same (HL) string but with the found A char replaced by a null
@ -32,6 +27,7 @@ _parseExpr:
; Sets Z if found, unset if not found. ; Sets Z if found, unset if not found.
_findAndSplit: _findAndSplit:
push hl push hl
call .skipCharLiteral
call findchar call findchar
jr nz, .end ; nothing found jr nz, .end ; nothing found
; Alright, we have our char and we're pointing at it. Let's replace it ; Alright, we have our char and we're pointing at it. Let's replace it
@ -45,6 +41,27 @@ _findAndSplit:
pop hl ; HL is back to the start pop hl ; HL is back to the start
ret ret
.skipCharLiteral:
; special case: if our first char is ', skip the first 3 characters
; so that we don't mistake a literal for an iterator
push af
ld a, (hl)
cp 0x27 ; '
jr nz, .skipCharLiteralEnd ; not a '
xor a ; check for null char during skipping
; skip 3
inc hl
cp (hl)
jr z, .skipCharLiteralEnd
inc hl
cp (hl)
jr z, .skipCharLiteralEnd
inc hl
.skipCharLiteralEnd:
pop af
ret
.find:
; 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
; DE (left) and IX (right) ; DE (left) and IX (right)
_resolveLeftAndRight: _resolveLeftAndRight:

Binary file not shown.