DIRECTORY
A3: TYPE USING [BaseType, Bundling, CanonicalType, IdentifiedType, IndexType, MarkedType, NewableType, NullableType, OperandInline, OrderedType, PermanentType, TargetType, TypeForTree, Unbundle],
Alloc: TYPE USING [Notifier],
ComData: TYPE USING [idATOM, idBOOL, idCARDINAL, idCHAR, idINT, idREAL, idSTRING, idTEXT, interface, ownSymbols, typeAtomRecord, typeCHAR, typeINT],
LiteralOps: TYPE USING [FindHeapString],
Log: TYPE USING [Error, ErrorHti, ErrorN, ErrorNode, ErrorNodeOp, ErrorSei, ErrorTree, ErrorTreeOp, ErrorType, Warning],
P3: TYPE USING [Attr, emptyAttr, fullAttr, voidAttr, NarrowOp, NPUse, BoundNP, MergeNP, SequenceNP, TextForm, phraseNP, AddrOp, All, And, Apply, Assignment, Case, CatchPhrase, ClearRefStack, Cons, Discrimination, Dot, EnterType, Extract, Id, ListCons, MakeLongType, MakeRefType, MiscXfer, Narrowing, New, Range, RecordMention, SealRefStack, SearchCtxList, TextRep, TypeAppl, TypeExp, UnsealRefStack],
P3S: TYPE USING [ImplicitInfo, implicitRecord, safety, self],
SymLiteralOps: TYPE USING [EnterAtom, EnterText],
Symbols: TYPE USING [Base, HTIndex, Type, ISEIndex, CSEIndex, RecordSEIndex, nullType, CSENull, RecordSENull, codeANY, codeCHAR, codeINT, typeANY, ctxType, seType],
SymbolOps: TYPE USING [ConstantId, EqTypes, NormalType, RCType, TypeForm, TypeRoot, UnderType],
Tree: TYPE USING [Base, Index, Link, Map, NodeName, Null, NullIndex, treeType],
TreeOps: TYPE USING [FreeNode, GetHash, GetNode, ListLength, PopTree, PushTree, PushNode, SetAttr, SetInfo, UpdateList],
Types: TYPE USING [SymbolTableBase, Assignable, Equivalent];
OperandDescriptor:
TYPE =
RECORD[
type: Type, -- 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: Type, 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[Type] = {RETURN[rStack[rI].type]};
RAttr: PUBLIC PROC RETURNS[Attr] = {RETURN[rStack[rI].attr]};
UType: PUBLIC PROC RETURNS[CSEIndex] = {RETURN[UnderType[rStack[rI].type]]};
longUnsigned: Type; -- a hint for mwconst
textType: ARRAY TextForm OF Type; -- 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 ← nullType; textType ← ALL[nullType];
rStack ← NEW[RStack[32]];
rI ← -1};
ExpReset:
PUBLIC
PROC = {
IF rStack # NIL THEN rStack ← NIL};
MakeNumeric:
PROC[type: Type]
RETURNS[Type] = {
RETURN[
SELECT TypeForm[type]
FROM
long => MakeLongType[dataPtr.idINT, type],
ENDCASE => dataPtr.idINT]
EvalNumeric:
PROC[t: Tree.Link, op: Tree.NodeName←$none]
RETURNS[val: Tree.Link] = {
val ← GenericRhs[t, dataPtr.idINT];
SELECT NormalType[rStack[rI].type]
FROM
dataPtr.typeINT => NULL;
typeANY => rStack[rI].type ← MakeNumeric[rStack[rI].type];
ENDCASE =>
IF op # $none THEN Log.ErrorTreeOp[missingOp, val, op]
ELSE Log.ErrorTree[typeClash, val];
RETURN};
ArithOp:
PROC[node: Tree.Index] = {
OPEN tb[node];
saveNP: NPUse;
son[1] ← EvalNumeric[son[1], tb[node].name]; 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: Type]
RETURNS[CSEIndex] = {
sei: CSEIndex = NormalType[type];
RETURN[
WITH t: seb[sei]
SELECT
FROM
relative => NormalType[t.offsetType],
ENDCASE => sei]
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.ErrorTreeOp[missingOp, son[1], plus];
lr ← TRUE; son[2] ← EvalNumeric[son[2]]}
ELSE {
SELECT type
FROM
dataPtr.typeINT, typeANY => NULL;
ENDCASE => Log.ErrorTreeOp[missingOp, son[1], plus];
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.ErrorNodeOp[unsafeOp, node, plus];
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.ErrorTreeOp[missingOp, son[1], minus];
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.ErrorTreeOp[missingOp, son[1], minus]; rStack[rI].type ← typeANY};
son[2] ← EvalNumeric[son[2]]};
IF P3S.safety = checked AND seb[lType].typeTag = ref THEN
Log.ErrorNodeOp[unsafeOp, node, minus];
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], tb[node].name]; SetAttributes[node];
IF tb[node].attr1 THEN rStack[rI].attr.const ← FALSE}
EnumOp:
PROC[node: Tree.Index, target: Type] = {
IF UniOperand[node]
THEN {
tb[node].son[1] ← GenericRhs[tb[node].son[1], target]; SetAttributes[node];
IF ~IndexType[RType[]]
THEN
Log.ErrorTreeOp[missingOp, tb[node].son[1], tb[node].name]}
RelOp:
PROC[node: Tree.Index, ordered:
BOOL] = {
OPEN tb[node];
type, target: Type;
attr: Attr;
saveNP: NPUse;
implicitOp: BOOL;
son[1] ← GenericRhs[son[1], typeANY]; saveNP ← phraseNP;
type ← RType[]; target ← BaseType[type]; attr ← RAttr[];
implicitOp ← (son[1] = Tree.Null);
son[2] ← GenericRhs[son[2], target];
type ← BalanceTypes[target, BaseType[RType[]]
! UnresolvedTypes => {
Log.ErrorType[typeClash, son[2], [dataPtr.ownSymbols, type]];
RESUME[typeANY]}];
IF (ordered
AND ~OrderedType[type])
OR (~ordered
AND ~IdentifiedType[type])
THEN
Log.ErrorTreeOp[missingOp, son[1], name];
BalanceAttributes[node];
attr ← And[attr, RAttr[]];
IF implicitOp AND son[1] # Tree.Null THEN Log.ErrorTree[typeClash, son[2]];
SELECT TypeForm[type]
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.idBOOL, attr]; phraseNP ← MergeNP[saveNP][phraseNP]};
In:
PROC[node: Tree.Index] = {
OPEN tb[node];
type: Type;
saveNP: NPUse;
son[1] ← GenericRhs[son[1], typeANY]; saveNP ← phraseNP;
type ← RType[];
son[2] ← Range[son[2], CanonicalType[type]];
[] ← BalanceTypes[BaseType[type], BaseType[RType[]]
! UnresolvedTypes => {
Log.ErrorType[typeClash, tb[node].son[1], [dataPtr.ownSymbols, RType[]]];
RESUME[typeANY]}];
BalanceAttributes[node];
rStack[rI-1].attr ← And[rStack[rI-1].attr, rStack[rI].attr]; RPop[];
rStack[rI].type ← dataPtr.idBOOL;
phraseNP ← MergeNP[saveNP][phraseNP]};
BoolOp:
PROC[node: Tree.Index] = {
OPEN tb[node];
attr: Attr;
saveNP: NPUse;
SealRefStack[];
son[1] ← Rhs[son[1], dataPtr.idBOOL]; attr ← RAttr[]; saveNP ← phraseNP;
ClearRefStack[];
son[2] ← Rhs[son[2], dataPtr.idBOOL];
UnsealRefStack[];
attr ← And[attr, RAttr[]];
RPop[]; RPop[];
RPush[dataPtr.idBOOL, attr]; phraseNP ← SequenceNP[saveNP][phraseNP]};
Interval:
PUBLIC
PROC[t: Tree.Link, target: Type, constant:
BOOL] = {
node: Tree.Index = GetNode[t];
type: Type;
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[BaseType[type], BaseType[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: Type]
RETURNS[Type] = {
RETURN[
IF target = typeANY
OR (~EqualTypes[type, target]
AND EqTypes[NormalType[type], target])
THEN TargetType[type]
ELSE target]
ResolveTypes:
PROC[type1, type2, target: Type, t: Tree.Link]
RETURNS[type: Type] = {
failed: BOOL;
IF target = typeANY THEN failed ← TRUE
ELSE {
ENABLE UnresolvedTypes => {failed ← TRUE; RESUME[typeANY]};
failed ← FALSE;
type ← BalanceTypes[BalanceTypes[target, type1], BalanceTypes[target, type2]]};
IF failed
THEN {
Log.ErrorType[
typeClash, t, [dataPtr.ownSymbols, CanonicalType[type1]]];
type ← typeANY};
RETURN};
IfExp:
PROC[node: Tree.Index, target: Type] = {
OPEN tb[node];
type: Type;
attr: Attr;
entryNP, saveNP: NPUse;
SealRefStack[];
son[1] ← Rhs[son[1], dataPtr.idBOOL];
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 TypeForm[type] = $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: Type, driver: PROC[Tree.Index, Tree.Map], foldable: BOOL] = {
type: Type;
attr: Attr;
saveNP: NPUse;
started: BOOL;
Selection: Tree.Map = {
subType: Type;
entryNP: NPUse = phraseNP;
v ← BalancedRhs[t, target];
subType ← BalanceTypes[type, RType[]
! UnresolvedTypes => {RESUME[ResolveTypes[type, RType[], target, v]]}];
IF TypeForm[subType] = $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: Type] = {
OPEN tb[node];
attr: Attr;
saveNP: NPUse;
started: BOOL;
type: Type;
SubMinMax: Tree.Map = {
subType: Type;
v ← BalancedRhs[t, target];
attr ← And[attr, RAttr[]]; saveNP ← MergeNP[saveNP][phraseNP];
subType ← BalanceTypes[CanonicalType[RType[]], type
! UnresolvedTypes => {RESUME[ResolveTypes[subType, type, target, v]]}];
IF subType # typeANY
THEN {
IF ~started
THEN {
IF ~OrderedType[subType] THEN Log.ErrorTreeOp[missingOp, v, name];
target ← BalancedTarget[target, subType]; started ← TRUE}
ELSE IF ~EqTypes[type, subType]
THEN
IF ~OrderedType[subType] THEN Log.ErrorTree[typeClash, v];
type ← subType};
RPop[]; RETURN};
attr ← fullAttr; saveNP ← none; started ← FALSE; type ← typeANY;
son[1] ← UpdateList[son[1], SubMinMax];
SELECT TypeForm[type]
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: Type] = {
subType: Type = 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[opaqueTest];
ENDCASE;
IF ~EqTypes[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[rangeType] # dataPtr.typeINT THEN GO TO fail;
ENDCASE => GO TO fail;
EXITS
fail => Log.ErrorTreeOp[missingAttr, son[1], name];
END;
RPush[type, fullAttr]};
Unspec:
PROC[type: Type]
RETURNS[
BOOL] = {
sei: CSEIndex = UnderType[type];
RETURN[
WITH t: seb[sei]
SELECT
FROM
basic => t.code = codeANY,
ENDCASE => FALSE]
SafeForUnspec:
PROC[target: Type]
RETURNS[
BOOL] = {
RETURN[P3S.safety # checked OR RCType[target] = none]};
Rhs:
PUBLIC
PROC[exp: Tree.Link, lhsType: Type]
RETURNS[val: Tree.Link] = {
rhsType: Type;
lhsSei, rhsSei: CSEIndex;
val ← Exp[exp, lhsType]; rhsType ← rStack[rI].type;
lhsSei ← UnderType[lhsType]; rhsSei ← UnderType[rhsType];
SELECT
TRUE
FROM
(lhsSei = rhsSei), Unspec[lhsType] => NULL;
ENDCASE => {
-- immediate matching is inconclusive
UNTIL Types.Assignable[[own, lhsSei], [own, rhsSei]]
DO
WITH t: seb[rhsSei]
SELECT
FROM
subrange => rhsType ← UnderType[t.rangeType];
record => {
IF Bundling[rhsSei] = 0 THEN GO TO nomatch;
rhsType ← Unbundle[LOOPHOLE[rhsSei, RecordSEIndex]];
val ← ForceType[val, IF Unspec[rhsType] THEN typeANY ELSE rhsType]};
ref, arraydesc => {
SELECT TypeForm[lhsSei]
FROM
$long => {
IF ~Types.Assignable[[own, NormalType[lhsSei]], [own, rhsSei]]
THEN
GO TO nomatch;
val ← Lengthen[val, MakeLongType[rhsType, lhsType]]};
ENDCASE => GO TO nomatch;
rhsType ← lhsType};
basic => {
IF Unspec[rhsSei]
AND SafeForUnspec[lhsSei]
THEN
SELECT TypeForm[lhsSei]
FROM
$long => val ← Lengthen[val, MakeLongType[typeANY, lhsType]];
ENDCASE
ELSE
SELECT TypeForm[lhsSei]
FROM
$long => {
IF ~Types.Assignable[[own, NormalType[lhsSei]], [own, rhsSei]]
THEN
GO TO nomatch;
val ← Lengthen[val, lhsType]};
$real =>
IF rhsSei = 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[rhsSei];
SELECT TypeForm[lhsSei]
FROM
$long =>
SELECT
TRUE
FROM
Unspec[NormalType[lhsSei]] => {
lhsType ← rhsType; lhsSei ← UnderType[lhsType]};
Unspec[subType]
AND SafeForUnspec[lhsSei] =>
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, lhsSei]]
THEN
GO TO nomatch;
rhsType ← UnderType[t.rangeType]; val ← Shorten[val, rhsType]};
ENDCASE => GO TO nomatch};
ENDCASE => GO TO nomatch;
rhsSei ← UnderType[rhsType];
REPEAT
nomatch => {
-- no coercion is possible
Log.ErrorType[typeClash,
IF exp = Tree.Null THEN implicit.tree ELSE val,
[dataPtr.ownSymbols, lhsType]];
rhsType ← lhsType};
ENDLOOP;
rStack[rI].type ← rhsType};
IF TypeForm[rhsType] = $transfer
AND OperandInline[val]
THEN
Log.ErrorTree[misusedInline, val];
RETURN};
GenericRhs:
PROC[exp: Tree.Link, target: Type]
RETURNS[val: Tree.Link] = {
type: Type;
val ← Exp[exp, target]; type ← rStack[rI].type;
put value in canonical form
DO
sei: CSEIndex = UnderType[type];
WITH t: seb[sei]
SELECT
FROM
subrange => type ← t.rangeType;
record => {
IF Bundling[sei] = 0 THEN EXIT;
type ← Unbundle[LOOPHOLE[sei, RecordSEIndex]];
val ← ForceType[val, type]};
ENDCASE => EXIT;
rStack[rI].type ← type;
ENDLOOP;
RETURN};
BalancedRhs:
PROC[exp: Tree.Link, target: Type]
RETURNS[val: Tree.Link] = {
type: Type;
val ← Exp[exp, target];
SELECT TypeForm[target]
FROM
$long, $real => {
type ← CanonicalType[rStack[rI].type];
IF type # typeANY
AND TypeForm[target] # TypeForm[type]
AND EqualTypes[NormalType[target], type]
THEN {
SELECT TypeForm[target]
FROM
$long =>
IF TypeForm[type] # $real
THEN
val ← Lengthen[val, MakeLongType[type, target]];
real => {val ← Float[val, type, target]; rStack[rI].attr.const ← FALSE};
ENDCASE;
rStack[rI].type ← target}};
ENDCASE;
RETURN};
AttrClass:
PROC[type: Type]
RETURNS[{short, long, real}] = {
sei: CSEIndex = UnderType[type];
RETURN[
WITH t: seb[sei]
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: Type;
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: Type]
RETURNS[Tree.Link] = {
PushTree[t]; PushNode[lengthen, 1]; SetInfo[target]; RETURN[PopTree[]]};
Shorten:
PROC[t: Tree.Link, target: Type]
RETURNS[Tree.Link] = {
PushTree[t]; PushNode[shorten, 1]; SetInfo[target]; RETURN[PopTree[]]};
Float:
PROC[t: Tree.Link, type, target: Type]
RETURNS[Tree.Link] = {
PushTree[
IF TypeForm[type] = $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[]]};