mirror of
https://github.com/hsoft/collapseos.git
synced 2024-12-04 04:48:06 +11:00
forth: improve input flow
Readline, instead of being triggered by the end of execution of the last compiled line is now triggered "just in time", by "WORD". This allows IMMEDIATE words reading input buffer to span multiple lines ( comments for example, but colon definitions will soon follow ).
This commit is contained in:
parent
e1f815baeb
commit
7befe56597
@ -7,18 +7,18 @@
|
||||
: NOT 1 SWAP SKIP? EXIT 0 * ;
|
||||
: RECURSE R> R> 2 - >R >R EXIT ;
|
||||
: ( LIT@ ) WORD SCMP NOT SKIP? RECURSE ; IMMEDIATE
|
||||
( Hello, hello, krkrkrkr... do you hear me? )
|
||||
( Ah, voice at last! Some lines above need comments )
|
||||
( BTW: Forth lines limited to 64 cols because of default )
|
||||
( input buffer size in Collapse OS )
|
||||
( NOT: a bit convulted because we don't have IF yet )
|
||||
( RECURSE: RS TOS is for RECURSE itself, then we have to dig )
|
||||
( one more level to get to RECURSE's parent's caller. )
|
||||
( IF true, skip following (fbr). Also, push br cell ref H, )
|
||||
( to PS )
|
||||
( Hello, hello, krkrkrkr... do you hear me?
|
||||
Ah, voice at last! Some lines above need comments
|
||||
BTW: Forth lines limited to 64 cols because of default
|
||||
input buffer size in Collapse OS
|
||||
NOT: a bit convulted because we don't have IF yet
|
||||
RECURSE: RS TOS is for RECURSE itself, then we have to dig
|
||||
one more level to get to RECURSE's parent's caller.
|
||||
IF true, skip following (fbr). Also, push br cell ref H,
|
||||
to PS )
|
||||
: IF ['] SKIP? , ['] (fbr) , H 1 ALLOT ; IMMEDIATE
|
||||
( Subtract TOS from H to get offset to write to IF or ELSE's )
|
||||
( br cell )
|
||||
( Subtract TOS from H to get offset to write to IF or ELSE's
|
||||
br cell )
|
||||
: THEN DUP H -^ SWAP C! ; IMMEDIATE
|
||||
( write (fbr) addr, allot, then same as THEN )
|
||||
: ELSE ['] (fbr) , 1 ALLOT DUP H -^ SWAP C! H 1 - ; IMMEDIATE
|
||||
|
@ -468,10 +468,18 @@ CURRENT_:
|
||||
.dw sysvarWord
|
||||
.dw CURRENT
|
||||
|
||||
.db "IN>"
|
||||
.fill 4
|
||||
.dw CURRENT_
|
||||
.db 0
|
||||
INP:
|
||||
.dw sysvarWord
|
||||
.dw INPUTPOS
|
||||
|
||||
; ( n -- )
|
||||
.db "."
|
||||
.fill 6
|
||||
.dw CURRENT_
|
||||
.dw INP
|
||||
.db 0
|
||||
DOT:
|
||||
.dw nativeWord
|
||||
|
@ -112,10 +112,21 @@ LIT@ x -- a Read following LIT and push its addr to a
|
||||
SCMP a1 a2 -- n Compare strings a1 and a2. See CMP
|
||||
|
||||
*** I/O ***
|
||||
|
||||
A little word about inputs. There are two kind of inputs: direct and buffered.
|
||||
As a general rule, we read line in a buffer, then feed words in it to the
|
||||
interpreter. That's what "WORD" does. If it's at the End Of Line, it blocks and
|
||||
wait until another line is entered.
|
||||
|
||||
KEY input, however, is direct. Regardless of the input buffer's state, KEY will
|
||||
return the next typed key.
|
||||
|
||||
. n -- Print n in its decimal form
|
||||
EMIT c -- Spit char c to stdout
|
||||
KEY -- c Get char c from stdin
|
||||
EMIT c -- Spit char c to output stream
|
||||
IN> -- a Address of variable containing current pos in input
|
||||
buffer.
|
||||
KEY -- c Get char c from direct input
|
||||
PC! c a -- Spit c to port a
|
||||
PC@ a -- c Fetch c from port a
|
||||
WORD -- a Read one word from stdin and push its addr
|
||||
WORD -- a Read one word from buffered input and push its addr
|
||||
|
||||
|
@ -102,13 +102,15 @@ forthMain:
|
||||
ld (CURRENT), hl
|
||||
ld hl, HERE_INITIAL
|
||||
ld (HERE), hl
|
||||
; Set (INPUTPOS) to somewhere where there's a NULL so we consider
|
||||
; ourselves EOL.
|
||||
ld (INPUTPOS), hl
|
||||
xor a
|
||||
ld (hl), a
|
||||
forthRdLine:
|
||||
ld hl, msgOk
|
||||
call printstr
|
||||
forthRdLineNoOk:
|
||||
call printcrlf
|
||||
call stdioReadLine
|
||||
ld (INPUTPOS), hl
|
||||
; Setup return stack. After INTERPRET, we run forthExecLine
|
||||
ld ix, RS_ADDR
|
||||
; We're about to compile the line and possibly execute IMMEDIATE words.
|
||||
@ -146,24 +148,18 @@ forthExecLine:
|
||||
|
||||
; (we don't have RECURSE here. Calling interpret makes us needlessly use our
|
||||
; RS stack, but it can take it, can't it? )
|
||||
; WORD DUP C@ (to check if null) SKIP? (skip if not null) EXIT COMPILE INTERPRET
|
||||
; WORD COMPILE IN> @ C@ (to check if null) SKIP? (skip if not null) EXIT INTERPRET
|
||||
.db 0b10 ; UNWORD
|
||||
INTERPRET:
|
||||
.dw compiledWord
|
||||
.dw WORD
|
||||
.dw DUP
|
||||
.dw COMPILE
|
||||
.dw INP
|
||||
.dw FETCH
|
||||
.dw CFETCH
|
||||
.dw CSKIP
|
||||
.dw .stop
|
||||
.dw COMPILE
|
||||
.dw INTERPRET
|
||||
.dw EXIT
|
||||
|
||||
.stop:
|
||||
.dw compiledWord
|
||||
.dw DROP
|
||||
.dw R2P
|
||||
.dw DROP
|
||||
.dw INTERPRET
|
||||
.dw EXIT
|
||||
|
||||
msgOk:
|
||||
|
@ -7,7 +7,8 @@ pad:
|
||||
; Read word from (INPUTPOS) and return, in HL, a null-terminated word.
|
||||
; Advance (INPUTPOS) to the character following the whitespace ending the
|
||||
; word.
|
||||
; Z set of word was read, unset if end of line.
|
||||
; When we're at EOL, we call fetchline directly, so this call always returns
|
||||
; a word.
|
||||
readword:
|
||||
ld hl, (INPUTPOS)
|
||||
; skip leading whitespace
|
||||
@ -16,6 +17,7 @@ readword:
|
||||
inc hl
|
||||
ld a, (hl)
|
||||
or a
|
||||
; When at EOL, fetch a new line directly
|
||||
jr z, .empty
|
||||
cp ' '+1
|
||||
jr c, .loop1
|
||||
@ -39,9 +41,8 @@ readword:
|
||||
pop hl ; <-- lvl 1. our result
|
||||
ret ; Z set from XOR A
|
||||
.empty:
|
||||
ld (hl), a
|
||||
inc a ; unset Z
|
||||
ret
|
||||
call fetchline
|
||||
jr readword
|
||||
|
||||
; Sets Z if (HL) == E and (HL+1) == D
|
||||
HLPointsDE:
|
||||
@ -336,3 +337,10 @@ DEinHL:
|
||||
ld (hl), d
|
||||
inc hl
|
||||
ret
|
||||
|
||||
fetchline:
|
||||
call printcrlf
|
||||
call stdioReadLine
|
||||
ld (INPUTPOS), hl
|
||||
ret
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user