Forth and PostScript

a side-by-side reference sheet

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

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

$ gforth /tmp/add.forth
none
shebang
 
none none
repl
 
$ gforth none
save image
load image
are identifiers case sensitive no yes
end-of-line comment 1 1 + \ addition 1 1 add % addition
multiple line comment 1 1 ( comment
another comment )
+
none
variables and expressions
forth postscript
assignment variable a
3 a !
7 a @ +
/a 3 def
7 currentdict /a get add
increment and decrement 7 1+
7 1-
null
 
none null
null test
 
none
undefined variable access
stack
forth postscript
stacks data
floating point
return
locals
operand
dictionary
execution
graphics state
clipping path
stack underflow
display stack .s
displays float stack:
f.s
none
clear stack clears data stack:
clearstack
clears data and float stack:
clearstacks
clear
count stack depth
fdepth
count
copy stack
 
count copy
(a -- ) drop
displays item being dropped:
.
operate on float stack:
fdrop
f.
pop
(a -- a a) dup
fdup
dup
(a b -- b a) swap
fswap
exch
(a b -- b) nip
fnip
exch pop
(a b -- a b a) over
fover
1 index
(a b -- b a b) tuck
ftuck
dup 3 1 roll
(a b c -- b c a) rot
frot
3 -1 roll
(a b c -- a b c a) 2 pick
2 fpick
2 index
(a b c d -- b c d a) 3 roll
3 froll
4 -1 roll
arithmetic and logic
forth postscript
true and false true false
-1 0
true false
falsehoods
 
false 0 false
logical operators and or invert xor and or not xor
relational operators = <> > < >= <=
f= f<> f> f< f>= f<=
eq ne gt lt ge le
min and max 1 2 min
1 2 max
three value comparison
float literal must contain an e:
3.14e0
3.14
3.14e0
numeric predicates
arithmetic operators + - * ?? / mod ??
float stack operators:
f+ f- f* f/ f
add sub mul div idiv mod exp
unary negation negate
fnegate
neg
integer division
integer division by zero
float division
float division by zero
power 2e0 32e0 f
sqrt 2e0 fsqrt
sqrt(-2) pushes this non-literal value onto stack:
-na
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
transcendental constants pi
1e0 fexp
float truncation return floats
fround ?? floor ??
round truncate floor ceiling
absolute value
and signum
-7 abs
-7e0 fabs
abs
integer overflow modular arithmetic
float overflow
 
float limits
rational construction
rational decomposition
complex construction
complex decomposition
real and imaginary component, argument, absolute value, conjugate
random number
uniform integer, uniform float, normal float
rand generates random integer from 0 to 231-1:
rand 100 mod
none
none
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
binary, octal, and hex literals
radix
strings
forth postscript
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.
string escapes \a \b \e \f \n \r \t \v \" \\ \, \ooo \xxx \b \f \n \r \t \\ \( \) \ooo
newline in literal no, use \n no, use \n
character access (hello) 0 get
length (hello) length
concatenate
split
join
trim
pad
number to string 7 (12) cvi add
73.9 (.037) cvr add
string to number
case manipulation
sprintf
dates and time
forth postscript
broken-down date and time type
current date/time \ pushes six values onto stack:
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
microseconds
sleep
timeout
cpu usage
arrays
forth postscript
literal [ 1 2 3 ]
size
 
[ 1 2 3 ] length
empty test
 
lookup
 
[ 1 2 3 ] 0 get
update
out-of-bounds behavior rangecheck error
element index
slice
slice to end
manipulate back
manipulate front
array concatenate
replicate
copy
array iteration [ 50 100 150 ] { 100 moveto (foo) show } forall
indexed iteration
iterate over range
instantiate range as array
reverse
sort
dedupe
membership
intersection
union
relative complement, symmetric difference
map
filter
reduce
min and max element
universal and existential tests
sample w/o replacement
zip
heap
allocate region on heap pushes address and 0 onto stack:
10 allocate
free region on heap free
resize region on heap
write
read
dictionaries
forth postscript
dictionary literal << 1 (one) 2 (two) 3 (three) >>
dictionary length << 1 (one) 2 (two) >> length
dictionary element access pushes (one) onto stack:
<< 1 (one) 2 (two) >> 1 get
element not found behavior undefined error
set dictionary element /h << 1 (one) 2 (two) >> def
currentdict /h get 3 (three) put
range
functions
forth postscript
define function : add3 + + ; /add3 { add add } def
invoke function 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
return value
 
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
recursive function
mutually recursive functions
anonymous function { 2 add }
invoke anonymous function 3 { 2 add } exec
closure
function as value
compose functions
partial application
fried quotation
execution control
forth postscript
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
if bool
if
  if true
then
bool { if true } if
if else bool
if
  if true
else
  if false
then
bool { if true } { if false } ifelse
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
while
  code
repeat
{
  bool { exit } if
  code
} loop
infinite loop begin
  code
again
{ code } loop
loop 10 times 10 0 ?do code loop 10 { code } repeat
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
exceptions
forth postscript
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
handle exception ['] risky word catch if handle error then {
  risky code
} stopped { handle error }
file handles
forth postscript
standard file handles
read line from stdin
write line to stdout
write to stdout ." hello" cr
redirect to file
files
forth postscript
file test, regular file text
file size
is file readable, writable, executable
set file permissions
touch file
copy file, remove file, rename file
create symlink, symlink test, readlink
generate unused file name
directories
forth postscript
working directory
get and set
build pathname
dirname and basename
absolute pathname
make directory
recursive copy
remove empty directory
remove directory and contents
directory test
processes and environment
forth postscript
command line arguments
program name
environment variable
get, set
user id and name
exit bye quit
external command
backticks
pid
and parent pid
set signal handler
send signal
libraries and namespaces
forth postscript
interpret file foo.fs include
or
s" foo.fs" included
load library require foo.fs
or
s" foo.fs" required
hot patch
load error
main routine in library
library path
library path environment variable
namespace declaration
unqualified import of namespace
reflection
forth postscript
query data type none 3 type
pretty print
dump location and stack ~~
show code see word
documentation
graphics
forth postscript
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:
newpath
72 72 moveto
144 144 lineto
144 72 lineto
closepath
stroke
set current line width default value is 1:
2 setlinewidth
arc of circle creates half-circular arc centered at (144,144) with radius 40:
newpath
144 144 40 90 270 arc
stroke
bezier curve control points are (144,144), (288,144), (288,288), and (144,288):
newpath
144 144 moveto
288 144 288 288 144 288 curveto
stroke
filled polygon creates solid triangle:
newpath
72 72 moveto
144 144 lineto
144 72 lineto
closepath
fill
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
currentrgbcolor
currentfont
currentmatrix
currentlinewidth
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

interpreter

How to invoke the interpreter.

shebang

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

repl

How to invoke the REPL.

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.

forth:

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

Paren delimited comments do not nest.

Variables and Expressions

assignment

Stack

Arithmetic and Logic

operators

Strings

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

microseconds

sleep

timeout

cpu usage

Arrays

literal

Syntax for an array literal.

size

How to get the length of an array.

empty test

How to test whether an array is empty.

lookup

How to look up the value stored at an index.

update

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.

zip

How to convert two sequences into a sequence of pairs.

Heap

Dictionaries

Functions

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

closure

function as value

How to treat a function as a value.

compose functions

partial application

fried quotation

Execution Control

Exceptions

File Handles

Files

Directories

Processes and Environment

command line arguments

program name

environment variable

user id and name

exit

external command

backticks

pid

set signal handler

send signal

Libraries and Namespaces

Reflection

Graphics

Forth

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

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

Ghostscript
PSAlter
Preview

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:

%!PS
/showobject { () exch 40 string cvs show } bind readonly def
/showerror {
    /saved_errorname $error /errorname get def
    /saved_command $error /command get def
    initgraphics
    /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
issue tracker | content of this page licensed under creative commons attribution-sharealike 3.0