-- Juno2TopImpl.mesa
-- August 30, 1983 12:45 pm
-- Last Edited by: Gnelson, December 10, 1983 4:41 pm
DIRECTORY Juno2Top, ParseWindow, ViewerTools, IO, Parser, ParserGen, Atom,
Lexer, Rope, Process, JunoExec, Lisp, PrettyPrint, JunoBind, JunoSolver,
JunoToCedar, ParseTable, JunoSyntax;
Juno2TopImpl: PROGRAM
IMPORTS ParseWindow, ViewerTools, IO, Parser, Lexer, JunoToCedar,
Rope, Process, JunoExec, Lisp, JunoBind, Atom, ParseTable, JunoSyntax
EXPORTS Juno2Top
= {OPEN Lisp, JB: JunoBind, JS: JunoSyntax;
ROPE: TYPE = Rope.ROPE;
defs: ParseWindow.Handle ← ParseWindow.NewHandle
[ViewerTools.MakeNewTextViewer[[file: "active.juno2", name: "active.juno2"]]];
-- because the parser generator is not very smart about unparsing, we need to adjust
-- the unparsing types of a few operators for which convention dictates a non-standard
-- format:
FixUpUnparserTypes: PROC[] = {
Fix: PROC[a: ATOM, n: INT] = {
p: ParseTable.Properties = ParseTable.Search[defs.ph.table, a, NIL];
p.unparserType ← n};
Fix[JS.comma, 7];
Fix[JS.semicolon, 7];
Fix[JS.colon, 7];
Fix[JS.leftpren, 6];
Fix[JS.leftbracket, 6]};
Parse2: PUBLIC PROC [] = {ParseWindow.ParseViewer[defs]};
al: PUBLIC JB.Alist ← JB.EmptyBinding[];
Create: PUBLIC PROC[l: LIST OF REF] =
{al ← JB.NewBind[al, Atom.MakeAtom[NARROW[l.first]], l.rest.first]};
-- defs is the window of definitions of procedures, predicates, and functions.
in: IO.STREAM;
out: IO.STREAM;
-- These two streams will be used for the interpreter's read-eval-print loop
Print2: PUBLIC PROC[l: LIST OF REF] =
{WHILE l # NIL DO Print3[l.first]; l ← l.rest ENDLOOP};
Print3: PROC[r: REF] = {
WITH r SELECT FROM
rr: REF REAL => IO.Put[out, IO.real[rr↑]];
rt: ROPE => IO.Put[out, IO.rope[rt]];
ri: REF INT => IO.Put[out, IO.int[ri↑]];
rt: REF TEXT => IO.Put[out, IO.text[rt]];
a: ATOM => IO.Put[out, IO.atom[a]];
rc: REF CHAR => IO.Put[out, IO.char[rc↑]];
rb: REF BOOL => IO.Put[out, IO.bool[rb↑]]
ENDCASE => ERROR};
interpreterParser: Parser.Handle ← Parser.NewHandle[];
-- this parser will be hooked up to the input stream in; it will
-- parse the same language as the parser within defs.
ReadEvalPrint: PUBLIC PROC[prompt: ROPE, env: JB.Alist, defs: REF] RETURNS [al: JB.Alist] =
{P: IO.BreakProc -- [char: CHAR] RETURNS [CharClass], CharClass = {break, sepr, other}
= TRUSTED {IF char = IO.CR THEN RETURN [break] ELSE RETURN [other]};
r: ROPE;
al ← env;
DO ENABLE {ABORTED => LOOP};
IO.Put[out, IO.rope["\n"], IO.rope[prompt]];
r ← IO.GetToken[in, P]; -- read a line from the interpreter window
[] ← IO.GetToken[in, P]; -- read and ignore the CR that terminated r
interpreterParser.in.in ← IO.RIS[Rope.Concat[r, " "]];
-- convert it to a stream and hook it to the parser
interpreterParser.in.eof ← FALSE;
interpreterParser.in.error ← NIL;
Lexer.Lex[interpreterParser.in];
IF interpreterParser.in.eof THEN LOOP;
Parser.Parse[interpreterParser];
IF interpreterParser.error # NIL OR ~ interpreterParser.eof THEN
{IO.Put[out, IO.rope["Syntax error"]]; LOOP};
IF interpreterParser.result = $Debug THEN SIGNAL Debug;
interpreterParser.result ← CONS[interpreterParser.result, NIL];
al ← JunoExec.Exec[Car[interpreterParser.result], al, defs];
ENDLOOP};
Debug: SIGNAL = CODE;
Foo: PROC[] = {bar: JB.Alist ← ReadEvalPrint["-> ", al, defs];};
GetProc: PROC[moduleName: ROPE, procName: ROPE]
RETURNS [p: PROC ANY RETURNS ANY] = {
success: BOOL;
[success, p] ← JunoToCedar.GetProc[[moduleName, procName]];
IF NOT success THEN ERROR};
[in, out] ← IO.CreateViewerStreams["Juno Interpreter"];
defs.grammerfilename ← "juno2.grammar";
ParseWindow.GenerateParser[defs];
FixUpUnparserTypes[];
Parse2[];
-- The above commands generate the parser. Next, extract the appropriate pieces
-- and hook them up into a parser for the interpreter window.
{lexer: Lexer.Handle ← Lexer.NewHandle[];
lexer.type ← defs.ph.in.type;
lexer.opList ← defs.ph.in.opList;
interpreterParser.in ← lexer;
interpreterParser.table ← defs.ph.table};
Create[LIST[Rope.FromRefText["Create"], NEW[PROC ANY RETURNS ANY ← Create]]];
Create[LIST[Rope.FromRefText["GetProc"],
NEW[PROC ANY RETURNS ANY ← GetProc]]];
[] ← JunoExec.Exec[$Init, al, defs];
Process.Detach[FORK Foo[]];
}.