Living Languages
Department of Computer Science
University of Illinois at Urbana-Champaign
1304 W. Springfield
Urbana, IL 61801 USA
(217) 328-3523
August 1992
Languages Must Evolve or Die
The marriage of reflection with object-oriented programming and design techniques holds out the promise of dramatically changing the way that we think about, organize, implement, and use programming languages and systems. The combination of object-oriented programming languages and reflective metalevel architectures allows the full power of the object-oriented approach to be brought to bear upon object-oriented languages themselves Together, they have the potential to permit the long deferred promise of truly open programming languages and system to be realized.
Modern programming languages are arguably the single most significant achievement of 40-odd years of software-related research. However, success often breeds a sense of disciplinary complacency. Maybe the question we should be asking ourselves is not what should this-or-that ++ look like. Perhaps we should ask instead what kind of architectural ideas will succeed programming languages themselves.
The challenges we are calling upon the next generation of programming languages to address are quite different from those that drove the design of the current crop of languages. Concurrent computing, distributed computing, persistent object bases, and graphical user interfaces all present challenges that are inadequately addressed by mainstream programming languages. Together, they emphasize the need to provide a way for languages to adapt as they confront changing requirements.
Traditional programming languages were in essence carved in stone when their defining reports (and revised reports, and revised revised reports) were issued. Building languages themselves out of objects can allow programming languages be specialized and to adapt as individual programmers address new problems.
The process of building domain specific resuable artificacts can be thought of as building a high-level, domain specific programming language. The developers of such code should not be impeded by their languages or tools. If such developers are indeed engaged in language design (and I believe they are) we should strive to make sure that our programming systems get out of the way and allow them to do the best job that they can.
A living language is one that is able to adapt and evolve as the needs of the people who use it change. I believe that object-oriented languages with reflective metalevel architectures have the flexibility necessary to meet the needs of the next generation of computing systems.
Object-Oriented Object-Oriented Languages
A programming language with an object-oriented metalevel architecture is one in which programs are themselves constructed out of first-class objects. Metalevel objects, or metaobjects are objects that define, implement, support, or otherwise participate in the execution of application, or base level programs.
A reflective object-oriented language allows a running program to look at or change the objects out of which it is built. Together, these metaobjects constitute the system's self-representation. These objects reify otherwise implicit aspects of the underlying system. The ability to inspect, but not alter, the objects that implement a system is referred to as introspection.
A reflective object-oriented program can access the very objects that in turn define how it works, and can alter them dynamically if necessary. Changes made to these objects are immediately reflected in the actual dynamic state of the state of the system, and vice versa. The requirement that this dynamic constistency be maintained is sometimes refered to as the causal connection requirement.
Programming languages built out of objects are easy to extend. Features may be added to a suitably designed reflective object-oriented language by adding a set of metaobjects to support them to the language. These objects may, of course, be specializations of existing objects. A well designed reflective metalevel architecture can limit the scope of extensions to a single object, class, or computation, or allow them to be in effect system wide. Features that have usually required the definition and implementation of whole new languages, such as backtracking [LaLonde & Van Gulik 1987], futures [Foote & Johnson 1989] and persistence [Paepke 1990] have been added to existing languages using reflective facilities.
Reflection can also allow programmers to create new metalevel objects and selectively substitute them for existing part of the running system. This ability allows programmers to add objects to trace a program's execution, for example, from within the language. Support for debugging in most languages is usually treated in an ad-hoc fashion by individual implementations. An object-oriented reflective metalevel architecture allows support for debugging to be provided at the language level.
A language that supports the dynamic redefinition of existing parts of the system is said to be mutable. A language that supports the addition of new features, but not the redefinition of old ones is said to be extensible [Stroustrup 1991]. The ability to exploit the existing definition of a system to augment its behavior gives the programmer considerable leverage over the rest of the system.
It is easy to dynamically introduce new objects and object types into a running reflective program, since these objects, as well as the objects that define them, are themselves first-class, dynamic objects. By contrast, consider the difficulty associated with dynamically handling a new type of object in a C++ program that has already been compiled.
Because programming systems with object-oriented reflective metalevel architectures have a model of themselves embedded within them, they exhibit a substantial capacity for metamorphosis. Reflection has the potential to extend the runtime reach of a programming system inward into the definition of the language itself, downward into its implementation, and outward into realms currently considered the provinces of operating systems, programming environments and database systems. Reflection has the potential to bring areas as disparate as programming language design, compiler construction, code generation, debugging, tracing, concurrent programming, and semantics together under a single umbrella.
A characteristic of the lifecycle of object-oriented entities is the emergence of structural insight into an application domain as the result of successive reapplication. Constructing the elements of programming systems out of dynamic first class objects can lead to a reassessment of where the walls between objects, environments, operating systems, databases, and command languages should be placed. As a system evolves, internal structure emerges. Objects are ideal for capturing this structure. As walls crumble, these constituent objects can serve as a structural redoubt one level below . Without objects, one would have to fall all the way back into the implementation to reorganize a system. A comprehensive reexamination of how a system supports running objects could permit autonomous objects to break free of the processes that spawned them and migrate unencumbered among other processes, processors, and persistent object bases.
A good sign that a programming language feature is needed is when a lot of people go to a great deal of effort to build it themselves atop existing languages. There is abundant evidence that dynamic metalevel objects are such a feature. Open systems need open languages.
Frameworks Facilitate Change
Object-oriented programming languages and systems are having a profound impact on the way that we organize, design, implement, and maintain software. These techniques allow us to treat software components and systems alike as durable, yet malleable artifacts, which evolve along with their requirements Object-oriented languages make it much easier to design software components and systems that can adapt as requirements evolve and change [Foote 1988a]. The judicious use of object-oriented techniques can promote the emergence of reusable abstract classes, components, and object-oriented frameworks [Deutsch 1983] [Johnson & Foote 1988].
An object-oriented framework is composed of a set of abstract classes and components that together comprise an abstract or generic solution to a range of potential application requirements. The framework's abstract classes and components must be customized by the framework's clients to suit the requirements of specific applications. Frameworks, unlike abstract classes, are often characterized by an inversion of control. That is, rather than calling framework elements directly, the client must sometimes instead supply the framework with components that are "called-back" by the framework at an appropriate time.
Durable, reusable object-oriented artifacts emerge most readily from an iterative reapplication of existing abstract classes, components, and frameworks to successive, related requirements. Object-oriented entities evolve at every level along a trajectory that takes them through an initial prototype phase, and expansionary exploratory phase, and a consolidation phase. During the consolidation phase, structural insight gained during successive reapplications is exploited to increase the generality, structural integrity, and reusability of these entities. As entities evolve, many will progress from loosely structured, application specific, inheritance-based "white-box" entities to fully encapsulated, fairly general, component-based "black box" entities.
A Framework for Reflective Metalevel Architectures
The current surge of interested in object-oriented reflection and metalevel architectures is, I believe, based on the observation that object-oriented languages and programs are as much themselves an appropriate domain for object-oriented techniques as are windowing systems, operating systems, or accounting systems. The vision underlying this observation is one of a programming system in which the language definition itself is distributed across a constellation of objects which are themselves subject to dynamic scrutiny and modification.
Such a system would allow users to construct new language level objects which would stand on an equal footing with previously existing features. A language built of such programmable objects would be arbitrarily extensible, and would permit language as well as application level objects to be utilized to help the system adapt and evolve as requirements change A particularly intriguing consequence of this approach is that the components of such a system can themselves serve as the basis for an object-oriented framework that can support an evolving family of different programming approaches and paradigms.
Reusable object-oriented frameworks cannot be constructed in a top-down fashion. They are the result of an iterative process that unfolds at all levels of a system as objects are successively reapplied to address changing requirements. The following are design principles that might characterize a linguistic framework.
o Reflective metalevel architectures should be designed with message passing at the bottom, malleable self-representations, extensionality, abstract inheritance, first -class representation, abstract dispatching, and abstract scope.
o All significant elements of a languages' programming model ought to be themselves reflected in first-class elements of that language's metalevel architecture. For instance, if the programming model makes extensive use of a notion like "class", then Class objects should be explicit, first-class elements of the metaarchitecture that coexist with ordinary application objects at runtime.
o Hence, a framework for object-oriented reflective metalevel architectures might draw from a rich palette of potential metaobjects, including variables, selectors, messages, interpreters, script sets, handles, environments, continuations, contexts, message queues, stores, closures, classes, types, prototypes, signatures, methods, code, threads, and instances...
Movable Walls
A characteristic of the lifecycle of object-oriented entities is the emergence of structural insight into an application domain as the result of successive reapplication. Constructing the elements of programming systems out of dynamic first class objects can lead to a reassessment of where the walls between objects, environments, operating systems, databases, and command languages should be placed.
Traditional programming environments, whether they are based on the compile/link/load model, or the image model seen with languages such as Lisp or Smalltalk, tend to trap objects on reservations circumscribed by runtime support requirements They may influence or exploit objects outside their addressing spaces only indirectly, via I/O. I believe that advances in hardware and software technology make it appropriate to reassess the relationship among object-oriented languages themselves, their runtime environments, and the rest of the world. For instance, shared memory, distributed, and networked systems, concurrent systems, and object-oriented databases all present novel runtime challenges. It is already clear that reflective techniques are having a significant impact on the way in which we think around concurrent systems. Reflective techniques have also been employed to add persistence to objects in existing image-based systems [Paepcke 1990]. The growing popularity of object-oriented databases also attests to the observation that first-class objects have a place outside individual applications.
Voltaire is said to have said that if God did not exist, it would be necessary to invent him. One can make a case that the architects of systems such as X and the Macintosh Operating Systems have discovered that the same is true of object-oriented programming in general, and of dynamic, autonomous objects in particular. In those cases where linguistic support for object-orientation has not been present, object-like entities have been constructed in a home-brew fashion, out of elements like C structs and pointers to functions. Indeed, it is difficult to think of a significant GUI package that does not employ object-oriented facilities. What is striking in packages like the X Toolkit is not just that object-orientation was found to be indispensable, but that some of the object-oriented facilities that were included go beyond not only C++, but Smalltalk and Lisp as well in terms of metalevel sophistication. The renewed interest in the C++ community in metalevel facilities attests to their necessity.
For instance, the resource managers seen in both X and the Macintosh Toolbox can be thought of as forerunners of genuine rudimentary object-oriented databases. X Resource IDs are reference or handle-like objects with a scope that may span several active address spaces. Atoms are IDs that play a role similar to that of Lisp Symbols. The resource manager itself contains sophisticated facilities for interpreting and converting strings to resources. Since the C (and C++) namespaces are not accessible at runtime, the resource manager also is recruited to aid in the cumbersome task of mapping runtime name strings on to compile time program level names. Many X widgets are themselves framework-like structures, with elaborate callback hooks that perform the sorts of functions one might employ CLOS :before or :after methods for. This all suggests that the next generation of object-oriented programming language will have to cope with a need for features like as expression evaluation, smart handles, and persistent, distributed, and shared objects.
Can reflective object-oriented metalevel architecture help to address these needs? And if so, how? Can the relationships among system components like compilers, loaders, interprocess communication, and storage management be refactored in such a way so as to allow objects to flourish outside the processes in which they were spawned? What sort of facilities might be necessary to support such autonomous objects, and where must these facilities be located in order to allow them to work? And, what sorts of metalevel linguistic manipulation might we undertake to simplify all of this?
It is interesting to speculate as to what some of the answers might be. For instance, if the sort of dynamic translation seen in Smalltalk and Self were available as a sort of operating system level service, along with storage and namespace management services, it is possible to imagine how individual objects might flourish beyond the umbilicals that tie them to their originating processes. A key contribution that reflective languages might make to this vision is that the vastly more complex semantics for handles and namespace management need only be mobilized for objects outside their wombs. Object-oriented techniques themselves are essential if one is to even contemplate such a system organization.
The Hamiltonians vs. the Jeffersonians
During the early development of American representative democracy, two schools of thought emerged. The Jeffersonians felt that the people could be trusted with decisions such as the election of the president, while the Hamiltonians believed that an educated elite, and not the masses, should make such choices.
Allowing the programmer to make local modifications to the existing components of a programming language reflects a distinctly Jeffersonian philosophy towards language design. It is undeniable that such power has a high abuse potential. The price of freedom, after all, is responsibility.
One can make the case that the Hamiltonian view that the definition of the language itself should beyond the reach of the programmer has unnecessarily hamstrung language as well as application evolution. The traditional view of language design has been that a programming language emerges, fully formed and carved in stone by a single hand, from some castle in the Alps. Mistakes made by the designers of such languages may persist for a generation, until such languages are supplanted altogether. Consider Pascal's inflexible array dimensions. The programs written in these languages must then be translated somehow, or die ignominious deaths. This approach makes it impossible for a language to attempt to cope with new challenges, such as the need to support parallelism, or a persistent object store, or to support application specific extensions.
I believe the argument that reflection is dangerous because it gives programmers too much power is a specious one. Existing programming languages already give clumsy programmers more than ample opportunities to shoot themselves in the foot. I'll concede that reflective systems allow the clumsy programmer to fire several rounds per second into his foot, without reloading. Still, I'm confident that, as is the case with features such as pointers, competent programmers will make appropriate use of the power of reflection with care and skill. Potential abuse by inept programmers should not justify depriving the programming community of a potentially vital set of tools.
Certainly, metaprogramming is not for everyone. Most users will not need to resort to designing and building, as opposed to using, reflective facilities. Metaprogramming should not be undertaken frivolously. However, a language should not be an obstacle to its users, or to its own evolution. The age of Software Stalinism is past.
Open Languages
One of the explanations for the renewed popularity of reflection, particularly in the object-oriented community, is that we have become heirs to a long tradition of trying to make programming languages as open as possible. This section examines some of this tradition.
Nowhere has the open languages tradition flourished more than in the Lisp community. Indeed, Self, Smalltalk, 3-Lisp, 3-KRS, CLOS, ObjVLisp, the Actor languages, and ABCL/R can all trace their ancestry either directly or indirectly to Lisp. A metacircular definition was given for Lisp in [McCarthy et. al. 1962]. This definition gave a blueprint for a program that could take other Lisp programs in the form of Lisp data structures and execute them. This program, in turn, allowed Lisp data structures (s-expressions) to be passed to a function (eval) and executed as code. In [McCarthy 1978] McCarthy recalls the following about the preparation of [McCarthy 1960]:
"...Another way to show that LISP was neater than Turning machines was to write a universal LISP function and show that it was briefer and more comprehensible thatn the description of a universal Turing machine. This was the LISP function eval[e,a], which computes the value of a Lisp expression e -- the second argument a being a list of assignments to variables. (a is required to make the recursion work). Writing eval required inventing a notation representing LISP functions as LISP data, and such a notation was devised for the purposes of the paper with no thought that it would be used to express LISP programs in practice..."
It is clear that McCarthy recognized that a programming language could be at least as effective as alternative formal approaches for defining how a programming language works. However, McCarthy and his group did not at first foresee the practical potential that their approach had for actual metaprogramming.
In Smalltalk-72 [Goldberg & Kay 1976] [Ingalls 1983] code was viewed by the interpreter as simply a stream of tokens. The object returned by any computation could hijack the local message stream, and gobble down as many tokens as it saw fit, Pac-Man style. Smalltalk-74 introduced a programmer accessible object that represented the incoming message stream. Thus, not only could all the message stream operations be examined in Smalltalk, but the user could also define his (sic) own extensions to the message stream semantics.
With Smalltalk-76, the designers of Smalltalk began to retreat from the most extravagant of such dynamic excesses in the name of efficiency. Still, the imperative that elements of the system itself be aggressively promoted to first-class status was retained. Ingalls referred to the following as the Smalltalk Philosophy:
"choose a small number of general principles and apply them uniformly".
On the topic of kernel size and openness, Ingalls stated:
"We have always sought to reduce the size of the Smalltalk kernel. This is not only an aesthetic desideratum; kernel code is inaccessible to the normal user, and we have always tried to minimize the parts of of our system that can not be examined and altered by the curious user."
This requirement that the user be able to examine or alter as much of the system as possible meshes nicely with our our contemporary working definitions for reflection. Indeed, the extensive set of metaobjects in Smalltalk-80 [Goldberg & Robson 1983] is one of the best existing examples of the power of such objects. [Deutsch and Shiffman 1984] describes a strategy for efficiently implementing what we now call Smalltalk's highly reflective Context objects. It is important to note that way before we had a name for it, the Smalltalk community was doing the seminal work on what we are now calling object-oriented reflective metalevel architectures.
The goal of aggressively promoting elements of the language to first-class status, as well a recognition of the perils of regress can be seen in the Actor community in this passage from [Lieberman 1986]:
"Many object-oriented systems supply linguistic mechanisms for creating objects with methods, variables and extensions. An alternative approach, which is advocated in the actor formalism, is to define methods, variables, and extensions as objects in their own right, with their behavior determined by a message passing protocol among them. Obviously, and object representing a method cannot itself have a methods, otherwise infinite recursion would result."
This passage from the same paper also recognizes the merits of a small, highly extensible object-oriented kernel:
"The mechanisms for sharing knowledge in object-oriented languages have now grown so complicated that it is impossible to reach universal consensus on the best mechanism. Using object-oriented programming itself to implement the basic building blocks of state and behavior is the best approach for allowing experimentation and coexistence among competing formalisms."
We Must Build Atop a Flexible Foundation
I believe that we in the object-oriented programming community are discovering a principle that Pacific Rim architects already know. That is: To stay the seismic upheaval that confronts a system during the course of its lifetime, it must be built atop a flexible foundation. We can no longer think of our programming languages and systems as rigid structures that will withstand generations of buffeting in this face of changing requirements. We must instead construct systems that not only build on past experience, but are able to adapt and evolve as well. We must build our houses of brick rather than straw, but make sure that there is shock absorbing material in place in their foundations as well.
The cobbler's children, it has been said, are often the last to be shod. Just as objects are good for building programs, so too they are good for building programming languages and programming systems.
REFERENCES
[Abelson & Sussman 1985 Harold Abelson and Gerald Jay Sussman with Julie Susmann Structure and Interpretation of Computer Programs MIT Press, Cambridge, Mass. McGraw-Hill, New York, 1985 [Agha 1986] Gul Agha ACTORS: A Model of Concurrent Computation in Distributed Systems MIT Press, 1986 [Bawden 1988] Alan Bawden Reification without Evaluation Proc. Symposium on Lisp and Functional Programming, 1988 pages 342-248 [Bennett 1987] John K. Bennett The Design and Implementation of Distributed Smalltalk OOPSLA '87 Proceedings Orlando, FL, October 4-8 1977 pages 118-330 [Bobrow et. al. 1988] D. G. Bobrow, L. G. DeMichiel, R. P. Gabriel, S. E. Keene, G. Kiczales, and D. A. Moon Common Lisp Object System Specification X3J13 Document 88-002R SIGPLAN Notices, Volume 23, Special Issue, September 1988 [Bobrow & Kiczales 1988] Daniel G. Bobrow and Gregor Kiczales The Common Lisp Object System Metaobject Kernel -- A Status Report Proceedings of the 1988 Conference on Lisp and Functional Programming [Borning 1979] Alan Borning ThingLab -- A Constraint Oriented Simulation Laboratory Technical Report No. SSL-79-3 Xerox Palo Alto Research Center July 1979 [Borning & Ingalls 1982] A. H. Borning and D. H. H. Ingalls A Type Declaration and Inference System for Smalltalk 9th POPL, 1982, pages 133-141 [Borning & O'Shea 1986] A. Borning and T. O'Shea DeltaTalk: An Empirically and Aesthetically Motivated Simplification of the Smalltalk-80 Language (unpublished) 1986 [Borning 1986] Alan Borning Classes versus Prototypes in Object-Oriented Languages Proceedings of the ACM/IEEE Fall Joint Computer Conference Dallas, TX, November 1986, pages 36-40 [Briot 1989] Jean-Pierre Briot Actalk: A Testbed for Classifying and Designing Actor Languages in the Smalltalk-80 Environment LITP 89-33 RXF, Rank Xerox ECOOP '89 [Chambers et. al. 1989] Craig Chambers, David Ungar, Elgin Lee An Efficient Implementation of SELF a Dynamically-Typed Object-Oriented Language Based on Prototypes OOPSLA '89 Proceedings New Orleans, LA October 1-6 1989, pages 49-70 [Cointe 1987] Pierre Cointe Metaclasses are First Class: The ObjVlisp Model OOPSLA '87 Proceedings Orlando, FL, October 4-8 1977, pages 156-167 [Danvy & Malmkjaer 1988] Oliver Danvy and Karoline Malmkjaer Intensions and Extensions in a Reflective Tower 1988 ACM Conference on Lisp and Functional Programming, Smowbird, UT, July 1988 pages 327-341 [des Rivieres & Smith 1984] Jim des Rivieres and Brian Cantwell Smith The Implementation of Procedurally Reflective Languages Proc. of the 1984 ACM Symposium on Lisp and Functional Programming August, 1984, pages 331-347 [des Rivieres 1988] Jim des Rivieres Control-Related Meta-Level Facilities in Lisp in Meta-Level Architectures and Reflection P. Maes and D. Nardi, editors Elsevier Science Publishers B. V. North-Holland, 1988, pages 101-110 [Deutsch 1983] L. Peter Deutsch Reusability in the Smalltalk-80 Programming System ITT Proceedings of the Workshop on Reusability in Programming, 1983, pages 72-76 (reprinted in Tutorial on Software Reusability, IEEE Computer Society Press, 1987) [Deutsch & Schiffman 1984] L. Peter Deutsch and Allan M. Schiffman Efficient Implementation of the Smalltalk-80 System Proceedings of the Tenth Annual ACM Symposium on Principles of Programming Languages, 1983, pages 297-302 [Ellis & Stroustrup 1990] Margaret A. Ellis and Bjarne Stroustrup The Annotated C++ Reference Manual Addison-Wesley, Reading, MA, 1990 [Ferber 1989] Jacques Ferber Computational Reflection in Class-Based Object-Oriented Languages OOPSLA '89 Proceedings New Orleans, LA October 1-6 1989, pages 317-326 [Foote 1988a] Brian Foote Designing to Facilitate Change with Object-Oriented Frameworks Masters Thesis, 1988 University of Illinois at Urbana-Champaign [Foote & Johnson 1989] Brian Foote and Ralph E. Johnson Reflective Facilities in Smalltalk-80 OOPSLA '89 Proceedings New Orleans, LA October 1-6 1989, pages 327-335 [Foote 1990] Brian Foote Object-Oriented Reflective Metalevel Architectures: Pyrite or Panacea? OOPSLA/ECOOP '90 Workshop on Reflection and Metalevel Architectures Mamdouh Ibrahim, Brian Foote, Jean-Pierre Briot, Gregor Kiczales, Satoshi Matsuoka, and Takuo Watanabe, organizers [Foote 1991] Brian Foote Flexible Foundations and Movable Walls OOPSLA '91 Workshop on Reflection and Metalevel Architectures Phoenix, AZ Mamdouh Ibrahim, Brian Foote, Pierre Cointe, Gregor Kiczales, Satoshi Matsuoka, and Takuo Watanabe, organizers [Friedman & Wand 1984] D. P. Friedman and M. Wand Reflection without Metaphysics Proc. Symposium on Lisp and Functional Programming, pages 348-355, August 1984 [Goldberg & Kay 1976] Adele Goldberg and Alan Kay, editors with the Learning Research Group Smalltalk-72 Instruction Manual Xerox Palo Alto Research Center [Goldberg & Robson 1983] Adele Goldberg and David Robson Smalltalk-80: The Language and its Implementation Addison-Wesley, Reading, MA, 1983 [Goldberg 1984] Adele Goldberg Smalltalk-80: The Interactive Programming Environment Addison-Wesley, Reading, MA, 1984 [Halstead 1985] Robert H. Halstead, Jr. MultiLISP: A language for Concurrent Symbolic Computation ACM Transactions on Programming Languages and Systems Volume 7,. Number 4 October 1985, pages 501-538 [Hewitt & de Jong 1983] Carl Hewitt and Peter de Jong Analyzing the Role of Description and Actions in Open Systems AAAI '83, pages 162-167 [Hoeltze et. al. 1990] Urs Hoeltze, Bay-Wei Chang, Craig Chambers, and David Ungar The Self Papers, and the Self Manual (unpublished) [Ibrahim & Cummins 1988] Mamdouh H. Ibrahim and Fred A. Cummins KSL: A Reflective Object-Oriented Programming Language Proceedings of the International Conference on Computer Languages Miami, FL, October 9-13 1988 [Ingalls 1978] Daniel H. H. Ingalls The Smalltalk-76 Programming System Design and Implementation 5th ACM Symposium on POPL, pages 9-15 Tucson, AZ, USA, January 1978 [Ingalls 1983] Daniel H. H. Ingalls The Evolution of the Smalltalk-80 Virtual Machine in Smalltalk 80: Bits of History, Words of Advice Glenn Krasner, editor Addison-Wesley, Reading, MA 1983 [Jefferson 1985] David. R. Jefferson Virtual Time ACM Transactions on Programming Langauges and Systems Volume 7, Number 3, pages 404-425, July 1985 [Johnson & Foote 1988] Ralph E. Johnson and Brian Foote Designing Reusable Classes Journal of Object-Oriented Programming Volume 1, Number 2, June/July 1988 pages 22-35 [Johnson et. al. 1988] Ralph E. Johnson, Justin O. Graver, and Laurance W. Zurawski TS: An Optimizing Compiler for Smalltalk OOPSLA '88 Proceedings San Diego, CA, September 25-30, 1988 pages 18-26 [Kaiser & Garlan 1987] Gail E. Kaiser and David Garlan Melding Software Systems f rom Reusable Building Blocks IEEE Software, Volume 4 Number 4 July 1987 pages 17-24 [Keene 1989] Sonya E. Keene Object-Oriented Programming in Common Lisp A Programmer's Introduction to CLOS Addison-Wesley, 1989 [Kiczales & Rodriguez 1990] Gregor Kiczales and Luis Rodriguez Efficient Method Dispatch in PCL Proceedings of the 1990 ACM Conference on Lisp and Functional Programming Nice, France, June 1990, pages 99-105 The Art of the Metaobject Protocol MIT Press, 1991 [Kiczales et. al. 1991] Gregor Kiczales, Jim Des Rivieres, and Daniel G. Bobrow The Art of the Metaobject Protocol MIT Press, 1991 [Kim et. al. 1989] Won Kim and Frederick H. Lochovsky, editors Object-Oriented Concepts, Databases, and Applications Addison-Wesley, Cambridge, MA, 1989 [Krasner et. al. 1983] Glenn Krasner, editor Smalltalk 80: Bits of History, Words of Advice Addison-Wesley, Reading, MA 1983 [LaLonde et. al. 1986] Wilf R. LaLonde, Dave A. Thomas and John R. Pugh An Exemplar Based Smalltalk OOPSLA '86 Proceedings Portland, OR, October 4-8 1977 pages 322-330 [LaLonde & Van Gulik 1988] Wilf R. LaLonde and Mark Van Gulik Building a Backtracking Facility in Smalltalk Without Kernel Support OOPSLA '88 Proceedings San Diego, CA, September 25-30, 1988 pages 105-122 [Lieberman 1986] Henry Lieberman Using Protypical Objects to Implement Shared Behavior in Object-Oriented Systems OOPSLA '86 Proceedings Portland, OR, October 4-8 1977 pages 214-223 [Lieberman et. al. 1988] Henry Lieberman, Lynn A. Stein, and David Ungar Treaty of Orlando Special OOPSLA '87 Addendum to the Proceedings SIGPLAN Notices, May 1988 Volume 23, Number 5 [Lindsey & van der Muelen 1973] C. H. Lindsey and S.G van der Muelen Informal Introduction to ALGOL 68 North-Holland Publishing Co., Amsterdam American Elsevier Publishing Co., NY, 1973 [Maes 1987a] Pattie Maes Computational Reflection Artificial Intelligence Laboratory Vrije Universiteit Brussel Technical Report 87-2 [Maes 1987b] Pattie Maes Concepts and Experiments in Computational Reflection OOPSLA '87 Proceedings Orlando, FL, October 4-8 1977 pages 147-155 [Maes et. al. 1988] Pattie Maes and Daniele Nardi, editors Meta-Level Architectures and Reflection Elsevier Science Publishers B. V. North-Holland, 1988 [McCarthy 1960] John McCarthy Recursive Functions of Symbolic Expressions and their Computation by Machine, part 1 Communiations of the ACM Volume 3, Number 4, pages 184-185 [McCarthy et. al. 1962] John McCarthy, Paul W. Abrahams, Daniel J. Edwards, Timothy P. Hart, and Michael I. Levin Lisp 1.5 Programmer's Manual MIT Press, Cambridge, MA, 1962 [McCarthy 1978] John McCarthy History of Lisp ACM SIGPLAN History of Programming Languages Conference Los Angeles, CA June 1-3 1978 pages 217-223 [McCullough 1987] Paul L. McCullough Transparent Forwarding: First Steps OOPSLA '87 Proceedings Orlando, FL, October 4-8 1987 pages 331-341 [Messick & Beck 1985] Steven L. Messick and Kent L. Beck Active Variables in Smalltalk-80 Technical Report CR-85-09 Computer Research Lab, Tektronix, Inc., 1985 [Paepcke 1990] Andreas Paepcke PCLOS: Stress Testing CLOS OOPSLA/ECOOP '90 Proceedings Ottawa, Ontario, Canada October 21-25, 1990 pages 194-221 [Pascoe 1986] Geoffrey A. Pascoe Encapsulators: A New Software Paradigm in Smalltalk-80 OOPSLA '86 Proceedings Portland, OR, September 29-October 2 1986, pages 341-346 [Smith 1982] Brian Cantwell Smith Reflection and Semantics in a Procedural Programming Language Ph. D. Thesis, MIT MIT/LCS/TR-272 [Smith 1984] Brian Cantwell Smith Reflection and Semantics in Lisp Proceedings of the 1984 ACM Principles of Programming Languages Conference pages 23-35 [Smith & des Rivieres 1984] Brian Cantwell Smith and Jim des Rivieres Interim 3-LISP Reference Manual Xerox Intelligent Systems Laboratory ISL-1 Xerox Palo Alto Research Center June 1984 [Smith 1987] Randall B. Smith Experiences with the Alternate Reality Kit: An Example of the Tension Between Literalism and Magic. CHI+GI 1987 Conference Proceedings [Steele & Sussmann 1976] Guy Lewis Steele Jr. and Gerald Jay Sussman Lambda: The Ultimate Imperative MIT AI Memo 353 March 10, 1976 [Steele 1976] Guy Lewis Steele Jr. Lambda: The Ultimate Declarative MIT AI Memo 379 November 1976 [Steele 1977] Guy Lewis Steele Jr. Debunking the "Expensive Procedure Call" Myth or, Procedure Call Implementations Considered Harmful, or Lambda: The Ultimate GOTO MIT AI Memo 443 October 1977 [Steele 1984] Guy L. Steele Jr. Common Lisp: The Language Digital Press, 1984 [Steele 1990] Guy L. Steele Jr. Common Lisp: The Language Second Edition Digital Press, 1990 [Stefik & Bobrow 1986] Mark Stefik and Daniel G. Bobrow Object-Oriented Programming: Themes and Variations AI Magazine 6(4): 40-62, Winter, 1986 [Stefik et. al. 1986] M. Stefik, D. Bobrow and K. Kahn Integrating Access-Oriented Programming into a Multiprogramming Environment IEEE Software, 3, 1 (January 1986), pages 10-18 [Stein 1987] Lynn Andea Stein Delegation is Inhertance OOPSLA '87 Proceedings Orlando, FL, October 4-8 1977 pages 138-146 [Stein et. al. 1989] Lynn Andea Stein, Henry Lieberman, and David Ungar A Shared View of Sharing: The Treaty of Orlando in Object-Oriented Concepts, Databases, and Applications Won Kim and Frederick H. Lochovsky, editors Addison-Wesley, Reading, MA, 1989 [Stroustrup 1986] Bjarne Stroustrup The C++ Programming Language Addison-Wesley, Reading, MA, 1986 [Stroustrup 1991] Bjarne Stroustrup The C++ Programming Language Second Edition Addison-Wesley, Reading, MA, 1991 [Sussmann & Steele 1978] Guy Lewis Steele Jr. and Gerald Jay Sussman The Art of the Interpreter, or The Modularity Complex (Parts Zero, One, and Two) MIT AI Memo 453 May 1978 [Tiemann 1988] Michael D. Tiemann Solving the RPC problem in GNU C++ 1988 USENIX C++ Conference Denver, CO, October 17-21 1988 [Ungar & Smith 1987] David Ungar and Randall B. Smith Self: The Power of Simplicity OOPSLA '87 Proceedings Orlando, FL, October 4-8 1977, pages 227-242 [van Wijngaarden et. al. 1976] A. van Wijngaarden, B. J. Mailoux, J. E. L. Peck, C. H. A. Koster, M. Sintzoff, C. H. Lindsey, L. G. L. T. Meertens and R. J. Fisker Springer-Verlag, Berlin, Heidelberg, New York 1976 [Yokote & Tokoro 1986] Yasuhiko YokoteYasuhiko Yokote and Mario Tokoro The Design and Implementation of ConcurrentSmalltalk OOPSLA '86 Proceedings Portland, OR, September 29-October 2 1986 pages 331-340 [Wand & Friedman 1986] Mitchell Wand and Daniel P. Friedman The Mystery of the Tower Revealed: A Non-Reflective Description of the Reflective Tower ACM Conference on Lisp and Functional Programming Boston, MA, August 1986 [Watanabe & Yonezawa 1988] Takuo Watanabe and Akinori Yonezawa Reflection in an Object-Oriented Concurrent Language OOPSLA '88 Proceedings San Diego, CA, September 25-30, 1988 pages 306-315 [Yonezawa et. al. 1989] Akinori Yonezawa, editor ABCL: An Object-Oriented Concurrent System MIT Press, Cambridge, MA 1989