DIRECTORY Core, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, IO, Pipal, PipalCore, PipalInstanceTable, PipalInt, PipalIO, PipalMos, PipalSinix, PipalUI, PatchWork, RefTab, Rope, TerminalIO; PatchWorkImpl: CEDAR PROGRAM IMPORTS CoreClasses, CoreIO, CoreOps, CoreProperties, IO, PatchWork, Pipal, PipalCore, PipalInstanceTable, PipalInt, PipalIO, PipalMos, PipalSinix, PipalUI, RefTab, Rope, TerminalIO EXPORTS PatchWork = BEGIN OPEN PatchWork; CellType: TYPE = Core.CellType; Object: TYPE = Pipal.Object; Objects: TYPE = Pipal.Objects; Wire: TYPE = Core.Wire; WireSeq: TYPE = Core.WireSeq; ROPE: TYPE = Core.ROPE; Properties: TYPE = Core.Properties; Wires: TYPE = Core.Wires; Signal: PUBLIC SIGNAL [cellType: CellType] = CODE; Error: PUBLIC ERROR [type: ATOM, message: ROPE, cellType: CellType] = CODE; PinsCorrespondingToSeveralPublics: PUBLIC SIGNAL [cellType: CellType, obj: Object, publics: Wires, geometry: Object] = CODE; NoPinsOnAtomicPublic: PUBLIC SIGNAL [cellType: CellType, obj: Object, public: Wire, message: ROPE _ NIL] = CODE; layoutAtomsTable: RefTab.Ref _ RefTab.Create[]; LayoutAtomData: TYPE = REF LayoutAtomDataRec; LayoutAtomDataRec: TYPE = RECORD [layoutProc: LayoutProc, decorateProc: DecorateProc, attributesProc: AttributesProc _ NIL]; RegisterLayoutAtom: PUBLIC PROC [layoutAtom: ATOM, layoutProc: LayoutProc, decorateProc: DecorateProc _ NIL, attributesProc: AttributesProc _ NIL] RETURNS [sameAtom: ATOM] = { sameAtom _ layoutAtom; IF ~RefTab.Store[layoutAtomsTable, layoutAtom, NEW [LayoutAtomDataRec _ [layoutProc: layoutProc, decorateProc: decorateProc, attributesProc: attributesProc]]] THEN TerminalIO.PutF["LayoutProc and DecorateProc for %g overwritten\n", IO.atom[layoutAtom]]; }; GetLayoutAtomData: PROC [layoutAtom: ATOM] RETURNS [layoutAtomData: LayoutAtomData] = { entry: ROPE; layoutAtomData _ NARROW [RefTab.Fetch[layoutAtomsTable, layoutAtom].val]; IF layoutAtomData#NIL THEN RETURN; entry _ PipalUI.FetchKeyLine["PatchWork.LoadList", IO.PutR1[IO.atom[layoutAtom]]]; IF entry=NIL THEN RETURN [NIL]; PipalUI.ExecuteInTerminal[entry]; layoutAtomData _ NARROW [RefTab.Fetch[layoutAtomsTable, layoutAtom].val]; }; GetLayoutAtomRegistration: PUBLIC PROC [layoutAtom: ATOM] RETURNS [layoutProc: LayoutProc _ NIL, decorateProc: DecorateProc _ NIL, attributesProc: AttributesProc _ NIL] = { layoutAtomData: LayoutAtomData _ GetLayoutAtomData[layoutAtom]; IF layoutAtomData=NIL THEN RETURN; layoutProc _ layoutAtomData.layoutProc; decorateProc _ layoutAtomData.decorateProc; attributesProc _ layoutAtomData.attributesProc; }; layoutAtomProp: PUBLIC ATOM _ CoreProperties.RegisterProperty[$Layout]; GetLayoutAtom: PUBLIC PROC [cellType: CellType] RETURNS [layoutAtom: ATOM _ NIL] = { layoutAtom _ NARROW [CoreProperties.InheritCellTypeProp[cellType, layoutAtomProp]]; }; CopyDecorations: PROC [to, from: CellType, obj: Object] = { CopyPins: PROC [toWire, fromWire: Wire] = { IF NOT PipalCore.HasPort[PipalCore.layoutDecoration, fromWire] THEN SIGNAL NoPinsOnAtomicPublic[from, obj, fromWire, CoreOps.GetFullWireName[from.public, fromWire]]; PipalCore.AddPort[PipalCore.layoutDecoration, toWire, PipalCore.GetPort[PipalCore.layoutDecoration, fromWire]]; }; CoreOps.VisitAtomicPairs[to.public, from.public, CopyPins]; }; CheckDecorations: PROC [ct: CellType, obj: Object] = { CheckPins: PROC [wire: Wire] = { IF NOT PipalCore.HasPort[PipalCore.layoutDecoration, wire] THEN SIGNAL NoPinsOnAtomicPublic[ct, obj, wire, CoreOps.GetFullWireName[ct.public, wire]]; }; CoreOps.VisitRootAtomics[ct.public, CheckPins]; }; FromPatchWorkRecord: PRIVATE TYPE = RECORD [int: INT]; fromPatchWorkTable: PRIVATE RefTab.Ref _ RefTab.Create[]; SetFromPatchWork: PRIVATE PROC [cellType: CellType] = { obj: Object _ PipalCore.GetObject[PipalCore.layoutDecoration, cellType]; int: INT _ LOOPHOLE [cellType]; IF RefTab.Fetch[fromPatchWorkTable, obj].val#NIL THEN Signal[cellType]; -- same object is stuffed on two different cells! That breaks the invariants, and Lichen will not work! [] _ RefTab.Store[fromPatchWorkTable, obj, NEW [FromPatchWorkRecord _ [int]]]; }; Layout: PUBLIC PROC [cellType: CellType] RETURNS [obj: Object] = { layoutAtom: ATOM; layoutAtomData: LayoutAtomData; name: ROPE _ CoreOps.GetCellTypeName[cellType]; obj _ PipalCore.GetObject[PipalCore.layoutDecoration, cellType]; IF obj#NIL THEN RETURN; layoutAtom _ NARROW [CoreProperties.GetCellTypeProp[cellType, layoutAtomProp]]; IF layoutAtom=NIL THEN layoutAtom _ NARROW [CoreProperties.GetCellClassProp[cellType.class, layoutAtomProp]]; IF layoutAtom=NIL AND cellType.class.recast=NIL THEN ERROR Error[$NoLayoutAtom, "Impossible to find a layoutAtom for this cellType", cellType]; layoutAtomData _ GetLayoutAtomData[IF layoutAtom=NIL THEN $Recast ELSE layoutAtom]; IF layoutAtomData=NIL THEN ERROR Error[$NoRegistration, IO.PutFR["LayoutAtom %g has not been registered", IO.atom[layoutAtom]], cellType]; IF layoutAtomData.attributesProc#NIL THEN layoutAtomData.attributesProc[cellType]; obj _ layoutAtomData.layoutProc[cellType]; IF name#NIL THEN obj _ Pipal.CreateAnnotation[obj, Pipal.nameProp, name]; PipalCore.PutObject[PipalCore.layoutDecoration, cellType, obj]; IF layoutAtomData.decorateProc#NIL THEN layoutAtomData.decorateProc[cellType, obj]; CheckDecorations[cellType, obj]; SetFromPatchWork[cellType]; }; GetPatchWorkExtractedCTKey: PUBLIC PROC [extractedCT: CellType] RETURNS [key: INT _ 0] = { obj: Object _ PipalCore.GetObject[PipalCore.layoutDecoration, extractedCT]; ref: REF FromPatchWorkRecord _ NARROW [RefTab.Fetch[fromPatchWorkTable, obj].val]; IF ref#NIL THEN key _ ref.int; }; IsPatchWorkGenerated: PUBLIC PROC [obj: Object] RETURNS [BOOL] = { RETURN [RefTab.Fetch[fromPatchWorkTable, obj].val#NIL]; }; FromLayoutWithoutPublic: PUBLIC PROC [obj: Object] RETURNS [cellType: CellType] = { cellType _ NARROW [PipalSinix.Extract[obj, PipalSinix.layoutMode].result]; IF IsPatchWorkGenerated[obj] THEN RETURN; -- done twice! SetLayoutAndDecoration[cellType, obj]; CheckDecorations[cellType, obj]; SetFromPatchWork[cellType]; }; maskSuffix: PUBLIC ROPE _ ".mask"; GetAndAddSuffix: PROC [cellType: CellType] RETURNS [obj: Object] = { ctName: ROPE _ CoreOps.GetCellTypeName[cellType]; maskName: ROPE _ Rope.Cat[ctName, maskSuffix]; obj _ PipalIO.Fetch[maskName]; }; Get: LayoutProc = { obj _ Pipal.CreateAnnotation[GetAndAddSuffix[cellType], PipalMos.indirectProp, NIL]; }; Flatten: PUBLIC PROC [object: Object] RETURNS [flat: Object] = { instances: Objects _ NIL; EachChild: PipalInt.EachChildProc = { instances _ CONS [PipalInt.TransformObject[transformation, Flatten[child]], instances]; }; IF Pipal.ObjectClass[object]=Pipal.annotationClass THEN { annotation: Pipal.Annotation _ NARROW [object]; IF annotation.key=$DontFlatten AND annotation.value#NIL THEN RETURN [object]; RETURN [Pipal.CreateAnnotation[Flatten[annotation.child], annotation.key, annotation.value]]; }; IF PipalMos.IsAtomic[object] THEN RETURN [object]; [] _ PipalInt.Enumerate[object, EachChild]; flat _ Pipal.CreateOverlay[instances]; }; GetAndFlatten: LayoutProc = { obj _ Flatten[GetAndAddSuffix[cellType]]; }; Value: LayoutProc = { obj _ NARROW [CoreProperties.GetCellTypeProp[cellType, $PWCoreValue]]; }; DecorateValue: PUBLIC DecorateProc = { extractedCT: CellType _ NARROW [PipalSinix.Extract[obj, PipalSinix.layoutMode].result]; extractedToSource: RefTab.Ref _ RefTab.Create[extractedCT.public.size]; FindInExtractedPublic: CoreOps.EachWireProc = { FOR names: LIST OF ROPE _ CoreOps.GetFullWireNames[cellType.public, wire], names.rest WHILE names#NIL DO name: ROPE _ names.first; extractedWire: Wire _ CoreOps.FindWire[extractedCT.public, name]; previousSourceWire: Wire _ NARROW [RefTab.Fetch[extractedToSource, extractedWire].val]; IF extractedWire=NIL OR extractedWire.size#0 THEN LOOP; IF previousSourceWire#NIL AND previousSourceWire#wire THEN SIGNAL PinsCorrespondingToSeveralPublics[cellType, obj, LIST [previousSourceWire, wire], PipalCore.GetPort[PipalCore.layoutDecoration, extractedWire]]; IF NOT PipalCore.HasPort[PipalCore.layoutDecoration, extractedWire] THEN SIGNAL NoPinsOnAtomicPublic[cellType, obj, extractedWire, name]; PipalCore.AddPort[PipalCore.layoutDecoration, wire, PipalCore.GetPort[PipalCore.layoutDecoration, extractedWire]]; [] _ RefTab.Store[extractedToSource, extractedWire, wire]; ENDLOOP; }; [] _ CoreOps.VisitWire[cellType.public, FindInExtractedPublic]; }; AttributeAbutXorY: AttributesProc = { ambiguous, inX: BOOL; [ambiguous, inX] _ InstancesInXOrY[PipalCore.schematicsDecoration, cellType, PipalUI.schematicFudge]; IF ambiguous THEN ERROR Error[$CallerBug, "*** Ambiguity for deciding between AbutX and AbutY.\n", cellType]; SortInstances[PipalCore.schematicsDecoration, cellType, IF inX THEN SortInX ELSE SortInY]; }; LayoutAbutXorY: LayoutProc = { obj _ (IF InstancesInXOrY[PipalCore.schematicsDecoration, cellType, PipalUI.schematicFudge].inX THEN AbutX ELSE AbutY)[cellType]; }; AttributeX: AttributesProc = {SortInstances[PipalCore.schematicsDecoration, cellType, SortInX]}; AttributeY: AttributesProc = {SortInstances[PipalCore.schematicsDecoration, cellType, SortInY]}; AbutX: LayoutProc = {obj _ Abut[TRUE, cellType]}; AbutY: LayoutProc = {obj _ Abut[FALSE, cellType]}; ReverseAbutX: LayoutProc = {obj _ Abut[TRUE, cellType, TRUE]}; ReverseAbutY: LayoutProc = {obj _ Abut[FALSE, cellType, TRUE]}; Abut: PROC [inX: BOOL, cellType: CellType, reverse: BOOL _ FALSE] RETURNS [obj: Object] = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; subObjects: LIST OF Object _ NIL; FOR i: NAT DECREASING IN [0 .. data.size) DO subObjects _ CONS [Layout[data[i].type], subObjects]; ENDLOOP; obj _ PipalInt.CreateAbut[inX, IF reverse THEN Pipal.Reverse[subObjects] ELSE subObjects]; }; AbutFlipXAndDecorate: LayoutProc = {obj _ AbutFlipAndDecorate[cellType, TRUE]}; AbutFlipYAndDecorate: LayoutProc = {obj _ AbutFlipAndDecorate[cellType, FALSE]}; AbutFlipAndDecorate: PROC [cellType: CellType, inX: BOOL] RETURNS [obj: Object] = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; flip: BOOL _ FALSE; -- indicates polarity of the coming flip instances: Objects _ NIL; -- instances for constructing the cell layout0: Object _ Layout[data[0].type]; isize0: PipalInt.Size _ PipalInt.AbutBox[layout0].size; pos: PipalInt.Position _ [0, 0]; -- position (in ir coordonnates) of the coming cell FOR i: NAT IN [0 .. data.size) DO orientation: PipalInt.Orientation _ IF flip THEN IF inX THEN mirrorX ELSE rotate180X ELSE identity; layout: Object _ Layout[data[i].type]; ir: PipalInt.Rectangle = PipalInt.TransformRectangle[[PipalInt.zeroVector, orientation], PipalInt.AbutBox[layout]]; trans: PipalInt.Transformation = [PipalInt.Sub[pos, ir.base], orientation]; -- translation, in the cell coordonnate system IF NOT (IF inX THEN ir.size.y=isize0.y ELSE ir.size.x=isize0.x) THEN ERROR; -- incompatible y dimension for an abutX instances _ CONS [PipalInt.TransformObject[trans, layout], instances]; PipalCore.PutTrans[PipalCore.layoutDecoration, data[i], trans]; IF inX THEN pos.x _ pos.x + ir.size.x ELSE pos.y _ pos.y + ir.size.y; flip _ NOT flip; ENDLOOP; obj _ Pipal.CreateOverlay[instances]; PipalCore.PutRecordPorts[PipalCore.layoutDecoration, cellType, PipalInt.AbutBox[obj]]; }; ArrayX: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutX]; obj _ Pipal.CreateAnnotation[Layout[recasted], PipalMos.indirectProp, NIL]; }; ArrayY: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutY]; obj _ Pipal.CreateAnnotation[Layout[recasted], PipalMos.indirectProp, NIL]; }; ArrayFlipX: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutFlipX]; obj _ Pipal.CreateAnnotation[Layout[recasted], PipalMos.indirectProp, NIL]; }; ArrayFlipY: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawAbutFlipY]; obj _ Pipal.CreateAnnotation[Layout[recasted], PipalMos.indirectProp, NIL]; }; ReverseArrayX: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawReverseAbutX]; obj _ Pipal.CreateAnnotation[Layout[recasted], PipalMos.indirectProp, NIL]; }; ReverseArrayY: LayoutProc = { recasted: CellType _ CoreOps.Recast[cellType]; SetLayout[recasted, $RawReverseAbutY]; obj _ Pipal.CreateAnnotation[Layout[recasted], PipalMos.indirectProp, NIL]; }; Recast: LayoutProc = { obj _ Pipal.CreateAnnotation[Layout[CoreOps.Recast[cellType]], PipalMos.indirectProp, NIL]; }; DecorateEnumeration: PUBLIC PROC [cellType: CellType, obj: Object, reverse: BOOL _ FALSE] = { rank: NAT _ 0; Each: PipalInt.EachChildProc = { instance: CoreClasses.CellInstance _ recordData[IF reverse THEN recordData.size-rank-1 ELSE rank]; IF Layout[instance.type]#child THEN ERROR Error[$CallerBug, "DecorateEnumeration assumptions not valid", cellType]; PipalCore.PutTrans[PipalCore.layoutDecoration, instance, transformation]; }; recordData: CoreClasses.RecordCellType _ NARROW [cellType.data]; abutBox: PipalInt.Rectangle _ PipalInt.AbutBox[obj]; IF PipalInt.CountChildren[obj]#recordData.size THEN ERROR Error[$CallerBug, "DecorateEnumeration assumption not valid: layout has a different number of instances than record CellType", cellType]; WHILE Pipal.ObjectClass[obj]=Pipal.annotationClass DO obj _ PipalInt.NthChild[obj].nthChild; ENDLOOP; [] _ PipalInt.Enumerate[obj, Each]; PipalCore.PutRecordPorts[PipalCore.layoutDecoration, cellType, abutBox]; }; DecorateAbutXY: DecorateProc = {DecorateEnumeration[cellType, obj, FALSE]}; DecorateReverseAbut: DecorateProc = {DecorateEnumeration[cellType, obj, TRUE]}; DecorateRecasted: PUBLIC DecorateProc = { CopyDecorations[cellType, CoreOps.Recast[cellType], obj]; }; Rotated: PROC [cellType: CellType] RETURNS [rotatedCT: CellType] = { rct: CoreClasses.RecordCellType; IF cellType.class#CoreClasses.recordCellClass THEN ERROR Error[$CallerBug, "Rotation CellType expected [RecordCell with one instance]", cellType]; rct _ NARROW [cellType.data]; IF rct.size#1 THEN ERROR Error[$CallerBug, "Rotation CellType expected [RecordCell with one instance]", cellType]; rotatedCT _ rct[0].type; }; FlipX: LayoutProc = { obj _ PipalInt.CreateOrient[mirrorX, Layout[Rotated[cellType]]]; }; FlipY: LayoutProc = { obj _ PipalInt.CreateOrient[rotate180X, Layout[Rotated[cellType]]]; }; Rot90: LayoutProc = { obj _ PipalInt.CreateOrient[rotate90, Layout[Rotated[cellType]]]; }; Rot180: LayoutProc = { obj _ PipalInt.CreateOrient[rotate180, Layout[Rotated[cellType]]]; }; Rot270: LayoutProc = { obj _ PipalInt.CreateOrient[rotate270, Layout[Rotated[cellType]]]; }; DecorateTransformed: PUBLIC DecorateProc = { rotatedCT: CellType = Rotated[cellType]; trans: PipalInt.Transformation; child: Object; abutBox: PipalInt.Rectangle _ PipalInt.AbutBox[obj]; WHILE Pipal.ObjectClass[obj]=Pipal.annotationClass DO obj _ PipalInt.NthChild[obj].nthChild; ENDLOOP; IF PipalInt.CountChildren[obj]#1 THEN ERROR Error[$CallerBug, "DecorateTransformed is not supposed to be called with an obj that does not expand into a one instance cell", cellType]; [trans, child] _ PipalInt.NthChild[obj]; IF Layout[rotatedCT]#child THEN ERROR Error[$CallerBug, "DecorateTransformed: some invariant broken", cellType]; PipalCore.PutTrans[PipalCore.layoutDecoration, NARROW [cellType.data, CoreClasses.RecordCellType][0], trans]; PipalCore.PutRecordPorts[PipalCore.layoutDecoration, cellType, abutBox]; }; SortInX: PUBLIC PROC [pos1, pos2: PipalInt.Position] RETURNS [BOOL] = {RETURN [pos1.xpos2.x]}; ReverseSortInY: PUBLIC PROC [pos1, pos2: PipalInt.Position] RETURNS [BOOL] = {RETURN [pos1.y>pos2.y]}; InstanceAbutBox: PROC [decoration: PipalCore.Decoration, instance: CoreClasses.CellInstance] RETURNS [abutBox: PipalInt.Rectangle] = { trans: PipalInt.Transformation _ PipalCore.GetTrans[decoration, instance]; object: Object _ PipalCore.GetObject[decoration, instance.type]; abutBox _ PipalInt.TransformRectangle[trans, PipalInt.AbutBox[object]]; }; InstancesInXOrY: PUBLIC PROC [decoration: PipalCore.Decoration, record: CellType, fudge: INT _ 0] RETURNS [ambiguous, inX: BOOL] = { data: CoreClasses.RecordCellType _ NARROW [record.data]; overlappingInX, overlappingInY: BOOL _ FALSE; FOR i: NAT IN [0 .. data.size-1) DO rect1: PipalInt.Rectangle _ InstanceAbutBox[decoration, data[i]]; FOR j: NAT IN (i .. data.size) DO rect2: PipalInt.Rectangle _ InstanceAbutBox[decoration, data[j]]; IF rect1.base.x+fudge extractedPublic layout _ Layout[sourceCT]; extractedCT _ NARROW [PipalSinix.Extract[layout, PipalSinix.layoutMode].result]; extractedToSource _ RefTab.Create[]; -- maps extractedWire to source extractedInstances _ InstanceTableFromPublic[PipalCore.layoutDecoration, PipalInt.BBox[layout, []], extractedCT.public]; key _ GetPatchWorkExtractedCTKey[extractedCT]; CoreOps.VisitRootAtomics[sourceCT.public, FillTable]; }; InstanceTableFromPublic: PROC [decoration: PipalCore.Decoration, bbox: PipalInt.Rectangle, public: WireSeq] RETURNS [table: PipalInstanceTable.Table] = { FillInstanceTable: PROC [wire: Wire] = { PipalInstanceTable.Insert[table, [], PipalCore.GetPort[decoration, wire], wire]; }; table _ PipalInstanceTable.Create[bbox]; CoreOps.VisitRootAtomics[public, FillInstanceTable]; }; [] _ RegisterLayoutAtom[$Get, Get, DecorateValue]; [] _ RegisterLayoutAtom[$GetAndFlatten, GetAndFlatten, DecorateValue]; [] _ RegisterLayoutAtom[$Value, Value, DecorateValue]; [] _ RegisterLayoutAtom[$ValueNoDecorate, Value]; [] _ RegisterLayoutAtom[$AbutListXNoDecorate, AbutX]; [] _ RegisterLayoutAtom[$AbutListYNoDecorate, AbutY]; [] _ RegisterLayoutAtom[$RawAbutX, AbutX, DecorateAbutXY]; [] _ RegisterLayoutAtom[$RawAbutY, AbutY, DecorateAbutXY]; [] _ RegisterLayoutAtom[$RawAbutFlipX, AbutFlipXAndDecorate]; [] _ RegisterLayoutAtom[$RawAbutFlipY, AbutFlipYAndDecorate]; [] _ RegisterLayoutAtom[$RawReverseAbutX, ReverseAbutX, DecorateReverseAbut]; [] _ RegisterLayoutAtom[$RawReverseAbutY, ReverseAbutY, DecorateReverseAbut]; [] _ RegisterLayoutAtom[$AbutX, AbutX, DecorateAbutXY, AttributeX]; [] _ RegisterLayoutAtom[$AbutY, AbutY, DecorateAbutXY, AttributeY]; [] _ RegisterLayoutAtom[$Abut, LayoutAbutXorY, DecorateAbutXY, AttributeAbutXorY]; [] _ RegisterLayoutAtom[$ReverseAbutX, ReverseAbutX, DecorateReverseAbut, AttributeX]; [] _ RegisterLayoutAtom[$ReverseAbutY, ReverseAbutY, DecorateReverseAbut, AttributeY]; [] _ RegisterLayoutAtom[$ArrayX, ArrayX, DecorateRecasted]; [] _ RegisterLayoutAtom[$ArrayY, ArrayY, DecorateRecasted]; [] _ RegisterLayoutAtom[$ArrayFlipX, ArrayFlipX, DecorateRecasted]; [] _ RegisterLayoutAtom[$ArrayFlipY, ArrayFlipY, DecorateRecasted]; [] _ RegisterLayoutAtom[$ReverseArrayX, ReverseArrayX, DecorateRecasted]; [] _ RegisterLayoutAtom[$ReverseArrayY, ReverseArrayY, DecorateRecasted]; [] _ RegisterLayoutAtom[$Recast, Recast, DecorateRecasted]; [] _ RegisterLayoutAtom[$FlipX, FlipX, DecorateTransformed]; [] _ RegisterLayoutAtom[$FlipY, FlipY, DecorateTransformed]; [] _ RegisterLayoutAtom[$Rot90, Rot90, DecorateTransformed]; [] _ RegisterLayoutAtom[$Rot180, Rot180, DecorateTransformed]; [] _ RegisterLayoutAtom[$Rot270, Rot270, DecorateTransformed]; END. PatchWorkImpl.mesa Copyright ำ 1988 by Xerox Corporation. All rights reserved. Created by Bertrand Serlet, May 8, 1988 2:18:10 am PDT Bertrand Serlet May 11, 1988 10:55:41 pm PDT Basics Exceptions LayoutAtomsTable Primitives Copies decorations from from to to We check that the public of the source and the public of the recasted layout are similar, and we copy properties from one to the other Checks that's ct is properly decorated. You don't really want to know why! We compute the attributes (if any) Now the layout We decorate for lazy decorations Now we decorate the source cellType We check those decorations, and we decorate layoutCellType. We need to do that in order to be able to return layoutCellType as the result of the extraction. We mark obj as coming from Layout $Get, $GetAndFlatten, $Value and $ValueNoDecorate Question for the reader: Why are we making an indirect here??? Answer: because two different cellTypes can have the exact same name and Layout: $Get. For example two icons extracted in different Sisyph contexts will yield two different (but identical!) cellTypes. Abuts, Arrays and Recast We decorate each instance with the appropriate trans, so that the Lazy GetPins can find the location We decorate each instance with the appropriate trans, so that the Lazy GetPins can find the location Rotations Help for writing DecorateProcs Short cut Saving "Checkpoints" Core Shell Layout Backdoor for clients such as PWCoreLichen Creates a table instance -> public Initialization and various registrations สญ˜šœ™Icodešœ<™˜>Kšœ˜KšœW˜WKšœ ˜ Kšœ˜—K˜šะbn œœ˜Kšœ/œ}˜ตKšœ ˜Kšœœ ˜—head™Kšœ œ˜Kšœœ˜Kšœ œ˜Kšœœ ˜Kšœ œ˜Kšœœœ˜Kšœ œ˜#Kšœœ˜—™ šฯnœœœœ˜2J˜—š Ÿœœœœ œœ˜KJ˜—šŸ!œœœGœ˜|J˜—Jš Ÿœœœ:œœœ˜p—šœ™Jšœ/˜/J˜Kšœœœ˜-KšœœœWœ˜|K˜šŸœœœœ7œ#œœ œ˜ฏKšœ˜šœ-œm˜ŸKšœEœ˜^—K˜K˜—šŸœœœœ%˜WKšœœ˜ Kšœœ2˜IKšœœœœ˜"Kšœ3œœ˜RKš œœœœœ˜Kšœ!˜!Kšœœ2˜IK˜K˜—šŸœœœœœœœ#œ˜ฌKšœ?˜?Kšœœœœ˜"Kšœ(˜(Kšœ,˜,Kšœ/˜/K˜——šœ ™ šœœœ,˜GJ˜—š Ÿ œœœœœœ˜TKšœ œ@˜SK˜K˜—Kšœ"™"šŸœœ&˜;šŸœœ˜+šœœ9˜?Jšœœ[˜f—Jšœo˜oK˜—Kšœ†™†Kšœ;˜;K˜K˜—Kšœ'™'šŸœœ ˜6šŸ œœ˜ šœœ5œ˜@JšœO˜U—K˜—Kšœ/˜/K˜K˜—Jšœ"™"Jš œะbkœœœœ˜6šœ œ˜9J˜—šŸœœœ˜7KšœH˜HKšœœœ ˜Kšœ+œœฯch˜ฐKšœ+œ ˜NK˜J˜—šŸœœœœ˜BKšœ œ˜Kšœ˜Kšœœ%˜/Kšœ@˜@Kšœœœœ˜Kšœ œ<˜Ošœ œœ˜Kšœ œC˜V—š œ œœœœ˜5KšœV˜[—Kš œ#œ œœ œ ˜Sšœœœ˜Kšœœ0œ˜o—K™"Kšœœœ)˜RK™Kšœ*˜*Kšœœœ9˜IK™ Kšœ?˜?Kšœ#™#Kšœœœ,˜SKšœ™Kšœ ˜ Kšœ!™!Kšœ˜Kšœ˜—K˜š Ÿœœœœœ ˜ZKšœK˜KKšœœœ-˜RKšœœœ˜J˜J˜—š Ÿœœœœœ˜BJšœ,œ˜7J˜J˜—šŸœœœœ˜SJšœ œ9˜JKšœœœก˜8Kšœ&˜&Kšœ ˜ Kšœ˜K˜——šœ1™1šœ œœ ˜"J˜—šŸœœœ˜DJšœœ%˜1Jšœ œ ˜.Jšœ˜J˜J˜—K™>K™ษšžœ˜JšœOœ˜TK˜K˜—šŸœœœœ˜@Jšœœ˜šŸ œ˜%Jšœ œG˜WJ˜—šœ1œ˜9Jšœœ ˜/Jš œœœœœ ˜MJšœW˜]J˜—Jšœœœ ˜2Jšœ+˜+Jšœ&˜&Jšœ˜J˜—šŸ œ˜Jšœ)˜)K˜K˜—šŸœ˜Kšœœ:˜FK˜K˜—šŸ œœ˜&Jšœœ9˜WJšœG˜Gšžœ˜/š œœœœ?œœ˜hKšœœ˜KšœA˜AKšœœ6˜WKš œœœœœ˜7Kš œœœœœ2œ[˜าšœœ>˜DJšœœ:˜E—Jšœr˜rKšœ:˜:Kšœ˜—J˜—Jšœ?˜?Kšœ˜——™šŸœ˜%Kšœœ˜Kšœe˜eKšœ œœV˜mKšœ8œœ œ ˜ZKšœ˜K˜—šŸœ˜KšœœWœœ˜K˜K˜—šŸ œV˜`K˜—šŸ œV˜`K˜—KšŸœœ ˜1KšŸœœ ˜2KšŸ œœ œ˜>šŸ œœ œ˜?K˜—š Ÿœœœœœœ˜[Kšœ#œ˜:Kšœ œœ œ˜!š œœ œœ˜,Kšœ œ$˜5Kšœ˜—Jš œŸ œœ œœ ˜ZK˜K˜—šŸœ4œ˜OK˜—šŸœ4œ˜PK˜—šŸœœœœ˜SKšœ#œ˜:Kšœœœก(˜˜>Jšœ>˜>—J˜Kšœ˜K™—…—[8u้