Beginner

Operators in Forth

Learn arithmetic, comparison, logical, and stack-manipulation operators in Forth using reverse Polish notation on the data stack

In most programming languages, an expression like (2 + 3) * 4 is parsed by the compiler with carefully defined precedence and associativity rules. Forth takes an entirely different approach: there are no operators in the conventional sense at all. Every “operator” is just another word that consumes values from the data stack and pushes its result back. Because evaluation is strictly left-to-right and operands appear before the word that uses them, Forth has no operator precedence to memorize — the order you write things is the order they happen.

This tutorial covers the categories of operators you will use most often: arithmetic (+, -, *, /, MOD), stack manipulation (DUP, SWAP, OVER, DROP, ROT), comparison (=, <>, <, >), and bitwise/logical (AND, OR, INVERT). All of them follow the same model — they are words, and they communicate through the stack.

A note on notation: Forth uses postfix (reverse Polish) form. Instead of 2 + 3, you write 2 3 +. The numbers are pushed onto the stack first, and then + pops the top two values, adds them, and pushes the result. Once this clicks, complex expressions become a simple sequence of stack transformations.

Arithmetic Operators

Forth’s arithmetic words consume operands from the stack and leave the result on the stack. Use . (dot) to pop and print a number.

Create a file named operators.fth:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
\ Arithmetic operators
." 2 + 3 = " 2 3 + . CR
." 10 - 4 = " 10 4 - . CR
." 6 * 7 = " 6 7 * . CR
." 20 / 3 = " 20 3 / . CR
." 20 MOD 3 = " 20 3 MOD . CR

\ /MOD returns both quotient and remainder
\ Stack effect: ( n1 n2 -- rem quot )
." 20 /MOD 3 -> " 20 3 /MOD . . CR

\ Negation and absolute value
." NEGATE 5 = " 5 NEGATE . CR
." ABS -7 = " -7 ABS . CR

\ Stack manipulation words
." DUP of 4: " 4 DUP . . CR
." SWAP 1 2: " 1 2 SWAP . . CR
." OVER 1 2: " 1 2 OVER . . . CR

\ Comparison operators (-1 = true, 0 = false)
." 3 = 3 -> " 3 3 = . CR
." 3 < 5 -> " 3 5 < . CR
." 5 > 3 -> " 5 3 > . CR

\ Bitwise / logical operators
." -1 AND 0 -> " -1 0 AND . CR
." -1 OR  0 -> " -1 0 OR . CR
." INVERT 0 -> " 0 INVERT . CR

\ No precedence: (2+3)*4 is just left-to-right
." (2+3)*4 = " 2 3 + 4 * . CR

bye

How each line works

  • 2 3 + pushes 2, pushes 3, then + pops both and pushes 5.
  • 20 3 / performs integer division. Gforth follows symmetric/floored semantics for positive operands, so the result is 6.
  • 20 3 MOD leaves the remainder, 2, on the stack.
  • 20 3 /MOD is a combined word with stack effect ( n1 n2 -- rem quot ). It is more efficient than doing / and MOD separately because the underlying CPU produces both in a single divide.
  • NEGATE and ABS are unary — they consume one value and produce one.

Stack Manipulation as “Operators”

In Forth, moving values around on the stack is just as fundamental as arithmetic. These words have no analogue in infix languages because variables and parentheses normally hide the question of where values live.

The most important stack words and their effects:

WordStack effectDescription
DUP( a -- a a )Duplicate the top item
DROP( a -- )Discard the top item
SWAP( a b -- b a )Exchange the top two items
OVER( a b -- a b a )Copy the second item to the top
ROT( a b c -- b c a )Rotate the third item to the top

These are how you “name” operands without using variables. For example, to compute x² + 1 without storing x in a variable, you duplicate it:

1
2
\ ( x -- x²+1 )
DUP * 1 +

Comparison Returns a Flag

Comparison words like =, <>, <, >, <=, >= consume two values and push a flag: -1 (all bits set) for true and 0 for false. This is the same convention used by AND, OR, and INVERT, which means logical and bitwise operations are unified — there is no separate boolean type.

1
2
3
4
3 3 =          \ -1 (true)
3 5 <          \ -1 (true)
-1 0 AND       \ 0  (false)
-1 INVERT      \ 0

Because -1 is all bits set in two’s complement, bitwise AND/OR/INVERT work correctly as logical operators on these flags.

No Operator Precedence

In most languages, 2 + 3 * 4 evaluates to 14 because * binds tighter than +. In Forth, you choose the order by writing words in that order:

1
2
2 3 + 4 *      \ (2+3)*4  = 20
3 4 * 2 +      \ 2+(3*4)  = 14

Parentheses are not needed because the stack itself records the partial results. Many Forth programmers consider this the language’s biggest readability win once they adjust: what you see is exactly what happens, step by step.

Running with Docker

1
2
3
4
5
# Pull the Gforth image
docker pull forthy42/gforth:latest

# Run the operators example
docker run --rm -v $(pwd):/app -w /app forthy42/gforth:latest gforth operators.fth -e bye

Expected Output

2 + 3 = 5 
10 - 4 = 6 
6 * 7 = 42 
20 / 3 = 6 
20 MOD 3 = 2 
20 /MOD 3 -> 6 2 
NEGATE 5 = -5 
ABS -7 = 7 
DUP of 4: 4 4 
SWAP 1 2: 1 2 
OVER 1 2: 1 2 1 
3 = 3 -> -1 
3 < 5 -> -1 
5 > 3 -> -1 
-1 AND 0 -> 0 
-1 OR  0 -> -1 
INVERT 0 -> -1 
(2+3)*4 = 20 

Note: Gforth’s . always prints a trailing space after a number. The /MOD line shows 6 2 because the quotient was on top of the stack — the first . pops and prints it, then the second . prints the remainder underneath.

Key Concepts

  • Operators are words. +, *, =, and DUP are all just words that operate on the data stack — there is no special operator syntax.
  • Postfix is precedence-free. The order you write words is the order they execute. Parentheses are never needed for arithmetic.
  • Stack effect comments matter. Notation like ( a b -- b a ) documents what a word consumes and produces. Reading and writing these is essential Forth literacy.
  • Booleans are integers. True is -1 (all bits set), false is 0. This lets AND, OR, INVERT serve as both bitwise and logical operators.
  • /MOD is faster than / and MOD separately. Combined words exist because the underlying machine often produces both results in one operation.
  • Stack manipulation replaces variables. DUP, SWAP, OVER, and ROT are the way you reuse and rearrange values without binding them to names.
  • Whitespace separates words. 2 3+ is an error or a strange identifier — every word, including operators, must be surrounded by spaces.

Running Today

All examples can be run using Docker:

docker pull forthy42/gforth:latest
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining