TIP:            279
Title:          Adding an Extensible Object System to the Core
Version:        $Revision: 1.10 $
Author:         Gustaf Neumann <neumann@wu-wien.ac.at>
Author:         Larry W. Virden <lvirden@yahoo.com>
State:          Draft
Type:           Project
Vote:           Pending
Created:        05-Oct-2006
Post-History:   
Tcl-Version:    8.7

~ Abstract

This TIP proposes adding OO support to the Tcl core, consisting mostly
of a dispatcher plus a small number of helper commands. The TIP
allows the coexistence of multiple object systems by providing a
common framework, the Tcl Minimal Object System (TMOS).  The framework
will contain, as well, a small, basic oriented language (Tcl Core Object
Oriented Language, TclCOOL) to make it usable in the core without any
extensions. All defined commands of the minimal object system are
defined in the '''::oo''' namespace, which is not used by any current
mainstream OO system. It has been designed specifically to allow a relatively 
simple re-implementation of the known object systems.

~ Rationale and Basic Requirements

Rather than proposing any kind of OO language, the TIP suggests to add a
framework to the core that many existing and future extensions (including
XOTcl) can use. This framework alone is not useful as an OO language, but is
an environment that can host multiple OO languages in parallel, such as Snit
or XOTcl (maybe the language from current [257] as well), without pushing a
single model. Languages like Snit or XOTcl can continue to develop, the core
developers can optimize and integrate better with the tcl-core, etc.

The framework (Tcl Minimal Object System, TMOS) consists of an
flexible object interpreter (dispatcher) able to run the most powerful
current object extensions. This dispatcher is accompanied by a
"minimal object system" and a small set of predefined, but unattached 
methods (basic method set) and an "extension mechanism". For the
bootstrapping of different object systems, only a single method for
allocating objects or classes is proposed, plus a few commands for
setting up the object/class relations and registering methods.

The Tcl Minimal Object System is used for the definition of TclCOOL
(Tcl Core Object Oriented Language). TclCOOL is simple but powerful
object language realized with TMOS. 

Additional object systems (like XOTcl, SNIT or STOOP) can be loaded as
an extensions (being not part of the core), and can provide their own
method-sets (or re-use the predefined method set, or reuse the
methods-set of some extension).

This approach provides a flexibility much higher than in other popular
scripting languages and lets object system designers continue to
improve their work based on Tcl.

~ The Tcl Minimal Object System

The minimal object system consists of a base class ('''::oo::object''') and a
meta-class ('''::oo::class''', subclass of '''::oo::object''').

|   name of class  kind of class  superclass     instance-of
|  ==========================================================
|   ::oo::object   class          ::oo::object   ::oo::class
|   ::oo::class    meta-class     ::oo::object   ::oo::class

The meta-class '''::oo::class''' has two methods named "'''alloc'''" and "'''dealloc'''" 
(names are arbitrary, as shown later) to create objects or classes. '''::oo::object'''
has no methods at all.

The minimal object system is intended to be specialized by one or more
different object systems. An object system is created by sub-classing the base
classes, configuring these according to the object systems needs. This
configuration consists of defining its relations to the general base and
meta-class, and equipping these extension-specific classes with additional
functionality (providing methods). The whole configuration of the object
system can be done completely from the scripting level.

The minimal object system defines the following commands and methods 
in the ::oo namespace:

 * Two classes

|   ::oo::class
|   ::oo::object

 * Two unexported Tcl commands for OO-language designer

|   ::oo::alias
|   ::oo::setrelation

 * Three exported Tcl commands to be used by in the languages

|   ::oo::my
|   ::oo::self
|   ::oo::next 

 * An unregistered (unattached) set of methods that can be used for classes

|   alloc, dealloc, instproc, instforward, info

 * An unregistered (unattached) set of methods that can be used for objects
|   instvar forward info

The Tcl command ::oo::setrelation

|   ::oo::setrelation class|obj <relation> <target>

allows one to define/redefine relations between objects, classes and
mixins. This is a primitive command designed for the language
developer, not for the user of the implemented object oriented
language. The following relations are supported: '''mixin'''
(abbreviation for per-object mixin), '''instmixin''' (for per-class
mixin), '''filter''' (for per-object filter), '''instfilter''' (for
per-class filter), '''class''', and '''superclass'''. The meaning of
these relations is defined by the dispatcher, which is responsible for
the linearization of the commands.

The dispatcher determines the invocation order depending on the
precedence order and the resolution order. The precedence order
defines the priorization of classes and determines therefore the
shadowing of methods. The precedence order is per-object mixins,
followed by per-class mixins, followed by the class hierarchy. All of
these refer not to single classes but to class hierarchies, where the
contained classes are linearized; when a class is mixed into a
precedence order, where it is already present, it has no effect.
The precedence of object specific methods is between mixins 
and the intrinsic class hierarchy.

The method resolution order overlays the precedence order. While the
precedence order determines, what method should be called, the method
resolution order determines what other methods should be called before
this method. The resolution order supports per class filters (methods
to be called before every method dispatch for every instance of this
class) and per-object filters (to be called before every method
dispatch of this object). Filters are defined in a filter chain, where
object specific filters take precedence over class specific
filters. Filters can change the results of methods. Immediately before
and after certain methods pre- and post-conditions can be evaluated
(similar to method-combinators in CLOS), between statements,
invariants can be checked.

The invocation order defines the layering of methods, the method
chaining (calling shadowed/filtered methods) is performed through the
command next. Per-object filters, per-class filters, per-object mixins
and per-class mixins can be applied conditionally based on
tcl-expressions (guards) executed int the object context.

When an undefined method is invoked on an object, the
call (method name and the arguments of the invocation) are passed to
the method '''unknown'''. If no such method exists, an error message
is generated.

The Tcl command ::oo::alias

|   ::oo::alias class|obj methodName ?-objscope? ?-per-object? cmdName

registers a command (''cmdName'') under a certain name (''methodName'')
to an object or class (1st argument) to make the command available 
as a method. The options ''-objscope'' makes instance variables of the
object/class appear as local variables, therefore Tcl commands to which
variable names are passed (e.g. set, append, lappend, ...) can access
instance variables without additional effort. 

~~ Example for defining TclCOOL (Tcl Core Object Oriented Language)

~~~ Create base and meta class:

|   namespace eval tcl-cool {}
|   ::oo::class alloc ::tcl-cool::object
|   ::oo::class alloc ::tcl-cool::class

After creation, the classes ::tcl-cool::class and
::tcl-cool::object are instances of ::oo::class.
This is not what we want to have. ''tcl-cool::object''
should be the most general superclass of TclCOOL, and
''tcl-cool::class'' should be the most general superclass of
TclCOOL. Without this redefinition ::tcl-cool::class and 
::tcl-cool::object would not have methods (except alloc and dealloc),
even if we provide methods for these base classes.

~~~ Define the basic class relations:

Since we are bootstrapping the language from a minimal
command-set, we will use the setrelation command to define the
basic relationships of the freshly defined classes.

First, we define that the superclasses of the newly defined class
named ''::tcl-cool::class'') should be the general meta-class
::oo::class and as well ''::tcl-cool::object''. Therefore,
::tcl-cool::class will be a meta-class (its instances are classes) and
it will inherit all properties of the most general TclCOOL class.

|   ::oo::setrelation ::tcl::cool::class superclass {::oo::class ::tcl-cool::object} 

The next two commands define that ::tcl-cool::object and
::tcl-cool::class are instances of ::tcl-cool::class. In other words,
the class of e.g. ::tcl-cool::object is ::tcl-cool::class.

|   ::oo::setrelation ::tcl-cool::object class ::tcl-cool::class 
|   ::oo::setrelation ::tcl-cool::class  class ::tcl-cool::class 

The basic OO-relations of the two basic classes are defined. 
In a next step of the bootstrapping we attach methods to these classes.

~~~ Define methods for classes:

We define 3 methods for ''::tcl-cool::class'' based on the method-set for classes:

 * ''method'' is a means to define the methods, which are provided 
               to the instances of the class (''instproc'' in XOTcl)

 * ''forward'' is a forwarder for instances of the object (''instforward'' in XOTcl)

 * ''info'' is an introspection method for classes

|   ::oo::alias ::tcl-cool::class method  ::oo::methodset::class::instproc
|   ::oo::alias ::tcl-cool::class forward ::oo::methodset::class::instforward
|   ::oo::alias ::tcl-cool::class info    ::oo::methodset::class::info

~~~ Define methods for objects:

Next, we define 3 methods for ''object'' (actually ''::tcl-cool::object'') 
based on the method-set for objects:

 * ''variable'' is a means to import instance variables into
               the current scope (''instvar'' in XOTcl)

 * ''forward'' is a method for delegating calls to different objects

 * ''info'' is an introspection method for objects

|   ::oo::alias ::tcl-cool::object variable ::oo::methodset::object::instvar
|   ::oo::alias ::tcl-cool::object forward  ::oo::methodset::object::forward
|   ::oo::alias ::tcl-cool::object info     ::oo::methodset::object::info

The full definition of TclCOOL is available from
[http://media.wu-wien.ac.at/download/tcl-cool.tcl]

~ Methods from Extensions

This proposal defines only a small method-set (see above). However, it makes it 
straightforward to reuse the existing method-set (with maybe different names)
without forcing an intermediate interpretation layer, or to load an additional
method-set as extension. This additional method-set can be loaded dynamically via
'''package require'''. The object system developer can provided the methods as
Tcl commands in the extension's namespace. These commands can be attached to
the objects and classes of the object system to be defined with the command
''::oo::alias''.

The command alias should not allow extensions to register methods on 
'''::oo::object''' and '''::oo::class'''. All application object systems 
should only be allowed to register their methods on the language specific
superclasses.

The exact API for methods accessing the dispatcher internals will be specified
in another TIP.

The primitive commands (like '''my''', '''next''', '''self''',
'''configure''', ...) are provided by the OO namespace, and these can be 
provided by the extension writers by accessing the dispatcher structure
and its stack.

~ Strengths of the Approach

 * All OO extensions can use the powerful dispatcher

 * If a certain extensions don't require filters, mixins, etc., they simply
   don't have to activate these.

 * The XOTcl dispatcher can be seen as a prototype implementation, but it should
   be replaced by a more efficient implementation with tighter core
   integration, provided the regression tests of the languages (e.g., XOTcl)
   continue to work.

 * The prototype implementation based on the current XOTcl 1.5.3 alpha release

 > * is proven to work and sufficiently bug-free,

 > * is free of memory leaks,

 > * thread safe,

 > * provides execution of the destroy callbacks when a thread or
     program exits,

 > * provides uplevel transparency for interceptors,

 > * is well suited for IDEs (an arbitrary class from a class tree can be
     reloaded and redefined without altering the relations between classes
     and/or instances)

 * All OO systems are treated equal

 > * since we do not want to allow to register methods on '''::oo::object'''
     or '''::oo::class''', there is no "preferred" object system,

 > * every object system defines its own classes with its own names and own
     methods (although, it can reuse methods from all extensions with
     arbitrary names, as shown above)

 > * there is no need to namespace export from "oo::*" (these are no end-user
     commands).

 > * nobody is forced on any predefined semantics

 * no extensions are locked out

 > * existing "high level" extensions (like XOTcl) and their applications
     (e.g. OpenACS) continue to work

 > * since other OO language definitions are not part of the core, their development
     can continue, 

 > * other OO languages can easily benefit from the new core functionality

 > * the dispatcher is based on a superset of the requirements of 
     existing languages, so these should be able to use it.

 > * extending the dispatcher requires a TIP.

 * This proposal is in the Tcl tradition of Tcl as a 2-level meta-language,
   since it provides a highly adjustable framework for object oriented
   languages.

 * Providing such a framework will attract people and put Tcl in front of the
   other OO scripting languages.

~ Sample Implementation

 * XOTcl 1.5.3alpha is the reference dispatcher (it should be rewritten
   for inclusion in the core, and serves here only as proof-of-concept)
   [http://media.wu-wien.ac.at/download/xotcl-1.5.3-alpha2.tar.gz].

 * Example of the TclCOOL language (to be the ''part'' of the framework)
   [http://media.wu-wien.ac.at/download/tcl-cool.tcl]

 * Example of a subset of ITcl based on this TIP (implemented with 
   the framework, runs already part of the itcl regression tests:
   protection.test and basic.test, in the latter, only three error 
   messages differ) 
   [http://media.wu-wien.ac.at/download/itcl.tcl]

 * Example of the XOTcl language (as implemented ''with'' the
   framework):
   See generic/predefined.xotcl in the XOTcl 1.5.3alpha reference 
   implementation

~ Copyright

This document has been placed in the public domain.

