Living Languages

Brian Foote

Department of Computer Science

University of Illinois at Urbana-Champaign

1304 W. Springfield

Urbana, IL 61801 USA

(217) 328-3523

foote@cs.uiuc.edu

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
 

Brian Foote foote@cs.uiuc.edu
Last Modified: 3 December 1998