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;
};
 
 
}.