Some of the operators are of the form $x where x is one of the following:
{plus, minus, div, mult, mod, le, lt, eq, ne, gt, ge, and, or, not, max, min, size, bits, bytes, units, words, first, last, dot, assign, uparrow, leftSideuparrow, extractId, selectId, apply, index, cons};
ConcatCode: PROC[c1, c2: Code] RETURNS[Code];
CopyCode: PROC [Code] RETURNS [Code];
CodeToDoUnpopedCond: PROC[test, trueCase, falseCase: Code] RETURNS[Code];
CodeToPop: PROC[nPops: INT] RETURNS[Code];
CodeToDup: PROC RETURNS [Code];
NullCode: PROC RETURNS[Code];
CodeToLoadGlobalFrame: PROC [name: Rope.ROPE, nToSkip: INT] RETURNS [Code];
CodeToLoadNameScope:
PROC
RETURNS[Code];
Pushes the current name scope on top the stack
CodeToGetNameContext:
PUBLIC
PROC[scopeIndex:
CARDINAL]
RETURNS[Code];
Replaces the top of stack (a name scope) with the particular name context node specified by scopeIndex.
CodeToLoadContentsOfAMNode:
PROC[node: Node]
RETURNS[Code];
Pushes the contents of the node on top of the stack.
CodeToLoadAMNode:
PROC[node: Node]
RETURNS[Code];
Pushes the node on top of the stack.
CodeToMakeAMNode:
PROC[sourceType: Type]
RETURNS[Code];
replaces the top value on the stack with an amNode holding that value.
CodeToCoerce:
PROC[sourceType, targetType: Type]
RETURNS[Code];
replaces the top value on the stack with another value of a different type.
CodeToDoBinaryOp:
PROC[op: Operator, left, right: Type]
RETURNS[Code];
Replaces the top two values on the stack with a value computed from the given values. op is one of {plus, minus, div, mult, mod, le, lt, eq, ne, gt, ge, max, min}. The argument types are left and right.
CodeToDoUnaryOp:
PROC[op: Operator, type: Type]
RETURNS[Code];
replaces the top value on the stack with a value computed from the given value. op is one of {plus, minus}. The argument type is type.
CodeToBuildRecord:
PROC[nFields:
INT, rcdType: Type]
RETURNS[Code];
replace the top n values on the stack with a record containing those values.
CodeToStoreUnpopped:
PROC[indirectType: Type, sourceType: Type]
RETURNS[Code];
stores the top value on the stack at the location specified by the second value on the stack (assumed to be an indirect). Replaces the top two values on the stack with the top value.
CodeToLoadThroughIndirect:
PROC[indirectType: Type]
RETURNS[Code];
replaces the top value (assumed to be an indirect) with the contents of its target.
CodeToExtractField:
PROC[id: Rope.
ROPE, type: Type]
RETURNS[Code];
replaces the top value (assumed to have a field structure including the named field) with the contents of the named field.
CodeToSelectField:
PROC[id: Rope.
ROPE, indirectType: Type]
RETURNS[Code];
replaces the top value (assumed to be an indirect with a field structure including the named field) with an indirect to the named field.
CodeToDoApply:
PROC[operatorType: Type, operandType: Type]
RETURNS[Code];
Applies the operator (assumed to be one down in the stack) to the operand (assumed to be the top of the stack). Replaced these top two values of the stack with the result of the application. [apply is used for procedures, signals, errors, arrays, array descriptors, and sequences.]
CodeToDoIndex:
PROC[indirectOperatorType: Type, operandType: Type]
RETURNS[Code];
Applies the operator (assumed to be one down in the stack) to the operand (assumed to be the top of the stack). Replaced these top two values of the stack with the result of the application. [index is used for indirects to arrays, array descriptors, and sequences. It returns an indirect to the indexed entry.]
CodeToSelectNestedBlock:
PROC[set: INT, depth:
INT, indirectType: Type]
RETURNS[Code];
Only applies to frames. Assumes that the top of the stack holds an indirect to a frame. The result is the block that is nested depth levels from the outermost. That is, depth=0 produces the outermost block of local variables. (The args and results records may be obtained by using CodeToSelectField["&args", ..] or CodeToSelectField["&results", ..].)
The first argument selects between enumeration constant blocks (set = 1) and variable blocks (set = 0).
and here is the interpreter
Interpret: PROC[code: Code, cc: CC, debug: IO.STREAM ← NIL] RETURNS[Node];
The interpreter works with nodes. (Node is declared in CirioTypes.)
CreateCedarNode: PROC[ops: REF OperationsBody, type: Type, data: REF ANY] RETURNS[Node];
GetTypeOfNode: PROC[node: Node] RETURNS[Type];
most nodes just return their type. Indirects to unions check their current target type and return an appropriate indirect type. This type is very fleeting. Should only be used under appropriate controls by the interpreter.
GetCurrentTypeOfNode: PROC[node: Node, cc: CC] RETURNS[Type];
GetDataFromNode: PROC[node: Node] RETURNS[REF ANY];
Coerce:
PROC[sourceType, targetType: Type, node: Node, cc:
CC]
RETURNS[Node];
First checks for Conforms[GetTypeOfNode[node], sourceType] and Conforms[sourceType, targetType]. If both hold, then node is returned. If not, then then node.ops.coerce[sourceType, targetType, node, cc] is returned.
Comment: it is not clear what the rules are on which nodes have to provide which operations. Usually an operation need be provided only if the associated type generates code that provokes it. However, getCurrentType is envoked during an AMNodeSelectField. Hence, it seems that whenever selectField is needed, then getCurrentType is also needed.
OperationsBody: TYPE = CirioTypes.OperationsBody;
Some of these object procs are directly available
AdvanceNameScope: PROC [node: Node, cc: CC] RETURNS [Node];
ExamineParseTree: PROC[node: Node, cc: CC] RETURNS[ParseTree];
ApplyBinaryOp: PROC[op: Operator, leftType, rightType: Type, leftNode, rightNode: Node, cc: CC] RETURNS[Node];
ApplyUnaryOp: PROC[op: Operator, type: Type, node: Node, cc: CC] RETURNS[Node];
StoreThroughIndirectNode: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC];
LoadThroughIndirectNode:
PROC[indirectType: Type, indirectNode: Node, cc:
CC]
RETURNS[Node];
some implementations may choose to retain the indirect representation of the contents of the node. One can force a pure copy by using the following routine.
ForceNodeIn:
PROC[type: Type, node: Node, cc:
CC]
RETURNS[Node];
Some implementations of nodes that are supposed to be pure values are really holding an indirect to the value. This procedure returns a node that holds a pure instance of the value, creating one if needed, otherwise returning the original node.
ExtractFieldFromNode: PROC[id: Rope.ROPE, type: Type, node: Node, cc: CC] RETURNS[Node];
SelectFieldFromNode: PROC[id: Rope.ROPE, indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node];
ShowNode: PROC[to: IO.STREAM, node: Node, depth, width: INT, cc: CC];
ShowNodeBracketed: PROC[to: IO.STREAM, node: Node, depth, width: INT, cc: CC];
BreakShowNode: PROC[to: IO.STREAM, node: Node, depth, width: INT, cc: CC, sep: Rope.ROPE ← NIL];
GetNodeRepresentation:
PROC[node: Node, cc:
CC]
RETURNS[
REF
ANY];
This operation is only supplied by some nodes and it is implementation dependent. That is, even for a single type, the structure of returned representation may depend upon the target world to which the value belongs.