-- 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[]];

}.