Visualizing Program Execution
Bharat Jayaraman Charlotte M. Baltus
Department of Computer Science Department of Computer Science
SUNY at Buffalo SUNY at Buffalo
Buffalo, NY 14260 Buffalo, NY 14260
Abstract object-oriented and logic languages [3]. The significance
of this extension is that it can serve as a basis for develop-
The motivation for this work stems from the lack of good ing visualization tools for these languages.
visual tools for describing the execution of procedure-level The contour model visualization of program execution
constructs such as procedures, functions, coroutines, iter- is an example of an operational semantics for a language.
ators, methods, and processes. Our proposed solution to It differs from traditional operational semantics in that it is
this problem is an extension of an old technique called the pictorial rather than textual. Nevertheless it will be suf-
contour diagram, which was originally used to give seman- ficiently formal to give a clear and unambiguous mean-
tics for Algol-like languages. Our extensions allow the con- ing of programs. In essence, a contour diagram consists
tour diagram to be used for more modern languages, such of a set of nested boxes, or contours, where each box
as object-oriented languages, logic languages, etc. In this represents, using source-program identifiers (where possi-
paper, we explain this extended notation, and its use in vi- ble), the run-time information on the activation of some
sualizing the execution of procedural, object-oriented and procedure-level construct, i.e., the bindings for parameters
logic programs. The significance of this extension is that it and local variables, the executable instructions, and appro-
can serve as a basis for program visualization tools. priate linkage information. The nesting structure of con-
tours conveys the scoping of environments directly. We
show in this paper that contour models are very appropriate
1. Introduction for object-oriented languages because contours make very
explicit the important fact that objects are really environ-
The motivation for this work stems from the lack of good ments. To show the versatility of this approach, we also
visual tools for describing the execution of procedure-level discuss their use for another very different paradigm, logic
constructs such as procedures, functions, coroutines, iter- programming, especially the modeling of backtracking and
ators, methods, and processes. It may be noted that most partially-defined data objects (through logic variables). In
text-book descriptions of such constructs are not entirely recent work, contour models have also been applied to the
satisfactory: either they are given in terms of implemen- visualization of concurrent programs, especially Ada tasks
tation devices such as run-time stacks and pointers, which [1].
sacrifice clarity for efficiency, or else in terms of formal se- Since our emphasis is on understanding program execu-
mantics, which sacrifice clarity for precision. Furthermore, tion, we will not be concerned with compile-time issues,
these descriptions are not very suitable for a visual presen- such as type checking. We will focus on execution at the
tation. Our solution to this problem is an extension of an procedure-level, i.e., we will examine what happens when a
old technique called the contour diagram, which was orig- procedure is called, how parameters and non-locals are ac-
inally used to give semantics for Algol-like languages, i.e., cessed, etc. Not emphasized in this discussion are the de-
for scope rules, recursion, parameter transmission, etc. [4]. tails of executing assignment statements, sequencing, con-
(A very readable account of this use is in Organick et al ditional and iterative statements, as well as input/output.
[5].) The contour diagram gives a precise, high-level, and We assume the reader is familiar with various programming
visual account of the meaning of programs. The contribu- paradigms, especially object-oriented and logic program-
tion of this paper lies in showing how this notation can be ming concepts.
extended to account for more modern languages, such as The remainder of this paper is organized as follows:
Section 2 introduces the elements of the contour model and f. The superscript i is used to distinguish the different con-
shows its use for scope rules, recursive procedures, and dy- tours of f. Not shown in the figure are the internal details
namically allocated data objects. Section 3 shows how ob- of the program unit and contour. The local part of a con-
jects and inheritance in object-oriented programming can tour holds for each variable in the program unit its type and
be represented in the contour model. Section 4 considers value information; in addition, the local part holds informa-
the basic control and data objects from logic languages— tion on any procedures or functions defined in the program
backtracking and partially-defined structures. Finally, sec- unit, as well as the executable instructions of the program
tion 5 presents conclusions and areas of further work. unit. The linkage part holds information to enable proce-
dure/function return once execution within this contour has
completed. This linkage information is maintained as the
2. Contour Models: An Introduction value of the special variable rpdl, which stands for ‘return
point-dynamic link’.
To keep this paper self-contained, we first describe how We can now sketch the basic operation of a contour-
contour models work, and then discuss scope rules, recur- model based abstract machine for an Algol-like language:
sion, and dynamic data objects. Suppose that the top-level procedure is called main. Ini-
In the contour model, the effect of a procedure call is tially, a contour main1 is created by the underlying oper-
represented by a contour. A contour basically records in- ating system and control is given to the abstract machine.
formation local to a procedure definition and linkage infor- The abstract machine executes instructions of main1 in se-
mation to facilitate procedure return 1. In general, the local quence, starting at the first instruction. To keep track of its
information pertains to the identifiers declared in the proce- current instruction, the abstract machine has an instruction
dure as well as the procedure code itself. The information pointer. As variables are assigned values during execution,
about identifiers is structured as an array of entries, where the associated fields in the contour are updated. Suppose
each entry consists of an identifier name, its attribute, and that the abstract machine is about to execute the first call
its value. For example, if the identifier stands for a vari- on a procedure f. It would now construct a new contour f1
able name, then its attribute field would hold its type and its and set its rpdl field to be ‘ip in main1’, where ip is the in-
value field would hold its run-time value (if one has been struction following the call to f in main1. Exactly where a
assigned). In general there are different rules for contour newly created contour is placed relative to the calling con-
creation and deletion, but for now let us assume that a pro- tour depends upon the precise semantics of the language,
cedure call results in the creation of a contour, and the re- and we will discuss this issue in detail later. Parameters
turn from a procedure results in the deletion of the created to f are next transmitted—these details are also discussed
contour. Because recursive procedure calls are possible, later—and execution continues with the first instruction in
there could in general be several outstanding (i.e., not-yet- f1. When f1 eventually executes a return, its rpdl field is
completed) procedure calls at some point during program consulted to continue execution at ip in main1. The con-
execution. Therefore, to record the execution state of a pro- tour f1 is then deleted. Finally, when main1 reaches its
gram, in general, we must maintain multiple contours and end, the rpdl field in main1 is consulted to make the re-
link them together in some way. turn back to the system.
fi 2.1. Recursion, Scope Rules, Parameters
id attr value
Contour diagrams are particularly appropriate for under-
...
...
...
rpdl return pt. & dynamic link
standing statically-scoped languages. In these languages,
the scope of an identifier x declared in a program unit f
begin is the entire unit f and all nested units of f, except those
nested units where x is redeclared. For example, in the pro-
end f;
gram shown below, the scope of x declared in procedure
main includes procedure p1 but not procedure p2 (both
occurrences of p2), because x is redeclared inside p2. In
Figure 1. Basic Program Unit Contour. the presence of recursion, it is necessary to define the scope
of an identifier at execution time because multiple invoca-
Figure 1 shows a skeletal contour fi for some procedure tions of a procedure might coexist at execution time. This is
1 In order to model more advanced constructs such as coroutines and where the contour model is particularly helpful: The scope
backtracking, additional information would need to be maintained in the of an identifier x declared in a contour fi is the entire con-
contour. tour fi and all its nested contours, except those contours
where x is redeclared. main 1
Where exactly is a contour created? For statically- x int 2
scoped languages, the basic rule for contour creation is as y int 2
p1 proc p1.cf
follows:
p2 proc p2.cf
i rpdl system
The j-th call on a procedure h declared in contour f
results in the creation of contour hj nested inside fi .
p11
y int 0 4
We illustrate the above ideas with a program whose behav- p21
q proc p2 in main 1
ior is hard to explain without the aid of the contour model— x int y in p1 2
p2 proc p2.cf
rpdl "end"
the problem lies in the treatment of procedure parameters. rpdl "end"
We stress that this is not an example of a meaningful pro-
gram; its sole purpose is to show the value of contour dia-
grams in clarifying the meaning of static scoping. Figure 2
shows the contour model for this program at the point when p12
y int 1 2
the print statement in the outer procedure p2 is about to p2 1
q proc p2 in p1 1
be executed. x int y in p1 3
p2 proc p2.cf
rpdl "end"
rpdl "end"
procedure main
var x,y : int;
procedure p1(value y: int,
q: procedure(reference int)); p1 3
y int 2 3
procedure p2(reference x: int);
q proc p2 in p1 2
begin
p2 proc p2.cf
x := y + 2; print x; q(y);
rpdl "end"
end p2;
begin
if x==y then q(y) else p1(y+1,p2);
1
end p1; p2
x int y in p1 1
rpdl "end"
procedure p2(reference x: int);
...
begin print(x); i.p.
...
x := y + 2; print (x);
end p2;
begin
x := 2; y := x; p1(0, p2);
end main; Figure 2. Visualizing Procedural Programs.
When a procedure is passed in as the actual parame-
ter, the corresponding formal parameter is referred to as Space limitations preclude a detailed discussion of fig-
a procedure parameter, e.g., parameter q in p1. The ac- ure 2. The keys to this diagram are the bindings shown for
tual parameter matching a procedure parameter can either the parameter q in p11 , p12 , and p13. Although the pro-
be a procedure or another procedure parameter. The main cedure p2 is bound to q in each case, the associated con-
semantic issue with a procedure parameter concerns the tours are different, and this makes all the difference in the
contour—called the environment contour—in which the meaning of the program. We claim that it is very difficult to
contour for the argument procedure created. The reason convey the behavior of such programs without the contour
that the environment contour is significant is because it af- model.
fects the resolution of any non-local identifiers of the argu-
ment procedure. There are three possible choices for the 2.2. Dynamic Data Objects
environment contour: (1) the contour in which the argu-
ment procedure is declared; or (2) the contour in which Dynamically allocated data objects are drawn outside all
the argument procedure is passed as argument; or (3) the contours, in a separate area called the heap. Hence they are
contour in which the argument procedure is eventually in- also known as heap-allocated objects. These objects can be
voked. In statically-scoped languages, clearly the first thought of as data contours, i.e., they do not have any code
choice is the correct one. or linkage information. The following program fragment
serves to illustrate how data objects are represented: a construct called a class. When procedures are attached to
an object, they must be executed in the context of the object
procedure test;
in order that the fields of the object are correctly accessed.
type pair = record f1:int, f2:bool end;
type arr = dynamic array of pair;
Thus, objects are really environments. Moreover, since
var a,b: arr; these object-environments could be dynamically allocated,
begin the invocation of a procedure defined in a class must be un-
a := <[10,true], [20,false]>; derstood in a dynamically allocated object-environment.
b := a; The contour model provides a very good way of present-
... ing the execution of object-oriented programs. We illus-
end trate with a sample object-oriented (C++-like) program.
In the above program, variables a and b are bound to dy- class tree {
namically allocated objects. The act of creation can be public:
done in different ways (usually by a new operation); in the tree(int n)
above example, this is achieved implicitly by the assign- {value = n; left = right = NULL;};
ment of <[10,true], [20,false]> to a. The term procedure insert(int);
<[10,true], [20,false]> refers to an array of two // plus other procedures, e.g., print, etc.
record values, [10,true] and [20,false]. private:
int value;
For dynamically allocated data objects, the semantics
tree left;
of an assignment such as b:= a is of particular interest.
tree right;
There are two general options: assignment-by-copy and };
assignment-by-sharing. Figure 3 illustrates the difference
visually. In the case of copying, further distinctions can be // Implementation of insert
made, depending upon whether the copying is shallow or procedure tree::insert(int n)
deep. These can also be clearly portrayed using contour di- { if (value==n) return;
agrams. if (value<n)
if (right==NULL) right = new tree(n);
arr 1 else right.insert(n);
test 1 else if (left==NULL) left = new tree(n);
a arr else left.insert(n);
pair 1 pair 2
b arr }
10 true 20 false
rpdl ...
arr 2 main()
{ int choice;
tree tr;
(a) assignment-by-copy read(choice); tr = new tree(choice);
read(choice);
test 1 arr 1 while(choice != 99)
{ tr.insert(choice);
a arr
read(choice);
b arr pair 1 pair 2 }
rpdl ... 10 true 20 false }
This program defines a binary search tree (BST) abstrac-
(b) assignment-by-sharing tion and its implementation, as well as a main program that
uses the tree. Figure 4 explains how tree-insertion works;
Figure 3. Visualizing Dynamic Data Objects. in particular it clarifies precisely the meaning of procedure
calls such as right.insert(n), left.insert(n),
etc.
The contour diagram in figure 4 shows the state when the
3. Visualizing Object-Oriented Programs statement tr.insert(choice) inside the while-loop
has just completed for the first time and the inserted value
The two main concepts in object-oriented languages are is 100. Let us see how this state is reached. When the as-
abstract data types (ADTs) and inheritance. Objects are in- signment tr = new tree(choice) is executed (with
stances of ADTs, which, in OOP languages are defined by choice being set to 50), the contour tree1 is created
main 1 3.1. Representing Inheritance
tr tree *
choice int 100 In object-oriented languages, a new class may be defined
rpdl system
as a subclass of an existing class. A subclass inherits at-
...
tr.insert(choice); i.p. tributes of its ancestor classes, and may also override at-
...
tributes of its ancestor classes. Figure 5a shows a small
class hierarchy with five classes A, B, C, D, and E. Classes
tree 1 B and C are subclasses of A; D and E are subclasses of
tree constr. tree.cf B. The attributes of classes A, B, and D are shown within
insert proc. insert.cf
brackets, and are assumed to be procedures. We also as-
min func. min.cf
sume that suitable syntax has been used to indicate that at-
max func. max.cf
tribute q2 of D overrides q2 of B, while attribute p1 of B
print proc. print.cf
tree 2 shadows p1 of A. We will clarify the difference between
value int 50
tree constr. tree.cf overriding and shadowing shortly.
left tree * NULL
insert proc. insert.cf
right tree *
min func. min.cf A
insert 1 [p1,p2,p3]
11111111
00000000
00000000
11111111
n int 100
max func. max.cf
00000000
11111111
00000000
11111111
rpdl "while" print proc. print.cf
B
00000000
11111111 C
00000000
11111111
00000000
11111111
value int 100 [p1,q1,q2]
00000000
11111111 left tree * NULL
right tree * NULL
D E
[q2,r1]
(a)
Figure 4. Visualizing Object-Oriented Pro-
i
grams. A
p1
p2
p3
self
i
B
and a reference to it is assigned to tr. (The constructor p1
function tree in the above statement creates a new object- q1
environment of class tree.) The semantics for assignment q2
super
in OOP languages is by sharing. The fields in the object-
self
environment are divided into two sections, the public and D
i
the private section, in accordance with the class definition. test 1 q2
The public fields are visible to client programs and sub- d D r1
classes, but the private fields are not. This division is shown ... ... ...
super
by a double-line in the contour. self
Suppose now the statement tr.insert(choice)
inside the while-loop is executed. The contour for insert
must be created in the object-environment specified by tr.
Hence figure 4 shows the contour insert1 nested inside (b)
tree1. The input value 100 is transmitted to the value
parameter n. Since insert1 is nested inside tree1, Figure 5. Visualizing Inheritance.
the nonlocal variables value, left, and right of con-
tour insert1 are the variables declared in object tree1. How can inheritance be understood using contour mod-
Since the value to be inserted (100) is greater than the els? Since objects are environments, the environment for
value at the root of the tree (50), a reference to the new an object must reflect the visible information in all of its
object-environment tree2 is placed in variable right in parent classes as well. We do so by creating nested object-
tree1. The value field of tree2 is assigned to 100, and environment contours; thus, we simulate the basic rules of
its left and right fields to NULL. After the execution of inheritance by the normal scope rules for nested contours.
insert1 completes, its contour is deleted. Figure 5b shows these nested contours when an object of
class D is created. For example, a reference p1 in D i refers Figure 6 shows the contour diagram for the query ?-
to p1 of Bi, and a reference p3 in Di refers to p3 of Ai . gp(bob,sue) at the point when the search for the answer
Contours can visually clarify the difference between has just successfully concluded. This contour diagram em-
overriding and shadowing in some OO languges. Since q2 bodies all the information in the proof tree for this query,
in D overrides q2 in B, in the contour diagram of figure 5(b), and it also contains information to enable a more procedu-
this is shown by a dashed arrow. Suppose q1 is invoked in ral interpretation of the query.
test1 by d.q1(). The resulting contour would be allocated We briefly explain the new features of the contour dia-
inside Bi but outside Di . Suppose now that q1 calls q2. gram for logic programs. The basic idea is to create a con-
Here, the q2 refers to that in Di because q2 in Bi is over- tour for each successful unification of a goal with a clause-
ridden. On the other hand, a call such as d.p2(...) would head, and to delete this contour only if it is backtracked
result in a contour nested in Ai but outside Bi . If p2 now over. Additional fields in a contour are introduced in order
calls p1, this would refer to p1 in Ai (not Bi ), as a result of to keep track of alternative choices. In figure 6, we have
shadowing. identified the different clauses defining a predicate by sub-
Every object-environment contour has a variable called scripts. For example, p1 refers to the first clause of p, p2
self which points to the innermost object-environment to the second, etc. Similarly, p12, p22 , etc. refer to differ-
contour. Every object-environment contour except the out- ent invocations of p2. The field rpdl keeps track of the
ermost has a variable, super, which points to its immedi- return-point (code pointer) and dynamic-link (environment
ately surrounding object-environment contour. These vari- pointer), and indicates where execution should continue in
ables are called pseudo-variables because they are set once case of success. In general a contour might have two addi-
an object-environment is created, and be modified subse- tional fields:
quently. They help circumvent the normal rules of inheri-
tance. To illustrate, the reference self.q2 in Ai would re- a. To keep track of alternative choices at a backtrack
fer to q2 of Di . The reference super.q2 in Di would re- point—i.e., a contour where the invoking goal could
fer to q2 of Bi . An unqualified reference q2 in Ai would have unified with another clause-head—and also to
be undefined, and an unqualified reference q2 in Di would link together all such backtrack points, we have the
refer to the one in Di itself. The names self and super ncpb field, where the nc field has a pointer to the
are Smalltalk terminology; in C++ the variable this is the code of the next clause applicable, and pb field has
counterpart for self, but there is none for super. the previous backtrack point, if any. The pb field in-
Contour diagrams cannot directly represent multiple in- dicates where the execution should be backed up to
heritance without further extensions. The reason is that, in case of failure.
in the current scheme, a contour can be directly embedded
only inside one contour, whereas multiple inheritance re- b. To record which variables need to be reset when
quires the ability to directly embed a contour in two or more backtracking occurs, we have the reset field.
more contours. We are presently examining ways to over-
come this limitation. In order to keep the contour diagrams simple, we will
adopt the convention of not showing the ncpb field in case
the contour is not a backtrack point, and not showing the
4. Visualizing Logic Programs reset field when its contents are empty. Note that there
are two global pointers: ip, which points to the next in-
The two key aspects of the execution of practical logic struction to be executed, and mrb, which points to the con-
programming languages are backtracking and unification. tour corresponding to the most-recent backtrack point.
We illustrate these two aspects by two different examples, In general, when a failure occurs, (i) all variables re-
the first being the familiar family database example: ferred to in the reset fields of all contours created since
the most recent backtrack point (i.e., the contour pointed
f(bob, mark). f(ann, mark). to by the mrb register) are reset; (ii) all contours created
f(mark, joe). f(mary, steve). after the most recent backtrack point are deleted; (iii) the
nc field of the most recent backtrack point (say c) is con-
m(bob, mary). m(ann, mary).
sulted to find the next clause whose head is to be unified
m(mark, jane). m(mary, sue).
with the same goal that created contour c (found from c’s
p(X,Y) :- f(X,Y). rpdl field); and (iv) the nc field of contour c is updated
p(X,Y) :- m(X,Y). to point to the next clause; if there are no more clauses, the
mrb register is updated to the value of the pb field of con-
gp(X,Y) :- p(X,Z), p(Z,Y). tour c.
Now we briefly examine how the state in figure 6 is select(Y, L2, L).
reached. Basically, the query ?- gp(bob,sue) is in-
ferred as true since p(bob,mary) and p(mary,sue)
main 1
are inferred as true. And these in turn depend upon the
Answer
facts m(bob,mary) and m(mary,sue) for their proof.
rpdl system
This explains the overall structure of the contour diagram.
11
00
However, before p(bob,mary) can be inferred, Prolog’s 00
11
1 00
11
search strategy would first infer p(bob,mark) and then
p2 1
fail to find a proof for p(mark,sue). After backtrack-
ing, the contours for p11 , p12 , and p21 will be deleted. E 1
1
0
This is why the superscripts for the two instances of p2 P 0
1
L
shown in the contour diagram are 2 and 3, instead of 1 and
2, respectively. In figure 6 there is only contour (m11) at
R 1
rpdl "end"
which any alternative clauses could potentially unify with 2
the goal, and hence mrb points to m11 . 3 []
s1 1
main 1
rpdl X 1
system
L
ncpb s2 nil
gp 1 reset r in p2, 1
rpdl "perm"
X bob m.r.b.
Y sue
i.p.
Z mary
rpdl "end"
Figure 7. Representing Partially-Defined
p2 2 p2 3 Structures.
X bob X mary
Y Z in gp 1 Y sue
rpdl p(Z,Y) rpdl "end" This predicate computes in its second argument a per-
mutation of the list in the first argument. A top-level
m1 1 query ?- perm([1,2,3], Answer) is processed as
m4 1
ncpb m2 nil
m.r.b. follows: Clause p2 initially unifies with the top-level
reset Z in gp 1 rpdl "end"
query, and results in the creation of contour p21 , as shown
rpdl "end" i.p. in figure 7. Unification at this step binds L to the list
[1,2,3] and Answer to an instance of the term [E|P].
Note that E and P are still unbound. The term [E|P] can
Figure 6. Representing Backtrack Search. be represented in two ways, referred to as structure shar-
ing and structure copying respectively. We adopt the latter
approach in this presentation, as it is clearer and is also the
4.1. Partially-Defined Structures method of choice in modern Prolog systems. Shown in fig-
ure 7 is an instance of the term [E|P] created in the heap.
We now examine briefly how to represent Prolog data struc- The variables E and P in p21 are bound to these compo-
tures, especially lists, using the contour model. In Pro- nents, so that subsequent assignment to these variables (via
log, the constant [ ] stands for the empty list, and [X|L] unification) will cause these components to become instan-
stands for a list in which X is the head of the list and L is tiated.
the tail. The term [X|L] is an abbreviation for .(X, L), Figure 7 shows the state after goal select(E, R,
where . is a binary functor. L) has successfully unified with clause s1. Since X must
Consider the clauses of the perm predicate below. be bound to 1 and X also must unify with E, which is al-
p1: perm([], []). ready bound to the first component of the term just created
p2: perm(L, [E|P]) :- in the heap, this heap component now gets bound to 1. Note
select(E, R, L), perm(R, P). that unification never updates a variable; it may only cause
s1: select(X, L, [X|L]). an unbound variable to become bound. Once bound, future
s2: select(Y, [X|L2], [X|L]) :- references to a variable must use the bound value. In this
manner the binding for Answer is successively refined un- would typically be done by the course instructor for a pre-
til the first permutation is built. defined set of programs which he or she wants every student
in class to review. There are several practical issues relat-
ing to the presentation of heap data structures which must
5. Conclusions and Status be addressed in a full implementation. Here, we can make
use of recent work on analysis of heap data structures [2].
The contour model is a conceptual tool for understand-
ing program execution. Although originally proposed for
Algol-like languages [4], we have shown that it can be suc- References
cessfully adapted for object-oriented and logic program-
ming languages. We have used this extended notation in [1] L.K. Dillon. A Visual Execution Model for Ada Task-
the last five years, with good success, to explain a vari- ing. ACM Trans. on Software Engineering and Method-
ety of procedure-level constructs in programming language ology, 2(4):311–345, 1993.
courses. We have found that contours are particularly ap-
propriate for object-oriented languages because they clar- [2] R. Ghiya and L. Hendren. Is it a Tree, a DAG, or a
ify the important point that objects are really environments, Cyclic Graph? A Shape Analysis for Heap-Directed
i.e., contours. Pointers in C. Proc. 23rd ACM Symposium on Princi-
There is some similarity between the contour model and ples of Programming Languages, G. Steele (ed.), pp.
the activation-record model. Briefly, the difference is one 1–15, St. Petersburg, FL, 1996.
of clarity vs efficiency. The activation-record model is con-
cerned primarily with efficient run-time representations, [3] B. Jayaraman. Informal Semantics on Programming
and is at a lower level of abstraction compared with a con- Languages. Lecture Notes, 1995, 76 pages.
tour model. For example, in an activation-record model, [4] J.B. Johnston. The Contour Model of Block-Structured
we avoid making multiple copies of the instructions when Processes. ACM SIGPLAN Notices, 6:255–82, 1971.
procedure calls are made; we can also avoid, in many lan-
guages, storing the names of variables, etc. Such imple- [5] E. Organick, et al. Programming Language Structures,
mentation details are “abstracted away” in an operational Academic Press, 1975.
semantics, such as the contour model semantics, where the
main concern is clarity in presenting program execution. [6] B.J. MacLennan. Programming Languages: Design,
Understanding program execution using stacks of activa- Implementation and Evaluation, Holt, Rinehart, and
tion records is generally far more difficult and error-prone Winston, 1987.
than with contour diagrams. The run-time stack of activa-
tion records only conveys the calling-sequence clearly, but
the main problems in understanding higher-order functions,
functions, objects, etc. are the scoping issues. The contour
model provides a clear means of recording this information.
Although scoping issues do not arise in logic programs,
the contour diagram is helpful in that it directly reflects the
proof tree and clarifies the state of partially-defined data ob-
jects.
At the time of completion of this paper, a preliminary
prototype of a tool that helps visualize the execution sim-
ple procedural programs using contour diagrams has been
developed at SUNY-Buffalo. Our plan is to extend this tool
so as to support the more advanced features discussed in
this paper, i.e., for object-oriented and logic programming.
The typical mode in which the tool is used is to enter a pro-
gram in one of the supported languages and to request that
its execution be displayed visually as one steps through the
code. We envisage that the tool will also support a peda-
gogic mode, wherein the execution of a program can be an-
notated with (i.e., accompanied by) audio that explains the
progress of execution. Annotating a program with audio
View publication stats