From 3819dbc0839709f05372a8901acdf3daa0af8cfe Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Thu, 12 Mar 2020 13:08:11 -0400 Subject: [PATCH] forth: remove CMPDST We now always do ","-style writes in (HERE), even in IMMEDIATE mode. Simplifies things and paves the way for compiling words in Forth. --- apps/forth/dict.asm | 16 ++++++++-------- apps/forth/main.asm | 42 ++++++++++++++++++++++++++++-------------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/apps/forth/dict.asm b/apps/forth/dict.asm index 1b8c903..97b757c 100644 --- a/apps/forth/dict.asm +++ b/apps/forth/dict.asm @@ -332,12 +332,12 @@ IMMEDIATE: .db 1 ; IMMEDIATE LITERAL: .dw nativeWord - ld hl, (CMPDST) + ld hl, (HERE) ld de, NUMBER call DEinHL pop de ; number from stack call DEinHL - ld (CMPDST), hl + ld (HERE), hl jp exit ; ( -- c ) @@ -641,12 +641,12 @@ IF: ; Spit a conditional branching atom, followed by an empty 1b cell. Then, ; push the address of that cell on the PS. ELSE or THEN will pick ; them up and set the offset. - ld hl, (CMPDST) + ld hl, (HERE) ld de, CBRANCH call DEinHL push hl ; address of cell to fill inc hl ; empty 1b cell - ld (CMPDST), hl + ld (HERE), hl jp exit .db "ELSE" @@ -657,7 +657,7 @@ ELSE: .dw nativeWord ; First, let's set IF's branching cell. pop de ; cell's address - ld hl, (CMPDST) + ld hl, (HERE) ; also skip ELSE word. inc hl \ inc hl \ inc hl or a ; clear carry @@ -667,12 +667,12 @@ ELSE: ; Set IF's branching cell to current atom address and spit our own ; uncondition branching cell, which will then be picked up by THEN. ; First, let's spit our 4 bytes - ld hl, (CMPDST) + ld hl, (HERE) ld de, BRANCH call DEinHL push hl ; address of cell to fill inc hl ; empty 1b cell - ld (CMPDST), hl + ld (HERE), hl jp exit .db "THEN" @@ -683,7 +683,7 @@ THEN: .dw nativeWord ; See comments in IF and ELSE pop de ; cell's address - ld hl, (CMPDST) + ld hl, (HERE) ; There is nothing to skip because THEN leaves nothing. or a ; clear carry sbc hl, de ; HL now has relative offset diff --git a/apps/forth/main.asm b/apps/forth/main.asm index be98a48..7fb5607 100644 --- a/apps/forth/main.asm +++ b/apps/forth/main.asm @@ -21,9 +21,6 @@ .equ HERE @+2 ; Pointer to where we currently are in the interpretation of the current line. .equ INPUTPOS @+2 -; Pointer to where compiling words should output. During interpret, it's a -; moving target in (COMPBUF). During DEFINE, it's (HERE). -.equ CMPDST @+2 ; Buffer where we compile the current input line. Same size as STDIO_BUFSIZE. .equ COMPBUF @+2 .equ FORTH_RAMEND @+0x40 @@ -38,19 +35,29 @@ ; ; 1. read single word from line ; 2. compile word to atom -; 3. execute atom -; 4. goto 1 +; 3. if immediate, execute atom +; 4. goto 1 until we exhaust words +; 5. Execute compiled atom list as if it was a regular compiledWord. ; -; During step 3, it's possible that atom read from input, so INPUTPOS might -; have moved between 3 and 4. -; -; Because the Parameter Stack uses PS, we can't just go around calling routines: +; Because the Parameter Stack uses SP, we can't just go around calling routines: ; This messes with the PS. This is why we almost always jump (unless our call ; doesn't involve Forth words in any way). ; ; This presents a challenge for our interpret loop because step 4, "goto 1" ; isn't obvious. To be able to do that, we must push a "return routine" to the ; Return Stack before step 3. +; +; HERE and IMMEDIATE: When compiling in step 2, we spit compiled atoms in +; (HERE) to simplify "," semantic in Forth (spitting, in all cases, is done in +; (HERE)). However, suring input line compilation, it isn't like during ":", we +; aren't creating a new entry. +; +; Compiling and executing from (HERE) would be dangerous because an +; entry-creation word, during runtime, could end up overwriting the atom list +; we're executing. This is why we have this list in COMPBUF. +; +; During IMMEDIATE mode, (HERE) is temporarily set to COMPBUF, and when we're +; done, we restore (HERE) for runtime. This way, everyone is happy. ; *** Code *** forthMain: @@ -78,8 +85,12 @@ forthRdLine: call stdioReadLine ld ix, RS_ADDR-2 ; -2 because we inc-before-push ld (INPUTPOS), hl + ; We're about to compile the line and possibly execute IMMEDIATE words. + ; Let's save current (HERE) and temporarily set it to COMPBUF. + ld hl, (HERE) + push hl ; Saving HERE ld hl, COMPBUF - ld (CMPDST), hl + ld (HERE), hl forthInterpret: call readword jr nz, .execute @@ -111,9 +122,9 @@ forthInterpret: ; called, triggering an abort. ld de, LIT call .writeDE - ld de, (CMPDST) + ld de, (HERE) call strcpyM - ld (CMPDST), de + ld (HERE), de jr forthInterpret .immed: push hl ; --> lvl 1 @@ -124,16 +135,19 @@ forthInterpret: .execute: ld de, QUIT call .writeDE + ; Compilation done, let's restore (HERE) and execute! + pop hl ; Restore old (HERE) + ld (HERE), hl ld iy, COMPBUF jp compiledWord .writeDE: push hl - ld hl, (CMPDST) + ld hl, (HERE) ld (hl), e inc hl ld (hl), d inc hl - ld (CMPDST), hl + ld (HERE), hl pop hl ret