-- BBEval.mesa, BugBane evaluation routines
-- Russ Atkinson, December 7, 1982 11:40 am

DIRECTORY
BBContext USING [Context],
PPTree USING [Link],
Rope USING [ROPE],
RTBasic USING [nullType, TV, Type],
SymTab USING [Ref];

BBEval: CEDAR DEFINITIONS
= BEGIN OPEN BBContext, Rope, RTBasic;

Tree: TYPE = PPTree.Link;

EvalHead: TYPE = REF EvalHeadRep;
EvalHeadRep: TYPE = RECORD
[context: Context,
data: REF,
helpFatal: HelpFatal,
helpWrongType: HelpWrongType,
helpId: HelpId,
helpSelector: HelpSelector,
helpDefault: HelpDefault,
specials: SymTab.Ref,
globalContext: Context,
abortProc: AbortProc];

HelpWrongType: TYPE = PROC
[head: EvalHead, parent: Tree, value: TV, target: Type, msg: ROPE]
RETURNS [correct: RopeOrTV];
-- type of user proc called when the wrong type of TV is found
-- the user should return the correct TV (which must be OK for the target)
-- the user may also return a new error message
-- if target = nullType, then the true target may not be known
-- (this occurs for msg = "not applicable", for example)
-- if target = CODE[PROC], then some procedure should be returned

HelpId: TYPE = PROC
[head: EvalHead, parent: Tree, id: ROPE, context: Type, target: Type, msg: ROPE]
RETURNS [correct: RopeOrTV];
-- type of user proc called when the given id is not valid for the context
-- if the user returns a rope, the lookup will begin again with the new rope
-- if the user returns a TV, the lookup will return with that TV
-- if the user returns a fail, that will be the new msg for HelpFatal
-- if context = nullType, then the context is probably dynamic
-- (this may occur for msg = "undefined", for example)
-- if target = nullType, then the true target is not known

HelpSelector: TYPE = PROC
[head: EvalHead, parent: Tree, id: ROPE, context: TV, target: Type, msg: ROPE]
RETURNS [correct: RopeOrTV];
-- type of user proc called when the given id is not valid for the context
-- (note that the context is a TV)
-- if the user returns a rope, the lookup will begin again with the new rope
-- if the user returns a TV, the lookup will return with that TV
-- if the user returns a fail, that will be the new msg for HelpFatal
-- if target = nullType, then the true target is not known

HelpDefault: TYPE = PROC
[head: EvalHead, parent: Tree, type: Type, index: CARDINAL, msg: ROPE]
RETURNS [correct: RopeOrTV];
-- type of user proc called when a default value is not present
-- if index = 0, then the default is missing for type
-- if index > 0, then the default is missing for that component of type
-- the user should return a TV to be used as the default value
-- the user may also return a new error message

HelpFatal: TYPE = PROC [head: EvalHead, parent: Tree, msg: ROPE];
-- type of user proc called when a non-recoverable error is found
-- parent is the offending tree, msg describes what went wrong

AbortProc: TYPE = PROC [data: REF] RETURNS [abort: BOOL];
-- type of use procedure called to test for aborting during evaluation
-- (data comes from the eval head)
-- return TRUE to cause a call to helpFatal[head, tree, "aborted"]
-- return FALSE to proceed as normal

RopeOrTV: TYPE = RECORD
[SELECT tag: * FROM
rope => [rope: ROPE],
tv => [tv: TV],
both => [rope: ROPE, tv: TV],
fail => [fail: ROPE],
ENDCASE
] ← [fail[NIL]];

GetSymTab: PROC RETURNS [SymTab.Ref];
-- returns the global symbol table used for lookups

NewEvalHead: PROC
[context: Context,
helpFatal: HelpFatal,
helpWrongType: HelpWrongType ← NIL,
helpId: HelpId ← NIL,
helpSelector: HelpSelector ← NIL,
helpDefault: HelpDefault ← NIL,
data: REFNIL,
specials: SymTab.Ref ← NIL,
globalContext: Context ← NIL,
abortProc: AbortProc ← NIL]
RETURNS [EvalHead];
-- returns a new evaluator head
-- note that most of the help routines are optional
-- the user can supply special variables for lookup

Eval: PROC
[tree: Tree, head: EvalHead, target: Type ← nullType] RETURNS [TV];
-- evaluates the given tree using the given eval head
-- the TV returned is the return record if multiple values are returned
-- the TV is the null BBApply.TVSeq if no args are returned
-- otherwise the appropriate single TV is returned

END.