CDMakeProcCommands.mesa (module for ChipNDale)
Copyright © 1985 by Xerox Corporation. All rights reserved.
by Christian Jacobi, May 9, 1985 1:58:40 pm PDT
Last edited by: Christian Jacobi, November 3, 1986 6:30:14 pm PST
DIRECTORY
Ascii,
Atom,
CD,
CDAtomicObjects,
CDBasics,
CDCells,
CDDirectory,
CDInstances,
CDMakeProcPrivate,
CDProperties,
CDOps,
CDSequencer,
CDSymbolicObjects,
Convert,
IO,
PriorityQueue,
RefTab,
Rope,
SymTab,
TerminalIO,
TiogaFileOps,
TiogaOps,
ViewerTools;
CDMakeProcCommands: CEDAR PROGRAM
IMPORTS Ascii, Atom, Convert, CD, CDAtomicObjects, CDBasics, CDCells, CDDirectory, CDInstances, CDProperties, CDOps, CDSequencer, CDSymbolicObjects, IO, PriorityQueue, RefTab, Rope, SymTab, TerminalIO, TiogaFileOps, TiogaOps, ViewerTools
EXPORTS CDMakeProcPrivate =
BEGIN
Environment: TYPE = REF EnvironmentRep;
EnvironmentRep: PUBLIC TYPE = RECORD [
invocationKey: REF,
rootNode: TiogaFileOps.Ref,
commentNode: TiogaFileOps.Ref, --insert sibling for next comment
modHeaderNode: TiogaFileOps.Ref, --DIRECTORY... to excluding BEGIN
declNode: TiogaFileOps.Ref, --insert sibling for next declaration on module level
procNode: TiogaFileOps.Ref, --insert sibling for next global procedures
procDecNode: TiogaFileOps.Ref, --insert sibling for next local declaration
postDeclNode: TiogaFileOps.Ref, --insert sibling for next declaration on module level
firstModStatementNode: TiogaFileOps.Ref, --reserved for first statement
modStatementNode: TiogaFileOps.Ref, --insert sibling for next mudule statement
procName: Rope.ROPE,
modifier: INT ← 0,
directory: SymTab.Ref,
imports: SymTab.Ref,
declaredLayers: ARRAY CD.Layer OF Rope.ROPEALL[NIL],
nameToThing: SymTab.Ref,
thingToName: RefTab.Ref,
globalThingToName: RefTab.Ref,
hasDirGen: BOOLFALSE,
properties: CD.PropRef
];
ExpressionProc: TYPE = CDMakeProcPrivate.ExpressionProc;
GetEnvironmentProp: PUBLIC PROC [env: Environment, key: REF] RETURNS [REF] = {
RETURN [CDProperties.GetProp[env.properties, key]]
};
PutEnvironmentProp: PUBLIC PROC [env: Environment, key: REF, val: REF] = {
CDProperties.PutProp[env.properties, key, val]
};
RegisterExpressionProc: PUBLIC PROC [for: REF, ep: ExpressionProc, tech: CD.Technology ← NIL] = {
WITH for SELECT FROM
c: CD.ObjectClass =>
CDProperties.PutProp[c.properties, $MakeCallExpression, NEW[ExpressionProc𡤎p]];
a: ATOM => RegisterExpressionProc[CD.FetchObjectClass[a, tech], ep, tech];
ENDCASE => ERROR
};
SpecificCallExpression: PROC [env: Environment, ob: CD.Object] RETURNS [r: Rope.ROPENIL] = {
x: REF ← CDProperties.GetProp[ob.class.properties, $MakeCallExpression];
WITH x SELECT FROM
rmce: REF ExpressionProc => r ← rmce^[env, ob]
ENDCASE => NULL;
};
MakeNodeComment: PROC [node: TiogaFileOps.Ref] = {
TRUSTED { TiogaOps.PutProp[LOOPHOLE[node], $Comment, NEW[BOOLEANTRUE]] };
};
Reserve: PROC [env: Environment, key: Rope.ROPE] = {
[] ← SymTab.Store[env.nameToThing, key, $reserved];
};
IncludeDirectory: PUBLIC PROC [env: Environment, module: Rope.ROPE, import: BOOLTRUE] = {
[] ← SymTab.Store[env.nameToThing, module, $module];
[] ← SymTab.Insert[env.directory, module, module];
IF import THEN [] ← SymTab.Insert[env.imports, module, module];
};
MakeDirectory: PROC [env: Environment] = {
r: Rope.ROPENIL;
Each: SymTab.EachPairAction = {
IF num=0 THEN TiogaFileOps.SetContents[env.modHeaderNode, "DIRECTORY"]
ELSE r ← r.Concat[", "];
r ← r.Concat[key];
num ← num+1;
quit ← FALSE
};
num: INT ← 0;
[] ← env.directory.Pairs[Each];
IF num>0 THEN {
node: TiogaFileOps.Ref ← TiogaFileOps.InsertNode[env.modHeaderNode, TRUE];
TiogaFileOps.SetContents[node, r.Concat[";"]];
}
ELSE TiogaFileOps.SetContents[env.modHeaderNode, ""];
};
MakeImportsExpr: PROC [env: Environment] RETURNS [r: Rope.ROPENIL] = {
Each: SymTab.EachPairAction = {
IF num=0 THEN r ← "IMPORTS "
ELSE r ← r.Concat[", "];
r ← r.Concat[key];
num ← num+1;
quit ← FALSE
};
num: INT ← 0;
[] ← env.imports.Pairs[Each];
};
NewEnvironment: PROC [t: CD.Technology] RETURNS [env: Environment] = {
env ← NEW[EnvironmentRep←[properties: CD.InitPropRef[]]];
env.invocationKey ← NEW[INT];
env.rootNode ← TiogaFileOps.CreateRoot[];
env.commentNode ← TiogaFileOps.InsertNode[env.rootNode, TRUE];
TiogaFileOps.SetContents[env.commentNode, "--///temp/ChipNDale/temp.mesa"];
MakeNodeComment[env.commentNode];
env.commentNode ← TiogaFileOps.InsertNode[env.commentNode];
TiogaFileOps.SetContents[env.commentNode, "--created by ChipNDale"];
MakeNodeComment[env.commentNode];
env.modHeaderNode ← TiogaFileOps.InsertNode[env.commentNode];
env.declNode ← TiogaFileOps.InsertNode[env.modHeaderNode];
TiogaFileOps.SetContents[env.declNode, "BEGIN"];
GlobalDeclaration1[env, IO.PutFR["tech: CD.Technology ← CD.FetchTechnology[$%g];", IO.atom[t.key]]];
env.procNode ← TiogaFileOps.InsertNode[env.declNode];
TiogaFileOps.SetContents[env.procNode, ""];
env.postDeclNode ← TiogaFileOps.InsertNode[env.procNode];
TiogaFileOps.SetContents[env.postDeclNode, "context: CDGenerate.Context ← CDGenerate.AssertContext[""USER""];"];
env.firstModStatementNode ← env.modStatementNode ← TiogaFileOps.InsertNode[env.postDeclNode];
env.nameToThing ← SymTab.Create[];
env.directory ← SymTab.Create[];
env.imports ← SymTab.Create[];
env.thingToName ← RefTab.Create[];
env.globalThingToName ← RefTab.Create[];
};
FinishUp: PROC [env: Environment] = {
node: TiogaFileOps.Ref;
subNode: TiogaFileOps.Ref;
fileName: Rope.ROPE ← "///temp/ChipNDale/temp.mesa";
r: Rope.ROPENIL;
MakeDirectory[env];
node ← TiogaFileOps.InsertNode[env.modHeaderNode];
TiogaFileOps.SetContents[node, "Temp: CEDAR PROGRAM"];
subNode ← TiogaFileOps.InsertNode[node, TRUE];
TiogaFileOps.SetContents[subNode, Rope.Cat[MakeImportsExpr[env], " ="]];
r ← IO.PutFR["[] ← context.Register[""%g"", %g];", IO.rope[env.procName], IO.rope[env.procName]];
TiogaFileOps.SetContents[env.firstModStatementNode, r];
GlobalStatement[env, "END."];
TiogaFileOps.Store[env.rootNode, fileName];
env.rootNode ← env.commentNode ← env.modHeaderNode ← NIL;
env.declNode ← env.procNode ← env.postDeclNode ← NIL;
env.firstModStatementNode ← env.modStatementNode ← NIL;
env.directory ← env.imports ← env.nameToThing ← NIL;
env.thingToName ← NIL;
env.globalThingToName ← NIL;
TerminalIO.PutRope[fileName];
TerminalIO.PutRope[" created\n"];
[] ← ViewerTools.MakeNewTextViewer[info: [
file: fileName,
label: fileName,
name: fileName,
iconic: FALSE
]];
};
MakeProcedureNode: PROC [env: Environment] RETURNS [TiogaFileOps.Ref] = {
env.procNode ← TiogaFileOps.InsertNode[env.procNode];
env.procDecNode ← NIL;
RETURN [env.procNode]
};
MakeDeclarationNode: PROC [env: Environment] RETURNS [TiogaFileOps.Ref] = {
env.declNode ← TiogaFileOps.InsertNode[env.declNode];
RETURN [env.declNode]
};
GlobalDeclaration1: PUBLIC PROC [env: Environment, line: Rope.ROPE] = {
node: TiogaFileOps.Ref ← MakeDeclarationNode[env];
TiogaFileOps.SetContents[node, line];
};
GlobalDeclaration2: PUBLIC PROC [env: Environment, line: Rope.ROPE] = {
env.postDeclNode ← TiogaFileOps.InsertNode[env.postDeclNode];
TiogaFileOps.SetContents[env.postDeclNode, line];
};
GlobalStatement: PUBLIC PROC [env: Environment, line: Rope.ROPE] = {
env.modStatementNode ← TiogaFileOps.InsertNode[env.modStatementNode];
TiogaFileOps.SetContents[env.modStatementNode, line];
};
MakeDirGenerator: PROC [env: Environment] = {
IF ~env.hasDirGen THEN {
env.hasDirGen ← TRUE;
GlobalDeclaration2[env, "directory: CDGenerate.Context ← CDGenerate.AssertContext[""DIRECTORY""];"];
}
};
RequestGlobalIdent: PUBLIC PROC[env: Environment, proposed: Rope.ROPE, whatFor: REFNIL] RETURNS [Rope.ROPE] = {
RETURN [RequestIdent[env, proposed, whatFor, TRUE]];
};
GlobalIdent: PUBLIC PROC [env: Environment, whatFor: REF] RETURNS [Rope.ROPE] = {
RETURN [Ident[env, whatFor, TRUE]];
};
RopeToId: PROC [r: Rope.ROPE] RETURNS [id: Rope.ROPE] = {
first: BOOLTRUE;
Trans: Rope.TranslatorType = {
IF Ascii.Letter[old] THEN new ← old
ELSE IF Ascii.Digit[old] AND ~first THEN new ← old
ELSE new ← 'x;
first ← FALSE
};
id ← Rope.Translate[base: r, translator: Trans];
IF Rope.IsEmpty[id] THEN id ← "x";
};
RequestIdent: PROC [env: Environment, proposed: Rope.ROPENIL, whatFor: REFNIL, global: BOOL�LSE] RETURNS [r: Rope.ROPE] = {
proposed ← RopeToId[proposed];
r ← proposed;
DO
IF SymTab.Insert[env.nameToThing, r, whatFor] THEN {
IF global THEN
[] ← RefTab.Store[env.globalThingToName, whatFor, r];
[] ← RefTab.Store[env.thingToName, whatFor, r];
RETURN;
};
env.modifier ← env.modifier+1;
r ← IO.PutFR["%gx%g", IO.rope[proposed], IO.int[env.modifier]]
ENDLOOP
};
Ident: PROC [env: Environment, whatFor: REF, global: BOOL] RETURNS [Rope.ROPENIL] = {
tab: RefTab.Ref ← IF global THEN env.globalThingToName ELSE env.thingToName;
WITH RefTab.Fetch[tab, whatFor].val SELECT FROM
n: Rope.ROPE => RETURN [n];
ENDCASE =>NULL;
};
IdentForLocalObject: PROC [env: Environment, ob: CD.Object] RETURNS [name: Rope.ROPE] = {
first: CHAR;
name ← Ident[env, ob, FALSE];
IF name#NIL THEN RETURN [name];
name ← CDDirectory.Name[ob];
IF Rope.IsEmpty[name] THEN {
name ← Atom.GetPName[ob.class.objectType]
};
first ← Rope.Fetch[name];
IF Ascii.Letter[first] THEN first ← Ascii.Lower[first];
name ← Rope.Replace[
base: name, start: 0, len: 1,
with: Rope.FromChar[first]
];
name ← RequestIdent[env, name, ob, FALSE];
};
PosToRope: PUBLIC PROC [pos: CD.Position] RETURNS [r: Rope.ROPE] = {
RETURN [IO.PutFR["[x: %g, y: %g]",
IO.int[pos.x],
IO.int[pos.y]
]]
};
RectToRope: PUBLIC PROC [rect: CD.Rect] RETURNS [r: Rope.ROPE] = {
RETURN [IO.PutFR["[x1: %g, y1: %g, x2: %g, y2: %g]",
IO.int[rect.x1],
IO.int[rect.y1],
IO.int[rect.x2],
IO.int[rect.y2]
]]
};
LayerIdent: PUBLIC PROC [env: Environment, l: CD.Layer] RETURNS [r: Rope.ROPE] = {
IF env.declaredLayers[l]=NIL THEN {
r: Rope.ROPE;
name: Rope.ROPE ← RequestIdent[env, Atom.GetPName[CD.LayerKey[l]]];
env.declaredLayers[l] ← name;
r ← IO.PutFR["%g: CD.Layer ← CD.FetchLayer[t: tech, uniqueKey: $%g];",
IO.rope[name],
IO.atom[CD.LayerKey[l]]
];
GlobalDeclaration1[env, r];
};
RETURN [env.declaredLayers[l]]
};
LocalStatement: PUBLIC PROC [env: Environment, line: Rope.ROPE] = {
node: TiogaFileOps.Ref;
node ← TiogaFileOps.InsertAsLastChild[env.procNode];
TiogaFileOps.SetContents[node, line];
};
OrientationRope: PROC [o: CD.Orientation] RETURNS [r: Rope.ROPE] = {
RETURN [SELECT o FROM
original => "original",
mirrorX => "mirrorX",
rotate90 => "rotate90",
rotate90X => "rotate90X",
rotate180 => "rotate180",
rotate180X => "rotate180X",
rotate270 => "rotate270",
rotate270X => "rotate270X"
ENDCASE => "bad"]
};
TransformationRope: PROC [trans: CD.Transformation] RETURNS [r: Rope.ROPE] = {
r ← IO.PutFR["[[x: %g, y: %g]",
IO.int[trans.off.x],
IO.int[trans.off.y]
];
IF trans.orient#original THEN r ← Rope.Cat[r, ", ", OrientationRope[trans.orient]];
r ← Rope.Concat[r, "]"];
};
ProgramText: PROC [ob: CD.Object, design: CD.Design, env: Environment] = {
env.procName ← RequestGlobalIdent[env, CDDirectory.Name[ob], ob];
IF ~CDCells.IsCell[ob] THEN ob ← CDDirectory.Expand[ob, design, NIL].new;
IF ob#NIL AND CDCells.IsCell[ob] THEN {
is: CD.Position ← CD.InterestSize[ob];
pq: PriorityQueue.Ref ← PriorityQueue.Create[SortPred, IF is.x<is.y THEN $y ELSE $x];
ir: CD.Rect;
hasInst: BOOLFALSE;
num: INT ← 0;
r: Rope.ROPENIL;
cptr: CD.CellSpecific = NARROW[ob.specific];
childs: RefTab.Ref ← RefTab.Create[];
node: TiogaFileOps.Ref ← MakeProcedureNode[env];
EnQueueInst: CDCells.InstEnumerator = {
x: REF ← RefTab.Fetch[childs, inst.ob].val;
PriorityQueue.Insert[pq, inst];
IF x=NIL THEN {
num ← num+1;
[] ← RefTab.Store[childs, inst.ob, $first]
}
ELSE IF x=$first THEN {
r: Rope.ROPE ← IdentForLocalObject[env, inst.ob];
num ← num-1;
[] ← RefTab.Store[childs, inst.ob, $hasName];
LocalStatement[env, Rope.Cat[r, ": CD.Object;"]];
}
ELSE NULL;
};
TiogaFileOps.SetContents[node, Rope.Cat[env.procName, ": CDGenerate.GeneratorProc ="]];
env.procDecNode ← TiogaFileOps.InsertAsLastChild[env.procNode];
TiogaFileOps.SetContents[env.procDecNode, "BEGIN"];
--make declarations
[] ← CDCells.EnumerateInstances[ob, EnQueueInst];
IF num#0 THEN LocalStatement[env, "child: CD.Object;"];
LocalStatement[env, "IF design.technology#tech THEN ERROR;"];
LocalStatement[env, "ob ← CDCells.CreateEmptyCell[];"];
--make instances
FOR num: INT IN [0..PriorityQueue.Size[pq]) DO
inst: CD.Instance ← NARROW[PriorityQueue.Remove[pq]];
EachInst: PROC [inst: CD.Instance] = {
needInst: BOOLFALSE;
childName: Rope.ROPE ← "child";
trans: CD.Transformation ← inst.trans;
SELECT RefTab.Fetch[childs, inst.ob].val FROM
$hasName => {
childName ← IdentForLocalObject[env, inst.ob];
[r, needInst] ← MakeACallExpression[env, inst.ob];
r ← Rope.Cat[childName, " ← ", r, ";"];
LocalStatement[env, r];
IF needInst THEN [] ← RefTab.Store[childs, inst.ob, $hasValueMI]
ELSE [] ← RefTab.Store[childs, inst.ob, $hasValue]
};
$hasValue => {
childName ← IdentForLocalObject[env, inst.ob];
needInst ← FALSE;
};
$hasValueMI => {
childName ← IdentForLocalObject[env, inst.ob];
needInst ← TRUE;
};
ENDCASE => {
childName ← "child";
[r, needInst] ← MakeACallExpression[env, inst.ob];
r ← Rope.Cat[childName, " ← ", r, ";"];
LocalStatement[env, r];
};
IF CDProperties.GetInstanceProp[inst, $SignalName]#NIL OR CDProperties.GetInstanceProp[inst, $InstanceName]#NIL THEN needInst ← TRUE;
IF needInst THEN {
hasInst ← TRUE;
r ← Rope.Cat[
IO.PutFR["inst ← CDCells.IncludeOb[cell: ob, ob: %g, trans: %g, mode: dontResize].newInst;",
IO.rope[childName],
IO.rope[TransformationRope[trans]]
]];
}
ELSE {
r ← Rope.Cat[
IO.PutFR["[] ← CDCells.IncludeOb[cell: ob, ob: %g, trans: %g, mode: dontResize];",
IO.rope[childName],
IO.rope[TransformationRope[trans]]
]];
};
LocalStatement[env, r];
IF needInst THEN MakeInstanceStuff[env, inst];
};
EachInst[inst];
ENDLOOP;
--interest rect
ir ← CD.InterestRect[ob];
r ← Rope.Cat["CDCells.SetInterestRect[NIL, ob, ", RectToRope[ir], "];"];
LocalStatement[env, r];
--include in directory
r ← Rope.Cat["[] ← CDDirectory.Include[design: design, object: ob"];
IF cptr.name#NIL THEN
r ← Rope.Cat[r, ", alternateName: ", RopeToRope[cptr.name]];
r ← Rope.Cat[r, "];"];
LocalStatement[env, r];
LocalStatement[env, "END;"];
LocalStatement[env, ""];
IF hasInst THEN {
env.procDecNode ← TiogaFileOps.InsertNode[env.procDecNode];
TiogaFileOps.SetContents[env.procDecNode, "inst: CD.Instance;"];
};
childs ← NIL;
}
ELSE {
TerminalIO.PutRope["**could not convert to cell\n"];
ERROR ABORTED;
}
};
RopeToRope: PUBLIC PROC [r: Rope.ROPE] RETURNS [Rope.ROPE] = {
RETURN [Convert.RopeFromRope[r]];
};
AtomToRope: PUBLIC PROC [env: Environment, a: ATOM] RETURNS [Rope.ROPE] = {
r: Rope.ROPE ← Atom.GetPName[a];
leng: INT ← Rope.Length[r];
normalCase: BOOL ← leng>0;
FOR i: INT IN [0..leng) DO
c: CHAR ← Rope.Fetch[r, i];
IF ~(Ascii.Letter[c] OR Ascii.Digit[c]) THEN {normalCase←FALSE; EXIT}
ENDLOOP;
IF normalCase THEN RETURN [Rope.Cat["$", r]];
IncludeDirectory[env, "Atom"];
RETURN [ Rope.Cat["Atom.MakeAtom[", Convert.RopeFromRope[r], "]"] ];
};
MakeInstanceStuff: PROC[env: Environment, inst: CD.Instance] = {
r: Rope.ROPENIL;
HandleProp: PROC [key: ATOM] = {
val: Rope.ROPE ← CDOps.ToRope[CDProperties.GetInstanceProp[inst, key]];
IF ~Rope.IsEmpty[val] THEN {
r: Rope.ROPE ← Rope.Cat[
"CDProperties.PutInstanceProp[inst, ",
AtomToRope[env, key],
", ",
RopeToRope[val],
"];"
];
IncludeDirectory[env, "CDProperties"];
LocalStatement[env, r];
};
};
IF CDSymbolicObjects.IsSymbolicOb[inst.ob] THEN {
l: CD.Layer;
owner: ATOM;
name: Rope.ROPE ← CDSymbolicObjects.GetName[inst];
IF ~Rope.IsEmpty[name] THEN {
r ← Rope.Cat["CDSymbolicObjects.SetName[inst, ", RopeToRope[name], "];"];
LocalStatement[env, r];
};
l ← CDSymbolicObjects.GetLayer[inst];
IF l#CD.undefLayer THEN {
r ← Rope.Cat["CDSymbolicObjects.SetLayer[inst, ", LayerIdent[env, l], "];"];
LocalStatement[env, r];
};
owner ← CDSymbolicObjects.GetOwner[inst];
IF owner#NIL THEN {
r ← Rope.Cat["CDSymbolicObjects.SetOwner[inst, ", AtomToRope[env, owner], "];"];
LocalStatement[env, r];
};
}
ELSE {
HandleProp[$SignalName];
HandleProp[$InstanceName];
}
};
SortPred: PriorityQueue.SortPred = {
p1: CD.Position ← CDBasics.BaseOfRect[CDInstances.InstRectI[NARROW[x]]];
p2: CD.Position ← CDBasics.BaseOfRect[CDInstances.InstRectI[NARROW[y]]];
IF data=$y AND p1.y#p2.y THEN RETURN[p1.y<p2.y];
IF p1.x=p2.x THEN RETURN[p1.y<p2.y];
RETURN [p1.x<p2.x];
};
MakeACallExpression: PROC[env: Environment, ob: CD.Object] RETURNS [r: Rope.ROPENIL, mustHandleInstance: BOOLFALSE] = {
r ← SpecificCallExpression[env, ob];
IF Rope.IsEmpty[r] THEN {
IF ob.class.inDirectory THEN {
MakeDirGenerator[env];
r ← Rope.Cat["CDGenerate.FetchNCall[directory, design, ", RopeToRope[CDDirectory.Name[ob]], "]"];
}
ELSE IF CDAtomicObjects.IsAtomicOb[ob] THEN {
IncludeDirectory[env, "CDAtomicObjects"];
r ← "CDAtomicObjects.CreateAtomicOb[classKey: ";
r ← Rope.Cat[r, "$", CDOps.ToRope[ob.class.objectType], ", size: "];
r ← Rope.Cat[r, PosToRope[CD.InterestSize[ob]], ", "];
r ← Rope.Cat[r, "tech: tech, layer: ", LayerIdent[env, ob.layer], "]"];
}
ELSE IF CDSymbolicObjects.IsPin[ob] THEN {
IncludeDirectory[env, "CDSymbolicObjects"];
r ← IO.PutFR["CDSymbolicObjects.CreatePin[%g]", IO.rope[PosToRope[CD.InterestSize[ob]]]];
mustHandleInstance ← TRUE;
}
ELSE IF CDSymbolicObjects.IsSegment[ob] THEN {
IncludeDirectory[env, "CDSymbolicObjects"];
r ← IO.PutFR["CDSymbolicObjects.CreateSegment[length: %g, dummyWidth: %g]", IO.int[CD.InterestSize[ob].y], IO.int[CD.InterestSize[ob].x]];
mustHandleInstance ← TRUE;
}
ELSE IF CDSymbolicObjects.IsMark[ob] THEN {
IncludeDirectory[env, "CDSymbolicObjects"];
r ← IO.PutFR["CDSymbolicObjects.CreateMark[dummySize: %g]", IO.int[CD.InterestSize[ob].y]];
mustHandleInstance ← TRUE;
}
ELSE IF ob.class.wireTyped THEN {
IncludeDirectory[env, "CDRects"];
r ← "CDRects.CreateRect[size: ";
r ← Rope.Cat[r, PosToRope[CD.InterestSize[ob]]];
r ← Rope.Cat[r, ", l: ", LayerIdent[env, ob.layer], "]"];
}
ELSE {
r ← "--Unknown[]--";
IncludeDirectory[env, "CDRects"];
r ← Rope.Cat[r, "CDRects.CreateRect[size: "];
r ← Rope.Cat[r, PosToRope[CD.InterestSize[ob]]];
r ← Rope.Cat[r, ", l: CD.highLightError]"];
};
};
};
MakeProgramCommand: PROC [comm: CDSequencer.Command] = {
inst: CD.Instance = CDOps.TheInstance[comm.design, "make program text\n"];
IF inst#NIL THEN {
env: Environment ← NewEnvironment[comm.design.technology];
Reserve[env, "design"];
Reserve[env, "key"];
Reserve[env, "context"];
Reserve[env, "directory"];
Reserve[env, "imports"];
Reserve[env, "data"];
Reserve[env, "tech"];
Reserve[env, "child"];
Reserve[env, "ob"];
Reserve[env, "inst"];
IncludeDirectory[env, "CDCells"];
IncludeDirectory[env, "CDGenerate"];
IncludeDirectory[env, "CD"];
IncludeDirectory[env, "CDDirectory"];
ProgramText[inst.ob, comm.design, env];
FinishUp[env];
}
};
[] ← CDProperties.RegisterProperty[$MakeCallExpression, $chj];
CDSequencer.ImplementCommand[$MakeProgram, MakeProgramCommand,, doQueue];
TerminalIO.PutRope["make program command loaded\n"];
END.