Frames.mesa
Copyright Ó 1991 by Xerox Corporation. All rights reserved.
Sturgis, November 20, 1988
Sturgis, March 24, 1990 4:14:55 pm PST
Last changed by Theimer on July 16, 1989 4:46:23 pm PDT
Spreitze, August 14, 1991 8:41 am PDT
DIRECTORY
CirioTypes USING[CompilerContext, Node, Type],
Rope USING[ROPE];
Frames: CEDAR DEFINITIONS =
BEGIN
CC: TYPE = CirioTypes.CompilerContext;
Type: TYPE = CirioTypes.Type;
Node: TYPE = CirioTypes.Node;
Types
IndirectFrameTypeData: TYPE = RECORD[
enclosingContext: Type, -- an IndirectFrameType or IndirectGlobalFrameType
args: Type, -- an Indirect Record or FieldList Type
results: Type, -- an Indirect Record or FieldList Type
blocks: SEQUENCE nBlocks: CARDINAL OF Type]; -- each is an Indirect FieldListType
Identifiers will be looked up in the following order: iftd[nBlocks-1], ..., iftd[0], results, args, enclosingContext
Note: There are two substantial limitations implied by this definition. (1) we do not acknowledge the existence of opens. (2) there is no provision for the enclosing module (or is this simpley a frame) nor for items obtained through interfaces.
(1) can not be solved easily, because the symbol tables do not include information about opens. (Of course, one could parse the source file and reconstruct such information if one wanted to. Or, one could change the compiler to include such information in the symbol tables.
(2) We shall tackle in due time.
CreateIndirectFrameType: PROC[data: REF IndirectFrameTypeData, cc: CC] RETURNS[Type];
CCTypes.GetTypeRepresentation will return NIL.
IndirectGlobalFrameTypeData: TYPE = RECORD[
globalVars: Type]; -- globalVars is a record type
CreateIndirectGlobalFrameType: PROC[data: REF IndirectGlobalFrameTypeData, cc: CC] RETURNS[Type];
CCTypes.GetTypeRepresentation will return NIL.
Hypothesis (MJS, May 16, 1991): these don't need to know how to CreateIndirect, because that's done for them in RMTWFrames.
nodes
IndirectFrameData: TYPE = RECORD[
procedure: Node, -- eventually I have to decide what to do about catch phrases
enclosingContext: Node, -- an IndirectFrame or IndirectGlobalFrame
descriptor: Node, -- a Rope
args: Node, -- an Indirect FieldList
results: Node, -- an Indirect FieldList
getSourcePosition: PROC[procData: REF ANY, cc: CC] RETURNS[Node],
getCallingNode: PROC[procData: REF ANY, cc: CC] RETURNS[Node],
procData: REF ANY,
blocks: SEQUENCE nBlocks: CARDINAL OF Node]; -- each is an Indirect FieldList
CreateIndirectFrameNode: PROC[data: REF IndirectFrameData, type: Type, cc: CC] RETURNS[Node];
Frame nodes respond to the following field extractions:
&sourcePosition returns a SourcePositionNode
&procedure returns the ProcedureNode for the procedure that the frame is an instance of.
&descriptor returns the descriptor RopeNode
&caller returns an indirect frame node for caller
&enclosingContext returns an indirect frame node or globalframe node for enclosing context
Note: one can determine the source position associated with the pc of an indirectFrameNode as follows: CedarCode.ExtractFieldFromNode["&sourcePosition", indirectFrameNodeType, indirectFrameNode, cc] will return a SourcePositionNode.
IndirectGlobalFrameData: TYPE = RECORD[
descriptor: Node, -- RopeNode
globalVars: Node]; -- globalVars is a record type
CreateIndirectGlobalFrameNode: PROC[data: REF IndirectGlobalFrameData, type: Type, cc: CC] RETURNS[Node];
Indirect Global Frame nodes respond to the following field extraction
&descriptor returns the descriptor RopeNode
CreateSourcePositionNode: PROC[name: Rope.ROPE, index: INT, cc: CC] RETURNS[Node];
A SourcePositionNode accepts no operations except getNodeRepresentation. CedarCode.GetNodeRepresentation[node, cc] returns REF SourcePositionRep.
FrameAdvanceNameScope: PROC [node: Node, cc: CC] RETURNS [Node];
SourcePositionRep: TYPE = RECORD[name: Rope.ROPE, index: INT];
The following is experimental
Frames occur on stacks.
We offer the following Cedar type for a stack.
The debugger will use values of this type for obtaining frames.
Target worlds will offer procedures which, when given the equivalent of a frame pointer, return a relevant stack, whose current frame is that given by the initial frame pointer.
StackOfFrames: TYPE = REF StackOfFramesBody;
StackOfFramesBody: TYPE = RECORD[
data: REF ANY,
procs: REF StackOfFramesProcs];
StackOfFramesProcs: TYPE = RECORD[
walkStack: PROC[StackOfFrames, INT] RETURNS[Node]];
walkStack moves the currentFrame pointer, and returns a Node for the resulting curretnFrame. 0 just returns the currentFrame. +1 sets the currentFrame pointer to the caller of currentFrame. -1 sets the currentFrame pointer to the frame called by the currentFrame. One may move in units of more than 1. moves that would carry one beyond the ends of the stack leave one positioned on the appropriate end frame of the stack. (At the moment, no error is generated.)
The following is even more experimental
Stacks (and other data) occur in target worlds
TargetWorld: TYPE = REF TargetWorldBody;
TargetWorldBody: TYPE = RECORD[
twData: REF ANY,
procs: REF TargetWorldProcs];
TargetWorldProcs: TYPE = RECORD[
positions
getCodePositionFromSource: PROC[sourcePosition: Node, twData: REF ANY, cc: CC, atExit: BOOLEANFALSE] RETURNS[Node],
getSourcePositionFromCode: PROC[codePosition: Node, twData: REF ANY, cc: CC] RETURNS[Node],
If, when calling getCodePositionFromSource, atExit is true, then the codePoint is at the exit of whatever procedure contains the source position. Otherwise, the codePoint is at some (implementation dependent) convenient position preceeding (or equal to) the given source position.
In any case, several source positions may produce the same code position. Thus, one would not expect the source position obtained from a code position to agree with the source position from which the code position was obtained.
breakpoints
setBreak: PROC[codePosition: Node, twData: REF ANY, cc: CC] RETURNS[brkIndex: CARD],
listBreaks: PROC[for: PROC[brkIndex: CARD, codePosition: Node], twData: REF ANY, cc: CC],
getBrkIndexFromCodePos: PROC[codePosition: Node, twData: REF ANY, cc: CC] RETURNS[brkIndex: CARD],
brkIndex = 0 means we don't recognize it
getCodePositionFromBrkIndex: PROC[brkIndex: CARD, twData: REF ANY, cc: CC] RETURNS[Node],
clearOneBreak: PROC[brkIndex: CARD, twData: REF ANY, cc: CC],
clearAllBreaks: PROC[twData: REF ANY, cc: CC],
getBrkIndexFromBreakInfo: PROC[breakInfo: Node, twData: REF ANY, cc: CC] RETURNS[brkIndex: CARD],
brkIndex = 0 means we don't recognize it
clearBrkFromBreakInfo: PROC[breakInfo: Node, twData: REF ANY, cc: CC]
Note: these breakpoint procedures invoke ENTRY procedures. There will be a monitor deadlock if one attempts to call clearOneBreak from inside listBreaks.for. getCodePositionFromBrkIndex returns NIL if there is no corresponding break entry.
];
CreateTargetWorldNode: PROC[tw: TargetWorld, cc: CC] RETURNS[Node];
CedarCode.GetNodeRepresentation[node, cc] will return tw. We hide this information inside a Node so that CCTypes will not depend on Frames. (Because CCTypes traffics in target worlds.)
BreakPoints are installed at CodePositions. These are target world dependent nodes. One must be careful when calling target world procedures that involve code positions to be sure one is using the target world of the code position.
CreateCodePosition: PROC[info: REF ANY, cc: CC] RETURNS[Node];
CedarCode.ExtractFieldFromNode["&targetWorld", CedarCode.GetTypeOfNode[codePositionNode], codePositionNode, cc] will return the target world of the code position. CedarCode.GetNodeRepresentation[codePositionNode, cc] returns the info used to create the code position node.
When breakpoints occur, they are identified by a BreakInfo node. These are target world dependent nodes. As usual, one must be sure that the target world of the node corresponds to the target world of the break procedure that one is calling.
CreateBreakInfo: PROC[info: REF ANY, cc: CC] RETURNS[Node];
CedarCode.ExtractFieldFromNode["&targetWorld", CedarCode.GetTypeOfNode[breakInfoNode], breakInfoNode, cc] will return the target world of the breakpoint. CedarCode.GetNodeRepresentation[breakInfoNode, cc] returns the info used to create the BreakInfo node.
END..