OperandDescriptor: 
TYPE = 
RECORD[
type: CSEIndex,  -- type of operand
attr: Attr];  -- attributes
 
RStack: TYPE = RECORD [SEQUENCE length: NAT OF OperandDescriptor];
rStack: REF RStack ← NIL;
rI: INTEGER;   -- index into rStack
RPush: 
PUBLIC 
PROC [type: CSEIndex, attr: Attr] = {
rI ← rI + 1;
WHILE rI >= rStack.length 
DO
newLength: NAT = rStack.length + 16;
newStack: REF RStack = NEW[RStack[newLength]];
FOR i: INTEGER IN [0 .. rI) DO newStack[i] ← rStack[i] ENDLOOP;
rStack ← newStack;
ENDLOOP;
 
rStack[rI] ← [type:type, attr:attr]};
 
RPop: PUBLIC PROC = {IF rI < 0 THEN ERROR; rI ← rI-1};
RType: PUBLIC PROC RETURNS [CSEIndex] = {RETURN [rStack[rI].type]};
RAttr: PUBLIC PROC RETURNS [Attr] = {RETURN [rStack[rI].attr]};
longUnsigned: CSEIndex; -- a hint for mwconst
textType: ARRAY TextForm OF CSEIndex;  -- a hint for text literals
ExpInit: 
PUBLIC 
PROC = {
implicit ← [type: typeANY, tree: Tree.Null, attr: emptyAttr];
P3S.implicitRecord ← RecordSENull;
own ← dataPtr.ownSymbols; -- make a parameter?
longUnsigned ← CSENull;  textType ← ALL[CSENull];
rStack ← NEW[RStack[32]];
rI ← -1};
 
ExpReset: 
PUBLIC 
PROC = {
IF rStack # NIL THEN rStack ← NIL;
};
 
 
MakeNumeric: 
PROC [type: CSEIndex] 
RETURNS [CSEIndex] = {
RETURN [
SELECT seb[type].typeTag 
FROM
long => MakeLongType[dataPtr.typeINT, type],
ENDCASE => dataPtr.typeINT]};
 
 
EvalNumeric: 
PROC [t: Tree.Link] 
RETURNS [val: Tree.Link] = {
val ← GenericRhs[t, dataPtr.typeINT];
SELECT NormalType[rStack[rI].type] 
FROM
dataPtr.typeINT => NULL;
typeANY => rStack[rI].type ← MakeNumeric[rStack[rI].type];
ENDCASE => Log.ErrorTree[typeClash, val];
 
RETURN};
 
ArithOp: 
PROC [node: Tree.Index] = {
OPEN tb[node];
saveNP: NPUse;
son[1] ← EvalNumeric[son[1]];  saveNP ← phraseNP;
son[2] ← EvalNumeric[son[2]]; 
BalanceAttributes[node];
rStack[rI-1].attr ← And[rStack[rI-1].attr, rStack[rI].attr];
IF attr1 THEN rStack[rI-1].attr.const ← FALSE;
RPop[];  phraseNP ← MergeNP[saveNP][phraseNP]};
 
ArithType: 
PROC [type: CSEIndex] 
RETURNS [CSEIndex] = {
type ← NormalType[type];
RETURN [
WITH seb[type] 
SELECT 
FROM
relative => NormalType[UnderType[offsetType]],
ENDCASE => type]};
 
 
Plus: 
PROC [node: Tree.Index] = {
OPEN tb[node];
type: CSEIndex;
lr: BOOL;
saveNP: NPUse;
son[1] ← GenericRhs[son[1], typeANY];  saveNP ← phraseNP;
type ← ArithType[rStack[rI].type];
IF seb[type].typeTag = ref 
OR type = dataPtr.typeCHAR 
THEN {
IF RCType[type] # none THEN Log.ErrorTree[typeClash, son[1]];
lr ← TRUE; son[2] ← EvalNumeric[son[2]]}
 
ELSE {
SELECT type 
FROM
dataPtr.typeINT, typeANY => NULL;
ENDCASE => Log.ErrorTree[typeClash, son[1]];
 
son[2] ← GenericRhs[son[2], typeANY];
lr ← FALSE;  type ← ArithType[rStack[rI].type];
SELECT 
TRUE 
FROM
type = dataPtr.typeINT, type = dataPtr.typeCHAR => NULL;
seb[type].typeTag = ref =>
IF RCType[type] # none THEN Log.ErrorTree[typeClash, son[2]];
 
ENDCASE => {
IF type # typeANY THEN Log.ErrorTree[typeClash, son[2]];
rStack[rI].type ← MakeNumeric[rStack[rI].type]}};
 
 
 
IF P3S.safety = checked 
AND seb[type].typeTag = ref 
THEN
Log.ErrorNode[unsafeOperation, node];
 
BalanceAttributes[node];
rStack[rI-1].attr ← And[rStack[rI-1].attr, rStack[rI].attr];
IF attr1 THEN rStack[rI-1].attr.const ← FALSE;
IF ~lr THEN rStack[rI-1].type ← rStack[rI].type;
RPop[];  phraseNP ← MergeNP[saveNP][phraseNP]};
 
Minus: 
PROC [node: Tree.Index] = {
OPEN tb[node];
type, lType, rType: CSEIndex;
lr: BOOL;
saveNP: NPUse;
son[1] ← GenericRhs[son[1], typeANY];  saveNP ← phraseNP;
type ← NormalType[rStack[rI].type]; lType ← ArithType[type];  lr ← TRUE;
IF seb[lType].typeTag = ref 
OR lType = dataPtr.typeCHAR 
THEN {
IF RCType[lType] # none THEN Log.ErrorTree[typeClash, son[1]];
son[2] ← GenericRhs[son[2], typeANY];  rType ← ArithType[rStack[rI].type];
SELECT 
TRUE 
FROM
rType = typeANY => NULL;
Types.Equivalent[[own, lType], [own, rType]] => lr ← FALSE;
rType = dataPtr.typeINT => NULL;
ENDCASE => Log.ErrorTree[typeClash, son[2]]}
 
 
ELSE {
SELECT type 
FROM
dataPtr.typeINT, typeANY => NULL;
ENDCASE => {Log.ErrorTree[typeClash, son[1]]; rStack[rI].type ← typeANY};
 
son[2] ← EvalNumeric[son[2]]};
 
IF P3S.safety = checked 
AND seb[lType].typeTag = ref 
THEN
Log.ErrorNode[unsafeOperation, node];
 
BalanceAttributes[node];
rStack[rI-1].attr ← And[rStack[rI-1].attr, rStack[rI].attr];
IF attr1 THEN rStack[rI-1].attr.const ← FALSE;
IF ~lr 
THEN rStack[rI-1].type ←
IF attr2 THEN MakeLongType[dataPtr.typeINT, rStack[rI].type] ELSE dataPtr.typeINT;
 
RPop[];  phraseNP ← MergeNP[saveNP][phraseNP]};
 
UnaryOp: 
PROC [node: Tree.Index] = {
IF UniOperand[node] 
THEN {
tb[node].son[1] ← EvalNumeric[tb[node].son[1]];  SetAttributes[node];
IF tb[node].attr1 THEN rStack[rI].attr.const ← FALSE}};
 
 
EnumOp: 
PROC [node: Tree.Index, target: CSEIndex] = {
IF UniOperand[node] 
THEN {
tb[node].son[1] ← GenericRhs[tb[node].son[1], target];  SetAttributes[node];
IF ~IndexType[RType[]] THEN Log.ErrorTree[typeClash, tb[node].son[1]]}};
 
 
RelOp: 
PROC [node: Tree.Index, ordered: 
BOOL] = {
OPEN tb[node];
type: CSEIndex;
attr: Attr;
saveNP: NPUse;
implicitOp: BOOL;
son[1] ← GenericRhs[son[1], typeANY];  saveNP ← phraseNP; 
type ← NormalType[RType[]];  attr ← RAttr[];
implicitOp ← (son[1] = Tree.Null);
son[2] ← GenericRhs[son[2], type];
type ← BalanceTypes[type, NormalType[RType[]]
! UnresolvedTypes => {Log.ErrorTree[typeClash, son[2]]; RESUME [typeANY]}];
 
IF (ordered 
AND ~OrderedType[type]) 
OR (~ordered 
AND ~IdentifiedType[type]) 
THEN
Log.ErrorNode[relationType, node];
 
BalanceAttributes[node];
attr ← And[attr, RAttr[]];
IF implicitOp AND son[1] # Tree.Null THEN Log.ErrorTree[typeClash, son[2]];
SELECT seb[type].typeTag 
FROM
basic, enumerated => NULL;
transfer => {
IF OperandInline[son[1]] THEN Log.ErrorTree[misusedInline, son[1]];
IF OperandInline[son[2]] THEN Log.ErrorTree[misusedInline, son[2]];
attr.const ← FALSE};
 
real => attr.const ← FALSE;
ENDCASE;
 
RPop[];  RPop[];
RPush[dataPtr.typeBOOL, attr];  phraseNP ← MergeNP[saveNP][phraseNP]};
 
In: 
PROC [node: Tree.Index] = {
OPEN tb[node];
type: CSEIndex;
saveNP: NPUse;
son[1] ← GenericRhs[son[1], typeANY];  saveNP ← phraseNP;
type ← RType[];
son[2] ← Range[son[2], CanonicalType[type]];
[] ← BalanceTypes[NormalType[type], NormalType[RType[]]
! UnresolvedTypes => {Log.ErrorTree[typeClash, tb[node].son[1]]; RESUME [typeANY]}];
 
BalanceAttributes[node];
rStack[rI-1].attr ← And[rStack[rI-1].attr, rStack[rI].attr];  RPop[];
rStack[rI].type ← dataPtr.typeBOOL;
phraseNP ← MergeNP[saveNP][phraseNP]};
 
BoolOp: 
PROC [node: Tree.Index] = {
OPEN tb[node];
attr: Attr;
saveNP: NPUse;
SealRefStack[];
son[1] ← Rhs[son[1], dataPtr.typeBOOL]; attr ← RAttr[]; saveNP ← phraseNP; 
ClearRefStack[];
son[2] ← Rhs[son[2], dataPtr.typeBOOL]; 
UnsealRefStack[];
attr ← And[attr, RAttr[]];
RPop[];  RPop[];
RPush[dataPtr.typeBOOL, attr]; phraseNP ← SequenceNP[saveNP][phraseNP]};
 
Interval: 
PUBLIC 
PROC [t: Tree.Link, target: CSEIndex, constant: 
BOOL] = {
node: Tree.Index = GetNode[t];
type: CSEIndex;
attr: Attr;
saveNP: NPUse;
target ← TargetType[target];
tb[node].son[1] ← BalancedRhs[tb[node].son[1], target];  saveNP ← phraseNP;
type ← rStack[rI].type ← CanonicalType[rStack[rI].type];  attr ← RAttr[];
IF constant AND ~attr.const THEN Log.ErrorTree[nonConstant, tb[node].son[1]];
tb[node].son[2] ← BalancedRhs[tb[node].son[2], target];  
rStack[rI].type ← CanonicalType[rStack[rI].type];
[] ← BalanceTypes[NormalType[type], NormalType[RType[]]
! UnresolvedTypes => {Log.ErrorTree[typeClash, tb[node].son[2]]; RESUME [typeANY]}];
 
attr ← And[attr, RAttr[]];
IF constant AND ~RAttr[].const THEN Log.ErrorTree[nonConstant, tb[node].son[2]];
BalanceAttributes[node];
IF tb[node].attr1 THEN attr.const ← FALSE;
phraseNP ← MergeNP[saveNP][phraseNP];
RPop[]; rStack[rI].attr ← attr};
 
BalancedTarget: 
PROC [target, type: CSEIndex] 
RETURNS [CSEIndex] = {
RETURN [
IF target = typeANY
OR (~EqualTypes[type, target] AND NormalType[type] = target)
THEN TargetType[type]
ELSE target]};
 
 
ResolveTypes: 
PROC [type1, type2, target: CSEIndex, t: Tree.Link]
RETURNS [type: CSEIndex] = {
failed: BOOL;
IF target = typeANY THEN failed ← TRUE
ELSE {
ENABLE UnresolvedTypes => {failed ← TRUE; RESUME [typeANY]};
failed ← FALSE;
type1 ← BalanceTypes[target, type1];
type2 ← BalanceTypes[target, type2];
type ← BalanceTypes[type1, type2]};
 
IF failed THEN {Log.ErrorTree[typeClash, t]; type ← typeANY};
RETURN};
 
IfExp: 
PROC [node: Tree.Index, target: CSEIndex] = {
OPEN tb[node];
type: CSEIndex;
attr: Attr;
entryNP, saveNP: NPUse;
SealRefStack[];
son[1] ← Rhs[son[1], dataPtr.typeBOOL]; 
attr ← RAttr[];  RPop[];  entryNP ← phraseNP;
UnsealRefStack[];
son[2] ← BalancedRhs[son[2], target];
attr ← And[attr, RAttr[]]; saveNP ← SequenceNP[entryNP][phraseNP];
type ← RType[];  RPop[];
target ← BalancedTarget[target, type];
son[3] ← BalancedRhs[son[3], target];  attr ← And[attr, RAttr[]];
type ← BalanceTypes[type, RType[]
! UnresolvedTypes => {RESUME [ResolveTypes[type, RType[], target, son[3]]]}];
 
IF seb[type].typeTag = transfer 
THEN {
IF OperandInline[son[2]] THEN Log.ErrorTree[misusedInline, son[2]];
IF OperandInline[son[3]] THEN Log.ErrorTree[misusedInline, son[3]];
attr.const ← FALSE};
 
phraseNP ← BoundNP[saveNP][SequenceNP[entryNP][phraseNP]];
RPop[];  RPush[type, attr]};
 
SelectExp: 
PROC [
node: Tree.Index, target: CSEIndex,
driver: PROC [Tree.Index, Tree.Map], foldable: BOOL] = {
type: CSEIndex;
attr: Attr;
saveNP: NPUse;
started: BOOL;
Selection: Tree.Map = {
subType: CSEIndex;
entryNP: NPUse = phraseNP;
v ← BalancedRhs[t, target];
subType ← BalanceTypes[type, RType[]
! UnresolvedTypes => {RESUME [ResolveTypes[type, RType[], target, v]]}];
 
IF seb[subType].typeTag = transfer 
AND OperandInline[v] 
THEN
Log.ErrorTree[misusedInline, v];
 
saveNP ← BoundNP[saveNP][SequenceNP[entryNP][phraseNP]];
IF subType # typeANY THEN type ← subType;
IF ~started THEN target ← BalancedTarget[target, type];
attr ← And[attr, RAttr[]];  RPop[];  started ← TRUE;  RETURN};
 
type ← typeANY;  attr ← fullAttr;  started ← FALSE;  saveNP ← none;
driver[node, Selection];  attr ← And[attr, RAttr[]];  RPop[];
attr.const ← foldable AND attr.const AND tb[node].attr2;
RPush[type, attr];  phraseNP ← saveNP};
 
MinMax: 
PROC [node: Tree.Index, target: CSEIndex] = {
OPEN tb[node];
attr: Attr;
saveNP: NPUse;
started: BOOL;
type: CSEIndex;
SubMinMax: Tree.Map = {
subType: CSEIndex;
v ← BalancedRhs[t, target];
attr ← And[attr, RAttr[]];  saveNP ← MergeNP[saveNP][phraseNP];
subType ← CanonicalType[RType[]]; 
subType ← BalanceTypes[subType, type 
! UnresolvedTypes => {RESUME[ResolveTypes[subType, type, target, v]]}];
 
IF type # subType 
AND subType # typeANY 
THEN {
IF ~OrderedType[subType] THEN Log.ErrorNode[relationType, node];
type ← subType;
IF ~started THEN target ← BalancedTarget[target, type]};
 
RPop[];  started ← TRUE;  RETURN};
 
attr ← fullAttr;  saveNP ← none;  started ← FALSE;  type ← typeANY;
son[1] ← UpdateList[son[1], SubMinMax];
SELECT seb[type].typeTag 
FROM
long => {attr1 ← FALSE; attr2 ← TRUE};
real => {attr1 ← TRUE; attr2 ← FALSE; attr.const ← FALSE};
ENDCASE => attr1 ← attr2 ← FALSE;
 
RPush[type, attr];  phraseNP ← saveNP};
 
TypeTest: 
PROC [node: Tree.Index, from, to: CSEIndex] = {
subType: CSEIndex = CanonicalType[from];
op: NarrowOp = Narrowing[type: subType, target: to];
SELECT 
TRUE 
FROM
op.error => Log.ErrorTree[typeClash, tb[node].son[1]];
op.computed => Log.ErrorTree[missingBinding, tb[node].son[1]];
op.unImpl => Log.Warning[unimplemented];
ENDCASE;
 
IF subType # from THEN tb[node].son[1] ← ForceType[tb[node].son[1], subType];
tb[node].attr1 ← op.indirect;
IF (tb[node].attr2 ← op.rtTest) THEN EnterType[MarkedType[to]];
tb[node].attr3 ← op.tagTest};
 
EndPoint: 
PROC [node: Tree.Index] = {
OPEN tb[node];
type: CSEIndex;
son[1] ← TypeExp[son[1]];
type ← UnderType[TypeForTree[son[1]]];
BEGIN
WITH seb[type] 
SELECT 
FROM
basic =>
SELECT code 
FROM
codeINT, codeCHAR => NULL;
ENDCASE => GO TO fail;
 
 
enumerated => NULL;
relative => IF TypeForm[offsetType] # subrange THEN GO TO fail;
subrange => NULL;
long =>
IF NormalType[UnderType[rangeType]] # dataPtr.typeINT THEN GO TO fail;
 
ENDCASE => GO TO fail;
 
EXITS
fail => Log.ErrorTree[typeClash, son[1]];
 
END;
 
RPush[type, fullAttr]};
 
Unspec: 
PROC [type: CSEIndex] 
RETURNS [
BOOL] = {
RETURN [
WITH t: seb[type] 
SELECT 
FROM
basic => t.code = codeANY,
ENDCASE => FALSE]};
 
 
SafeForUnspec: 
PROC [target: CSEIndex] 
RETURNS [
BOOL] = {
RETURN [P3S.safety # checked OR RCType[target] = none]};
 
Rhs: 
PUBLIC 
PROC [exp: Tree.Link, lhsType: CSEIndex] 
RETURNS [val: Tree.Link] = {
rhsType: CSEIndex;
val ← Exp[exp, lhsType];
rhsType ← rStack[rI].type;
SELECT 
TRUE 
FROM
(lhsType = rhsType), Unspec[lhsType] => NULL;
ENDCASE => {  
-- immediate matching is inconclusive
UNTIL Types.Assignable[[own, lhsType], [own, rhsType]] 
DO
WITH t: seb[rhsType] 
SELECT 
FROM
subrange => rhsType ← UnderType[t.rangeType];
record => {
IF Bundling[rhsType] = 0 THEN GO TO nomatch;
rhsType ← Unbundle[LOOPHOLE[rhsType, RecordSEIndex]];
val ← ForceType[val, IF Unspec[rhsType] THEN typeANY ELSE rhsType]};
 
ref, arraydesc => {
SELECT seb[lhsType].typeTag 
FROM
long => {
IF ~Types.Assignable[[own, NormalType[lhsType]], [own, rhsType]] 
THEN
GO TO nomatch;
 
val ← Lengthen[val, lhsType]};
 
ENDCASE => GO TO nomatch;
 
rhsType ← lhsType};
 
basic => {
IF Unspec[rhsType] 
AND SafeForUnspec[lhsType] 
THEN
SELECT seb[lhsType].typeTag 
FROM
long => val ← Lengthen[val, MakeLongType[typeANY, lhsType]];
ENDCASE
 
 
ELSE 
SELECT seb[lhsType].typeTag 
FROM
long => {
IF ~Types.Assignable[[own, NormalType[lhsType]], [own, rhsType]] 
THEN
GO TO nomatch;
 
val ← Lengthen[val, lhsType]};
 
real =>
IF rhsType = dataPtr.typeINT 
THEN {
val ← Float[val, rhsType, lhsType]; rStack[rI].attr.const ← FALSE} 
 
ELSE GO TO nomatch;
 
ENDCASE => GO TO nomatch;
 
rhsType ← lhsType};
 
long => {
subType: CSEIndex = NormalType[rhsType];
SELECT seb[lhsType].typeTag 
FROM
long =>
SELECT 
TRUE 
FROM
Unspec[NormalType[lhsType]] => lhsType ← rhsType;
Unspec[subType] 
AND SafeForUnspec[lhsType] =>
rhsType ← lhsType;
 
ENDCASE => GO TO nomatch;
 
 
real =>
IF subType = dataPtr.typeINT 
THEN {
val ← Float[val, rhsType, lhsType];  rStack[rI].attr.const ← FALSE;
rhsType ← lhsType} 
 
ELSE GO TO nomatch;
 
basic, subrange => {
IF ~Types.Assignable[[own, subType], [own, lhsType]] 
THEN
GO TO nomatch;
 
rhsType ← UnderType[t.rangeType]; val ← Shorten[val, rhsType]};
 
enumerated =>
IF EqualTypes[rhsType, dataPtr.typeATOM] 
THEN {
Log.ErrorTree[missingCoercion, val];  rhsType ← lhsType}
 
ELSE GOTO nomatch;
 
ENDCASE => GO TO nomatch};
 
 
ENDCASE => GO TO nomatch;
 
REPEAT
nomatch => { 
-- no coercion is possible
Log.ErrorTree[typeClash,
IF exp = Tree.Null THEN implicit.tree ELSE val];
 
rhsType ← lhsType};
 
 
ENDLOOP;
 
rStack[rI].type ← rhsType};
 
 
IF seb[rhsType].typeTag = transfer 
AND OperandInline[val] 
THEN
Log.ErrorTree[misusedInline, val];
 
RETURN};
 
GenericRhs: 
PROC [exp: Tree.Link, target: CSEIndex] 
RETURNS [val: Tree.Link] = {
type: CSEIndex;
val ← Exp[exp, target];  type ← rStack[rI].type;
put value in canonical form
DO
WITH seb[type] 
SELECT 
FROM
subrange => type ← UnderType[rangeType];
record => {
IF Bundling[type] = 0 THEN EXIT;
type ← Unbundle[LOOPHOLE[type, RecordSEIndex]];
val ← ForceType[val, type]};
 
ENDCASE => EXIT;
 
rStack[rI].type ← type;
ENDLOOP;
 
SELECT seb[target].typeTag 
FROM
enumerated =>
IF EqualTypes[type, dataPtr.typeATOM] 
THEN {
Log.ErrorTree[missingCoercion, val];  rStack[rI].type ← target};
 
 
ENDCASE;
 
RETURN};
 
BalancedRhs: 
PROC [exp: Tree.Link, target: CSEIndex] 
RETURNS [val: Tree.Link] = {
type: CSEIndex;
val ← Exp[exp, target];
SELECT seb[target].typeTag 
FROM
long, real => {
type ← CanonicalType[rStack[rI].type];
IF type # typeANY 
AND seb[target].typeTag # seb[type].typeTag
AND EqualTypes[NormalType[target], type] 
THEN {
SELECT seb[target].typeTag 
FROM
long => IF seb[type].typeTag # real THEN val ← Lengthen[val, target];
real => {val ← Float[val, type, target]; rStack[rI].attr.const ← FALSE};
ENDCASE;
 
rStack[rI].type ← target}};
 
 
 
enumerated =>
IF EqualTypes[rStack[rI].type, dataPtr.typeATOM] 
THEN {
Log.ErrorTree[missingCoercion, val];  rStack[rI].type ← target};
 
 
ENDCASE;
 
RETURN};
 
AttrClass: 
PROC [type: CSEIndex] 
RETURNS [{short, long, real}] = {
RETURN [
WITH t: seb[type] 
SELECT 
FROM
long => long,
real => real,
relative => AttrClass[UnderType[t.offsetType]],
ENDCASE => short]};
 
 
SetAttributes: 
PROC [node: Tree.Index] = {
SELECT AttrClass[rStack[rI].type] 
FROM
long => {tb[node].attr1 ← FALSE; tb[node].attr2 ← TRUE};
real => {tb[node].attr1 ← TRUE; tb[node].attr2 ← FALSE};
ENDCASE => tb[node].attr1 ← tb[node].attr2 ← FALSE};
 
 
BalanceAttributes: 
PROC [node: Tree.Index] = {
lType, rType: CSEIndex;
lType ← rStack[rI-1].type;  rType ← rStack[rI].type;
SELECT AttrClass[lType] 
FROM
long => {
SELECT AttrClass[rType] 
FROM
long => {tb[node].attr1 ← FALSE; tb[node].attr2 ← TRUE};
real => {
rStack[rI-1].type ← rType;
tb[node].son[1] ← Float[tb[node].son[1], lType, rType];
rStack[rI-1].attr.const ← FALSE;
tb[node].attr1 ← TRUE;  tb[node].attr2 ← FALSE};
 
ENDCASE => {
rStack[rI].type ← rType ← MakeLongType[rType, lType];
tb[node].son[2] ← Lengthen[tb[node].son[2], rType];
tb[node].attr1 ← FALSE;  tb[node].attr2 ← TRUE}};
 
 
 
real => {
tb[node].attr1 ← TRUE;  tb[node].attr2 ← FALSE;
SELECT AttrClass[rType] 
FROM
real => NULL;
ENDCASE => {
rStack[rI].type ← lType;
tb[node].son[2] ← Float[tb[node].son[2], rType, lType];
rStack[rI].attr.const ← FALSE}};
 
 
 
ENDCASE =>
SELECT AttrClass[rType] 
FROM
long => {
rStack[rI-1].type ← lType ← MakeLongType[lType, rType];
tb[node].son[1] ← Lengthen[tb[node].son[1], lType];
tb[node].attr1 ← FALSE;  tb[node].attr2 ← TRUE};
 
real => {
rStack[rI-1].type ← rType;
tb[node].son[1] ← Float[tb[node].son[1], lType, rType];
rStack[rI-1].attr.const ← FALSE;
tb[node].attr1 ← TRUE;  tb[node].attr2 ← FALSE};
 
ENDCASE => tb[node].attr1 ← tb[node].attr2 ← FALSE};
 
 
 
 
Lengthen: 
PROC [t: Tree.Link, target: CSEIndex] 
RETURNS [Tree.Link] = {
PushTree[t]; PushNode[lengthen, 1]; SetInfo[target]; RETURN [PopTree[]]};
 
Shorten: 
PROC [t: Tree.Link, target: CSEIndex] 
RETURNS [Tree.Link] = {
PushTree[t]; PushNode[shorten, 1]; SetInfo[target]; RETURN [PopTree[]]};
 
Float: 
PROC [t: Tree.Link, type, target: CSEIndex] 
RETURNS [Tree.Link] = {
PushTree[
IF seb[type].typeTag = long
THEN t
ELSE Lengthen[t, MakeLongType[type, typeANY]]];
 
SELECT NormalType[type] 
FROM
dataPtr.typeINT => {PushNode[float, 1]; SetInfo[target]};
typeANY => NULL;
ENDCASE => Log.ErrorTree[typeClash, t];
 
RETURN [PopTree[]]};