DIRECTORY Basics, BitOps, Convert, CoreClasses, CoreFlat, CoreOps, CoreProperties, HashTable, IO, Rope; CoreFlatImpl: CEDAR PROGRAM IMPORTS Basics, BitOps, Convert, CoreClasses, CoreOps, CoreProperties, HashTable, IO, Rope EXPORTS CoreFlat = BEGIN OPEN CoreFlat; PathError: PUBLIC ERROR [msg: ROPE _ NIL] = CODE; MakeError: PROC [m: ROPE _ NIL] = { IF m=NIL THEN m _ "parse failed"; ERROR PathError[m]; }; cutLabelProp: ATOM _ CoreProperties.RegisterProperty[$CoreCutLabel]; CellInstanceCutLabels: PUBLIC PROC [on: CellInstance, l1, l2, l3, l4, l5, l6: ROPE _ NIL] RETURNS [same: CellInstance] = { same _ CellInstanceCutLabelList[on, LabelList[l1, l2, l3, l4, l5, l6]] }; CellInstanceCutLabelList: PUBLIC PROC [on: CellInstance, labels: LIST OF ROPE] RETURNS [same: CellInstance] = { lbls: LIST OF ROPE _ NARROW[CoreProperties.GetCellInstanceProp[on, cutLabelProp]]; lbls _ CombineLabelLists[lbls, labels]; CoreProperties.PutCellInstanceProp[on, cutLabelProp, lbls]; same _ on; }; CellTypeCutLabels: PUBLIC PROC [on: CellType, l1, l2, l3, l4, l5, l6: ROPE _ NIL] RETURNS [same: CellType] = { same _ CellTypeCutLabelList[on, LabelList[l1, l2, l3, l4, l5, l6]] }; CellTypeCutLabelList: PUBLIC PROC [on: CellType, labels: LIST OF ROPE] RETURNS [same: CellType] = { lbls: LIST OF ROPE _ NARROW[CoreProperties.GetCellTypeProp[on, cutLabelProp]]; lbls _ CombineLabelLists[lbls, labels]; CoreProperties.PutCellTypeProp[on, cutLabelProp, lbls]; same _ on; }; CellClassCutLabels: PUBLIC PROC [on: CellClass, l1, l2, l3, l4, l5, l6: ROPE _ NIL] RETURNS [same: CellClass] = { same _ CellClassCutLabelList[on, LabelList[l1, l2, l3, l4, l5, l6]] }; CellClassCutLabelList: PUBLIC PROC [on: CellClass, labels: LIST OF ROPE] RETURNS [same: CellClass] = { lbls: LIST OF ROPE _ NARROW[CoreProperties.GetCellClassProp[on, cutLabelProp]]; lbls _ CombineLabelLists[lbls, labels]; CoreProperties.PutCellClassProp[on, cutLabelProp, lbls]; same _ on; }; CreateCutSet: PUBLIC PROC [instances, cellTypes, cellClasses, labels: LIST OF ROPE _ NIL, flatCells: FlatCellTypes _ NIL] RETURNS [cutSet: CutSet] = { cutSet _ NEW[CutSetRec _ [ instances: instances, cellTypes: cellTypes, cellClasses: cellClasses, labels: labels, flatCells: flatCells]]; }; CutSetMember: PUBLIC PROC [root: CellType, flatCell: FlatCellTypeRec, cutSet: CutSet] RETURNS [member: BOOL _ FALSE] = { parent: CellType; instance: CellInstance; cellType: CellType; [parent, instance, cellType] _ ResolveFlatCellType[root, flatCell]; member _ CutSetMemberResolved[flatCell, instance, cellType, cutSet] }; CutSetMemberResolved: PUBLIC PROC [flatCell: FlatCellTypeRec, instance: CellInstance, cellType: CellType, cutSet: CutSet] RETURNS [member: BOOL _ FALSE] = { name: ROPE _ NIL; IF cutSet=NIL THEN RETURN[FALSE]; FOR flats: FlatCellTypes _ cutSet.flatCells, flats.rest UNTIL flats=NIL DO IF FlatCellTypeEqualRec[flats.first^, flatCell] THEN RETURN[TRUE]; ENDLOOP; IF instance#NIL THEN { name _ CoreClasses.GetCellInstanceName[instance]; IF name#NIL THEN IF OneInOther[LIST[name], cutSet.instances] THEN RETURN [TRUE]; }; name _ CoreOps.GetCellTypeName[cellType]; IF name#NIL THEN IF OneInOther[LIST[name], cutSet.cellTypes] THEN RETURN [TRUE]; IF OneInOther[LIST[cellType.class.name], cutSet.cellClasses] THEN RETURN [TRUE]; IF instance#NIL THEN IF OneInOther[NARROW[CoreProperties.GetCellInstanceProp[instance, cutLabelProp]], cutSet.labels] THEN RETURN [TRUE]; IF OneInOther[NARROW[CoreProperties.GetCellTypeProp[cellType, cutLabelProp]], cutSet.labels] THEN RETURN [TRUE]; IF OneInOther[NARROW[CoreProperties.GetCellClassProp[cellType.class, cutLabelProp]], cutSet.labels] THEN RETURN [TRUE]; }; OneInOther: PROC [one, other: LIST OF ROPE] RETURNS [yes: BOOL _ FALSE] = { FOR this: LIST OF ROPE _ one, this.rest UNTIL this=NIL DO FOR that: LIST OF ROPE _ other, that.rest UNTIL that=NIL DO IF Rope.Equal[CoreOps.FixStupidRef[this.first], CoreOps.FixStupidRef[that.first]] THEN RETURN[TRUE]; ENDLOOP; ENDLOOP; }; LabelList: PROC [l1, l2, l3, l4, l5, l6: ROPE _ NIL] RETURNS [labels: LIST OF ROPE _ NIL] = { IF l1#NIL THEN labels _ CONS[l1, labels]; IF l2#NIL THEN labels _ CONS[l2, labels]; IF l3#NIL THEN labels _ CONS[l3, labels]; IF l4#NIL THEN labels _ CONS[l4, labels]; IF l5#NIL THEN labels _ CONS[l5, labels]; IF l6#NIL THEN labels _ CONS[l6, labels]; }; CombineLabelLists: PROC [l1, l2: LIST OF ROPE _ NIL] RETURNS [combined: LIST OF ROPE] = { combined _ l1; FOR lbls: LIST OF ROPE _ l2, lbls.rest UNTIL lbls=NIL DO combined _ CONS[lbls.first, combined]; ENDLOOP; }; ParseInstancePath: PUBLIC PROC [root: CellType, pathRope: ROPE, cutSet: CutSet] RETURNS [path: InstancePath] = { instance: CellInstance; within: CellType; token: ROPE; ts: IO.STREAM; firstChar: CHAR; tokenKind: IO.TokenKind; [path, instance, within, token, ts, firstChar, tokenKind] _ ParsePartialInstancePath[root, pathRope, cutSet]; path _ AddInstance[path, instance, within]; CheckNoMore[ts, firstChar, tokenKind]; }; InstancePathRope: PUBLIC PROC [root: CellType, path: InstancePath] RETURNS [pathRope: ROPE _ NIL] = { AppendName: UnboundFlatCellProc = { IF instance#NIL AND cell=instance.type THEN { name: ROPE _ CoreClasses.GetCellInstanceName[instance]; IF name=NIL THEN { cellTypeName: ROPE _ CoreOps.InheritCellTypeName[instance.type]; name _ Convert.RopeFromInt[CoreClasses.InstanceIndex[parent, instance]]; IF cellTypeName#NIL THEN name _ Rope.Cat[name, "(", cellTypeName, ")"]; }; pathRope _ Rope.Cat[pathRope, "/", name]; }; NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, AppendName]; }; AppendName[root, [path, 0]]; }; InstancePathEqual: PUBLIC PROC [one, other: InstancePath] RETURNS [equal: BOOL] = { oneBits: ARRAY [0..2) OF INT _ LOOPHOLE[one.bits]; otherBits: ARRAY [0..2) OF INT _ LOOPHOLE[other.bits]; equal _ one.length=other.length AND oneBits=otherBits; }; InstancePathHash: PUBLIC PROC [path: InstancePath] RETURNS [hash: CARDINAL _ 0] = { bits: BitOps.BitQWord _ BitOps.QuadShift[LOOPHOLE[path.bits], path.length-64]; FOR i: NAT IN [0..4) DO hash _ Basics.BITXOR[hash, bits[i]]; ENDLOOP; }; AddInstance: PUBLIC PROC [currentPath: InstancePath, instance: CoreClasses.CellInstance, parent: CellType] RETURNS [newPath: InstancePath] = { newPath _ currentPath; IF instance#NIL THEN { withinCT: CellType _ CoreOps.ToBasic[parent]; withinRCT: CoreClasses.RecordCellType _ NARROW[withinCT.data]; index: NAT _ CoreClasses.InstanceIndex[withinCT, instance]; IF index=-1 THEN ERROR; -- instance not found in parent CellType newPath _ ExtendPath[currentPath, index, withinRCT]; }; }; ExtendPath: PUBLIC PROC [currentPath: InstancePath, index: NAT, rct: CoreClasses.RecordCellType] RETURNS [newPath: InstancePath] = { pathBits: NAT _ BitOps.NBits[rct.size]; newPath _ currentPath; FOR bit: NAT IN [0..pathBits) DO newPath.bits[newPath.length+bit] _ BitOps.EBFW[index, bit, pathBits]; ENDLOOP; newPath.length _ newPath.length + pathBits; }; BindInstance: PUBLIC PROC [parent: FlatCellTypeRec, actual, public: WireSeq, bindings: Bindings] RETURNS [newBindings: Bindings] = { BindPublicToActual: CoreOps.EachWirePairProc = { bind: FlatWire _ NIL; IF bindings#NIL THEN bind _ NARROW [HashTable.Fetch[table: bindings, key: actualWire].value]; [] _ HashTable.Store[table: newBindings, key: publicWire, value: IF bind=NIL THEN NEW[FlatWireRec _ [flatCell: parent, wire: actualWire]] ELSE bind]; }; newBindings _ HashTable.Create[public.size+1]; IF CoreOps.VisitBindingSeq[actual: actual, public: public, eachWirePair: BindPublicToActual] THEN ERROR; }; ParseCellTypePath: PUBLIC PROC [root: CellType, pathRope: ROPE, cutSet: CutSet] RETURNS [flatCell: FlatCellTypeRec] = { instance: CellInstance; within: CellType; token: ROPE; ts: IO.STREAM; firstChar: CHAR; tokenKind: IO.TokenKind; thisCell: CellType; [flatCell, instance, within, token, ts, firstChar, tokenKind, thisCell] _ ParsePartialCellTypePath[root, pathRope, cutSet]; flatCell.path _ AddInstance[flatCell.path, instance, within]; CheckNoMore[ts, firstChar, tokenKind]; }; CellTypePathRope: PUBLIC PROC [root: CellType, flatCell: FlatCellTypeRec] RETURNS [pathRope: ROPE] = { pathRope _ InstancePathRope[root, flatCell.path]; IF flatCell.recastCount>0 THEN pathRope _ Rope.Cat[pathRope, "*", Convert.RopeFromInt[flatCell.recastCount]]; }; FlatCellTypeEqual: PUBLIC PROC [one, other: REF ANY] RETURNS [equal: BOOL] = { equal _ FlatCellTypeEqualRec[NARROW [one, FlatCellType]^, NARROW [other, FlatCellType]^]; }; FlatCellTypeEqualRec: PUBLIC PROC [one, other: FlatCellTypeRec] RETURNS [equal: BOOL] = { equal _ InstancePathEqual[one.path, other.path] AND one.recastCount=other.recastCount; }; FlatCellTypeHash: PUBLIC PROC [flatCell: REF ANY] RETURNS [hash: CARDINAL] = { hash _ FlatCellTypeHashRec[NARROW[flatCell, FlatCellType]^]; }; FlatCellTypeHashRec: PUBLIC PROC [flatCell: FlatCellTypeRec] RETURNS [hash: CARDINAL] = { hash _ InstancePathHash[flatCell.path]; hash _ Basics.BITXOR[hash, flatCell.recastCount]; }; ResolveFlatCellType: PUBLIC PROC [root: CellType, flatCell: FlatCellTypeRec] RETURNS [parent: CellType, instance: CellInstance, cellType: CellType] = { Search: UnboundFlatCellProc = { upParent _ parent; upInstance _ instance; upCellType _ cell; NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, Search] }; upParent: CellType _ NIL; upInstance: CellInstance _ NIL; upCellType: CellType _ NIL; Search[cell: root, target: flatCell]; parent _ upParent; instance _ upInstance; cellType _ upCellType; }; BoundFlatCellType: PUBLIC PROC [root: CellType, flatCell: FlatCellTypeRec] RETURNS [bindings: Bindings, instance: CellInstance, cellType: CellType] = { Search: BoundFlatCellProc = { upBindings _ bindings; upInstance _ instance; upCellType _ cell; NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, Search] }; upBindings: Bindings _ NIL; upInstance: CellInstance _ NIL; upCellType: CellType _ NIL; Search[cell: root, target: flatCell]; bindings _ upBindings; instance _ upInstance; cellType _ upCellType; }; ParseWirePath: PUBLIC PROC [root: CellType, pathRope: ROPE, cutSet: CutSet] RETURNS [flatWire: FlatWireRec] = { AddWire: PROC [subWire: NAT] = { pathBits: NAT _ BitOps.NBits[flatWire.wire.size]; instanceBits: PACKED ARRAY [0..16) OF BOOL _ LOOPHOLE[subWire]; FOR bit: NAT IN [0..pathBits) DO flatWire.path.bits[flatWire.path.length+bit] _ instanceBits[16-pathBits+bit]; ENDLOOP; flatWire.path.length _ flatWire.path.length + pathBits; flatWire.wire _ flatWire.wire[subWire]; IF flatWire.wireRoot=actual THEN publicWire _ publicWire[subWire]; }; InternalRoot: PROC = { rct: CoreClasses.RecordCellType _ NIL; flatWire.flatCell.path _ AddInstance[flatWire.flatCell.path, instance, within]; flatWire.flatCell.recastCount _ 0; [rct, flatWire.flatCell] _ MakeRecord[IF instance=NIL THEN root ELSE instance.type, instance, flatWire.flatCell, cutSet]; flatWire.wire _ rct.internal; flatWire.wireRoot _ internal; }; AppendNameWire: PROC = { state _ sawWireNameOrNumber; IF RootWire[]#none THEN MakeError["Cannot name a wire actual, internal, or public"]; FOR subWire: CARDINAL IN [0..flatWire.wire.size) DO IF Rope.Equal[token, CoreOps.GetShortWireName[IF flatWire.wireRoot=actual THEN publicWire[subWire] ELSE flatWire.wire[subWire]]] THEN { AddWire[subWire]; EXIT; }; REPEAT FINISHED => { -- This hack is for Don Curry's benefit hackName: ROPE _ token; DO [token, firstChar, tokenKind] _ ParseToken[ts ! IO.EndOfStream => EXIT]; hackName _ Rope.Cat[hackName, token]; ENDLOOP; FOR subWire: CARDINAL IN [0..flatWire.wire.size) DO IF Rope.Equal[hackName, CoreOps.GetShortWireName[IF flatWire.wireRoot=actual THEN publicWire[subWire] ELSE flatWire.wire[subWire]]] THEN { AddWire[subWire]; EXIT; }; REPEAT FINISHED => MakeError["Can't find wire"]; ENDLOOP; }; ENDLOOP; }; AppendNumberWire: PROC = { subWire: CARDINAL _ Convert.CardFromRope[token]; IF flatWire.wire=NIL THEN InternalRoot[]; IF subWire>=flatWire.wire.size THEN MakeError["No such wire"]; AddWire[subWire]; }; PossibleRootWire: PROC = { wireType: RootWireType _ RootWire[]; SELECT wireType FROM public => { state _ sawWireRoot; flatWire.flatCell.path _ AddInstance[flatWire.flatCell.path, instance, within]; flatWire.wire _ thisCell.public; flatWire.wireRoot _ public; }; internal => { state _ sawWireRoot; InternalRoot[]; }; actual => { parentCT: CellType _ within; IF instance=NIL THEN MakeError["Can't access actual of root"]; state _ sawWireRoot; flatWire.wire _ instance.actual; publicWire _ instance.type.public; flatWire.wireRoot _ actual; flatWire.flatCell.recastCount _ 0; UNTIL parentCT.class=CoreClasses.recordCellClass DO new: CellType _ CoreOps.Recast[parentCT]; IF new#parentCT THEN flatWire.flatCell.recastCount _ flatWire.flatCell.recastCount + 1; parentCT _ new; ENDLOOP; flatWire.instanceIndex _ CoreClasses.InstanceIndex[parentCT, instance]; }; none => { InternalRoot[]; AppendNameWire[]; }; ENDCASE => ERROR; }; RootWireType: TYPE = {public, internal, actual, none}; RootWire: PROC RETURNS [RootWireType] = { RETURN [SELECT TRUE FROM Rope.Equal[token, "PUBLIC", FALSE] => public, Rope.Equal[token, "INTERNAL", FALSE] => internal, Rope.Equal[token, "ACTUAL", FALSE] => actual, ENDCASE => none]; }; WirePathParseStates: TYPE = {start, expectMaybeRoot, sawWireRoot, expectWireNameOrNumber, sawWireNameOrNumber, sawLeft, sawNumber, sawRight}; instance: CoreClasses.CellInstance; within: CellType; token: ROPE; ts: IO.STREAM; firstChar: CHAR; tokenKind: IO.TokenKind; thisCell: CellType; publicWire: Wire _ NIL; state: WirePathParseStates _ start; [flatWire.flatCell, instance, within, token, ts, firstChar, tokenKind, thisCell] _ ParsePartialCellTypePath[root, pathRope, cutSet]; flatWire.validPath _ TRUE; DO SELECT state FROM start => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM '[ => state _ sawLeft; '. => state _ expectMaybeRoot; ENDCASE => MakeError[]; tokenID => PossibleRootWire[]; tokenDECIMAL => {AppendNumberWire[]; state _ sawWireNameOrNumber}; ENDCASE => MakeError[]; expectMaybeRoot => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM '[ => state _ sawLeft; ENDCASE => MakeError[]; tokenID => PossibleRootWire[]; tokenDECIMAL => {AppendNumberWire[]; state _ sawWireNameOrNumber}; ENDCASE => MakeError[]; sawWireRoot => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM '. => state _ expectWireNameOrNumber; ENDCASE => MakeError[]; ENDCASE => MakeError[]; expectWireNameOrNumber => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM '[ => state _ sawLeft; ENDCASE => MakeError[]; tokenID => AppendNameWire[]; tokenDECIMAL => {AppendNumberWire[]; state _ sawWireNameOrNumber}; ENDCASE => MakeError[]; sawWireNameOrNumber => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM '. => state _ expectWireNameOrNumber; '[ => state _ sawLeft; ENDCASE => MakeError[]; ENDCASE => MakeError[]; sawLeft => SELECT tokenKind FROM tokenDECIMAL => {AppendNumberWire[]; state _ sawNumber}; ENDCASE => MakeError[]; sawNumber => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM '] => state _ sawRight; ENDCASE => MakeError[]; ENDCASE => MakeError[]; sawRight => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM '. => state _ expectWireNameOrNumber; '[ => state _ sawLeft; ENDCASE => MakeError[]; tokenID => AppendNameWire[]; tokenDECIMAL => {AppendNumberWire[]; state _ sawWireNameOrNumber}; ENDCASE => MakeError[]; ENDCASE => MakeError[]; [token, firstChar, tokenKind] _ ParseToken[ts ! IO.EndOfStream => {tokenKind _ tokenEOF; EXIT}]; ENDLOOP; IF state=sawWireRoot OR state=expectWireNameOrNumber OR state=sawLeft OR state=sawNumber THEN MakeError[]; }; WirePathRope: PUBLIC PROC [root: CellType, wire: FlatWireRec] RETURNS [pathRope: ROPE] = { cellType: CellType _ ResolveFlatCellType[root, wire.flatCell].cellType; rootWire: Wire; IF wire.wireRoot=actual THEN { wire.flatCell.path _ ExtendPath[wire.flatCell.path, wire.instanceIndex, NARROW[cellType.data, CoreClasses.RecordCellType]]; wire.flatCell.recastCount _ 0; }; pathRope _ CellTypePathRope[root, wire.flatCell]; IF (NOT Rope.IsEmpty[pathRope]) AND wire.wireRoot#internal THEN pathRope _ Rope.Cat[pathRope, "."]; pathRope _ Rope.Cat[pathRope, SELECT wire.wireRoot FROM internal => NIL, public => "public", actual => "actual", ENDCASE => ERROR]; rootWire _ SELECT wire.wireRoot FROM public => cellType.public, internal => NARROW [cellType.data, CoreClasses.RecordCellType].internal, actual => NARROW [cellType.data, CoreClasses.RecordCellType][wire.instanceIndex].type.public, ENDCASE => ERROR; IF wire.validPath THEN { visitWire: Wire _ rootWire; begin: NAT _ 0; index: NAT; name: ROPE; UNTIL begin=wire.path.length DO pathBits: NAT _ BitOps.NBits[visitWire.size]; instanceBits: PACKED ARRAY [0..16) OF BOOL _ ALL [FALSE]; FOR bit: NAT IN [0..pathBits) DO instanceBits[16-pathBits+bit] _ wire.path.bits[begin+bit]; ENDLOOP; begin _ begin + pathBits; index _ LOOPHOLE[instanceBits]; visitWire _ visitWire[index]; name _ CoreOps.GetShortWireName[visitWire]; IF name=NIL THEN name _ Convert.RopeFromInt[index]; IF NOT Rope.IsEmpty[pathRope] THEN pathRope _ Rope.Cat[pathRope, "."]; pathRope _ Rope.Cat[pathRope, name]; ENDLOOP; } ELSE { IF NOT Rope.IsEmpty[pathRope] THEN pathRope _ Rope.Cat[pathRope, "."]; pathRope _ Rope.Cat[pathRope, CoreOps.GetFullWireName[rootWire, wire.wire]]; }; }; FlatWireEqual: PUBLIC PROC [one, other: REF ANY] RETURNS [equal: BOOL] = { equal _ FlatWireEqualRec[NARROW [one, FlatWire]^, NARROW [other, FlatWire]^]; }; FlatWireEqualRec: PUBLIC PROC [one, other: FlatWireRec] RETURNS [equal: BOOL] = { equal _ one.wire=other.wire AND FlatCellTypeEqualRec[one.flatCell, other.flatCell]; }; FlatWireHash: PUBLIC PROC [wire: REF ANY] RETURNS [hash: CARDINAL] = { hash _ FlatWireHashRec[NARROW [wire, FlatWire]^]; }; FlatWireHashRec: PUBLIC PROC [wire: FlatWireRec] RETURNS [hash: CARDINAL] = { hash _ FlatCellTypeHashRec[wire.flatCell]; hash _ Basics.BITXOR[hash, Basics.LowHalf[LOOPHOLE[wire.wire]]]; hash _ Basics.BITXOR[hash, Basics.HighHalf[LOOPHOLE[wire.wire]]]; }; CanonizeWire: PUBLIC PROC [root: CellType, child: FlatWireRec] RETURNS [parent: FlatWireRec] = { Search: BoundFlatCellProc = { upBindings _ bindings; NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, Search] }; upBindings: Bindings _ NIL; Search[cell: root, target: child.flatCell]; IF upBindings=NIL THEN parent _ child ELSE { parentRef: FlatWire _ NARROW[HashTable.Fetch[upBindings, child.wire].value]; parent _ IF parentRef=NIL THEN child ELSE parentRef^; }; }; NextUnboundCellType: PUBLIC PROC [cell: CellType, target: FlatCellTypeRec, flatCell: FlatCellTypeRec, instance: CellInstance, index: NAT, parent: CellType, flatParent: FlatCellTypeRec, data: REF ANY, proc: UnboundFlatCellProc] = { IF FlatCellTypeEqualRec[target, flatCell] THEN RETURN; IF cell.class=CoreClasses.recordCellClass THEN { rct: CoreClasses.RecordCellType _ NARROW[cell.data]; pathBits: NAT _ BitOps.NBits[rct.size]; childFlatCell: FlatCellTypeRec _ [flatCell.path, 0]; instance: CellInstance; IF FlatCellTypeEqualRec[target, allFlatCells] THEN { FOR inst: NAT IN [0..rct.size) DO instance _ rct[inst]; childFlatCell.path _ ExtendPath[flatCell.path, inst, rct]; proc[cell: instance.type, target: target, flatCell: childFlatCell, instance: instance, index: inst, parent: cell, flatParent: flatCell, data: data]; ENDLOOP; } ELSE { instanceBits: PACKED ARRAY [0..16) OF BOOL _ ALL [FALSE]; IF target.path.length<=flatCell.path.length THEN ERROR; -- illegal move FOR bit: NAT IN [0..pathBits) DO instanceBits[16-pathBits+bit] _ target.path.bits[flatCell.path.length+bit]; childFlatCell.path.bits[flatCell.path.length+bit] _ target.path.bits[flatCell.path.length+bit]; ENDLOOP; index _ LOOPHOLE[instanceBits]; instance _ rct[index]; childFlatCell.path.length _ childFlatCell.path.length + pathBits; proc[cell: instance.type, target: target, flatCell: childFlatCell, instance: instance, index: index, parent: cell, flatParent: flatCell, data: data]; } } ELSE { new: CellType _ NIL; IF cell.class.recast=NIL THEN ERROR; -- illegal move new _ CoreOps.Recast[cell]; IF new#cell THEN flatCell.recastCount _ flatCell.recastCount + 1; proc[cell: new, target: target, flatCell: flatCell, instance: instance, index: index, parent: parent, flatParent: flatParent, data: data]; }; }; NextBoundCellType: PUBLIC PROC [cell: CellType, target: FlatCellTypeRec, flatCell: FlatCellTypeRec, instance: CellInstance, index: NAT, parent: CellType, flatParent: FlatCellTypeRec, data: REF ANY, bindings: Bindings, proc: BoundFlatCellProc] = { BindCellType: UnboundFlatCellProc = { newBindings: Bindings _ IF instance=previousInstance AND cell=previousCell THEN bindings ELSE BindInstance[parent: flatParent, actual: IF instance=NIL OR instance.type#cell THEN previousCell.public ELSE instance.actual, public: cell.public, bindings: bindings]; proc[cell, target, flatCell, instance, index, parent, flatParent, data, newBindings]; }; previousCell: CellType _ cell; previousInstance: CellInstance _ instance; NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, BindCellType]; }; InitialBindingTable: PUBLIC PROC [root: CellType] RETURNS [bindings: Bindings] = { Bind: PROC [wire: Wire] RETURNS [subWires: BOOL _ TRUE, quit: BOOL _ FALSE] --CoreOps.EachWireProc-- = { IF subWires _ (NOT HashTable.Fetch[bindings, wire].found) THEN { fw: FlatWire = NEW [FlatWireRec _ [wireRoot: public, wire: wire]]; IF NOT HashTable.Insert[bindings, wire, fw] THEN ERROR; }; }; bindings _ HashTable.Create[]; IF CoreOps.VisitWireSeq[root.public, Bind] THEN ERROR; bindings _ bindings; }; ParsePartialCellTypePath: PROC [root: CellType, pathRope: ROPE, cutSet: CutSet] RETURNS [flatCell: FlatCellTypeRec, instance: CellInstance _ NIL, within: CellType, token: ROPE, ts: IO.STREAM, firstChar: CHAR, tokenKind: IO.TokenKind, thisCell: CellType _ NIL] = { RecastToClass: PROC = { DO IF NOT first THEN { new: CellType _ NIL; CheckRecast[flatCell, instance, thisCell, cutSet]; new _ CoreOps.Recast[thisCell]; IF new#thisCell THEN flatCell.recastCount _ flatCell.recastCount + 1; thisCell _ new; }; first _ FALSE; IF Rope.Equal[token, thisCell.class.name] THEN EXIT; ENDLOOP; state _ sawCellClassNameOrRecastNumber; }; RecastByNumber: PROC = { recastNumber: CARDINAL _ Convert.CardFromRope[token]; FOR rn: CARDINAL IN [0..recastNumber) DO new: CellType _ NIL; CheckRecast[flatCell, instance, thisCell, cutSet]; new _ CoreOps.Recast[thisCell]; IF new#thisCell THEN flatCell.recastCount _ flatCell.recastCount + 1; thisCell _ new; ENDLOOP; state _ sawRecastNumber; }; CheckCellClassName: PROC = { IF NOT Rope.Equal[token, thisCell.class.name] THEN MakeError[Rope.Cat["Incorrect cell class name ", token]]; state _ sawCellClassName; }; CellTypePathParseStates: TYPE = {start, sawAsterisk, sawRecastNumber, sawLeftParan, sawCellClassName, sawCellClassNameOrRecastNumber}; state: CellTypePathParseStates _ start; first: BOOL _ TRUE; [flatCell.path, instance, within, token, ts, firstChar, tokenKind] _ ParsePartialInstancePath[root, pathRope, cutSet]; thisCell _ IF instance=NIL THEN root ELSE instance.type; flatCell.recastCount _ 0; IF tokenKind#tokenEOF THEN DO SELECT state FROM start => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM '* => state _ sawAsterisk; '., '[ => EXIT; ENDCASE => MakeError[]; tokenID => EXIT; tokenDECIMAL => EXIT; ENDCASE => MakeError[]; sawAsterisk => SELECT tokenKind FROM tokenID => RecastToClass[]; tokenDECIMAL => RecastByNumber[]; ENDCASE => MakeError[]; sawRecastNumber => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM '( => state _ sawLeftParan; '* => state _ sawAsterisk; '., '[ => EXIT; ENDCASE => MakeError[]; ENDCASE => MakeError[]; sawLeftParan => SELECT tokenKind FROM tokenID => CheckCellClassName[]; ENDCASE => MakeError[]; sawCellClassName => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM ') => state _ sawCellClassNameOrRecastNumber; ENDCASE => MakeError[]; ENDCASE => MakeError[]; sawCellClassNameOrRecastNumber => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM '* => state _ sawAsterisk; '., '[ => EXIT; ENDCASE => MakeError[]; ENDCASE => MakeError[]; ENDCASE => MakeError[]; [token, firstChar, tokenKind] _ ParseToken[ts ! IO.EndOfStream => {tokenKind _ tokenEOF; EXIT}]; ENDLOOP; IF state=sawAsterisk OR state=sawLeftParan OR state=sawCellClassName THEN MakeError[]; }; ParsePartialInstancePath: PROC [root: CellType, pathRope: ROPE, cutSet: CutSet] RETURNS [path: InstancePath _ nullInstancePath, instance: CellInstance _ NIL, within: CellType, token: ROPE, ts: IO.STREAM, firstChar: CHAR, tokenKind: IO.TokenKind] = { AppendNameInstance: PROC = { found: BOOL _ FALSE; rct: CoreClasses.RecordCellType; path _ AddInstance[path, instance, within]; within _ IF instance=NIL THEN root ELSE instance.type; rct _ MakeRecord[within, instance, [path, 0], cutSet].rct; FOR inst: CARDINAL IN [0..rct.size) DO IF Rope.Equal[token, CoreClasses.GetCellInstanceName[rct[inst]]] THEN { instance _ rct[inst]; found _ TRUE; EXIT; }; REPEAT FINISHED => FOR inst: CARDINAL IN [0..rct.size) DO IF Rope.Equal[token, CoreOps.GetCellTypeName[rct[inst].type]] THEN { IF found THEN MakeError["Append by cell type name is ambiguous"]; instance _ rct[inst]; found _ TRUE; }; ENDLOOP; ENDLOOP; IF NOT found THEN MakeError[Rope.Cat["Can't find instance or cell type of name ", token]]; state _ sawInstanceNameOrNumber; }; AppendNumberInstance: PROC = { rct: CoreClasses.RecordCellType; inst: CARDINAL _ Convert.CardFromRope[token]; path _ AddInstance[path, instance, within]; within _ IF instance=NIL THEN root ELSE instance.type; rct _ MakeRecord[within, instance, [path, 0], cutSet].rct; IF inst>=rct.size THEN MakeError[Rope.Cat["No such instance ", token]]; instance _ rct[inst]; state _ sawInstanceNumber; }; CheckCellTypeName: PROC = { IF NOT Rope.Equal[token, CoreOps.InheritCellTypeName[instance.type]] THEN MakeError[Rope.Cat["Incorrect cell type name ", token]]; state _ sawCellTypeName; }; InstancePathParseStates: TYPE = {start, expectInstanceNameOrNumber, sawInstanceNumber, sawLeftParan, sawCellTypeName, sawInstanceNameOrNumber}; state: InstancePathParseStates _ start; within _ root; ts _ IO.RIS[pathRope]; DO [token, firstChar, tokenKind] _ ParseToken[ts ! IO.EndOfStream => {tokenKind _ tokenEOF; EXIT}]; SELECT state FROM start => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM '/ => state _ expectInstanceNameOrNumber; '*, '[ => EXIT; ENDCASE => MakeError[]; tokenID => EXIT; tokenDECIMAL => EXIT; ENDCASE => MakeError[]; expectInstanceNameOrNumber => SELECT tokenKind FROM tokenID => AppendNameInstance[]; tokenDECIMAL => AppendNumberInstance[]; ENDCASE => MakeError[]; sawInstanceNumber => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM '( => state _ sawLeftParan; '/ => state _ expectInstanceNameOrNumber; '*, '., '[ => EXIT; ENDCASE => MakeError[]; ENDCASE => MakeError[]; sawLeftParan => SELECT tokenKind FROM tokenID => CheckCellTypeName[]; ENDCASE => MakeError[]; sawCellTypeName => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM ') => state _ sawInstanceNameOrNumber; ENDCASE => MakeError[]; ENDCASE => MakeError[]; sawInstanceNameOrNumber => SELECT tokenKind FROM tokenSINGLE => SELECT firstChar FROM '/ => state _ expectInstanceNameOrNumber; '*, '., '[ => EXIT; ENDCASE => MakeError[]; ENDCASE => MakeError[]; ENDCASE => MakeError[]; ENDLOOP; IF state=expectInstanceNameOrNumber OR state=sawLeftParan OR state=sawCellTypeName THEN MakeError[]; }; MakeRecord: PROC [cellType: CellType, instance: CellInstance, flatCell: FlatCellTypeRec, cutSet: CutSet] RETURNS [rct: CoreClasses.RecordCellType, newFlatCell: FlatCellTypeRec] = { UNTIL cellType.class=CoreClasses.recordCellClass DO new: CellType _ NIL; CheckRecast[flatCell, instance, cellType, cutSet]; new _ CoreOps.Recast[cellType]; IF new#cellType THEN flatCell.recastCount _ flatCell.recastCount + 1; cellType _ new; ENDLOOP; rct _ NARROW [cellType.data]; newFlatCell _ flatCell }; CheckRecast: PROC [flatCell: FlatCellTypeRec, instance: CellInstance, cellType: CellType, cutSet: CutSet] = { IF cellType.class.recast=NIL THEN MakeError["Attempting to name something inside of a primitive element"]; IF CutSetMemberResolved[flatCell, instance, cellType, cutSet] THEN MakeError["Attempting to name something below the current cutSet"]; }; CheckNoMore: PROC [ts: IO.STREAM, firstChar: CHAR, tokenKind: IO.TokenKind] = { IF tokenKind#tokenEOF THEN MakeError[]; }; ParseToken: PROC [ts: IO.STREAM] RETURNS [token: ROPE, firstChar: CHAR, tokenKind: IO.TokenKind] = { token _ IO.GetTokenRope[ts, Breaks].token; firstChar _ Rope.Fetch[token]; tokenKind _ SELECT TRUE FROM Rope.Length[token]=1 AND Breaks[firstChar]=break => tokenSINGLE, firstChar IN ['0..'9] => tokenDECIMAL, ENDCASE => tokenID; }; Breaks: IO.BreakProc = { RETURN[SELECT char FROM IN [IO.NUL .. IO.SP] => sepr, '/, '., '(, '), '[, '], '* => break, ENDCASE => other] }; END. ®CoreFlatImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Barth, February 18, 1987 6:27:13 pm PST Last Edited by: Gasbarro October 24, 1986 2:28:18 pm PDT Last Edited by: Louis Monier January 20, 1987 10:42:41 am PST Mike Spreitzer November 18, 1986 2:41:15 pm PST Error Cut Sets Instances IF equal THEN FOR bit: NAT IN [0..one.length) DO IF one.bits[bit]#other.bits[bit] THEN { equal _ FALSE; EXIT; }; ENDLOOP; CellTypes Wires WirePath ::= {start} ?((PUBLIC | INTERNAL | ACTUAL ) {sawWireRoot} . {expectWireNameOrNumber} ) (( Name | Number ) {sawWireNameOrNumber} ?( . {expectWireNameOrNumber})) | ( [ {sawLeft} Number {sawNumber} ] {sawRight} ) Enumeration Utilities CellTypePath ::= {start} * {sawAsterisk} ( Name | (Number {sawRecastNumber} ?( ( {sawLeftParan} Name {sawCellClassName} ) ) ) {sawCellClassNameOrRecastNumber} ) InstancePath ::= {start} / {expectInstanceNameOrNumber} ( Name | (Number {sawInstanceNumber} ?( ( {sawLeftParan} Name {sawCellTypeName} ) ) ) {sawInstanceNameOrNumber} ) token: ROPE; IF tokenKind=tokenSINGLE AND firstChar='. THEN [token, firstChar, tokenKind] _ ParseToken[ts ! IO.EndOfStream => {tokenKind _ tokenEOF; CONTINUE}]; Ê"<– "cedar" style˜codešœ™Kšœ Ïmœ7™BK™'K™8K™=K™/K™—KšÏk œUžœ˜gK˜•StartOfExpansion[]šÐbn œžœž˜KšžœKžœ˜ZKšžœ ˜Kšœžœžœ ˜—K˜head™š Ïn œžœžœžœžœžœ˜1K˜—š  œžœžœžœ˜#Kšžœžœžœ˜!Kšžœ˜K˜K˜——™šœžœ2˜DK˜—š  œžœžœ,žœžœžœ˜zJšœF˜FKšœ˜J˜—š œžœžœžœžœžœžœ˜oJš œžœžœžœžœ7˜RJšœ'˜'Jšœ;˜;J˜ Kšœ˜J˜—š  œžœžœ(žœžœžœ˜nJšœB˜BKšœ˜J˜—š œžœžœžœžœžœžœ˜cJš œžœžœžœžœ3˜NJšœ'˜'Jšœ7˜7J˜ Kšœ˜J˜—š  œžœžœ)žœžœžœ˜qJšœC˜CKšœ˜J˜—š œžœžœžœžœžœžœ˜fJš œžœžœžœžœ4˜OJšœ'˜'Jšœ8˜8J˜ Kšœ˜J˜—š  œžœžœ-žœžœžœžœžœžœ˜–šœ žœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ˜K˜—š   œžœžœ=žœ žœžœ˜xK˜K˜K˜KšœC˜CKšœC˜CKšœ˜K˜—š  œžœžœYžœ žœžœ˜œKšœžœžœ˜Kš žœžœžœžœžœ˜!šžœ5žœžœž˜JKšžœ.žœžœžœ˜BKšžœ˜—šžœ žœžœ˜Kšœ1˜1Kšžœžœžœžœ žœžœžœžœ˜PK˜—Kšœ)˜)Kšžœžœžœžœ žœžœžœžœ˜PKš žœ žœ+žœžœžœ˜PKšžœ žœžœžœ žœMžœžœžœ˜‰Kš žœ žœIžœžœžœ˜pKš žœ žœPžœžœžœ˜wKšœ˜K˜—š  œžœžœžœžœžœžœžœ˜Kš žœžœžœžœžœžœž˜9š žœžœžœžœžœžœž˜;KšžœPžœžœžœ˜dKšžœ˜—Kšžœ˜—Kšœ˜K˜—š  œžœžœžœžœ žœžœžœžœ˜]Jšžœžœžœ žœ ˜)Jšžœžœžœ žœ ˜)Jšžœžœžœ žœ ˜)Jšžœžœžœ žœ ˜)Jšžœžœžœ žœ ˜)Jšžœžœžœ žœ ˜)Kšœ˜K˜—š œžœ žœžœžœžœžœ žœžœžœ˜YKšœ˜š žœžœžœžœžœžœž˜8Jšœ žœ˜&Jšžœ˜—Kšœ˜K˜——™ š  œžœžœžœžœ˜pKšœ˜Kšœ˜Kšœžœ˜ Kšœžœžœ˜Kšœ žœ˜Kšœ žœ ˜Kšœm˜mKšœ+˜+Kšœ&˜&Kšœ˜K˜—š  œžœžœ&žœ žœžœ˜eK˜šŸ œ˜#šžœ žœžœ˜-Kšœžœ-˜7šžœžœžœ˜Kšœžœ.˜@KšœH˜HKšžœžœžœ/˜GK˜—Kšœ)˜)K˜—Kšœc˜cKšœ˜K˜—Kšœ˜Kšœ˜K˜—š  œžœžœžœ žœ˜SKš œ žœžœžœžœ ˜2Kš œ žœžœžœžœ ˜6Kšœ žœ˜6š žœžœžœžœžœž™0šžœžœ™'Kšœžœ™Kšžœ™K™—Kšžœ™—Kšœ˜K˜—š  œžœžœžœžœ ˜SKšœ)žœ˜Nšžœžœžœž˜Jšœžœ˜$Jšžœ˜—Kšœ˜K˜—š  œžœžœSžœ˜ŽKšœ˜šžœ žœžœ˜Kšœ-˜-Kšœ(žœ˜>Kšœžœ1˜;Kšžœ žœžœÏc(˜@Kšœ4˜4Kšœ˜—Kšœ˜K˜—š   œžœžœ$žœ#žœ˜„Kšœ žœ˜'Kšœ˜šžœžœžœž˜ Kšœ*žœ˜EKšžœ˜—Kšœ+˜+K˜K˜—š  œžœžœHžœ˜„K˜š œ˜0Kšœžœ˜Kšžœ žœžœžœ;˜]Kš œAžœžœžœžœ5žœ˜•Kšœ˜K˜—Kšœ.˜.Kšžœ[žœžœ˜hKšœ˜K˜——™ š  œžœžœžœžœ ˜wKšœ˜Kšœ˜Kšœžœ˜ Kšœžœžœ˜Kšœ žœ˜Kšœ žœ ˜Kšœ˜Kšœ{˜{Kšœ=˜=Kšœ&˜&Kšœ˜K˜—š  œžœžœ-žœ žœ˜fKšœ1˜1KšžœžœO˜mKšœ˜K˜—š œžœžœžœžœžœ žœ˜NKšœžœžœ˜YKšœ˜K˜—š  œžœžœžœ žœ˜YKšœ0žœ#˜VKšœ˜K˜—š œžœžœ žœžœžœžœ˜NKšœžœ˜Kšœ˜Kšœ˜K˜—š œžœ˜Kšœ$˜$šžœ ž˜šœ ˜ Kšœ˜KšœO˜OKšœ ˜ Kšœ˜K˜—šœ ˜ Kšœ˜Kšœ˜K˜—šœ ˜ K˜Kšžœ žœžœ*˜>Kšœ˜Kšœ ˜ Kšœ"˜"Kšœ˜Kšœ"˜"šžœ,ž˜3Kšœ)˜)KšžœžœC˜WKšœ˜Kšžœ˜—KšœG˜GK˜—šœ ˜ Kšœ˜Kšœ˜K˜—Kšžœžœ˜—K˜K˜—šœžœ$˜6K˜—š œžœžœ˜)šžœžœžœž˜Kšœžœ ˜-Kšœžœ˜1Kšœžœ ˜-Kšžœ ˜—K˜K˜—Kš Ïb œ¢žœ¢œžœ¢œžœ¢œ*¢œ¢œ¢œ¢œ¢œ¢œ¢œ¢œ-¢™ÛKšœžœt˜Kšœ#˜#Kšœ˜Kšœžœ˜ Kšœžœžœ˜Kšœ žœ˜Kšœ žœ ˜Kšœ˜Kšœžœ˜Kšœ#˜#Kšœ„˜„Kšœžœ˜šž˜šžœž˜šœ žœ ž˜šœžœ ž˜$Kšœ˜Kšœ˜Kšžœ˜—Kšœ˜KšœB˜BKšžœ˜—šœžœ ž˜(šœžœ ž˜$Kšœ˜Kšžœ˜—Kšœ˜KšœB˜BKšžœ˜—šœžœ ž˜$šœžœ ž˜$Kšœ%˜%Kšžœ˜—Kšžœ˜—šœžœ ž˜/šœžœ ž˜$Kšœ˜Kšžœ˜—Kšœ˜KšœB˜BKšžœ˜—šœžœ ž˜,šœžœ ž˜$Kšœ%˜%Kšœ˜Kšžœ˜—Kšžœ˜—šœ žœ ž˜ Kšœ8˜8Kšžœ˜—šœ žœ ž˜"šœžœ ž˜$Kšœ˜Kšžœ˜—Kšžœ˜—šœ žœ ž˜!šœžœ ž˜$Kšœ%˜%Kšœ˜Kšžœ˜—Kšœ˜KšœB˜BKšžœ˜—Kšžœ˜—Kšœ0žœ'žœ˜`Kšžœ˜—Kš žœžœžœžœžœ ˜jK˜K˜—š   œžœžœ%žœ žœ˜ZKšœG˜GKšœ˜šžœžœ˜KšœHžœ-˜{Kšœ˜K˜—Kšœ1˜1Kšžœžœžœžœ%˜dKš œžœžœ žœ*žœžœ˜ƒšœ žœž˜$Kšœ˜Kšœ žœ6˜HKšœ žœM˜]Kšžœžœ˜—šžœžœ˜K˜Kšœžœ˜Kšœžœ˜ Kšœžœ˜ šžœž˜Kšœ žœ ˜-Kš œžœžœ žœžœžœžœ˜9šžœžœžœž˜ Kšœ:˜:Kšžœ˜—Kšœ˜Kšœžœ˜Kšœ˜K˜+Kšžœžœžœ#˜3Kšžœžœžœ%˜GKšœ$˜$Kšžœ˜—Kšœ˜—šžœ˜Kšžœžœžœ%˜GKšœL˜LK˜—Kšœ˜K˜—š  œžœžœžœžœžœ žœ˜JKšœžœžœ˜MKšœ˜K˜—š  œžœžœžœ žœ˜QJšœžœ4˜SKšœ˜K˜—š  œžœžœžœžœžœžœ˜FKšœžœ˜1Kšœ˜K˜—š  œžœžœžœžœ˜MJšœ*˜*Jšœžœžœ˜@Jšœžœžœ˜AKšœ˜K˜—š  œžœžœ&žœ˜`K˜š œ˜Kšœ˜Kšœf˜fK˜K˜—Kšœžœ˜Kšœ+˜+Kšžœ žœžœ˜%šžœ˜Kšœžœ0˜LKš œ žœ žœžœžœ ˜5Kšœ˜—Kšœ˜K˜——™ š  œžœžœežœ7žœžœ ˜æKšžœ(žœžœ˜6šžœ(žœ˜0Kšœ"žœ ˜4Kšœ žœ˜'Kšœ4˜4K˜šžœ,žœ˜4šžœžœžœž˜!K˜Kšœ:˜:Kšœ”˜”Kšžœ˜—K˜—šžœ˜Kš œžœžœ žœžœžœžœ˜9Kšžœ*žœžœ¡˜Hšžœžœžœž˜ KšœK˜KKšœ_˜_Kšžœ˜—Kšœžœ˜Kšœ˜KšœA˜AKšœ•˜•K˜—K˜—šžœ˜Kšœžœ˜Kš žœžœžœžœ¡˜5Kšœ˜Kšžœ žœ1˜AKšœŠ˜ŠK˜—Kšœ˜K˜—š  œžœžœežœ7žœžœ2˜öK˜š  œ˜%Kšœžœžœžœ žœ*žœ žœžœžœžœ;˜…KšœU˜UK˜K˜—K˜Kšœ*˜*Kšœe˜eKšœ˜K˜—š œžœžœžœ˜Rš œžœžœ žœžœžœžœ¡œ˜hšžœ žœ(žœ˜@Kšœžœ0˜BKšžœžœ&žœžœ˜7K˜—K˜—K˜Kšžœ)žœžœ˜6K˜K˜K˜——™ š œžœžœžœ6žœžœžœžœ žœ žœ!žœ˜‡K˜š  œžœ˜šž˜šžœžœžœ˜Kšœžœ˜Kšœ2˜2Kšœ˜Kšžœžœ1˜EKšœ˜K˜—Kšœžœ˜Kšžœ(žœžœ˜4Kšžœ˜—Kšœ'˜'Kšœ˜K˜—š œžœ˜Kšœžœ˜5šžœžœžœž˜(Kšœžœ˜Kšœ2˜2Kšœ˜Kšžœžœ1˜EKšœ˜Kšžœ˜—Kšœ˜Kšœ˜K˜—š œžœ˜Kšžœžœ(žœ:˜lKšœ˜Kšœ˜K˜—Kš¢œ¢œ¢œ¢œ¢œ¢œ,¢œ¢œ#¢™¡Kšœžœi˜†Kšœ'˜'Kšœžœžœ˜Kšœv˜vKš œ žœ žœžœžœ˜8K˜šžœžœž˜šžœž˜šœ žœ ž˜šœžœ ž˜$Kšœ˜Kšœ žœ˜Kšžœ˜—Kšœ žœ˜Kšœžœ˜Kšžœ˜—šœžœ ž˜$Kšœ˜Kšœ!˜!Kšžœ˜—šœžœ ž˜(šœžœ ž˜$Kšœ˜Kšœ˜Kšœ žœ˜Kšžœ˜—Kšžœ˜—šœžœ ž˜%Kšœ ˜ Kšžœ˜—šœžœ ž˜)šœžœ ž˜$Kšœ-˜-Kšžœ˜—Kšžœ˜—šœ"žœ ž˜7šœžœ ž˜$Kšœ˜Kšœ žœ˜Kšžœ˜—Kšžœ˜—Kšžœ˜—Kšœ0žœ'žœ˜`Kšžœ˜—Kšžœžœžœžœ ˜VKšœ˜K˜—š œžœžœžœBžœžœžœžœ žœ žœ˜ùK˜š œžœ˜Kšœžœžœ˜Kšœ ˜ Kšœ+˜+Kš œ žœ žœžœžœ˜6Kšœ:˜:šžœžœžœž˜&šžœ?žœ˜GKšœ˜Kšœžœ˜ Kšžœ˜K˜—š žœžœžœžœžœž˜9šžœ<žœ˜DKšžœžœ4˜AKšœ˜Kšœžœ˜ K˜—Kšžœ˜—Kšžœ˜—KšžœžœžœI˜ZKšœ ˜ K˜K˜—š œžœ˜Kšœ ˜ Kšœžœ˜-Kšœ+˜+Kš œ žœ žœžœžœ˜6Kšœ:˜:Kšžœžœ1˜GKšœ˜Kšœ˜Kšœ˜K˜—š œžœ˜Kšžœžœ?žœ9˜‚Kšœ˜K˜K˜—Kš¢œ¢œ¢œ¢œ¢œ¢œ+¢œ¢œ¢™ªKšœžœr˜Kšœ'˜'Kšœ˜Kšœžœžœ ˜šž˜Kšœ0žœ'žœ˜`šžœž˜šœ žœ ž˜šœžœ ž˜$Kšœ)˜)Kšœ žœ˜Kšžœ˜—Kšœ žœ˜Kšœžœ˜Kšžœ˜—šœžœ ž˜3Kšœ ˜ Kšœ'˜'Kšžœ˜—šœžœ ž˜*šœžœ ž˜$Kšœ˜Kšœ)˜)Kšœžœ˜Kšžœ˜—Kšžœ˜—šœžœ ž˜%Kšœ˜Kšžœ˜—šœžœ ž˜(šœžœ ž˜$Kšœ&˜&Kšžœ˜—Kšžœ˜—šœžœ ž˜0šœžœ ž˜$Kšœ)˜)Kšœžœ˜Kšžœ˜—Kšžœ˜—Kšžœ˜—Kšžœ˜—Kšžœ"žœžœžœ ˜dKšœ˜K˜—š  œžœYžœD˜´šžœ,ž˜3Kšœžœ˜Kšœ2˜2Kšœ˜Kšžœžœ1˜EKšœ˜Kšžœ˜—Kšœžœ˜Kšœ˜K˜K˜—š  œžœ\˜mKšžœžœžœI˜jKšžœ<žœD˜†K˜K˜—š   œžœžœžœ žœ žœ˜OKšœžœ™ Kš žœžœžœ1žœ'žœ™“Kšžœžœ ˜'K˜K˜—š  œžœžœžœžœ žœ žœ žœ˜dKšœžœ ˜*Kšœ˜šœ žœžœž˜Kšœžœ(˜@Kšœ žœ˜&Kšžœ ˜—Kšœ˜K˜—šŸœžœ˜šžœžœž˜Kš žœžœžœžœžœ ˜Kšœ$˜$Kšžœ ˜—K˜K˜——Kšžœ˜—…—q^˜H