.op "INITIALIZER_OP          26"
int 26
int mode
tree expression
tree next_initializer
.bd
Initializers are the initial-value expressions that appear in
definitions of variables in C (see DEFINE_DYNM_OP and DEFINE_STAT_OP).
In the case of local variables, which are reinitialized whenever they
are allocated, these expressions are arbitrary.
In the case of static variables, these expressions must be constants
or REFTO operators whose operands are constants or OBJECT_OPs.
.sp
Initializers are formed by linking a number of INITIALIZER_OPs and
ZERO_INITIALIZER_OPs together through their 'next_initializer' fields.
ZERO_INITIALIZER_OP is a compact representation of an
initializer consisting of all zeros.
.sp
Any mode is allowable in an INITIALIZER.
INT and UNSIGNED initializers cause one word to be filled;
LONG INT, LONG UNSIGNED, and FLOAT cause two words to be filled;
LONG FLOAT causes four words to be filled;
STOWED expressions fill as many words as the size of the expression
allows (STOWED mode CONST_OPs are particularly useful here).
.bx
Example:  int ai[3] = {1, 2, 3}
          (a local declaration, where ai is assigned object id 8)
         13          DEFINE_DYNM_OP
         8              Object has id 8
         26             INITIALIZER_OP
         1                 INT_MODE
         9                 CONST_OP (the init. expression)
         1                    INT_MODE
         1                    Constant has length 1
         1                    Constant has value 1
         26                INITIALIZER_OP
         1                    INT_MODE
         9                    CONST_OP
         1                       INT_MODE
         1                       Constant has length 1
         2                       Constant has value 2
         26                   INITIALIZER_OP
         1                       INT_MODE
         9                       CONST_OP
         1                          INT_MODE
         1                          Constant has length 1
         3                          Constant has value 3
         39                      NULL_OP (end of initializers)
         3              Object has size 3 words

As an alternative,

         13          DEFINE_DYNM_OP
         8              Object has id 8
         26             INITIALIZER_OP
         7                 STOWED_MODE
         9                 CONST_OP
         7                    STOWED_MODE
         3                    Constant is 3 words long
         1                    First word is 1
         2                    Second word is 2
         3                    Third word is 3
         39                NULL_OP (end of initializers)
         3              Object is 3 words long
.ex
.op "LABEL_OP                27"
int 27
int object_id
.bd
LABEL_OP is used to place the target label for 'goto' statements.
The parameter 'object_id' is the integer identifier used by GOTO_OPs
to identify their target labels.
.bx
Example:  label lab;.... lab:
          (assume the label declaration causes 'lab' to be assigned
          the object id 6)
         27          LABEL_OP
         6              The object ID of the label
.ex
.op "LE_OP                   28"
int 28
int mode
tree left
tree right
.bd
The result of this operator is an rvalue, 1 if the value of the left
operand is less than or equal to the value of the right, 0 otherwise.
Both operands must have the mode specified by the parameter 'mode';
STOWED mode is not allowable.
Note that LE [ul always] returns a value of mode INTEGER.
Magnitude comparisons are generated for unsigned operands, to insure
correct results.
.sp
Use LE_OP to implement all tests for less-than-or-equal-to,
whether they appear in boolean expressions or flow-of-control tests.
The restriction against STOWED operands may be lifted if the author
feels sufficiently threatened.
.bx
Example:  i <= 1 (where i is an integer object with id 12)

         28       LE_OP
         1           INT_MODE
         40          OBJECT_OP
         1              INT_MODE
         12             Object id 12
         9           CONST_OP
         1              INT_MODE
         1              Constant has length 1
         1              Constant has value 1
.ex
.op "LSHIFTAA_OP             29"
int 29
int mode
tree left
tree right
.bd
The result of this operator is an rvalue,
the value of the left operand shifted logically (zero-fill) left the
number of bit places specified by the value of the right operand.
As a side effect, the result is stored back into the left operand.
The left operand must be an lvalue or a bit field (see FIELD_OP).
The operation mode may be INT, LONG INT, UNSIGNED, or LONG UNSIGNED,
and the left operand must have the same mode.
The right operand must be of mode INT or UNSIGNED, and really should
have a value between 0 and the length of the left operand, inclusive.
(Reasonable results outside this range are not guaranteed.)
.sp
LSHIFTAA stands for "left-shift and assign."
The operator is used to implement "<<=" in C.
.bx
Example:  i <<= 1 (where i is an integer object with id 12)

         29       LSHIFTAA_OP
         1           INT_MODE
         40          OBJECT_OP
         1              INT_MODE
         12             Object id 12
         9           CONST_OP
         1              INT_MODE
         1              Constant has length 1
         1              Constant has value 1
.ex
.op "LSHIFT_OP               30"
int 30
int mode
tree left
tree right
.bd
The result of this operator is an rvalue,
the value of the left operand shifted left logically (zero-fill)
the number of bit places specified by the value of the right operand.
The operation mode may be INT, LONG INT, UNSIGNED, or LONG UNSIGNED,
and the left operand must have the same mode.
The right operand must be of mode INT or UNSIGNED, and really should
have a value between 0 and the length of the left operand, inclusive.
(Reasonable results outside this range are not guaranteed.)
.sp
LSHIFT is used to implement the "<<" operator in C.
.bx
Example:  i << 1 (where i is an integer object with id 12)

         30       LSHIFT_OP
         1           INT_MODE
         40          OBJECT_OP
         1              INT_MODE
         12             Object id 12
         9           CONST_OP
         1              INT_MODE
         1              Constant has length 1
         1              Constant has value 1
.ex
.op "LT_OP                   31"
int 31
int mode
tree left
tree right
.bd
The result of this operator is an rvalue,
1 if the value of the left operand is less than the value of the right,
0 otherwise.
Both operands must have the mode given in the parameter 'mode'.
Note that LT always returns a value of mode INTEGER, no matter what
the operation mode was.
The operation mode may not be STOWED.
Magnitude comparisons are used if the operands are unsigned, to insure
correct results.
.sp
LT is used to implement the test for less-than, in both Boolean expressions
and flow-of-control expressions.
The restriction against STOWED operands may be removed if an angry
armed mob storms the author's office.
.bx
Example:  i < 1 (where i is an integer object with id 12)

         31       LT_OP
         1           INT_MODE
         40          OBJECT_OP
         1              INT_MODE
         12             Object id 12
         9           CONST_OP
         1              INT_MODE
         1              Constant has length 1
         1              Constant has value 1
.ex
.op "MODULE_OP               32"
int 32
.bd
This operator is not used in procedure definitions;
it is used strictly to separate modules in input streams.
.bx
.ex
.op "MULAA_OP                33"
int 33
int mode
tree left
tree right
.bd
The result of this operation is an rvalue, the product of the value
of the left operand and the value of the right.
As a side effect, the product is stored into the left operand.
The left operand must be an lvalue or a bit field.
Both operands must have the same mode as the operation, and that
mode may not be STOWED.
.sp
MULAA stands for "multiply and assign."
It is used to implement the multiplication assignment operators
("*=" in C, "*:=" or "mulab" in Algol 68).
When either operand is known to be a power of 2, the multiplication
will be replaced by a left logical shift.
.bx
Example:  i *= 10 (where i is an integer object with id 12)

         33       MULAA_OP
         1           INT_MODE
         40          OBJECT_OP
         1              INT_MODE
         12             Object id 12
         9           CONST_OP
         1              INT_MODE
         1              Constant has length 1
         10             Constant has value 10
.ex
.op "MUL_OP                  34"
int 34
int mode
tree left
tree right
.bd
The result of this operation is an rvalue, the product of the value
of the left operand and the value of the right.
Both operands must have the same mode as the operation, and that
mode may not be STOWED.
.sp
MUL_OP is used to implement simple multiplication.
When either operand is known to be a power of 2, the multiplication
will be replaced by a left logical shift.
.bx
Example:  i * 2 (where i is an integer object with id 12)

         34       MUL_OP
         1           INT_MODE
         40          OBJECT_OP
         1              INT_MODE
         12             Object id 12
         9           CONST_OP
         1              INT_MODE
         1              Constant has length 1
         2              Constant has value 2
.ex
.op "NEG_OP                  35"
int 35
int mode
tree operand
.bd
The result of this operator is an rvalue, the additive inverse
of the value of the operand.
Unsigned operands are subtracted from 2**n, where n is the number of
bits used to represent them (16 or 32, in this implementation).
The operation mode must be the same as the mode of the operand,
and may not be STOWED.
.sp
NEG_OP implements the unary minus (negation) operator for all the
primitive arithmetic data modes.
.bx
Example:  -i   (where i is an integer object with id 12)

         35       NEG_OP
         1           INT_MODE
         40          OBJECT_OP
         1              INT_MODE
         12             Object has id 12
.ex
.op "NEXT_OP                 36"
int 36
int levels
.bd
NEXT_OP yields no result value, but
causes an immediate restart of a particular enclosing
loop.
'Levels' - 1 enclosing loops are terminated (see BREAK_OP) and then
a branch is taken to the proper restart point in the next enclosing loop.
For the FOR_LOOP, the restart point is the re-initialization statement
at the end of the body.
For DO_LOOPs and WHILE_LOOPs, the restart point is the evaluation of
the iteration condition.
.bx
Example:  next 2 (break 1 loop, continue the next outermost)

         36       NEXT_OP
         2           Levels
.ex
.op "NE_OP                   37"
int 37
int mode
tree left
tree right
.bd
The result of this operator is an rvalue, 1 if the value of the left
operand does not equal the value of the right, 0 otherwise.
The modes of both operands must match the mode of the operation,
and STOWED mode is not allowed.
Note that NE_OP always returns a value of mode INTEGER, no matter what
operation mode is specified.
.sp
NE implements the test for inequality in all contexts.
Use of nuclear weapons might be enough to convince the author to
lift the restriction against STOWED operands.
.bx
Example:  i <> 1 (where i is an integer object with id 12)

         37       NE_OP
         1           INT_MODE
         40          OBJECT_OP
         1              INT_MODE
         12             Object id 12
         9           CONST_OP
         1              INT_MODE
         1              Constant has length 1
         1              Constant has value 1
.ex
.op "NOT_OP                  38"
int 38
int mode
tree operand
.bd
The result of this operator is an rvalue, the logical negation of
the operand value.
(Ie, if the operand has value zero, the result of the NOT_OP will be
1; if the operand is non-zero, the result of the NOT_OP will be zero.)
The mode of the operand must be the same as the mode of the operation,
and STOWED mode is not allowed.
The result of a NOT_OP is [ul always] of mode INTEGER, no matter what the
operation mode.
.sp
NOT_OP is normally used to implement Boolean negation.
For bitwise complementation, use COMPL_OP.
.bx
Example:  !i   (where i is an integer object with id 12)

         38       NOT_OP
         1           INT_MODE
         40          OBJECT_OP
         1              INT_MODE
         12             Object has id 12
.ex
.op "NULL_OP                 39"
int 39
.bd
The null operator is usually used to terminate lists constructed with
the sequence operator SEQ_OP,
or to indicate that a subtree has been omitted.
For example, if a conditional has no else_part, the missing subtree
must be represented by a NULL_OP.
SEQ also acts as a delimiter at several places in the input stream.
.bx
Example:
         39       NULL_OP
.ex
.op "OBJECT_OP               40"
int 40
int mode
int object_id
.bd
The result of this operator is an lvalue, corresponding to a variable
defined by the front end.
'Mode' is unrestricted; objects may have any primitive data mode,
including STOWED (for arrays and records).
The 'object_id' parameter gives the identification number that was
supplied in the definition or declaration of the object.
.sp
Normally, each occurrence of a variable in the source program produces
an OBJECT_OP in the intermediate form.
OBJECTs are the primitive lvalues from which all other lvalue-producing
constructs are derived.
.sp
Each object that is referenced in the intermediate form must be identified
by a simple integer known as the "object id."
Typically these ids are assigned at declaration time (for variables)
or at time of first reference (for locations, like procedure names or
statement labels).
Object ids should be unique within each IMF module.
.bx
Example:  i  (where i is an integer object, with object id 12)

         40       OBJECT_OP
         1           INT_MODE
         12          Object id 12
.ex
.op "ORAA_OP                 41"
int 41
int mode
tree left
tree right
.bd
The result of this operator is an rvalue, the bitwise inclusive-or
of the values of the left and right operands.
As a side effect, the result is stored back into the left operand.
The left operand must be an lvalue or a bit field (see FIELD_OP).
The operation mode must be INT, LONG INT, UNSIGNED, or LONG UNSIGNED,
and the modes of both operands must match the operation mode.
.sp
ORAA stands for "logical or and assign."
It is used to implement the C assignment operator "|=".
.bx
Example:  i |= 1 (where i is an integer object with id 12)

         41       ORAA_OP
         1           INT_MODE
         40          OBJECT_OP
         1              INT_MODE
         12             Object id 12
         9           CONST_OP
         1              INT_MODE
         1              Constant has length 1
         1              Constant has value 1
.ex
.op "OR_OP                   42"
int 42
int mode
tree left
tree right
.bd
The result of this operator is an rvalue, the bitwise inclusive-or of
the values of the left and right operands.
The operation mode must be INT, LONG INT, UNSIGNED, or LONG UNSIGNED,
and the modes of both operands must match the operation mode.
.sp
OR is used to implement bit-oriented logical operations, like the
"|" operator of C.
Although OR can be used in Boolean expressions, the sequential-OR
operator SOR_OP is usually more appropriate.
.bx
Example:  i | 1 (where i is an integer object with id 12)

         42       OR_OP
         1           INT_MODE
         40          OBJECT_OP
         1              INT_MODE
         12             Object id 12
         9           CONST_OP
         1              INT_MODE
         1              Constant has length 1
         1              Constant has value 1
.ex
.op "POSTDEC_OP              43"
int 43
int mode
tree left
tree right
.bd
The result of this operator is an rvalue, the value of the left operand
before the operator is executed.
As a side effect, the left operand is decremented by the value of the
right operand.
The left operand must be an lvalue or a bit field (see FIELD_OP),
and must have the same mode as the operation.
The right operand must be a CONST_OP, with the same mode as the operation.
.sp
The POSTDEC operator corresponds to the C postfix autodecrement construct.
.bx
Example:  p--  (where p is a long unsigned (pointer) object with
               object id 15, and p is intended to point to integers)

         43       POSTDEC_OP
         4           LONG_UNS_MODE
         40          OBJECT_OP
         4              LONG_UNS_MODE
         15             Object id of p
         9           CONST_OP
         4              LONG_UNS_MODE
         2              Constant has length 2
         0              Constant has value...
         1              ...1, expressed as a long integer
.ex
.op "POSTINC_OP              44"
int 44
int mode
tree left
tree right
.bd
The result of this operator is an rvalue, the value of the left operand
before the operator is executed.
As a side effect, the left operand is incremented by the value of the
right operand.
The left operand must be an lvalue or a bit field (see FIELD_OP),
and must have the same mode as the operation.
The right operand must be a CONST_OP, with the same mode as the operation.
.sp
The POSTINC operator corresponds to the C postfix autoincrement construct.
.bx
Example:  p++  (where p is a long unsigned (pointer) object with
               object id 15, and p is intended to point to integers)

         44       POSTINC_OP
         4           LONG_UNS_MODE
         40          OBJECT_OP
         4              LONG_UNS_MODE
         15             Object id of p
         9           CONST_OP
         4              LONG_UNS_MODE
         2              Constant has length 2
         0              Constant has value...
         1              ...1, expressed as a long integer
.ex
.op "PREDEC_OP               45"
int 45
int mode
tree left
tree right
.bd
The result of this operator is an rvalue, the value of the left operand
decremented by the value of the right operand.
As a side effect, the result is stored back into the left operand.
The left operand must be an lvalue or a bit field (see FIELD_OP),
and must have the same mode as the operation.
The right operand must be a CONST_OP, with the same mode as the operation.
.sp
The PREDEC operator corresponds to the C prefix autodecrement construct.
.bx
Example:  --p  (where p is a long unsigned (pointer) object with
               object id 15, and p is intended to point to integers)

         45       PREDEC_OP
         4           LONG_UNS_MODE
         40          OBJECT_OP
         4              LONG_UNS_MODE
         15             Object id of p
         9           CONST_OP
         4              LONG_UNS_MODE
         2              Constant has length 2
         0              Constant has value...
         1              ...1, expressed as a long integer
.ex
.op "PREINC_OP               46"
int 46
int mode
tree left
tree right
.bd
The result of this operator is an rvalue, the value of the left operand
incremented by the value of the right operand.
As a side effect, the result is stored back into the left operand.
The left operand must be an lvalue or a bit field (see FIELD_OP),
and must have the same mode as the operation.
The right operand must be a CONST_OP, with the same mode as the operation.
.sp
The PREINC operator corresponds to the C prefix autoincrement construct.
.bx
Example:  ++p  (where p is a long unsigned (pointer) object with
               object id 15, and p is intended to point to integers)

         46       PREINC_OP
         4           LONG_UNS_MODE
         40          OBJECT_OP
         4              LONG_UNS_MODE
         15             Object id of p
         9           CONST_OP
         4              LONG_UNS_MODE
         2              Constant has length 2
         0              Constant has value...
         1              ...1, expressed as a long integer
.ex
.op "PROC_CALL_ARG_OP        47"
int 47
int mode
tree expression
tree next_argument
.bd
Procedure call arguments are specified in a linked list of
PROC_CALL_ARG_OPs attached to a PROC_CALL_OP.
An argument expression is specified by the parameter 'expression';
its mode must be given by the parameter 'mode'.
The parameter 'next_argument' is simply the next procedure argument in
the list.
Any mode expression is allowable as an argument, since the Prime
procedure call convention passes a fixed-size pointer to the actual
argument, rather than the argument itself.
.sp
Note that arguments (with the exception of bit fields) are always passed
by reference.
If arguments are to be copied on procedure entry or exit, the [ul called]
procedure must do the copying.
(See PROC_DEFN_ARG_OP; an argument will be copied automatically if it
is given the disposition VALUE_DISP.)
Bit fields are an exception; they are not addressable objects, and so
are always passed by value.
.sp
See PROC_CALL_OP for examples of PROC_CALL_ARG_OP.