A CurrCmd.T
maintains an abstract syntax tree and allows editing commands
to be performed on it. A CurrCmd.T
has no graphical representation.
A CurrCmd
is a Juno command of the form:
CurrCmd ::= VAR <variables> IN [ <constraint> -> ] <command> END (1) | <command> (2)where <variables> is a near-var list (i.e., a list of variables with optional hints), <constraint> is a Juno constraint (hence, a conjunction), and <command> is a Juno command. The two forms of a
CurrCmd
are referred
to in the rest of this interface as case (1)
and case (2)
,
respectively. The two cases are distinguished because the outer-most
command in case (2) is NOT a projection.
CurrCmd
s talk to their clients using the update
and enable
methods. update
is called when the AST is changed. enable
is
called whenever DisableClients
is called, typically when one of the
clients wishes to obtain an exclusive lock on the AST.
It is an error to make modifications to the AST contained in the
CurrCmd.T
, except through the procedures provided here.
Some of the variables in the AST are considered to be points. A point
is a variable that is declared to be either near a pair (h,v)
, where
h
and v
are both real-number constants, or near a position (x,y) REL
(p,q)
where p
and q
are identifiers representing points. CurrCmd
provides procedures for accessing and modifying the points.
A CurrCmd.T
also contains a scope, in which the current command is
compiled.
INTERFACEIfCurrCmd ; IMPORT JunoAST, Atom, JunoScope, JunoPt; IMPORT JunoValue, JunoRT; TYPE T <: TPublic; TPublic = ROOT OBJECT codeValid := FALSE; skipify: BOOLEAN; slot := -1 END; Real = JunoValue.Real;
t: T
, the boolean t.codeValid
is TRUE
iff the compiled code in the
global code table reflects t
's AST and t.skipify
. If t.codeValid
is
TRUE
, then slot
is the index of the compiled code in JunoRT.code_tbl
for the current command.
----------------- Creation / Replacement / Accessors --------------------
PROCEDURE New(ast: JunoAST.Cmd; scp: JunoScope.T := NIL): T;
Create a newCurrCmd.T
object. Ifscp
isNIL
, a new top-level scope is created. Requiresast # NIL
.
PROCEDURE GetAST(cc: T): JunoAST.Cmd; PROCEDURE ChangeAST(cc: T; ast: JunoAST.Cmd);
Respectively return the current command associated withcc
, or set the current command associated withcc
tocmd
. The latter procedure requiresast # NIL
.
Various components of the AST returned by
GetAST(cc)
may be extracted
using the following procedures:
PROCEDURE GetVariables(ast: JunoAST.Cmd): JunoAST.NearVarList;
In case (1), return the <variables> section ofast
; in case (2), return an emtpyNearVarList
.
PROCEDURE GetVariable(ast: JunoAST.T; v: JunoAST.Id): JunoAST.NearVarLink;
If the variablev
is one of the variables inGetVariables(ast)
, then return its link. Otherwise, return NIL.
PROCEDURE GetConstraint(ast: JunoAST.Cmd): JunoAST.Formula;
In case (1), return the <constraint> section ofast
, or JunoTRUE
if there isn't one; in case (2), return JunoTRUE
.
PROCEDURE GetCmd(ast: JunoAST.Cmd): JunoAST.Cmd;
Return the <command> section of ast
.
--------------------- Scope-Related Operations --------------------------
PROCEDURE GetScope(cc: T): JunoScope.T; PROCEDURE SetScope(cc: T; scp: JunoScope.T);
Observe / report cc
's top-level scope.
PROCEDURE NewDeclName(cc: T; prefix: TEXT; tryEmptySuffix := FALSE): TEXT;
Return a name of the formprefix & N
, whereN
is the smallest non-negative integer such that that name is not bound inccmd
's scope. IftryEmptySuffix
is TRUE andprefix
is not defined in the current scope, thenprefix
is returned.
--------------------------- Modification --------------------------------
PROCEDURE Skipify(ast: JunoAST.Cmd): JunoAST.Cmd;
Return a version ofast
in which the portion ofast
that would be returned byGetCmd(ast)
is replaced bySKIP
.
PROCEDURE AddVariable(cc: T; name: JunoAST.Id; loc: JunoPt.T; near: JunoAST.Expr; frozen := FALSE);
In case (1), appends a new variable to the <variables> ofcc
; in case (2), changescc
to have the form of case (1) with a single new variable. In either case, the new variable is namedname
, has valueloc
, and hintnear
. Iffrozen = TRUE
, then the new variable is asserted to be equal to its hint. Requires thatnear # NIL
and that, in case (1), <variables> does not already contain a variable namedname
.
PROCEDURE AddConstraint(cc: T; con: JunoAST.Constraint);
Conjoins the constraintcon
to the right-most disjunct of the <constraint> ofcc
. Ifcc
has no <constraint>,con
is added as a new guard of thecc
<command>.
PROCEDURE AddCommand(cc: T; cmd: JunoAST.Cmd);
Appendscmd
to the <command> ofcc
. If that <command> isSKIP
, thenSKIP
is replaced bycmd
.
PROCEDURE RemCommand(cc: T): BOOLEAN;
Destructively remove the last command from the <command> ofcc
. This procedure is a no-op if the <command> isSKIP
. If the <command> is not a sequence, then it is replaced bySKIP
. Return TRUE iff the current command was changed.
PROCEDURE DoRel(cc: T; c, a, b: JunoAST.Id);
Destructively change the hint for the pointc
in the AST. If the hint was previously of the formc ~= (x, y) REL (a, b)
, then it is changed to an absolute hint of the formc ~= (x', y')
. Otherwise, it is changed to a hint of the formc ~= (x, y) REL (a, b)
, without changing its position (unless the pointsa
andb
have the same location, in which case this procedure is a no-op). The namesc
,a
, andb
must be local variables of the current AST.
PROCEDURE DoRel1(cc: T; c, a: JunoAST.Id);
LikeDoRel
, but makesc
's hint relative to the single pointa
, that is, of the formR2.Plus(a, (x,y))
.
------------------------ Operations on Points ---------------------------
PROCEDURE PointLocation(cc: T; id: JunoAST.Id; VAR (*OUT*) h, v: Real): BOOLEAN;
Report the location of the pointid
. ReturnFALSE
if the variableid
does not exist, or is not a point; returnTRUE
otherwise.
PROCEDURE FreezePoint(cc: T; a: JunoAST.Id);
Toggle thefrozen
attribute of the point nameda
incc
.
PROCEDURE IsFrozen(cc: T; a: JunoAST.Id): BOOLEAN;
Return TRUE iffa
is the name of a frozen point incc
.
PROCEDURE MovePoint(cc: T; a: JunoAST.Id; h, v: Real);
Move the pointa
incc
to (h,v) by changing its hint. The syntactic form ofa
's hint will be preserved. A checked run-time error occurs ifa
is not one ofcc
's variables or if it does not have a hint.
TYPE PointProc = PROCEDURE(atom: Atom.T; READONLY pt: JunoPt.T); PROCEDURE ForAllPoints(cc: T; p: PointProc);
Call the procedurep
for each point. The procedurep
will be invoked with the name and absolute location of each point-valued variable named in the current commandcc
.
------------------------ Folding Operations -----------------------------
TYPE FoldKind = { Pred, Proc, ProcNoArgs }; EXCEPTION BadFoldArg(JunoAST.Id);
Indicates that the argument identifier was named as an explicit argument to the folded procedure, but no such variable exists in the current command.
PROCEDURE GetFoldArgs(cc: T): JunoAST.IdList;
Return the names of variables in the current command with no hints or with literal, point-valued hints. These are the variables that should become arguments to the folded procedure when the user has not specified any arguments explicitly.
PROCEDURE FoldByHeader(cc: T; hdr: JunoAST.PredHeader; kind := FoldKind.Proc): JunoAST.Decl RAISES {BadFoldArg};
Return a new predicate or procedure declaration namedname
corresponding to the current command. Ifkind
isPred
, then the current command's body is ignored, and a predicate definition is made; otherwise, a procedure definition is made. Ifkind
isProcNoArgs
, then the folded procedure has not arguments; all locals of the current command become locals of the folded procedure. Otherwise,hdr.ins
provides the lits of arguments to the resulting predicate or procedure, and any locals ofcc
that are not inhdr.ins
and that have absolute hints will automatically be converted to have relative hints.
PROCEDURE FoldByName(cc: T; name: JunoAST.Id; kind := FoldKind.Proc): JunoAST.Decl;
LikeFoldByHeader
, but whenkind # ProcNoArgs
, the arguments of the folded predicate or procedure are determined automatically usingGetFoldArgs
above. The parameters of the folded predicate or procedure are those locals that are either unhinted, or whose hints are literal point values.
PROCEDURE FoldAnim(cc: T; hdr: JunoAST.PredHeader; sliderPts: JunoAST.IdList): JunoAST.ProcDecl RAISES {BadFoldArg};
Produce the declaration of the current commandcc
folded as an animation with name and arguments determined fromhdr
, and slider pointssliderPts
.
PROCEDURE FoldAnimFrame(cc: T; hdr: JunoAST.PredHeader; sliderPts: JunoAST.IdList): JunoAST.ProcDecl;
Return the declaration for theFrame
procedure resulting from folding the current commandcc
as an animation with name and arguments determined fromhdr
, and slider pointssliderPts
. The name of the resulting procedure will be thehdr.name
concatenated withFrame
. If that procedure is already defined in the current command scope, then trailing digits are added as necessary to produce an unused name.
PROCEDURE FoldAnimCreator(cc: T; hdr: JunoAST.PredHeader; frameNm: JunoAST.Id): JunoAST.ProcDecl;
Return the declaration for theAnim
-creation procedure resulting from folding the current commandcc
as an animation with name and arguments determined fromhdr
. The name of the resulting procedure will be thehdr.name
concatenated withAnim
. If that procedure is already defined in the current command scope, then trailing digits are added as necessary to produce an unused name. The resulting procedure returns an animation whose closure is for the procedure namedframeNm
.
PROCEDURE FoldAnimCmd(cc: T; args: JunoAST.IdList; animProcNm: JunoAST.Id): JunoAST.Cmd;
Return the command that should become the current command when the current commandcc
is folded as an animation,animProcNm
is the name of the procedure produced byFoldAnimCreator
, andargs
is the list of fold arguments.
------------------------- Running / Updating ----------------------------
TYPE RTError = RECORD errorMsg: TEXT; execRes: JunoRT.ExecRes END;In the event of a run-time error,
errorMsg
is a descriptive error
message, and execRes
is the execution result produced by the Juno
machine.
EXCEPTION CompileError(TEXT); RuntimeError(RTError); PROCEDURE Run(cc: T; skipify: BOOLEAN): BOOLEAN RAISES {CompileError, RuntimeError};
Compile the current command in the current scope, and then execute it. Ifskipify
is TRUE, applySkipify
to the current command before compiling it. ReturnsTRUE
iff the current command was modified due to the hints of the variables being updated.Raises
CompileError
in the event of a compilation error; the argument of the exception is a descriptive error message. RaisesRuntimeError
in the event of a run-time error.
PROCEDURE UpdateHints(cc: T): BOOLEAN;
Update the hints for the variables incc
to reflect their current values in the oldest frame of the run-time stack. Requires that the indexes of the variables in that stack agree with the indexes incc
. ReturnsTRUE
iff any hints were updated.
END CurrCmd.