From c159b6a927e8305ecc54d068688f4c7556cef935 Mon Sep 17 00:00:00 2001 From: Caleb Ristvedt Date: Wed, 21 Jun 2017 03:32:38 -0500 Subject: [PATCH] Refactor, fix bugs, and reword comments in initial_library.fs Some of the comments seemed a bit off. Additionally, there was a bug in AGAIN in which it didn't actually compile a jump. Also, WHILE's compile-time stack effect is now consistent with gforth, which means we can have multi-exit while loops. Also, added UNTIL. Also, added [CHAR] so we don't have to keep looking up ascii values for characters. Also, whichever bug it was that caused problems with splitting definitions up across multiple lines is now gone, so long live the newlines! --- stage3/inital_library.fs | 42 +++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/stage3/inital_library.fs b/stage3/inital_library.fs index 5f17cce..7e5f91f 100644 --- a/stage3/inital_library.fs +++ b/stage3/inital_library.fs @@ -46,11 +46,13 @@ \ The literal code address of LIT. Don't think too hard about it. : LITERAL [ ' LIT DUP , , ] , , ; -\ Lookup a word and append some literals +\ Compile the CFA of a word looked up as a literal : ['] ' LITERAL ; IMMEDIATE -\ Define IF as if top of stack is false branch to Literal value not yet written -: IF [ ' 0BRANCH LITERAL ] , HERE 0 , ; IMMEDIATE +\ CONTROL STRUCTURES + +\ Compile a conditional forward branch, to be resolved by THEN or ELSE. +: IF ['] 0BRANCH , HERE 0 , ; IMMEDIATE \ Get displacement between two address and write the difference to the address first given : TARGET! OVER - SWAP ! ; @@ -61,20 +63,31 @@ \ And our ELSE for our IF : ELSE HERE 2 CELLS + TARGET! ['] BRANCH , HERE 0 , ; IMMEDIATE -\ Put here on the stack for the while to pickup and turn into an immediate jump +\ A backwards branch destination, to be resolved by AGAIN, UNTIL, or REPEAT. : BEGIN HERE ; IMMEDIATE -\ Use stack value from begin to loop if still true -: WHILE [COMPILE] IF ; IMMEDIATE +\ This forward conditional branch will be resolved by REPEAT. +: WHILE [COMPILE] IF SWAP ; IMMEDIATE -\ Who doesn't love repeat? -: REPEAT HERE 2 CELLS + TARGET! ['] BRANCH , HERE SWAP TARGET! CELL ALLOT ; IMMEDIATE +\ Resolve a backwards branch. +: AGAIN ['] BRANCH , HERE SWAP TARGET! CELL ALLOT ; IMMEDIATE -\ Writes our repetition target -: AGAIN HERE SWAP TARGET! ; IMMEDIATE +: UNTIL ['] 0BRANCH , HERE SWAP TARGET! CELL ALLOT ; IMMEDIATE + +\ Resolve the latest forward branch and compile a backwards branch. +: REPEAT [COMPILE] AGAIN [COMPILE] THEN ; IMMEDIATE + +\ Note that it is possible to use multiple exits from a +\ BEGIN ... WHILE ... REPEAT loop, as long as you resolve the forward branches +\ manually. For example, BEGIN ... WHILE ... WHILE ... REPEAT THEN will allow +\ an exit from either WHILE. You can even put other stuff between the REPEAT and +\ THEN if you need to handle certain exits specially. Use sparingly unless +\ you're sure you understand how it works. + +: [CHAR] KEY LITERAL ; IMMEDIATE \ If true put t otherwise put f -: .BOOL IF 116 EMIT ELSE 102 EMIT THEN ; +: .BOOL IF [CHAR] t ELSE [CHAR] f THEN EMIT ; \ Writes a Byte to HEAP : C, HERE C! 1 ALLOT ; @@ -86,7 +99,7 @@ : CR 10 EMIT ; \ Makes a string on the HEAP from everything between it and " -: STR" HERE BEGIN KEY DUP 34 != WHILE C, REPEAT DROP HERE OVER - ; +: STR" HERE BEGIN KEY DUP [CHAR] " != WHILE C, REPEAT DROP HERE OVER - ; \ Extends STR" to work in Compile mode : S" STATE IF ['] BRANCH , HERE 0 , STR" ROT HERE TARGET! SWAP LITERAL LITERAL ELSE STR" THEN ; IMMEDIATE @@ -119,7 +132,10 @@ : +C! OVER C! 1 + ; \ Given a number and address write out string form of number at address and returns address and length (address should have at least 10 free bytes). -: NUM>STRING DUP >R OVER 0 < IF SWAP NEGATE SWAP 45 +C! THEN DUP >R SWAP BEGIN NEXT-DIGIT ROT SWAP 48 + +C! SWAP DUP WHILE REPEAT DROP R> 2DUP - REVERSE-STRING R> SWAP OVER - ; +: NUM>STRING DUP >R OVER 0 < IF SWAP NEGATE SWAP [CHAR] - +C! + THEN DUP >R SWAP + BEGIN NEXT-DIGIT ROT SWAP 48 + +C! SWAP DUP WHILE REPEAT + DROP R> 2DUP - REVERSE-STRING R> SWAP OVER - ; \ A user friendly way to print a number : . PAD NUM>STRING TYPE ;