View · Search · Index
No registered users in community xowiki
in last 10 minutes

[Xotcl] TIP #257 & XOTcl as an OO framework

From: Gustaf Neumann <neumann_at_wu-wien.ac.at>
Date: Thu, 05 Oct 2006 01:07:21 +0200

Dear XOTcl community,

i am sure, some of you are following with interest the discussions
about TIP #257 (adding OO to the core), where the proponents
have developed an (incompatible) subset of XOTcl, that gives me
the impression, that it will be very hard to build on it. There is
a new implementation built from scratch, the implementor repeats,
that he is not understanding certain functionalities from XOTcl
(e.g. instmixins), is fixing hard bugs (forgot e.g. to loop check
on filters), is not handling thread/interpreter exits, etc. It will
take a while to debug the code, many other problems will
(naturally) show up with that code. The code does not seem
to be build for extensibility. Functionalities, that were dropped
from XOTcl that depend on dispatcher or callstack properties
are very hard to extend, especially, when there are no hooks.
The implementor has no ear for xotcl requests and repeats that
he has no time. Maybe i see the situation to negative, but i
don't think currently, the TIP is going into a direction doing
a good thing for the Tcl community (or XOTcl in particular).

Here is a slightly different proposal. Let me know, what you think
about it. I have this proposal already implemented (see below,
1.5.3alpha) and i am wondering - no matter how the TIP develops
- whether we should go this direction with XOTcl. Allthough
the first set of regression tests work already with an accordingly
bootstrapped XOTcl, the introspection tests don't work (since
there are now two top-level classes above ::xotcl::Object
and ::xotcl::Class. Btw, the implementation took me less
time than writing this proposal, and fits very nice with the
new slot model (one can define a default superclass with
the standard slot mechanism for e.g. "::xotcl::Class Dog",
where te superclass of Dog should be ::xotcl::Object" and not
necessarily the topmost superclass).

The change will be visible in XOTcl programs, since there
will be two new top-level classes. If you care and you
have objections against adding these classes, please let me
know. In case there is a strong objection, i will reconsider this
change.

-gustaf neumann

The proposal:

Rather than proposing any kind of OO language, i would suggest
to add a framework to the core, that every extension
(including XOTcl) can use. This framework is not useful as an
OO language on its own, but an environment that can host multiple
OO languages in parallel, such as Snit or XOTcl (maybe the
language from current TIP 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.

This approach (and implementation) is much closer aligned with the original
intention suited for multiple object systems. This proposal provides a
flexibility much higher than in other popular scripting languages and
lets object systems designer continue to improve their work.

My proposal is to add a framework consisting of an
flexible enough object interpreter (dispatcher) able to run the most
powerful current object extensions. This dispatcher is accompanied by
a "minimal object system" 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
e.g. setting up the object/class relations and registering methods).
The remainder of the object system (like XOTcl) can be loaded
as an extension (being not part of the core), but providing the
method set.


The Minimal Object System

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

                                                   superclass
instance-of
   ::oo::object class ::oo::object
::oo::class
   ::oo::class meta-class ::oo::object ::oo::class

The meta-class ::oo::class has a single method named "alloc" (name is
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.

Example for XOTcl:

  Create base and meta class:

    oo::class alloc ::xotcl::Object
    oo::class alloc ::xotcl::Class

  Define relation to the minimal object system:

    ::xotcl::setrelation ::xotcl::Class superclass {::oo::class
::xotcl::Object}
    ::xotcl::setrelation ::xotcl::Object class ::xotcl::Class
    ::xotcl::setrelation ::xotcl::Class class ::xotcl::Class

The superclasses of ::xotcl::Class are defined to be ::oo::class and
::xotcl::Object. ::xotcl::Object and ::xotcl::Class are defined as
instances of ::xotcl::class. The command setrelation supports the
following relations: "mixin", "instmixin", "filter", "instfilter",
"class", and "superclass" (alternatively, a reduced set "mixin",
"filter", "class", and "superclass", when a flag "per-object" can be
specified). The meaning of this relations is defined by the
dispatcher, which is responsible for the linearizion of the commands.


Methods from extensions:

This proposal does not define methods (maybe except alloc), but
instead an extension mechanism for defining methods. An implementor of
an OO-language can provide methods. These methods 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. This is achieved by the command alias:

   ::oo::alias <class|object> methodName cmdName

The following three commands register the method "instvar" and "proc"
for ::xotcl::Object (available for all objects in XOTcl) and
"instproc" for ::xotcl::Class

  ::xotcl::alias ::xotcl::Object instvar ::xotcl::cmd::instvar
  ::xotcl::alias ::xotcl::Object proc ::xotcl::cmd::proc
  ::xotcl::alias ::xotcl::Class instproc ::xotcl::cmd::instproc

The name of the method (3rd argument) can differ from the name of the
command (4th argument). Therefore, also the "alloc" method mentioned
above can be registered the same way under arbitrary names. The same
command can be registered under several names for different objects or
classes.

The command alias should not allow to register methods on ::oo::object
and ::oo::class. All end user object systems should only be allowed to
subclass (e.g. oo::object or ::xotcl::Object) and to register the
methods on their objects and classes.

The registered methods are defined with the standard signature for
TclCommands but receive in ClientData the object or class structure
(like in today XOTcl implementation). The handling for different
client data (as for example for XOTcl's forwarders) is provided in an
XOTcl style. C-extension writers can define non-leaf methods calling
"next" from the C level.

  Example:
  static int MyMethod1( ClientData cdata, Tcl_Interp *interp,
                         int objc, Tcl_Obj *CONST objv[] ) {
    int rc;
    /* ... */
    rc = XOTclNextObjCmd(cdata, interp, objc,objv);
    /* ... */
    return rc;
  }

The primitive commands (like my, next, self, configure, ...) can be
provided by the OO namespace (if there is sufficient agreement), or
can be provided by the extension writers (provided they have access to
obtain the needed information).


Advantages:

- 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 can 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
    * 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 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 continue to work
   * the XOTcl language definition is not part of the core, its development
     can continue
   * the XOTcl requirements are a superset of the requirements of other
     languages.
   * XOTcl can be executed with essentially the same speed as current
     versions.

- 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, at least in terms of flexibility.


Sample Implementation:

The actual snapshot of XOTcl is based on this framework using
::oo::object and ::oo::class as base object system. It contains
a preprocessor variable OO, that turns on the sub-classing of the base
object system (per default). The XOTcl C-Code does defines only
oo::object and oo::class, the XOTcl base objects are created already
by the scripting code.

Note, that this is a preview version of XOTcl and not suited for running
critical applications on it. It is passing the the first sets of the
regression tests but fails on the introspection regression tests (it
is not expecting to see e.g. ::oo::object as base class). It would be
possible to hide the base object system from the introspection, but i
am not sure this is a good idea. I am waiting for some feedback from
the community before either finishing the regression test or removing
the sub-classing of ::oo::object again.

Here is the snapshot code:
http://media.wu-wien.ac.at/download/xotcl-1.5.3-alpha.tar.gz

Below is the basic script level initialization for XOTcl, where the
classes ::xotcl::Object and ::xotcl::Class and their methods are
defined.

best regards
-gustaf neumann

===================================================
# $Id: predefined.xotcl,v 1.12 2006/10/04 20:40:23 neumann Exp $
if {[info command oo::object] ne ""} {
  ::xotcl::alias ::oo::class alloc ::xotcl::cmd::Class::alloc
  oo::class alloc ::xotcl::Object
  oo::class alloc ::xotcl::Class
  ::xotcl::setrelation ::xotcl::Class superclass {::oo::class
::xotcl::Object}
  ::xotcl::setrelation ::xotcl::Object class ::xotcl::Class
  ::xotcl::setrelation ::xotcl::Class class ::xotcl::Class
}

# provide the standard command set for ::xotcl::Object
foreach cmd [info command ::xotcl::cmd::Object::*] {
  ::xotcl::alias ::xotcl::Object [namespace tail $cmd] $cmd
}
# provide some Tcl-commands as methods for ::xotcl::Object
foreach cmd {array append eval incr lappend trace subst unset} {
  ::xotcl::alias ::xotcl::Object $cmd -objscope ::$cmd
}
# provide the standard command set for ::xotcl::Class
foreach cmd [info command ::xotcl::cmd::Class::*] {
  ::xotcl::alias ::xotcl::Class [namespace tail $cmd] $cmd
}
# "init" must exist on Object. per default it is empty.
::xotcl::Object instproc init args {}