juno-app/src/Editor.i3


 Copyright (C) 1992, Digital Equipment Corporation                         
 All rights reserved.                                                      
 See the file COPYRIGHT for a full description.                            
                                                                           
 Last modified on Sat Mar 23 18:16:04 PST 1996 by heydon                   
      modified on Tue Feb 21 15:04:27 PST 1995 by gnelson                  
      modified on Fri Aug  7 21:51:50 PDT 1992 by myers                    
<* PRAGMA LL *>
An Editor.T is a TextPort.T containing a Juno source module together with a cache of Juno parse trees. If te is a Juno editor, then src[te] is the text contained in te and trees[te] is the cache of parse trees. An editor te is {\it valid} iff trees[te] is the sequence of parse trees of type JunoAST.Block resulting from successfully parsing src[te].

INTERFACE Editor;

IMPORT JunoAST, JunoScope;
IMPORT TextPort, VBT, Atom;
IMPORT Wr, Rd;

VAR (*CONST*)
  PointToolSym, TextToolSym, SetToolSym, ParamSym, TemplToolSym: Atom.T;

TYPE
  T <: Public;
  Public = TextPort.T OBJECT METHODS
    init(src: TEXT; readOnly := FALSE): T;
    txtModified(); <* LL.sup = VBT.mu *>
    getToolType(nm: Atom.T; VAR (*OUT*) type: Atom.T): BOOLEAN;
    getMenu(nm: Atom.T): VBT.T
  END;
NEW(T, txtModified := P).init(src, readOnly) returns a valid T containing initial source src such that P will be called whenever the text is modified. The editor is read-only iff readOnly = TRUE.

The txtModified method is called whenever the text of the editor has been modified since the last time the TextPort's modified bit was reset. The default txtModified method is a no-op.

The call ed.getToolType(nm, type) sets type to PointToolSym, TextToolSym, TemplToolSym, or SetToolSym and returns TRUE if nm is contained in one of these user interface pragmas. Otherwise, it returns FALSE.

The call ed.getMenu(nm) returns a menu of parameters associated with the procedure named nm in the editor ed. The menu contains a menu tool for each value associated with nm in a Param user-interface declaration.

TYPE
  Forest <: ForestPublic;
  ForestPublic = OBJECT
    tree: JunoAST.Block;
    next: Forest := NIL;
  END;

PROCEDURE Trees(te: T): Forest;
Return trees[te].

PROCEDURE Valid(te: T): BOOLEAN;
Return TRUE iff te is valid. After the user makes a modification to src[te], te is invalid until the next successful call to Parse.

PROCEDURE Parse(te: T; time: VBT.TimeStamp): BOOLEAN;
If src[te] is a syntactically correct Juno program, set trees[te] to make te valid and return TRUE. Otherwise, pretty-print and display an error to the user, and return FALSE.

PROCEDURE Unparse(te: T; errast: JunoAST.T := NIL;
  msg: TEXT := NIL; time: VBT.TimeStamp := 0);
<* LL.sup < te *>
Unparse trees[te] to te. Requires errast and msg are either both NIL or both non-NIL. If time # 0 and both are non-NIL, then additionally highlight the unparsed text of errast using timestamp time if it appears in one of the trees, and pop-up an error message box containing msg.

PROCEDURE AddTree(te: T; ast: JunoAST.T);
Append ast to the end of the list of trees in te, and append an unparsed version of ast to te's source. If ast is a procedure declaration for a procedure whose name has CurrCmd as a prefix, then push ast onto the editor's current command stack; if it is a UI declaration, then it must have the correct number of arguments, and any procedure it names must not currently be named in any other UI declaration in te.

PROCEDURE NextCmdNum(te: T): CARDINAL;
Return the number of the next available command on the current command stack.

PROCEDURE NextCmdName(te: T): Atom.T;
Return the name of the next available command on the current command stack.

PROCEDURE PopCurrCmd(te: T; VAR (*OUT*) nm: JunoAST.Id): JunoAST.Cmd;
<* LL.sup <= VBT.mu *>
Return the body of the procedure on the top of the current command stack, and set nm to the name of this procedure. If the body is of the form IF VAR ... IN ... END FI, then the outer IF ... FI is stripped off the result. Returns NIL if the stack is empty or if the editor is not valid. In this case, the value of nm is undefined.

PROCEDURE Width(tp: TextPort.T): CARDINAL;
Return the width in characters of tp.

PROCEDURE ModuleName(te: T): Atom.T;
If the first non-comment block of trees[te] is a JunoAST.Module, return the module name; otherwise, return NIL.

PROCEDURE Compile(
    e: T;
    time: VBT.TimeStamp;
    scp: JunoScope.T;
    VAR (*OUT*) modName: JunoAST.Id;
    VAR (*OUT*) entity: JunoScope.Mod;
    uniqueModName := TRUE): BOOLEAN;
<* LL.sup < e *>
Parses (if necessary) and compiles the contents of the editor e under the scope scp. If the compilation was successful, sets modName to the name of the module (or to NIL if there is no MODULE header), sets entity to a module entity whose public and scp scopes have parent scope scp and that contain bindings for public and all declarations, respectively, and returns TRUE. Otherwise, displays an error to the user using event-time time and returns FALSE.

If uniqueModName = TRUE, then if a module name is specified, it must not appear in scp.

This procedure does not pretty-print the contents of e or process the UI declarations in e. See Unparse and EditorUI.CompileUI.

If successful, this procedure also has a side-effect on the Juno machine: it stores compiled versions of the predicates, functions and procedures appearing in e in the global code table. It also builds associations according to the UI pragmas in e.


PROCEDURE SaveSlots(wr: Wr.T);
Write to wr the indexes of any internal JunoRT slots that are stored in the editor.

PROCEDURE RestoreSlots(rd: Rd.T);
Read from wr the indexs stored by SaveSlots, and set the internal slots to the values read.

END Editor.

Editor's implementation is in: