GetNewPath:
PUBLIC
PROC [rootCellType: Core.CellType, newPath: Core.
ROPE, currentInstancePath: CoreClasses.CellInstances ←
NIL, currentWirePath: Core.Wires ←
NIL]
RETURNS [newInstancePath: CoreClasses.CellInstances, newWirePath: Core.Wires] = {
RemoveInstance:
PROC = {
IF newInstancePath=NIL THEN MakeError["Underflowed instance path"];
state ← instanceRemove;
newInstancePath ← newInstancePath.rest;
};
AppendNameInstance:
PROC = {
ct: Core.CellType ← Recordify[newInstancePath.first.type];
rct: CoreClasses.RecordCellType ← NARROW[ct.data];
instance: CoreClasses.CellInstance ← NIL;
IF Rope.Equal[token, "ROOT", FALSE] THEN ERROR;
state ← sawInstanceNameOrNumber;
FOR inst:
CARDINAL
IN [0..rct.size)
DO
IF Rope.Equal[token, CoreClasses.GetCellInstanceName[rct[inst]]]
THEN {
instance ← rct[inst];
EXIT;
};
REPEAT
FINISHED =>
FOR inst:
CARDINAL
IN [0..rct.size)
DO
IF Rope.Equal[token, CoreOps.GetCellTypeName[rct[inst].type]]
THEN {
IF instance#NIL THEN MakeError["Append by cell type name is ambiguous"];
instance ← rct[inst];
};
ENDLOOP;
ENDLOOP;
IF instance=NIL THEN MakeError["Can't find instance or cell type"];
newInstancePath ← CONS[instance, newInstancePath];
};
AppendNumberInstance:
PROC = {
ct: Core.CellType ← Recordify[newInstancePath.first.type];
rct: CoreClasses.RecordCellType ← NARROW[ct.data];
inst: CARDINAL ← Convert.CardFromRope[token];
state ← sawInstanceNameOrNumber;
IF inst>rct.size THEN MakeError["No such instance"];
newInstancePath ← CONS[rct[inst], newInstancePath];
};
RemoveWire:
PROC = {
IF newWirePath=NIL THEN MakeError["Underflowed wire path"];
state ← wireRemove;
newWirePath ← newWirePath.rest;
};
AppendNameWire:
PROC = {
parent: Core.Wire ← NIL;
child: Core.Wire ← NIL;
state ← sawWireNameOrNumber;
IF RootWire[]#none THEN MakeError["Cannot name a wire actual, internal, or public"];
IF newWirePath=NIL THEN MakeError["No wire root"];
parent ← newWirePath.first;
IF visitingActual
THEN {
ERROR; -- not implemented
}
ELSE {
FOR subWire:
CARDINAL
IN [0..parent.size)
DO
IF Rope.Equal[token, CoreOps.GetShortWireName[parent[subWire]]]
THEN {
child ← parent[subWire];
EXIT;
};
ENDLOOP;
IF child=NIL THEN MakeError["Can't find wire"];
newWirePath ← CONS[child, newWirePath];
};
};
AppendNumberWire:
PROC = {
subWire: CARDINAL ← Convert.CardFromRope[token];
state ← sawWireNameOrNumber;
IF newWirePath=NIL THEN MakeError["No wire root"];
IF subWire>newWirePath.first.size THEN MakeError["No such wire"];
newWirePath ← CONS[newWirePath.first[subWire], newWirePath];
};
PossibleRootWire:
PROC = {
SELECT RootWire[]
FROM
public => {
state ← sawWireRoot;
newWirePath ← IF newInstancePath=NIL THEN LIST[rootCellType.public]
ELSE LIST[newInstancePath.first.type.public];
};
internal => {
ct: Core.CellType ← Recordify[IF newInstancePath=NIL THEN rootCellType ELSE newInstancePath.first.type];
rct: CoreClasses.RecordCellType ← NARROW[ct.data];
state ← sawWireRoot;
newWirePath ← LIST[rct.internal];
};
actual => {
state ← sawWireRoot;
IF newInstancePath=NIL THEN MakeError["No instance for actual"];
newWirePath ← LIST[newInstancePath.first.actual];
visitingActual ← TRUE;
};
none => 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];
};
MakeError:
PROC [m: Core.
ROPE ←
NIL] = {
IF m=NIL THEN m ← "parse failed";
ERROR ParseError[m];
};
state: PathParseStates ← start;
visitingActual: BOOL ← TRUE;
s: IO.STREAM ← IO.RIS[newPath];
tokenKind: IO.TokenKind;
token: Core.ROPE;
newInstancePath ← currentInstancePath;
newWirePath ← currentWirePath;
DO
[tokenKind, token] ← IO.GetCedarTokenRope[s ! IO.EndOfStream => EXIT];
SELECT state
FROM
start =>
SELECT tokenKind
FROM
tokenSINGLE =>
SELECT Rope.Fetch[token]
FROM
'/ => state ← sawSlash;
'- => RemoveWire[];
ENDCASE => MakeError[];
tokenID => PossibleRootWire[];
tokenDECIMAL => AppendNumberWire[];
ENDCASE => MakeError[];
sawSlash =>
SELECT tokenKind
FROM
tokenSINGLE =>
SELECT Rope.Fetch[token]
FROM
'- => RemoveInstance[];
'. => state ← sawDot;
ENDCASE => MakeError[];
tokenID => {
state ← sawInstanceNameOrNumber;
IF Rope.Equal[token, "ROOT", FALSE] THEN newInstancePath ← NIL
ELSE AppendNameInstance[];
};
tokenDECIMAL => AppendNumberInstance[];
ENDCASE => MakeError[];
instanceRemove =>
SELECT tokenKind
FROM
tokenSINGLE =>
SELECT Rope.Fetch[token]
FROM
'- => RemoveInstance[];
'. => state ← sawDot;
ENDCASE => MakeError[];
tokenID => AppendNameInstance[];
tokenDECIMAL => AppendNumberInstance[];
ENDCASE => MakeError[];
expectInstanceNameOrNumber =>
SELECT tokenKind
FROM
tokenID => AppendNameInstance[];
tokenDECIMAL => AppendNumberInstance[];
ENDCASE => MakeError[];
sawInstanceNameOrNumber =>
SELECT tokenKind
FROM
tokenSINGLE =>
SELECT Rope.Fetch[token]
FROM
'/ => state ← expectInstanceNameOrNumber;
'. => state ← sawDot;
ENDCASE => MakeError[];
ENDCASE => MakeError[];
sawDot =>
SELECT tokenKind
FROM
tokenSINGLE =>
SELECT Rope.Fetch[token]
FROM
'- => RemoveWire[];
ENDCASE => MakeError[];
tokenID => PossibleRootWire[];
tokenDECIMAL => AppendNumberWire[];
ENDCASE => MakeError[];
sawWireRoot =>
SELECT tokenKind
FROM
tokenSINGLE =>
SELECT Rope.Fetch[token]
FROM
'. => state ← expectWireNameOrNumber;
ENDCASE => MakeError[];
ENDCASE => MakeError[];
wireRemove =>
SELECT tokenKind
FROM
tokenSINGLE =>
SELECT Rope.Fetch[token]
FROM
'- => RemoveWire[];
ENDCASE => MakeError[];
tokenID => AppendNameWire[];
tokenDECIMAL => AppendNumberWire[];
ENDCASE => MakeError[];
expectWireNameOrNumber =>
SELECT tokenKind
FROM
tokenID => AppendNameWire[];
tokenDECIMAL => {state ← sawWireNameOrNumber; AppendNumberWire[]};
ENDCASE => MakeError[];
sawWireNameOrNumber =>
SELECT tokenKind
FROM
tokenSINGLE =>
SELECT Rope.Fetch[token]
FROM
'. => state ← expectWireNameOrNumber;
ENDCASE => MakeError[];
ENDCASE => MakeError[];
ENDCASE => MakeError[];
ENDLOOP;
};