InterpreterTool To Cedar Users Date December 9, 1983 From Paul Rovner Location PARC Subject Cedar InterpreterTool Organization CSL XEROX Release as /Indigo/Cedar/Documentation/InterpreterToolDoc.tioga Came from /Indigo/PreCedar/Documentation/InterpreterToolDoc.tioga Last edited by Paul Rovner, December 9, 1983 8:36 am Abstract This document describes the InterpreterTool for Cedar 5. The InterpreterTool is a typescript-style tool with a read/eval/print control loop at the top level, like the CommandTool. It is used primarily for debugging and testing, but it is also used for determining and occasionally changing status variables in a running system, perhaps one a world-swap or teledebug away. It provides several related facilities: parsing, evaluation and printing of Cedar expressions in the context of the running system; management of breakpoints; and interactive control of uncaught signals, breakpoints and other exceptional conditions. Top-Level Control The top-level control loop of an InterpreterTool instance is a sequence of assignment expressions. This behavior is reflected by the prompt rope, which identifies a new "&-variable" followed by "_" on each new line. Each such &-variable is used to hold the result of its right-hand side; the new &variable becomes part of the naming context of the InterpreterTool instance (see below). If the last character on the line before the CR is "!", then the level of detail of the printout is increased. Multiple !'s can be used at the end of a line to increase the level of detail even more. Special variables (&depth and &width) are available for controlling the default level of detail for printout. If the last character on the line before the CR is "?" then the assignment is performed, but the type of the expression is printed rather than its value (this is also true if the ? is followed only by !'s). Creating an instance of the tool Typing Interpreter to a CommandTool will create a new instance of the InterpreterTool with the interface records and loaded program modules of the local world as its initial "naming context." Occurrence of an exceptional condition (uncaught signal, breakpoint, etc.) will also cause creation of a new instance of the InterpreterTool to be an "event handler" for the exceptional condition. The initial naming context will be that at the point of occurrence of the exceptional condition; additional operations associated with handling "events" will be enabled. SMALL PRINT: Occurrence of an exceptional condition (uncaught signal, breakpoint, etc.) will use an existing instance of the InterpreterTool if possible. An existing instance can be used if it was the last one made "dormant" (see below) or if the exceptional condition was raised as a result of an action initiated from that instance in the same process. In the latter case the new exceptional condition will be identified as a "nested" one and the new prompt rope will get <***> prepended to it. For example, a nested "Event" will occur if a procedure that contains a breakpoint or raises a signal is invoked from an InterpreterTool. Naming Contexts The conventions for name-lookup ought to be simple. They should be consistent with the language and with the AMModel. Users should find them easy to determine, understand and utilize. The implementation of name-lookup should be efficient. At any given time, an InterpreterTool instance has a naming context, i.e. a set of (name, value) pairs with at most one binding to a given name. This is called its "current naming context." Each naming context identifies ONE of the following: 1. a local frame Names: the set of ones statically accessible by the code at the specified PC. This includes the names in the global frame of the associated procedure, but does not include names introduced by the module's DIRECTORY or IMPORTS clauses or by any OPEN clause. 2. a global frame Names: the set of ones defined at the top level of the program module: types, constants, variables, procedures. This does not include names introduced by the module's DIRECTORY or IMPORTS clauses or by any OPEN clause. 3. an interface record Names: the set of ones defined in the interface. 4. a world: either the local one or the Outload one or one teledebugging. Names: the current set of program module instances (global frames) and interface records in the world. AND the set of special (name, value) pairs described below. For example, when the current naming context identifies a global frame, names from that frame and from the set of special names are normally the only ones accessible. Special procs exist to convert an ir name or module name to its value (&ir, &gf ... see below). NOTE: The world context of the current context will be used to find any name that is prefixed with %, whether or not the current context is a world context. This is useful for naming interface records or program modules in an event handler, for example. Summary of changes from Cedar 4.4 No automatic search of local frames in the dynamic procedure-call history is performed. A global frame as the current context and a local frame as the current context are mutually exclusive options (but if a local frame is the name-lookup context then names in its global frame are accessible.) Global frames and interface records can be named simply only if the current context is for a world. Of course, &gf and &ir can be used in any context. The world context will be used for any name that is prefixed with %. Predefined Names Selected words from the language Boolean values: TRUE and FALSE TYPEs: CHARACTER, WORD, PROC ANY, INT, INTEGER, BOOL, ATOM, PROC, CARDINAL, BOOLEAN, PROCESS, CHAR, ROPE, REF, CARD &-Variables Each InterpreterTool comes with its own, private, pre-defined set of (name, value) pairs that begin with the letter "&." This set is always included in the current naming context; its bindings can be changed and extended by user actions. I'll call this set "the &-extension." The interpreter treats assignment to a name that begins with "&" as a new binding between that name and the specified value, just as it does with other assignments. The differences are that type checking is not done for assignment to &-variables and that mention of a new &-variable on the left-hand-side causes the &-extension to be changed to include the new (name, value) pair. If the &-variable is not new then the binding to its old value is replaced with the new one. This facility is used by the InterpreterTool to remember old results (e.g. &37). It can also be used (by users) to define new temporary variables in InterpreterTool instance, e.g. by interpreting a line like &temp _ proc[x] Subsequent reference by the user to &temp will yield the value of the earlier call on "proc." The pre-defined &-variables are listed below with their names and typical arguments and with the full type of their pre-defined values. <> &help["pattern"] <> <> &slf[n] set local frame as naming context SetLocalFrameAsNamingContext: PROC [n: INT _ 0]; <> <<0 => the local frame previously used as the naming context>> < the frame at the root of the stack>> < the frame at the top of the stack>> &sgf[progName] set global frame as naming context SetGlobalFrameAsNamingContext: PROC [progName: ROPE _ NIL]; < the global frame previously used as the naming context; none => error>> <> &sir[progName] set interface record as naming context SetInterfaceRecordAsNamingContext: PROC [interfaceName: ROPE _ NIL]; <> &sw[worldName] set world name as naming context SetWorldAsNamingContext: PROC [worldName: ROPE _ NIL]; <> < the world associated with this InterpTool>> <> <> &gf[progName] get global frame -- new for 5.0 GetGlobalFrame: PROC [progName: ROPE _ NIL] RETURNS[TV]; <> <> <> &ir[irName] get interface record -- new for 5.0 GetInterfaceRecord: PROC [irName: ROPE] RETURNS[TV]; <> <> <> <<&ir[SafeStorage].TrimSystemZone[]>> &fm[pattern] print modules with names matching the pattern FindMatching: PROC [ -- find program modules with matching names pattern: ROPE, world: WorldVM.World _ NIL--NIL => use local world--]; <> &type[expr] print the type of the expression GetType: PROC [expr: ROPE]; <> & --The last value assigned <> &or[addr, len] print the addressed contents in octal OctalRead: PROC [ -- print the addressed contents in octal addr: LONG CARDINAL _ 0, len: CARDINAL _ 4, width: CARDINAL _ 16, base: CARDINAL _ 8, offset: CARDINAL _ 0]; &ors[addr, len] print the contents addressed in the first bank in octal OctalReadShort: PROC [ -- ditto, but address is in the first bank (NOT the MDS) addr: CARDINAL _ 0, len: CARDINAL _ 4, width: CARDINAL _ 16, base: CARDINAL _ 8, offset: CARDINAL _ 0]; &ow[addr, word, len] write the contents of the addressed word OctalWrite: PROC [ -- write the contents of the addressed word addr: LONG CARDINAL _ 0, word: CARDINAL _ 0, len: INT _ 1]; &ows[addr, word, len] write the contents of the word addressed in the first bank OctalWriteShort: PROC [ -- ditto, but address is in the first bank (NOT the MDS) addr: CARDINAL _ 0, word: CARDINAL _ 0, len: INT _ 1]; &ar[addr, bytes] print the addressed contents as characters AsciiRead: PROC [ -- print the addressed contents as characters addr: LONG CARDINAL _ 0, bytes: NAT _ 8]; &ars[addr, bytes] print the contents addressed in the first bank as characters AsciiReadShort: PROC [ -- ditto, but address is in the first bank (NOT the MDS) addr: CARDINAL _ 0, bytes: NAT _ 8]; &orc[gf, pc, bytes] print the addressed contents as code bytes OctalReadCode: PROC [ -- print the addressed contents as code bytes gf, pc: CARDINAL, bytes: CARDINAL _ 8]; &ofc[gf, pc, ...] find an instance of the specified code byte sequence OctalFindCode: PROC [ -- find an instance of the specified code byte sequence gf: CARDINAL, pc: CARDINAL _ 0, b0, b1, b2, b3, b4 , b5, b6, b7, b8, b9: CARDINAL _ 0]; &sob[gf, pc] set octal break SetOctalBreak: PROC [gf, pc: CARDINAL]; &clob[gf, pc] clear octal break ClearOctalBreak: PROC [gf, pc: CARDINAL]; &lob[] list octal breaks ListOctalBreaks: PROC; &tlf[lf] trust as local frame <> TrustLocalFrame: PROC [lf: CARDINAL] RETURNS [TV]; &tgf[gf] trust as global frame <> TrustGlobalFrame: PROC [gf: CARDINAL] RETURNS [TV]; &plf[lf] print local frame PrintLocalFrame: PROC [lf: CARDINAL]; &pgf[gf] print global frame PrintGlobalFrame: PROC [gf: CARDINAL]; &H this InterpreterTool's handle <> &width: printing width for this interpretertool; See PrintTV &depth: printing depth for this interpretertool; See PrintTV <> &SetBreak: set break at selected source loc; any click on SetBreak <> SetBreak: PROC [h: InterpreterToolPrivate.Handle _ NIL]; &ClearBreak: clear specified break; left click on ClearBreak(s) <> <> ClearBreak: PROC[h: InterpreterToolPrivate.Handle _ NIL, breakIndex: BreakIndex _ 0]; &WalkStack: set a local frame context (eventhandler) < nFrames _ 1;>> < nFrames _ -1;>> < nFrames _ 0;>> <> < walk up to the nFrames'th caller (towards the root). nFrames negative => walk deeper to the nFrames'th callee (towards the deepest frame). nFrames = 0 => walk directly to the deepest frame.>> WalkStack: PROC[h: InterpreterToolPrivate.Handle _ NIL, nFrames: INT _ 1]; &Source: show source loc of current lf context (eventhandler); any click on Source <> Source: PROC [h: InterpreterToolPrivate.Handle _ NIL]; &ListBreaks: list all breaks; any click on ListBreaks <> ListBreaks: PROC [h: InterpreterToolPrivate.Handle _ NIL]; &ShowFrame: show the current lf context (eventhandler); any click on ShowFrame <> ShowFrame: PROC [h: InterpreterToolPrivate.Handle _ NIL]; &ClearAllBreaks: clear all breaks; right click on ClearBreak(s) <> ClearAllBreaks: PROC [h: InterpreterToolPrivate.Handle _ NIL];