The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Language::Eforth - a tiny embedded Forth interpreter

SYNOPSIS

  use Language::Eforth;
  my $f = Language::Eforth->new;

  $f->eval("2 2 + .s\n");
  print scalar $f->pop, "\n";

  $f->push(3, 7);
  print "depth: ", $f->depth, "\n";

  $f->eval("+\n");
  print scalar $f->pop, "\n";

  $f->reset;

  # there are, however, better ways to reverse a list of small
  # integers than this
  $f->eval("1 2 3 4\n");
  my @reverse = $f->drain;  # qw(4 3 2 1)

DESCRIPTION

This module embeds a tiny embeddable Forth interpreter.

https://github.com/howerj/embed

The interpreter has a 16-bit cell size, does not support floating point values, AND CONTRARY TO THE ans fORTH SPECIFICATION REQUIRES LOWER-CASE WORDS. Consult embed.fth for details on various "Error Codes" and other documentation.

Memory usage while not zero should not be very significant; it mostly depends on the EMBED_CORE_SIZE count of 16-bit cells allocated. And whatever Perl needs. Assertion failures are also possible, unless the compile was somehow done with -DNDEBUG.

METHODS

These may croak should something be awry with the input, or if memory allocation fails in the constructor.

depth

Returns the data stack depth as an unsigned integer.

drain

Utility method to drain the data stack of all values as unsigned integers, or returns the empty list otherwise. See also reset.

Since version 0.02.

eval expr

Evaluates the string expr. expr MUST end with a newline. Output from words such as .s or . or u. is sent to standard output; use Capture::Tiny or similar to redirect this, if need be.

Input could be specified in a heredoc (see eg/shape for an example) or could be loaded into a string via a module like File::Slurper.

No return value.

new

Constructor. Returns a pointer to the interpreter used by the other methods.

pop

Pops an unsigned integer off of the data stack. In list context this returns the value and the return code. If the code is non-zero something went awry, probably a stack under- or overflow.

  my ( $value, $failed ) = $f->pop;
  if ( $failed ) { die "pop failed ($failed)\n" }

Otherwise, use the return value in scalar context, but then there is a semipredicate problem where 0 could mean the value zero, or that there was a failure:

  my $v;
  $f->reset;              # empty the stack
  $f->eval("2 2 xor\n");  # calculate a value
  $v = scalar $f->pop;    # 0, the value
  $v = scalar $f->pop;    # 0, the semipredicate (underflow)

The value can be made 16-bit signed via:

  $f->push(54321);
  my $x = $f->pop;
  my $y = Language::Eforth::signed($x);
  say "$y $x";            # -11215 54321

See also drain.

push integer [ integer .. ]

Pushes integers onto the data stack. Values will be modulated to the 16-bit cell size:

  $f->push(-1); 
  $f->eval("u.\n");       # 65535

Returns the number of items pushed and the return code of the last item pushed. The count may be fewer than the number of items supplied; if so, the return code is likely some non-zero value.

  my ( $count, $status ) = $f->push(@long_list);
  if ( $count != @long_list ) { die "get a bigger box\n"; }

Note that embed_push uses a cell_t or uint16_t so the integer goes through both Perl's SvUV and then C's uint16_t. How the forth treats the bit patterns in the stack depends on the word involved, e.g. . verses u..

  $f->push(-1); 
  $f->eval(" dup .  dup u. \n");

Since version 0.02 push accepts multiple values.

reset

Resets the state of the interpreter. Among other things this will clear the data stack. See also drain.

No return value.

FUNCTIONS

These utility functions are not exported.

signed value

The pop and drain methods tend to return unsigned short values (uint16_t); such values may need conversion on the Perl side to be signed (int16_t) for display or debugging needs. This function runs the given value through an signed short conversion and returns the result, after the fashion of Procrustes with his guests.

Since version 0.02.

unsigned value

Ensures that value falls within the uint16_t range. This will probably happen automatically for values passed to push as embed_push expects a uint16_t argument.

Since version 0.02.

SEE ALSO

https://github.com/howerj/embed

"Starting FORTH". Leo Brodie. 1981.

COPYRIGHT & LICENSE

Copyright 2022 Jeremy Mates, All Rights Reserved.

This program is distributed under the (Revised) BSD License.