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:
REF←
NIL] = {
tryAlso: Rope.ROPE ← NIL;
IF table=NIL THEN RETURN;
data ← RefTab.Fetch[table.keys, hint].val;
IF data=
NIL
THEN {
tryAlso: Rope.ROPE ← NIL;
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] = {
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.
ROPE←
NIL] = {
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 [
ATOM←
NIL] = {
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.