BoolExGen.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Curry, August 5, 1987 9:56:31 am PDT
Last Edited by: Don Curry August 2, 1987 11:11:45 am PDT
DIRECTORY BoolEx, IO, SymTab;
BoolExGen: CEDAR PROGRAM
IMPORTS BoolEx, IO, SymTab
EXPORTS BoolEx
= BEGIN
inType:   NAT = default-2000;  -- for elementary type checking
outType:   NAT = default-1000;  -- for elementary type checking
Context:   TYPE = BoolEx.Context;
default:   NAT = BoolEx.default;
InOut:   TYPE = BoolEx.InOut;
Create: PUBLIC PROC[name: IO.ROPE] RETURNS[ctx: Context] = {
RETURN[NEW[BoolEx.ContextRec ← [
name:   name,
expr:   NIL,
logic:   LIST[NIL],
data:   LIST[NIL],
declares:  NIL,   -- Used during declarations
signals:  NIL,   -- Used after all declarations
termIndex: 0,
outTermTab: SymTab.Create[],
invTab:  SymTab.Create[] ] ] ]};
Declare: PUBLIC PROC [ctx: Context, name: IO.ROPE, io: InOut, size: NAT ← 1]
RETURNS [ix: NAT] = {
ix ← IF ctx.declares=NIL THEN 0 ELSE ctx.declares.first.index+1;
ctx.declares ← CONS[[name, io, size, ix], ctx.declares];
ix ← ix + (IF io=in THEN inType ELSE outType)};
If: PUBLIC PROC[ctx: Context, f, v: NAT, m: NAT ← default] = {
currentLogic: BoolEx.CurrentLogic ← ctx.logic.first;
IF f = default OR v = default  THEN ERROR;
IF f NOT IN [inType..outType) THEN ERROR;
currentLogic ← CONS[[f-inType, v, m], currentLogic];
ctx.logic ← CONS[currentLogic, ctx.logic];
ctx.data ← CONS[ctx.data.first, ctx.data]};
And: PUBLIC PROC[ctx: Context, f, v: NAT, m: NAT ← default] = {
currentLogic: BoolEx.CurrentLogic ← ctx.logic.first;
IF f = default OR v = default  THEN ERROR;
IF f NOT IN [inType..outType) THEN ERROR;
currentLogic ← CONS[[f-inType, v, m], currentLogic];
ctx.logic.first ← currentLogic};
AddOut: PUBLIC PROC[ctx: Context, f, v: NAT, m: NAT ← default] = {
currentData: BoolEx.CurrentData ← ctx.data.first;
IF f = default OR v = default THEN ERROR;
IF f NOT IN [outType..default) THEN ERROR;
currentData ← CONS[[f-outType, v, m], currentData];
ctx.data.first ← currentData};
EndIf: PUBLIC PROC[ctx: Context]= {
GetInv: PROC[nm: IO.ROPE] RETURNS[inv: IO.ROPE] = {
inv ← NARROW[SymTab.Fetch[ctx.invTab, nm].val];
IF inv=NIL THEN {
def:  LIST OF REF;
inv  ← IO.PutFR["NOT%g", IO.rope[nm]];
def  ← LIST[BoolEx.OpNm[not], nm];
def  ← LIST[BoolEx.OpNm[var], inv, def];
ctx.expr  ← CONS[def, ctx.expr];
[]←SymTab.Store[ctx.invTab, nm, inv]} };
def:  LIST OF REFNIL;
term:  LIST OF REFNIL;
termNm: IO.ROPEIO.PutFR["xT%03g", IO.int[ctx.termIndex]];
IF ctx.termIndex=0 THEN {
ctx.signals ← NEW [BoolEx.SignalSeqRec[ctx.declares.first.index+1]];
FOR decl: LIST OF BoolEx.Declaration ← ctx.declares, decl.rest WHILE decl#NIL DO
ctx.signals[decl.first.index] ← decl.first; ENDLOOP};
ctx.termIndex ← ctx.termIndex+1;
FOR logic: BoolEx.CurrentLogic ← ctx.logic.first, logic.rest WHILE logic#NIL DO
name:  IO.ROPE ← ctx.signals[logic.first.f].name;
size:  NAT  ← ctx.signals[logic.first.f].size;
v:   NAT  ← logic.first.v;
m:   NAT  ← logic.first.m;
IF ctx.signals[logic.first.f].io#in THEN ERROR;
IF size=1
THEN {IF (m MOD 2)=1 THEN
term ← CONS[(IF (v MOD 2)=1 THEN name ELSE GetInv[name]), term]}
ELSE FOR bit: NAT DECREASING IN [0..size) DO
bitNm: IO.ROPE ← IO.PutFR["%g%g", IO.rope[name], IO.int[bit]];
bitOne: BOOL  ← (v MOD 2)=1;
msk:  BOOL  ← (m MOD 2)=1;
v ← v/2; m ← m/2;
IF ~msk THEN LOOP;
term ← CONS[(IF bitOne THEN bitNm ELSE GetInv[bitNm]), term] ENDLOOP;
ENDLOOP;
term  ← CONS[BoolEx.OpNm[and], term];
def  ← LIST[BoolEx.OpNm[var], termNm, term];
ctx.expr  ← CONS[def, ctx.expr];
FOR data: BoolEx.CurrentData ← ctx.data.first, data.rest WHILE data#NIL DO
OrToOutput: PROC[out: IO.ROPE] = {
outTerms: LIST OF REFNARROW[SymTab.Fetch[ctx.outTermTab, out].val];
outTerms ← CONS[termNm, outTerms];
[]←SymTab.Store[ctx.outTermTab, out, outTerms]};
name: IO.ROPE  ← ctx.signals[data.first.f].name;
size: NAT   ← ctx.signals[data.first.f].size;
v:  NAT   ← data.first.v;
IF ctx.signals[data.first.f].io#out THEN ERROR;
IF size=1
THEN {IF (v MOD 2)=1 THEN OrToOutput[name]}
ELSE FOR bit: NAT DECREASING IN [0..size) DO
bitNm: IO.ROPE ← IO.PutFR["%g%g", IO.rope[name], IO.int[bit]];
bitOne: BOOL  ← (v MOD 2)=1;
v ← v/2;
IF bitOne THEN OrToOutput[bitNm] ENDLOOP;
ENDLOOP;
ctx.logic ← ctx.logic.rest;
ctx.data ← ctx.data.rest};
Finish: PUBLIC PROC[ctx: Context] RETURNS[mach: LIST OF REF] = {
OutDefs: SymTab.EachPairAction = {
def:  LIST OF REF;
outSum: LIST OF REF ← NARROW[val];
outSum ← CONS[BoolEx.OpNm[or], outSum];
def  ← LIST[BoolEx.OpNm[out], key, outSum];
ctx.expr  ← CONS[def, ctx.expr]};
[]←SymTab.Pairs[ctx.outTermTab, OutDefs];
ctx.expr ← CONS[BoolEx.OpNm[mach], CONS[ctx.name, ctx.expr]];
IF ctx.logic.rest #NIL THEN ERROR;
IF ctx.data.rest #NIL THEN ERROR;
IF ctx.logic.first #NIL THEN ERROR;
IF ctx.data.first #NIL THEN ERROR;
BoolEx.Sort[ctx.expr];
RETURN[NARROW[ctx.expr]]};
END.