µEforth for Linux

Building

Linux builds of µEforth are no longer published as this isn't really ideal for Linux anyway.

Instead build as follows:

sudo apt install ninja-build
git clone https://github.com/flagxor/ueforth
cd ueforth
./configure.py
ninja

http://github.com/flagxor/ueforth - Complete Unprocessed Source Code

µEforth

µEforth Words

Null Terminated Strings

As null terminated strings are used throughout C interfaces, their use is supported in Forth by way of several non-standard words with the convention of using Z/z to refer to such strings in names and stack comments.

Z" ( "string" -- z ) Creates a null terminated string on the heap
Z>S ( z -- a n ) Convert a null terminated string to a counted string
S>Z ( a n -- z ) Conver a counted string string to null terminated (copies string to heap)
Raw Strings

Raw strings are provided better support using a string for the duration of the current command, without consuming heap memory.

R" ( "string" -- a n ) Creates a temporary counted string
R| ( string| -- a n ) Creates a temporary counted string ending with |
Utilities
DUMP ( a n -- ) Dump a memory region
SEE ( "name" -- ) Attempt to decompile a word
VARIABLE ECHO -- Determines if commands are echoed
REMAINING ( -- n ) Bytes remaining in Forth heap.
DUMP-FILE ( data data# fn fn# -- ) Write contents of a file throws on error.
Vocabularies

uEForth uses a hybrid of Forth-79 and Forth-83 style vocabularies. By default vocabularies chain to the vocabulary in which they were defined, as in Forth-79. However, like Forth-83, ALSO can be used to add vocabularies to a vocabulary stack of which CONTEXT @ is the first item. The word ONLY clears the vocabulary stack, but as there is no separate ONLY vocabulary, it also sets CONTEXT to the FORTH vocabulary. The word SEALED modifies the most recently defined vocabulary such that it does not chain. Note, this must be done before words are added to it.

VOCABULARY ( "name" ) Create a vocabulary with the current vocabulary as parent
FORTH ( -- ) Make the FORTH vocabulary the context vocabulary
DEFINITIONS ( -- ) Make the context vocabulary the current vocabulary
VLIST ( -- ) List the words in the context vocabulary (not chains)
WORDS ( -- ) List the words in the context vocabulary (including chains)
TRANSFER ( "name" ) Move a word from its current dictionary to the current vocabulary
                    Useful for "hiding" built-in words
TRANSFER{ ..words.. }TRANSFER ( -- ) Transfer multiple words to the current vocabulary
ALSO ( -- ) Duplicate the vocabulary at the top of the vocabulary stack
PREVIOUS ( -- ) Drop the vocabulary at the top of the vocabulary stack
ONLY ( -- ) Reset context stack to one item, the FORTH dictionary
            Non-standard, as there's no distinct ONLY vocabulary
ORDER ( -- ) Print the vocabulary search order
SEALED ( -- ) Alter the last vocabulary defined so it doesn't chain
Interpret Time Conditions

[IF], [ELSE], and [THEN] can be used to selectively compile. Used in tandem with DEFINED? they can be used to handle the absence of modules gracefully. Nesting is supported.

DEFINED? ( "name" -- xt|0 ) Check if a word exists (works at compile time too).
[IF] ( f -- ) Conditionally interpret the text the follows.
[ELSE] ( -- ) Interpret time ELSE.
[THEN] ( -- ) Interpret time THEN.
Floating-Point

Requires v7.0.6.5+

Single precision floating-point support is available as a work in progress. While initially left out in the name of minimalism, hardware support for floating-point argues some advantages to limited support.

Floating point is kept on a separate stack.

NOTE: Tasks currently don't correctly support floating point. A single floating point stack is shared by all tasks.

FLOAT OPCODES
-------------
DOFLIT ( --- ) Puts a float from the next cell onto float stack.
FP@ ( -- a )
FP! ( a -- )
SF@ ( a -- r ) Single precision load
SF! ( r a -- ) Single precision store
FDUP ( r -- r r )
FNIP ( ra rb -- rb )
FDROP ( r -- )
FOVER ( ra rb -- ra rb ra )
FSWAP ( ra rb -- rb ra )
F0< ( r -- f )
F0= ( r -- f )
F+ ( r r -- r )
F- ( r r -- r )
F* ( r r -- r )
F/ ( r r -- r )
1/F ( r -- r )
S>F ( n -- r )
F>S ( r -- n )

HIGH LEVEL
----------
F= ( r r -- f )
F< ( r r -- f )
F> ( r r -- f )
F<= ( r r -- f )
F>= ( r r -- f )
F<> ( r r -- f )

SFLOAT ( -- 4 )
SFLOATS ( n -- n*4 )
SFLOAT+ ( a -- a+4 )
SF, ( r -- )

AFLITERAL ( r -- )
FLITERAL ( r -- ) IMMEDIATE

FCONSTANT ( r "name" )
FVARIABLE ( "name" )

PI ( -- r )

FSQRT ( r r -- r )

F.S ( -- ) Print float stack.
Locals

Locals allow named word local parameters and values.

Syntax:
  { local1 local2 .. -- comment }
or
  { local1 local2 .. }

Locals are ordered to match the stack, examples:
: 2OVER { a b c d } a b c d a b ;
: MAX { a b -- biggest } a b < IF b ELSE a THEN ;

( Equivalent with DO and FOR )
: POW2 { n } 1 { s } n FOR AFT s 2* to s THEN NEXT s ;
: POW2 { n } 1 { s } n 0 DO s 2* to s LOOP s ;

Capabilities and limitations:

Shell Utilities

Requires v7.0.7.3+ -- ONLY Posix + ESP32

cp ( "src" "dst" -- ) Copy "src" file to "dst".
mv ( "src" "dst" -- ) Rename "src" file to "dst".
rm ( "path" -- ) Remove "path" file.
touch ( "path" -- ) Create "path" file if it doesn't exist.
cat ( "path" -- ) Print contents of "path" file.
ls ( "path" -- ) List files or directories in "path".

Requires v7.0.7.3+ -- ONLY Posix

cd ( "path" -- ) Change director to "path".
mkdir ( "path" -- ) Create directory "path".
rmdir ( "path" -- ) Remove directory "path".
pwd ( -- ) Print current directory.
Visual Editor

Requires v7.0.7.2+

VISUAL EDIT ( "path" --) Enters a visual editor opening file "path".

NOTE: On ESP32 requires connection over an ANSI serial terminal like Putty.

LIMITATIONS: Terminal doesn't know screen dimensions
             and is very redraw inefficient.

Keys:
  Ctrl-S          -- Save now.
  Ctrl-X / Ctrl-Q -- Quit, asking Y/N to save.
  Ctrl-L          -- Redraw the screen.
  Backspace       -- Delete a character backwards.
  Arrow Keys      -- Movement.
  PgUp/PgDn       -- Scroll up/down a page.
Blocks
USE ( "name" -- ) Use "name" as the blockfile, e.g. USE /spiffs/foo
OPEN-BLOCKS ( a n -- ) Open a file as the block file
LOAD ( n -- ) Evaluate a block
THRU ( a b -- ) Load blocks a thru b
LIST ( n -- ) List a block
BLOCK ( n -- a ) Get a 1024 byte block
BUFFER ( n -- a ) Get a 1024 byte block without regard to old contents
UPDATE ( -- ) Mark the last block modified
FLUSH ( -- ) Save and empty all buffers
EMPTY-BUFFERS ( -- ) Empty all buffers
SAVE-BUFFERS ( -- ) Save all buffers
SCR ( -- a ) Pointer to last listed block
Block Editor
These words are available inside the EDITOR vocabulary. Note the block editor places newlines in the 63rd column of each line to make the block file readable in a text editor.
WIPE ( -- ) Blank out the current block
L ( -- ) List the current block
D ( n -- ) Delete a line in the current block
E ( n -- ) Clear a line in the current block
R ( n "text" -- ) Replace a line in the current block
A ( n "text" -- ) Add (insert) a line in the current block
P ( -- ) Move to the previous block
N ( -- ) Move to the next block
Sockets

Requires v7.0.7.2+ for UDP

These words are available inside the sockets vocabulary.
socket ( domain type protocol -- sock/err )
setsockopt ( sock level optname optval optlen -- 0/err )
bind ( sock addr addrlen -- 0/err )
listen ( sock connections -- 0/err )
sockaccept ( sock addr addrlen -- sock/err ) -- varies from bsd socks
connect ( sock addr addrlen -- 0/err )
select ( numfds readfds writefds errfds timeout -- fd/err )
poll ( pollfds n timeout -- fd/err )
send ( sock a n flags -- n/err )
sendto ( sock a n flags addr addrlen -- n/err )
sendmsg ( sock msg flags -- n/err )
recv ( sock a n flags -- n/err )
recvfrom ( sock a n flags addr addrlen -- n/err )
recvmsg ( sock msg flags -- n/err )
gethostbyname ( hostnamez -- hostent/0 )
errno ( -- err ) -- ESP32 only as of v7.0.7.2

sockaddr ( "name" -- ) creates a sockaddr structure
->port@ ( a -- n ) get port from sockaddr
->port! ( n a -- ) set port in sockaddr
->addr@ ( a -- n ) get big-endian address from sockaddr
->addr! ( n a -- ) set big-endian address in sockaddr
ip. ( n -- ) Print address as x.y.z.w IP address.

( Constants )
SOCK_STREAM SOCK_DGRAM SOCK_RAW
AF_INET
sizeof(sockaddr_in)
SOL_SOCKET
SO_REUSEADDR

Dictionary Images and Startup

WARNING: Danger ahead.
Snapshotting the dictionary may not be stable across reinstallations of the C build of Forth.

A collection of non-standard words is provided that allow snapshotting the dictionary and restoring it at startup, with a start word.

SAVE ( "name" -- ) Saves a snapshot of the current dictionary to a file.
RESTORE ( "name" -- ) Restore a snapshot from a file.
REMEMBER ( -- ) Save a snapshot to the default file
                (./myforth or /spiffs/myforth on ESP32).
STARTUP: ( "name" -- ) Save a snapshot to the default file arranging for
                       "name" to be run on startup.
REVIVE ( -- ) Restore the default filename.
RESET ( -- ) Delete the default filename.

Here's an example usage:

: welcome ." Hello!" cr 100 0 do i . loop cr ;
startup: welcome
bye

( Next boot will run a custom startup message )

reset

( Reset removes the custom message )

The INTERNALS vocabulary has some additional words for more control.

SAVE-NAME ( a n -- ) Save a snapshot if the current vocabulary to a file.
RESTORE-NAME ( a n -- ) Restore a snapshot from a file.
'COLD ( -- a ) Address of the word that will be run on startup.
REMEMBER-FILENAME ( -- a n ) Deferred word specifying the platform specific
                             default snapshot filename.
Web Interface
These words are inside the web-interface vocabulary.
server ( port -- ) Start web UI on port (used to implement webui).
HTTP Daemon

Requires v7.0.6+

These words are inside the httpd vocabulary.
server ( port -- ) Start an httpd on port.
handleClient ( -- ) Get next request.
path ( -- a n ) Request path, e.g. /foo
method ( -- a n ) Request method, e.g. GET
header ( a n -- a n ) Contents of header (or empty string).
body ( -- a n ) Rquest body.
Telnet Daemon
These words are inside the web-interface vocabulary.
server ( port -- ) Start telnet daemon on port.

Linux

Linux Opcodes

Linux libraries and the operating system can be accessed via the use of the DLSYM word. Functions can be requested by name from particular modules. As the dynamic linking module is already loaded initially, a 0 for the module allows the library loading function (dlopen) to be loaded from Forth.

DLSYM ( module name-z -- fn )

See posix_main.c.

Native functions all called with CALL(n) (see Windows & Linux Calling below).

Linux Imports

Various Linux calls including Xlib are imported in posix.fs and xlib.fs. In addition, TYPE and KEY are connected to stdin and stdout.

Windows & Linux Calling

As unfortunately both Windows and Linux have system and library calls with as many as 10 parameters (for example XCreateImage), a collection of calling thunks is required. A single varidic thunk would be ideal, but is hard to do without per platform assembly language.

CALL0 ( fn -- n )
CALL1 ( n fn -- n )
CALL2 ( n n fn -- n )
CALL3 ( n n n fn -- n )
CALL4 ( n n n n fn -- n )
CALL5 ( n n n n n fn -- n )
CALL6 ( n n n n n n fn -- n )
CALL7 ( n n n n n n n fn -- n )
CALL7 ( n n n n n n n n fn -- n )
CALL9 ( n n n n n n n n n fn -- n )
CALL10 ( n n n n n n n n n n fn -- n )

See calling.h.