NovaForth Console

This is a REPL for NovaForth, using the Vulcan imaginary CPU. You can type lines of Forth code and have them evaluated, and see the results.

For a full introduction to NovaForth, read this sample chapter from the upcoming Vulcan book. A short tutorial is below:

Tutorial and examples:

Forth programs are a series of "words" separated by whitespace. NovaForth evaluates words line-by-line, and a full dictionary of available words is listed below. Here are some example programs:

5 3 + .
This program pushes the numbers "5" and "3" to the stack, then adds the top two numbers on the stack, and finally pops the top number from the stack (now "8") and prints it.

." Hello, world!"
This program prints a standard greeting.

: square dup * ;
4 square .
This defines a new word, "square", which multiplies the top value on the stack by itself. The second line then calls that word on the number "4" and prints the result.

: collatz
  dup 2 % if
    3 * 1 +
  else
    2 /
  then ;

4 collatz 5 collatz .s
This defines a word "collatz" which showcases conditionals: if the number given to it is odd, it returns triple that number plus one; if it's even, it returns half that number. The ".s" word prints the stack without modifying it and is a useful debugging tool.

: countdown begin dup . ." ... " 1 - dup not until pop ;
10 countdown
Demonstrating a loop, this program counts from its argument down to 1.

NovaForth Dictionary

Arithmetic and stack juggling

+a b -- cAddition
-a b -- cSubtraction
*a b -- cMultiplication
/a b -- cDivision (truncates to integer)
%a b -- cModulus
popa --Throw away the top element of the stack
dupa -- a aDuplicate the top element of the stack
swapa b -- b aSwap the top two elements of the stack
pick * index -- * el Copy an element from deep in the stack to the top. "0 pick" is equivalent to dup, "1 pick" pushes the value one below the top, and so on
rot a b c -- b c a Rotate the top three elements on the stack
-rot a b c -- c a b Rotate the top three elements on the stack the other direction (prelude word)
?dupa -- a a OR 0 -- 0Duplicates the top of stack if it's nonzero
>ra --Pushes the top of the stack to the R stack
r>-- aPushes the top of the R stack to the stack
r@-- aCopies the top of the R stack to the stack, leaving the R stack unchanged
rpickindex -- aPicks a value from deep in the R stack, much like "pick" does with the data stack
rdrop--Drop the top value from the R stack (prelude word)
lshifta b -- cBinary-shifts "a" left "b" bits, shifting in zeroes (prelude word)
rshifta b -- cBinary-shifts "a" right "b" bits, shifting in zeroes (prelude word)
arshifta b -- cArithmetic right shift: right-shift leaving the high order bit untouched (to preserve sign) (prelude word)
rora -- bRoll one bit right, moving the low bit to the high bit (prelude word)
rola -- bRoll one bit left, moving the high bit to the low bit (prelude word)
overa b -- a b aDuplicate the value one below top (prelude word)
nipa b -- bDrop the value one below top (prelude word)
tucka b -- b a bDuplicate the top value, placing it underneath the one below top (prelude word)
2dupa b -- a b a bDuplicate the top two values (prelude word)
negatea -- bMultiply the top of stack by -1 (prelude word)
absa -- bReturn the absolute value of the top of stack (prelude word)

I/O

word word-- addrCopies word to the pad, leaving its address on the stack
pad-- addrPushes the address of the pad to the stack
number str-- num 1 OR -- 0Tries to parse the given word as a number, pushes the number followed by 1 if it's parseable and 0 if it's not
hex--Switches all I/O to hexadecimal mode
dec--Switches all I/O to base-10 mode (the default)
.a --Prints the number on the top of the stack
s"-- addrReads a string until a double-quote, copies them to the heap, and returns the address of the string
."--Reads a string until a double-quote and prints it
emitch --Emits a byte (as ASCII) to the console
printaddr --Prints a null-terminated string to the console
.s--Prints the stack contents as a debugging aid
space--Prints a space (prelude word)
cr--Prints a newline (10 followed by 13, carriage return and line feed) (prelude word)

Logic and control structures

>a b -- cReturns a 1 if a is greater than b, 0 otherwise (signed comparison)
<a b -- cReturns a 1 if a is less than b, 0 otherwise (signed comparison)
u>a b -- cReturns a 1 if a is greater than b, 0 otherwise (unsigned comparison) (prelude word)
u<a b -- cReturns a 1 if a is less than b, 0 otherwise (unsigned comparison) (prelude word)
=a b -- cReturns a 1 if a is equal to b, 0 otherwise
&a b -- cBitwise-and of a and b
|a b -- cBitwise-or of a and b
^a b -- cBitwise-xor of a and b
nota -- bIf the argument is a 0, returns 1. Otherwise returns 0
comparea b -- cCompares two strings for equality, returns 1 if they're equal and 0 otherwise
if / else / thencond --A conditional branch: "condition if truepath else falsepath then". The "else" branch is optional (prelude words)
begin / untilcond --A post-test loop: "until" jumps back to the corresponding "begin" as long as top of stack is 0 (prelude words)

Memory management

@addr -- valRead the 3-byte word at the given address
!val addr --Write a 3-byte word to the given address
c@addr -- valRead one byte from the given address
c!val addr --Write one byte to the given address
&heap-- addrPushes the address of the heap pointer
here-- addrPushes the current value of the heap pointer (equivalent to "&heap @")
variable name--Creates a variable of the given name, which pushes its address when called (prelude word)
+!val addr --Increments the 3-byte word at "addr" by "val" (prelude word)
c+!val addr --Increments the byte at "addr" by "val" (prelude word)
allotval -- addrIncrement the heap by "val" bytes, returning the start address of the allotted region (prelude word)
freeval -- addrDecrement the heap by "val" bytes, returning the new heap address (prelude word)

Assembly and compilation

executeaddr --Calls the given address
[--Enters interpret mode
]--Enters compile mode
,a --Compiles a number to the heap
:--Begins definition of a new word: calls create and enters compile mode
;--Ends a word definition: compiles a return instruction and leaves compile mode
$ mnemonic-- aPushes the equivalent opcode to the given instruction mnemonic
asmop --Compiles an instruction of the given opcode (with no argument)
#asmop arg --Compiles an instruction of the given opcode with an argument
>asmop --Compiles an instruction of the given opcode with a blank argument, and stores the argument's address to the R stack
resolveaddr --Writes the top of the stack to the address on top of the R stack (used to resolve a blank argument left by >asm)
{--Begins an anonymous function
}-- addrEnds an anonymous function and leaves its address on the stack
exit--Early return from a word definition
continue word--Jumps to the given word as a tail call (replacing the current stack frame)
postpone word--Delays execution of the given word: compiles a call to a compile-mode word or compiles instructions to compile a call to an interpret-mode word (see the NovaForth guide)
literal-- addrCompiles an instruction to push the number at the top of the stack

Dictionary manipulation

create name--Creates a dictionary entry for a given word (pointing to the heap)
immediate--Moves the most recently defined word from the interpret dictionary to the compile dictionary
does>-- addrDefines the runtime behavior of a defining word (see the NovaForth guide)
' word-- addrConsumes a word, looks it up in the dictionary, and returns its address
[']-- addrConsumes a word at runtime, looks it up in the dictionary, and returns its address

Miscellaneous

\--Begins a comment that lasts to the end of the line
(--Begins a comment that lasts to the matching close paren

Prelude

These definitions are run when the console is loaded:


        

This early-access demo was created by Ross Andrews in January 2023