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.