4.3BSD/usr/contrib/icon/docs/tr84-11b.roff

.bp
.ce 10
\f3Appendix A \(em The Parse Tree\fR
.ce 0
.sp 1
.PP
The parse tree is a collection of nodes, described below,
rooted at a
\f3proc\fR
node.
Nodes have a common format:
the first field contains the node type,
the second and third fields contain a line and column number
relating the node to the source program,
and the next zero to four fields contain node-dependent information.
The line and column numbers are usually those of the first token
or the primary token of the construct;
for example, in
\f3binop\fR
nodes, they are the location of the operator; in
\f3if\fR
nodes, they are the location of the
\fMif\fR
token.
.PP
The following list of node types
gives a brief description of the node and
a list of the node-dependent fields and their uses.
The fields are named
.I val
if they contain an integer value,
.I str
if they contain a pointer to a string, or
.I tree
if they contain a pointer to another node (a leaf or subtree).
A digit between
0 and 3
is appended indicating its position in the node.
.PP
Seven of the nodes \(em
\f3cset\fR,
\f3id\fR,
\f3int\fR,
\f3op\fR,
\f3real\fR,
\f3res\fR,
and
\f3str\fR
\(em are leaf nodes.
These nodes, allocated and returned by the lexical analyzer,
represent source program tokens.
The remaining nodes contain one or more pointers to other nodes,
either leaves or subtrees.
.LP
.nr Z \n(PD
.nr PD \nZ
.de X
.IP \f3\\$1\fR 8n
..
.de Y
.nr PD 0
.IP \h'10n'\fI\\$1\fR \w'\fItree1'u+12n
..
.sp \nZu
.KS
.X activat
A transmission expression (\fIe1\fR @ \fIe2\fR).
.Y tree0
The operator (an \f3op\fR node).
.Y tree1
\fIe1\fR.
.Y tree2
\fIe2\fR.
.KE
.sp \nZu
.KS
.X alt
An alternation expression (\fIe1\fR | \fIe2\fR).
.Y tree0
\fIe1\fR.
.Y tree1
\fIe2\fR.
.KE
.sp \nZu
.KS
.X augop
An augmented assignment expression (\fIe1\fR \(ci\fM:=\fR \fIe2\fR).
.Y tree0
The operator.
.Y tree1
\fIe1\fR.
.Y tree2
\fIe1\fR.
.KE
.sp \nZu
.KS
.X bar
A repeated alternation expression (\^\^|\fIe\fR).
.Y tree0
\fIe\fR.
.KE
.sp \nZu
.KS
.X binop
A binary operation (\fIe1\fR \(ci \fIe2\fR).
.Y tree0
The operator.
.Y tree1
\fIe1\fR.
.Y tree2
\fIe2\fR.
.KE
.sp \nZu
.KS
.X break
A
\fMbreak\fR
expression (\fMbreak [\fIe\fM]\fR).
.Y tree0
\fIe\fR.
.KE
.sp \nZu
.KS
.X case
A
\fMcase\fR
expression (\fMcase \fIe\fM of { \*(El }\fR).
.Y tree0
\fIe\fR.
.Y tree1
The list of case clauses.
If there is only one case clause, this field points to the
\f3ccls\fR
node; if there are more, it points to a
\f3clist\fR
node.
.KE
.sp \nZu
.KS
.X ccls
A case clause
(\fIe1\fR : \fIe2\fR).
.Y tree0
\fIe1\fR.
For a
\fMdefault\fR
clause, this field points to a
\f3res\fR
node that contains the reserved word
\fMdefault\fR.
.Y tree1
\fIe2\fR.
.KE
.sp \nZu
.KS
.X clist
A list of case clauses.
The list is represented as a binary tree,
with left branches pointing to case clauses
and right branches pointing to a list of the remaining case clauses.
The right branch of the last
\f3clist\fR
node points directly to a
\f3ccls\fR
node.
.Y tree0
A case clause (pointer to a
\f3ccls\fR
node).
.Y tree1
Pointer to another
\f3clist\fR
node, or to the last
\f3ccls\fR
node in the list.
.KE
.sp \nZu
.KS
.X conj
A conjunction expression (\fIe1 \fM&\fI e2\fR).
.Y tree0
\fIe1\fR.
.Y tree1
\fIe2\fR.
.KE
.sp \nZu
.KS
.X create
A \fMcreate\fR expression (\fMcreate\fI e\fR).
.Y tree0
\fIe\fR.
.KE
.sp \nZu
.KS
.X cset
A leaf node representing a cset literal.
.Y str0
The string equivalent of the literal.
.Y val1
The length of the string.
.KE
.sp \nZu
.KS
.X elist
An expression list, as in a list construction
or the argument list in a procedure call.
An expression list, like a list of case clauses,
is represented as a binary tree.
.Y tree0
An expression.
.Y tree1
Pointer to another
\f3elist\fR
node, or to the last expression in the list.
.KE
.sp \nZu
.KS
.X empty
This node is used as a placeholder for missing expressions in
control structures and expression lists.
.KE
.sp \nZu
.KS
.X field
A field reference to a record (\fIe\fM . \fIident\fR).
.Y tree0
\fIe\fR.
.Y tree1
Pointer to an
\f3id\fR
node, containing the field name \fIident\fR.
.KE
.sp \nZu
.KS
.X id
A leaf node representing an identifier.
.Y str0
The name of the identifier.
.KE
.sp \nZu
.KS
.X if
An
\fMif\fR
expression (\fMif\fI e1 \fMthen\fI e2 \fM[\fMelse\fI e3\fM]\fR).
.Y tree0
\fIe1\fR.
.Y tree1
\fIe2\fR.
.Y tree2
\fIe3\fR.
.KE
.sp \nZu
.KS
.X int
A leaf node representing an integer literal.
.Y str0
The string representation of the literal.
.KE
.sp \nZu
.KS
.X invok
A procedure call or mutual evaluation expression (\fIe\fM ( \fIargs\fM )\fR).
.Y tree0
\fIe\fR.
.Y tree1
The argument list \fIargs\fR.
If there is one argument, this field points to the expression;
if there are more, it points to an
.I elist
node.
.KE
.sp \nZu
.KS
.X key
A keyword reference (\fM&\fI\^ident\fR).
.Y val0
The index of the keyword \fIident\fR, defined in the file
\fMtran/keyword.h\fR.
.KE
.sp \nZu
.KS
.X limit
A limitation expression (\fIe1\fR \e \fIe2\fR).
.Y tree0
\fIe1\fR.
.Y tree1
\fIe2\fR.
.KE
.sp \nZu
.X list
A list (\^\fM[\fIe1\fR, \fIe2\fR, \*(El \fM]\fR).
.Y tree0
The list of elements.
If there is one element, this field points to the expression;
if there are more, it points to an
\f3elist\fR
node.
.KE
.sp \nZu
.KS
.X loop
A loop expression (\fIloop\fR \fIe1\fR [\fMdo\fI e2\fR]).
.Y tree0
The style of loop.
This field points to a
\f3res\fR
node, which identifies the reserved word that introduced the loop.
.Y tree1
\fIe1\fR.
.Y tree2
\fIe2\fR.
.KE
.sp \nZu
.KS
.X next
A
\fMnext\fR
expression.
.Y
.sp -1
.KE
.sp \nZu
.KS
.in 0
.X not
A
\fMnot\fR
expression (\fNnot \fIe\fR).
.Y tree0
\fIe\fR.
.KE
.sp \nZu
.KS
.X op
A leaf node representing an operator.
.Y val0
The token type of the operator.
.KE
.sp \nZu
.KS
.X proc
A procedure.
This node is always at the root of the parse tree.
.Y tree0
The procedure name.
This field points to an
\f3id\fR
node containing the name.
.Y tree1
The
\fMinitial\fR
clause.
.Y tree2
The procedure body.
If there is one expression in the procedure body,
this field points to it;
if there are more, it points to an
\f3elist\fR
node.
.Y tree3
A node containing the
\fMend\fR
token.
This field is used to supply a line number for the implicit return
at the end of a procedure.
.KE
.sp \nZu
.KS
.X real
A leaf node representing a real number literal.
.Y str0
The string representation of the literal.
.KE
.sp \nZu
.KS
.X res
A leaf node representing a reserved word.
.Y val0
The token type of the reserved word.
.KE
.sp \nZu
.KS
.X ret
A
\fMreturn\fR
or
\fMfail\fR
expression.
.Y tree0
The type of return.
This field points to a
\f3res\fR
node, which contains the reserved word
\fMreturn\fR
or
\fMfail\fR.
.Y tree1
The expression following
\fMreturn\fR,
or a pointer to an
\f3empty\fR
node.
.KE
.sp \nZu
.KS
.X scan
A scanning expression (\fIe1\fR \fM?\fR \fIe2\fR).
.Y tree0
The operator.
.Y tree1
\fIe1\fR.
.Y tree2
\fIe2\fR.
.KE
.sp \nZu
.KS
.X sect
A section expression (\fIe1\fR [\fIe2\fR : \fIe3\fR]).
.Y tree0
\fIe1\fR.
.Y tree1
\fIe2\fR.
.Y tree2
\fIe3\fR.
.KE
.sp \nZu
.KS
.X slist
A list of expressions separated by semicolons,
as in a procedure body (a statement list).
This list, like expression lists and case lists,
is represented as a binary tree.
.Y tree0
An expression in the list.
.Y tree1
A pointer to another
\f3slist\fR
node, or to the last expression in the list.
.KE
.sp \nZu
.KS
.X str
A leaf node representing a string literal.
.Y str0
The string value of the literal.
.Y val1
The length of the string,
necessary because the string may contain the \s-2ASCII\s+2
.I null
character, which would otherwise terminate the string.
.KE
.sp \nZu
.KS
.X susp
A
\fMsuspend\fR
expression (\fMsuspend\fR [\fIe\fR]).
.Y tree0
\fIe\fR.
.KE
.sp \nZu
.KS
.X toby
A
\fMto-by\fR
expression (\fIe1\fM to \fIe2\fM by \fIe3\fR).
.Y tree0
\fIe1\fR.
.Y tree1
\fIe2\fR.
.Y tree2
\fIe3\fR.
.KE
.sp \nZu
.KS
.X to
A
\fMto\fR
expression (\fIe1\fM to \fIe2\fR).
.Y tree0
\fIe1\fR.
.Y tree1
\fIe2\fR.
.KE
.sp \nZu
.KS
.X unop
A unary operation (\(ci \fIe\fR).
.Y tree0
The operator.
.Y tree1
\fIe\fR.
.KE
.nr PD \nZ
.bp
.ce 10
\f3Appendix B \(em Icon Grammar\fR
.ce 0
.sp 1
.PP
The following grammar describes the Icon language.
Reserved words and operators
are shown in a sans-serif type face;
nonterminals are in italics.
The nonterminals
.I ident ,
.I literal ,
.I strliteral ,
and
.I empty
are left undefined in the syntax.
.sp 2
.ta 1.5iR 1.5i+1mL
.ft I
.tr |\(br
.tr -\-
.tr +\(pl
.tr /\(sl
.tr *\(**
.ss 9
.de X
\t\\$1\h'1m'\(->\t\\$2
.br
..
.de Y
.if n .sp 1
.if t .sp .5
..
.X    program    "decls"
.Y
.ne 2
.X      decls    "empty"
.X         ""    "decls decl"
.Y
.ne 3
.X       decl    "record"
.X         ""    "proc"
.X         ""    "global"
.X         ""    "link"
.Y
.X       link    "\fMlink\fI lnklist"
.Y
.ne 2
.X     lnklist   "lnkfile"
.X          ""   "lnklist , lnkfile"
.Y
.X     lnkfile   "ident"
.X          ""   "strliteral"
.Y
.ne 2
.X     global    "\fMglobal\fI idlist"
.Y
.X     record    "\fMrecord\fI ident \fM(\fI arglist \fM)\fI"
.Y
.X       proc    "prochead \fM;\fI locals initial procbody \fMend\fI"
.Y
.X   prochead    "\fMprocedure\fI ident \fM(\fI arglist \fM)\fI"
.Y
.ne 2
.X    arglist    "empty"
.X         ""    "idlist"
.Y
.ne 2
.X     idlist    "ident"
.X         ""    "idlist \fM,\fI ident"
.Y
.ne 2
.X     locals    "empty"
.X         ""    "locals retention idlist \fM;\fI"
.Y
.ne 2
.X  retention    "\fMlocal\fI"
.X         ""    "\fMstatic\fI"
.X         ""    "\fMdynamic\fI"
.Y
.ne 2
.X    initial    "empty"
.X         ""    "\fMinitial\fI expr \fM;\fI"
.Y
.ne 2
.X   procbody    "empty"
.X         ""    "nexpr \fM;\fI procbody"
.Y
.ne 2
.X      nexpr    "empty"
.X         ""    "expr"
.Y
.ne 2
.X       expr    "expr1a"
.X         ""    "expr \fM&\fI expr1a"
.Y
.ne 2
.X      expr1a  "expr1"
.X         ""   "expr1a \fM?\fI expr1"
.Y
.ne 5
.X      expr1    "expr2"
.X         ""    "expr2 op1 expr1"
.X         ""    "expr2 op1a expr1"
.X         ""    "expr2 \fM?:=\fI expr1"
.X         ""    "expr2 \fM&:=\fI expr1"
.X         ""    "expr2 \fM@:=\fI expr1"
.Y
.ne 6
.X        op1    "\fM:= | :=: | <- | <->\fI"
.Y
.if n .X op1a    "\fM+:= | -:= | *:= | /:= | %:= | ^:=\fI"
.if n .X   ""    "\fM++:= | --:= | **:= | \(or\(or:= | \(or\(or\(or:=\fI"
.if t .X op1a    "\fM+:= | -:= | *:= | /:= | %:= | ^:= | ++:= | \
--:= | **:= | \(or\(or:= | \(or\(or\(or:=\fI"
.X      ""       "\fM<:= | <=:= | =:= | >=:= | >:= | ~=:= \fM"
.X      ""       "\fM<<:= | <<=:= | ==:= | >>=:= | >>:= | ~==:=\fI"
.X      ""       "\fM===:= | ~===:=\fI"
.Y
.ne 3
.X      expr2    "expr3"
.X         ""    "expr2 \fMto\fI expr3"
.X         ""    "expr2 \fMto\fI expr3 \fMby\fI expr3"
.Y
.ne 2
.X      expr3    "expr4"
.X         ""    "expr4 \(or expr3"
.Y
.ne 2
.X      expr4    "expr5"
.X         ""    "expr4 op4 expr5"
.Y
.ne 3
.X        op4    "\fM< | <= | = | >= | > | ~=\fI"
.X         ""    "\fM<< | <<= | == | >>= | >> | ~==\fI"
.X         ""    "\fM=== | ~===\fI"
.Y
.ne 2
.X      expr5    "expr6"
.X         ""    "expr5 op5 expr6"
.Y
.ne 2
.X      op5     "\fM\(or\(or | \(or\(or\(or\fI"
.Y
.ne 2
.X      expr6    "expr7"
.X         ""    "expr6 op6 expr7"
.Y
.X        op6    "\fM+ | - | ++ | --\fI"
.Y
.ne 2
.X      expr7    "expr8"
.X         ""    "expr7 op7 expr8"
.Y
.X        op7    "\fM* | / | % | **\fI"
.Y
.ne 2
.X      expr8    "expr9"
.X         ""    "expr9 ^ expr8"
.Y
.ne 2
.X      expr9    "expr10"
.X         ""    "expr9 \fM\e\fI expr10"
.X         ""    "expr9 \fM @ \fIexpr10"
.Y
.ne 5
.X     expr10    "expr11"
.X         ""    "\fMnot\fI expr10"
.X         ""    "\fM@\fI expr10"
.X         ""    "\(or expr10"
.X         ""    "op10 expr10"
.Y
.X       op10    "\fM. | ! | + | - | ~ | = | * | / | \e | ? | ^\fI"
.Y
.ne 20
.X     expr11    "ident"
.X         ""    "literal"
.X         ""    "\fM&\fI ident"
.X         ""    "expr11 \fM.\fI ident"
.X         ""    "expr11 \fM[\fI nexpr \fM]\fI"
.X         ""    "expr11 \fM(\fI exprlist \fM)\fI"
.X         ""    "expr11 \fM{\fR exprlist \fM}\fI"
.X         ""    "\fM[\fI exprlist \fM]\fI"
.X         ""    "\fM(\fI exprlist \fM)\fI"
.X         ""    "{ compound }"
.X         ""    "while"
.X         ""    "until"
.X         ""    "every"
.X         ""    "repeat"
.X         ""    "\fMnext\fI"
.X         ""    "\fMbreak\fI nexpr"
.X         ""    "\fMcreate\fI expr"
.X         ""    "if"
.X         ""    "case"
.X         ""    "return"
.X         ""    "section"
.Y
.ne 2
.X      while    "\fMwhile\fI expr"
.X         ""    "\fMwhile\fI expr \fMdo\fI expr"
.Y
.ne 2
.X      until    "\fMuntil\fI expr"
.X         ""    "\fMuntil\fI expr \fMdo\fI expr"
.Y
.ne 2
.X      every    "\fMevery\fI expr"
.X         ""    "\fMevery\fI expr \fMdo\fI expr"
.Y
.X     repeat    "\fMrepeat\fI expr"
.Y
.ne 2
.X         if    "\fMif\fI expr \fMthen\fI expr"
.X         ""    "\fMif\fI expr \fMthen\fI expr \fMelse\fI expr"
.Y
.X       case    "\fMcase\fI expr \fMof\fI { caselist }"
.Y
.ne 2
.X   caselist    "cclause"
.X         ""    "caselist \fM;\fI cclause"
.Y
.ne 2
.X    cclause    "\fMdefault\fM :\fI expr"
.X         ""    "expr \fM:\fI expr"
.Y
.ne 3
.X     return    "\fMfail\fI"
.X         ""    "\fMreturn\fI nexpr"
.X         ""    "\fMsuspend\fI nexpr"
.Y
.X    section    "expr11 \fM[\fI expr sectop expr \fM]\fI"
.Y
.X     sectop    "\fM: | +: | -:\fI"
.Y
.ne 2
.X   exprlist    "nexpr"
.X         ""    "exprlist \fM,\fI nexpr"
.Y
.ne 2
.X   compound    "nexpr"
.X         ""    "nexpr \fM;\fI compound"
.ss 4
.tr ||
.tr --
.tr ++
.tr //
.tr **
.uf I
.ft R
.bp
.de Op
.if \\n(.$=2 .IP \h'3n'\f3\\$1\h'2n'\fI\\$2\fR 6n
.if \\n(.$=1 .IP \h'3n'\f3\\$1\fR 6n
.br
..
.ce 10
\f3Appendix C \(em Ucode\fR
.ce 0
.sp 1
.PP
The intermediate ucode generated by the Icon translator
resembles a stack-oriented assembly language.
A ucode program is a sequence of labels and instructions.
A label marks a location in the program to which other instructions
may transfer control.
Labels are of the form \*(oq\f3lab L\fIn\fR\*(cq, where
.I n
is a decimal number.
A ucode instruction either describes an imperative operation
or communicates information to the Icon linker.
Instructions consist of an opcode followed by zero or more arguments.
Arguments can be decimal or octal integers,
names, or label references.
.PP
The intermediate language operates exclusively on the stack.
There are several kinds of objects that can appear on the stack:
descriptors, which represent Icon values and variables;
procedure frame markers, which mark the beginning of a new procedure frame;
expression frame markers, which delimit expression instances;
and generator frame markers, which mark inactive generators.
For more details about the stack, refer to Section 3.2.
.PP
The opcodes and their arguments are described in three groups below.
The global symbol table file has a similar format.
The opcodes used there are described in the fourth group.
.sp 1
.SH
Imperative Instructions
.PP
The instructions below,
together with the operators described in the next section,
represent run-time actions for which code is executed.
.KS
.Op bscan
Save the values of \fM&subject\fR and \fM&pos\fR on the stack
and establish values for them.
This operation is reversible.
.KE
.KS
.Op ccase
Duplicate the value on the stack
just below the current expression frame.
Used in
\fMcase\fR
expressions.
.KE
.KS
.Op chfail lab
Change the failure label for the current expression frame to
.I lab .
Used for repeated evaluation.
.KE
.KS
.Op  coact
Switch co-expression evaluation. Create a procedure frame on the current
co-expression stack. Transfer the result from old stack to new stack,
dereferencing if necessary. Set the activator field in new stack block to
point to old co-expression stack block. Return from procedure frame on
new co-expression stack.
.KE
.KS
.Op  cofail
Fail from current co-expression to activating co-expression.
Create a procedure frame on current co-expression stack. Fail from
procedure frame on activator's co-expression stack.
.KE
.KS
.Op  coret
Switch evaluation to activating co-expression.
Create a procedure frame on current co-expression stack. Transfer
the result from old stack to activator's stack, dereferencing it if the result
is on the old stack.
Return from the procedure frame on new co-expression stack.
.KE
.KS
.Op  create
Create a co-expression. Allocate
co-expression stack and heap blocks. Copy the arguments
and locals variables from the current procedure frame into the heap block.
Create a procedure frame in the new co-expression stack using the arguments
and other locals from current procedure frame. Create a procedure
frame for dummy call to \fMcoact\fR on the new co-expression stack.
Push a descriptor representing the new co-expression onto current co-expression
stack.
.KE
.KS
.Op cset n
Push a descriptor representing the cset literal at constant table location
.I n
onto the stack.
.KE
.KS
.Op dup
Push a descriptor representing the null value onto the stack, and then duplicate the value that
was the previous top of the stack.
Used in most augmented assignments.
.KE
.KS
.Op efail
Signal failure in the current expression.
If there are any inactive generators, reactivate the most recent one.
If there are none, branch to the failure label
for the current expression frame.
If the failure label is null,
exit the current expression frame,
and signal failure in the enclosing one.
.KE
.KS
.Op eret
Return a value from an expression.
Save the value on top of the stack,
exit the current expression frame,
and push the value onto the stack as part of the enclosing expression frame.
.KE
.KS
.Op escan
Restore
\fM&subject\fR
and
\fM&pos\fR
from the stack.
This operation is reversible.
.KE
.KS
.Op esusp
Suspend a value from an expression.
The value on the top of the stack is saved,
and a generator frame hiding the current expression frame is created.
The surrounding expression frame is duplicated,
and the value is pushed onto the stack as part of that expression frame.
When reactivated,
\f3esusp\fR
in turn reactivates any inactive generators in the suspended expression.
.KE
.KS
.Op field name
Access the field
.I name
of the record on the top of the stack.
.KE
.KS
.Op file name
Set the file name to
.I name
for use in error messages and tracing.
Used at the beginning of each procedure.
.KE
.KS
.Op goto lab
Transfer control to the instruction following label
.I lab .
.KE
.KS
.Op incres
Increment result count field in current co-expression stack block.
.KE
.KS
.Op init? lab
If the initialization statement for the current procedure
has already been executed once, go to
.I lab .
.KE
.KS
.Op int n
Push a descriptor representing the integer literal at constant table location
.I n
onto the stack.
.KE
.KS
.Op invoke n
Invoke a procedure or create a record.
The number of arguments or fields on the stack is given by
.I n .
The procedure (which may be a record constructor) is on the stack,
just beyond the arguments.
After invocation, the arguments are popped from the stack,
and the returned value is pushed (see
\f3pret\fR).
.KE
.KS
.Op keywd n
Push a descriptor representing a value or trapped variable representing keyword
.I n
onto the stack.
(See
\fMtran/keyword.h\fR
for keyword numbers.)
.KE
.KS
.Op limit
Check the value on the top of the stack for a legal limitation value.
If the value is zero, failure is signalled in the current expression (see
\f3efail\fR).
.KE
.KS
.Op line n
Set the line number to
.I n
for use in error messages and tracing.
.KE
.KS
.Op llist n
Create a list of
.I n
values.
The values are popped from the stack
and the created list is pushed back onto the stack.
.KE
.KS
.Op lsusp
Decrement the limitation counter for the current expression frame.
If the counter becomes zero, then return a value
from the current expression frame (see
\f3eret\fR);
otherwise, suspend a value from the current expression frame (see
\f3esusp\fR).
.KE
.KS
.Op mark lab
Save the current expression and generator frame pointers on the stack,
then create a new expression frame, with failure label
.I lab .
Control is transferred to
.I lab
if failure occurs in the expression frame and there are no suspended
generators to reactivate (see
\f3efail\fR).
The failure label \fML0\fR indicates that control is to be
transferred to the failure label in the enclosing expression.
.KE
.KS
.Op pfail
Return from the current procedure, and signal failure (see
\f3efail\fR).
.KE
.KS
.Op pnull
Push a descriptor representing the null value onto the stack.
.KE
.KS
.Op pop
Pop the top element off of the stack.
.KE
.KS
.Op pret
Return from the current procedure
with the result that is on top of the stack.
.KE
.KS
.Op psusp
Suspend from the current procedure
with the result that is on top of the stack.
.KE
.KS
.Op push1
Push a descriptor representing the integer 1 onto the stack.
.KE
.KS
.Op pushn1
Push a descriptor representing the integer \-1 onto the stack. This is used as default in
mutual goal-directed evaluation.
.KE
.KS
.Op real n
Push a descriptor representing the real literal at constant table location
.I n
onto the stack.
.KE
.KS
.Op  refresh
Allocate space for a new co-expression stack. Create a procedure frame
in new co-expression stack using arguments and other locals from
entry block for co-expression operand. Create a procedure frame for
dummy call to \fMcoact\fR on new co-expression stack.
Push a descriptor representing the new co-expression onto current co-expression
stack.
.KE
.KS
.Op sdup
Duplicate the descriptor on the top of the stack.
Used in assignment augmented with string scanning.
.KE
.KS
.Op str n
Push a descriptor representing the string literal at constant table location
.I n
onto the stack.
.KE
.KS
.Op unmark n
Exit from
.I n
expression frames.
No value is pushed onto the stack in their place.
.KE
.KS
.Op var n
Push the descriptor for the variable at location
.I n
in the local symbol table onto the stack.
.KE
.sp 1
.SH
Operators
.PP
The instructions below perform the functions
corresponding to the indicated Icon operator.
The operands are evaluated and pushed onto the stack from left to right,
so that the topmost element of the stack is the rightmost operand.
The operands are popped before
the result of the operation is pushed onto the stack.
All operations dereference their operands as necessary,
but only after all operands have been evaluated and pushed onto the stack.
All operations attempt to convert their operands to an appropriate type.
If this implicit conversion fails, an error is issued.
Relational tests fail if the specified condition is not met;
the result of a successful comparison is the value of the right-hand operand.
Arithmetic operations cause an error to be issued
if the result overflows or underflows.
If an operation cannot be performed for some other reason,
it fails.
.LP
.ta 0.5i 1.5i 3.5i 4.5i
.de X
\t\f3\\$1\fM\t\\$2\t\f3\\$3\fM\t\\$4\fR
.br
..
.ne 21
.tr |\(or
.tr +\(pl
.tr -\-
.tr /\(sl
.tr *\(**
.ss 9
.X asgn         "x := y"      null         "/x"
.X bang         "!x"          number       "+x"
.X cat          "x || y"            numeq        "x = y"
.X compl        "~x"                numge        "x >= y"
.X diff         "x -- y"            numgt        "x > y"
.X div          "x / y"             numle        "x <= y"
.X eqv          "x === y"           numlt        "x < y"
.X inter        "x ** y"            numne        "x ~= y"
.X lconcat      "x ||| y"           plus         "x + y"
.X lexeq        "x == y"            power        "x ^ y"
.X lexge        "x >>= y"           random       "?x"
.X lexgt        "x >> y"            rasgn        "x <- y"
.X lexle        "x <<= y"           rswap        "x <-> y"
.X lexlt        "x << y"            sect         "x\^[\^y:z]"
.X lexne        "x ~== y"           size         "*x"
.X minus        "x - y"             subsc        "x\^[\^y]"
.X mod          "x % y"             swap         "x :=: y"
.X mult         "x * y"             tabmat       "=x"
.X neg          "-x"                toby         "x to y by z"
.X neqv         "x ~=== y"          unioncs      "x ++ y"
.X nonnull      "\ex"               value        ".x"
.tr ||
.tr ++
.tr --
.tr //
.tr **
.ss 4
.sp 1
.SH
Non-Imperative Instructions
.PP
The following instructions generate no executable code.
Instead, they communicate various information to the linker
each procedure and its symbol table.
An Icon procedure is translated into a sequence of ucode
instructions beginning with a
\f3proc\fR
instruction, followed by a sequence of
\f3local\fR
instructions, a sequence of
\f3con\fR
instructions, a
\f3declend\fR
instruction, then the imperative instructions describing
the procedure body.
An
\f3end\fR
instruction terminates the procedure.
.KS
.Op proc name
Begin a new procedure with the indicated name.
The local and constant tables are initialized.
The procedure block is not generated at this time,
since the local identifiers have not yet been declared.
.KE
.KS
.Op local n,flags,name
Enter
.I name
into the current procedure's local symbol table at location
.I n .
The symbol's
.I flags
indicate information about the symbol, its scope, and its retention.
All identifiers referred to in a procedure appear in the
local symbol table.
If an identifier is undeclared,
its scope is determined by consulting the global symbol table
and a list of functions.
.KE
.KS
.Op con n,flags,value
Enter
.I value
into the current procedure's constant table at location
.I n
in the table.
The type of the constant (integer, real, or string) is indicated by
.I flags .
For integer and real literals,
.I value
is an 11-digit octal number;
for string and cset literals,
it is a comma-separated list of 3-digit octal numbers,
each representing one byte in the string.
.KE
.KS
.Op declend
Signal the end of the procedure prologue.
The procedure block is generated at this point.
.KE
.KS
.Op end
Signal the end of a procedure.
.KE
.sp 1
.SH
Global Symbol Table Instructions
.PP
A single global symbol table file is output during each translation.
Record declarations appear first in the file;
they are output as they are encountered in the Icon source program.
The first instruction following the record declarations is
\f3impl\fR,
which may be followed by a
\f3trace\fR
instruction, then by the global declarations.
The global declarations are output at the end of translation.
.KS
.Op record name,n
Declare a record with the indicated name and
.I n
fields.
One line for each field follows this line,
each containing the field number and name.
.KE
.KS
.Op impl scope
Declare the implicit scope as indicated.
.I Scope
can be either
\f3local\fR
or
\f3error\fR.
If the implicit scope is
\f3error\fR,
undeclared identifiers are flagged as warnings during linking;
otherwise, they are made local variables.
The implicit scope is
\f3error\fR
if the
\f3\-u\fR
option was given on the translator command line, otherwise it is
\f3local\fR.
.KE
.KS
.Op trace
Enable run-time tracing.
This instruction is present if the
\f3\-t\fR
option was given on the translator command line,
and causes the keyword
\fM&trace\fR
to be initialized to \-1.
.KE
.KS
.Op global n
Begin the global symbol table.
There are
.I n
global declarations following, one per line.
Each global declaration contains a sequence number,
the flags, the identifier name,
and the number of formal parameters (for procedures) or fields (for records).
.KE
.KS
.Op link name
Search each directory named in the \fIIPATH\fR environment variable
for a file named \fIname.u1\fR. If the file is
located, it is added to the list of files to link.
.KE
.bp
.if \nv .ss 9
.ce 10
\f3Appendix D \(em Data Representations\fR
.ce 0
.sp 1
.SH
Descriptor Formats
.PP
The figures below depict each of the six descriptor types
mentioned in Section 3.1.
Each descriptor is two words long;
the first word is shown on top of the second.
.sp 1
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n)e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e |
LI | L S S S S S S S S S S S S S S C |
L  | L S S S S S S S S S S S S S S S |
L  | L S S S S S S S S S S S S S S C |
L  | L S S S S S S S S S S S S S S S | .
:_
Null::0
:_
::0
:_
.TE
.sp 1
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n)e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e |
LI | C  | CI S S S S S S S S S S S S S S |
L  | L    S  S S S S S S S S S S S S S S |
L  | CI   S  S S S S S S S S S S S S S S |
L  | L    S  S S S S S S S S S S S S S S | .
:_
String Qualifier:0:length
:_
:address of string
:_
.TE
.sp 1
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n)e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e |
LI | C  | C | CI S S S S S S S | CI S S S S S |
L  | L    S   S  S S S S S S S   S  S S S S S |
LI | CI   S   S  S S S S S S S   S  S S S S S |
L  | L    S   S  S S S S S S S   S  S S S S S | .
:_
Integer:1:0:flags:type = \fR1
:_
:integer
:_
.TE
.sp 1
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n)e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e |
LI | C  | C | CI S S S S S S S | CI S S S S S |
L  | L    S   S  S S S S S S S   S  S S S S S |
LI | CI   S   S  S S S S S S S   S  S S S S S |
L  | L    S   S  S S S S S S S   S  S S S S S | .
:_
Value:1:0:flags:type \(>= \fR2
:_
:address of data block
:_
.TE
.sp 1
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n)e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e |
LI | C  | C | C | CI S S S S S S S S S S S S |
L  | L    S   S   S  S S S S S S S S S S S S |
LI | CI   S   S   S  S S S S S S S S S S S S |
L  | L    S   S   S  S S S S S S S S S S S S | .
:_
Variable:1:1:0:offset
:_
:address of descriptor
:_
.TE
.sp 1
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n)e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e |
LI | C  | C | C | CI S S S S S S | CI S S S S S |
L  | L    S   S   S  S S S S S S   S  S S S S S |
LI | CI   S   S   S  S S S S S S   S  S S S S S |
L  | L    S   S   S  S S S S S S   S  S S S S S | .
:_
Trapped Variable:1:1:1:flags:type
:_
:address of data block
:_
.TE
\fINotes:\fR The offset in a variable descriptor is the number of words from
the top of the block in which the descriptor that is pointed to occurs.
The second word in the descriptors for the trapped variables for \fM&pos\fR, \fM&random\fR,
and \fM&trace\fR contain addresses of locations in statically allocated data.
.bp
.SH
Data Block Formats
.PP
The data blocks used by the Icon system are pictured below.
The data type code,
shown as both a mnemonic and an integer,
is always the first word of the block and has the same
value as the type code in the
.I value
or
.I "trapped variable"
descriptor that refers to it.
All
.I name
fields in the data blocks are
.I "string qualifier"
descriptors, and all
.I pointers
in the data blocks are
.I "variable"
descriptors.
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
Long Integer Block:T_LONGINT = 2
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::32-bit integer
:_::_

:_
.TE
\fINote:\fR Long integers apply only when \fMsizeof(int) != sizeof(long)\fR
.sp
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
Real Block:T_REAL = 3
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L         L       ^        L
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::double-precision real
:_::_



:_::_

:_
.TE
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
Cset Block:T_CSET = 4
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       ^        L       |
L         L       ^        L
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::256-bit character set
:_::_

:_::_



:_::_

:_::_

:_
.TE
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
File Block:T_FILE = 5
:_
.T&
L       | CI      S        S       | .
:\s-2UNIX\s+2 file descriptor
:_
:file status
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::file name
:_::_

:_
.TE
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
Procedure Block:T_PROCEDURE = 6
:_
.T&
L       | CI      S        S       | .
:size of this data block
:_
:entry point address
:_
:number of arguments
:_
:number of dynamic locals
:_
:number of static locals
:_
:index of first static local
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::procedure name
:_::_

:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::name of first identifier
:_::_

:_
.T&
L       | L       CB       L       |
L         L       CB       L
L       | L       CB       L       |
L       | L       S        S       | .
::.
::.
::.
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::name of last identifier
:_::_

:_
.TE
\fINotes:\fR Identifiers include arguments and locals.
Similar blocks are used for built-in functions; in this
case the word for the number of dynamic locals contains \-1.
For functions, there are no argument names. Functions like \fMwrite\fR,
which have an arbitrary number of argument, are indicated by
the value \-1 in place of the number of arguments. Record constructors
are distinguished from other functions by the value \-2
in place of the number of dynamic locals. Each record declaration
is distinguished by a unique record identification number, which
appears in place of the number of static locals.
.sp
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
List Header Block:T_LIST = 7
:_
.T&
L       | CI      S        S       | .
:current size of list
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::pointer to first list block
:_::_

:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::pointer to last list block
:_::_

:_
.TE
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
List Element Block:T_LELEM = 11
:_
.T&
L       | CI      S        S       | .
:size of this data block
:_
:number of slots in this block
:_
:index of first slot used
:_
:number of slots used
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::pointer to previous list block
:_::_

:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::pointer to next list block
:_::_

:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::first slot
:_::_

:_
.T&
L       | L       CB       L       |
L         L       CB       L
L       | L       CB       L       |
L       | L       S        S       | .
::.
::.
::.
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::last slot
:_::_

:_
.TE
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
Table Header Block:T_TABLE = 8
:_
.T&
L       | CI      S        S       | .
:current table size
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::default value
:_::_

:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::first hash bucket
:_::_

:_
.T&
L       | L       CB       L       |
L         L       CB       L
L       | L       CB       L       |
L       | L       S        S       | .
::.
::.
::.
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::last hash bucket
:_::_

:_
.TE
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
Table Element Block:T_TELEM = 10
:_
.T&
L       | CI      S        S       | .
:hash number
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::pointer to next element
:_::_

:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::entry value
:_::_

:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::assigned value
:_::_

:_
.TE
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
Set Header Block:T_SET = 20
:_
.T&
L       | CI      S        S       | .
:current set size
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::first hash bucket
:_::_

:_
.T&
L       | L       CB       L       |
L         L       CB       L
L       | L       CB       L       |
L       | L       S        S       | .
::.
::.
::.
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::last hash bucket
:_::_

:_
.TE
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
Set Element Block:T_SELEM = 21
:_
.T&
L       | CI      S        S       | .
:hash number
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::member value
:_::_

:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::pointer to next member
:_::_

:_
.TE
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
Record Block:T_RECORD = 9
:_
.T&
L       | CI      S        S       | .
:size of this data block
:_
:pointer to record constructor
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::first field of record
:_::_

:_
.T&
L       | L       CB       L       |
L         L       CB       L
L       | L       CB       L       |
L       | L       S        S       | .
::.
::.
::.
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::last field of record
:_::_

:_
.TE
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
Co-Expression Stack Block:T_ESTACK = 18
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::most recent activator
:_::_

:_
.T&
L       | CI      S        S       | .
:stack base
:_
:stack pointer
:_
:address pointer
:_
:Icon/C boundary
:_
:number of results produced
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::pointer to refresh block
:_::_

:_
.T&
L       | L       CB       L       |
L         L       CB       L
L       | L       CB       L       |
L       | L       S        S       | .
::.
::.
::.
:_
.TE
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
Co-Expression Heap Block:T_EBLOCK = 19
:_
.T&
L       | CI      S        S       | .
:size of this data block
:_
:entry point address
:_
:number of arguments
:_
:number of locals
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::procedure
:_::_

:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::value of first identifier
:_::_

:_
.T&
L       | L       CB       L       |
L         L       CB       L
L       | L       CB       L       |
L       | L       S        S       | .
::.
::.
::.
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::value of last identifier
:_::_

:_
.TE
\fINote:\fR Identifiers include arguments and locals.
.sp
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
Substring Trapped Variable:T_TVSUBS = 12
:_
.T&
L       | CI      S        S       | .
:length of substring
:_
:relative position of substring
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::variable containing substring
:_::_

:_
.TE
.KE
.sp 1
.KS
.TS
center tab(:) ;
L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) |
LI      | C       S        S       | .
:_
Table Element Trapped Variable:T_TVTBL = 14
:_
.T&
L       | CI      S        S       | .
:hash number
:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::pointer to table
:_::_

:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::entry value
:_::_

:_
.T&
L       | L       CI       L       |
L       | L       ^        L       |
L       | L       ^        L       |
L       | L       S        S       | .
::
:_::_

:_
.TE
\fINote\fR: The last descriptor in a table element trapped variable
is not used until the element is inserted in the table, at which
time the table element trapped variables is converted into a
table element block.
.KE
.bp
.ce 10
\f3Appendix E \(em Stack Frame Formats\fR
.ce 0
.sp 1
.PP
Stack frame formats depend on computer architecture and the
C compiler that is used. Consequently, stack frame formats are
specific to a particular implementation. This appendix gives the
UNIX PDP-11 and VAX-11 stack frame formats. See [3] for a detailed
description of the design of stack frame formats.
.PP
On the PDP-11 and VAX-11 stacks start in high memory and grow
downward. On these computers, a push causes the stack
pointer to decrease and a pop causes the stack pointer to
increase, while ``top of the stack'' refers to the
\fIlowest\fR memory location that is logically contained in the stack.
The diagrams that follow are arranged accordingly.
.PP
There are three kinds of stack frames: \fIprocedure frames\fR, \fIexpression
frames\fR, and \fIgenerator frames\fR.
For each kind of frame, a
.I "frame pointer"
points to the most recent
.I "frame marker" ,
which marks one end of the frame.
These frame pointers are referred to as \fIpfp\fR, \fIefp\fR, and \fIgfp\fR,
respectively.
Each frame marker contains a pointer
to the next most recent marker of the same kind.
.sp 2
.ce
\f3PDP-11 Stack Frame Formats\fR
.sp 2
.PP
On the PDP-11, \fIpfp\fR, \fIefp\fR, and \fIgfp\fR are in registers
\fIr5\fR, \fIr4\fR, and \fIr3\fR, respectively,
whenever an Icon procedure is active.
In the interpreter implementation,
.I r2
contains the interpreter's program counter (\fIipc\fR),
which points to the next icode operation to be done.
When a C procedure is active,
only the procedure frame pointer is kept in a register;
registers
.I r2\-r4
are used for local variables by C procedures.
.sp 1
.SH
Procedure Frames on the PDP-11
.PP
Icon procedure frames are augmented C procedure frames.
A procedure frame contains a procedure's
arguments, local variables,
and temporary storage for incomplete computations.
When an active procedure invokes another procedure,
a new procedure frame is created for the new procedure,
which then becomes active.
As such, the new procedure represents an incomplete computation
in the calling procedure,
so the new procedure frame is
.Q nested
within the old one.
The
.I "procedure marker"
is placed on the stack between the arguments and local variables.
The format of the procedure frame is shown below.
The locations are relative to \fIpfp\fR.
.DS
.ta 1iR 1.6i
		arguments
	4	number of arguments
	2	return address
\fIpfp\fR \(->	0	previous \fIpfp\fR
	\-2	previous \fIefp\fR
	\-4	previous \fIgfp\fR
	\-6	previous \fIipc\fR
	\-8	previous source program line number
	\-10	previous source program file name
.DE
Expression and generator frames are always
contained wholly within a procedure frame,
and their respective frame pointers are cleared to zero
after being saved in the procedure marker.
.PP
The first argument to a procedure is located at 6(\fIpfp\fR),
the second at 10(\fIpfp\fR), and so on.
The first local variable is located at \-14(\fIpfp\fR),
the second at \-18(\fIpfp\fR), and so on.
.PP
Procedure markers created for functions and operators
do not contain the source program line number or file name,
since functions and operators do not change it.
Because they are C procedures,
their local variables are not descriptors
and are subject to C language conventions,
but everything above the marker (higher addresses)
is subject to Icon language conventions.
The location of the procedure marker for functions and operators
is considered the
.I boundary ,
mentioned in Section 3.2.
.sp 1
.SH
Expression Frames on the PDP-11
.PP
An expression frame limits the scope of backtracking.
No inactive generator outside the current expression frame
may be reactivated until evaluation of the current expression is complete.
The format of an expression marker is shown below;
locations are relative to
\fIefp\fR.
.DS
.ta 1iR 1.6i
\fIefp\fR \(->	0	previous \fIefp\fR
	\-2	previous \fIgfp\fR
	\-4	failure label for expression frame
.DE
When an expression frame is created,
the generator frame pointer is cleared after being saved
in the expression marker,
to indicate that there are no inactive generators that may
be reactivated while the new expression frame is current.
An expression frame extends from its expression marker
to the top of the stack.
Expression frames are not disjoint;
new frames are always nested within older ones.
.PP
When failure occurs within an expression and there
are no inactive generators to reactivate,
the expression frame is exited,
and control is transferred to the failure label.
If the failure label is null, however,
another failure occurs within the new expression frame,
and the logic is the same.
.PP
For limited expressions,
the limitation counter is contained in an Icon integer
just above the expression marker at 2(\fIefp\fR).
This counter is decremented each time the expression suspends a result.
.SH
Generator Frames on the PDP-11
.PP
Generator frames are augmented procedure frames.
A generator frame preserves the state of execution of a inactive generator.
When a suspending procedure calls
\fMpsusp\fR,
a generator marker is placed on the stack
to mark the point of suspension,
and the most recent expression frame
.I outside
the suspending procedure frame
(the expression frame that was current just prior to
invocation of the suspending procedure)
is then duplicated and pushed onto the stack.
The suspending procedure then returns,
so that the expression frame that was duplicated is current.
Thus, the generator frame is contained within the expression frame, and
.Q hides
the inactive generator.
The format of the generator marker is shown in the following table;
locations are shown relative to \fIgfp\fR.
.DS
.ta 1iR 1.6i
	10	reactivation address
	8	previous \fIpfp\fR
	6	previous \fIefp\fR
	4	previous \fIgfp\fR
	2	previous \fIipc\fR
\fIgfp\fR \(->	0	previous boundary address
	\-2	previous value of \fM&level\fR
	\-4	previous source program line number
	\-6	previous source program file name
.DE
The last five words of the generator marker
are actually part of a procedure marker,
created by the call to
\fMpsusp\fR.
Thus, the reactivation address is just the return address for
\fMpsusp\fR.
.PP
When a function or operator suspends,
there is a boundary that becomes hidden.
This boundary address needs to be restored upon reactivation.
It is also important to the garbage collector,
since the portion of a generator frame between the hidden
boundary and the generator marker does not have
the well-defined structure that is required.
.sp 2
.ce
\f3VAX-11 Stack Frame Formats\fR
.sp 2
.PP
The C frames on the VAX are variable in size and \fIap\fR is used
to facilitate access to the arguments.
.SH
Procedure Frames on the VAX-11
.PP
On the VAX-11, there is a program counter (\fIpc\fR),
a stack pointer (\fIsp\fR),
a frame pointer (\fIfp\fR), and
an argument pointer (\fIap\fR).
These pointers are registers \fIr15\fR, \fIr14\fR, \fIr13\fR, and \fIr12\fR,
respectively.
Icon uses \fIfp\fR for \fIpfp\fR, \fIr11\fR for \fIefp\fR, and
\fIr10\fR for \fIgfp\fR.
.PP
The procedure frame for the VAX-11 is:
.DS
.ta 1iR 1.6i
		arguments
	4	number of arguments
\fIap\fR \(->	0	number of words in the argument list
	\-4	previous \fIefp\fR
	\-8	previous \fIgfp\fR
		.\^.\^.
	16	previous \fIpc\fR
	12	previous \fIfp\fR
	8	previous \fIap\fR
	4	program status word and register mask
\fIfp\fR \(->	0	0 (condition handler status)
	\-4	previous source program line number
	\-8	previous source program file name
		local variables
.DE
The first argument is at 8(\fIap\fR), the second argument is at
16(\fIap\fR), and so on. The first local variable is at \-16(\fIfp\fR)\fR,
the second local variable is at \-24(\fIfp\fR), and so on.
.SH
Expression Frames on the VAX-11
.PP
The expression frame marker for the VAX-11 is:
.DS
.ta 1iR 1.6i
\fIefp\fR \(->	0	previous \fIefp\fR
	\-4	previous \fIgfp\fR
	\-8	failure label for expression frame
.DE
.SH
Generator Frames on the VAX-11
.PP
The generator frame marker for the VAX-11 is:
.DS
.ta 1iR 1.6i
		previous \fIefp\fR
		previous \fIgfp\fR
		.\^.\^.
		last saved register
	20	reactivation address
	16	previous \fIfp\fR
	12	previous \fIap\fR
	8	program status word and register mask
	4	0 (condition handler address)
\fIgfp\fR \(->	0	previous boundary address
	\-4	previous value of \fM&level\fR
	\-8	previous source program line number
	\-12	previous source program file name
.DE
.bp
.ce 10
\f3Appendix F \(em Sample Functions\fR
.ce 0
.sp 1
.PP
The following routines are examples of the source code
for Icon functions.
As indicated in the report,
each routine consists of a C procedure that performs the indicated
function and a procedure block linking the C procedure with
the Icon procedure invocation mechanism.
.PP
The first example is the code for the routine \fMwrite\fR,
as supplied with the Icon distribution, and is included
to show how a routine is written to handle a variable number
of arguments.
.Ds
.ta 3.5i
#include "../h/rt.h"

/*
 * write(a,\*bb,\*b...) - write arguments.
 */

Xwrite(nargs)
int nargs;
   {
   register int n;
   char sbuf\^[MAXSTRING];
   struct descrip arg;
   FILE *f;

   f = stdout;
   arg = nullstr;

   for (n = 1; n \*(<= nargs; n++) {
      arg = ARG(n);
      DeRef(arg);	/* dereference arguments */
.De
.Ds
.ta 3.5i
      if (!QUAL(arg) && TYPE(arg) == T_FILE) {
         if (n > 1) {
            putc('\en', f);
            fflush(f);
            }
         if ((BLKLOC(arg)->file.status & FS_WRITE) == 0)
            runerr(213, &arg);
         f = BLKLOC(arg)->file.fd;
         arg = nullstr;
         }
      else {
         if (n == 1 && (k_output.status & FS_WRITE) == 0)
            runerr(213, NULL);
         defany(&arg, &nullstr);
         if (cvstr(&arg, sbuf) == NULL)
            runerr(109, &arg);
         putstr(f, STRLOC(arg), STRLEN(arg));
         }
      }
.De
.Ds
.ta 3.5i
   putc('\en', f);
   fflush(f);
   if (STRLOC(arg) \*(>= sbuf && STRLOC(arg) < sbuf + MAXSTRING) {
      sneed(STRLEN(arg));
      STRLOC(arg) = alcstr(STRLOC(arg), STRLEN(arg));
      }
   ARG(0) = arg;
   }

Procblock(write,\*b-1)
.De
The \-1 in the \fMProcblock\fR macro indicates that \fMwrite\fR
takes an arbitrary number of arguments.
.PP
The following two routines are examples of
typical functions that could
be added to the run-time system using the technique described
in Section 4.
.PP
The first of these routines, \fMseek\fR, interfaces to the C
library routine \fMfseek\fR.
.Ds
.Ta 3.5i
#include "../h/rt.h"

/*
 * seek(file,\*boffset,\*bstart) - seek to offset byte from start in file.
 */

Xseek(nargs, arg3, arg2, arg1, arg0)
int nargs;
struct descrip arg3, arg2, arg1, arg0;
   {
   long l1, l2;
   int status;
   FILE *fd;
   long ftell();

   DeRef(arg1);
   if (arg1.type != D_FILE)
      runerr(106);
.Dd
   defint(&arg2, &l1, 0);
   defshort(&arg3, 0);

   fd = BLKLOC(arg1)->file.fd;

   if ((BLKLOC(arg1)->file.status == 0) ||
       (fseek(fd, l1, arg3.value.integer) == -1))
      fail();
   mkint(ftell(fd), &arg0);
   }

Procblock(seek,\*b3)
.De
The argument 3 in the \fMProcblock\fR macro indicates that
\fMseek\fR takes three arguments.
.PP
The routine \fMgetenv\fR provides access to
shell environment variables through the C library procedure \fMgetenv\fR.
.Ds
.ta 3.5i
#include "../h/rt.h"

/*
 * getenv(s) - return contents of environment variable s
 */

Xgetenv(nargs, arg1, arg0)
int nargs;
struct descrip arg1, arg0;
   {
   register char *p;
   register int len;
   char sbuf\^[MAXSTRING];

   DeRef(&arg1);
.Dd
.ta 3.5i
   if (!QUAL(arg1))	/* check legality of argument */
      runerr(103, &arg1);
   if (STRLEN(arg1) \*(<= 0 || STRLEN(arg1) \*(>= MAXSTRING)
      runerr(401, &arg1);
   qtos(&arg1, sbuf);	/* convert argument to C-style string */

   if ((p = getenv(sbuf)) != NULL) {	/* get environment variable */
      len = strlen(p);
      sneed(len);
      STRLEN(arg0) = len;
      STRLOC(arg0) = alcstr(p, len);
      }
   else	/* fail if variable not in environment */
      fail();
   }

Procblock(getenv,\*b-1)
.De