DIRECTORY
CD, CDCells, CDCommandOps, CDDirectory, CDImports, CDOps, CDProperties, CDSatellites, CDSequencer,
Core, CoreClasses, CoreOps, CoreGeometry, CoreProperties,
IO, Rope, RopeList, 
Sinix, SinixOps, Sisyph, SymTab, 
TerminalIO, ViewerClasses;

SisyphCmdsImpl: CEDAR PROGRAM
IMPORTS CD, CDCells, CDCommandOps, CDDirectory, CDImports, CDOps, CDProperties, CDSatellites, CDSequencer, CoreClasses, CoreOps, CoreGeometry, CoreProperties, IO, Rope, RopeList, Sinix, SinixOps, Sisyph, SymTab, TerminalIO
SHARES Sinix, Sisyph = BEGIN
ROPE:		TYPE = Rope.ROPE;
ROPES:	TYPE = LIST OF ROPE;
Wire:		TYPE = Core.Wire;
Wires:		TYPE = Core.Wires;
CellType:	TYPE = Core.CellType;
UnMakeIcon: PROC [comm: CDSequencer.Command] = {
selected: CD.Instance _ TheCellInstance[comm.design, "UnMakeIcon\n"];
IF selected=NIL THEN RETURN;
CleanUpIconProperties[selected.ob];
TerminalIO.PutF
["UnMakeIcon of %g done.\n", IO.rope[CDDirectory.Name[selected.ob, comm.design]]]}; 

MakeCellIcon: PROC [comm: CDSequencer.Command] = {
key: ATOM;
rope, name: ROPE;
selected: CD.Instance _ TheCellInstance[comm.design, "MakeCellIcon\n"];
IF selected=NIL THEN RETURN;
name _ CDDirectory.Name[selected.ob, comm.design];
IF NOT Rope.Match["*.icon", name] 
THEN TerminalIO.PutF["*** Convention for icons is to suffix them with '.icon'.\n"];
SELECT TerminalIO.RequestSelection[Rope.Cat["MakeCellIcon of ", name], LIST ["From Code", "From Schematic"], "choice of the nature of the cell icon", LIST ["Code returns a CellType", "Schematic should extract as a CellType"]] FROM
1	=> {
key _ $CodeFor; rope _ TerminalIO.RequestRope["Type code: "];
TerminalIO.PutF["done.\n"]};
2	=> {
rope _ TerminalIO.RequestRope["Type schematic name: "];
IF Rope.IsEmpty[rope] AND Rope.Match["*.icon", name] 
THEN rope _ Rope.Cat[Rope.Substr[name, 0, Rope.Length[name]-5], ".sch"]; 
IF CDDirectory.Fetch[comm.design, rope]=NIL THEN {
TerminalIO.PutF["*** No object '%g' in design.\n", IO.rope[rope]];
RETURN};
IF Rope.Equal[rope, name] THEN {
TerminalIO.PutF["*** You can't do that: same icon and sch name!\n"];
RETURN};
IF NOT Rope.Match["*.sch", rope] THEN TerminalIO.PutF["*** Convention for schematics is to suffix them with '.sch'.\n"];
key _ $IconFor;
TerminalIO.PutF["%g made cell icon of %g.\n", IO.rope[name], IO.rope[rope]]};
ENDCASE	=> {TerminalIO.PutF["*** Not done.\n"]; RETURN};
CleanUpIconProperties[selected.ob];
CDProperties.PutObjectProp[selected.ob, key, rope];
CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, $SisyphExtractCellIcon]}; 

MakeWireIcon: PROC [comm: CDSequencer.Command] = {
key: ATOM;
rope, name: ROPE;
choice: INT;
selected: CD.Instance _ TheCellInstance[comm.design, "MakeWireIcon\n"];
IF selected=NIL THEN RETURN;
name _ CDDirectory.Name[selected.ob, comm.design];
IF NOT Rope.Match["*.icon", name] 
THEN TerminalIO.PutF["*** Convention for icons is to suffix them with '.icon'.\n"];
choice _ TerminalIO.RequestSelection[
Rope.Cat["MakeWireIcon of ", name], 
LIST ["From Code; Named", "From Code; UnNamed", "From Schematic; Named", "From Schematic; UnNamed"], 
"choice of the nature of the cell icon", 
LIST ["Code returns a Wire", "Code returns a Wire", "Schematic should extract as a CellType", "Schematic should extract as a CellType"] ];
SELECT choice FROM
1, 2	=> {
key _ $CodeFor; rope _ TerminalIO.RequestRope["Type code: "];
TerminalIO.PutF["done.\n"]};
3, 4	=> {
rope _ TerminalIO.RequestRope["Type schematic name: "];
IF Rope.IsEmpty[rope] AND Rope.Match["*.icon", name] 
THEN rope _ Rope.Cat[Rope.Substr[name, 0, Rope.Length[name]-5], ".sch"]; 
IF CDDirectory.Fetch[comm.design, rope]=NIL THEN {
TerminalIO.PutF["*** No object '%g' in design.\n", IO.rope[rope]];
RETURN};
IF Rope.Equal[rope, name] THEN {
TerminalIO.PutF["*** You can't do that: same icon and sch name!\n"];
RETURN};
IF NOT Rope.Match["*.sch", rope] THEN TerminalIO.PutF["*** Convention for schematics is to suffix them with '.sch'.\n"];
key _ $IconFor;
TerminalIO.PutF["%g made wire icon of %g.\n", IO.rope[name], IO.rope[rope]]};
ENDCASE	=> {TerminalIO.PutF["*** Not done.\n"]; RETURN};
CleanUpIconProperties[selected.ob];
CDProperties.PutObjectProp[selected.ob, key, rope];
CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, SELECT choice FROM 1, 3 => $SisyphExtractNamedWireIcon, 2, 4 => $SisyphExtractUnNamedWireIcon, ENDCASE => ERROR]}; 

MakeSequenceIcon: PROC [comm: CDSequencer.Command] = {
selected: CD.Instance _ TheCellInstance[comm.design, "MakeSequenceIcon\n"];
IF selected=NIL THEN RETURN;
CleanUpIconProperties[selected.ob];
CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, $SisyphExtractSequence];
IF ParseSatellites[CDSatellites.GetSatelliteRopes[selected.ob]].keyword=NIL THEN TerminalIO.PutF["*** Warning: there is no satellite of the form 'Keyword: Expression'.\n"];
TerminalIO.PutF["Sequencing of %g done.\n", IO.rope[CDDirectory.Name[selected.ob, comm.design]]]}; 
MakeInvisibleToExtractor: PROC [comm: CDSequencer.Command] = {
nInstances: INT _ 0;
FOR w: LIST OF CD.Instance _ CDOps.InstList[comm.design], w.rest WHILE w#NIL DO
inst: CD.Instance _ w.first;
IF inst.selected THEN {
CDProperties.PutInstanceProp[inst, Sisyph.mode.extractProcProp, $ExtractNull];
nInstances _ nInstances+1;
FlushCache[comm.design, inst.ob] }
ENDLOOP;
TerminalIO.PutF["Made %g instances invisible to Sisyph\n", IO.int[nInstances]] }; 

MakeVisibleToExtractor: PROC [comm: CDSequencer.Command] = {
nInstances: INT _ 0;
FOR w: LIST OF CD.Instance _ CDOps.InstList[comm.design], w.rest WHILE w#NIL DO
inst: CD.Instance _ w.first;
IF inst.selected THEN {
CDProperties.PutInstanceProp[inst, Sisyph.mode.extractProcProp, NIL];
nInstances _ nInstances+1;
FlushCache[comm.design, inst.ob]}
ENDLOOP;
TerminalIO.PutF["Made %g instances visible to Sisyph\n", IO.int[nInstances]]}; 

FlushCache: PROC [design: CD.Design, obj: CD.Object] = {
name: ROPE _ CDDirectory.Name[obj, design];
iconFor: REF = CDProperties.GetObjectProp[obj, $IconFor];
schName: ROPE = IF ISTYPE [iconFor, ROPE] THEN NARROW [iconFor] ELSE NIL;
sch: CD.Object = IF schName#NIL THEN CDDirectory.Fetch[design, schName] ELSE NIL;
FlushEachInstance: CDCells.InstEnumerator = {FlushCache[design, inst.ob]};
IF name=NIL AND (CDCells.IsCell[obj] OR CDImports.IsImport[obj]) THEN name _ CD.Describe[ob: obj, design: design];
IF (CDProperties.GetObjectProp[obj, $SinixInstanceCache]#NIL OR CDProperties.GetObjectProp[obj, $SinixObjectCache]#NIL) AND name#NIL 
THEN TerminalIO.PutF["Flushing %g.\n", IO.rope[name]]; -- We use the property although it is PRIVATE because printing is just a hint
Sinix.FlushCache[obj];
IF CDCells.IsCell[obj] 
THEN [] _ CDCells.EnumerateInstances[obj, FlushEachInstance];
IF sch#NIL 
THEN FlushCache[design, sch]};

FlushSisyphCaches: PROC [comm: CDSequencer.Command] = {
FOR w: LIST OF CD.Instance _ CDOps.InstList[comm.design], w.rest WHILE w#NIL DO
IF w.first.selected THEN FlushCache[comm.design, w.first.ob];
ENDLOOP}; 

ShowInstExpressions: PROC [comm: CDSequencer.Command] = {
selected: CD.Instance _ CDOps.TheInstance[comm.design, "ShowInstExpressions\n"];
IF selected=NIL THEN RETURN;
PutRopes["Instance Expressions:\n", NARROW [CDProperties.GetInstanceProp[selected, Sisyph.expressionsProp]]]};

AddInstExpression: PROC [comm: CDSequencer.Command] = {
exprs: ROPES;
selected: CD.Instance _ CDOps.TheInstance[comm.design, "AddInstExpression\n"];
IF selected=NIL THEN RETURN;
exprs _ NARROW [CDProperties.GetInstanceProp[selected, Sisyph.expressionsProp]];
PutRopes["Add Instance Expression.  Previous Instance Expressions:\n", exprs];
exprs _ CONS [TerminalIO.RequestRope[Rope.Cat["  New Expression: "]], exprs];
CDProperties.PutInstanceProp[selected, Sisyph.expressionsProp, exprs]};

EditInstExpressions: PROC [comm: CDSequencer.Command] = {
exprs: ROPES;
selected: CD.Instance _ CDOps.TheInstance[comm.design, "EditInstExpressions\n"];
IF selected=NIL THEN RETURN;
TerminalIO.PutF["Edit Instance Expressions\n"];
exprs _ NARROW[CDProperties.GetInstanceProp[selected, Sisyph.expressionsProp]];
exprs _ EditExpressions[exprs, "Expression"];
CDProperties.PutInstanceProp[selected, Sisyph.expressionsProp, exprs]};

ShowObjExpressions: PROC [comm: CDSequencer.Command] = {
selected: CD.Instance _ CDOps.TheInstance[comm.design, "ShowObjExpressions\n"];
IF selected=NIL THEN RETURN;
PutRopes["Object Expressions:\n", NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]];
IF NOT CDImports.IsImport[selected.ob] THEN RETURN;
IF NARROW [selected.ob.specific, CDImports.ImportSpecific].boundOb=NIL 
THEN TerminalIO.PutF["Object is an unbound import.\n"]
ELSE PutRopes["Object Expressions of the bound import:\n", NARROW [CDProperties.GetObjectProp[NARROW [selected.ob.specific, CDImports.ImportSpecific].boundOb, Sisyph.expressionsProp]]]};

AddObjExpression: PROC [comm: CDSequencer.Command] = {
exprs: ROPES;
selected: CD.Instance _ TheCellInstance[comm.design, "AddObjExpression\n"];
IF selected=NIL THEN RETURN;
exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]];
PutRopes["Add Object Expression.  Previous Object Expressions:\n", exprs];
exprs _ CONS [TerminalIO.RequestRope[Rope.Cat["  New Expression: "]], exprs];
CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, exprs]};

EditObjExpressions: PROC [comm: CDSequencer.Command] = {
exprs: ROPES;
selected: CD.Instance _ TheCellInstance[comm.design, "EditObjExpressions\n"];
IF selected=NIL THEN RETURN;
TerminalIO.PutF["Edit Object Expressions\n"];
exprs _ NARROW[CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]];
exprs _ EditExpressions[exprs, "Expression"];
CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, exprs]};

ShowParmNames: PROC [comm: CDSequencer.Command] = {
selected: CD.Instance _ CDOps.TheInstance[comm.design, "ShowParmNames\n"]; -- not TheCellInstance for discovering old settings
IF selected=NIL THEN RETURN;
PutRopes["Parameter Names (0 for no parameter):\n", NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.parmNamesProp]]]};
SetParmName: PROC [comm: CDSequencer.Command] = {
insts: LIST OF CD.Instance _ AllCellInstances[comm.design, "SetParmName\n"];
IF insts=NIL THEN RETURN;
SELECT TerminalIO.RequestSelection["Setting Parameters", LIST ["Explicitly", "Implicitly"], "Better ABORT and click the doc if you do not know what you are doing ...", LIST ["All selected cells with get the specified parameters", "Automatic program setting parameters"]] FROM
1 => {
parms: ROPES _ NIL;
DO
input: ROPE _ TerminalIO.RequestRope["  Parameter: "];
IF Rope.IsEmpty[input] THEN EXIT;
parms _ CONS [input, parms];
ENDLOOP;
WHILE insts#NIL DO 
TerminalIO.PutF["Setting parameters on cell %g.\n", IO.rope[CD.Describe[ob: insts.first.ob, design: comm.design]]];
CDProperties.PutObjectProp[insts.first.ob, Sisyph.parmNamesProp, parms]; 
insts _ insts.rest;
ENDLOOP};
2 => {
IF TRUE THEN {TerminalIO.PutF["Not yet implemented.\n"]; RETURN};
WHILE insts#NIL DO 
name: ROPE = CDDirectory.Name[object: insts.first.ob, design: comm.design];
parms: ROPES; reasonForWorld: ROPE;
[parms, reasonForWorld] _ ComputeParameters[comm.design, insts.first.ob, insts.first.properties];
IF reasonForWorld=NIL
THEN {
TerminalIO.PutF["Setting parameters on cell %g.\n", IO.rope[name]];
CDProperties.PutObjectProp[insts.first.ob, Sisyph.parmNamesProp, parms]}
ELSE TerminalIO.PutF["*** Could not set parameters for cell %g because %g.\n", IO.rope[name], IO.rope[reasonForWorld]];
insts _ insts.rest;
ENDLOOP};
ENDCASE	=> RETURN};
EditParmNames: PROC [comm: CDSequencer.Command] = {
parms: ROPES;
selected: CD.Instance _ TheCellInstance[comm.design, "EditParmNames\n"];
IF selected=NIL THEN RETURN;
TerminalIO.PutF["Edit Object Expressions\n"];
parms _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.parmNamesProp]];
parms _ EditExpressions[parms, "Parameter"];
CDProperties.PutObjectProp[selected.ob, Sisyph.parmNamesProp, parms]};
sequenceKeyWords: SymTab.Ref _ SymTab.Create[5];

ParseSatellites: PROC [ropes: ROPES]
RETURNS [keyword, expr: ROPE _ NIL, others: ROPES _ NIL] = {
WHILE ropes#NIL DO
tokenKind1, tokenKind2: IO.TokenKind; token1, token2: ROPE; rest: ROPE;
[tokenKind1, token1, rest] _ Sisyph.ParseRope[ropes.first];
[tokenKind2, token2, rest] _ Sisyph.ParseRope[rest];
IF tokenKind1=tokenID AND SymTab.Fetch[sequenceKeyWords, token1].found AND Sisyph.IsParsedChar[tokenKind2, token2, ':] 
THEN IF keyword=NIL 
THEN {keyword _ token1; expr _ rest} 
ELSE {TerminalIO.PutF["*** SisyphExtractSequence: Conflicting sequencing satellites '%g:%g' and '%g'.\n", IO.rope[keyword], IO.rope[expr], IO.rope[ropes.first]]; ERROR}
ELSE others _ CONS [ropes.first, others];
ropes _ ropes.rest;
ENDLOOP};

FindPorts: PROC [baseCell: CellType, wires: Wires] RETURNS [set: CoreClasses.SequenceSet] = {
nats: LIST OF NAT _ NIL;
size: NAT _ 0;
WHILE wires#NIL DO
FOR w: NAT IN [0 .. baseCell.public.size) DO
sequenceName: ROPE _ CoreOps.GetShortWireName[wires.first]; 
IF wires.first=baseCell.public[w] OR (sequenceName#NIL AND Rope.Equal[sequenceName, CoreOps.GetShortWireName[baseCell.public[w]]]) THEN {
nats _ CONS [w, nats]; size _ size + 1;
EXIT};
REPEAT FINISHED => ERROR;
ENDLOOP; 
wires _ wires.rest;
ENDLOOP;
set _ NEW [CoreClasses.SequenceSetRec[size]];
FOR i: INT IN [0 .. size) DO set[i] _ nats.first; nats _ nats.rest ENDLOOP};

ExtractSequence: Sinix.ExtractProc = {
name: ROPE _ mode.nameProc[obj, userData];
cx: Sisyph.Context;
keyword, expr: ROPE;
others: ROPES;
cellType: CellType; 
count: NAT;
[keyword, expr, others] _ ParseSatellites[NARROW [CDProperties.GetObjectProp[obj, Sinix.satellitesProp]]];
IF keyword=NIL THEN {
TerminalIO.PutF["*** SisyphExtractSequence: Sequence does not contain any of sequencing information (e.g. an object satellite 'SeqX: 32').\n"];
ERROR};
CDProperties.PutObjectProp[obj, Sinix.satellitesProp, others];
cx _ Sisyph.EvaluateParameters[userData, obj, properties];
Sisyph.EvalExpr[cx, keyword, expr, FALSE];
count _ NAT [Sisyph.FetchInt[cx, keyword].value];
Sinix.PutF["Extracting [Sisyph] cell %g (%g: %g)\n", IO.rope[name], IO.rope[keyword], IO.int[count]];
name _ Rope.Substr[name, 0, Rope.Index[name, 0, ".sch"]]; -- hack
name _ Rope.Substr[name, 0, Rope.Index[name, 0, ".icon"]]; -- hack
cellType _ ExtractSequenceIcon[obj, cx, keyword, count, name, Sisyph.GetCoreProps[cx]]; 
props _ Sisyph.GetCoreInstProps[cx];
result _ cellType};

ExtractSequenceIcon: PROC
[obj: CD.Object, cx: Sisyph.Context, resultVar: ROPE, count: NAT, name: ROPE, props: Core.Properties] RETURNS [sequence: CellType] = {
iconCT: CellType = NARROW [Sinix.ExtractCell[obj, Sisyph.mode, NIL, cx].result];
iconRCT: CoreClasses.RecordCellType = NARROW [iconCT.data];
subCT: CellType;
layoutAtom: REF;
sequenceWires, flatSequenceWires: Wires _ NIL;
IF iconRCT.size#1 THEN {
TerminalIO.PutF["*** SisyphExtractSequence: Sequence should contain one and only one subcell.\n"];
ERROR};
subCT _ iconRCT[0].type;
Sisyph.ProcessGlobalNames[iconCT, cx];
FOR i: NAT IN [0 .. iconRCT.internal.size) DO
wire: Wire = iconRCT.internal[i];
name: ROPE _ CoreOps.GetShortWireName[wire];
IF name=NIL THEN name _ "some wire";
IF NOT CoreOps.RecursiveMember[iconRCT[0].actual, wire] THEN {
TerminalIO.PutF["*** SisyphExtractSequence: %g is not connected to subcell.\n", IO.rope[name]];
ERROR}; 
IF NOT CoreOps.RecursiveMember[iconCT.public, wire] THEN {
TerminalIO.PutF["*** SisyphExtractSequence: %g is not public.\n", IO.rope[name]];
ERROR}; 
ENDLOOP;
FOR i: NAT IN [0 .. subCT.public.size) DO
IF CoreProperties.GetWireProp[iconRCT[0].actual[i], $Sequence]#NIL 
THEN sequenceWires _ CONS [subCT.public[i], sequenceWires];
IF CoreProperties.GetWireProp[iconRCT[0].actual[i], $FlatSequence]#NIL 
THEN flatSequenceWires _ CONS [subCT.public[i], flatSequenceWires];
ENDLOOP;
sequence _ CoreClasses.CreateSequence[
args: NEW [CoreClasses.SequenceCellTypeRec _ [
base: subCT, count: count, 
sequence: FindPorts[subCT, sequenceWires], 
flatSequence: FindPorts[subCT, flatSequenceWires] ]],
name: name, props: props ];
FOR i: NAT IN [0..sequence.public.size) DO
iconWire: Wire = CoreClasses.CorrespondingActual[iconRCT[0], subCT.public[i]];
CopyWireProperties[from: iconWire, to: sequence.public[i]] ENDLOOP;
CoreGeometry.PutObject[Sisyph.mode.decoration, sequence, obj];
layoutAtom _ SymTab.Fetch[sequenceKeyWords, resultVar].val;
IF layoutAtom#NIL THEN CoreProperties.PutCellTypeProp[sequence, $Layout, layoutAtom];
};

CopyWireProperties: PROC[from, to: Wire] = {
eachProp: PROC[atom:ATOM, ref: REF] = {CoreProperties.PutWireProp[to, atom, ref]};
CoreProperties.Enumerate[from.properties, eachProp]};
ComputeParameters: PROC [design: CD.Design, obj: CD.Object, properties: CD.PropList] RETURNS [parms: ROPES, reasonForWorld: ROPE _ NIL] = {
cx: Sisyph.Context _ SymTab.Create[11];
parms _ NARROW [CDProperties.GetObjectProp[obj, Sisyph.parmNamesProp]];
IF parms#NIL THEN RETURN;
Sisyph.Store[cx, "design", NEW [CD.Design _ design]];
Sisyph.Insert[cx, "globalNames", NEW [ROPES _ Sisyph.defaultGlobalNames]];
[] _ Sinix.Extract[
obj: obj, mode: Sisyph.mode, properties: properties, userData: cx 
! ANY		=> {reasonForWorld _ "???"; GOTO Return} ];
parms _ LIST ["0"]; 
EXITS Return	=> RETURN};
PutRopes: PROC [rope: ROPE, ropes: ROPES] = {
TerminalIO.PutF[rope];
WHILE ropes#NIL DO
TerminalIO.PutF["\t%g\n", IO.rope[ropes.first]]; ropes _ ropes.rest;
ENDLOOP};

TheCellInstance: PROC [design: CD.Design, text: ROPE _ NIL]
RETURNS [inst: CD.Instance _ NIL] = {
inst _ CDOps.TheInstance[design, text];
IF inst=NIL OR CDCells.IsCell[inst.ob] THEN RETURN;
TerminalIO.PutF["*** Selected instance is not a cellcan't do it.\n"];
inst _ NIL};

AllCellInstances: PROC [design: CD.Design, text: ROPE _ NIL]
RETURNS [insts: LIST OF CD.Instance _ NIL] = {
IF text#NIL THEN TerminalIO.PutRope[text];
FOR w: CD.InstanceList _ CDOps.InstList[design], w.rest WHILE w#NIL DO
IF NOT w.first.selected THEN LOOP; 
IF NOT CDCells.IsCell[w.first.ob] 
THEN {TerminalIO.PutRope["   selection is not a cell; failed\n"]; RETURN [NIL]};
insts _ CONS [w.first, insts];
ENDLOOP;
IF insts=NIL THEN TerminalIO.PutRope["   no selection; failed\n"]};

CleanUpIconProperties: PROC [obj: CD.Object] = {
Sinix.FlushCache[obj];
CDProperties.PutObjectProp[obj, $IconFor, NIL];
CDProperties.PutObjectProp[obj, $CodeFor, NIL];
CDProperties.PutObjectProp[obj, Sisyph.mode.extractProcProp, NIL];
CDProperties.PutObjectProp[obj, Sisyph.expressionsProp, StripResultExprs
[NARROW [CDProperties.GetObjectProp[obj, Sisyph.expressionsProp]]]] };

StripResultExprs: PROC [in: ROPES] RETURNS [out: ROPES _ NIL] = {
FOR l: ROPES _ in, l.rest WHILE l#NIL DO
expr: ROPE _ l.first;
IF NOT Rope.Match[expr, "*cI*_*"] AND NOT Rope.Match[expr, "*wI*_*"] AND NOT Rope.Match[expr, "*wire*_*"] THEN out _ CONS [expr, out]
ENDLOOP};

EditExpressions: PROC [oldExprs: ROPES, prompt: ROPE] RETURNS [allExprs: ROPES _ NIL] = {
input: ROPE;
noOldExprs: BOOL _ oldExprs=NIL;
TerminalIO.PutF["\n"];
WHILE oldExprs#NIL DO
input _ TerminalIO.RequestRope[Rope.Cat["  ", prompt, ": ", oldExprs.first, "  Replacement: "]];
SELECT TRUE FROM
Rope.Equal[input, "-"] => TerminalIO.PutF["  ** Deleted\n"];
Rope.IsEmpty[input] => allExprs _ CONS [oldExprs.first, allExprs];
ENDCASE => allExprs _ CONS [input, allExprs];
oldExprs _ oldExprs.rest;
ENDLOOP;
IF noOldExprs THEN {
input _ TerminalIO.RequestRope[Rope.Cat["  New ", prompt, ": "]];
WHILE ~Rope.IsEmpty[input] AND ~Rope.Equal[input, "-"] DO
allExprs _ CONS [input, allExprs];
input _ TerminalIO.RequestRope[Rope.Cat["  New ", prompt, ": "]];
ENDLOOP};
allExprs _ RopeList.Reverse[allExprs]};
MatchProc: TYPE = PROC [old: ROPE] RETURNS [BOOL];
MatchTransistor:		MatchProc = {RETURN [Rope.Match["*CreateTransistor[[*", old]]};
MatchAmpersand:	MatchProc = {RETURN [Rope.Match["*&*_*", old]]};
MatchName:			MatchProc = {RETURN [Rope.Match["name _ \"*\"", old]]};
MatchSchCI:			MatchProc = {RETURN [Rope.Match["*cI*_*ES[\"*\",*cx]", old]]};
MatchCodeCI:			MatchProc = {RETURN [Rope.Match["*cI*_*", old]]};
MatchCodeWI:			MatchProc = {RETURN [Rope.Match["*wI*_*", old]]};
MatchWire:				MatchProc = {RETURN [Rope.Match["*wire*_*", old]]};
MatchDeclare:			MatchProc = {RETURN [Rope.Match[ "*Sisyph.Store[cx,*\"*\",*NEW[*_*]]", old]]};

Change: PROC [master: REF, location: ROPE] RETURNS [needInteraction: ROPE _ NIL] = {
news: ROPES;
CDProperties.PutProp[master, $CameFrom, NIL];
CDProperties.PutProp[master, $OriginalName, NIL];
CDProperties.PutProp[master, $CDBringoverLibraryName, NIL];
CDProperties.PutProp[master, $SisyphArguments, NIL];
FOR list: ROPES _ NARROW [CDProperties.GetProp[master, Sisyph.expressionsProp]], list.rest WHILE list#NIL DO
old: ROPE = list.first;
SELECT TRUE FROM
MatchName[old]	=> {
new: ROPE = Rope.Substr[old, 8, Rope.Length[old]-9];
TerminalIO.PutF["changed '%g' to '%g'.\n", IO.rope[old], IO.rope[new]];
news _ CONS [new, news];
};
MatchSchCI[old]	=> {
pos1: INT _ Rope.Find[old, "\""];
pos2: INT _ Rope.Find[old, "\"", pos1+1];
sch: ROPE = Rope.Substr[old, pos1+1, pos2-pos1-1];
TerminalIO.PutF["changed '%g' to an $IconFor property '%g'.\n", IO.rope[old], IO.rope[sch]];
CDProperties.PutProp[master, $IconFor, sch];
CDProperties.PutProp[master, Sisyph.mode.extractProcProp, $SisyphExtractCellIcon]};
MatchCodeCI[old]	=> {
code: ROPE = Rope.Substr[old, Rope.Find[old, "_"]+1];
TerminalIO.PutF["changed '%g' to an $CodeFor property '%g'.\n", IO.rope[old], IO.rope[code]];
CDProperties.PutProp[master, $IconFor, NIL]; -- because $IconFor was not the truth in CD24!
CDProperties.PutProp[master, $CodeFor, code];
CDProperties.PutProp[master, Sisyph.mode.extractProcProp, $SisyphExtractCellIcon]};
MatchCodeWI[old]	=> {
code: ROPE = Rope.Substr[old, Rope.Find[old, "_"]+1];
TerminalIO.PutF["changed '%g' to an $CodeFor property '%g'.\n", IO.rope[old], IO.rope[code]];
CDProperties.PutProp[master, $CodeFor, code];
CDProperties.PutProp[master, Sisyph.mode.extractProcProp, $SisyphExtractNamedWireIcon]};
MatchWire[old] OR MatchTransistor[old]	=> {
TerminalIO.PutF["*** Found expression %g '%g' that is not converted automatically.\n", IO.rope[location], IO.rope[old]];
news _ CONS [old, news]};
MatchAmpersand[old]			=> {
TerminalIO.PutF["*** Found expression %g '%g' that uses a variable starting with '&'.\n", IO.rope[location], IO.rope[old]];
news _ CONS [old, news]};
MatchDeclare[old]			=> {
pos1: INT _ Rope.Find[old, "\""];
pos2: INT _ Rope.Find[old, "\"", pos1+1];
pos3: INT _ Rope.Find[old, "_", pos2+1];
pos4: INT _ Rope.Find[old, "]", pos3+1];
new: ROPE _ Rope.Cat[Rope.Substr[old, pos1+1, pos2-pos1-1], " ~ ", Rope.Substr[old, pos3+1, pos4-pos3-1]];
TerminalIO.PutF["changed '%g' to '%g'.\n", IO.rope[old], IO.rope[new]];
news _ CONS [new, news]};
ENDCASE		=> news _ CONS [old, news];
ENDLOOP;
CDProperties.PutProp[master, Sisyph.expressionsProp, news];
IF MatchTransistor[NARROW [CDProperties.GetProp[master, $CodeFor]]] THEN TerminalIO.PutF["*** Found $CodeFor %g '%g' that cannot be converted automatically.\n", IO.rope[location], IO.rope[NARROW [CDProperties.GetProp[master, $CodeFor]]]];
IF CDProperties.GetProp[master, $CodeFor]#NIL AND CDProperties.GetProp[master, $IconFor]#NIL THEN TerminalIO.PutF["*** Found both $CodeFor and $IconFor %g.  $CodeFor is probably the truth, but check that carefully!\n", IO.rope[location]];
FOR list: ROPES _ CDSatellites.GetSatelliteRopes[master], list.rest WHILE list#NIL DO
old: ROPE = list.first;
SELECT TRUE FROM
MatchName[old] OR MatchSchCI[old] OR MatchCodeCI[old] OR MatchCodeWI[old] OR MatchWire[old] OR MatchDeclare[old] OR MatchTransistor[old] OR MatchAmpersand[old]	=> {
needInteraction _ Rope.Cat["'", old, "' ", needInteraction]};
ENDCASE				=> {};
ENDLOOP};

Convert: PROC [comm: CDSequencer.Command] = {
design: CD.Design = comm.design;
EachObj: CDDirectory.EachObjectProc = {
EachInst: CDCells.InstEnumerator = {
needInteraction _ Change[inst, Rope.Cat["in ", name]];
IF needInteraction#NIL THEN TerminalIO.PutF["*** Some instance satellite(s) in %g need to be changed: %g.\n", IO.rope[name], IO.rope[needInteraction]]};
name: ROPE _ CDDirectory.Name[me, design];
needInteraction: ROPE _ Change[me, Rope.Cat["of ", name]];
IF needInteraction#NIL THEN TerminalIO.PutF["*** Some object satellite(s) of %g need to be changed: %g.\n", IO.rope[name], IO.rope[needInteraction]];
IF NOT CDCells.IsCell[me] THEN RETURN;
[] _ CDCells.EnumerateInstances[me, EachInst]};
[] _ CDDirectory.EnumerateDesign[design, EachObj];
TerminalIO.PutF["\n*** Converted!  Save the design\n"]};

NoDummiesInDir: PROC [comm: CDSequencer.Command] ~ {
design: CD.Design = comm.design;
n: INT _ 0;
elem: TYPE ~ RECORD [ob: CD.Object, name: ROPE];
EachEntry: CDDirectory.EachEntryAction ~ {
IF Rope.Match[pattern: "-no name*", object: name] OR -- style 1 `unnamed' object
Rope.Match[pattern: "-noname-*", object: name] OR -- style 2 `unnamed' object
Rope.Match[pattern: "/@*", object: name] OR -- twiddled SequencingSlash
CDImports.IsImport[ob] -- Import
THEN remove _ CONS [[ob, name], remove]};
remove: LIST OF elem;
IF CDDirectory.Enumerate[design, EachEntry] THEN ERROR;
WHILE remove#NIL DO -- remove them all, check that the name/object relation is OK
n _ n+1;
IF CDDirectory.Remove[design, remove.first.name, remove.first.ob]=NIL THEN ERROR;
remove _ remove.rest;
ENDLOOP;
TerminalIO.PutF["\n%g objects made anonymous!  Save the design!\n", IO.int[n]]};
ICom: PROC[
key:		ATOM,
proc:		CDSequencer.CommandProc,
queue:	CDSequencer.QueueMethod _ doQueueAndMark ] =
{CDSequencer.ImplementCommand[key, proc, NIL, queue]};

CDCommandOps.RegisterWithMenu
[$Debug, "SisyphConvert", "Convert to new Sisyph syntax", $SisyphConvert, Convert, doQueueAndMark];
CDCommandOps.RegisterWithMenu
[$Debug, "Get rid of -no name-*", "Remove from directory all entries for unnamed objects and imports", $SisyphNoDummiesInDir, NoDummiesInDir, doQueueAndMark];
[] _ SymTab.Store[sequenceKeyWords, "Seq", NIL];
[] _ SymTab.Store[sequenceKeyWords, "SeqX", $ArrayX];
[] _ SymTab.Store[sequenceKeyWords, "SeqY", $ArrayY];
[] _ SymTab.Store[sequenceKeyWords, "RSeqX", $ReverseArrayX];
[] _ SymTab.Store[sequenceKeyWords, "RSeqY", $ReverseArrayY];
Sinix.RegisterExtractProc[$SisyphExtractSequence, ExtractSequence];
ICom[key: $FlushSisyphCaches, proc: FlushSisyphCaches, queue: doQueue];
SinixOps.RegisterModeCommands[mode: Sisyph.mode];
ICom[key: $MakeCellIcon,			proc: MakeCellIcon,			queue: doQueueAndMark];
ICom[key: $MakeWireIcon,			proc: MakeWireIcon,		queue: doQueueAndMark];
ICom[key: $MakeSequenceIcon,	proc: MakeSequenceIcon,	queue: doQueueAndMark];
ICom[key: $UnMakeIcon,			proc: UnMakeIcon,			queue: doQueueAndMark];
ICom[key: $MakeInvisibleToExtractor, proc: MakeInvisibleToExtractor,queue: doQueueAndMark];
ICom[key: $MakeVisibleToExtractor,	proc: MakeVisibleToExtractor, queue: doQueueAndMark];
ICom[key: $SisyphShowParmNames,	proc: ShowParmNames, queue: doQueue];
ICom[key: $SisyphSetParmName,		proc: SetParmName];
ICom[key: $SisyphEditParmNames,	proc: EditParmNames];
ICom[key: $SisyphShowInstExpressions,	proc: ShowInstExpressions,	queue: doQueue];
ICom[key: $SisyphAddInstExpression,	proc: AddInstExpression,	queue: doQueueAndMark];
ICom[key: $SisyphEditInstExpressions,	proc: EditInstExpressions,	queue: doQueueAndMark];
ICom[key: $SisyphShowObjExpressions,	proc: ShowObjExpressions,	queue: doQueue];
ICom[key: $SisyphAddObjExpression,		proc: AddObjExpression,	queue: doQueueAndMark];
ICom[key: $SisyphEditObjExpressions,	proc: EditObjExpressions,	queue: doQueueAndMark];

END. 
��t��SisyphCmdsImpl.mesa
Copyright Ó 1985, 1986, 1987 by Xerox Corporation.  All rights reserved.
Created by Pradeep Sindhu, December 9, 1985 10:01:52 pm PST
Pradeep Sindhu, September 26, 1986 2:06:15 pm PDT
Barth, January 13, 1986 3:30:05 pm PST
Bertrand Serlet April 28, 1988 12:23:59 pm PDT
Jean-Marc Frailong December 9, 1987 6:50:30 pm PST
Last Edited by: Jacobi July 15, 1986 2:40:48 pm PDT
Don Curry January 20, 1988 3:43:54 pm PST


Icon Commands
Other Commands


Sequence Icons
There should be only one subcell
We deal with Global Variables
we check that there is no internal only
We compute which wires are going to be sequenced
We create the sequence
New code to copy properties from the extracted public to the new sequence public.
The object decoration!
We decorate with the appriopriate layout atom
Computing Parameters
This function is, of course, slightly fancy ...
Not really working, either!
Internal Utilities
Soon obsolete?
Convertion code
Remove from directory all entries for unnamed objects and imports. Returns number of removed objects.
Initialization
FilterSch: SinixOps.FilterProc =
{RETURN [Rope.Match["*.sch", name] OR Rope.Match["*.icon", name]]};
Convertion
Filling the Layout atoms for sequences
At this point, there is a strange dependency between Sisyph and PWCore, but it is not worth the effort making a separate module
Main Menu
SinixOps.RegisterBackgroundExtractionCommand[CD.FetchTechnology[$cmosB], Sisyph.mode, "Sch background extraction", $SchBackgroundExtract, FilterSch]; -- only works for CMosB.  Not very clean
Make Icon Menu
Change Visibility Menu
Make Parameter Menu (normally hidden)
Expressions Menu
�Ê¬��˜�™JšœH™HJšœ8Ïk™;Jšœ.™1Jšœ#™&Jšœ.™.Jšœ/™2Jšœ0™3Jšœ&™)—J™�š	˜	Jšœ`˜bJšœ9˜9Jšœ˜Jšœ!˜!Jšœ˜J˜�—šÏnœœ˜Jšœœ•œ=˜ÞJšœ˜J™�Jšœœœ˜Jš
œœœœœ˜Jšœœ
˜Jšœœ˜Jšœ
œ˜—head™
šž
œœ ˜0Jšœ
œ9˜EJšœ
œœœ˜Jšœ#˜#šœ˜Jšœœ5˜T—J˜�—šžœœ ˜2Jšœœ˜
Jšœœ˜Jšœ
œ;˜GJšœ
œœœ˜Jšœ2˜2šœœ˜"JšœO˜S—šœAœKœH˜æšœ˜Jšœ=˜=Jšœ˜—šœ˜Jšœ7˜7šœœ˜5JšœE˜I—šœ&œœ˜2Jšœ3œ
˜BJšœ˜—šœœ˜ JšœD˜DJšœ˜—JšœœœS˜xJšœ˜Jšœ.œ
œ˜M—Jšœ)œ˜8—Jšœ#˜#Jšœ3˜3Jšœ_˜_J˜�—šžœœ ˜2Jšœœ˜
Jšœœ˜Jšœœ˜Jšœ
œ;˜GJšœ
œœœ˜Jšœ2˜2šœœ˜"JšœO˜S—šœ%˜%Jšœ$˜$Jšœa˜eJšœ)˜)Jšœ†˜Š—šœ˜šœ	˜	Jšœ=˜=Jšœ˜—šœ	˜	Jšœ7˜7šœœ˜5JšœE˜I—šœ&œœ˜2Jšœ3œ
˜BJšœ˜—šœœ˜ JšœD˜DJšœ˜—JšœœœS˜xJšœ˜Jšœ.œ
œ˜M—Jšœ)œ˜8—Jšœ#˜#Jšœ3˜3Jš	œEœœMœœ˜¸J˜�—šžœœ ˜6Jšœ
œ?˜KJšœ
œœœ˜Jšœ#˜#Jšœ]˜]JšœFœœ\˜¬Jšœ,œ5˜c——™šžœœ ˜>Jšœœ˜š
œœœœ0œœ˜OJšœœ˜šœœ˜JšœN˜NJšœ˜Jšœ"˜"—Jšœ˜—Jšœ;œ˜RJ˜�—šžœœ ˜<Jšœœ˜š
œœœœ0œœ˜OJšœœ˜šœœ˜Jšœ@œ˜EJšœ˜Jšœ!˜!—Jšœ˜—Jšœ9œ˜OJ˜�—šž
œœ
œœ˜8Jšœœ!˜+Jšœ	œ-˜9Jšœ	œœœœœœœœ˜IJš
œœ
œ	œœ$œœ˜QJšžœ9˜JJšœœœœœœ#˜ršœ7œœ4œœœ˜…Jšœ#œÏcM˜„—Jšœ˜šœ˜Jšœ9˜=—šœœ˜Jšœ˜—J˜�—šžœœ ˜7š
œœœœ0œœ˜OJšœœ%˜=Jšœ˜
—J˜�—šžœœ ˜9Jšœ
œD˜PJšœ
œœœ˜Jšœ$œD˜nJ˜�—šžœœ ˜7Jšœœ˜
Jšœ
œB˜NJšœ
œœœ˜JšœœB˜PJšœN˜NJšœœA˜MJšœG˜GJ˜�—šžœœ ˜9Jšœœ˜
Jšœ
œD˜PJšœ
œœœ˜Jšœ/˜/JšœœA˜OJ˜-JšœG˜GJ˜�—šžœœ ˜8Jšœ
œC˜OJšœ
œœœ˜Jšœ"œD˜lJšœœ!œœ˜3šœœ:œ˜GJšœ2˜6Jšœ7œœV˜º—J˜�—šžœœ ˜6Jšœœ˜
Jšœ
œ?˜KJšœ
œœœ˜JšœœC˜QJšœJ˜JJšœœA˜MJšœH˜HJ˜�—šžœœ ˜8Jšœœ˜
Jšœ
œA˜MJšœ
œœœ˜Jšœ-˜-JšœœB˜PJ˜-JšœH˜HJ˜�—šž
œœ ˜3Jšœ
œ?Ÿ3˜~Jšœ
œœœ˜Jšœ4œC˜}J™�—šžœœ ˜1Jšœœœœ;˜LJšœœœœ˜šœ3œkœc˜“˜Jšœœœ˜š˜Jšœœ+˜6Jšœœœ˜!Jšœœ˜Jšœ˜—šœœœ˜Jšœ4œœ5˜sJšœI˜IJšœ˜Jšœ˜	——˜Jšœœœ-œ˜Ašœœœ˜J•StartOfExpansion*[object: CD.Object, design: CD.Design]šœœA˜KJšœœœ˜#Jšœa˜ašœ˜šœ˜Jšœ4œ
˜CJšœH˜H—JšœKœ
œ˜w—Jšœ˜Jšœ˜	——Jšœœ˜—J™�—šž
œœ ˜3Jšœœ˜
Jšœ
œ<˜HJšœ
œœœ˜Jšœ-˜-JšœœA˜OJ˜,JšœF˜F——™šœ0˜0J˜�—šžœœ	œ˜$Jš
œœœ
œœ˜<šœœ˜Jšœœœœ˜GJšœ;˜;Jšœ4˜4šœœ.œ-˜wšœœ	œ˜Jšœ!˜%Jš
œfœœ
œœ˜¨—Jšœ
œ˜)—Jšœ˜Jšœ˜	—J˜�—šž	œœ$œ#˜]Jš	œœœœœ˜Jšœœ˜šœœ˜šœœœ˜,Jšœœ*˜<š
œ œœœIœ˜‰Jšœœ˜'Jšœ˜—Jšœœœ˜Jšœ˜	—Jšœ˜Jšœ˜—Jšœœ$˜-Jš
œœœ
œ'œ˜LJ˜�—šžœ˜&Jšœœ ˜*Jšœ˜Jšœœ˜Jšœœ˜Jšœ˜Jšœœ˜Jšœ*œ:˜jšœ	œœ˜Jšœ˜Jšœ˜—Jšœ>˜>Jšœ:˜:Jšœ#œ˜*Jšœœ&˜1Jšœ5œ
œœ
˜eJšœ:Ÿ˜AJšœ;Ÿ˜BJšœX˜XJ˜$Jšœ˜J˜�—–¡ -- [obj: CD.Object, mode: Sinix.Mode, properties: PropertyLists.PropList _ NIL, userData: REF ANY _ NIL] RETURNS [result: REF ANY, props: Core.Properties _ NIL]šžœ˜Jšœœ(œ	œœœ˜†Jšœœ&œ˜PJšœ&œ˜;Jšœ˜Jšœœ˜Jšœ*œ˜.Jšœ ™ šœœ˜Jšœb˜bJšœ˜—Jšœ˜J™Jšœ&˜&Jšœ'™'šœœœ˜-Jšœ!˜!Jšœœ"˜,Jšœœœ˜$šœœ2œ˜>JšœPœ
˜_Jšœ˜—šœœ.œ˜:JšœBœ
˜QJšœ˜—Jšœ˜—Jšœ0™0šœœœ˜)šœ=œ˜CJšœœ"˜;—šœAœ˜GJšœœ&˜C—Jšœ˜—Jšœ™šœ&˜&šœœ%˜.Jšœ˜Jšœ+˜+Jšœ5˜5—Jšœ˜—J™Qšœœœ˜*JšœN˜NJšœ;œ˜C—J™Jšœ>˜>J™-Jšœ;˜;Jšœœœ?˜UJšœ˜J˜�—šžœœ˜,Jšœ
œœœ0˜RJšœ5˜5——™Jšœ/™/J™šžœœ
œœœœ	œœœ˜‹Jšœ'˜'Jšœœ9˜GJšœœœœ˜Jšœœœ˜5Jšœ!œœ˜Jšœ˜JšœB˜BJšœœœ˜2—Jšœœ˜Jšœœ˜——™šžœœœ	œ˜-Jšœ˜šœœ˜Jšœœ(˜DJšœ˜	—J˜�—š
žœœ
œœœ˜;Jšœœœ˜%Jšœ'˜'Jš
œœœœœ˜3JšœF˜FJšœœ˜J˜�—š
žœœ
œœœ˜<Jš
œ	œœœœ˜.Jšœœœ˜*š	œœ/œœ˜FJšœœœœ˜#šœœ˜"Jšœ>œœ˜P—Jšœœ˜Jšœ˜—Jšœœœ2˜CJ˜�—šžœœœ˜0Jšœ˜Jšœ*œ˜/Jšœ*œ˜/Jšœ=œ˜BšœH˜HJšœœ?˜F—J˜�—JšÏb™šžœœœœœœ˜Aš	œœœœ˜(Jšœœ˜Jšœœœœœœœœ˜…Jšœ˜	—J˜�—šžœœœ
œœœœ˜YJšœœ˜Jšœœœ˜ Jšœ˜šœ
œ˜Jšœ`˜`šœœ˜Jšœ<˜<Jšœ"œ˜BJšœœ˜-—J˜Jšœ˜—šœœ˜JšœA˜Ašœœ˜9Jšœœ˜"JšœA˜AJšœ˜	——Jšœ'˜'——™Jšœœœœœœ˜2Jšžœœ,˜QJšžœœ˜@Jšž	œœ$˜DJšž
œœ+˜LJšžœœ˜@Jšžœœ˜@Jšž	œœ ˜Ašžœœ;˜^J˜�—šžœœ
œœœœœ˜TJšœœ˜Jšœ(œ˜-Jšœ,œ˜1Jšœ6œ˜;Jšœ/œ˜4šœœœCœœ˜lJšœœ˜šœœ˜šœ˜Jšœœ+˜4Jšœ+œœ˜GJšœœ
˜J˜—šœ˜Jšœœ˜!Jšœœ ˜)Jšœœ)˜2Jšœ@œœ˜\Jšœ,˜,JšœS˜S—šœ˜Jšœœ+˜5Jšœ@œœ
˜]Jšœ'œŸ.˜[Jšœ-˜-JšœS˜S—šœ˜Jšœœ+˜5Jšœ@œœ
˜]Jšœ-˜-JšœX˜X—šœœ˜+JšœWœœ˜xJšœœ˜—šœ˜JšœZœœ˜{Jšœœ˜—šœ˜Jšœœ˜!Jšœœ ˜)Jšœœ˜(Jšœœ˜(Jšœœa˜jJšœ+œœ˜GJšœœ˜—Jšœœ
˜$—Jšœ˜—Jšœ;˜;Jšœœ+œYœœœ,˜îJšœ(œœ(œœzœ˜îš	œœ5œœ˜UJšœœ˜šœœ˜šœœœœœœœœ˜¤Jšœ=˜=—Jšœ
˜—Jšœ˜	—J˜�—šžœœ ˜-Jšœœ˜ šžœ ˜'šžœ˜$Jšœ6˜6Jš
œœœSœ
œ˜˜—Jšœœ ˜*Jšœœ%˜:Jš
œœœQœ
œ˜•Jšœœœœ˜&Jšœ/˜/—Jšœ2˜2Jšœ8˜8J˜�—šžœœ ˜4J™eJšœœ˜ Jšœœ˜Jš	œœœœœ˜0šž	œ!˜*šœ0œŸ˜PJšœ/œŸ˜MJšœ)œŸ˜GJšœŸ	˜ Jšœ
œ˜)——Jšœœœ˜Jšœ*œœ˜7šœœœŸ=˜QJ˜Jšœ@œœœ˜QJšœ˜Jšœ˜—JšœDœ
˜P——™šžœœ˜Jšœœ˜Jšœ˜šœ3˜3Jšœ)œ
˜6——J˜�šž	œ™ Jšœœœ™C—K™
šœ˜Jšœc˜c—šœ˜Jšœž˜ž—K™&Jšœ™Jšœ+œ˜0Jšœ5˜5Jšœ5˜5Jšœ=˜=Jšœ=˜=K™	JšœC˜CJšœG˜GJšœ1˜1Jšœ-œgŸ(™¾K™JšœH˜HJšœG˜GJšœL˜LJšœD˜DK™Jšœ[˜[JšœX˜XK™%JšœE˜EJšœ2˜2Jšœ5˜5K™JšœQ˜QJšœT˜TJšœX˜XJšœO˜OJšœS˜SJšœV˜VJ˜�—Jšœ ˜—�…—����jè��Œ��