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];
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: BOOLEAN ← TRUE;
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:
BOOLEAN ←
TRUE] ~ {
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:
BOOLEAN ←
TRUE] ~ {
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.STREAM ← SIGNAL 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;
};
}.