A technique for generating graphical abstractions of program data ...

10 downloads 1788 Views 214KB Size Report
paper we present a logic-based technique for recovering from the loss ... structures in the elds of software visualization and algorithm animation (see. 6]). ... by a Pascal program on its concrete data structures and suggests plausible ab- .... ware technology often hard to implement, but o ers a powerful mechanism for.
A technique for generating graphical abstractions of program data structures Camil Demetrescu1 ? and Irene Finocchi2 Dipartimento di Informatica e Sistemistica, Universita di Roma \La Sapienza", Via Salaria 113, 00198 Roma, Italy, Tel. +39-6-4991-8442, [email protected] 2 Dipartimento di Scienze dell'Informazione, Universita di Roma \La Sapienza", Via Salaria 113, 00198 Roma, Italy, Tel. +39-6-4991-8308, [email protected] 1

Abstract. Representing abstract data structures in a real programming

language is a key step of algorithm implementation and often requires programmers to introduce language-dependent details irrelevant for both a high-level analysis of the code and algorithm comprehension. In this paper we present a logic-based technique for recovering from the loss of abstraction related to the implementation process in order to create intuitive high-level pictorial representations of data structures, useful for program debugging, research and educational purposes.

1 Introduction In the last few years there has been growing interest in taking advantage of visual capabilities of modern computing systems for representing through images information from several application domains. Indeed, certain e ort has been devoted to exploring the e ectiveness of pictorial representations of code and data structures in the elds of software visualization and algorithm animation (see [6]). In particular, since data structures have a natural graphical interpretation, the use of computer-generated images is extremely attractive for displaying their features, the information they contain and their temporal evolution. This seems very useful for both the debugging of programs and research and educational purposes. One of the earliest experiments in this area led to the development of the system Incense (see [5]), able to automatically generate natural graphical displays of data structures represented in a Pascal-like language directly accessing compiler's symbol table and choosing a layout for variables according to their types. The visualization of abstract data structures (e.g. digraphs and queues), as opposed to concrete ones (namely, those found in program source code), is the basic idea behind the system UWPI (see [4]), that analyzes operations performed by a Pascal program on its concrete data structures and suggests plausible abstractions for them chosen from a xed set. ?

This author was partially supported by EU ESPRIT Long Term Research Project ALCOM-IT under contract no. 20244.

High-level debugging of programs could take great advantage of visualization capabilities, yet most modern conventional debuggers are basically textoriented and rely on direct built-in displays of program variables. For example, the Metrowerks CodeWarrior debugger provides several low-level representations of numeric variables (decimal, hexadecimal etc.) and allows programmers to interact with disclosure triangles to examine structures' elds and to recursively follow pointed objects. Two fundamental criteria for evaluating systems for visualizing data structures are the level of abstraction of pictorial representations they produce and their automation. In [6] three levels of abstraction are considered:

{ direct representations, typical of debuggers, are obtained by mapping information explicitly stored in program's data structures directly onto a picture;

{ structural representations are achieved by hiding and encapsulating irrelevant details of concrete data structures;

{ synthesized representations emphasize aspects of data structures not explicitly coded in the program, but deduced from it.

Unfortunately, abstraction and automation requirements appear to con ict: systems that automatically produce visualizations usually gather shallow information from program's source code and are not able to recover the original meaning of data structures, perhaps lost during algorithm's implementation. Hence, programming the visual interpretation of data structures through additional code seems necessary in order to obtain customized structural and synthesized representations, but requires additional e ort of the programmer. In this paper we address the visualization of data structures through a programmable logic-based interpretation of their meaning. Due to the lack of space, we focus our attention on synthesized representations, that seem the most dicult to realize. The method we propose has been used in the development of the algorithm animation system Leonardo detailed in [2]. The paper is organized as follows. After describing the logic-based visualization framework that is the backbone of our approach (section 2), in sections 3 and 4 we introduce the concept of abstraction recovery and we present techniques for visualizing both indexed and linked representations of graphs and trees, easily extendable to other kinds of data structures. We conclude with some remarks about advantages and disadvantages of our approach.

2 The visualization framework In gure 1 we propose a logic-based architecture for visualizing information extracted from concrete data structures. The diagram highlights two main moments of the visualization process. The rst step consists in augmenting an underlying program with declarations about the abstract interpretation of its data structures. The second one is related to: 1) the execution of the underlying program; 2) the generation of high-level data structures from concrete ones

AAAAAAAAA AAAAAAAAA AAAAAAAAA Underlying program

Functions and procedures definitions

Program execution machine

Augmented program

Data structures definitions

Write

Read

UNDERLYING PROGRAM COMPUTATION

Predicates definitions

PROGRAMMING TIME Visualization request

Predicates computation requests

Concrete data structures

Read

Predicates interpreter

Predicates results

ABSTRACTION RECOVERY COMPUTATION

EXECUTION TIME

Visualizer High-level data structures

Rendering libraries

IMAGE RENDERING COMPUTATION

Fig. 1. Logic-based architecture for visualizing data structures according to user's declarations; 3) their visualization by means of rendering libraries, specifying objects' default retinal features and their layout. In the sequel we will assume to deal with underlying C programs and with declarations speci ed as predicates in a logic-based language called Alpha (see [3] for details). An Alpha predicate is a boolean function with \by value" or \by name" arguments, computed according to a Prolog-like backtracking mechanism that allows it to return in its \by name" parameters di erent values on sequential repeated calls. From the point of view of a user interested in programming a visualization, an augmented C program can be created by embedding in the text of a C program the de nitions of Alpha standard predicates, having a xed prede ned signature that allows them to be recognized and computed on visualizer's demand. Standard predicates are classi ed into constructors and descriptors. The rst ones concern the declaration of abstract objects (graphs, lists, queues etc.) and their sub-objects (vertices, edges, items etc.). The second ones are optional and declare objects' retinal features such as the color of vertices. Moreover, predicates' de nitions may refer to variables of the underlying program, making their output dependent on information stored in concrete data structures. From the point of view of the visualization system, the e ective generation of a picture starts by computing the standard predicates de ned by the user and by collecting their output values into high-level data structures (abstraction recovery computation). These ones are then directly accessed by the visualizer that maps them onto a graphical representation (rendering computation). The visualization process is triggered by update requests to the visualizer, generated either on user's demand or automatically. In the second case, requests may be issued either at regular intervals of time or as a consequence of dynamic modi cations to concrete data structures performed by the underlying program. The last option, supported by the tool described in [2], requires a complex software technology often hard to implement, but o ers a powerful mechanism for high-level visual debugging of programs: actually, if the consistency between images and program execution is automatically mantained, wrong actions of the program can be easily detected.

3 Abstraction recovery Identifying suitable data structures and representing them in a chosen programming language are two key steps in the design and implementation of algorithms. Unfortunately, the concrete representation of abstract data structures often requires programmers to introduce language-dependent details irrelevant for a high-level analysis of the code and causes a not desirable loss of abstraction: information about the meaning of concrete data structures and their usage does not usually appear in the code, but remains part of programmer's know-how. Nevertheless, our interest in the visualization is focused on the ability to convey essential information and to recover from this loss of abstraction. As an example, let us consider a directed graph G(V; A) concretely represented in C by means of its adjacency matrix (see [1]): struct AdjMatrix { int n; char m[100][100]; } g;

According to a usual convention, the variable g may be interpreted as an instance of a directed graph, with V = f0; : : :; g:n ? 1g  f0; : : :; 99g and A = f(x; y) 2 V 2 : g:m[x][y] 6= 0g. The following Alpha declarations translate this piece of information into a computer-usable form: Graph(Out 1); Directed(1); Node(Out N,1) For N: InRange(N,0,g.n-1); Arc(X,Y,1) If g.m[X][Y]!=0;

They declare that there is a graph with label 1, it is directed, its nodes are identi ed by the numbers in the range [0; : : :; g:n ? 1] and there is an arc (x; y) if and only if g:m[x][y] 6= 0. Observe that InRange is a prede ned Alpha predicate able to enumerate all integer values in a given range. Moreover, predicates Node and Arc refer to the variable g of the underlying program. In our framework, standard predicates are computed by an interpreter due to a sequence of requests issued by the visualizer according to a precise query algorithm. In gure 2 we give a possible fragment of a query algorithm that invokes predicates Graph, Directed, Node and Arc. Note that predicates Graph and Node are enumerative, being able, in case, to return di erent values on subsequent calls thanks to the baktracking-based computation mechanism provided by the Alpha language. This is an extremely powerful feature for compactly specifying sets of values. The visualizer uses the previous query algorithm fragment to build the highlevel data structures G, dg , Vg and Ag , 8g 2 G, containing the labels of declared graphs, their type (directed or undirected), their nodes and their arcs, respectively. Then, it may use a graph drawing algorithm to produce a geometric layout for each declared graph.

G

;

while (Graph(g)=true) do begin

G

G [ fgg

Vg

;

Ag

;

if (Directed(g)=true) then dg true else dg false while (Node(n,g)=true) do Vg

end

for all (x;y) 2 Vg  Vg if (Arc(x,y,g)=true) then Ag

Vg [ fng Ag [ f(x; y)g

Fig. 2. Query algorithm that invokes predicates Graph, Directed, Node and Arc If any of standard predicates Graph, Directed, Node or Arc has not been de ned in the augmented program, the interpreter assumes it is false by default. This choice gives the visualizer great exibility, allowing it to provide default values for any piece of information left unde ned by the user. Our approach, based on logic assertions, appears very powerful for highlighting formal properties of data structures and for conveying synthesized information into images. For example, consider the following declarations: Graph(Out 2); Node(Out N,2) For N: Node(N,1); Arc(X,Y,2) Assign S In { S=0; for (int i=0;ileft ,N) For N:PreVisit(((struct node*)R)->right,N)

Moreover Moreover ;

PreV isit returns the pointers to all items of the tree rooted in R according to a recursive scheme; thus, tree nodes can be enumerated by simply invoking it

with input parameter root. The rest of the code for visualizing the tree is given below: Tree(Out 1); Node(Out N,1) For N:PreVisit(root,N); AdjList(X,Out Y,1) Assign Y=((struct node*)X)->left Moreover Assign Y=((struct node*)X)->right ;

5 Conclusions In this paper we presented an architecture for creating intuitive high-level visualizations of concrete data structures. In particular we focused our attention on the use of logic-based techniques for recovering from the loss of abstraction related to the implementation process. Relevant features of our approach are: { freedom of representation: there are no limitations on the type of concrete data structures; { freedom of interpretation: the same variable may be interpreted in several ways, leading to di erent pictorial representations; this is achieved by uncoupling concrete data structures from high-level ones; { possibility of logic reasoning on data structures: formal properties can be easily visualized. We presented some examples concerning the visualization of graphs and trees, yet the same ideas hold for other kinds of abstract data structures, too (e.g. queues, lists, stacks etc.). We considered the temporal complexity of the abstraction recovery process, as it is a critical point when dealing with large data structures, and we showed that an accurate choice of predicates may reduce it. The reader interested in this approach can nd further information over the Internet at: http://www.dis.uniroma1.it/~demetres/Leonardo/.

References 1. Cormen, T.H., Leiserson, C.E., Rivest, R.L. (1990), Introduction to Algorithms, MIT Press, Cambridge, MA. 2. Crescenzi, P., Demetrescu, C., Finocchi, I., Petreschi, R., (1997), Leonardo: a software visualization system, Proceedings WAE'97, pp. 146-155. 3. Demetrescu, C., Finocchi, I., (1998), A general-purpose logic-based visualization framework, Proceedings WSCG'99, pp. 55-62. 4. Henry, R.R., Whaley, K.M., Forstall, B., (1990), The University of Washington Illustrating Compiler, Proceedings of the ACM SIGPLAN`90 Conference on Programming Language Design and Implementation, 223-233, New York: ACM. 5. Myers, B.A., (1983), Incense: a system for displaying data structures, Computer Graphics, 17(3): 115-125. 6. Roman, G.C., Cox, K.C., (1993), A taxonomy of program visualization systems, Computer, 26, 11-24.

Suggest Documents