Sequence Traces for Object-Oriented Executions

Researchers have developed a large variety of semantic models of object-oriented computations. These include object calculi as well as denotational, small-step operational, big-step operational, and reduction semantics. Some focus on pure object-oriented computation in small calculi; many others mingle the object-oriented and the procedural aspects of programming languages. In this paper, we present a novel, two-level framework of objectoriented computation. The upper level of the framework borrows elements from UML’s sequence diagrams to express the message exchanges among objects. The lower level is a parameter of the upper level; it represents all those elements of a programming language that are not object-oriented. We show that the framework is a good foundation for both generic theoretical results and practical tools, such as object-oriented tracing debuggers. 1. Models of Execution Some 30 years ago, Hewitt [22, 23] introduced the ACTOR model of computation, which is arguably the first model of object-oriented computation. Since then, people have explored a range of mathematical models of object-oriented program execution: denotational semantics of objects and classes [7, 8, 25, 33], object calculi [1], small step and big step operational semantics [10], reduction semantics [16], formal variants of ACTOR [2], and others [4, 20]. While all of these semantic models have made significant contributions to the community’s understanding of object-oriented languages, they share two flaws. First, consider theoretical results such as type soundness. For ClassicJava, the type soundness proof uses Wright and Felleisen’s standard technique of ensuring that type information is preserved while the computation makes progress. If someone extends ClassicJava with constructs such as while loops or switch statements, it is necessary to re-prove everything even though the extension did not affect the object-oriented aspects of the model. Second, none of these models are good starting points for creating practical tools. Some models focus on pure core objectoriented languages; others are models of real-world languages but mingle the semantics of object-oriented constructs (e.g., method invocations) with those of procedural or applicative nature (internal blocks or while loops). If a programmer wishes to debug the object-oriented actions in a Java program, a tracer based on any of these semantics would display too much procedural information. Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. To copy otherwise, to republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. Figure 1. Graphical sequence trace. In short, a typical realistic model is to object-oriented debugging as a bit-level representation is to symbolic data structure exploration. In this paper, we introduce a two-level [32] semantic framework for modeling object-oriented programming languages that overcomes these shortcomings. The upper level represents all objectoriented actions of a program execution. It tracks six kinds of actions via a rewriting system on object-configurations [26]: object creation, class inspection, field inspection, field mutation, method calls, and method return; we do not consider any other action an object-oriented computation. The computations at this upper level have a graphical equivalent that roughly corresponds to UML sequence diagrams [17]. Indeed, each configuration in the semantics corresponds to a diagram, and each transition between two configurations is an extension of the diagram for the first configuration. The upper level of the framework is parameterized over the internal semantics of method bodies, dubbed the lower level. To instantiate the framework for a specific language, a semanticist must map the object-oriented part of a language to the object-oriented level of the framework and must express the remaining actions as the lower level. The sets and functions defining the lower level may be represented many ways, including state machines, mathematical functions, or whatever else a semanticist finds appropriate. We demonstrate how to instantiate the framework with a Java subset. In addition to developing a precise mathematical meaning for the framework, we have also implemented a prototype of the framework. The prototype traces a program’s object-oriented actions and allows programmers to inspect the state of objects. It is a component of the DrScheme programming environment [13] and covers the kernel of PLT Scheme’s class system [15]. The next section presents a high-level overview. Section 3 introduces the framework and establishes a generalized soundness theorem. Section 4 demonstrates how to instantiate the framework for a subset of Java and extends the soundness theorem to that instantiation. Section 5 presents our tool prototype. The last two sections are about related and future work. −→ t Any number of elements of the form t. c[e] Expression e in evaluation context c. e[x := v] Substitution of v for free variable x in expression e. d p −→ r The set of partial functions of domain d and range r. d f −→ r The set of finite mappings of domain d and range r. [ −−−→ a 7→ b] The finite mapping of each a to the corresponding b. f [ −−−→ a 7→ b] Extension of finite mapping f by each mapping of a to b (overriding any existing mappings). Figure 2. Notational conventions.