File: ExprReadImpl.mesa   
Copyright © 1984 by Xerox Corporation. All rights reserved.
Created by: Mayo, July 11, 1984 1:04:25 pm PDT
Last Edited by: Mayo, July 23, 1984 6:03:35 pm PDT
DIRECTORY
ExprRead,
Commander USING [CommandProc, Register],
Interpreter USING [Evaluate],
FS USING [StreamOpen, Error],
IO USING [STREAM, PutF, GetLineRope, rope, EndOfStream],
PrintTV USING [Print],
SymTab USING [Ref, Create, Pairs, Store, EachPairAction],
AMTypes USING [TV],
AMBridge USING [SomeRefFromTV, TVForROPE],
Rope USING [ROPE, SkipTo, SkipOver, Length, Substr, Fetch, Cat];
ExprReadImpl: CEDAR PROGRAM    
IMPORTS Commander, IO, FS, PrintTV, AMBridge, Interpreter, SymTab, Rope EXPORTS ExprRead = BEGIN
OPEN ExprRead;
Error: PUBLIC ERROR[ec: ErrorCode, msg: Rope.ROPE] = CODE;
whiteSpace: Rope.ROPE ← " \n\t";
Eval: PUBLIC PROC [expr: Rope.ROPE, symTab: SymTab.Ref] RETURNS [AMTypes.TV] = BEGIN
tv: AMTypes.TV;
none: BOOL;
err: Rope.ROPE;
[tv, err, none] ← Interpreter.Evaluate[rope: expr, symTab: symTab];
IF err # NIL THEN
ERROR Error[$CouldNotEval, Rope.Cat["Could not evaluate '", expr, "', error was '", err, "'."]]
ELSE IF none THEN
ERROR Error[$NoValue, Rope.Cat["Expression '", expr, "' did not return a value."]];
RETURN[tv];
END;
Assign: PUBLIC PROC [line: Rope.ROPE, symTab: SymTab.Ref] = BEGIN
var, expr: Rope.ROPE;
operatorPos: INT;
operator: CHAR;
tv: AMTypes.TV;
TrimWhite: PROC [in: Rope.ROPE] RETURNS[Rope.ROPE] = BEGIN
i, j: INT;
i ← Rope.SkipOver[in, 0, whiteSpace];
FOR j ← Rope.Length[in] - 1, j ← j - 1 WHILE j >= 0 DO
ch: CHAR ← Rope.Fetch[in, j];
IF ch # ' AND ch # '\n AND ch # '\t THEN EXIT;
ENDLOOP;
IF j < i THEN
RETURN[""]
ELSE
RETURN[Rope.Substr[in, i, j - i + 1]];
END;
operatorPos ← Rope.SkipTo[line, 0, "←~="];
IF operatorPos = Rope.Length[line] THEN
ERROR Error[$Syntax, Rope.Cat["No '←', '=', or '~' operator in '", line, "', evaluation not done."]];
operator ← Rope.Fetch[line, operatorPos];
IF operatorPos = Rope.Length[line] - 1 THEN
ERROR Error[$Syntax, Rope.Cat["Empty expression in '", line, "', assignment not done."]];
expr ← Rope.Substr[line, operatorPos + 1, Rope.Length[line] - operatorPos];
-- evaluate RHS
IF operator = '← THEN
tv ← Eval[expr, symTab]
ELSE {      
-- don't evaluate RHS, store as ROPE
expr ← TrimWhite[expr];
TRUSTED {tv ← AMBridge.TVForROPE[expr];};
};
IF operatorPos > 0 THEN BEGIN
start, end: INT;
-- parse the destination
var ← Rope.Substr[line, 0, operatorPos];
start ← Rope.SkipOver[var, 0, whiteSpace];
end ← Rope.SkipTo[var, 0, whiteSpace];
IF (end + 1 < Rope.Length[var]) AND (Rope.SkipOver[var, end + 1, whiteSpace] # Rope.Length[var]) THEN BEGIN
ERROR Error[$Syntax, Rope.Cat["Variable '", var, "' is malformed, assignment not done."]];
END
ELSE BEGIN
-- add into table
var ← Rope.Substr[var, start, end - start];
[] ← SymTab.Store[symTab, var, tv];
END;
END;
END;
ReadFile: PUBLIC PROC [fileName: Rope.ROPE, symTab: SymTab.Ref] = BEGIN
file: IO.STREAM ← NIL;
msg: Rope.ROPE ← NIL;
file ← FS.StreamOpen[fileName !FS.Error => IF error.group = user THEN {
msg ← error.explanation; CONTINUE }];
IF msg # NIL THEN ERROR Error[$FileError, msg];
DO
EOF: BOOLFALSE;
i: INT;
line: Rope.ROPE;
line ← file.GetLineRope[ ! IO.EndOfStream => {EOFTRUE; CONTINUE}];
IF EOF THEN EXIT;
i ← Rope.SkipOver[line, 0, whiteSpace];
IF i = Rope.Length[line] THEN LOOP;
IF Rope.Fetch[line, i] = '- AND i+1 < Rope.Length[line] AND Rope.Fetch[line, i+1] = '- THEN LOOP;
Assign[line, symTab];
ENDLOOP;
END;
TVToRope: PUBLIC PROC [tv: AMTypes.TV] RETURNS[Rope.ROPE] = BEGIN
ref: REF ANY;
TRUSTED {ref ← AMBridge.SomeRefFromTV[tv];};
WITH ref SELECT FROM
r: REF Rope.ROPE => RETURN[r^];
ENDCASE => RETURN[NIL];
END;
TVToListOfRope: PUBLIC PROC [tv: AMTypes.TV] RETURNS[LIST OF Rope.ROPE] = BEGIN
ref: REF ANY;
rr, rf: LIST OF Rope.ROPENIL;
TRUSTED {ref ← AMBridge.SomeRefFromTV[tv];};
WITH ref SELECT FROM
refR: REF LIST OF Rope.ROPE => RETURN[refR^];
r: LIST OF Rope.ROPE => RETURN[r];
refL: REF LIST OF REF ANY => {
FOR la: LIST OF REF ANY ← refL^, la.rest WHILE la # NIL DO
WITH la.first SELECT FROM
r: Rope.ROPE => rr ← CONS[r, rr];
ENDCASE => RETURN[NIL];
ENDLOOP;
};
l: LIST OF REF ANY => {
FOR la: LIST OF REF ANY ← l, la.rest WHILE la # NIL DO
WITH la.first SELECT FROM
r: Rope.ROPE => rr ← CONS[r, rr];
ENDCASE => RETURN[NIL];
ENDLOOP;
};
ENDCASE => RETURN[NIL];
FOR la: LIST OF Rope.ROPE ← rr, la.rest WHILE la # NIL DO
rf ← CONS[la.first, rf];
ENDLOOP;
RETURN[rf];
END;
TVToInt: PUBLIC PROC [tv: AMTypes.TV] RETURNS[REF INT] = BEGIN
ref: REF ANY;
TRUSTED {ref ← AMBridge.SomeRefFromTV[tv];};
WITH ref SELECT FROM
i: REF INT => RETURN[i];
c: REF CARDINAL => {
int: REF INTNEW[INT ← c^];
RETURN[int];
};
ENDCASE => RETURN[NIL];
END;
TVToCardinal: PUBLIC PROC [tv: AMTypes.TV] RETURNS[REF CARDINAL] = BEGIN
ref: REF ANY;
TRUSTED {ref ← AMBridge.SomeRefFromTV[tv];};
WITH ref SELECT FROM
i: REF INT => {
IF i^ < 0 THEN
RETURN[NIL]
ELSE {
card: REF CARDINALNEW[CARDINAL ← i^];
RETURN[card];
};
};
c: REF CARDINAL => RETURN[c];
ENDCASE => RETURN[NIL];
END;
TVToAtom: PUBLIC PROC [tv: AMTypes.TV] RETURNS[ATOM] = BEGIN
ref: REF ANY;
TRUSTED {ref ← AMBridge.SomeRefFromTV[tv];};
WITH ref SELECT FROM
a: REF ATOM => RETURN[a^];
ENDCASE => RETURN[NIL];
END;
Test: Commander.CommandProc = BEGIN
PrintVals: SymTab.EachPairAction = BEGIN
-- PROC [key: Key, val: Val] RETURNS [quit: BOOL]
cmd.out.PutF["%g = ", IO.rope[key]];
PrintTV.Print[NARROW[val], cmd.out];
cmd.out.PutF["\n"];
RETURN[FALSE];
END;
tab: SymTab.Ref ← SymTab.Create[];
in: Rope.ROPE;
cmd.out.PutF["FileName? "];
in ← cmd.in.GetLineRope[];
ReadFile[in, tab];
cmd.out.PutF["--- VARIABLES SET ---\n"];
[] ← SymTab.Pairs[tab, PrintVals];
END;
Commander.Register[key: "ExprReadImplTest", proc: Test, doc: "test program"];
END.