ParserPrivate2Impl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Bhargava, August 11, 1986 10:36:33 am PDT
Bill Jackson (bj) August 18, 1986 10:09:52 pm PDT
DIRECTORY
AbstractTypesDef USING [ConstantNode, TypeNode],
Convert USING [RopeFromCard, RopeFromInt],
HashTable USING [Delete, Erase, Fetch, GetSize, Insert, Store, Value],
IO USING [card, int, rope, PutF, PutFR, STREAM],
ParserPrivateDef USING [],
Rope USING [ROPE, Cat, Equal],
RopeList USING [DAppend, Map, Cons],
SiroccoPrivate USING [AquireState, CComponent, CComponentBody, CType, CTypeBody, DirectoryEntry, EndItAll, FunctionList, Handle, MakeUpName, TABLES, UnresolvedConstantTableEntry],
ThreeC4Support USING [GetReportStream, GetSourceInfo],
WartDef USING [Generic, identifierNode];
ParserPrivate2Impl: CEDAR PROGRAM
IMPORTS Convert, HashTable, IO, Rope, RopeList, SiroccoPrivate, ThreeC4Support
EXPORTS ParserPrivateDef ~ {
OPEN SiroccoPrivate;
Copied Types
ConstantNode: TYPE ~ AbstractTypesDef.ConstantNode;
Generic: TYPE ~ WartDef.Generic;
identifierNode: TYPE ~ WartDef.identifierNode;
ROPE: TYPE ~ Rope.ROPE;
TypeNode: TYPE ~ AbstractTypesDef.TypeNode;
Value: TYPE ~ HashTable.Value;
Procs
AddLocalConstantToRope: PUBLIC PROC [id: identifierNode, constantName: ROPE, constantType: ROPE, constantFunctions: LIST OF ROPE, inValue: ROPE, t1: TABLES] RETURNS [rope: ROPE, newConstantFunctions: LIST OF ROPE, t2: TABLES] ~ {
info: REF DirectoryEntry;
successful: BOOLEAN;
temp: Value;
[successful, temp] ← HashTable.Fetch[t1.localTable, id.text];
IF (NOT successful)
THEN {
rope ← Rope.Cat[inValue, id.text]; -- Enumeration Constant
newConstantFunctions ← constantFunctions;
t2 ← t1;
RETURN;
};
info ← NARROW[temp];
IF (NOT Rope.Equal[info.constant, ""])
THEN {
rope ← Rope.Cat[inValue, info.constant];
newConstantFunctions ← AddFunctionList[info, constantFunctions];
[] ← AddFunctionToTable[info, constantFunctions, t1];
t2 ← t1;
RETURN;
};
[info.constant, info.functions, t1] ← NARROW[info.value, ConstantNode].procs.ConstantToRope[info.value, id.text, info.type, info.functions, info.constant, t1];
rope ← Rope.Cat[inValue, info.constant];
constantFunctions ← AddFunctionList[info, constantFunctions];
[] ← AddFunctionToTable[info, constantFunctions, t1];
RETURN[rope, constantFunctions, t1];
};
CanonicaliseLocalReferenceType: PUBLIC PROC [id: identifierNode, t1: TABLES] RETURNS [ cannonicalType: ROPE, typeTree: CType, t2: TABLES ] ~ {
info: REF DirectoryEntry;
overwrite: BOOLEAN;
successful: BOOLEAN;
temp: Value;
type: CType;
typeNode: TypeNode;
h: SiroccoPrivate.Handle;
ReturnCanonicalKey: PUBLIC PROC [id: identifierNode] RETURNS [key: ROPE] ~ {
key ← Rope.Cat[h.programKey, id.text];
};
h ← SIGNAL SiroccoPrivate.AquireState[];
t2 ← t1;
[successful, temp] ← HashTable.Fetch[t1.localTable, id.text];
IF (successful)
THEN {
info ← NARROW[temp];
[successful, temp] ← HashTable.Fetch[t1.typeTable, info.type];
IF (successful)
THEN {
type ← NARROW[temp];
cannonicalType ← info.type;
typeTree ← type;
RETURN;
}
ELSE [] ← SendError["Compiler Error"]; -- COMPILER ERROR
}
ELSE {
[successful, temp] ← HashTable.Fetch[t1.unresolvedTypeTable, id.text];
IF (successful)
THEN {
typeNode ← NARROW[temp];
overwrite ← HashTable.Store[t1.unresolvedTypeTable, id.text, NIL];
IF (NOT overwrite)
THEN {
IF (typeNode = NIL)
THEN [] ← SendError["Cyclic Dependency"] -- CYCLIC DEPENDENCY
ELSE {
[cannonicalType, typeTree, t1] ← typeNode.procs.CanonicaliseType[typeNode, t1];
IF (Rope.Equal[cannonicalType, "DEFAULT"])
THEN cannonicalType ← ReturnCanonicalKey[id];
successful ← HashTable.Insert[t1.typeTable, cannonicalType, typeTree];
Should Sucessful always be true? No As in the case of Integers
info ← NEW[DirectoryEntry ← [type~cannonicalType, constant~"", functions~NIL, value~NIL]];
successful ← HashTable.Insert[t1.localTable, id.text, info];
Should Sucessful always be true? I Think So.
IF (NOT successful)
THEN [] ← SendError["Compiler Error"]; -- COMPILER ERROR (The Redeclaration should have been caught while entering stuff in the UnresolvedTypeTable)
RETURN;
}
}
ELSE [] ← SendError["Compiler Error"]; -- COMPILER ERROR
}
ELSE {
[] ← SendError["Undeclared Identifier"] -- UNDECLARED ID;
};
};
};
CheckIfEmpty: PUBLIC PROC [tables: TABLES] RETURNS [new: TABLES] ~ {
IF (HashTable.GetSize[tables.workTable] # 0)
THEN [] ← SendError["Missing Enumeration in Choice"];
new ← tables;
};
ClearWorkTable: PUBLIC PROC [tables: TABLES] RETURNS [new: TABLES] ~ {
HashTable.Erase[tables.workTable];
new ← tables;
};
CompareClass: PUBLIC PROC [first: CType, second: Generic] RETURNS [comp: CComponent] ~ {
IF (first.class # second)
THEN [] ← SendError["Type Mismatch"];
comp ← first.children;
};
Copy: PUBLIC PROC [t1: ROPE, t2: CType, t3: ConstantNode, t4: TABLES] RETURNS [ROPE, CType, ConstantNode, TABLES] ~ {
RETURN[t1, t2, t3, t4];
};
CopyCComponent: PUBLIC PROC [in: CComponent] RETURNS [out: CComponent] ~ {
out ← in;
};
EnterNamesIntoWorkTable: PUBLIC PROC[type: CType, tables: TABLES] RETURNS [new: TABLES] ~ {
list: CComponent ← type.children;
HashTable.Erase[tables.workTable];
WHILE (list # NIL) DO
IF (NOT HashTable.Insert[tables.workTable, list.name, ""]) THEN ERROR; -- Compiler ERROR
list ← list.sibling;
ENDLOOP;
new ← tables;
};
FetchFromTypeTable: PUBLIC PROC [t1: TABLES, key: ROPE] RETURNS [value: CType] ~ {
successful: BOOLEAN;
temp: Value;
[successful, temp] ← HashTable.Fetch[t1.typeTable, key];
IF (NOT successful)
THEN [] ← SendError["Compiler Error"]; --COMPILER ERROR
value ← NARROW[temp];
};
FillWorkTable: PUBLIC PROC [type: CType, tables: TABLES] RETURNS [new: TABLES] ~ {
list: CComponent ← type.children;
length: INT ← -1;
HashTable.Erase[tables.workTable];
WHILE (list # NIL) DO
IF (NOT HashTable.Insert[tables.workTable, list.name, ""]) THEN ERROR; -- Compiler ERROR
IF (NOT HashTable.Insert[tables.workTable, Convert.RopeFromInt[list.val],""]) THEN ERROR; -- Compiler ERROR
list ← list.sibling;
length ← length +1;
ENDLOOP;
WHILE (length >= 0) DO
IF (NOT HashTable.Delete[tables.workTable, Convert.RopeFromInt[length]])
THEN [] ← SendError["Enumeration not Continous hence cannot be used as tag for Choice"];
length ← length - 1;
ENDLOOP;
new ← tables;
};
GetConstantType: PUBLIC PROC [id: identifierNode, t1: TABLES] RETURNS [cannonicalType: ROPE, typeTree: CType, constant: ConstantNode, table : TABLES ] ~ {
info: REF DirectoryEntry;
successful, overwrite: BOOLEAN;
temp: Value;
value: REF UnresolvedConstantTableEntry;
h: SiroccoPrivate.Handle;
ReturnCanonicalKey: PUBLIC PROC [id: identifierNode] RETURNS [key: ROPE] ~ {
key ← Rope.Cat[h.programKey, id.text];
};
h ← SIGNAL SiroccoPrivate.AquireState[];
table ← t1;
[successful, temp] ← HashTable.Fetch[t1.localTable, id.text];
IF (successful)
THEN { -- Already resolved
info ← NARROW[temp];
[successful, temp] ← HashTable.Fetch[t1.typeTable, info.type];
IF (successful)
THEN { -- Get Type
cannonicalType ← info.type;
typeTree ← NARROW[temp];
constant ← NARROW[info.value];
RETURN;
}
ELSE [] ← SendError["Compiler Error"]; -- COMPILER ERROR
}
ELSE { -- Unresolved
[successful, temp] ← HashTable.Fetch[t1.unresolvedConstantTable, id.text];
IF (successful)
THEN { -- Must be succesful if name was declared
value ← NARROW[temp];
overwrite ← HashTable.Store[t1.unresolvedConstantTable, id.text, NIL];
IF (NOT overwrite)
THEN { -- if new declaration
IF (value = NIL)
THEN [] ← SendError["Cyclic Dependancy"] -- already being processed: CYCLIC DEPENDANCY
ELSE {
[cannonicalType, typeTree, t1] ← NARROW[value.type, TypeNode].procs.CanonicaliseType[value.type, t1];
IF (Rope.Equal["DEFAULT", cannonicalType])
THEN cannonicalType ← ReturnCanonicalKey[id];
successful ← HashTable.Insert[t1.typeTable, cannonicalType, typeTree];
t1 ← NARROW[value.constant, ConstantNode].procs.Coerce[value.constant, typeTree, cannonicalType, t1];
info ← NEW[DirectoryEntry];
info.type ← cannonicalType;
info.constant ← "";
info.functions ← NIL;
[info.constant, info.functions, t1] ← NARROW[value.constant, ConstantNode].procs.ConstantToRope[value.constant, id.text, cannonicalType, info.functions, info.constant, t1];
info.value ← value.constant;
constant ← NARROW[value.constant];
successful ← HashTable.Insert[t1.localTable, id.text, info];
RETURN;
}
}
ELSE [] ← SendError["Compiler Error"]; -- COMPILER ERROR
}
ELSE {
[] ← SendError["Undeclared Identifier"] -- UNDECLARED ID;
};
};
};
GetCTypeFirstChild: PUBLIC PROC [first: CType] RETURNS [comp: CComponent] ~ {
comp ← first.children;
};
InsureErrorType: PUBLIC PROC [id: identifierNode, t: TABLES] RETURNS [new: TABLES] ~ {
type: CType;
cannonicalType: ROPE;
constant: ConstantNode;
[cannonicalType, type, constant, t] ← GetConstantType[id, t];
IF (type.class = error)
THEN new ← t
ELSE [] ← SendError["Identifier Not Decarled as an ERROR"]; -- Identifier should be a declared error
new ← t;
};
IntoUnresolvedTypeTable: PUBLIC PROC [t1: TABLES, key: ROPE, value: TypeNode] RETURNS [new: TABLES] ~ {
IF (HashTable.Insert[t1.unresolvedTypeTable, key, value])
THEN new ← t1
ELSE [] ← SendError["Redeclared Identifier"]; -- Redeclared Identifier
new ← t1; -- I'm not sure why this one is here... (bj)
};
IntoUnresolvedConstantTable: PUBLIC PROC [t1: TABLES, key: ROPE, type: TypeNode, constant: ConstantNode] RETURNS [new: TABLES] ~ {
value: REF UnresolvedConstantTableEntry;
value ← NEW[UnresolvedConstantTableEntry];
value.type ← type;
value.constant ← constant;
IF HashTable.Insert[t1.unresolvedConstantTable, key, value]
THEN new ← t1
ELSE [] ← SendError["Redeclared Identifier"]; -- Redeclared Identifier
new ← t1; -- I'm not sure why this one is here... (bj)
};
IsEnumerationConstant: PUBLIC PROC [type: CType, id: identifierNode] RETURNS [INT ← 0] ~ {
notFound: BOOLEANTRUE;
sibling: CComponent ← type.children;
WHILE ((sibling # NIL) AND notFound) DO
IF Rope.Equal[sibling.name, id.text]
THEN notFound ← FALSE
ELSE sibling ← sibling.sibling;
ENDLOOP;
IF (sibling = NIL)
THEN [] ← SendError["UnDeclared Enumeration"];
};
MkCComponent: PUBLIC PROC [name: ROPE, valBinding: INT, typeBinding: ROPE, sibling: CComponent] RETURNS [new: CComponent] ~ {
new ← NEW[CComponentBody];
new.sibling ← sibling;
new.name ← name;
new.val ← valBinding;
new.type ← typeBinding;
};
MkCType: PUBLIC PROC [class: Generic, bound: INT, children: CComponent] RETURNS [new: CType] ~ {
new ← NEW[CTypeBody];
new.class ← class;
new.bound ← bound;
new.children ← children;
};
MkNILCComponent: PUBLIC PROC RETURNS [nil: CComponent] ~ {
nil ← NIL;
};
NotEnumeration: PUBLIC PROC[type: CType] RETURNS [result: BOOLEANTRUE] ~ {
result ← NOT (type.class = enumeration);
};
Remove: PUBLIC PROC [id: identifierNode, tables: TABLES] RETURNS [new: TABLES] ~ {
IF (NOT HashTable.Delete[tables.workTable, id.text])
THEN [] ← SendError["Undeclared or Redeclared Identifier"];
new ← tables;
};
SeeIfDuplicated: PUBLIC PROC [tables: TABLES, id: identifierNode, constant: CARD] RETURNS [new: TABLES] ~ {
IF (NOT HashTable.Insert[tables.workTable, id.text,""])
THEN [] ← SendError[Rope.Cat["Duplicates in Enumerated Type, ", id.text, " redeclared"]];
IF (NOT HashTable.Insert[tables.workTable, Convert.RopeFromCard[constant],""])
THEN [] ← SendError["Two identifiers have the same value in Enumerated Type"];
new ← tables;
};
SeeIfInt: PUBLIC PROC[type: CType] RETURNS [yes: BOOLEANTRUE] ~ {
IF (type.class = integer)
OR (type.class = longInteger)
THEN NULL
ELSE [] ← SendError["Type Mismatch, negative number not expected"];
};
SendError: PUBLIC PROC [errMsg: ROPE] RETURNS [c: CARD] ~ {
length: INT;
position: INT;
outstream: IO.STREAMSIGNAL ThreeC4Support.GetReportStream;
[position, length] ← SIGNAL ThreeC4Support.GetSourceInfo;
IO.PutF[outstream, "\nError: %g at %g..%g\n",
IO.rope[errMsg],
IO.int[position],
IO.int[position+length]
];
ERROR SiroccoPrivate.EndItAll;
};
TryToCoerceNumber: PUBLIC PROC [first: CType, value: CARD] RETURNS [num: INT] ~ {
ERRORS HERE SHOULD BE RECOVERED FROM
SELECT first.class FROM
procedure,
cardinal,
error,
unspecified => {
IF (value IN CARDINAL)
THEN num ← 1
ELSE [] ← SendError["Wrong Number"];
};
integer => {
IF (value IN [0..32768])
THEN num ← 1
ELSE [] ← SendError["Wrong Number"];
};
longInteger => {
IF (value IN [0..2147483648])
THEN num ← 1
ELSE [] ← SendError["Wrong Number"];
};
longCardinal => {
IF (value IN CARD)
THEN num ← 1
ELSE [] ← SendError["Wrong Number"];
};
ENDCASE => {
[] ← SendError["Wrong Number"];
num ← 0;
};
};
ValueToConstant: PUBLIC PROC [value: Value] RETURNS [constant: ConstantNode] ~ {
dir : REF DirectoryEntry;
dir ← NARROW[value];
constant ← NARROW[dir.value];
};
ValueToRope: PUBLIC PROC [value: Value] RETURNS [rope: ROPE] ~ {
dir: REF DirectoryEntry;
dir ← NARROW[value];
rope ← dir.type;
};
ValueToRopeConstant: PUBLIC PROC [value: Value, invalue: ROPE] RETURNS [rope: ROPE] ~ {
dir: REF DirectoryEntry;
dir ← NARROW[value];
rope ← Rope.Cat[invalue, dir.constant];
};
Array: PUBLIC PROC [constantType: ROPE, tables: TABLES] RETURNS [yes: BOOLEAN] ~ {
successful: BOOLEAN;
temp: Value;
type: CType;
[successful, temp] ← HashTable.Fetch[tables.typeTable, constantType];
IF (NOT successful) THEN ERROR;
type ← NARROW [temp];
yes ← (type.class = array);
};
GetObjectName: PUBLIC PROC [name: ROPE, tables: TABLES] RETURNS [objectName: ROPE] ~ {
temp: Value;
successful: BOOLEAN;
[successful, temp] ← HashTable.Fetch[tables.madeUpNameTable, name];
IF successful
THEN objectName ← NARROW [temp]
ELSE objectName ← SiroccoPrivate.MakeUpName[name, "Object", tables];
};
IntoCondensedFunctionTable: PUBLIC PROC [functionName, function: ROPE, tables: TABLES] RETURNS [TABLES] ~ {
[] ← HashTable.Insert[tables.condensedFunctionTable, functionName, function];
RETURN[tables];
};
MakeUpFunctionName: PUBLIC PROC RETURNS [madeUpName: ROPE] ~ {
h: SiroccoPrivate.Handle ← SIGNAL SiroccoPrivate.AquireState;
madeUpName ← IO.PutFR["P%gV%gFcn%g",
IO.card[h.programNo],
IO.card[h.versionNo],
IO.card[h.uniqueNo]
];
h.uniqueNo ← h.uniqueNo + 1;
};
AddFunctionList: PUBLIC PROC [value: Value, list: FunctionList] RETURNS [newList: FunctionList] ~{
entry: REF DirectoryEntry;
entry ← NARROW[value];
newList ← RopeList.DAppend[list, entry.functions];
};
AddFunctionToTable: PUBLIC PROC [value: Value, list: FunctionList, tables: TABLES] RETURNS [newTables: TABLES] ~{
entry: REF DirectoryEntry;
FromFunctionTableToCondensedFunctionTable: PROC [entry: ROPE] RETURNS [] ~
{
value: Value;
successful: BOOLEAN;
[successful, value] ← HashTable.Fetch[tables.functionTable, entry];
successful ← HashTable.Insert[tables.condensedFunctionTable, entry, value];
};
entry ← NARROW[value];
RopeList.Map[entry.functions, FromFunctionTableToCondensedFunctionTable];
newTables ← tables;
};
ConsFunctionList: PUBLIC PROC [list: FunctionList, newElement: ROPE] RETURNS [newList: FunctionList] ~ {
newList ← list ← RopeList.Cons[list, newElement];
};
TypeOfSequence: PUBLIC PROC [sequenceName: ROPE, tables: TABLES] RETURNS [typeOf: ROPE] ~ {
sucessful: BOOLEAN;
value: HashTable.Value;
type: CType;
[sucessful, value] ← HashTable.Fetch[tables.typeTable, sequenceName];
type ← NARROW [value];
typeOf ← type.children.type
};
GetTypeOfComponent: PUBLIC PROC [id: identifierNode, name: ROPE, tables: TABLES] RETURNS [typeOf: ROPE] ~ {
sucessful: BOOLEAN;
value: HashTable.Value;
type: CType;
list: CComponent;
[sucessful, value] ← HashTable.Fetch[tables.typeTable, name];
type ← NARROW [value];
list ← type.children;
WHILE ((NOT Rope.Equal[list.name, id.text]) AND (list # NIL)) DO
list ← list.sibling;
ENDLOOP;
IF list = NIL THEN ERROR ELSE typeOf ← list.type;
};
}.