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