Minimalistic Forth-like virtual machine

Hi, there!

I’ve written semi-toy virtual stack machine (a pipe dream has come true :upside_down_face:). To be honest I did not write it from a clean sheet of paper - I used these lessons as a “cheat sheet”.

No, I’m not Forth programmer (Lord forbid :slight_smile: ), but I think that

  • Forth is a gem, without any doubt
  • implementing something Forth-like is a good way to learn some other language.

About the implementation itself: of course, it is not a fully-blown one:

$ zig-out/bin/zf 
zf> .dict
bye . cr .dict .dstk .rstk .cstk .code dup drop
+ - * / mod = <> > < 0= 0<> 0> 0< max min : ;
if else then do i loop ( 
zf> 
zf> 1 2 3 
zf> .dstk
dstk[3] = 0x0000000000000003 <- top
dstk[2] = 0x0000000000000002
dstk[1] = 0x0000000000000001
zf> 

But even with this minimalistic set of predefined words we can do something kinda useful:

zf> : τετραγωνίζω dup * . ;
zf> 7 τετραγωνίζω cr
49 
zf> 

Greek word “τετραγωνίζω” (tetragonizo) means “to square”.

More complicated example:

zf> : divisable-by-three 3 mod 0= ;
zf> : test do i dup divisable-by-three if . else drop then loop cr ;
zf> 30 1 test
3 6 9 12 15 18 21 24 27 

That’s it.

4 Likes

Woah, nice! I’m super into this. I don’t have anything insightful to add, but I’ve bookmarked your project to dive into later. Looks really cool!

@ratfactor thanks for positive response!

added data segment and variables:

zf> : var create 1 allot ;
zf> : km 1000 * ;
zf> : hour 3600 * ;
zf> var distance
zf> var time
zf> var speed
zf> 100 km distance !
zf> 1 hour time !
zf> distance @ time @ / speed !
zf> .data
data[0] = 0x00000000000186a0 ('distance')
data[1] = 0x0000000000000e10 ('time')
data[2] = 0x000000000000001b ('speed')
zf> : take-and-print @ . cr ;
zf> speed take-and-print
27 

got speed in [m/s].