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
interpreter
 
$ echo "1 1 + . cr bye" > /tmp/add.forth

$ gforth /tmp/add.forth
none $ factor file
shebang
 
none none #! /usr/bin/env factor
repl
 
$ 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
SYMBOL: a

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

tuck
(a b c -- b c a) rot
frot
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

roll
arithmetic and logic
forth postscript factor
true and false true false
-1 0
true false t f
falsehoods
 
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:
3.14e0
3.14
3.14e0
! must contain decimal point or e:
10.0
1e1
numeric predicates number?
integer?
float?
rational?
complex?
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
fnegate
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:
-na
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
 
1/0.
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
none
none
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
0o52
0x2a
radix USE: math.parser

42 7 >base
"60" 7 base>
strings
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
trim
pad
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}
anchors
 
^ $ \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?
modifiers
 
i d m s r
substitution USE: regexp

"do re mi mi mi" R/ mi/ "ma" re-replace
group capture
 
none
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:
date&time
USE: calendar

now
to unix epoch, from unix epoch USE: calendar

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

unix-1970
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
timeout
cpu usage
arrays
forth postscript factor
literal [ 1 2 3 ] ! arrays need not be homogeneous
{ 1 2 "foo" }

! creates resizable array:
V{ 1 2 "foo" }
size
 
[ 1 2 3 ] length { 1 2 3 } length
empty test
 
{ 2 3 4 } empty?
lookup
 
[ 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>
copy
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
dedupe
membership 7 { 1 2 3 } member?
intersection
union
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
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 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
SYMBOL: h

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

1 100 [a,b]
functions
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
closure
function as value ! push word "dup" on stack:
\ dup

! execute word on top of stack:
execute
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
  if true
then
bool { if true } if bool [ if true ] when
if else bool
if
  if true
else
  if false
then
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
while
  code
repeat
{
  bool { exit } if
  code
} loop
[ bool ] [ code ] while
infinite loop begin
  code
again
{ 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
exceptions
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
files
forth postscript factor
file test, regular file text USE: io.files.info

"/etc/hosts" exists?
"/etc/hosts" regular-file?
file size USE: io.files.info

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

"/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
directories
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: io.files.info

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

(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

real-user-id
real-user-name
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:
wait-for-process
backticks
pid
and parent pid
set signal handler
send signal
libraries and namespaces
forth postscript factor
interpret file foo.fs include
or
s" foo.fs" included
USE: command-line

"/tmp/foo.factor" run-script
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 USE: foo

! import multiple namespaces:
USING: foo bar ;
reflection
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
graphics
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:
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.

factor:

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.

forth:

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

Paren delimited comments do not nest.

Variables and Expressions

assignment

factor:

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

a get

Stack

Arithmetic and Logic

operators

factor:

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.

Strings

Regular Expressions

literal

The syntax for a regular expression value.

factor:

The complete list of parsing words for regular expression values:

R!
R"
R#
R'
R(
R/
R@
R[
R`
R{
R|

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

factor:

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

anchors

match test

case insensitive match test

modifiers

substitution

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

microseconds

sleep

timeout

cpu usage

Arrays

factor:

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.

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.

factor:

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

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.

factor:

Heap

Dictionaries

Functions

define function

How to define a function.

factor:

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.

factor:

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

Factor

Factor Handbook
Vocabulary Index

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