stage0/stage3/inital_library.fs

247 lines
9.2 KiB
Forth
Raw Normal View History

\ Copyright (C) 2017 Jeremiah Orians
\ Copyright (C) 2017 Reepca
\ This file is part of stage0.
\
\ stage0 is free software: you can redistribute it and/or modify
\ it under the terms of the GNU General Public License as published by
\ the Free Software Foundation, either version 3 of the License, or
\ (at your option) any later version.
\
\ stage0 is distributed in the hope that it will be useful,
\ but WITHOUT ANY WARRANTY; without even the implied warranty of
\ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\ GNU General Public License for more details.
\
\ You should have received a copy of the GNU General Public License
\ along with stage0. If not, see <http://www.gnu.org/licenses/>.
\ Simply cat this file to the top of any forth program that leverages its functionality
\ then execute the resulting out put as so:
\ ./bin/vm --rom roms/forth --memory 1M --tape_01 The_combined_file
\ All writes via WRITE8 will be written to tape_02 or whatever name you prefer via the --tape_02 option
\ However should you wish to leverage readline for interacting with forth use vm-production but be warned
\ WILL see duplicate lines being printed when you hit enter as both readline and the forth are echoing your key strokes
\ Define our CELL size as 4 bytes
: CELL 4 ;
\ Save us from manually calculating how many bytes is a given number of CELLS
: CELLS CELL * ;
\ Setup an easy to reference FLAGS offset Constant
: >FLAGS 2 CELLS + ;
\ Update the flags of the latest defintion to IMMEDIATE
: IMMEDIATE LATEST >FLAGS DUP @ 0x2 OR SWAP ! ;
\ Define ALLOT to allocate a give number of bytes
: ALLOT HERE + DP! ;
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
\ Read a word, lookup and return pointer to its definition.
: ' WORD DROP FIND >CFA ;
\ Lookup a word and write the address of its definition
: [COMPILE] ' , ; IMMEDIATE
\ The literal code address of LIT. Don't think too hard about it.
: LITERAL [ ' LIT DUP , , ] , , ;
\ Compile the CFA of a word looked up as a literal
: ['] ' LITERAL ; 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 ! ;
\ equivalent to "ENDIF".
: THEN HERE TARGET! ; IMMEDIATE
\ And our ELSE for our IF
: ELSE HERE 2 CELLS + TARGET! ['] BRANCH , HERE 0 , ; IMMEDIATE
\ A backwards branch destination, to be resolved by AGAIN, UNTIL, or REPEAT.
: BEGIN HERE ; IMMEDIATE
\ This forward conditional branch will be resolved by REPEAT.
: WHILE [COMPILE] IF SWAP ; IMMEDIATE
\ Resolve a backwards branch.
: AGAIN ['] BRANCH , HERE SWAP TARGET! CELL ALLOT ; 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 [CHAR] t ELSE [CHAR] f THEN EMIT ;
\ Writes a Byte to HEAP
: C, HERE C! 1 ALLOT ;
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
\ addr count -- high low
: BOUNDS OVER + SWAP ;
\ Prints Memory from address a to a + b when invoked as a b TYPE
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
: TYPE BOUNDS BEGIN 2DUP > WHILE DUP C@ EMIT 1 + REPEAT 2DROP ;
\ So we don't have to type 10 EMIT for newlines anymore
: CR 10 EMIT ;
\ Makes a string on the HEAP from everything between it and "
: STR" HERE BEGIN KEY DUP [CHAR] " != WHILE C, REPEAT DROP HERE OVER - ;
\ Extends STR" to work in Compile mode
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
: S" STATE IF ['] BRANCH , HERE 0 , STR" ROT HERE TARGET! SWAP LITERAL LITERAL
ELSE STR" THEN ; IMMEDIATE
2017-07-13 02:07:53 +01:00
\ Extends S" to behave the way most users want
: ." [COMPILE] S" STATE IF ['] TYPE , ELSE TYPE THEN ; IMMEDIATE
\ add the ANS keyword for modulus
: MOD % ;
\ add ANS keyword for getting both Quotent and Remainder
: /MOD 2DUP MOD >R / R> ;
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
\ valid bases are from 2 to 36.
CREATE BASE 10 ,
\ Primitive needed for printing base 10 numbers
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
: NEXT-DIGIT BASE @ /MOD ;
\ Give us a 400bytes of storage to play with
: PAD HERE 100 CELLS + ;
\ Assuming 2's complement
: NEGATE NOT 1 + ;
\ Swap the contents of 2 Memory addresses
: CSWAP! 2DUP C@ SWAP C@ ROT C! SWAP C! ;
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
\ Given an address and a number of Chars, reverses a string (handy for little
\ endian systems that have bytes in the wrong order)
: REVERSE-STRING OVER + 1 -
BEGIN 2DUP < WHILE 2DUP CSWAP! 1 - SWAP 1 + SWAP REPEAT 2DROP ;
\ Given an address and number, writeout number at address and increment address
: +C! OVER C! 1 + ;
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
\ works for hex and stuff
2017-07-13 02:07:53 +01:00
: >ASCII-DIGIT DUP 10 < IF 48 ELSE 55 THEN + ;
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
\ 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 [CHAR] - +C!
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
THEN DUP >R SWAP \ R: str-start digits-start
BEGIN NEXT-DIGIT ROT SWAP >ASCII-DIGIT +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 ;
\ A temp constant that is going to be replaced
: STACK-BASE 0x00090000 ;
\ Given current stack pointer calculate and display number of underflowed cells
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
: .UNDERFLOW ." Warning: stack is underflowed by "
STACK-BASE SWAP - CELL / . ." cells!" CR ;
\ Display the number of entries on stack in <n> form
: .HEIGHT STACK-BASE - CELL / ." <" . ." > " ;
\ Display count and contents of stack or error message if Underflow
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
: .S DSP@ DUP STACK-BASE < IF .UNDERFLOW
ELSE DUP .HEIGHT STACK-BASE
BEGIN 2DUP > WHILE DUP @ . 32 EMIT CELL + REPEAT
2DROP
THEN ;
\ Pop off contents of stack to Zero stack
: CLEAR-STACK BEGIN DSP@ STACK-BASE > WHILE .S 10 EMIT DROP REPEAT STACK-BASE DSP! ;
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
: ( BEGIN KEY [CHAR] ) = UNTIL ; IMMEDIATE
\ Note: for further reading, see brad rodriguez's moving forth stuff.
\ The return address currently on the stack points to the next word to be
\ executed. DOER! should only be compiled by DOES> or other similar words, so
\ the address on the return stack should be right past DOER!'s. Which should be
\ the code to make the action for the latest word. Since we only want to set
\ this code as the latest word's action, not actually execute it at this point,
\ we don't bother putting anything back on the return stack - we'll return
\ straight up past the word we came from.
\ For example: consider this definition
\ : CONSTANT CREATE , DOES> @ ;
\ This compiles to the sequence: DOCOL CREATE , DOER! @ EXIT
\ DOER! will point the latest word (the CREATEd one) to the code right past it -
\ the @ EXIT - and then exit the definition it's in.
: DOER! R> SWAP >CFA ! ;
\ This is a tricky one. Basically, we need to compile a little bit of machine
\ code that will invoke the code that follows. Notes: R12 should, at this point,
\ have the address of the place we got here from. So we should just put
\ that+cell on the stack (for use by what follows DOES>) and run DOCOL. (Note:
\ implemented in forth.s)
\ Assumes most significant byte is at lower address
2017-07-13 02:07:53 +01:00
: 2C, DUP 0xFF00 AND 8 RSHIFT C, 0xFF AND C, ;
\ Compiles an assembly-level jump to a location.
\ We may have to compile more than just a jump in the future in order
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
\ for DOES> to work properly - we'd need to load the address into a register,
\ having the actual address nearby, and then use that coroutine jump thing.
\ JUMP over the Address, the address, LOADRU32 R0 -4, JSR_COROUTINE R0
: JUMP-TO, 0x3C000008 , , 0x2E60FFFC , 0x0D010000 , ;
Fix CREATE, implement DOES>, more words Implemented some new words in forth.s: * 'DODOES Gives the address of the assembly for DODOES. Used by DOES> when compiling machine code to jump to it and activate the following high-level forth code. This is how non-primitive actions for a word can be set. * LATEST! Sets the LATEST pointer. For when the user wants to write their own way of extending the dictionary (word lists, vocabularies, etc). * R@ Copies the top of the return stack to the data stack. Useful for when loops start getting non-trivial and you start wondering of all those ROTs aren't efficient enough. Maybe someday we'll implement a register-allocating compiler. Probably not. Too complicated for bootstrapping. * Not really words but used: DODOES and DOVAR. DOVAR is the default behavior of CREATEd words - it just pushes a pointer to whatever was allotted right after the word was created. DODOES is jumped to in order to invoke high-level forth behaviors for words. * Changed behavior of CREATE to better match the way it usually works. Added some words to inital_library.fs (we should fix that name sometime): * Added a variable BASE to control what base numbers are printed in. * Turns out I misunderstood what WORD did and mis-diagnosed an early problem in ' - so it turns out that nothing was being allotted in the dictionary, just stuff in "string space", which if I understand properly just sort of fills up infinitely as long as WORD is being invoked. Some other forths try to solve this by introducing an input buffer for the current line, at the cost of some complexity (as words like [CHAR] and S" have to take that into account). Anyway, the HERE and DP! are gone from ' now. * Added BOUNDS for common setup for sequence-iterating loops. * Added region-comment "(" (note that it doesn't nest), used most often for stack comments. * Added hex dump printer DUMP and support words, number of bytes printed per line is controlled by LINE-SIZE. It looks pretty nice, much of the design is based off of gforth's. * Added DOES> and supporting words, and used it to make VARIABLE, CONSTANT, and DEFER. * Added TUCK, MIN, SPACES, :NONAME, FILL, and <>. Add LSHIFT and RSHIFT to the wishlist, as ghetto shifting with division seems to behave a bit strangely when given negative values. Also, we're now advanced enough to support the tictactoe I wrote awhile back for gforth! http://paste.lisp.org/display/349394
2017-06-24 08:31:53 +01:00
\ Sets the action of the latest word
: DOES> ['] LATEST , ['] DOER! , 'DODOES JUMP-TO, ; IMMEDIATE
\ Sets the action of a certain word
: DOER> ['] DOER! , 'DODOES JUMP-TO, ; IMMEDIATE
: TUCK SWAP OVER ;
: MIN 2DUP < IF SWAP THEN DROP ;
: HEX 16 BASE ! ;
: DECIMAL 10 BASE ! ;
CREATE LINE-SIZE CELL ,
: PRINTABLE? DUP 127 < SWAP 31 > AND ;
: EMIT-PRINTABLE DUP PRINTABLE? IF EMIT ELSE DROP [CHAR] . EMIT THEN ;
: DUMP-TYPE BOUNDS BEGIN 2DUP > WHILE DUP C@ EMIT-PRINTABLE 1 + REPEAT 2DROP ;
\ will always print two characters.
: .HEX-BYTE DUP 16 / >ASCII-DIGIT EMIT 15 AND >ASCII-DIGIT EMIT ;
: DUMP-LINE 2DUP BOUNDS BEGIN 2DUP > WHILE DUP C@ .HEX-BYTE ." " 1 + REPEAT
2DROP ." " DUMP-TYPE CR ;
: DUMP-LINES LINE-SIZE @ * BOUNDS
BEGIN 2DUP > WHILE DUP LINE-SIZE @ TUCK DUMP-LINE + REPEAT 2DROP ;
: DUMP LINE-SIZE @ /MOD -ROT 2DUP DUMP-LINES LINE-SIZE @ * + SWAP DUMP-LINE ;
: VARIABLE CREATE 0 , ;
: CONSTANT CREATE , DOES> @ ;
: NOOP ;
: DEFER CREATE ['] NOOP , DOES> @ EXECUTE ;
: IS ' CELL + STATE IF LITERAL ['] ! , ELSE ! THEN ; IMMEDIATE
\ emits n spaces.
: SPACES BEGIN DUP WHILE 32 EMIT 1 - REPEAT DROP ;
' NOOP @ CONSTANT 'DOCOL
\ Starts a definition without a name, leaving the execution token (the thing
\ that can be passed to EXECUTE) on the stack.
: :NONAME HERE 'DOCOL , ] ;
\ fill n bytes with char.
\ addr n char --
: FILL >R BOUNDS BEGIN 2DUP > WHILE DUP R@ C! 1 + REPEAT 2DROP R> DROP ;
: <> != ;