Calculate.mesa
Copyright Ó 1992 by Xerox Corporation. All rights reserved.
Last edited by: Mitchell on December 16, 1982 2:32 pm
Last edited by SChen on May 1, 1984 3:53:45 pm PDT
Last edited by Bob Hagmann on May 8, 1984 8:46:31 am PDT
Last changed by Pavel on May 5, 1989 7:15:02 pm PDT
Brian Oki, May 2, 1990 11:26 am PDT
Christian Jacobi, May 14, 1992 3:00 pm PDT
DIRECTORY
Commander USING [CommandProc, Register],
IO USING [char, Error, GetChar, GetInt, int, PeekChar, PutF1, PutFR1, PutRope, Reset, SkipWhitespace, STREAM],
Process USING [Detach],
Rope USING [ROPE],
ViewerIO USING [CreateViewerStreams];
Calculate: CEDAR MONITOR     --(note 1.2)
IMPORTS Commander, IO, Process, ViewerIO =
BEGIN
ROPE: TYPE = Rope.ROPE;
windowCount: INT ¬ 0; -- a count of the number of calculators created.
MakeCalculator: ENTRY Commander.CommandProc = { --(note 1.10)
[cmd: Commander.Handle] RETURNS [result: REF ANY ← NIL, msg: ROPE ← NIL]
Puts up a calculator window.
title: ROPE;
windowCount ¬ windowCount + 1;
title ¬ IO.PutFR1["Adding Machine #%g", IO.int[windowCount]]; --(note 1.11)
TRUSTED {Process.Detach[FORK Calculate[title]];} --(note 1.12)
};
Calculate: PROC[title: ROPE] = {
Creates typescript window separate from CommandTool with given title. Uses IO procedures to read an integer expression from the typescript and print its value.
in, out: IO.STREAM;
[in: in, out: out] ¬ ViewerIO.CreateViewerStreams[title]; --(note 1.13)
DO  -- Read an expression, terminated by a CR:
ENABLE IO.Error =>     --(note 1.14)
IF ec=SyntaxError THEN {
IO.Reset[in];
IO.PutRope[out, "\nIncorrect input. Please retype the expression.\n\n"];
LOOP;
}
ELSE EXIT;
answer: INT ¬ 0;  -- initialize sum to zero.
opChar: CHAR ¬ '+;  -- first integer should be added.
IO.PutRope[out, "Type one or more integers separated by + and - and terminate with CR to compute value:\n"];
DO -- Read an operator and an integer, skipping leading blanks, eg., NUL, CR, SP, etc.
number: INT ¬ IO.GetInt[in];
SELECT opChar FROM
'+ => answer ¬ answer + number;
'- => answer ¬ answer - number;
ENDCASE => {
IO.PutF1[out, "Illegal operator (%g). Please retype the expression.\n\n", IO.char[opChar]];
EXIT;
};
IF IO.PeekChar[in]='\n THEN
GO TO NextLine; -- the normal way out.
[]¬ IO.SkipWhitespace[in];
opChar ¬ IO.GetChar[in];
REPEAT
NextLine => {
[] ¬ IO.GetChar[in]; -- toss CR (note 1.15)
IO.PutF1[out, "\nThe answer is: %g.\n\n", IO.int[answer]];
};
ENDLOOP;
ENDLOOP;
};
Start code registers a Calculate and ReverseName command, which must be invoked for this program to do anything:
Commander.Register[key: "Calculate", proc: MakeCalculator, doc: "A simple adding machine"];
END.