Related pages:
⇒ See FORTH 3/4.
: 2LITERAL SWAP POSTPONE LITERAL POSTPONE LITERAL ; IMMEDIATE
: 2constant SWAP CREATE , , DOES> DUP @ SWAP CELL+ @ ; : 2variable CREATE 2 CELLS ALLOT ;
create myStr "Hello World!" : str. ". ; myStr str Hello World!
:a0 aPrimitve00 aPrimitive01 EXIT :a1 aPrimitive10 aPrimitive11 EXIT :a2 CALL a1 CALL a0 EXIT :a3 CALL a2 EXIT
:a0 CALL &aPrimitve00 &aPrimitive01 &EXIT :a1 CALL &aPrimitive10 &aPrimitive11 &EXIT :a2 CALL &a1 &a0 &EXIT :a3 CALL &a2 &EXIT
:a0 call aPrimitve00 call aPrimitive01 ret :a1 call aPrimitive10 call aPrimitive11 ret :a2 call a1 call a0 ret :a3 call a2 ret
: a0 aPrimitve00 aPrimitive01 ;
: a1 aPrimitive10 aPrimitive11 ;
: a2 a1 a0 ;
[token of ENTER] [token of a1] [token of a0] [token of EXIT]
: LIT R> DUP 4 + >R @ ;
R00# LIT 1234 --- R01# .S --- 0 : $000004D2 1,234
LIT 1234 :1: Invalid memory address >>>LIT<<< 1234 Backtrace:
: S" \ comp: ( -<string">- ) run: ( -- addr len ) \ *G Compiletime: s" parses the input stream until it finds the next " and \ ** compiles it into the current definition. Runtime: s" leaves the address \ ** and the length of the compiled string on the stack. STATE @ IF COMPILE (S") ," \ see also ." and .( ELSE ((S")) THEN ; IMMEDIATE
- accept input from user - find word in dictionary -- if found - check immediate flag and execute the word if so; --- if word is not immediate - check VM state: ---- if state is execution - execute the word ---- if state is compilation - compile the word into threaded code -- if word is not found --- try to interpret it as a number ---- if it is a number - check VM state ----- if state is execution - put the number to the top of the stack ----- if state is compilation - compile number as LITERAL ---- if the word can't be interpreted as number - display error message - repeat all above forever
| Primitive | Stack effects | Description |
|---|---|---|
| >r | ( x – ) | |
| r> | ( – x ) | |
| 1+ | ( x – y ) | |
| 0= | ( x – flag ) | |
| nand | ( x y – z ) | |
| @ | ( addr – x ) | |
| dup! | ( x addr – x ) | |
| execute | ( addr – ) | |
| exit | ( – ) | |
| May be included because of hardware considerations | ||
| drop | ( x – ) | |
| dup | ( x – x x ) | |
| swap | ( x y – y x ) | |
| Primitive | Stack effects | Description |
|---|---|---|
| @ | ( addr – x ) | Fetch memory contents at addr |
| ! | ( x addr – ) | Store x at addr |
| sp@ | ( – sp ) | Get pointer to top of data stack |
| rp@ | ( – rp ) | Get pointer to top of return stack |
| 0= | ( x – flag ) | -1 if top of stack is 0, 0 otherwise |
| + | ( x y – z ) | Sum the two numbers at the top of the stack |
| nand | ( x y – z ) | NAND the two numbers at the top of the stack |
| exit | ( r:addr – ) | Pop return stack and resume execution at addr |
| key | ( – x ) | Read key stroke as ASCII character |
| emit | ( x – ) | Print low byte of x as an ASCII character |
| Variable | Description |
|---|---|
| state | 0: execute words; 1: compile word addresses to the dictionary |
| tib | Terminal input buffer, where input is parsed from |
| >in | Current parsing offset into terminal input buffer |
| here | Pointer to next free position in the dictionary |
| latest | Pointer to most recent dictionary entry |
| #(oct) | Primitive | FORTH Word #1 | FORTH Word #2 | Stack effects | Description |
|---|---|---|---|---|---|
| Jump Instructions | |||||
| 00 | Ret | ”;” | ”;” | Jump thru R (destructive) | |
| 01 | Exec | “ex” | ” ;:” | Jump thru R, save P in R | |
| 02 | Jmp | “jump” | “jump” | Jump thru I ( The opcode is not used explicitly. The compiler generates it ) | |
| 03 | Call | “call” | “call” | Jump thru I, push current address to R ( The opcode is not used explicitly. Referencing any defined word generates a call ) | |
| 04 | Unext | “unext” | “unext” | Jump to slot 0 ( Discards the address left by for ) | |
| 05 | Next | “next” | “next” | If R is non-zero, jump thru I and decrement R. Otherwise pop R | |
| 06 | If | “if” | “if” | Jump thru I if T is zero | |
| 07 | MinusIf | ”-if” | ”-if” | Jump thru I if T is positive | |
| Memory Instructions | |||||
| 10 | FetchP | ”@p” | ”@p+” | Fetch thru P, increment P | |
| 11 | FetchPlus | ”@+” | ”@+” | Fetch thru A, increment A | |
| 12 | FetchB | ”@b” | ”@b” | Fetch thru B | |
| 13 | Fetch | ”@” | ”@” | Fetch thru A | |
| 14 | StoreP | ”!p” | ”!p+” | Store thru P, increment P | |
| 15 | StorePlus | ”!+” | ”!+” | Store thru A, increment A | |
| 16 | StoreB | ”!b” | ”!b” | Store thru B | |
| 17 | Store | ”!” | ”!” | Store thru A | |
| ALU Instructions | |||||
| 20 | MultiplyStep | ”+*” | ”+*” | Multiply step: add S to T if A0=1 then shift T and A right | |
| 21 | Times2 | “2*” | “2*” | Shift T left | |
| 22 | Div2 | “2/” | “2/” | Shift T right; sign fill | |
| 23 | Not | ”-” | ”-” | One's complement T | |
| 24 | Plus | ”+” | ”+” | Add S to T (discard S) | |
| 24 | Add S to T with carry ( Requires bit 9 of P be set ) | ||||
| 25 | And | “and” | “and” | Bit-wise and of S and T | |
| 26 | Or | “or” | “or” | Bit-wise exclusive-or of S and T | |
| 27 | Drop | “drop” | “drop” | Discard T | |
| Stack Instructions | |||||
| 30 | Dup | “dup” | “dup” | Create a working copy of T | |
| 31 | Pop | “pop” | “pop” | Fetch R (destructive) | |
| 32 | Over | “over” | “over” | Fetch S (non-destructive) | |
| 33 | ReadA | “a” | “a” | Fetch A (non-destructive) | |
| 34 | Nop | ”.” | ”.” | Do nothing | |
| 35 | Push | “push” | “push” | Push T into R | |
| 36 | SetB | “b!” | “b!” | Store into B ( Be careful to distinguish b! and !b ) | |
| 37 | SetA | “a!” | “a!” | Store into A | |
| Type | Ting | Brinkhoff | Plichota | GA-F18 | Stack effect | Comments |
|---|---|---|---|---|---|---|
| Memory Access | C@ | C@ | ||||
| C@ | C@ | |||||
| @ | @ | @ | @ | |||
| a | ||||||
| @a | ||||||
| @p | ||||||
| @b | ||||||
| @+ | ||||||
| !p | ||||||
| !+ | ||||||
| !b | ||||||
| a! | ||||||
| b! | ||||||
| ! | ! | ! | ! | |||
| Math | + | + | + | + | ||
| - | - | |||||
| +* | ||||||
| 2* | ||||||
| * | * | |||||
| / | ||||||
| 2/ | ||||||
| MOD | ||||||
| Logic | AND | NAND | NAND | and | ||
| OR | or | |||||
| XOR | XOR | |||||
| INVERT | ||||||
| Stack | DUP | DUP | dup | |||
| SWAP | SWAP | |||||
| OVER | over | |||||
| DROP | DROP | drop | ||||
| >R | >R | push | ||||
| R> | R> | pop | ||||
| R@ | ||||||
| Control | IF | 0BRANCH | IF | if | ||
| -if | ||||||
| ELSE | ||||||
| THEN | ||||||
| BEGIN | ||||||
| WHILE | ||||||
| REPEAT | ||||||
| AGAIN | ||||||
| DO | ||||||
| LOOP | ||||||
| EXECUTE | ex | |||||
| <name>; | ||||||
| <name> | ||||||
| unext | ||||||
| next | ||||||
| EXIT | EXIT | |||||
| Defining | : | : | ||||
| ; | ; | ; | ||||
| CONSTANT | ||||||
| VARIABLE | ||||||
| I/O & Comms | IN | IN | i/o | |||
| OUT | OUT | |||||
| Other | DODOES | LIT | ||||
| data | ||||||
| - - -u | ||||||
| - -l- | ||||||
| –lu | ||||||
| -d- - | ||||||
| -d-u | ||||||
| -dl- | ||||||
| -dlu | ||||||
| r- - - | ||||||
| r-l- | ||||||
| r-lu | ||||||
| rd- - | ||||||
| rdl- | ||||||
| rdlu | ||||||
| Type | Word | Name | Stack effect | Comments |
|---|---|---|---|---|
| 1 Memory Access | ! | store | ||
| , | comma | |||
| @ | fetch | |||
| ALIGN | ||||
| ALIGNED | ||||
| CELL+ | cell-plus | |||
| CELLS | ||||
| C! | c-store | |||
| C, | c-comma | |||
| C@ | c-fetch | |||
| CALIGN | c-allign | |||
| CALIGNED | c-alligned | |||
| CHAR+ | char-plus | |||
| CHARS | chars | |||
| 2 Arithmetic | + | plus | ||
| * | star | |||
| 2* | two-star | |||
| */MOD | star-slash-mod | |||
| - | minus | |||
| / | slash | |||
| 2/ | two-slash | |||
| MOD | ||||
| 3 Logic | 0= | zero-equals | ||
| < | less-than | |||
| AND | ||||
| INVERT | ||||
| TRUE | ||||
| LSHIFT | l-shift | |||
| = | equals | |||
| > | greater-than | |||
| OR | ||||
| XOR | x-or | |||
| FALSE | ||||
| RSHIFT | r-shift | |||
| 4 Stack | DUP | dupe | ||
| SWAP | ||||
| >R | to-r | |||
| R@ | r-fetch | |||
| DROP | ||||
| OVER | ||||
| R> | r-from | |||
| ROT | rote | |||
| 5 Flow Control | IF | |||
| THEN | ||||
| WHILE | ||||
| REPEAT | ||||
| DO | ||||
| I | ||||
| ’ | tick | |||
| ELSE | ||||
| BEGIN | ||||
| AGAIN | ||||
| UNTIL | ||||
| LOOP | ||||
| J | ||||
| EXECUTE | ||||
| 6 Definitions | : | colon | ||
| CONSTANT | ||||
| CREATE | ||||
| ; | semicolon | |||
| VARIABLE | ||||
| DOES> | does | |||
| 7 Device | KEY | |||
| EMIT | ||||
| KEY? | key-question | |||
| CR | c-r | |||
| 8 Tools | ( | paren | ||
| .S | dot-s | |||
| \ | backslash | |||
| Word | Name | Stack effect | Comments |
|---|---|---|---|
| (lit) | |||
| execute | |||
| (branch) | |||
| (0branch) | |||
| (loop) | |||
| (+loop) | |||
| (do) | |||
| i | |||
| leave | |||
| and | |||
| or | |||
| xor | |||
| « | |||
| » | |||
| ;s | |||
| (does) | |||
| r> | |||
| >r | |||
| r | |||
| 0= | |||
| 0< | |||
| + | |||
| d+ | |||
| minus | |||
| dminus | |||
| over | |||
| drop | |||
| swap | |||
| dup | |||
| @ | |||
| c@ | |||
| ! | |||
| ic! | |||
| vram | |||
| clock | |||
| at | |||
| cls | |||
| .hex | |||
| edit | |||
| list | |||
| trace | |||
| plot | |||
| blk> | |||
| >blk | |||
| >port> | |||
| spi | |||
:dodoes as generalized entry point for all high-level definitions, or Call for primitive-centric implementations. @ and ! to access the memory. >R and R> for the return stack, so anything can be moved. + or 2* for Artihmetik. And NAND as a universal bit instruction. ?BRANCH or 0= for branches. And finally ;S and EXECUTE for execution. Everything else can be defined from these words, even if it then needs temporary variables:: lit' r> @ ; : cell lit' [ 2 , ] ; \ oder 4 oder 8 ... : tmp1 lit' [ here cell+ , 0 , ] ; : dup tmp1 ! tmp1 @ tmp1 @ ; : lit r> dup cell + >r @ ;
: double dup + ; 16 double
vocabulary voc1 vocabulary voc2 voc1 definitions : txt1 ." 1 " ; : txt2 ." 2 " ; voc2 definitions : txt1 ." 3 " ; : txt2 ." 4 " ; forth definitions : txt1 ." 5 " ; : txt2 ." 6 " ; voc1 txt1 voc2 txt1 forth txt1 voc1 txt2 voc2 txt2 forth txt2
float fValue = 1.0; int iValue = (int)fvalue;
: DUPDUP DUP ?ERRORIF NAME>E EXIT THEN DUP ?ERRORIF NAME>E EXIT THEN ;
: FOO " foo.txt" R/O OPEN >R BUF B/BUF R@ READ #BUF ! R> CLOSE ;
OPEN ( addr u -- file-id ) READ ( addr u1 file-id -- u2 ) CLOSE ( file-id -- ) BUF \ buffer address B/BUF \ length of buffer in bytes #BUF \ length of data read from a file
: FOO " foo.txt" R/O OPEN-FILE ?ERROR >R BUF B/BUF R@ READ-FILE ?ERROR #BUF ! R> CLOSE-FILE ?ERROR ; : ?ERROR ( err# -- ) \ handles error ?DUP IF ( print error message or do whatever ) QUIT THEN ;
TRY OPEN ( error handling code ) or ANS standard way: ' OPEN CATCH ( error handling code ) If I want to explicitly handle the error of the whole word FOO, I can use: TRY FOO ( error handling code )
\G Read the 16 bit port x1. CODE P@ ( x1 -- x2 ) \ EXTRA "p-fetch" MOV DX, BX IN AX, DX MOV BX, AX NEXT END-CODE \G Read the 8 bit port x. CODE PC@ ( x -- char ) \ EXTRA "p-c-fetch" MOV DX, BX IN AL, DX $IF386 MOVZX BX, AL $ELSE XOR AH, AH MOV BX, AX $THEN NEXT END-CODE \G Write x1 to 16 bit port x2. CODE P! ( x1 x2 -- ) \ EXTRA "p-store" MOV DX, BX POP AX OUT DX, AX POP BX NEXT END-CODE \G Write char to 8 bit port x. CODE PC! ( char x -- ) \ EXTRA "p-c-store" MOV DX, BX POP AX OUT DX, AL POP BX NEXT END-CODE
: I_dont_now_jet ; variable #I_dont_now_jet ' I_dont_now_jet #I_dont_now_jet ! : bike #I_dont_now_jet @ execute ; : two_bike ." four weels " ; : one_bike ." two weels " ; : one ' one_bike #I_dont_now_jet ! ; : two ' two_bike #I_dont_now_jet ! ; one bike two bike
forth \ use the vocabulary forth, use ORDER to see the vocabulary stack : bicycle ( -- ) \ make a word bicycle, ( -- ) that does not change number of items on the stack 2 wheels ! \ store 2 in the variable wheels ,but gif a error becose it is not defind jet vehicle \ call the word vehicle, but gif a error because it is not defind jet ; so bicycle is not made
variable wheels 5 wheels ! wheels @ . " it works
/ "variable wheels" is a pointer variable wheels : vehicle cr ." my vhicle has " wheels @ . ." wheels " ; : bicycle 2 wheels ! vehicle ; bicycle
' DUP EXECUTE
gets the xt of DUP and executes it. You can't use ' inside a definition. To do that you use”
['] : X ['] DUP EXECUTE ;
. Some Forthers find these words very ugly and annoying. They want Forth to always use the same words”.
: : CREATE ] ;
: ; [ ; IMMEDIATE