File: PWPLABasicsImpl.mesa   
Copyright Ó 1985, 1987 by Xerox Corporation. All rights reserved.
Created by: Monier, March 14, 1985 9:54:02 pm PST
Bertrand Serlet April 14, 1987 4:13:22 am PDT
DIRECTORY
Atom, CD, CDDirectory, CDExpr, CDIO,
PW,
PWPLABasics,
BoolOps, Rope, IO, FS, SymTab, TerminalIO;
PWPLABasicsImpl: CEDAR PROGRAM    
IMPORTS Atom, BoolOps, CDDirectory, CDExpr, CDIO, FS, IO, PW, Rope, TerminalIO
EXPORTS PWPLABasics
SHARES CDDirectory = BEGIN
OPEN PWPLABasics;
Error: PUBLIC ERROR[ec: ErrorCode, msg: ROPE] ~ CODE;
-- Looks for name1, name2, then name3; if absent, return NIL and screams if required
GetTile: PROC[from: CD.Design, name1, name2, name3: ROPENIL, required: BOOL] RETURNS [obj: CD.Object] =
BEGIN
obj ← SELECT TRUE FROM
IsPresent[from, name1] => PW.Get[from, name1],
IsPresent[from, name2] => PW.Get[from, name2],
IsPresent[from, name3] => PW.Get[from, name3],
ENDCASE => NIL;
IF obj = NIL AND required THEN
BEGIN
TerminalIO.PutF["PWPLA could not find tile '%g'", IO.rope[name1]];
IF name2 # NIL THEN TerminalIO.PutF[" nor '%g'", IO.rope[name2]];
IF name3 # NIL THEN TerminalIO.PutF[" nor '%g'", IO.rope[name3]];
TerminalIO.PutF[".\n'"];
ERROR Error[MissingTile, NIL];
END;
END;
IsPresent: PROC [whereTilesAre: CD.Design, name: ROPE] RETURNS [BOOL] =
{RETURN [CDDirectory.Fetch[whereTilesAre, name]#NIL]};
-- Check if all names are non-NIL
AllPresent: PUBLIC PROC [list: LIST OF CD.Object] RETURNS [b: BOOLTRUE] =
{WHILE list#NIL DO b ← b AND list.first#NIL; list ← list.rest; ENDLOOP};
RequiredTile: PUBLIC PROC [from: CD.Design, name1, name2, name3: ROPENIL] RETURNS [CD.Object] =
{RETURN[GetTile[from, name1, name2, name3, TRUE]]};
OptionalTile: PUBLIC PROC [from: CD.Design, name1, name2, name3: ROPENIL] RETURNS [CD.Object] =
{RETURN[GetTile[from, name1, name2, name3, FALSE]]};
ListRefAnyToListRope: PUBLIC PROC [list: LIST OF REF] RETURNS [LIST OF ROPE] =
BEGIN
RETURN[IF list=NIL THEN NIL ELSE CONS[NARROW[list.first], ListRefAnyToListRope[list.rest]]];
END;
ListRefAnyToListOfListRope: PUBLIC PROC [list: LIST OF REF] RETURNS [llr: LIST OF LIST OF ROPE] =
BEGIN
IF list=NIL THEN RETURN[NIL];
llr ← CONS[
ListRefAnyToListRope[NARROW[list.first, LIST OF REF]],
ListRefAnyToListOfListRope[list.rest]];
END;
Length: PUBLIC PROC [list: LIST OF ROPE] RETURNS [length: INT ← 0] =
BEGIN
WHILE list # NIL DO length ← length+1; list ← list.rest; ENDLOOP;
END;
EnsureSize: PUBLIC PROC [list: LIST OF ROPE, quantity: INT] =
{IF Length[list] # quantity THEN ERROR};
-- Read equations one at a time, converting to sum-of-products as we go
GetEQN: PUBLIC PROC[par: SymTab.Ref, inNames, outNames: LIST OF ROPE] RETURNS[BoolOps.TruthTable] =
BEGIN
tt: BoolOps.TruthTable;
inAtoms, reverseAtoms: LIST OF ATOMNIL;
eqnTrees, reversedEqnTrees: LIST OF BoolOps.Tree ← NIL;
message: ROPE;
allErrorMessages: ROPENIL;
IF inNames = NIL OR outNames = NIL THEN
ERROR Error[ParameterErrors, "Both 'Inputs' and 'Outputs' must be specified."];
-- read equations one at a time, converting to sum-of-products as we go
FOR outs: LIST OF ROPE ← outNames, outs.rest WHILE outs # NIL DO
eqn: ROPENIL;
t: BoolOps.Tree ← NIL;
eqn ← CDExpr.FetchRope[par, outs.first].val;
IF eqn = NIL THEN {
allErrorMessages ← Rope.Cat[allErrorMessages, "Equation for output '", outs.first, "' is missing.\n"];
};
FOR i: INT DECREASING IN [0 .. Rope.Length[eqn]) DO -- remove trailing semicolon
ch: CHAR ← Rope.Fetch[eqn, i];
IF ch # ' AND ch # '\t AND ch # '\n THEN {
IF ch = '; AND i > 0 THEN eqn ← Rope.Substr[eqn, 0, i];
EXIT;
};
ENDLOOP;
message ← NIL;
t ← BoolOps.RopeToTree[eqn ! BoolOps.Error => {message ← msg; CONTINUE}];
IF message # NIL THEN
allErrorMessages ← Rope.Cat[allErrorMessages, "Could not translate equation for output '", outs.first, Rope.Cat["', error was: ", message, "\n"]]
ELSE {
message ← NIL;
t ← BoolOps.TreeToSOP[t ! BoolOps.Error => {message ← msg; CONTINUE}];
IF message # NIL THEN
allErrorMessages ← Rope.Cat[allErrorMessages, "Could not translate output '", outs.first, Rope.Cat["' to sum-of-products form, error was: ", message, "\n"]]
ELSE {
reversedEqnTrees ← CONS[t, reversedEqnTrees];
};
};
ENDLOOP;
IF ~Rope.Equal[allErrorMessages, NIL] THEN ERROR Error[ParameterErrors, allErrorMessages];
-- reverse our list of equations since it is backwards
FOR trees: LIST OF BoolOps.Tree ← reversedEqnTrees, trees.rest WHILE trees # NIL DO
eqnTrees ← CONS[trees.first, eqnTrees];
ENDLOOP;
-- create a list of atoms from the input names
FOR ins: LIST OF ROPE ← inNames, ins.rest WHILE ins # NIL DO
reverseAtoms ← CONS[Atom.MakeAtom[ins.first], reverseAtoms];
ENDLOOP;
FOR ins: LIST OF ATOM ← reverseAtoms, ins.rest WHILE ins # NIL DO
inAtoms ← CONS[ins.first, inAtoms];
ENDLOOP;
-- make a truth table
message ← NIL;
tt ← BoolOps.SOPToTT[inAtoms, eqnTrees ! BoolOps.Error => {message ← msg; CONTINUE}];
IF message # NIL THEN
ERROR Error[ParameterErrors, Rope.Cat["Could not translate equations to truth table form, error was: ", message, "\n"]];
RETURN[tt];
END;
FetchTT: PUBLIC PROC [par: SymTab.Ref] RETURNS [truthTable: BoolOps.TruthTable] =
BEGIN
-- get the truth table from a file
GetTTFile: PROC[ttFile: ROPE] RETURNS[tt: BoolOps.TruthTable] =
BEGIN
ttStream: IO.STREAM;
explanation: ROPE;
IF ttFile = NIL THEN RETURN[NIL];
ttStream ← FS.StreamOpen[fileName: ttFile, wDir: CDIO.GetWorkingDirectory[] ! FS.Error => IF error.group = user THEN {ttStream ← NIL; CONTINUE}];
IF ttStream = NIL THEN
ERROR Error[ParameterErrors, Rope.Cat["Could not open truth table file '", ttFile, "'.\n"]];
tt ← BoolOps.StreamToTT[ttStream ! BoolOps.Error => {explanation ← msg; CONTINUE}];
IF explanation # NIL THEN
ERROR Error[ParameterErrors, Rope.Cat["Error in reading truth table: ", explanation, "\n"]];
END;
-- read the truth table directly from parameters file
GetTT: PROC[par: SymTab.Ref] RETURNS[BoolOps.TruthTable] = BEGIN
ref: REF ANY;
ref ← CDExpr.FetchRef[par, "TruthTable"].val;
IF ref = NIL THEN RETURN[NIL];
IF ~ISTYPE[ref, BoolOps.TruthTable] THEN ERROR Error[ParameterErrors, Rope.Cat["TruthTable option is not of type BoolOps.TruthTable!"]];
RETURN[NARROW[ref]];
END;
-- get a truth table
SELECT TRUE FROM
CDExpr.FetchRope[par, "TruthTableFile"].found =>
truthTable ← GetTTFile[CDExpr.FetchRope[par, "TruthTableFile"].val]; -- Read TruthTable from a file
CDExpr.FetchRef[par, "TruthTable"].found =>
truthTable ← GetTT[par]; -- Read TruthTable directly
ENDCASE => -- should be GetEQN[inputNames, outputNames]
truthTable ← NIL;
END;
DumpTruthTable: PUBLIC PROC [tt: BoolOps.TruthTable, ttFile: ROPE] = BEGIN
-- dump truth table to file
ttStream: IO.STREAM;
message: ROPENIL;
ttStream ← FS.StreamOpen[fileName: ttFile, wDir: CDIO.GetWorkingDirectory[], accessOptions: $create ! FS.Error => IF error.group = user THEN {ttStream ← NIL; CONTINUE}];
IF ttStream = NIL THEN ERROR Error[NoDump, Rope.Cat["Could not create truth table dump file '", ttFile, "'.\n"]];
BoolOps.TTToStream[tt, ttStream ! BoolOps.Error => {message ← msg; CONTINUE}];
IF message # NIL THEN ERROR Error[NoDump, Rope.Cat["Could not dump truth table to file '", ttFile, "', error was: ", message, "\n"]];
END;
END.