OperandDescriptor:
TYPE =
RECORD[
type: CSEIndex, -- type of operand
attr: Attr]; -- attributes
RStack: TYPE = RECORD [SEQUENCE length: NAT OF OperandDescriptor];
rStack: LONG POINTER TO 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: LONG POINTER TO RStack = zone.NEW[RStack[newLength]];
FOR i: INTEGER IN [0 .. rI) DO newStack[i] ← rStack[i] ENDLOOP;
zone.FREE[@rStack];
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 [scratchZone:
UNCOUNTED
ZONE] = {
zone ← scratchZone;
implicit ← [type: typeANY, tree: Tree.Null, attr: emptyAttr];
P3S.implicitRecord ← RecordSENull;
own ← dataPtr.ownSymbols; -- make a parameter?
longUnsigned ← CSENull; textType ← ALL[CSENull];
rStack ← zone.NEW[RStack[32]];
rI ← -1};
ExpReset:
PUBLIC
PROC = {
IF rStack # NIL THEN zone.FREE[@rStack];
zone ← 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[]]};