4.6 Program Graphs
4.6.1 Flow Graphs
As mentioned above, the pg of a Taal program is the starting point of its execution simulation. Basically, the pg combines two kinds of structures:
• the fasg described in Section 4.5, modelling the required elements of the concrete syntax in terms of nodes and edges representing abstract syntax elements,
• flow graphs, which model the sequential execution relation between exe- cutable statements.
Given the fasg of a Taal program, we construct the corresponding pg by applying graph production rules which add control flow information to the fasg. Traditionally [83], flow graphs are directed graphs in which every node, except for the final node (or end node), represents the execution of some program instruction. The other nodes of a flow graph are partitioned into procedure nodes and predicate nodes. The difference is that a procedure node has exactly one successor node, whereas a predicate node has multiple successors (usually two) and depending on the evaluation of some (Boolean) condition, one successor is taken.
In our approach we define flow graphs in a similar way, distinguishing pro- cedure nodes, predicate nodes, and context nodes. The context nodes serve as both start and end nodes of the flow graphs.
Definition 4.1 (flow graph). A flow graph is a directed graph consisting of
three types of nodes (also called flow elements), namely procedure, predicate and context nodes, connected by different types of successor-edges. Procedure and predicate nodes represent executable statements; the context nodes represent the start and end point of each flow graph; the successor-edges represent the se- quential relation between between statements. For every flow graph the following properties hold:
• a flow graph has exactly one context node which has one outgoing successor-
edge;
• every procedure node has exactly one outgoing successor-edge; • every predicate node has exactly two outgoing successor-edges.
A flow graph can best be understood in relation to a locus of control, which is a node of the Execution Graph (discussed in detail in Section 4.7) standing for a thread of execution. Control is said to be at a node of the flow graph. Such
Chapter 4. Semantics Through Graph Transformations
a node represents the next syntax element to be simulated and can, in compiler terminology, be compared to the instruction to which the program counter is pointing. In our formalism, the program counter will be represented by a special edge labelled pc of which the target node represents the syntax element to be simulated. In Section 4.7.2 we will further elaborate on the appearance of the program counter in our formalism. The successor-edges indicate where control should go after it leaves the current syntax element. In our approach we distinguish three different kinds of successor-edges, by using the labels flowNext, flowTrue, and flowFalse.
Every flow graph will have a single context node that serves as both its start and its end node. This yields cyclic flow graphs which is a bit unusual. This cyclic property is discussed in more detail in Section 4.7. The general structure of flow graph is depicted in Fig. 4.10. We say that every syntax element that can serve as either a procedure, predicate, or context node is a FlowElement. In the coming paragraphs, we will discuss each of the subclasses in more detail.
ContextNode PredicateNode Expression ProcedureNode FlowElement -flowTrue -flowNext -flowFalse -flowNext -condition
Figure 4.10: Flow graph meta-model.
Procedure Nodes. Procedure nodes represent statements after which it is deter- ministic which statement to execute next. The syntax elements that can serve as a procedure node are shown in Fig. 4.11. One element that seems a bit out of place here is the VarDecl-element since it is neither a Statement nor an Ex- pression. When discussing the context nodes it will become clear why we model it as a procedure node.
4.6 Program Graphs
ProcedureNode
ReturnStat ExpStat AssignStat ForkStat VarDecl
Figure 4.11: Procedure nodes.
Predicate Nodes. Statements that are represented by predicate nodes are related to a condition, which will be evaluated to either true or false. The actual value of the condition determines which branch will be taken. In this paper we only consider predicate nodes with two outgoing successor-edges: one for the case the condition is evaluated to true and one for the case the condition is false. As Fig. 4.12 shows, in Taal there are only two kinds of statements for which a conditional expression needs to be evaluated: the WhileStat and the ConditionalStat(if-then and if-then-else).
PredicateNode
ConditionalStat WhileStat
Figure 4.12: Predicate nodes.
Context Nodes. Fig. 4.13 shows what types of nodes can appear as context
nodes. In special cases, such as an ObjectType without attributes, a flow graph can exist of only the context node. In those cases, the context node still has a successor-edge, which in this case points back to the context node, making the cyclic property even clearer.
We will discuss each of the different context nodes in more detail.
Program context: Program flow graphs control the startup of the program being modelled. In TAAL, program startup is modelled by the execution
Chapter 4. Semantics Through Graph Transformations
ContextNode
Program OperImpl ObjectType
Figure 4.13: Context nodes.
of the start expression of the program. This expression may require other kinds of statements to be executed. A program’s initial expression will typically be built up from an expression which instantiates an object on which a method will then be called (this is the case in the example shown in Section 4.3). A program graph always contains exactly one flow graph at Program context.
ObjectType context: ObjectType flow graphs are traversed when an object is instantiated. Object creation will be discussed in detail in Section 4.7. Now it becomes clear why the VarDecl-element is a subclass of ProcedureN- ode: instantiating an object means that its instance variables need to be created and assigned their initial value. Instance variables declarations are represented by VarDecl-elements and therefore VarDecl-elements are part of ObjectType flow graphs. A program graph contains a ObjectType flow graph for each ObjectType being specified in the original program.
OperImpl context: OperImplflow graphs control the execution of the body of operations. The execution of an operation can be split up into a number of phases: (1) evaluating the parameters, (2) calling the operation, (3) looking up the corresponding implementation, (4) passing the actual pa- rameters, (5) instantiating the local variables and (6) executing the body. An OperImpl flow graph only takes care of the last two phases. The first and second phase are part of another flow graph in which the operation is called. The third and fourth phase will be discussed in detail in Sec- tion 4.7.3. A program graph contains a OperImpl flow graph for each operation that has been implemented in the original program, including the operations implemented in the standard library.
4.6 Program Graphs
Remark. There is one structural constraint on flow graphs as they appear in our work, that cannot be specified in the meta-model shown in Fig. 4.10. For any FlowElement, incoming flowNext-edges and incoming flowTrue-edges are mutu- ally exclusive. If a FlowElement has an incoming flowTrue-edge this means that it is part of a BlockStat which will only be executed if a particular condition evaluates to true. Since Taal does not provide plain goto statement that could enable to jump to any point in the program, as for example available in the C programming language [116], there is no other way to reach this FlowElement during simulation of the program.