Find a file
Koichi Nakamura a78b646597 Update readme
2021-01-12 12:07:12 +09:00
.github/workflows Fix wiki format 2021-01-11 18:04:05 +09:00
benchmark Add benchmark/matmul.fs 2021-01-11 21:03:56 +09:00
example Update README and example 2021-01-10 01:14:42 +09:00
others Fixed misuse of stringify 2021-01-11 18:48:49 +09:00
test Add report-and-exit 2021-01-11 14:33:11 +09:00
.gitignore Add .gitignore 2020-12-28 22:11:45 +09:00
bootstrap.fs Fixed a bug 2021-01-12 11:41:25 +09:00
LICENSE fix copyright year 2021-01-02 13:29:46 +09:00
Makefile fix makefile target name 2021-01-11 15:37:09 +09:00
planck.xxd fix typo 2021-01-11 18:33:28 +09:00
README.md Update readme 2021-01-12 12:07:12 +09:00
runtests.fs Add report-and-exit 2021-01-11 14:33:11 +09:00

PlanckForth: Bootstrapping Forth from Handwritten ELF Binary

This project aims to bootstrap a Forth interpreter from hand-written tiny ELF binary. This is just for fun. No practical use.

How to build

Only xxd is needed to build PlanckForth.

$ git clone https://github.com/nineties/planckforth.git
$ cd planckforth
$ make
xxd -r -c 8 planck.xxd > planck
chmod +x planck

Implementations in other languages are in others.

Hello World

The hello world program at the beginning looks like this.

$ ./planck
kHtketkltkltkotk tkWtkotkrtkltkdtk!tk:k0-tQ

After bootstrapping by bootstrap.fs, it looks like this.

$ ./planck < bootstrap.fs
." Hello World!" cr

bootstrap.fs can also takes a file as an input program like this.

$ cat example/fib.fs
: fib dup 2 < unless 1- dup recurse swap 1- recurse + then ;
20 fib . cr
$ ./planck < bootstrap.fs example/fib.fs
6765

Running Tests

$ ./planck < bootstrap.fs runtests.fs

Builtin Words

code name stack effect semantics
Q quit ( n -- ) Exit the process
C cell ( -- n ) The size of Cells
h &here ( -- a-addr ) The address of 'here' cell
l &latest ( -- a-addr ) The address of 'latest' cell
k key ( -- c ) Read character
t type ( c -- ) Print character
j jump ( -- ) Unconditional branch
J 0jump ( n -- ) Jump if a == 0
f find ( c -- xt ) Get execution token of c
x execute ( xt -- ... ) Run the execution token
@ fetch ( a-addr -- w ) Load value from addr
! store ( w a-addr -- ) Store value to addr
? cfetch ( c-addr -- c ) Load byte from addr with sign extension
$ cstore ( c c-addr -- ) Store byte to addr
d dfetch ( -- a-addr ) Get data stack pointer
D dstore ( a-addr -- ) Set data stack pointer
r rfetch ( -- a-addr ) Get return stack pointer
R rstore ( a-addr -- ) Set return stack pointer
i docol ( -- a-addr ) Get the code pointer of interpreter
e exit ( -- ) Exit current function
L lit ( -- n ) Load immediate
S litstring ( -- c-addr ) Load string literal
+ add ( a b -- c ) c = (a + b)
- sub ( a b -- c ) c = (a - b)
* mul ( a b -- c ) c = (a * b)
/ divmod ( a b -- c d ) c = (a mod b), d = (a / b)
& and ( a b -- c ) c = (a & b)
| or ( a b -- c ) c = (a | b)
^ xor ( a b -- c ) c = (a ^ b)
< less ( a b -- c ) c = (a < b)
u uless ( a b -- c ) c = (a unsigned< b)
= equal ( a b -- c ) c = (a == b)
{ shl ( a b -- c ) c = a << b (logical)
} shr ( a b -- c ) c = a >> b (logical)
) sar ( a b -- c ) c = a >> b (arithmetic)
v argv ( -- a-addr u ) argv and argc
V version ( -- c-addr ) Runtime infomation string

Implementations

Implementation of runtime build test status
Handwritten ELF binary for i386-linux make i386-linux-handwritten
C make c C
Python 3.x make python python

Benchmarks

See Wiki/Benchmarks