DIRECTORY
IO USING [PutF, PutFR, rope, RopeFromROS, ROS, STREAM],
Rope USING [Equal, ROPE],
SaffronATDef USING [EvaluateAndTypeCheckExpression, ExpNode, InitializationNode, TypeExpNode],
SaffronBaseDef USING [AccessValNode, CompilerStateNode, DemandTypeDeclarationField, FieldNode, LookupNameInContextRib, LookupNameInFieldList],
SaffronContext USING [],
SaffronContextPrivateTypes,
SaffronErrorHandling USING [FatalError, InternalError, Message, Warning],
SaffronGenericDef USING [IdNode],
SaffronProgramGraphPrivateTypes USING [ParameterizedFieldDescriptorNodeBody];

SaffronDeclarationAnalysisImpl: CEDAR PROGRAM 
IMPORTS IO, Rope, SaffronATDef, SaffronBaseDef, SaffronErrorHandling
EXPORTS SaffronBaseDef, SaffronContext
~ BEGIN

OPEN 
AT: SaffronATDef, 
BD: SaffronBaseDef, 
EH: SaffronErrorHandling,
GEN: SaffronGenericDef, 
PG: SaffronProgramGraphPrivateTypes,
PT: SaffronContextPrivateTypes;

LocalContextNode: TYPE ~ REF LocalContextNodeBody;
LocalContextNodeBody: PUBLIC TYPE ~ PT.LocalContextNodeBody;

ContextRibNode: TYPE ~ REF ContextRibNodeBody;
ContextRibNodeBody: PUBLIC TYPE ~ PT.ContextRibNodeBody;

FrozenFieldListNode: TYPE = REF FrozenFieldListNodeBody;
FrozenFieldListNodeBody: PUBLIC TYPE = PT.FrozenFieldListNodeBody;

FieldListNode: TYPE = REF FieldListNodeBody;
FieldListNodeBody: PUBLIC TYPE = PT.FieldListNodeBody;

TypeGraphNodeNode: TYPE ~ REF TypeGraphNodeNodeBody;
TypeGraphNodeNodeBody: PUBLIC TYPE ~ PT.TypeGraphNodeNodeBody;

ValueNode: TYPE = REF ValueNodeBody;
ValueNodeBody: PUBLIC TYPE = PT.ValueNodeBody;

FieldNode: TYPE = REF FieldNodeBody;
FieldNodeBody: PUBLIC TYPE = PT.FieldNodeBody;

ParameterizedFieldDescriptorNode: TYPE = REF ParameterizedFieldDescriptorNodeBody;
ParameterizedFieldDescriptorNodeBody: PUBLIC TYPE = PG.ParameterizedFieldDescriptorNodeBody;


AnalyzeDependencies: PUBLIC PROC [dg: DependencyGraphNode, fl: FieldListNode, lc: LocalContextNode, cs: BD.CompilerStateNode] RETURNS [FieldListNode, LocalContextNode]~ 
BEGIN
NodeProc: PROC [dgn: DependencyGraphNodeNode] = BEGIN
WITH dgn SELECT FROM
d: REF value DependencyGraphNodeNodeBody =>
IF NOT DependsOnRuntimeState[dgn] THEN {
field: REF constant FieldNodeBody _ NARROW[d.of];
targetType: TypeGraphNodeNode _ field.type;
expNode: AT.ExpNode _ NARROW[field.value, REF unparsed ValueNodeBody].parseTree;
field.value _ AT.EvaluateAndTypeCheckExpression[expNode, lc, fl, cs, targetType];
};
d: REF runtime DependencyGraphNodeNodeBody => {};
d: REF size DependencyGraphNodeNodeBody => 
SIGNAL EH.Warning[0, "size dgn proc not yet implemented"];
d: REF first DependencyGraphNodeNodeBody => 
IF DependsOnRuntimeState[dgn] 
THEN ERROR EH.FatalError[0, "FIRST[] is not constant"]
ELSE {
field: REF typeDecl FieldNodeBody _ NARROW[d.of];
namedType: PT.NamedTGN _ NARROW[field.type.body];
elementTGN: PT.ElementTGN _ NARROW[namedType.type.body];
WITH elementTGN SELECT FROM
e: REF subrange PT.ElementTGNBody => {
expNode: AT.ExpNode _ NARROW[e.body.firstElement, REF unparsed ValueNodeBody].parseTree;
e.body.firstElement _ AT.EvaluateAndTypeCheckExpression[expNode, lc, fl, cs, e.body.baseType];
};
e: REF enumerated base PT.ElementTGNBody => {
SIGNAL EH.Warning[0, "first dgn proc not yet implemented for base enumerated tgn"]
};
ENDCASE => ERROR EH.InternalError["should not be dependency-analyzing this kind of element type"];
};
d: REF last DependencyGraphNodeNodeBody => 
IF DependsOnRuntimeState[dgn] 
THEN ERROR EH.FatalError[0, "LAST[] is not constant"]
ELSE {
field: REF typeDecl FieldNodeBody _ NARROW[d.of];
namedType: PT.NamedTGN _ NARROW[field.type.body];
elementTGN: PT.ElementTGN _ NARROW[namedType.type.body];
WITH elementTGN SELECT FROM
e: REF subrange PT.ElementTGNBody => {
expNode: AT.ExpNode _ NARROW[e.body.lastElement, REF unparsed ValueNodeBody].parseTree;
e.body.lastElement _ AT.EvaluateAndTypeCheckExpression[expNode, lc, fl, cs, e.body.baseType];
};
e: REF enumerated base PT.ElementTGNBody => {
SIGNAL EH.Warning[0, "last dgn proc not yet implemented for base enumerated tgn"]
};
ENDCASE => ERROR EH.InternalError["should not be dependency-analyzing this kind of element type"];
};
ENDCASE;
END;
lc.dependencyGraph _ dg;
WalkDependencyGraph[lc.dependencyGraph, NodeProc];
RETURN[fl, lc];
END;


LookupIdentifierTGNs: PUBLIC PROC [fl: FieldListNode, lc: LocalContextNode] RETURNS [FieldListNode] = BEGIN
LookupTypeIdentifiersInFieldList[fl, fl, lc];
RETURN [fl];
END;

LookupTypeIdentifiers: PROC [tgn: TypeGraphNodeNode, fl: FieldListNode, lc: LocalContextNode] RETURNS [TypeGraphNodeNode] = BEGIN
IF ISTYPE[tgn.body, PT.IdentifierTGN]
THEN BEGIN
access: BD.AccessValNode;
lookedUpTGN: TypeGraphNodeNode;
id: GEN.IdNode _ NARROW[tgn.body, PT.IdentifierTGN].id;
field: FieldNode _ BD.LookupNameInFieldList[fl, id];
IF field = NIL THEN field _ BD.LookupNameInContextRib[id, lc.parentRib];
[access, lookedUpTGN] _ BD.DemandTypeDeclarationField[field];
RETURN [lookedUpTGN];
END
ELSE BEGIN
WITH tgn.body SELECT FROM
t: PT.ArrayTGN => {
t.indexType _ LookupTypeIdentifiers[t.indexType, fl, lc]; 
t.itemType _ LookupTypeIdentifiers[t.itemType, fl, lc];
};
t: PT.AtomTGN => {};
t: PT.BlockTGN => ERROR EH.InternalError["Name in local context bound to block TGN"];
t: PT.ConditionTGN => {};
t: PT.DescriptorTGN => t.itemType _ LookupTypeIdentifiers[t.itemType, fl, lc];
t: REF base PT.ElementTGNBody => {};
t: REF subrange PT.ElementTGNBody => 
t.body.baseType _ LookupTypeIdentifiers[t.body.baseType, fl, lc];
t: PT.InterfaceTGN => ERROR EH.InternalError["Name in local context bound to interface TGN"];
t: PT.ListTGN => t.elementType _ LookupTypeIdentifiers[t.elementType, fl, lc];
t: PT.LongTGN => t.underlyingType _ LookupTypeIdentifiers[t.underlyingType, fl, lc];
t: PT.MonitorlockTGN => {};
t: PT.NamedTGN => t.type _ LookupTypeIdentifiers[t.type, fl, lc];
t: PT.OpaqueTGN => {};
t: PT.PointerTGN => t.target _ LookupTypeIdentifiers[t.target, fl, lc];
t: PT.RealTGN => {};
t: PT.RecordTGN => LookupTypeIdentifiersInFrozenFieldList[t.fields, fl, lc];
t: PT.RefTGN => t.target _ LookupTypeIdentifiers[t.target, fl, lc];
t: PT.ReferentTGN => t.contents _ LookupTypeIdentifiers[t.contents, fl, lc];
t: PT.RelativeTGN => {
t.base _ LookupTypeIdentifiers[t.base, fl, lc]; 
t.pointer _ LookupTypeIdentifiers[t.pointer, fl, lc];
};
t: PT.SequenceTGN => {
t.tagType _ LookupTypeIdentifiers[t.tagType, fl, lc]; 
t.type _ LookupTypeIdentifiers[t.type, fl, lc];
};
t: PT.SpecianatedTGN => {
t.underlyingType _ LookupTypeIdentifiers[t.underlyingType, fl, lc];
};
t: PT.StringTGN => {};
t: PT.TopTGN => {};
t: PT.BottomTGN => {};
t: PT.TransferTGN => {
LookupTypeIdentifiersInFrozenFieldList[t.arguments, fl, lc];
LookupTypeIdentifiersInFrozenFieldList[t.results, fl, lc];
};
t: PT.UnspecifiedTGN => {};
t: PT.VarTGN => t.target _ LookupTypeIdentifiers[t.target, fl, lc];
t: PT.VariantPartTGN => {
t.tagType _ LookupTypeIdentifiers[t.tagType, fl, lc];
LookupTypeIdentifiersInFrozenUnionList[t.types, fl, lc];
};
t: PT.ZoneTGN => {};
ENDCASE => ERROR;
RETURN [tgn];
END;
END;

LookupTypeIdentifiersInFrozenFieldList: PROC [ffl: FrozenFieldListNode, fl: FieldListNode, lc: LocalContextNode] = BEGIN
LookupTypeIdentifiersInFieldList[ffl.cells, fl, lc];
END;

LookupTypeIdentifiersInFieldList: PROC [arg: FieldListNode, fl: FieldListNode, lc: LocalContextNode] = BEGIN
FOR cell: PT.FieldListCell _ arg.first, cell.next WHILE (cell # NIL) DO
WITH cell.node SELECT FROM
f: REF typeDecl FieldNodeBody 	=> f.type _ LookupTypeIdentifiers[f.type, fl, lc];
f: REF constant FieldNodeBody 	=> f.type _ LookupTypeIdentifiers[f.type, fl, lc];
f: REF variable FieldNodeBody 	=> f.type _ LookupTypeIdentifiers[f.type, fl, lc];
f: REF recordField FieldNodeBody	=> f.type _ LookupTypeIdentifiers[f.type, fl, lc];
ENDCASE => ERROR;
ENDLOOP;
END;

LookupTypeIdentifiersInFrozenUnionList: PROC [ful: PT.FrozenUnionList, fl: FieldListNode, lc: LocalContextNode] = BEGIN
FOR i: INT IN [0..ful.nTypes) DO
LookupTypeIdentifiersInFrozenFieldList[ful[i].fields, fl, lc];
ENDLOOP;
END;



DiscernSpecianatedTGNs: PUBLIC PROC [fl: FieldListNode, lc: LocalContextNode] RETURNS [FieldListNode] = BEGIN
DiscernSpecTGNsInFieldList[fl, fl, lc];
RETURN [fl];
END;

DiscernSpecTGNs: PROC [tgn: TypeGraphNodeNode, fl: FieldListNode, lc: LocalContextNode] RETURNS [TypeGraphNodeNode _ NIL] = BEGIN
IF ISTYPE[tgn.body, PT.SpecianatedTGN]
THEN BEGIN
stgn: PT.SpecianatedTGN _ NARROW[tgn.body];
underlyingType: TypeGraphNodeNode _ stgn.underlyingType;
restrictionList: LIST OF GEN.IdNode _ NIL;
WHILE TRUE DO 
WITH underlyingType.body SELECT FROM
ut: PT.NamedTGN => {underlyingType _ ut.type; restrictionList _ ut.restriction};
ENDCASE	=> ERROR EH.FatalError[0, "Bad type underlying specianated tgn"];
ENDLOOP;
END
ELSE BEGIN
WITH tgn.body SELECT FROM
t: PT.ArrayTGN => {
t.indexType _ DiscernSpecTGNs[t.indexType, fl, lc]; 
t.itemType _ DiscernSpecTGNs[t.itemType, fl, lc];
};
t: PT.AtomTGN => {};
t: PT.BlockTGN => ERROR EH.InternalError["Name in local context bound to block TGN"];
t: PT.ConditionTGN => {};
t: PT.DescriptorTGN => t.itemType _ DiscernSpecTGNs[t.itemType, fl, lc];
t: REF base PT.ElementTGNBody => {};
t: REF subrange PT.ElementTGNBody => 
t.body.baseType _ DiscernSpecTGNs[t.body.baseType, fl, lc];
t: PT.InterfaceTGN => ERROR EH.InternalError["Name in local context bound to interface TGN"];
t: PT.ListTGN => t.elementType _ DiscernSpecTGNs[t.elementType, fl, lc];
t: PT.LongTGN => t.underlyingType _ DiscernSpecTGNs[t.underlyingType, fl, lc];
t: PT.MonitorlockTGN => {};
t: PT.NamedTGN => t.type _ DiscernSpecTGNs[t.type, fl, lc];
t: PT.OpaqueTGN => {};
t: PT.PointerTGN => t.target _ DiscernSpecTGNs[t.target, fl, lc];
t: PT.RealTGN => {};
t: PT.RecordTGN => DiscernSpecTGNsInFrozenFieldList[t.fields, fl, lc];
t: PT.RefTGN => t.target _ DiscernSpecTGNs[t.target, fl, lc];
t: PT.ReferentTGN => t.contents _ DiscernSpecTGNs[t.contents, fl, lc];
t: PT.RelativeTGN => {
t.base _ DiscernSpecTGNs[t.base, fl, lc]; 
t.pointer _ DiscernSpecTGNs[t.pointer, fl, lc];
};
t: PT.SequenceTGN => {
t.tagType _ DiscernSpecTGNs[t.tagType, fl, lc]; 
t.type _ DiscernSpecTGNs[t.type, fl, lc];
};
t: PT.StringTGN => {};
t: PT.TopTGN => {};
t: PT.BottomTGN => {};
t: PT.TransferTGN => {
DiscernSpecTGNsInFrozenFieldList[t.arguments, fl, lc];
DiscernSpecTGNsInFrozenFieldList[t.results, fl, lc];
};
t: PT.UnspecifiedTGN => {};
t: PT.VarTGN => t.target _ DiscernSpecTGNs[t.target, fl, lc];
t: PT.VariantPartTGN => {
t.tagType _ DiscernSpecTGNs[t.tagType, fl, lc];
DiscernSpecTGNsInFrozenUnionList[t.types, fl, lc];
};
t: PT.ZoneTGN => {};
ENDCASE => ERROR;
RETURN [tgn];
END;
END;

DiscernSpecTGNsInFrozenFieldList: PROC [ffl: FrozenFieldListNode, fl: FieldListNode, lc: LocalContextNode] = BEGIN
DiscernSpecTGNsInFieldList[ffl.cells, fl, lc];
END;

DiscernSpecTGNsInFieldList: PROC [arg: FieldListNode, fl: FieldListNode, lc: LocalContextNode] = BEGIN
FOR cell: PT.FieldListCell _ arg.first, cell.next WHILE (cell # NIL) DO
WITH cell.node SELECT FROM
f: REF typeDecl FieldNodeBody 	=> f.type _ DiscernSpecTGNs[f.type, fl, lc];
f: REF constant FieldNodeBody 	=> f.type _ DiscernSpecTGNs[f.type, fl, lc];
f: REF variable FieldNodeBody 	=> f.type _ DiscernSpecTGNs[f.type, fl, lc];
f: REF recordField FieldNodeBody	=> f.type _ DiscernSpecTGNs[f.type, fl, lc];
ENDCASE => ERROR;
ENDLOOP;
END;

DiscernSpecTGNsInFrozenUnionList: PROC [ful: PT.FrozenUnionList, fl: FieldListNode, lc: LocalContextNode] = BEGIN
FOR i: INT IN [0..ful.nTypes) DO
DiscernSpecTGNsInFrozenFieldList[ful[i].fields, fl, lc];
ENDLOOP;
END;



DependencyGraphNode: TYPE = REF DependencyGraphNodeBody;
DependencyGraphNodeBody: PUBLIC TYPE = PT.DependencyGraphNodeBody;

DependencyGraphNodeNode: TYPE = REF DependencyGraphNodeNodeBody;
DependencyGraphNodeNodeBody: PUBLIC TYPE = PT.DependencyGraphNodeNodeBody;

DependencyGraphNodeCell: TYPE = REF DependencyGraphNodeCellBody;
DependencyGraphNodeCellBody: PUBLIC TYPE = PT.DependencyGraphNodeCellBody;

DependencyKind: PUBLIC TYPE = PT.DependencyKind;


CreateDependencyGraph: PROC [fl: FieldListNode, lc: LocalContextNode] RETURNS [DependencyGraphNode] = BEGIN
dg: DependencyGraphNode _ NEW[DependencyGraphNodeBody _ [lc, NIL]];
AddDGN: PROC [dgn: DependencyGraphNodeNode] = BEGIN
dg.roots _ CONS[dgn, dg.roots];
END;
FOR cell: PT.FieldListCell _ fl.first, cell.next WHILE (cell # NIL) DO
WITH cell.node SELECT FROM
c: REF typeDecl FieldNodeBody => {
namedTGN: PT.NamedTGN _ NARROW[c.type.body];
AddDGN[NEW[DependencyGraphNodeNodeBody _ 
[TRASH, NIL, NIL, size[cell.node]]]];
IF ISTYPE[namedTGN.type.body, PT.ElementTGN] THEN {
AddDGN[NEW[DependencyGraphNodeNodeBody _ 
[TRASH, NIL, NIL, first[cell.node]]]];
AddDGN[NEW[DependencyGraphNodeNodeBody _ 
[TRASH, NIL, NIL, last[cell.node]]]];
};
};
c: REF constant FieldNodeBody => {
AddDGN[NEW[DependencyGraphNodeNodeBody _ 
[TRASH, NIL, NIL, value[cell.node]]]];
};
c: REF variable FieldNodeBody => {
AddDGN[NEW[DependencyGraphNodeNodeBody _ 
[TRASH, NIL, NIL, value[cell.node]]]];
};
ENDCASE	=>
ERROR EH.InternalError["Bad kind of field for dependency analysis"];
ENDLOOP;
AddDGN[NEW[DependencyGraphNodeNodeBody _ [TRASH, NIL, NIL, runtime[]]]];
RETURN[dg];
END;

FakeDamageDependencyGraph: PUBLIC PROC [dg: DependencyGraphNode] RETURNS [DependencyGraphNode] = { RETURN [dg] };

FindDGN: PROC [dg: DependencyGraphNode, id: GEN.IdNode, kind: DependencyKind] RETURNS [found: BOOLEAN, dgn: DependencyGraphNodeNode]  = BEGIN
FOR roots: LIST OF DependencyGraphNodeNode _ dg.roots, roots.rest WHILE (roots # NIL) DO
dgn: DependencyGraphNodeNode _ roots.first;
IF (dgn.dependencyKind = kind) AND (WITH dgn SELECT FROM 
d: REF value DependencyGraphNodeNodeBody	=> Rope.Equal[id.text, d.of.name.text],
d: REF first DependencyGraphNodeNodeBody	=> Rope.Equal[id.text, d.of.name.text],
d: REF last DependencyGraphNodeNodeBody	=> Rope.Equal[id.text, d.of.name.text],
d: REF size DependencyGraphNodeNodeBody	=> Rope.Equal[id.text, d.of.name.text],
d: REF runtime DependencyGraphNodeNodeBody	=> TRUE,
ENDCASE				=> ERROR
)
THEN RETURN[TRUE, dgn];
ENDLOOP;
RETURN[FALSE, NIL];
END;

AddDependency: PROC [dgn1, dgn2: DependencyGraphNodeNode] = BEGIN
cell: DependencyGraphNodeCell _ NEW[DependencyGraphNodeCellBody _ [dgn2, NIL]];
IF dgn1.first = NIL
THEN dgn1.first _ cell
ELSE dgn1.last.next _ cell;
dgn1.last _ cell;
END;

AddFirstDependency: PUBLIC PROC [dg: DependencyGraphNode, dgn1: DependencyGraphNodeNode, id: GEN.IdNode] RETURNS [DependencyGraphNode] = BEGIN
found: BOOLEAN;
dgn2: DependencyGraphNodeNode;
[found, dgn2] _ FindDGN[dg, id, first];
IF found 
THEN AddDependency[dgn1, dgn2]
ELSE [] _ BD.DemandTypeDeclarationField[BD.LookupNameInContextRib[id, dg.lc.parentRib]];
RETURN [dg];
END;

AddLastDependency: PUBLIC PROC [dg: DependencyGraphNode, dgn1: DependencyGraphNodeNode, id: GEN.IdNode] RETURNS [DependencyGraphNode] = BEGIN
found: BOOLEAN;
dgn2: DependencyGraphNodeNode;
[found, dgn2] _ FindDGN[dg, id, last];
IF found 
THEN AddDependency[dgn1, dgn2]
ELSE [] _ BD.DemandTypeDeclarationField[BD.LookupNameInContextRib[id, dg.lc.parentRib]];
RETURN [dg];
END;

AddSizeDependency: PUBLIC PROC [dg: DependencyGraphNode, dgn1: DependencyGraphNodeNode, id: GEN.IdNode] RETURNS [DependencyGraphNode] = BEGIN
found: BOOLEAN;
dgn2: DependencyGraphNodeNode;
[found, dgn2] _ FindDGN[dg, id, size];
IF found 
THEN AddDependency[dgn1, dgn2]
ELSE [] _ BD.DemandTypeDeclarationField[BD.LookupNameInContextRib[id, dg.lc.parentRib]];
RETURN [dg];
END;

AddValueDependency: PUBLIC PROC [dg: DependencyGraphNode, dgn1: DependencyGraphNodeNode, id: GEN.IdNode] RETURNS [DependencyGraphNode] = BEGIN
found: BOOLEAN;
dgn2: DependencyGraphNodeNode;
[found, dgn2] _ FindDGN[dg, id, value];
IF found 
THEN AddDependency[dgn1, dgn2]
ELSE {
dg _ AddRuntimeDependency[dg, dgn1]; -- FIX ME!
};
RETURN [dg];
END;

AddRuntimeDependency: PUBLIC PROC [dg: DependencyGraphNode, dgn1: DependencyGraphNodeNode] RETURNS [DependencyGraphNode] = BEGIN
found: BOOLEAN;
dgn2: DependencyGraphNodeNode;
[found, dgn2] _ FindDGN[dg, NIL, runtime];
IF NOT found THEN ERROR;
AddDependency[dgn1, dgn2];
RETURN [dg];
END;


ShowDependencyGraph: PUBLIC PROC [on: IO.STREAM, nest: INT, dg: DependencyGraphNode] = BEGIN
FOR roots: LIST OF DependencyGraphNodeNode _ dg.roots, roots.rest WHILE (roots # NIL) DO
dgn: DependencyGraphNodeNode _ roots.first;
IF dgn.dependencyKind # runtime THEN {
IO.PutF[on, "%g depends on ", IO.rope[RopeFromDGN[dgn]]];
IF dgn.first = NIL 
THEN IO.PutF[on, "nothing"]
ELSE FOR cell: DependencyGraphNodeCell _ dgn.first, cell.next WHILE (cell # NIL) DO
IO.PutF[on, "%g", IO.rope[RopeFromDGN[cell.dependsOn]]];
IF cell.next # NIL THEN IO.PutF[on, ", "];
ENDLOOP;
IO.PutF[on, "\n"];
};
ENDLOOP;
END;


RopeFromDGN: PROC [dgn: DependencyGraphNodeNode] RETURNS [Rope.ROPE] = BEGIN
RETURN [WITH dgn SELECT FROM
d: REF value DependencyGraphNodeNodeBody	=> 
IO.PutFR["value of %g", IO.rope[d.of.name.text]],
d: REF first DependencyGraphNodeNodeBody	=> 
IO.PutFR["FIRST[%g]", IO.rope[d.of.name.text]],
d: REF last DependencyGraphNodeNodeBody	=> 
IO.PutFR["LAST[%g]", IO.rope[d.of.name.text]],
d: REF size DependencyGraphNodeNodeBody	=> 
IO.PutFR["SIZE[%g]", IO.rope[d.of.name.text]],
d: REF runtime DependencyGraphNodeNodeBody	=> 
"runtime state"
ENDCASE				=> ERROR
];
END;
BuildDependencyGraph: PUBLIC PROC [fl: FieldListNode, lc: LocalContextNode] RETURNS [DependencyGraphNode] = BEGIN
dg: DependencyGraphNode _ CreateDependencyGraph[fl, lc];
FOR cell: PT.FieldListCell _ fl.first, cell.next WHILE (cell # NIL) DO
WITH cell.node SELECT FROM
c: REF typeDecl FieldNodeBody => {
dgn1: DependencyGraphNodeNode _ FindDGN[dg, cell.node.name, size].dgn;
typeExp: AT.TypeExpNode _ c.parseTree;
namedTGN: PT.NamedTGN _ NARROW[c.type.body];
IF typeExp = NIL -- is it an opaque type?
THEN NULL -- eventually, we have to hook into the opaque type's OptSize....
ELSE dg _ typeExp.procs.AddSizeDependencies[typeExp, dg, dgn1];
IF ISTYPE[namedTGN.type.body, PT.ElementTGN] THEN {
elementTGN: PT.ElementTGN _ NARROW[namedTGN.type.body];
dgnf: DependencyGraphNodeNode _ FindDGN[dg, cell.node.name, first].dgn;
dgnl: DependencyGraphNodeNode _ FindDGN[dg, cell.node.name, last].dgn;
dg _ typeExp.procs.AddFirstDependencies[typeExp, dg, dgnf];
dg _ typeExp.procs.AddLastDependencies[typeExp, dg, dgnl];
};

};
c: REF constant FieldNodeBody => {
dgn1: DependencyGraphNodeNode _ FindDGN[dg, cell.node.name, value].dgn;
initialization: AT.InitializationNode _ c.initialization.node;
dg _ initialization.procs.AddValueDependencies[initialization, dg, dgn1];
};
c: REF variable FieldNodeBody => {
dgn1: DependencyGraphNodeNode _ FindDGN[dg, cell.node.name, value].dgn;
dg _ AddRuntimeDependency[dg, dgn1];
};
ENDCASE	=>
ERROR EH.InternalError["Bad kind of field for dependency analysis"];
ENDLOOP;
RETURN [dg];
END;

WalkDependencyGraph: PROC [dg: DependencyGraphNode, nodeProc: PROC [DependencyGraphNodeNode]] = BEGIN
FOR rootList: LIST OF DependencyGraphNodeNode _ dg.roots, rootList.rest 
WHILE (rootList # NIL) DO
rootList.first.visited _ FALSE;
ENDLOOP;
FOR rootList: LIST OF DependencyGraphNodeNode _ dg.roots, rootList.rest 
WHILE (rootList # NIL) DO
VisitNode[rootList.first, NIL, nodeProc];
ENDLOOP;
END;
VisitNode: PROC [node: DependencyGraphNodeNode, path: LIST OF DependencyGraphNodeNode, nodeProc: PROC [DependencyGraphNodeNode]] = BEGIN
IF node.visited THEN RETURN;
IF NodeIsInPath[node, path] THEN {
ros: IO.STREAM _ IO.ROS[];
ros.PutF["Cycle in dependency graph: %g", IO.rope[RopeFromDGN[node]]];
FOR p: LIST OF DependencyGraphNodeNode _ path, p.rest WHILE (p # NIL) DO
ros.PutF[" _ %g", IO.rope[RopeFromDGN[p.first]]];
IF p.first = node THEN EXIT;
ENDLOOP;
ERROR EH.FatalError[0, ros.RopeFromROS[]];
};
FOR cell: DependencyGraphNodeCell _ node.first, cell.next WHILE (cell # NIL) DO
VisitNode[cell.dependsOn, CONS[node, path], nodeProc];
ENDLOOP;
nodeProc[node];
node.visited _ TRUE;
END;

NodeIsInPath: PROC [dgn: DependencyGraphNodeNode, path: LIST OF DependencyGraphNodeNode] RETURNS [BOOLEAN] = BEGIN
FOR p: LIST OF DependencyGraphNodeNode _ path, p.rest WHILE (p # NIL) DO
IF p.first = dgn THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];
END;

NullNodeProc: PROC [dgn: DependencyGraphNodeNode] = BEGIN
SIGNAL EH.Message[IO.PutFR["Doing DGN %g", IO.rope[RopeFromDGN[dgn]]]];
END;

DependsOnRuntimeState: PROC [dgn: DependencyGraphNodeNode] RETURNS [BOOLEAN] = BEGIN
IF dgn.dependencyKind = runtime THEN RETURN [TRUE];
FOR cell: DependencyGraphNodeCell _ dgn.first, cell.next WHILE (cell # NIL) DO
IF DependsOnRuntimeState[cell.dependsOn] THEN RETURN [TRUE];
ENDLOOP;
RETURN [FALSE];
END;



END.
��1–��SaffronDeclarationAnalysisImpl.mesa
Last edited by: James Rauen August 25, 1988 4:36:21 pm PDT
Primitives for constructing and analyzing dependency graphs.

Perform the analysis described above on contextNode.  If contextNode is okay, fill in all of its SIZE, FIRST, and LAST fields.  (If we get really clever, and lucky, maybe we can also discriminate the Specianated types.) 
CompileDecList: PUBLIC PROC [decls: AT.DecListNode, lc: LocalContextNode, cs: BD.CompilerStateNode] RETURNS [LocalContextNode] = BEGIN
This is the starting point for compiling a list of declarations.  CompileDecList does the following:
(1) Build a field list with one entry for each name declared in decls.  Represent identifiers appearing where type expressions are expected as IdentifierTGN's.  Represent identifiers appearing where value expressions are expected as ???.
(2) Chill the field list, create a BlockTGN, and stuff the BlockTGN into lc's contents.
(3) Look up the names stubbed out in part (1), bashing their occurrences.
(4) Build a dependency graph for the names declared in decls.
(5) Walk through the dependency graph, filling in size/value/first/last attributes.  (Note that the bodies of procedure definitions, etc., are handled at this point).
(6) Return the local context, ready to be frozen into a rib. 
fl: BD.FieldListNode;
ffl: BD.FrozenFieldListNode;
block: TypeGraphNodeNode;

Build a field list with one entry for each name declared in decls.  Represent identifiers appearing where type expressions are expected as IdentifierTGN's.  Represent identifiers appearing where value expressions are expected as ???.  Chill the field list, create a BlockTGN, and stuff the BlockTGN into lc's contents.

[fl, lc] _ decls.procs.AddDeclarationsToFieldList[decls, BD.CreateEmptyFieldList[], lc, cs];
[lc, ffl] _ BD.FreezeFieldList[lc, fl];
[lc, block] _ BD.CreateBlockTGN[lc, ffl];
lc.contents _ NEW[PT.LocalContextContentsBody _ [frozen[block]]];

Now go back and look up all the IdentiferTGNs.  Replace the body field of each identifer TypeGraphNode with named TypeGraphNode corresponding to the identifier.  (Note: At this point, all value expressions are still trash or unparsed or defaultMe.)

LookupTypeIdentifersInLocalContext[lc, ffl];

Build a dependency graph for the names declared in decls.

lc.dependencyGraph _ BuildDependencyGraph[ffl, lc];

Do a topological sort of the dependency graph, performing the following on each node:
If the node is a value node which does not ultimately depend on the runtime state, then it must represent a static (compile-time constant) value.  Use the expression compiler to change the value's parse tree into a static representation.
If the node is a value node which ultimately depends on the runtime state, then it represents a variable or runtime constant.  Do nothing with it at this time.
If the node is a FIRST, LAST, or SIZE node which does not ultimately depend on the runtime state, then use the expression compiler to compute a static value and stuff this value into the appropriate slot of the appropriate type graph node.
If the node is a FIRST, LAST, or SIZE node which ultimately depends on the runtime state, then raise an error.
This will determine all the compile-time (static) quantities in the dependency graph.

BEGIN
NodeProc: PROC [dgn: DependencyGraphNodeNode] = BEGIN
WITH dgn SELECT FROM
d: REF value DependencyGraphNodeNodeBody =>
IF NOT DependsOnRuntimeState[dgn] THEN {
field: REF constant FieldNodeBody _ NARROW[d.of];
targetType: TypeGraphNodeNode _ field.type;
expNode: AT.ExpNode _ NARROW[field.value, REF unparsed ValueNodeBody].parseTree;
[field.value, lc] _ AT.CompileAndTypeCheckExpression[expNode, lc, cs, targetType];
};
d: REF runtime DependencyGraphNodeNodeBody => {};
d: REF size DependencyGraphNodeNodeBody => 
SIGNAL EH.Warning[0, "size dgn proc not yet implemented"];
d: REF first DependencyGraphNodeNodeBody => 
IF DependsOnRuntimeState[dgn] 
THEN ERROR EH.FatalError[0, "FIRST[] is not constant"]
ELSE {
field: REF typeDecl FieldNodeBody _ NARROW[d.of];
namedType: PT.NamedTGN _ NARROW[field.type.body];
elementTGN: PT.ElementTGN _ NARROW[namedType.type.body];
WITH elementTGN SELECT FROM
e: REF subrange PT.ElementTGNBody => {
expNode: AT.ExpNode _ NARROW[e.body.firstElement, REF unparsed ValueNodeBody].parseTree;
[e.body.firstElement, lc] _ AT.CompileAndTypeCheckExpression[expNode, lc, cs, e.body.baseType];
};
e: REF enumerated base PT.ElementTGNBody => {
SIGNAL EH.Warning[0, "first dgn proc not yet implemented for base enumerated tgn"]
};
ENDCASE => ERROR EH.InternalError["should not be dependency-analyzing this kind of element type"];
};
d: REF last DependencyGraphNodeNodeBody => 
IF DependsOnRuntimeState[dgn] 
THEN ERROR EH.FatalError[0, "LAST[] is not constant"]
ELSE {
field: REF typeDecl FieldNodeBody _ NARROW[d.of];
namedType: PT.NamedTGN _ NARROW[field.type.body];
elementTGN: PT.ElementTGN _ NARROW[namedType.type.body];
WITH elementTGN SELECT FROM
e: REF subrange PT.ElementTGNBody => {
expNode: AT.ExpNode _ NARROW[e.body.lastElement, REF unparsed ValueNodeBody].parseTree;
[e.body.lastElement, lc] _ AT.CompileAndTypeCheckExpression[expNode, lc, cs, e.body.baseType];
};
e: REF enumerated base PT.ElementTGNBody => {
SIGNAL EH.Warning[0, "last dgn proc not yet implemented for base enumerated tgn"]
};
ENDCASE => ERROR EH.InternalError["should not be dependency-analyzing this kind of element type"];
};
ENDCASE;
END;
lc.dependencyGraph _ BuildDependencyGraph[ffl, lc];
WalkDependencyGraph[lc.dependencyGraph, NodeProc];
END;

Now, proceed sequentially through the field list (the declarations), performing the following on each field:
If the field is a TYPE declaration, ignore it.  (What about type codes, etc.?)
If the field is a constant declaration and the ValueNode in its value slot is a static ValueNode, then we know that the field represents a compile-time constant  and that it was processed in the previous step.  So, ignore it.  (Fill in its code? -- no, the static value constructors should do this!).
If the field is a constant declaration and the ValueNode in its value slot is an unparsed value, then we know that it is a runtime constant.  Compile the ValueNode, producing a runtime ValueNode, and stuff this new node into the field's value slot.
(Can constants be initialized to trash?  They probably can!)
If the field is a variable declaration, then look at its initialValue slot:  
If there is a defaultMe ValueNode there, then no initialization was provided for the variable.  Check to see if the variable's type has a default initialization.  If so, produce a ValueNode containing this  (how???).  If not, produce a trash ValueNode.  Either way, stuff the new ValueNode into the field's initialValue slot.
If there is an unparsed ValueNode there, then compile the expression (producing a static or runtime ValueNode) and stuff this new ValueNode into the field's initialValue slot. 
If there is a trash ValueNode there, then the variable was explicitly initialized to TRASH.  Do nothing else.
Foo. 

BEGIN
FOR cell: PT.FieldListCell _ ffl.cells.first, cell.next WHILE (cell # NIL) DO
WITH cell.node SELECT FROM
field: REF typeDecl FieldNodeBody => {};
field: REF constant FieldNodeBody => {
WITH field.value SELECT FROM
value: REF static ValueNodeBody	=> {};
value: REF unparsed ValueNodeBody => {
[field.value, lc] _ AT.CompileAndTypeCheckExpression[value.parseTree, lc, cs, field.type];
};
value: REF trash ValueNodeBody => {};
ENDCASE	=> ERROR EH.InternalError["a"];
};
field: REF variable FieldNodeBody => {
WITH field.initialValue SELECT FROM
initialValue: REF defaultMe ValueNodeBody => {
field.initialValue _ BD.MakeTrash[field.type]
this also must check field.type for a default initialization!!
};
initialValue: REF unparsed ValueNodeBody => {
[field.initialValue, lc] _ AT.CompileAndTypeCheckExpression[initialValue.parseTree, lc, cs, field.type];
};
initialValue: REF trash ValueNodeBody => {};
ENDCASE	=> ERROR EH.InternalError["b"];
};
ENDCASE	=> ERROR EH.InternalError["c"];
ENDLOOP;
END;

Return the local context.

RETURN[lc];

END;
Looking Up IdentiferTGN's
t: PT.LinkTGN => {
t.tgn _ LookupTypeIdentifiers[t.tgn, fl, lc]; 
t.if _ LookupTypeIdentifiers[t.if, fl, lc];
};
Discerning SpecianatedTGN's
ut: PT.InterfaceTGN => 
IF (stgn.idParam = NIL) OR (stgn.expParam # NIL) 
THEN ERROR EH.FatalError[0, "Bad form of interface field selector"]
ELSE {
WHILE restrictionList # NIL DO
IF Rope.Equal[restrictionList.first.text, stgn.idParam.text]
THEN {
field: FieldNode _ SaffronContext.LookupNameInFieldList[ut.entries.cells, stgn.idParam];
WITH field SELECT FROM
f: REF typeDecl FieldNodeBody => RETURN[f.type];
ENDCASE => ERROR EH.FatalError[stgn.idParam.position, "Mumblefrotz in interface is not a type."];
}
ELSE restrictionList _ restrictionList.rest;
ENDLOOP;
ERROR EH.FatalError[stgn.idParam.position, IO.PutFR["%g is not valid as an interface field selector.", IO.rope[stgn.idParam.text]]];
};
a better error message, please?
t: PT.LinkTGN => {
t.tgn _ DiscernSpecTGNs[t.tgn, fl, lc]; 
t.if _ DiscernSpecTGNs[t.if, fl, lc];
};
Dependency Graph Primitives
Create a dependency graph with one node for each interesting quantity in ffl, plus an extra node indicating a runtime or side-effecting value.
do lookups
Add the dependency "dgn1 depends on dgn2"
SIGNAL EH.Message[IO.PutFR["Adding dependency: %g depends on %g", IO.rope[RopeFromDGN[dgn1]], IO.rope[RopeFromDGN[dgn2]]]];
if "first[id]" is not in dg, then just demand that id names a type.  If id does name a type, then this type must be in a higher context, and its size must therefore already be known.  If id doesn't name a type, then the call to LookupTypeNameInLocalContext will cause an error.  If it turns out that id is in dg, but first[id] isn't, then something else had better catch the error.  (the expression compiler?) but it shouldn't affect the validity of the dependency graph.  VERIFY THIS!!!  OR FIX IT!!!
if "last[id]" is not in dg, then just demand that id names a type.  If id does name a type, then this type must be in a higher context, and its size must therefore already be known.  If id doesn't name a type, then the call to LookupTypeNameInLocalContext will cause an error.  If it turns out that id is in dg, but first[id] isn't, then something else had better catch the error.  (the expression compiler?) but it shouldn't affect the validity of the dependency graph.  VERIFY THIS!!!  OR FIX IT!!!
if "size[id]" is not in dg, then just demand that id names a type.  If id does name a type, then this type must be in a higher context, and its size must therefore already be known.  If id doesn't name a type, then the call to LookupTypeNameInLocalContext will cause an error.
pfd: ParameterizedFieldDescriptorNode;
tgn: TypeGraphNodeNode;
[pfd, tgn] _ BD.GetPathToName[dg.lc, id];
IF NOT BD.Static[BD.CompileLValueIntoRValue[pfd, dg.lc]]
THEN dg _ AddRuntimeDependency[dg, dgn1];
Dependency Graph Construction
this does not catch named-named types, etc.  maybe a predicate in TypeConformanceImpl?
valueExp: AT.ExpNode _ NARROW[c.value, REF unparsed ValueNodeBody].parseTree;
dg _ valueExp.procs.AddValueDependencies[valueExp, dg, dgn1];

Topological Sort
Perform a topological sort on dg.  Apply nodeProc to each node of dg, applying nodeProc to a node n only after having applied it to all the nodes that n depends upon.  Signal an error and return immediately if a cycle is detected.

Return TRUE if dgn is an element of path, FALSE if it isn't.
Return TRUE if there is a path from dgn to a runtime DGN, FALSE otherwise. 
AddDeclarationsToLocalContext: PUBLIC PROC [fl: BD.FieldListNode, lc: LocalContextNode, cs: BD.CompilerStateNode] RETURNS [LocalContextNode] = BEGIN
fl should have been accumulated by calls to AddDeclarationToFieldList.  At this point, we have a field list which contains type graph trees (no names looked up yet).   This procedure looks up all the names referenced in fl, links them up, performs dependency analysis, and stuffs the resulting field list into the local context.
This should eventually be merged with FreezeLocalContext.
ffl: FrozenFieldListNode _ FreezeFieldList[lc, fl].ffl;
block: TypeGraphNodeNode _ CreateBlockTGN[lc, ffl].tgn;
lc.contents _ NEW[PT.LocalContextContentsBody _ [frozen[block]]];
RETURN [lc];
END;

moved to SaffronContextCreateCTImpl

MakeFieldListFromDecList: PUBLIC PROC [decls: AT.DecListNode, lc: LocalContextNode, cs: BD.CompilerStateNode] RETURNS [BD.FieldListNode, LocalContextNode] = BEGIN
fl: BD.FieldListNode;
lc1: LocalContextNode;
[fl, lc1] _ decls.procs.AddDeclarationsToFieldList[
decls, BD.CreateEmptyFieldList[], lc, cs];
link em up
dependency analysis
RETURN [fl, lc];
END;
ÊZ��˜�šœ#™#Icodešœ:™:—lead1™<K™�—šÏk	˜	Kšœœ"œœ˜7Kšœœ	œ˜Kšœ
œL˜^Kšœœz˜ŽKšœœ˜Kšœ˜Kšœœ/˜IKšœœ
˜!Kšœ œ(˜MK˜�—šÏnœœœ˜.Kšœœ:˜DKšœ˜&Kšœ˜K˜�šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ"˜$Kšœ˜—K˜�Kšœœœ˜2Kšœœœœ˜<K˜�Kšœœœ˜.Kšœœœœ˜8K˜�Jšœœœ˜8Jšœœœœ˜BJ˜�Jšœœœ˜,Jšœœœœ˜6J˜�Jšœœœ˜4Jšœœœœ˜>J˜�Jšœœœ˜$Jšœœœœ˜.J˜�Jšœœœ˜$Jšœœœœ˜.J˜�Jšœ"œœ&˜RJšœ&œœœ&˜\J˜�J˜�š
žœœœHœœ$˜©Kšœaœœœf™ÜKš˜šžœœ"˜5šœœ˜šœœ%˜+šœœœ˜(Kšœœœ˜1Kšœ+˜+Kšœ	œœœ#˜PKšœœA˜QK˜——Kšœœ+˜1šœœ%˜+Kšœœ1˜:—šœœ&˜,šœ˜Kšœœœ)˜6šœ˜Kšœœœ˜1Kšœœœ˜1Kšœœœ˜8šœœ˜šœœ
œ˜&Kšœ	œœœ#˜XKšœœF˜^K˜—šœœœ˜-KšœœI˜RK˜—KšœœœO˜b—K˜———šœœ%˜+šœ˜Kšœœœ(˜5šœ˜Kšœœœ˜1Kšœœœ˜1Kšœœœ˜8šœœ˜šœœ
œ˜&Kšœ	œœœ#˜WKšœœF˜]K˜—šœœœ˜-KšœœH˜QK˜—KšœœœO˜b—K˜———Kšœ˜—Kšœ˜—Kšœ˜Kšœ2˜2Kšœ	˜Kšœ˜K˜�—š
žœœœ	œ(œœ™†™dK™íK™WK™IK™=K™¦K™=—Kšœœ™Kšœœ™Kšœ™K™�Ibody™¾K™�Kšœ9œ!™\Kšœœ™'Kšœœ™)Kšœœœ-™AK™�M™øK™�Kšœ,™,K™�™9K™�—Kšœ3™3K™�™UM™íM™ŸMšœœœœÊ™ïMšœœœœI™n—M™UK™�š™šžœœ"™5šœœ™šœœ%™+šœœœ™(Kšœœœ™1Kšœ+™+Kšœ	œœœ#™PKšœœ<™RK™——Kšœœ+™1šœœ%™+Kšœœ1™:—šœœ&™,šœ™Kšœœœ)™6šœ™Kšœœœ™1Kšœœœ™1Kšœœœ™8šœœ™šœœ
œ™&Kšœ	œœœ#™XKšœœA™_K™—šœœœ™-KšœœI™RK™—KšœœœO™b—K™———šœœ%™+šœ™Kšœœœ(™5šœ™Kšœœœ™1Kšœœœ™1Kšœœœ™8šœœ™šœœ
œ™&Kšœ	œœœ#™WKšœœA™^K™—šœœœ™-KšœœH™QK™—KšœœœO™b—K™———Kšœ™Kšœ™—Kšœ3™3Kšœ2™2—šœ™K™�——™lMšœœ8™NMšœ¬™¬Mšœø™øM™<™MM™ÅM™°MšœUœ™m——Mšœ™K™�š™š	œœ,œ	œ™Mšœœ™Kšœœ™(šœœ™&šœ
œ™Kšœœ™&šœœ™&KšœœD™ZK™—Kšœœ™%Kšœœœ™'—K™—šœœ™&šœœ™#šœœ™.Kšœœ™-K™>K™—šœœ™-KšœœK™hK™—Kšœœ™,Kšœœœ™'—K™—Kšœœœ™'—Kšœ™——Kš™K™�M™K™�Kšœ™K™�Kšœ™—K˜�—headšÏz™š	žœœœ+œ˜kKšœ-˜-Kšœ˜Kšœ˜K˜�—šžœœCœ˜šœœœ˜%šœ˜
Kšœœ˜Kšœ˜Kšœœ
œœ˜7Kšœœ˜4Kšœ	œœ	œ*˜HKšœœ#˜=Kšœ˜Kš˜—šœ˜
šœ
œ˜šœœ˜K˜:K˜7Kšœ˜—Kšœœ˜Kšœœ
œœ;˜UKšœœ˜KšœœI˜NKšœœœ˜$šœœ
œ˜%KšœA˜A—Kšœœœœ?˜]šœœ
™Kšœ.™.Kšœ+™+Kšœ™—KšœœI˜NKšœœO˜TKšœœ˜Kšœœ<˜AKšœœ˜KšœœB˜GKšœœ˜KšœœG˜LKšœœ>˜CKšœœG˜Lšœœ˜Kšœ0˜0Kšœ5˜5Kšœ˜—šœœ˜Kšœ6˜6Kšœ/˜/Kšœ˜—šœœ˜KšœC˜CK˜—Kšœœ˜Kšœœ˜Kšœœ˜šœœ˜K˜<K˜:K˜—Kšœœ˜Kšœœ>˜Cšœœ˜Kšœ5˜5K˜8K˜—Kšœœ˜Kšœœ˜—Kšœ˜
Kšœ˜——šœ˜K˜�——šž&œœG˜xKšœ4˜4Kšœ˜K˜�—šž œœA˜lš	œœ&œ	œ˜Gšœœ˜KšœœK˜QKšœœK˜QKšœœK˜QKšœœM˜SKšœœ˜—Kšœ˜—Kšœ˜K˜�—šž&œœœ=˜wšœœœ˜ Kšœ>˜>Kšœ˜—Kšœ˜K˜�K˜�K˜�——šŸ™š	žœœœ+œ˜mKšœ'˜'Kšœ˜Kšœ˜K˜�—š	žœœCœœ˜šœœœ˜&šœ˜
Kšœœœ˜+Kšœ8˜8Kš	œœœœ
œ˜*šœœœ˜šœœ˜$KšœœJ˜Pšœœ™šœœœœ™1Kšœœœ6™Cšœ™šœœ™šœ:™<šœ™KšœX™Xšœœ™Kšœœœ	™0K™a—K™—Kšœ(™,—Kšœ™—Kšœœ#œ:œ™„Kšœ™———Kšœœœ6˜IK™—Kšœ˜—Kš˜—šœ˜
šœ
œ˜šœœ˜Kšœ4˜4Kšœ1˜1Kšœ˜—Kšœœ˜Kšœœ
œœ;˜UKšœœ˜KšœœC˜HKšœœœ˜$šœœ
œ˜%Kšœ;˜;—Kšœœœœ?˜]šœœ
™Kšœ(™(Kšœ%™%Kšœ™—KšœœC˜HKšœœI˜NKšœœ˜Kšœœ6˜;Kšœœ˜Kšœœ<˜AKšœœ˜KšœœA˜FKšœœ8˜=KšœœA˜Fšœœ˜Kšœ*˜*Kšœ/˜/Kšœ˜—šœœ˜Kšœ0˜0Kšœ)˜)Kšœ˜—Kšœœ˜Kšœœ˜Kšœœ˜šœœ˜Kšœ6˜6Kšœ4˜4K˜—Kšœœ˜Kšœœ8˜=šœœ˜Kšœ/˜/Kšœ2˜2K˜—Kšœœ˜Kšœœ˜—Kšœ˜
Kšœ˜——šœ˜K˜�——šž œœG˜rKšœ.˜.Kšœ˜K˜�—šžœœA˜fš	œœ&œ	œ˜Gšœœ˜KšœœE˜KKšœœE˜KKšœœE˜KKšœœG˜MKšœœ˜—Kšœ˜—Kšœ˜K˜�—šž œœœ=˜qšœœœ˜ Kšœ8˜8Kšœ˜—Kšœ˜K˜�K˜�K˜�——šŸ™Jšœœœ˜8Jšœœœœ˜BJ˜�Jšœœœ˜@Jšœœœœ˜JJ˜�Jšœœœ˜@Jšœœœœ˜JJ˜�Jšœœœœ˜0J˜�K˜�šžœœ+œ˜kK™ŽKšœœ œ˜Cšžœœ"˜3Kšœœ˜Kšœ˜—š	œœ%œ	œ˜Fšœœ˜šœœ˜"K™
Kšœ
œœ˜,šœœ˜)Jšœ
œœ˜%—šœœœ
œ˜3šœœ˜)Jšœ
œœ˜&—šœœ˜)Jšœ
œœ˜%—J˜—J˜—šœœ˜"šœœ˜)Jšœ
œœ˜&—J˜—šœœ˜"šœœ˜)Jšœ
œœ˜&—J˜—šœ˜
Jšœœ<˜D——Jšœ˜—Jšœœ 
œœ˜HJšœ˜Jšœ˜J˜�—š
žœœœœœ˜qJ˜�—šžœœœœ	œ#˜šœœœ0œ
œ˜XKšœ+˜+š
œœœœœ˜9KšœœJ˜PKšœœJ˜PKšœœI˜OKšœœI˜OKšœœ(œ˜3Kšœ˜K˜Kšœœœ˜—Kšœ˜—Kšœœœ˜Kšœ˜K˜�—šž
œœ)˜AK™)Kšœ œ&œ˜OKš
œœ	œ.œœ™{šœ˜Kšœ˜Kšœ˜—K˜Kšœ˜K˜�—šžœœœ>œ	œ˜ŽKšœœ˜Kšœ˜Kšœ'˜'šœ˜	Kšœ˜Kšœœœ.˜XKšœõ™õ—Kšœ˜Kšœ˜K˜�—šžœœœ>œ	œ˜Kšœœ˜Kšœ˜Kšœ&˜&šœ˜	Kšœ˜Kšœœœ.˜XKšœô™ô—Kšœ˜Kšœ˜K˜�—šžœœœ>œ	œ˜Kšœœ˜Kšœ˜Kšœ&˜&šœ˜	Kšœ˜Kšœœœ.˜XKšœ”™”—Kšœ˜Kšœ˜K˜�—šžœœœ>œ	œ˜ŽKšœœ˜Kšœ˜Kšœ'˜'šœ˜	Kšœ˜šœ˜Kšœ&™&K™Kšœ
œ™)šœœœœ%™8Kšœ%™)—Kšœ%Ïc
˜/K˜——Kšœ˜Kšœ˜K˜�—š	žœœœ:œ˜€Kšœœ˜Kšœ˜Kšœœ˜*Kšœœœœ˜Kšœ˜Kšœ˜Kšœ˜K˜�K˜�—šžœœœœœ˜\šœœœ0œ
œ˜XKšœ+˜+šœœ˜&Kšœœ˜9šœ
œ˜Kšœœ˜š	œœ6œ	œ˜SKšœœ$˜8Kšœ
œœœ˜*Kšœ˜——Jšœ˜—J˜Jšœ˜—šœ˜K˜�—K˜�—š	žœœ œœ˜Lšœœœ˜šœœ&˜,Kšœœ˜1—šœœ&˜,Kšœœ˜/—šœœ%˜+Kšœœ˜.—šœœ%˜+Kšœœ˜.—šœœ(˜.Kšœ˜—Kšœ˜K˜—Kšœ˜——šŸ™šžœœ+œ˜qKšœ8˜8š	œœ%œ	œ˜Fšœœ˜šœœ˜"JšœF˜FJšœ	œ˜&Jšœ
œœ˜,šœœ ˜)Jšœœ A˜KJšœ;˜?—šœœœ
œ˜3J™VJšœœœ˜7JšœG˜GJšœF˜FJ˜;J˜:J˜J˜�—J˜—šœœ˜"JšœG˜GJšœœ,˜>JšœI˜IJšœ
œœ
œ#™MJšœ=™=J˜—šœœ˜"JšœG˜GJ˜$J˜—šœ˜
Jšœœ<˜D——Jšœ˜—Jšœ˜Jšœ˜—K™�—šŸ™K˜�šžœœ%œ˜eKšœæ™æšœœœ3˜Hšœ
œ˜Kšœœ˜Kšœ˜——šœœœ3˜Hšœ
œ˜Kšœœ˜)Kšœ˜——Kšœ˜K™�—šž	œœ'œœ$œ˜ˆKšœœœ˜šœœ˜"Kš	œœœœœ˜Kšœ*œ˜Fšœœœ(œœ˜HKšœœ˜1Kšœœœ˜Kšœ˜—Kšœœ"˜*K˜—šœ7œ	œ˜OKšœœ˜6Kšœ˜—K˜Kšœœ˜Kšœ˜K˜�—š
žœœ&œœœœ˜rKšœœœ
™<šœœœ(œœ˜HKšœœœœ˜#Jšœ˜—Kšœœ˜Kšœ˜K˜�—šžœœ"˜9Kšœœ	œœ˜GKšœ˜K˜�—š	žœœ œœ˜TKšœœ/œ™KKšœœœœ˜3šœ6œ	œ˜NKšœ'œœœ˜<Kšœ˜—Kšœœ˜Kšœ˜K˜�—š
žœœœœ*œœ™”KšœÈ™ÈK™9K™7Kšœ7™7Kšœœœ-™AKšœ™Kšœ™K™�K™#K™�—K˜�šžœœœ	œ(œœœ$™¢Kšœœ™Kšœ™šœ3™3Kšœœ!™*—K™
K™Kšœ
™Kšœ™—K˜�Kšœ˜——�…—����P ��¡��