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 .sThis 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 countdownDemonstrating a loop, this program counts from its argument down to 1.
NovaForth Dictionary
Arithmetic and stack juggling
+ | a b -- c | Addition |
- | a b -- c | Subtraction |
* | a b -- c | Multiplication |
/ | a b -- c | Division (truncates to integer) |
% | a b -- c | Modulus |
pop | a -- | Throw away the top element of the stack |
dup | a -- a a | Duplicate the top element of the stack |
swap | a b -- b a | Swap 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) |
?dup | a -- a a OR 0 -- 0 | Duplicates the top of stack if it's nonzero |
>r | a -- | Pushes the top of the stack to the R stack |
r> | -- a | Pushes the top of the R stack to the stack |
r@ | -- a | Copies the top of the R stack to the stack, leaving the R stack unchanged |
rpick | index -- a | Picks 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) |
lshift | a b -- c | Binary-shifts "a" left "b" bits, shifting in zeroes (prelude word) |
rshift | a b -- c | Binary-shifts "a" right "b" bits, shifting in zeroes (prelude word) |
arshift | a b -- c | Arithmetic right shift: right-shift leaving the high order bit untouched (to preserve sign) (prelude word) |
ror | a -- b | Roll one bit right, moving the low bit to the high bit (prelude word) |
rol | a -- b | Roll one bit left, moving the high bit to the low bit (prelude word) |
over | a b -- a b a | Duplicate the value one below top (prelude word) |
nip | a b -- b | Drop the value one below top (prelude word) |
tuck | a b -- b a b | Duplicate the top value, placing it underneath the one below top (prelude word) |
2dup | a b -- a b a b | Duplicate the top two values (prelude word) |
negate | a -- b | Multiply the top of stack by -1 (prelude word) |
abs | a -- b | Return the absolute value of the top of stack (prelude word) |
I/O
word word | -- addr | Copies word to the pad, leaving its address on the stack |
pad | -- addr | Pushes the address of the pad to the stack |
number str | -- num 1 OR -- 0 | Tries 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" | -- addr | Reads 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 |
emit | ch -- | Emits a byte (as ASCII) to the console |
addr -- | 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 -- c | Returns a 1 if a is greater than b, 0 otherwise (signed comparison) |
< | a b -- c | Returns a 1 if a is less than b, 0 otherwise (signed comparison) |
u> | a b -- c | Returns a 1 if a is greater than b, 0 otherwise (unsigned comparison) (prelude word) |
u< | a b -- c | Returns a 1 if a is less than b, 0 otherwise (unsigned comparison) (prelude word) |
= | a b -- c | Returns a 1 if a is equal to b, 0 otherwise |
& | a b -- c | Bitwise-and of a and b |
| | a b -- c | Bitwise-or of a and b |
^ | a b -- c | Bitwise-xor of a and b |
not | a -- b | If the argument is a 0, returns 1. Otherwise returns 0 |
compare | a b -- c | Compares two strings for equality, returns 1 if they're equal and 0 otherwise |
if / else / then | cond -- | A conditional branch: "condition if truepath else falsepath then". The "else" branch is optional (prelude words) |
begin / until | cond -- | A post-test loop: "until" jumps back to the corresponding "begin" as long as top of stack is 0 (prelude words) |
Memory management
@ | addr -- val | Read the 3-byte word at the given address |
! | val addr -- | Write a 3-byte word to the given address |
c@ | addr -- val | Read one byte from the given address |
c! | val addr -- | Write one byte to the given address |
&heap | -- addr | Pushes the address of the heap pointer |
here | -- addr | Pushes 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) |
allot | val -- addr | Increment the heap by "val" bytes, returning the start address of the allotted region (prelude word) |
free | val -- addr | Decrement the heap by "val" bytes, returning the new heap address (prelude word) |
Assembly and compilation
execute | addr -- | 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 | -- a | Pushes the equivalent opcode to the given instruction mnemonic |
asm | op -- | Compiles an instruction of the given opcode (with no argument) |
#asm | op arg -- | Compiles an instruction of the given opcode with an argument |
>asm | op -- | Compiles an instruction of the given opcode with a blank argument, and stores the argument's address to the R stack |
resolve | addr -- | 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 |
} | -- addr | Ends 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 | -- addr | Compiles 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> | -- addr | Defines the runtime behavior of a defining word (see the NovaForth guide) |
' word | -- addr | Consumes a word, looks it up in the dictionary, and returns its address |
['] | -- addr | Consumes 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