Stack-Oriented Languages: Forth, PostScript, Factor

a side-by-side reference sheet

grammar and invocation | variables and expressions | stack | arithmetic and logic | strings | regexes
dates and time | arrays | heap | dictionaries | functions | execution control | exceptions | file handles | files
directories | processes and environment | libraries and namespaces | reflection | graphics

forth postscript factor
version used
Gforth 0.70 Preview 5.0 0.96
show version
$ gforth --version select About Preview in Preview menu note version when downloading
grammar and invocation
forth postscript factor
$ echo "1 1 + . cr bye" > /tmp/add.forth

$ gforth /tmp/add.forth
none $ factor file
none none #! /usr/bin/env factor
$ gforth none $ factor
save image "/tmp/factor.image" save-image
load image $ factor -i=/tmp/factor.image
are identifiers case sensitive no yes yes
end-of-line comment 1 1 + \ addition 1 1 add % addition 1 1 + ! addition
multiple line comment 1 1 ( comment
another comment )
none none
variables and expressions
forth postscript factor
assignment variable a
3 a !
7 a @ +
/a 3 def
7 currentdict /a get add

3 a set
7 a get +
increment and decrement 7 1+
7 1-
7 ?1+
none null null
null test
none a get null =
undefined variable access raises error
forth postscript factor
stacks data
floating point
graphics state
clipping path
stack underflow
display stack .s
displays float stack:
clear stack clears data stack:
clears data and float stack:
clear clear
count stack depth
copy stack
count copy
(a -- ) drop
displays item being dropped:
operate on float stack:
pop drop
(a -- a a) dup
dup dup
(a b -- b a) swap
exch swap
(a b -- b) nip
exch pop nip
(a b -- a b a) over
1 index over
(a b -- b a b) tuck
dup 3 1 roll USE: shuffle

(a b c -- b c a) rot
3 -1 roll rot
(a b c -- a b c a) 2 pick
2 fpick
2 index pick
(a b c d -- b c d a) 3 roll
3 froll
4 -1 roll USE: shuffle

arithmetic and logic
forth postscript factor
true and false true false
-1 0
true false t f
false 0 false f
logical operators and or invert xor and or not xor and or not xor
relational operators = <> > < >= <=
f= f<> f> f< f>= f<=
eq ne gt lt ge le = none < > >= <=
min and max 1 2 min
1 2 max
1 2 min
1 2 max
three value comparison ! push +lt+ +eq+ and +gt+ on stack:
1 2 <=>
1 1 <=>
2 1 <=>

! pushes +gt+ on stack:
1 2 >=<
float literal must contain an e:
! must contain decimal point or e:
numeric predicates number?
arithmetic operators + - * ?? / mod ??
float stack operators:
f+ f- f* f/ f
add sub mul div idiv mod exp USE: math ! for ^

+ - * / /i mod ^
unary negation negate
neg neg
integer division 7 3 /i
integer division by zero raises division by zero error
float division ! returns a rational:
7 3 /
float division by zero evaluates to: 1/0
power 2e0 32e0 f USE: math.functions

2 32 ^
sqrt 2e0 fsqrt 2 sqrt
sqrt(-2) pushes this non-literal value onto stack:
C{ 0.0 1.414213562373095 }
transcendental functions fexp fln fsin fcos ftan fasin facos fatan fatan2
also flog for base 10 logarithm
sqrt exp ln sin cos none none none none atan
also log for base 10 logarithm
USE: math.functions

exp log sin cos tan asin acos atan ??
! also log10 for base 10 logarithm
transcendental constants pi
1e0 fexp
USE: math.constants

pi e
float truncation return floats
fround ?? floor ??
round truncate floor ceiling USE: math.functions

round truncate floor ceiling
absolute value
and signum
-7 abs
-7e0 fabs
abs -7 abs
-7 sgn
integer overflow modular arithmetic none; converts to arbitrary length integer type
float overflow
float limits USE: math.constants

single-epsilon largest-float smallest-float
rational construction 7/3
7 3 /
rational decomposition 7/3 numerator
7/3 denominator
complex construction USE: math.functions

C{ 1 1.414 }
1 1.414 rect>
complex decomposition
real and imaginary component, argument, absolute value, conjugate
C{ 1 2 } real-part
C{ 1 2 } imaginary-part
C{ 1 2 } arg
C{ 1 2 } abs
C{ 1 2 } conjugate
random number
uniform integer, uniform float, normal float
rand generates random integer from 0 to 231-1:
rand 100 mod
USE: random

100 random
0 1 uniform-random-float
0 1 normal-random-float
random seed
13 srand
bit operators and or xor invert
logical shift by 3:
7 3 lshift
7 3 rshift
arithmetic shift by 1:
7 2*
7 2/
and or xor not
logical shift by 3:
7 3 bitshift
7 -3 bitshift
bitand bitor bitxor bitnot
! arithmetic shift by 3:
7 3 shift
7 -3 shift
binary, octal, and hex literals 0b101010
radix USE: math.parser

42 7 >base
"60" 7 base>
forth postscript factor
string literals allocates memory for string and pushes address and length onto stack:
s\" don't say \"no\""
(don't say "no")
parens and backslashes are escaped with backslashes. Balanced parens do not need to be escaped.
"don't say \"no\""
string escapes \a \b \e \f \n \r \t \v \" \\ \, \ooo \xxx \b \f \n \r \t \\ \( \) \ooo \e \n \r \s \t \\ \" \0 \uxxxxxx
newline in literal no, use \n no, use \n yes
character access (hello) 0 get 0 "hello" nth
length (hello) length "hello" length
concatenate "foo" "bar" append
split USE: splitting

"foo bar baz" " " split
join { "foo" "bar" "baz" } " " join
number to string 7 (12) cvi add
73.9 (.037) cvr add
USE: math.parser

7 "12" string>number +
73.9 ".037" string>number +
17 number>string
17.1 number>string
string to number
case manipulation
sprintf USE: formatting

"Spain" 7 13.1 "%s: %d %f" sprintf
regular expressions
forth postscript factor
literal R/ lorem|ipsum/
R@ /etc/hosts@

! how to create from a string:
"lorem|ipsum" <regexp>
"/etc/hosts" <regexp>
character class abbreviations \d \D \s \S \w \W \p{property} \P{property}
^ $ \A \z \Z \b \B
match test USE: regexp

"It's 1999" R/ 1999/ re-contains?
"It's 1999" "1999" <regexp> re-contains?
case insensitive match test USE: regexp

"Lorem" R/ lorem/i re-contains?
"Lorem" "lorem" "i" <optioned-regexp> re-contains?
i d m s r
substitution USE: regexp

"do re mi mi mi" R/ mi/ "ma" re-replace
group capture
back reference in match and substitution none
dates and time
forth postscript factor
broken-down date and time type timestamp
current date/time \ pushes six values onto stack:
USE: calendar

to unix epoch, from unix epoch USE: calendar

now timestamp>unix-time
1366558586 seconds unix-1970 time+
current unix epoch USE: calendar

date and time to string USE: calendar.format

now timestamp>string
format date
parse date
date subtraction USE: calendar

now unix-1970 time-
add duration USE: calendar

now 100 days time+
date parts USE: calendar

now year>>
now month>>
now day>>
time parts USE: calendar

now hour>>
now minute>>
! second>> returns a ratio:
now second>> truncate
build broken-down date and time USE: calendar

2013 4 21 9 36 15 -7 hours <timestamp>
day of week and day of year USE: calendar

! Sunday is zero:
now day-of-week
now day-of-year
microseconds now second>> dup truncate -
sleep USING: calendar threads ;

10 seconds sleep
500 milliseconds sleep
cpu usage
forth postscript factor
literal [ 1 2 3 ] ! arrays need not be homogeneous
{ 1 2 "foo" }

! creates resizable array:
V{ 1 2 "foo" }
[ 1 2 3 ] length { 1 2 3 } length
empty test
{ 2 3 4 } empty?
[ 1 2 3 ] 0 get 0 { 1 2 3 } nth
update ! sets 2nd element to 3.5:
{ 2 3 4 } dup 3.5 1 rot set-nth
out-of-bounds behavior rangecheck error ! raises error:
9 { 1 2 3 } nth

! returns f:
9 { 1 2 3 } nth?
element index ! returns 1:
"y" { "x" "y" "z" } index
slice ! allocates space for 3rd and 4th element.
2 4 { 1 2 3 4 5 } subseq

! space efficient version:
2 4 { 1 2 3 4 5 } <slice>
slice to end ! all elements at or after specified index:
{ "w" "x" "y" "z" } 1 tail
manipulate back ! puts { 6 7 8 9 } on stack:
{ 6 7 8 } 9 suffix
manipulate front ! add 5 to front:
{ 6 7 8 } 5 prefix

! put { 6 7 8 } and 5 onto stack:
{ 5 6 7 8 } unclip
array concatenate { 1 2 } { 3 4 } append
replicate ! creates array of ten zeros:
10 0 <array>

! creates space efficient sequence of ten zeros:
10 0 <repetition>
array iteration [ 50 100 150 ] { 100 moveto (foo) show } forall { "foo" "bar" "baz" } [ print ] each
indexed iteration { "x" "y" "z" } [ number>string print print ] each-index
iterate over range
instantiate range as array
reverse { 1 2 3 } reverse

! does not allocate new array:
{ 1 2 3 } <reversed>
sort { 1 3 2 4 } [ <=> ] sort
{ 1 3 2 4 } natural-sort
membership 7 { 1 2 3 } member?
relative complement, symmetric difference
map { 1 2 3 } [ dup * ] map
filter { 1 2 3 } [ 2 > ] filter
reduce { 1 2 3 } 0 [ + ] reduce
min and max element
universal and existential tests { 1 2 3 } [ even? ] all?
{ 1 2 3 } [ even? ] any?
sample w/o replacement USE: random

{ 3 7 5 12 19 8 } 3 sample
zip { 1 2 3 } { "x" "y" "z" } [ 2array ] 2map
allocate region on heap pushes address and 0 onto stack:
10 allocate
free region on heap free
resize region on heap
forth postscript factor
dictionary literal << 1 (one) 2 (two) 3 (three) >> ! association list:
{ { 1 "one" } { 2 "two" } { 3 "three" } }

! hashtable:
H{ { 1 "one" } { 2 "two" } { 3 "three" } }
dictionary length << 1 (one) 2 (two) >> length { { 1 "one" } { 2 "two" } } assoc-size
dictionary element access pushes (one) onto stack:
<< 1 (one) 2 (two) >> 1 get
! pushes "one" and t onto stack:
1 { { 1 "one" } { 2 "two" } } at*
element not found behavior undefined error ! pushes f twice onto stack:
4 { { 1 "one" } } at*
set dictionary element /h << 1 (one) 2 (two) >> def
currentdict /h get 3 (three) put

H{ { 1 "one" } { 2 "two" } } h set
"three" 3 h get set-at
range USE: math.ranges

1 100 [a,b]
forth postscript factor
define function : add3 + + ; /add3 { add add } def : add3 ( a1 a2 a3 -- s ) + + ;
invoke function 3 7 5 add3 3 7 5 add3 3 7 5 add3
missing argument behavior a stack underflow error results if the expected number of arguments is not on the stack a stack underflow error results if the expected number of arguments is not on the stack a stack underflow error results if the expected number of arguments is not on the stack
return value
values are returned by pushing them onto the stack values are returned by pushing them onto the stack values are returned by pushing them onto the stack
multiple return values no limit on the number of values a function can leave on the stack no limit on the number of values a function can leave on the stack a function can leave multiple values on the stack, but the change in stack size must match the stack effect declaration
recursive function USE: math-parser

: countdown ( n -- )
  dup 0 > [
    dup print 1 - countdown
  ] [
    drop "go" print
  ] if ;
mutually recursive functions ! there are already definitions for even? and odd?
! in the math vocabulary

DEFER: odd

: even ( n — bool ) dup 0 = [ drop t ] [ 1 - odd ] if ;
: odd ( n — bool ) dup 0 = [ drop f ] [ 1 - even ] if ;
anonymous function { 2 add } [ 2 + ]
invoke anonymous function 3 { 2 add } exec 3 [ 2 + ] call
function as value ! push word "dup" on stack:
\ dup

! execute word on top of stack:
compose functions ! compose quotations:
4 [ 2 * ] [ 3 - ] compose call

! words can be composed if quoted:
: mult2 ( x -- y ) 2 * ;
: sub3 ( x -- y ) 3 - ;
4 [ mult2 ] [ sub3 ] compose call
partial application 3 2 [ * ] curry call
fried quotation USE: fry

! each is same as: [ 2 + ]
2 '[ _ + ]
[ + ] '[ 2 @ ]
2 [ + ] '[ _ @ ]
execution control
forth postscript factor
notes on conditionals conditionals can only be used in word definitions.
endif can be used in place of then
ifelse : ifelse rot if drop else nip then ;
x @ 0 > x @ x @ negate ifelse
x 0 gt { x } { x neg } ifelse x get 0 > x get x get neg ?
if bool
  if true
bool { if true } if bool [ if true ] when
if else bool
  if true
  if false
bool { if true } { if false } ifelse bool [ if true ] [ if false ] if
notes on loops loops can only be used in word definitions.
leave can be used with loop to terminate early
exit terminates innermost for, forall, loop, or repeat
conditional loop begin
  bool { exit } if
} loop
[ bool ] [ code ] while
infinite loop begin
{ code } loop [ code t ] loop
loop 10 times 10 0 ?do code loop 10 { code } repeat 10 [ "foo" print ] times
for loop 10 0 ?do i code loop iterator value on stack
0 20 200 { 72 exch moveto (foo) show } for
for loop step 2 10 0 +do i code 2 +loop
forth postscript factor
notes on exceptions throw raises an exception if the top of the data stack is nonzero. exception puts a nonzero value on the stack. If the exception is not handled the string will be displayed by the interpreter on exit. catch can only be used in a word definition.
raise exception s" bam!" exception throw $error /errorname (foo) put stop "bam!" throw
handle exception ['] risky word catch if handle error then {
  risky code
} stopped { handle error }
[ risky code ] [ handle error ] recover
file handles
forth postscript factor
standard file handles input-stream output-stream ??
read line from stdin input-stream readln
write line to stdout
write to stdout ." hello" cr "hello" write
redirect to file
forth postscript factor
file test, regular file text USE:

"/etc/hosts" exists?
"/etc/hosts" regular-file?
file size USE:

"/etc/hosts" file-info size>>
is file readable, writable, executable USE:

"/etc/hosts" file-readable?
"/etc/hosts" file-writable?
"/etc/hosts" file-executable?
set file permissions
touch file "/tmp/foo" touch-file
copy file, remove file, rename file "/tmp/foo" "/tmp/bar" copy-file
"/tmp/foo" delete-file
"/tmp/bar" "/tmp/foo" move-file
create symlink, symlink test, readlink USE: io.files.links

"/etc/hosts" "/tmp/hosts" make-link
"/tmp/hosts" link-info symbolic-link?
"/tmp/hosts" read-link
generate unused file name USE: io.files.unique

! empty file is created with prefix:
"/tmp/foo" unique-file
forth postscript factor
working directory
get and set
USE: io.directories

current-directory get
"~" set-current-directory
build pathname "/etc" "hosts" append-path
dirname and basename "/etc/hosts" parent-directory
"/etc/hosts" file-name
absolute pathname
make directory USE: io.directories

"/tmp/foo/bar" make-directories
recursive copy
remove empty directory
remove directory and contents
directory test USE:

"/tmp" file-info directory?
processes and environment
forth postscript factor
command line arguments USE: command-line

program name
environment variable
get, set
USE: environment

"HOME" os-env
"/bin" "PATH" set-os-env
user id and name USE: unix.users

exit bye quit USE: system

0 exit
external command USE: io.launcher

! pushes process object on stack:
"ls" run-process
! pushes exit status on stack:
and parent pid
set signal handler
send signal
libraries and namespaces
forth postscript factor
interpret file foo.fs include
s" foo.fs" included
USE: command-line

"/tmp/foo.factor" run-script
load library require foo.fs
s" foo.fs" required
hot patch
load error
main routine in library
library path
library path environment variable
namespace declaration
unqualified import of namespace USE: foo

! import multiple namespaces:
USING: foo bar ;
forth postscript factor
query data type none 3 type USE: classes

3 class-of
pretty print pprint
dump location and stack ~~
show code see word
documentation \ tan help
forth postscript factor
default location of origin lower left corner of page
default scale 72 units per inch
text 72 72 moveto (hello) show
render page and start a new one showpage
set current font /Helvetica 20 selectfont
built-in fonts /Times-Roman /Times-Italic
/Times-Bold /Times-BoldItalic
/Helvetica /Helvetica-Oblique
/Helvetica-Bold /Helvetica-BoldOblique
/Courier /Courier-Bold
/Courier-Oblique /Courier-BoldOblique
closed polygon creates outline of triangle:
72 72 moveto
144 144 lineto
144 72 lineto
set current line width default value is 1:
2 setlinewidth
arc of circle creates half-circular arc centered at (144,144) with radius 40:
144 144 40 90 270 arc
bezier curve control points are (144,144), (288,144), (288,288), and (144,288):
144 144 moveto
288 144 288 288 144 288 curveto
filled polygon creates solid triangle:
72 72 moveto
144 144 lineto
144 72 lineto
set color default color is black. Sets current color to red:
1.0 0.0 0.0 setrgbcolor
translate coordinates move origin 72 units up and to the right:
72 72 translate
scale coordinates increase size of unit 72-fold:
72 72 scale
rotate coordinates rotate coordinates 90 degrees counterclockwise:
90 rotate
items in graphics state currentpoint
save graphics state gsave
restore graphics state grestore
_____________________________________________________________ _____________________________________________________________ _____________________________________________________________

version used

The version used for the examples in this sheet.

show version

How to get the version.

Grammar and Invocation


How to invoke the interpreter.


How to make a source file executable on a UNIX system.


How to invoke the REPL.


The factor REPL is called a listener. There is both a command line and GUI version.

save image

load image

are identifiers case sensitive

Are words case sensitive?

end-of-line comment

The syntax for a comment which ends at the end of the line.

multiple line comment

The syntax for a comment which can span multiple lines.


Paren delimited comments cannot span multiple lines when using the REPL.

Paren delimited comments do not nest.

Variables and Expressions



The following code will get the value for a variable and push it onto the stack:

a get


Arithmetic and Logic



The power operator ^ requires loading the math.functions library.

Factor's division operator / will return a rational if used on integers that don't divide evenly. /f always returns a float when used on integers.


Regular Expressions


The syntax for a regular expression value.


The complete list of parsing words for regular expression values:


In each of the above words, the second character is the character used to terminate the regular expression. The terminating character cannot appear in the regular expression itself, so it is not possible to use a parsing word to create a regular expression with all eleven terminating characters.

Furthermore whitespace must separate the parsing word from the regular expression, so it is not possible to create a regular expression with a parsing word that had leading whitespace.

Regular expressions created from strings do not have these limitations.

character class abbreviations


Upper case character class abbreviations are the complement of the lower case character class abbreviation

\d digit
\s whitespace
\w alphanumeric or underscore
\p{lower} lower case letter
\p{upper} upper case letter
\p{alpha} letter
\p{ascii} in ASCII range
\p{alnum} alphanumeric
\p{punct} punctuation
\p{blank} non-newline whitespace
\p{cntrl} control character
\p{space} whitespace
\p{xdigit} hex digit
\p{Nd} in Unicode category Nd


match test

case insensitive match test



group capture

back reference in match and substitution

Dates and Time

broken-down date and time type

current date/time

to unix epoch, from unix epoch

current unix epoch

date and time to string

format date

parse date

date subtraction

add duration

date parts

time parts

build broken-down date and time

day of week and day of year




cpu usage



Factor provides fixed-length array type which it calls arrays and a resizable array type which it calls vectors.

Factor arrays and vectors are mutable. Furthermore they can contain elements which are a mix of types.

Factor arrays and vectors are both examples of sequences. To be a sequence a Factor type must implement length, nth, and set-nth.


Syntax for an array literal.


How to get the length of an array.

empty test

How to test whether an array is empty.


How to look up the value stored at an index.


There are special words for extracting the first four elements of a sequence:

{ 1 2 3 4 } first
{ 1 2 3 4 } second
{ 1 2 3 4 } third
{ 1 2 3 4 } fourth


How to set the value stored at an index.

out-of-bounds behavior

What happens when an attempt is made to access the value at a non-existent index.


How to convert two sequences into a sequence of pairs.





define function

How to define a function.


invoke function

How to invoke a function.

missing argument behavior

What happens when too few arguments are passed to a function.

It is an error in stack-oriented languages when a function tries to read more values from a stack than are there. Since the stack may have had values in it which were not intended for the function, so in general stack-oriented languages cannot detect when too few arguments are passed to a function.


return value

How to return a value from a function.

multiple return values

recursive function

mutually recursive functions

anonymous function

invoke anonymous function


function as value

How to treat a function as a value.

compose functions

partial application

fried quotation

Execution Control


File Handles



Processes and Environment

command line arguments

program name

environment variable

user id and name


external command



set signal handler

send signal

Libraries and Namespaces




Gforth User Manual
A Beginner's Guide to Forth
Thinking Forth
ANS Forth

The data stack used by Forth procedures to pass operands consists of cells of machine words. These will be interpreted as signed integers, unsigned integers, or memory addresses, depending upon the operator invoked on them. A Forth interpreter does not perform any checks to ensure type safety.

To work with strings and arrays, a Forth programmer must allocate and free space on the heap with the allocate and free commands. Strings are then represented on the data stack with two cells: the address of the string and the length of the string. To make working with these string representations easier, there are operators which manipulate the stack two cells at a time: 2drop, 2dup, 2swap.

Most Forth implementations support floating point numbers. Floats are kept on a separate stack, and many data stack operators have a floating point stack analogue. Floating point operators have an "f" prefix: fdrop, fdup, fswap, f+, f*, f<.


PostScript Language Reference (pdf)
PDF Reference (pdf)

PostScript is a commonly used page description language. It has programming language features one might not expect to find in such a special purpose language such as looping and branching commands, arrays and dictionaries, and even commands which read from standard input and write to standard out.

Like Forth, PostScript is a language with built-in operators that add value to or remove values from an operand stack. Unlike Forth, PostScript keeps track of the type of each value in the operand stack, and it will raise an error if an operator is called on an operand of the wrong type. PostScript also offers string, array, and dictionary data types so that direct access to memory is not needed or even supported.

A PostScript document consists of a sequence of pages, one for each execution of the showpage operator. PostScript provides a selection of operators which paint marks such as letters, shapes, or lines onto the page. The painted marks are collected in a buffer. When a showpage operator is invoked, the marks are rendered on the page and the buffer is cleared. If two marks overlap, the mark which was painted last will be completely visible, and the earlier mark will be partially or completely obscured as if it had been painted over.

The coordinate system used for determining the location of a painting mark places the origin in the lower left corner of the pa by default. The scale is 72 units per inch, with the x coordinate increasing in a rightward direction and the y coordinate increasing in an upward direction. The program may scale, rotate, or translate the coordinate system as pleased as long as the transformation is linear. The size of the page depends on the output device. Although the origin is by default the lower left corner of the physical page, some printers cannot print on the margin of the page; such printers cannot place a mark at or near the origin. The portions of marks which are outside the renderable window of the output device are ignored.

Some of the behavior of the painting operands is governed by the current graphics state. This reduces the number of operands that must be pushed onto the stack when calling a painting operator. The most commonly used parameters in the current graphics state are the current position, path, color, font, line width, coordinate transformation matrix. The gsave and grestore will push the current graphics state onto a stack or pop and restore the top value of the graphics state from the same stack.

PostScript Development


One can test PostScript code by sending it to a printer, but it is better to have an application which can render the PostScript on a screen. Ghostscript is free and runs on Unix and Linux. PSAlter can be purchased for Windows.

Mac OS X includes an application called Preview which renders PDF documents on the screen. It can also be used to render PostScript which it accomplishes by automatically converting the PostScript to PDF. Preview doesn't provide informative error messages. The following PostScript shows how to use the stopped operator to catch an error and display the error name and the command that caused the error:

/showobject { () exch 40 string cvs show } bind readonly def
/showerror {
    /saved_errorname $error /errorname get def
    /saved_command $error /command get def
    /Helvetica 20 selectfont
    72 644 moveto (this error occurred: ) show
    144 572 moveto currentdict /saved_errorname get showobject
    72 504 moveto (operator causing the error: ) show
    144 432 moveto currentdict /saved_command  get showobject
    $error /newerror false put
    showpage } bind readonly def

    /Helvetica-Bold 20 selectfont
    72 576 moveto
    /h << 1 (one) 2 (two) >> def
    currentdict /h get 3 get show showpage

} stopped { showerror } if


Factor Handbook
Vocabulary Index

content of this page licensed under creative commons attribution-sharealike 3.0