FORTH-ish interpreter
Go to file
David 8065d43efd shut up my syntax highlighter about un-labeled source blocks 2021-02-28 13:22:33 -05:00
examples fix some string bugs and make external-file-loading work 2021-02-26 20:49:10 -05:00
.gitignore initial commit; we have evaluation! 2021-02-13 21:09:56 -05:00
README.md shut up my syntax highlighter about un-labeled source blocks 2021-02-28 13:22:33 -05:00
builtins.go basic command-line library handling 2021-02-26 22:09:43 -05:00
builtins_test.go implement SEE and make comments suck less 2021-02-24 20:19:25 -05:00
eval.go basic command-line library handling 2021-02-26 22:09:43 -05:00
flags.go tests, abstracting output for PRINT and EMIT 2021-02-20 12:09:04 -05:00
go.mod add a nice readline experience (with history!) 2021-02-28 12:30:21 -05:00
go.sum add a nice readline experience (with history!) 2021-02-28 12:30:21 -05:00
main.go add a nice readline experience (with history!) 2021-02-28 12:30:21 -05:00
mem.go fix bug in variable addressing if they weren't immediately written to 2021-02-25 21:13:03 -05:00
mem_test.go initial commit; we have evaluation! 2021-02-13 21:09:56 -05:00
stack.go make IF/ELSE/THEN work! 2021-02-20 15:52:27 -05:00
stack_test.go make IF/ELSE/THEN work! 2021-02-20 15:52:27 -05:00
words.go VARIABLE 2021-02-24 21:27:52 -05:00
words_test.go make IF/ELSE/THEN work! 2021-02-20 15:52:27 -05:00

README.md

Prosper

Prosper is a Forth-like stack-based language. While taking specific influence from Forth, it does not attempt to emulate or implement the ANS Forth standards.

Currently, the language is entirely interactive -- to explore, simply run go run . in the root of this project and an interactive session will begin.

Syntax

Prosper is stack-based, as mentioned, so all the standard stack semantics are present:

> 1 2 3 4 + * -
ok
> .
-13 ok

New words can be defined using : ;:

> : SQUARE DUP * ;
ok
> 10 SQUARE .
100 ok

It has a single loop construct, DO LOOP:

> : TOFIVE 5 0 DO I . LOOP ;
ok
> TOFIVE
0 1 2 3 4 ok

Branches using IF ELSE THEN work:

> : EMOJI 0 < IF 128201 EMIT ELSE 128200 EMIT THEN ;
ok
> 100 EMOJI 
📈 ok
> -100 EMOJI
📉 ok

Here's a Fibonacci implementation:

> : FIB 2DUP + ;
ok
> : FIBN 0 1 ROT 1 DO FIB ROT DROP LOOP SWAP DROP ;
ok
> 10 FIBN .
55 ok

Propser also has a basic off-stack memory model using variables, constants, and pointers:

> VARIABLE FOO
ok
> 10 FOO !
ok
> FOO @
ok
> .
10 ok
> 100 CONSTANT HUNDRED
ok
> HUNDRED HUNDRED * .
10000 ok

And, of course, it knows how to quit:

> BYE
bye

Future Plans

  • Rearchitect how compilation works -- currently, non-built-in words are stored as raw sets of strings, which means in the case of things like IF/ELSE/THEN we have to re-parse the tree and use the IFStack to track the parse status. It'd be better to compile to some intermediate representation so that the compiler can store the JMP locations inline and execution just flows from instruction to instruction instead of re-parsing the entire descent-tree every time.
  • More looping constructs (EXIT, ?DO, and WHILE would be nice).
  • Add ways for Prosper words to hook into the input/output streams (probably required for self-hosting a prosper compiler in prosper, which is a long way off).