e9244b80ee
Instead of buffering input in memory one line at a time, we go in "just in time" mode and always read contents directly from I/O, without buffering. It forces us to implement a `ioPutback` scheme, but on the other hand it greatly simplifies cases where multiple tokens are on the same line (when a label is directly followed by an instruction). The end result feels much more solid and less hackish.
49 lines
908 B
NASM
49 lines
908 B
NASM
; *** Variables ***
|
|
.equ IO_IN_GETC IO_RAMSTART
|
|
.equ IO_IN_PUTC IO_IN_GETC+2
|
|
.equ IO_IN_SEEK IO_IN_PUTC+2
|
|
.equ IO_IN_TELL IO_IN_SEEK+2
|
|
.equ IO_OUT_GETC IO_IN_TELL+2
|
|
.equ IO_OUT_PUTC IO_OUT_GETC+2
|
|
.equ IO_OUT_SEEK IO_OUT_PUTC+2
|
|
.equ IO_OUT_TELL IO_OUT_SEEK+2
|
|
; see ioPutBack below
|
|
.equ IO_PUTBACK_BUF IO_OUT_TELL+2
|
|
.equ IO_RAMEND IO_PUTBACK_BUF+1
|
|
|
|
; *** Code ***
|
|
|
|
ioInit:
|
|
xor a
|
|
ld (IO_PUTBACK_BUF), a
|
|
ret
|
|
|
|
ioGetC:
|
|
ld a, (IO_PUTBACK_BUF)
|
|
or a ; cp 0
|
|
jr nz, .getback
|
|
ld ix, (IO_IN_GETC)
|
|
jp (ix)
|
|
.getback:
|
|
push af
|
|
xor a
|
|
ld (IO_PUTBACK_BUF), a
|
|
pop af
|
|
ret
|
|
|
|
; Put back non-zero character A into the "ioGetC stack". The next ioGetC call,
|
|
; instead of reading from IO_IN_GETC, will return that character. That's the
|
|
; easiest way I found to handle the readWord/gotoNextLine problem.
|
|
ioPutBack:
|
|
ld (IO_PUTBACK_BUF), a
|
|
ret
|
|
|
|
ioPutC:
|
|
ld ix, (IO_OUT_PUTC)
|
|
jp (ix)
|
|
|
|
ioSeek:
|
|
ld ix, (IO_IN_SEEK)
|
|
jp (ix)
|
|
|