CDSimpleRulesImpl.mesa (part of ChipNDale)
Copyright © 1985, 1986, 1987 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, July 5, 1985 4:58:37 pm PDT
Last edited by: Christian Jacobi, April 20, 1987 7:06:20 pm PDT
DIRECTORY
Atom, CD, CDEnvironment, CDProperties, CDRects, CDSimpleRules, CDSimpleRulesBackdoor, CDValue, RefTab, Rope, SymTab;
CDSimpleRulesImpl: CEDAR MONITOR    
IMPORTS Atom, CD, CDEnvironment, CDProperties, CDRects, CDValue, RefTab, Rope, SymTab
EXPORTS CDSimpleRules, CDSimpleRulesBackdoor =
BEGIN
OPEN CDSimpleRulesBackdoor, CDSimpleRules;
NotKnown: PUBLIC ERROR = CODE;
techTables: REF TablePair ←
NEW[TablePair←[names: SymTab.Create[mod: 3, case: FALSE], keys: RefTab.Create[3]]];
rulesTable: CD.PropRef ← CD.InitPropRef[];
TablePair: TYPE = RECORD [
names: SymTab.Ref,
keys: RefTab.Ref
];
StoreInTablePair: PROC [table: REF TablePair, key: REF, data: REF] = {
[] ← RefTab.Store[table.keys, key, data];
WITH key SELECT FROM
r: Rope.ROPE => [] ← SymTab.Store[table.names, r, data];
rt: REF TEXT => [] ← SymTab.Store[table.names, Rope.FromRefText[rt], data];
a: ATOM => [] ← SymTab.Store[table.names, Atom.GetPName[a], data];
ENDCASE => NULL;
};
FindInTablePair: PROC [table: REF TablePair, hint: REF] RETURNS [data: REFNIL] = {
tryAlso: Rope.ROPENIL;
IF table=NIL THEN RETURN;
data ← RefTab.Fetch[table.keys, hint].val;
IF data=NIL THEN {
tryAlso: Rope.ROPENIL;
WITH hint SELECT FROM
r: Rope.ROPE => tryAlso ← r;
rt: REF TEXT => tryAlso ← Rope.FromRefText[rt];
ENDCASE => NULL;
IF tryAlso#NIL THEN RETURN [SymTab.Fetch[table.names, tryAlso].val]
};
};
GetRulesRep: PUBLIC PROC [rules: Rules] RETURNS [IRules] = {
WITH rules SELECT FROM
r: IRules => RETURN [r];
ENDCASE => NULL;
WITH CDProperties.GetPRefProp[rulesTable, rules] SELECT FROM
r: IRules => RETURN [r];
ENDCASE => NULL;
WITH rules SELECT FROM
a: ATOM => {
CDEnvironment.ExecFileEntry[key: Atom.GetPName[a]];
WITH CDProperties.GetPRefProp[rulesTable, a] SELECT FROM
r: IRules => RETURN [r];
ENDCASE => ERROR NotKnown;
};
ENDCASE => ERROR NotKnown;
};
InternalRules: PROC [rules: Rules, layer: CD.Layer] RETURNS [IRules] = {
WITH rules SELECT FROM
r: IRules => RETURN [r];
ENDCASE => NULL;
IF rules=NIL THEN {
tech: CD.Technology ← CD.LayerTechnology[layer];
IF tech=NIL THEN ERROR NotKnown;
RETURN [GetRulesRep[tech]]
};
WITH CDProperties.GetPRefProp[rulesTable, rules] SELECT FROM
r: IRules => RETURN [r];
ENDCASE => NULL;
WITH rules SELECT FROM
a: ATOM => {
CDEnvironment.ExecFileEntry[key: Atom.GetPName[a]];
RETURN [GetRulesRep[a]];
};
ENDCASE => ERROR NotKnown;
};
MinWidth: PUBLIC PROC [rules: Rules, layer: CD.Layer] RETURNS [CD.Number] = {
r: IRules ~ InternalRules[rules, layer];
RETURN [ IF r.minWidth=NIL THEN 0 ELSE r.minWidth[r, layer] ]
};
MaxWidth: PUBLIC PROC [rules: Rules, layer: CD.Layer] RETURNS [CD.Number] = {
r: IRules ~ InternalRules[rules, layer];
RETURN [ IF r.maxWidth=NIL THEN 0 ELSE r.maxWidth[r, layer] ]
};
MinSpace: PUBLIC PROC [rules: Rules, l1, l2: CD.Layer] RETURNS [CD.Number] = {
r: IRules ~ InternalRules[rules, l1];
RETURN [ IF r.minSpace=NIL THEN 0 ELSE r.minSpace[r, l1, l2] ]
};
GetValue: PUBLIC PROC [rules: Rules, id: ATOM] RETURNS [v: CD.Number] = {
r: IRules ~ InternalRules[rules, CD.errorLayer];
IF r.getValue=NIL THEN ERROR NotKnown;
RETURN [ r.getValue[rules, id] ];
};
GetRuleDescription: PUBLIC PROC [rules: Rules, id: ATOM] RETURNS [r: Rope.ROPENIL] = {
rul: IRules ~ InternalRules[rules, CD.errorLayer];
IF rul.getRuleDescription#NIL THEN r ← rul.getRuleDescription[rules, id];
};
GetLayer: PUBLIC PROC [technology, layer: REF] RETURNS [l: CD.Layer←CD.errorLayer] = {
tech: CD.Technology ← GetTechnology[technology];
IF tech=NIL AND technology#NIL THEN ERROR NotKnown;
WITH layer SELECT FROM
a: ATOM => {
l ← CD.FetchLayer[tech, a];
IF l#CD.errorLayer OR a=$errorLayer THEN RETURN [l];
};
rl: REF CD.Layer => RETURN [rl^];
ri: REF INT => RETURN [ri^];
ENDCASE => NULL;
WITH FindInTablePair[GetLayerReg[tech], layer] SELECT FROM
a: ATOM => RETURN [CD.FetchLayer[tech, a]];
ENDCASE => ERROR NotKnown;
};
GetLayerReg: PROC [tech: CD.Technology] RETURNS [REF TablePair] = {
WITH CDValue.Fetch[tech, techTables] SELECT FROM
tp: REF TablePair => RETURN [tp];
ENDCASE =>
[] ← CDValue.StoreConditional[tech, techTables, NEW[TablePair←[names: SymTab.Create[mod: 7, case: FALSE], keys: RefTab.Create[7]]]];
RETURN [GetLayerReg[tech]];
};
Rect: PUBLIC PROC [size: CD.Position, layer: CD.Layer] RETURNS [CD.Object] = {
RETURN [CDRects.CreateRect[size, layer]]
};
Contact: PUBLIC PROC [rules: Rules, l1, l2: CD.Layer] RETURNS [CD.Object] = {
r: IRules ~ InternalRules[rules, l1];
RETURN [ IF r.contact=NIL THEN NIL ELSE r.contact[r, l1, l2] ]
};
LargeContact: PUBLIC PROC [rules: Rules, design: CD.Design, size: CD.Position, l1, l2: CD.Layer] RETURNS [CD.Object] = {
r: IRules ~ InternalRules[rules, l1];
IF design#NIL AND design.technology#r.technology THEN ERROR;
RETURN [ IF r.largeContact=NIL THEN NIL ELSE r.largeContact[r, design, size, l1, l2] ]
};
GetTechnology: PUBLIC PROC [hint: REF] RETURNS [t: CD.Technology←NIL] = {
WITH hint SELECT FROM
tech: CD.Technology => RETURN [tech];
r: IRules => RETURN [r.technology];
ENDCASE => NULL;
t ← CDEnvironment.GetTechnology[hint];
IF t=NIL THEN {
WITH FindInTablePair[techTables, hint] SELECT FROM
t: CD.Technology => RETURN [t];
ENDCASE => NULL;
WITH CDProperties.GetPRefProp[rulesTable, hint] SELECT FROM
r: IRules => RETURN [r.technology];
ENDCASE => NULL;
WITH hint SELECT FROM
a: ATOM => {
CDEnvironment.ExecFileEntry[key: Atom.GetPName[a]];
WITH CDProperties.GetPRefProp[rulesTable, hint] SELECT FROM
r: IRules => RETURN [r.technology];
ENDCASE => NULL;
};
ENDCASE => NULL;
};
};
GetRulesKey: PUBLIC PROC [rules: Rules] RETURNS [ATOMNIL] = {
r: IRules ~ InternalRules[rules, 0];
RETURN [r.key]
};
GetRulesProp: PUBLIC PROC [rules: Rules, key: REF] RETURNS [x: REF] = {
r: IRules ← InternalRules[rules, 0];
x ← CDProperties.GetPRefProp[r.properties, key];
WHILE x=NIL AND r.inherit#NIL DO
r ← InternalRules[r.inherit, 0];
x ← CDProperties.GetPRefProp[r.properties, key];
ENDLOOP;
};
RegisterRules: PUBLIC PROC [r: RulesRep] = {
rule: IRules ←
WITH CDProperties.GetPRefProp[rulesTable, IF r.key#NIL THEN r.key ELSE r.technology] SELECT FROM
r: IRules => r,
ENDCASE => NEW[RulesRep←r];
--actual assignments
IF r.technology#NIL THEN {
IF rule.technology#NIL AND rule.technology#r.technology THEN
RETURN WITH ERROR CD.Error[calling, "tech missmatch"];
rule.technology ← r.technology;
};
IF r.minWidth#NIL THEN rule.minWidth ← r.minWidth;
IF r.minSpace#NIL THEN rule.minSpace ← r.minSpace;
IF r.maxWidth#NIL THEN rule.minSpace ← r.minSpace;
IF r.getValue#NIL THEN rule.getValue ← r.getValue;
IF r.getRuleDescription#NIL THEN rule.getRuleDescription ← r.getRuleDescription;
IF r.contact#NIL THEN rule.contact ← r.contact;
IF r.largeContact#NIL THEN rule.largeContact ← r.largeContact;
IF r.data#NIL THEN rule.data ← r.data;
--inheritance
WITH CDProperties.GetPRefProp[rulesTable, r.inherit] SELECT FROM
in: IRules => {
IF rule.technology=NIL THEN rule.technology ← in.technology;
IF rule.minWidth=NIL THEN rule.minWidth ← in.minWidth;
IF rule.minSpace=NIL THEN rule.minSpace ← in.minSpace;
IF rule.maxWidth=NIL THEN rule.maxWidth ← in.maxWidth;
IF rule.getValue=NIL THEN rule.getValue ← in.getValue;
IF rule.getRuleDescription=NIL THEN rule.getRuleDescription ← in.getRuleDescription;
IF rule.contact=NIL THEN rule.contact ← in.contact;
IF rule.largeContact=NIL THEN rule.largeContact ← in.largeContact;
};
ENDCASE => NULL;
IF rule.technology=NIL THEN ERROR CD.Error[calling, "NIL tech"];
IF rule.properties=NIL THEN rule.properties ← CD.InitPropRef[];
--registrations
IF rule.key=NIL THEN {
rule.key ← rule.technology.key;
CDProperties.PutPRefProp[rulesTable, rule.technology, rule];
--storing 2 refs is a small danger:
--to prevent errors, either stored rules are not changed (but they will), or, the technology
--registers rules with the NIL key first, before it ever uses technology.key
};
CDProperties.PutPRefProp[rulesTable, rule.key, rule];
};
RegisterLayerName: PUBLIC PROC [name: REF, layer: CD.Layer, technology: CD.Technology] = {
t: CD.Technology ← CD.LayerTechnology[layer];
IF t#NIL THEN {
IF technology#NIL AND technology#t THEN ERROR;
technology ← t;
};
StoreInTablePair[GetLayerReg[technology], name, CD.LayerKey[layer]]
};
RegisterTechnologyName: PUBLIC PROC [name: REF, technology: CD.Technology] = {
IF technology=NIL THEN ERROR;
StoreInTablePair[techTables, name, technology];
};
FetchRules: PUBLIC PROC [design: CD.Design] RETURNS [rules: ATOM] = {
x: REF ← CDProperties.GetProp[design, $DesignRules];
IF x=NIL THEN x ← design.technology;
rules ← GetRulesKey[x];
};
[] ← CDProperties.RegisterProperty[$DesignRules, $chj];
END.