Forth expressions

7th November 2024

This is a library that adds balanced expressions to Forth.

DECIMAL

CREATE BRACES
   HERE ,
   64 CELLS ALLOT

: >BRACES ( depth -- )
   1 CELLS BRACES +!
   BRACES @ ! ;

: BRACES> ( -- old-depth )
   BRACES @ @
   -1 CELLS BRACES +! ;

: { ( -- )
   DEPTH >BRACES ;

: } ( -- )
   DEPTH  BRACES> 1+  <> ABORT" Unbalanced expression" ;: } ( -- )
   DEPTH  BRACES> 1+  <>
   ABORT" Unbalanced braces" ;

Now { and } let us check the stack is balanced.

This is especially typical for maths, but can be used in any situation where we expect the stack to produce one result.

.( Example: )
   { 1 2 + } .
   { 5 { 1 2 + } * } .  CR

.( Failure: )
   { 1 2 3 + } .  CR

Output:

Example: 3 15
Failure: Unbalanced expressionFailure: Unbalanced braces

Cost

This adds a runtime cost where it’s used.

We can do a ‘release’ build without the checks, though:

: { ( -- )
   ;  IMMEDIATE

: } ( -- )
   ;  IMMEDIATE

So we have the power of a statically-checked feature, without any of the normal complexity for that, which I think is a fair tradeoff for doing two kinds of builds.

Cleaning up

We should really provide a way to reset the stack.

: RESET-BRACES ( -- )
   BRACES BRACES ! ;

And we should do it automatically on certain words, this is a dumb and done way to do it:

: QUIT
   RESET-BRACES QUIT ;

: ABORT
   RESET-BRACES ABORT ;

: ?RESET-BRACES
   DUP IF  RESET-BRACES  THEN ;

: THROW
   ?RESET-BRACES THROW ;

: ABORT"
   POSTPONE ?RESET-BRACES
   POSTPONE ABORT" ;  IMMEDIATE

Overflow/underflow

We should also check for overflow/underflow.

: >BRACES ( depth -- )
   BRACES @  BRACES 64 CELLS +  = ABORT" Brace stack overflow"
   >BRACES ;

: BRACES> ( -- old-depth )
   BRACES @  BRACES  = ABORT" Brace stack underflow"
   BRACES> ;
: >BRACES ( depth -- )
   BRACES @  BRACES 64 CELLS +
   = ABORT" Brace overflow"
   >BRACES ;

: BRACES> ( -- old-depth )
   BRACES @  BRACES
   = ABORT" Brace underflow"
   BRACES> ;

This wraps the existing words with checks.

Licence

I license the code on this page under the MIT or CC0 licence, at your discretion.


Copyright © 2024 Chris Leonard