diff --git a/apps/forth/core.fth b/apps/forth/core.fth index b01ddc7..2b8c7c2 100644 --- a/apps/forth/core.fth +++ b/apps/forth/core.fth @@ -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 diff --git a/apps/forth/dict.asm b/apps/forth/dict.asm index 0eabf72..febab0d 100644 --- a/apps/forth/dict.asm +++ b/apps/forth/dict.asm @@ -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 diff --git a/apps/forth/dictionary.txt b/apps/forth/dictionary.txt index 6213fd0..9ad8d51 100644 --- a/apps/forth/dictionary.txt +++ b/apps/forth/dictionary.txt @@ -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 diff --git a/apps/forth/main.asm b/apps/forth/main.asm index 468c42f..bb5b934 100644 --- a/apps/forth/main.asm +++ b/apps/forth/main.asm @@ -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: diff --git a/apps/forth/util.asm b/apps/forth/util.asm index b2b1a7d..b238cab 100644 --- a/apps/forth/util.asm +++ b/apps/forth/util.asm @@ -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 +