Index: .gitignore =================================================================== diff -u -r2111020b49da8ce57758e51accf0b6073037f0d2 -re8715774bf274fbeadabf08a5a0777a968f71148 --- .gitignore (.../.gitignore) (revision 2111020b49da8ce57758e51accf0b6073037f0d2) +++ .gitignore (.../.gitignore) (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -4,6 +4,7 @@ config.* .gdb_history *-xotcl.html +xo-*.html xotclsh pkgIndex.tcl Makefile Index: Makefile.in =================================================================== diff -u -r8f2c993e02fe43f23c7e1653d05f6e298c23b2b2 -re8715774bf274fbeadabf08a5a0777a968f71148 --- Makefile.in (.../Makefile.in) (revision 8f2c993e02fe43f23c7e1653d05f6e298c23b2b2) +++ Makefile.in (.../Makefile.in) (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -36,6 +36,7 @@ # Requires native paths PLATFORM_DIR = `@CYGPATH@ $(srcdir)/@TEA_PLATFORM@` target_doc_dir = ./doc +xotcl_target_doc_dir = ./library/xotcl/doc src_lib_dir_native = `@CYGPATH@ ${src_lib_dir}` src_doc_dir_native = `@CYGPATH@ ${src_doc_dir}` @@ -237,13 +238,13 @@ fulldoc: doc pdf # use language reference as sample file to trigger generation of documentation files -doc: $(target_doc_dir)/langRef-xotcl.html +doc: $(xotcl_target_doc_dir)/langRef-xotcl.html -$(target_doc_dir)/langRef-xotcl.html: $(src_lib_dir)/xotcl/doc/langRef.xotcl $(XOTCL_DOC_SOURCE) +$(xotcl_target_doc_dir)/langRef-xotcl.html: $(src_lib_dir)/xotcl/doc/langRef.xotcl $(XOTCL_DOC_SOURCE) @docs=""; \ for i in $(XOTCL_DOC_SOURCE); do docs="$$docs `@CYGPATH@ $$i`"; done; \ $(TCLSH) $(src_lib_dir)/xotcl/library/lib/makeDoc.xotcl \ - $(target_doc_dir) $$docs + $(xotcl_target_doc_dir) $$docs pdf: -(cd $(src_doc_dir); htmldoc --webpage --format pdf14 --title \ @@ -514,7 +515,7 @@ clean: -rm -rf $(BINARIES) $(CLEANFILES) @NXSH@ @XOWISH@ pkgIndex.tcl ./receiver \ - $(target_doc_dir)/*-xotcl.html + $(xotcl_target_doc_dir)/*-xotcl.html find ${srcdir} -type f -name \*~ -exec rm \{} \; @if test ! "x$(subdirs)" = "x" ; then dirs="$(subdirs)" ; \ for dir in $$dirs ; do \ Index: TODO =================================================================== diff -u -r30173337f3b4d0d9c224713b2c86c622b26f3046 -re8715774bf274fbeadabf08a5a0777a968f71148 --- TODO (.../TODO) (revision 30173337f3b4d0d9c224713b2c86c622b26f3046) +++ TODO (.../TODO) (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -982,6 +982,11 @@ - updated migration guide, added section for callstack introspection - updated serializer for new names +- Introduced $xotcl_target_doc_dir for generated xotcl documentation. + Generate xotcl documentation in this directory. +- moved more (hopefully all) xotcl doc components into library/xotcl/doc + + TODO: - nameing * self/current: @@ -1071,8 +1076,9 @@ - "Objects" im left-bar irreführend, sollten eher "Classes" sein. Allerdings sollten auch objekte dukumentierbar sein -- doc-tools: was machen die argumenten von :? (bspw. ops?); ich nehme an, das ist work in progress. - sinnvoll wäre: [:?var obj varname body], da viele (die meisten) operationen auf anderen objeken ausgeführt werden +- doc-tools: was machen die argumente von :? (bspw. ops?); ich nehme an, das ist work in progress. + sinnvoll wäre: [:?var obj varname body], da viele (die meisten) operationen + auf anderen objeken ausgeführt werden - die Dokumentation der Objekt- und Klassenmethoden muss aus gentclapi weg und in predefined.tcl und xotcl2.tcl hineinwandern. Es werden nicht alle @@ -1098,8 +1104,14 @@ XO_o_cleanup_idx, XO_o_residualargs_idx, -- info method pararmetersyntax not defined for classical tcl procs (needed?) +- Either transfer documentation for xotcl from @-notation to new doc system, + or (maybe better) provide a renderer for @-structures to new doc system + infrastructure (less work). +- do we need templates (such as object.html.tmpl) in installed docs + (currently nx*/doc/NextLanguageCore/assets/) it is confusing, since changes + should be made to the templates in nx*/library/lib/doc-assets/. + - copy decls for objectMethod and classMethod as comments to xotcl.c, fix and check order Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-0.9.3'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-0.9.4'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.0'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.0.1'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.0.2'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.1.0'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.1.1'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.2.0'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.3.0'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.3.1'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.3.3'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.3.4'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.3.5'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.3.6'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.3.7'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.3.8'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.3.9'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.4.0'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.4.1'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.5.0'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.5.1'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.5.2'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.5.3'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.5.4'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.5.5'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.5.6'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.6.0'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.6.1'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.6.2'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/Announce-1.6.3'. Fisheye: No comparison available. Pass `N' to diff? Index: doc/cascaded-message-filter.gif =================================================================== diff -u -rc72f9f638677608fab1502cd696c8f2d6b2952f9 -re8715774bf274fbeadabf08a5a0777a968f71148 Binary files differ Index: doc/features.gif =================================================================== diff -u -rc72f9f638677608fab1502cd696c8f2d6b2952f9 -re8715774bf274fbeadabf08a5a0777a968f71148 Binary files differ Index: doc/filter-inheritance.gif =================================================================== diff -u -rc72f9f638677608fab1502cd696c8f2d6b2952f9 -re8715774bf274fbeadabf08a5a0777a968f71148 Binary files differ Index: doc/next-path-mixin-movement.gif =================================================================== diff -u -rc72f9f638677608fab1502cd696c8f2d6b2952f9 -re8715774bf274fbeadabf08a5a0777a968f71148 Binary files differ Index: doc/next-path.gif =================================================================== diff -u -rc72f9f638677608fab1502cd696c8f2d6b2952f9 -re8715774bf274fbeadabf08a5a0777a968f71148 Binary files differ Index: doc/obj_class_system.gif =================================================================== diff -u -rc72f9f638677608fab1502cd696c8f2d6b2952f9 -re8715774bf274fbeadabf08a5a0777a968f71148 Binary files differ Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/openacs-4/readme.txt'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/sample-source.xotcl'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/tutorial.html'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/xo-daemon.html'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/xo-whichPkg.html'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/xocomm-test.html'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `doc/xotcl-doc.css'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `library/serialize/RecoveryPoint.xotcl'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `library/serialize/ScriptCreator.xotcl'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e8715774bf274fbeadabf08a5a0777a968f71148 refers to a dead (removed) revision in file `library/serialize/Serializer.xotcl'. Fisheye: No comparison available. Pass `N' to diff? Index: library/xotcl/doc/Announce-0.9.3 =================================================================== diff -u --- library/xotcl/doc/Announce-0.9.3 (revision 0) +++ library/xotcl/doc/Announce-0.9.3 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,57 @@ +Announcing XOTcl 0.9.3 +********************** + +WHAT IS XOTCL? + + XOTcl is an object-oriented extension of Tcl that was derived from + OTcl. In short, XOTcl tries to provide a highly flexible, + reflective, component-based, and object-oriented environment. It + integrates language support for high level concepts which are not + found in other languages, with reasonable performance. It prevails + the Tcl programming style and the dynamic/introspective nature of + the language, rather than introducing other language's styles and + rigidness (such as C++) into Tcl. + + +RECENT CHANGES relative to 0.9 are: + + - A "more or less" TEA compliant build process and its + directory structure (aligend it as far as possible to Tcl, sample + extension and other extensions) + + * We started building an XOTcl stub lib. + + * We separated xotcl from its library/applications + (there is an xotcl- directory in the full distribution + that just builds, installs, etc. the XOTcl libraries ... this + can for instance be used in other distributions using and + shipping XOTcl, but not using the shells). + + * The full distribution still builds shells, but they are using + "package require" to load the XOTcl libraries now. + + * For building xowish (the XOTcl Tk shell) you do only require + an installed Tk version on Unix now. + + - On Windows we still use nmake due to problems with VCC 6.0 in + all TEA compliant extensions we have checked, but we use a + completely new build process (more or less one-to-one the + Unix build process). + + - A few minor bugfixes. + + - We have tested this release on platforms we have access to + (Linux, Win NT, Solaris). Please inform us, if there are some + problems on your platform so that we can eliminate them in future + releases. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + Index: library/xotcl/doc/Announce-0.9.4 =================================================================== diff -u --- library/xotcl/doc/Announce-0.9.4 (revision 0) +++ library/xotcl/doc/Announce-0.9.4 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,100 @@ +Announcing XOTcl 0.9.4 +********************** + +WHAT IS XOTCL? + + XOTcl is an object-oriented extension of Tcl that was derived from + OTcl. In short, XOTcl tries to provide a highly flexible, + reflective, component-based, and object-oriented environment. It + integrates language support for high level concepts which are not + found in other languages, with reasonable performance. It prevails + the Tcl programming style and the dynamic/introspective nature of + the language, rather than introducing other language's styles and + rigidness (such as C++) into Tcl. + + +CHANGES relative to 0.9.3 are: + + - fixes: + + * separate reference counting for XOTcl objects and classes + to avoid references from tcl_obj's internal representation + to freed memory + + * fixes for AOL-Server (many thanks to Zoran Vasiljevic for + that and for his great help during fixing the problems above) + + * improved portability: horrible macro substitution + bug, when USE_ALLOCA or USE_MALLOC was specified; these + are used for some platforms such as AIX + + * fixing path search for XOTcl library (bug was introduced in + 0.9.3 in connection with TEA compliance) + + * fixed a bug in copy/move (many thanks for Artur Trzewik + for reporting this) in connection with constructors + (constructors are not called automatically in copy/move + operations anymore) + + * various small fixes in libraries (e.g. HTTP support, + generation of pkgIndex-files, using "my", ...) + + - enhancements: + + * new global command "my": + one can use now: + + Class Counter -parameter {{n 0}} + Counter instproc ++ {} { my incr n } + Counter instproc print {} { puts "actual value: [my n]"} + + Counter c1 + c1 ++ + c1 print + + In earlier versions it was neccessary to use "[self]" + instead of "my". This change reduces the number of + special characters in XOTcl programs. + "[self]" will continue to be supported by XOTcl. + + * extended semantics of "new" + + a) Object new ... + b) Object new -childof ... + c) Object new -volatile ... + d) Object new -volatile -childof ... + + where (a) creates now "global" objects not in the global + namespace anymore, but in the ::xotcl namespace, (b) can + be used to create objects as child of other objects + (e.g. as children of the actual object [self]; the objects + are deleted, when the specified object is deleted). (c) + creates are "global" objects as in (a), but they are + deleted, when the scope of the current + tcl-proc/object-proc/instproc is left and (d) is a + combination of (b) and (c). + + - optimizations: + + * XOTcl is trying to keep Tcl_Objs of type tclCmdNameType + instead of converting it to XOTclObjectType agressively. + + * A patch for Tcl 8.4a3 is available from the XOTcl web site + for performance hungry applications to provide special + byte-code-support for xotcl, that yields for classical + benchmark programs up to 40%. This patch is not likely to + be integrated into the general Tcl core in the new or + distant future. + + For more details, please consult the ChangeLog + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + Index: library/xotcl/doc/Announce-1.0 =================================================================== diff -u --- library/xotcl/doc/Announce-1.0 (revision 0) +++ library/xotcl/doc/Announce-1.0 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,51 @@ +Announcing XOTcl 1.0 +******************** + +WHAT IS XOTCL? + + XOTcl is an object-oriented extension of Tcl that was derived from + OTcl. In short, XOTcl tries to provide a highly flexible, + reflective, component-based, and object-oriented environment. It + integrates language support for high level concepts which are not + found in other languages, with reasonable performance. It prevails + the Tcl programming style and the dynamic/introspective nature of + the language, rather than introducing other language's styles and + rigidness (such as C++) into Tcl. + + +CHANGES relative to 0.9.4 are: + + - fixes: + + * various small fixes for compilation with tcl8.4.* + + * fixed some more memory-leaks that showed up in connection + with multi-threading (many thanks to Zoran Vasiljevic for + his great help) + + * removed a few panics() by tcl errors (important for servers) + + * various small fixes in Httpd-code + + * fixes in filter-search mechanism + + * the general cleanup method __exitHandler (called on + interpreter exits and on thread exits) defined now + as a proc of Object + + - optimizations: + + * speedup during recreation of objects + + For more details, please consult the ChangeLog + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + Index: library/xotcl/doc/Announce-1.0.1 =================================================================== diff -u --- library/xotcl/doc/Announce-1.0.1 (revision 0) +++ library/xotcl/doc/Announce-1.0.1 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,57 @@ +Announcing XOTcl 1.0.1 +********************** + +WHAT IS XOTCL? + + XOTcl is an object-oriented extension of Tcl that was derived from + OTcl. In short, XOTcl tries to provide a highly flexible, + reflective, component-based, and object-oriented environment. It + integrates language support for high level concepts which are not + found in other languages, with reasonable performance. It prevails + the Tcl programming style and the dynamic/introspective nature of + the language, rather than introducing other language's styles and + rigidness (such as C++) into Tcl. + + +CHANGES relative to 1.0 are: + + - fixes: + + * fixed installation bug on windows (when installed on + drives different to c:) + + * fixes for aolserver 3.5.* + + * fix for "object info default arg var" in connection + with filters + + * Serializer handles filter guards now + + - new functionality and improvements: + + * improved recreate semantics, makes it easier to + overload recreation logic. + + * new method "noinit" to create objects without + calling the constructor + + - optimizations: + + * general speedup (10 to 15%) by using client data of + namespace instead of Tcl_AssocData for interpreter state + + * faster and more flexible Serializer + + + For more details, please consult the ChangeLog + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + Index: library/xotcl/doc/Announce-1.0.2 =================================================================== diff -u --- library/xotcl/doc/Announce-1.0.2 (revision 0) +++ library/xotcl/doc/Announce-1.0.2 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,76 @@ +Announcing XOTcl 1.0.2 +********************** + +WHAT IS XOTCL? + + XOTcl is an object-oriented extension of Tcl that was derived from + OTcl. In short, XOTcl tries to provide a highly flexible, + reflective, component-based, and object-oriented environment. It + integrates language support for high level concepts which are not + found in other languages, with reasonable performance. It prevails + the Tcl programming style and the dynamic/introspective nature of + the language, rather than introducing other language's styles and + rigidness (such as C++) into Tcl. + + +CHANGES relative to 1.0.1 are: + + - fixes: + + * fixes for copying/moving objects to same name + + * works out of the box with AOL-server 4.0 + (no patch for AOL-server needed) + + * various small fixes and code cleanup + + * new directory structure (no nested version numbers) + + * improved object and class serializer + + - new functionality and improvements: + + * new method "ismixin": Test whether the argument is a + mixin or instmixin of the object. + + * new method "hasclass": Test whether the argument is either + a mixin or instmixin of the object or if it is on the class + hierarchy of the object. This method combines the + functionalities of istype and ismixin. + + * arguments of configure methods can start now + with a leading "-" without ambiguity. In previous versions + + Class C -parameter {name counter} + C c1 -name -x -counter 123 + + the configuration of c1 was interpreted as follows + + method argc + name 0 + x 0 + counter 1 + + Starting with XOTcl 1.0.2 arguments can be protected + by putting it into a list: + + C c1 [list -name -x] -counter 123 + + which is interpreted as follows: + + method argc + name 1 + counter 1 + + For more details, please consult the ChangeLog + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + Index: library/xotcl/doc/Announce-1.1.0 =================================================================== diff -u --- library/xotcl/doc/Announce-1.1.0 (revision 0) +++ library/xotcl/doc/Announce-1.1.0 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,87 @@ +Announcing XOTcl 1.1.0 +********************** + +WHAT IS XOTCL? + + XOTcl is an object-oriented extension of Tcl that was derived from + OTcl. In short, XOTcl tries to provide a highly flexible, + reflective, component-based, and object-oriented environment. It + integrates language support for high level concepts which are not + found in other languages, with reasonable performance. It prevails + the Tcl programming style and the dynamic/introspective nature of + the language, rather than introducing other language's styles and + rigidness (such as C++) into Tcl. + + +CHANGES relative to 1.0.2 are: + + - New functionality and improvements: + + * Transitive instmixins (thanks to a suggestion of Neophytos Demetriou): + The new version supports a tree of mixins (mixins of mixins); + when a mixin-class X has instmixins Y registered, and X is + registered as instmixin for a class C, the mixin classes Y are + applied to C as well. + + * Conditional mixins (thanks to a suggestion of Neophytos Demetriou): + mixins and instmixins can have now guards similar to filters + that define when they should be applied + + * New composition strategy for (filter- and mixin-)guards: + when a guard is defined more than once for the same interceptor + the most specific guard is used, the others are overridden. + + * Creation of sub-objects via parameter: + XOTcl's parameter method supports now a switch named "-Class" + which can be used to create and configure sub-objects (see + tutorial for details) + + * New predefined method: __unknown + This method is called, whenever XOTcl references a class, + which is not defined yet (e.g.: Class C -superclass UNKNOWNCLASS) + This method is used for Zoran's wonderful ttrace package + (for aolserver and tcl-Threads) + + * Improved documentation: + - extended tutorial (Meta-Classes, Tk, ...) + - beautified tutorial (style files, distinction between + literals and placeholders, ...) + - fixed hundreds of typos + + * some speed improvements + + + - fixes: + + * New build system: + - per default no shells are built + - new configure switches eg. --with-xotclsh, -with-actiweb + --with-all + + * Fixes for https in connection with some versions of IE + + * Fixed a few issues with purify and mt (many thanks to Zoran!) + + * Fixes for proc-scoped variable in connections with mixins + + * Fixed passing of error codes from constructors + + * various small fixes and code cleanup + - with newer versions of autoconf + - various fixes for stubs + - improved build under windows + - starkit compliance (many thanks to MichaelL@frogware.com) + + + For more details, please consult the ChangeLog + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + Index: library/xotcl/doc/Announce-1.1.1 =================================================================== diff -u --- library/xotcl/doc/Announce-1.1.1 (revision 0) +++ library/xotcl/doc/Announce-1.1.1 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,52 @@ +Announcing XOTcl 1.1.1 +********************** + +WHAT IS XOTCL? + + XOTcl is an object-oriented extension of Tcl that was derived from + OTcl. In short, XOTcl tries to provide a highly flexible, + reflective, component-based, and object-oriented environment. It + integrates language support for high level concepts which are not + found in other languages, with reasonable performance. It prevails + the Tcl programming style and the dynamic/introspective nature of + the language, rather than introducing other language's styles and + rigidness (such as C++) into Tcl. + + +CHANGES relative to 1.1.0 are: + + - Improved portability + * for Mac OS X (many thanks to Daniel Steffen) + * freebsd 4.9 (many thanks to Marc Spitzer) + + - configure can run outside of xotcl-tree and + can install to a different directory. Example: + + % mkdir -p /tmp/xotcl/unix + % cd /tmp/xotcl/unix + % ~/xotcl-1.1.1/unix/configure --with-all + % make + % make test + % make install DESTDIR=/tmp + + - several fixes and improvements such as + * added option --with-tkinclude for configure + (only needed, when built with optional --with-xowish) + * made gdbm work when compiled with threads enabled + * fix for initialization of stubtables in gdbm + * fixes for HTTP support (return format of values in + HTTP OPTION command made windows explorer hang) + * easy provision for redirects in HTTP server + + For more details, please consult the ChangeLog + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + Index: library/xotcl/doc/Announce-1.2.0 =================================================================== diff -u --- library/xotcl/doc/Announce-1.2.0 (revision 0) +++ library/xotcl/doc/Announce-1.2.0 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,199 @@ +Announcing XOTcl 1.2.0 +********************** + +WHAT IS XOTCL? + + XOTcl is an object-oriented extension of Tcl that was derived from + OTcl. In short, XOTcl tries to provide a highly flexible, + reflective, component-based, and object-oriented environment. It + integrates language support for high level concepts which are not + found in other languages, with reasonable performance. It prevails + the Tcl programming style and the dynamic/introspective nature of + the language, rather than introducing other language's styles and + rigidness (such as C++) into Tcl. + + +CHANGES relative to 1.1.1 are: + + - Qualitative Improvements + * improved performance (up to more than 30% faster) + * reduced dependency on Tcl internals (stack rewritings removed) + * less C-code (code reduction of about 500 lines c code) + * defined macros to access Tcl's internal structures + Due to the speedup, an emulation of an itcl like language + in XOTcl can be faster than itcl itself (see below). + + - Functional Improvements + * new subcommands of self: + self callinglevel: returns the scope of the proc/instproc + calling the current method (ignoring filters and next) + self activelevel: returns the scope of the proc/instproc + preceding the current method (might be a next call, + ignoring filters) + the returned level can be used in uplevel/upvar as first argument + + * new methods upvar/uplevel + "my uplevel set x 1" is a short form of "uplevel [self callinglevel] set x 1" + + * sub-objects can be called like methods (potential incompatibility) + If an object named o has a sub-object q (i.e. o::q) it is now + possible to invoke the sub-object via "o q ?method args?". This change + makes it possible to + + - to redefine tcl sub-commands via procs/instprocs by defining + the command with subcommands as an object (instead of defining + a command as a proc and its subcommands via a large + and hard-to-refine switch statement) + + - to use the same approach for defining subcommands of subcommands + (and so on) in the same way; it would be possible to define e.g. + the xotcl info methods via an object), + + - to use interceptors (filters/mixins) for some or all subcommands (maybe you + are only interested in "file delete") + + - to extend a tcl command on the fly by defining new subcommands + (by defining new procs/instprocs) + + - to use the unknown mechanism to produce dynamic error messages + about valid subcommands (via introspection commands). + + As a simple example, one define the a specialized version of Tcl's + file-command (say ns::file) like the following: + + namespace eval ns { + Object file + file proc tail name { + set tail [file tail $name] + regexp {[^/\\]+$} $tail tail + return $tail + } + file proc unknown {subcmd args} { + return eval ::file $subcmd $args + } + } + + For more details, please consult the ChangeLog + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + +#======================================================================= +# extract from the logfile of oobench (in oo-bench.tar.gz, +# see http://media.wu-wien.ac.at/download.html) + +XOTcl + methcall: 0.470u 0.000s 0:00.41 114.6% 0+0k 0+0io 347pf+0w +ITcl emulation in XOTcl + methcall: 0.590u 0.000s 0:00.62 95.1% 0+0k 0+0io 351pf+0w +itcl + methcall: 0.870u 0.020s 0:00.92 96.7% 0+0k 0+0io 347pf+0w + + +#======================================================================= +package require XOTcl; namespace import -force xotcl::* + +########################################################### +## Small example to emulate a itcl-like language in XOTcl +## -gustaf neumann Jan. 2004 +########################################################### +namespace eval itcl { + Class create class -superclass Class + class instproc instvars {} { + set vars [list]; set c [self] + for {} {[string compare ::xotcl::Object $c]} {set c [$c info superclass]} { + eval lappend vars [$c set __autovars] + } + return "\n\tmy instvar [lsort -unique $vars]" + } + class proc constructor {args} { + if {[llength $args]==2} { + foreach {arglist body} $args break + } else { + foreach {arglist construct body} $args break + set body $construct\n$body + } + my parameter [list {this [self]}] + my proc constructor args {uplevel next $args} + my instproc init $arglist [my instvars]\n$body + } + class proc method {name arglist body} { + my proc $name args {uplevel next $args} + my instproc $name $arglist [my instvars]\n$body + } + class proc inherit {class} { + my superclass $class + } + class proc variable {arglist} { + foreach v $arglist {my lappend __autovars $v} + } + class instproc init {classdef} { + my set __autovars this + namespace eval [self class] $classdef + my class Class + } +} + +########################################################### +# Two Demo classes from oo-bench +########################################################### +itcl::class Toggle { + variable state + constructor {start_state} { + set state $start_state + } + method value {} { + return $state + } + + method activate {} { + set state [expr {!$state}] + return $this + } +} + +itcl::class NthToggle { + inherit Toggle + variable count_max + variable counter + constructor {start_state max_counter} { + Toggle::constructor $start_state + } { + set count_max $max_counter + set counter 0 + } + method activate {} { + if {[incr counter] >= $count_max} { + Toggle::activate + set counter 0 + } + return $this + } +} + + +proc main {} { + set n [lindex $::argv 0] + set val 1 + set toggle [Toggle t1 $val] + for {set i 0} {$i < $n} {incr i} { + set val [[$toggle activate] value] + } + if {$val} {puts "true"} else {puts "false"} + + set val 1 + set ntoggle [NthToggle t2 1 3] + for {set i 0} {$i < $n} {incr i} { + set val [[$ntoggle activate] value] + } + if {$val} {puts "true"} else {puts "false"} +} + +main Index: library/xotcl/doc/Announce-1.3.0 =================================================================== diff -u --- library/xotcl/doc/Announce-1.3.0 (revision 0) +++ library/xotcl/doc/Announce-1.3.0 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,76 @@ +Announcing XOTcl 1.3.0 +********************** + +WHAT IS XOTCL? + + XOTcl is an object-oriented extension of Tcl that was derived from + OTcl. In short, XOTcl tries to provide a highly flexible, + reflective, component-based, and object-oriented environment. It + integrates language support for high level concepts which are not + found in other languages, with reasonable performance. It prevails + the Tcl programming style and the dynamic/introspective nature of + the language, rather than introducing other language's styles and + rigidness (such as C++) into Tcl. + + +Major changes relative to 1.2.0 are: + + - Qualitative Improvements + * Improved portability: + + TEA3 compatible build + + Much more polished configure+makefile (many thanks to + Jim Lynch for his help) + + * Improved code quality: + + fixed 2 possible segmentation violations (error handling) + + fixed free memory reads (many thanks to Zoran Vasiljevic + for his help with purify) + + * Less intrusive usage of XOTcl components: + + XOTcl procs and instprocs use now the namespace in which + they were defined. One can use XOTcl packages without having + the need to import xotcl globally or to use the xotcl-prefix + in all xotcl procs/instprocs. + + - Functional Improvements + * New forwarding mechanisms for fast delegation: + new methods 'forward' and 'instforward' (many thanks + to Bryan Schofield for fruitful discussions and suggestions). + This method is a superset of tclcmd/insttclcmd, which has + been marked as deprecated. See the tutorial for more details. + + * Nonpositional arguments for xotcl procs/instprocs; this is + a flexible way to check arguments, to provide defaults etc + for every xotcl proc/instproc. It uses a similar syntax as + ad_proc and ad_page_contract in OACS. See the tutorial for + more details. + + * Extended methods filter, mixin, instfilter, instmixin as + discussed in the XOTcl mailing list. These commands can be + used more flexibly as follows + + obj mixin same as: obj info mixin + obj mixin {C1 C2} same as: obj mixin set {C1 C2} + obj mixin set {C1 C2} sets the mixins for obj + obj mixin get same as: obj info mixin + obj mixin add C3 adds a mixin on front of the mixin list + obj mixin add C3 end adds a mixin at the end the mixin list + obj mixin add C3 3 adds a mixin at the 3rd position + obj mixin delete ::C3 removes the mixin from the mixin list + + The same semantics are available as well for filter, instmixin + and instfilter. This change is fully backward compatible. + {filter,instfilter,mixin,instmixin}append are deprecated now. + + + For more details about the changes, please consult the ChangeLog and documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun Index: library/xotcl/doc/Announce-1.3.1 =================================================================== diff -u --- library/xotcl/doc/Announce-1.3.1 (revision 0) +++ library/xotcl/doc/Announce-1.3.1 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,13 @@ +Announcing XOTcl 1.3.1 +********************** + +This is a minor fix release relative to 1.3.0. This fixes a few +problems introduced in 1.3.0 (invocation of checking procs in +nonpositional argument) and has a better build support for building +XOTcl outside of the source tree, the tar files are now dist-cleaned. + + +Best regards, + +Gustaf Neumann +Uwe Zdun Index: library/xotcl/doc/Announce-1.3.3 =================================================================== diff -u --- library/xotcl/doc/Announce-1.3.3 (revision 0) +++ library/xotcl/doc/Announce-1.3.3 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,54 @@ +Announcing XOTcl 1.3.3 +********************** + +WHAT IS XOTCL? + + XOTcl is an object-oriented extension of Tcl that was derived from + OTcl. In short, XOTcl tries to provide a highly flexible, + reflective, component-based, and object-oriented environment. It + integrates language support for high level concepts which are not + found in other languages, with reasonable performance. It prevails + the Tcl programming style and the dynamic/introspective nature of + the language, rather than introducing other language's styles and + rigidness (such as C++) into Tcl. + + +Major changes relative to 1.3.1 are: + + - Qualitative Improvements + + * Improved code quality: + + fixed possible segmentation violations in free memory reads + (many thanks to Zoran Vasiljevic for his help with purify) + + fixed "self callinglevel" when uplevel was called from uplevel + + fixed nonposargs + + fixed configure in connection with enable-symbols and + for aolserver configuration + + extended regression test + + * Improved Functionality + + Producing error message when a non-existing proc/instproc + is tried to be deleted + + fixed exists method for objects with namespaces by using + a namespace resolver + + fixed return code for unknown handling in next + + reduced memory consumption for objects and classes with procs/instprocs + of about 14% + + * Improved Documentation + + + + For more details about the changes, please consult the ChangeLog and documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.3.4 =================================================================== diff -u --- library/xotcl/doc/Announce-1.3.4 (revision 0) +++ library/xotcl/doc/Announce-1.3.4 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,55 @@ +Announcing XOTcl 1.3.4 +********************** + +WHAT IS XOTCL? + + XOTcl is an object-oriented extension of Tcl that was derived from + OTcl. In short, XOTcl tries to provide a highly flexible, + reflective, component-based, and object-oriented environment. It + integrates language support for high level concepts which are not + found in other languages, with reasonable performance. It prevails + the Tcl programming style and the dynamic/introspective nature of + the language, rather than introducing other language's styles and + rigidness (such as C++) into Tcl. + + +Major changes relative to 1.3.3 are: + + - Qualitative Improvements + + * Improved code quality: + + fixed possible segmentation violations in free memory reads + (many thanks to Zoran Vasiljevic for his help with purify) + + fixed "self callinglevel" when uplevel was called from uplevel + + Improved portability (many thanks to Jeffrey Hobbs) + + fixed nonposargs + + fixed configure in connection with enable-symbols and + for aolserver configuration + + extended regression test + + * Improved Functionality + + Producing error message when a non-existing proc/instproc + is tried to be deleted + + fixed exists method for objects with namespaces by using + a namespace resolver + + fixed return code for unknown handling in next + + reduced memory consumption for objects and classes with procs/instprocs + of about 14% + + * Improved Documentation + + + + For more details about the changes, please consult the ChangeLog and documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.3.5 =================================================================== diff -u --- library/xotcl/doc/Announce-1.3.5 (revision 0) +++ library/xotcl/doc/Announce-1.3.5 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,62 @@ +Announcing XOTcl 1.3.5 +********************** + +WHAT IS XOTCL? + + XOTcl is an object-oriented extension of Tcl that was derived from + OTcl. In short, XOTcl tries to provide a highly flexible, + reflective, component-based, and object-oriented environment. It + integrates language support for high level concepts which are not + found in other languages, with reasonable performance. It prevails + the Tcl programming style and the dynamic/introspective nature of + the language, rather than introducing other language's styles and + rigidness (such as C++) into Tcl. + + +Major changes relative to 1.3.4 are: + + - Qualitative Improvements + + * Improved code quality: + + fixed possible segmentation violations in non positional + argument handling + + moved the Serializer into a namespace such that + % package req XOTcl + % package req xotcl::serializer + Serialize .... + works without namespace imports (the Serializer is + still auto-exported, but this will change in the future) + + + + * Improved Functionality + + Non-positional arguments can be used in the same argument + list as positional ones (more compliant with OpenACS). + One can write now + % Object o + % o proc foo {-x:boolean -y a b} { ...} + instead of + % ... + % o proc foo {-x:boolean -y} {a b} { ...} + All introspection commands will work like before. + The old syntax (with the additional argument) is deprecated + and will be dropped in the future. + + + Serializer: support for objects with parent namespaces, which are + not xotcl objects + + + additional instproc for ::xotcl::Class allinstances + to return all instances for the actual class + + For more details about the changes, please consult the ChangeLog and documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.3.6 =================================================================== diff -u --- library/xotcl/doc/Announce-1.3.6 (revision 0) +++ library/xotcl/doc/Announce-1.3.6 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,61 @@ +Announcing XOTcl 1.3.6 +********************** + +WHAT IS XOTCL? + + XOTcl is an object-oriented extension of Tcl that was derived from + OTcl. In short, XOTcl tries to provide a highly flexible, + reflective, component-based, and object-oriented environment. It + integrates language support for high level concepts which are not + found in other languages, with reasonable performance. It prevails + the Tcl programming style and the dynamic/introspective nature of + the language, rather than introducing other language's styles and + rigidness (such as C++) into Tcl. + + +Major changes relative to 1.3.5 are: + + * Improved Functionality + + new info subcommand: info precedence + + + simplified meta class definitions: every class can be + changed into a metaclass by adding an instmixin of Class (or + one of its subclasses) to it. In order to define that every + class should be a metaclass, one can use now + Object instmixin Class + instead of the rather complicated solution i posted on + the xotcl mailing list not long ago. + + * Improved code quality: + + fixed possible crashes when + - objects are called with class methods (e.g. due to instmixins) + - when instmixins are defined recursively + (e.g. Class instmixin Class) + - objects are turned into classes by changing the + class relationship + + improved namespace resolution when mixin classes are defined + in namespaces (::xotcl:: namespace is skipped, since a + helper method that calles the primitive setting command + is defined there) + + fixed passing of error code from init methods + (thanks to Fabrice Pardo for noting it) + + returning PACKAGE_VERSION after a package require + (e.g. 'package req XOTcl' returns now 1.3.6) + + some code refactoring, fixed erroneous documentation of c code + + improved documentation + + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.3.7 =================================================================== diff -u --- library/xotcl/doc/Announce-1.3.7 (revision 0) +++ library/xotcl/doc/Announce-1.3.7 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,65 @@ +Announcing XOTcl 1.3.7 +************************* + +I am pleased to annouce XOTcl 1.3.7. +Major changes relative to 1.3.6 are: + + * Improved Functionality + + new option "switch" for non positional arguments to be used + to toggle the default value. A switch is a non positional argument + without extra argument. + + new option "isnextcall" for self + + new command "::xotcl::configure filter on|off" to turn off filters. + needed for serializing objects/classes with active filters + + several improvements for serializer to handle e.g. application + methods on Object/Class (needed for ad_instproc in oacs) + + improving namespace resolving in for object/class references + + moving all library packages into namespaces + + preventing "new" from overwriting objects + + allow xotcl to be used in slave interpreters + + + * Improved code quality: + + fixed namespace confusion in forward to expression calling + xotcl methods + + fixed possible crash in instvar when empty variable names are used + + some code cleanup + + improved documentation + + * new method "method" for defining methods (experimental): + Instead of using e.g. + + Object o1 + Class C + + o proc m1 {} {....} + C instproc m2 {} {....} + C proc m3 {} {....} + + one can use now + + o method m1 {} {....} + C method m2 {} {....} + C method -per-object m3 {} {....} + + in general, we can support options for method definitions, which + can be used as well for mixins, filters or info (instead of the + "inst" prefix). This way the problem of finding appropriate names for + distinguishing between object or class matters can be solved, + in rather rare cases (when referring the to class object) "-per-object" + can be used. The according name changes will happen in xotcl 2.0. + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.3.8 =================================================================== diff -u --- library/xotcl/doc/Announce-1.3.8 (revision 0) +++ library/xotcl/doc/Announce-1.3.8 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,67 @@ +Announcing XOTcl 1.3.8 +************************* + +I am pleased to annouce XOTcl 1.3.8 +Major changes relative to 1.3.6 are: + + * Improved Functionality + + new option "switch" for non positional arguments to be used + to toggle the default value. A switch is a non positional argument + without extra argument. + + new option "isnextcall" for self + + new command "::xotcl::configure filter on|off" to turn off filters. + needed for serializing objects/classes with active filters + + several improvements for serializer to handle e.g. application + methods on Object/Class (needed for ad_instproc in oacs) + + improving namespace resolving in for object/class references + + moving all library packages into namespaces + + preventing "new" from overwriting objects + + allow xotcl to be used in slave interpreters + + + * Improved code quality: + + fixed namespace confusion in forward to expression calling + xotcl methods + + fixed possible memory leak with instmixins + + fixed possible crash in instvar when empty variable names are used + + fixed namespace related bug in __unknown resolver hook + + some code cleanup + + improved documentation + + * new method "method" for defining methods (experimental): + Instead of using e.g. + + Object o1 + Class C + + o proc m1 {} {....} + C instproc m2 {} {....} + C proc m3 {} {....} + + one can use now + + o method m1 {} {....} + C method m2 {} {....} + C method -per-object m3 {} {....} + + in general, we can support options for method definitions, which + can be used as well for mixins, filters or info (instead of the + "inst" prefix). This way the problem of finding appropriate names for + distinguishing between object or class matters can be solved, + in rather rare cases (when referring the to class object) "-per-object" + can be used. The according name changes will happen in xotcl 2.0. + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.3.9 =================================================================== diff -u --- library/xotcl/doc/Announce-1.3.9 (revision 0) +++ library/xotcl/doc/Announce-1.3.9 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,41 @@ +Announcing XOTcl 1.3.9 +************************* + +Hi everybody. I am pleased to annouce the availability of XOTcl 1.3.9. +Major changes relative to 1.3.8 are: + + * Improved Functionality + + new subcommand for self: [self args] return the full argument list + of the current call + + " info vars" does not trigger read traces on each variable anymore + + Serializer: exportMethods accepts forwards/instforwards now + as well + + new switch -nocomplain for "mixin|instmixin|filter|instfilter delete" + to avoid error messages when deleting entries not there (similar unset) + + require automatically a namespace when a childobject is added + + new command ::xotcl::__qualify: convert an relative name + into an command name (exactly as create does it, ignoring + namespaces from transparent interceptors) + + * Improved code quality: + + fixing version numbers for package require + + Upgraded TEA to 3.4 + + updated rpm build (many thanks to Ildiko Schmidt and Alexander Bergolth) + + fixed bug with error propagation when getter/setter methods are + used for parameters (many thanks to Manfred Stelzhammer for + pointing this out) + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.4.0 =================================================================== diff -u --- library/xotcl/doc/Announce-1.4.0 (revision 0) +++ library/xotcl/doc/Announce-1.4.0 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,42 @@ +Announcing XOTcl 1.4.0 +************************* + +Hi everybody. I am pleased to annouce the availability of XOTcl 1.4.0. +Major changes relative to 1.3.9 are: + + * Improved Functionality + * new option: ::xotcl::configure softrecreate on|off + if softrecreate is set, class relations (superclass, subclass, class, instances) + are not affected by a recreate; this allows files with class definitions + more easily to reload + + easier syntax for providing commands for initializing default values + + setting and querying options for ::xotcl::configure simiar to set + + * Improved code quality: + + fixed a bug in connection with nonpositional arguments and "args" + + fixed a bug with adding on the fly transitive mixin classes + + fixed a bug with filter states after next + + fixed omitted error message after calling self with unknown subcommands + + fixed a bug with variable traces on thread exit (triggered by volatile) + + fixed incorrect rpm dependencies + + cleaner compile for xotcl for gcc 4.* under linux + + don't destroy namespace imported child objects + + info children returns true children, not namespace imported objects/classes + + unsetting the global variable "cmd" from predefined.xotcl + + Upgraded TEA to 3.5 + + more regression tests addeed + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.4.1 =================================================================== diff -u --- library/xotcl/doc/Announce-1.4.1 (revision 0) +++ library/xotcl/doc/Announce-1.4.1 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,207 @@ +Announcing XOTcl 1.5.0 +************************* + +Hi everybody. I am pleased to announce the availability of XOTcl 1.5.0. +Major changes relative to 1.4.0 are: + + * Improved Functionality + + + The C-level implementation of XOTcl create now the basic + classes ::xotcl::Object and ::xotcl::Class completely without + any methods. All predefined methods are now registered + from the initialization script-code (predefined.xotcl) + via the new command + + ::xotcl::alias | \ + ?-objscope? ?-per-object? + + which is used for registering predefined Tcl commands + as methods. These aliases are like zero cost forwarders, + since they lookup the function pointer from the commands + and used these in the methods. + + This change makes it possible to register the same command + on different classes (with maybe different names), such that + for example the predefined set method of ::xotcl::Object + can be replaced with a different method and the set method + can be registered on some other classes (maybe some + application classes). This change makes it as well quite + easy to use the XOTcl framework to develop some other + object oriented frameworks. + + + slots + TODO documentation of slots + TODO remove + TODO optimize via parametercmd + TODO parametercmd with 3+ args + TODO info parameter deprecated + + A slot is a meta-object that manages property-changes of + objects. A property is either an attribute or a role of an relation. + In a nutshell, a slot has among other attributes + - a name (which it used to access it), + - a domain (object or class on which it can be used) , and + - can be multivalued or not + We distinguish between system slots (predefined slots like + class, superclass, mixin, instmixin, filter, instfilter) and + application slots (e.g. attributes of classes). + + System Slots + ======== + + System slots are predefined slots defining e.g. some relations + between classes, or between objects and classes. + + The predefined system slots are: + - superclass: every class in XOTcl has one or more superclasses. + The name of this slot is "superclass", the domain is "::xotcl::Class", + the slot is multivalued. One object might have multiple superclasses. + - class: every object has a class; therefore, the domain of the slot + is "::xotcl::Class", the property is not multivalued. + - mixin: every object in XOTcl can have one or more mixin classes. + The name of this slot is "mixin", the domain is "::xotcl::Object", the slot is + multivalued. + - instmixin: same as above, but the domain is "::xotcl::Class" + - filter, instfilter: similar to "mixin" and "instmixin" + + Every slot can be used set and query the property from its domain. + The syntax for setting values is + newValue + replace newValue + and for getting its values is + set x [ ] +TODO "mixin set" -> "mixin assign" +TODO "mixin set" -> "mixin replace" +TODO "mixin set" -> "mixin reset" +TODO "mixin delete" -> "mixin remove" + where the first form is in both cases the short form of the second one. + Every multivalued slot has as well a method "add" and "remove" + + Examples for using the system slot "mixin" + + Object o; Class M; class N + o mixin ::M ;# replacing the per-object mixins of o with M + o mixin reset ::M ;# same as before + o mixin add ::N ;# add N to the front of the mixin list + o mixin delete ::M ;# delete M from the mixin list + puts [o mixin] ;# query the current mixin list + + Every system slot (e.g. superclass) has the exact same interface. + + + Attribute Slots + ========= + + Attribute slots are used to manage the setting and querying + of instance variables. We define now a person with three + attributes,"name", "salary" and "projects". + + Class Person -slots { + Attribute name + Attribute salary -default 0 + Attribute projects -default {} -multivalued true + } + + These attributes might have a default value or they might be + multivalued. When an instance of class Person is created, the + slot names can be used for specifying values for the slots. + + Person p1 -name "Joe" + + Object p1 has three instance variables, namely "name", + "salary" and "projects". Since slot "projects" is multivalued, + we can add values the "add" subcommand. + + Project project1 -name XOTcl \ + -description "A highly flexible OO scripting language" + + p1 projects add ::project1 + p1 projects add some-other-value + + The value of the instance variable "project" of Person p1 + is now the list "some-other-value ::project1" + + + Type Checking + ========= + + Attribute slots can have types assigned which are tested + whenever the instance variable is altered. The slot "salary" + is defined as integer whereas "projects" is defined to + be a list of instances of the class Project (a list, since + "projects" is defined as multivalued). + + Class Person -slots { + Attribute name + Attribute salary -default 0 -type integer + Attribute projects -default {} -multivalued true -type ::Project + } + + Person p2 -name "Sue" -salary 1000 + + The slot types are checked via Tcl variable traces. This means + that the values are enforced now matter how the variables + are accessed. The checks are performed in the following + two commands, and they will throw an error in the second + command, since "1100x" is not an integer. + + p2 incr salary 100 + p2 append salary x + + similarly the second command below will through + an error, since some-other-value is not an instance + of ::Project. + + p2 projects add ::project1 + p2 projects add some-other-value + + When a check throws an error, the instance variables + are reset to the previous value. To restore the original + value, an associative array "__oldvalue()" is kept as + instance variable in the object. + + In general, checking of variables can be turned off globally + by "::xotcl::Slot instmixin add ::xotcl::Slot::Nocheck". + It can be turned off selectively for each slot via + a per-object-mixin; if attributes are subclassed, + it is possible to register the "Nocheck" mixin on a + subclass of Attribute. + + procsearch returns for forwarders now "forward" or "instforward", + for parametercmds now "parametercmd" or "instparametercmd" + and for other commands "cmd" and "instcmd" + +info slots +TODO slow -superclass +TODO king of the bongo + + + improved forwarding ... expr earlybinding + %argclindex + + + improved serializer + - handling of slot dependencies + - + - + + * Improved code quality: + + fixed a bug with nonpositional arguments, some + positional arguments and "args" + + fixed a bug in nonpositional arguments when called without + arguments + + improved error messages in connection with nonpositional arguments + + more regression tests added + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.5.0 =================================================================== diff -u --- library/xotcl/doc/Announce-1.5.0 (revision 0) +++ library/xotcl/doc/Announce-1.5.0 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,232 @@ +Announcing XOTcl 1.5.0 +************************* + +Hi everybody. We are pleased to announce the availability of XOTcl 1.5.0. +Major changes relative to 1.4.0 are: + + * Improved Functionality + + + The C-level implementation of XOTcl creates now the basic + classes ::xotcl::Object and ::xotcl::Class completely without + any methods. All predefined methods are now registered from + the initialization script-code (predefined.xotcl) via the new + command + + ::xotcl::alias | \ + ?-objscope? ?-per-object? + + which is used for registering predefined Tcl commands as + methods. These aliases are like zero cost forwarders, since + they lookup the function pointer from the commands and used + these in the methods. + + This change makes it possible to register the same command + on different classes (with maybe different names), such that + for example the predefined set method of ::xotcl::Object can + be replaced with a different method and the set method can + be registered on some other classes (maybe some application + classes). + + This change makes it as well quite easy to develop some + other object oriented languages based on the XOTcl + framework, since all methods can be rearrange from the Tcl + layer . + + + + Slots + + A slot is a meta-object that manages property-changes of + objects. A property is either an attribute or a role of an + relation. + + In a nutshell, a slot has among other attributes + - a name (which it used to access it), + - a domain (object or class on which it can be used) , and + - can be multivalued or not + + Every slot defines a uniform interface to access its + content. So has for example, every multivalued slot a + method "add" to add a value to the list of values and a + method "remove" to remove it again. + + We distinguish between system slots (predefined slots like + class, superclass, mixin, instmixin, filter, instfilter) and + application slots (e.g. attributes of classes). + + System Slots + ======== + + System slots are predefined slots defining e.g. some relations + between classes, or between objects and classes. + + The predefined system slots are: + - superclass: every class in XOTcl has one or more superclasses. + The name of this slot is "superclass", the domain is "::xotcl::Class", + the slot is multivalued. One object might have multiple superclasses. + - class: every object has a class; therefore, the domain of the slot + is "::xotcl::Class", the property is not multivalued. + - mixin: every object in XOTcl can have one or more mixin classes. + The name of this slot is "mixin", the domain is "::xotcl::Object", the slot is + multivalued. + - instmixin: same as above, but the domain is "::xotcl::Class" + - filter, instfilter: similar to "mixin" and "instmixin" + + Every slot can be used set and query the property from its domain. + The syntax for setting values is + newValue + and for getting its values is + set x [ ] + + Every multivalued slot has as well a method "add" and "remove" + + Examples for using the system slot "mixin" + + Object o; Class M; class N + o mixin ::M ;# replacing the per-object mixins of o with M + o mixin add ::N ;# add N to the front of the mixin list + o mixin delete ::M ;# delete M from the mixin list + puts [o mixin] ;# query the current mixin list + + + Attribute Slots + ========= + + Attribute slots are used to manage the setting and querying + of instance variables. We define now a person with three + attributes,"name", "salary" and "projects". + + Class Person -slots { + Attribute name + Attribute salary -default 0 + Attribute projects -default {} -multivalued true + } + + Examples for using the slots are + + Person p1 -name "Joe" + p1 projects add project1 + + Some additional features of the slots are: + + - Support for value checking for + * primitive types (all types from "string is", like integer, + boolean, ...) + * instances of Classes (e.g. value must be an instance + of Person) + * custom value checkers + * uniform interface for single and multi-valued slots + + - Support for lazy initialization (e.g. when costly + commands (like SQL) are used to initialize instance + variables, not all variables are used for each object) + + - more experimental low level functionality, like + * initcmd (executed, whenever the variable is read the first time) + * valuecmd (executed, whenever the variable is read) + * valuechangedcmd (executed, whenever the variable is altered) + + For more details, see http://media.wu-wien.ac.at/doc/tutorial.html#slots + + + + Re-implementation of the method "parameter" based on slots. + All forms except + ... -parameter {name1 {name2 default2}} ... + (I.e. pure accessor parameters and parameters with + defaults) are deprecated, since slots are the much more + powerful and orthogonal construct. + + The old c-based parameter support based on "parameterclass" + is deprecated. It is still in the C-code (the method "parameter" + is redefined in predefined.xotcl). If someone urgently needs + it, please remove the parameter instproc from predefined + for the time being, and write an email to me, in case + you really need it). The C code for parameter will be removed + in the next release. + + + Improved introspection though the procsearch method. This + method reports now in its second argument not only + [inst]proc but as well [inst]forward, [inst]parametercmd + and [inst]cmd (the latter for methods implemented in C. + + * Improved introspection through "info" + - new subcommand "info slots" + - implemented backwards bug-compatible "info parameter", + deprecated + + + Improved serializer + - better handling of cyclical dependencies, when mixins are involved + - fix for namespace handling to make the XOTcl communication + library classes working with the aolserver (thanks for Stefan Sobernig + for pointing this out) + - Now other ::xotcl::* objects can be included in the aolserver blueprint + (e.g. non positional argument handlers) + - handling of slot dependencies + - more convenient calling of the serializer: + Method "serialize" for Object is defined when the package xotcl::serializer + is loaded. + + + Improved forwarding commands + - New option for the argument substitution. When the argument + list of the forward command contains "%argclindex {a b c}", then + depending of the number of arguments at invocation "a", "b" + or "c" is substituted. If more arguments are used at the invocation + of the forwarder than values are contained in the list after %argclindex, + an error is generated. + - New options for forwarder: + * The option -earlybinding can be used to look + up the function pointer of the called Tcl command at + definition time of the forwarder instead of invocation time. + This option should only be used for calling C-implemented Tcl commands) + * The option -verbose prints the substituted command in the forwarder + prior to invocation. + + + New snit-like utility functions: + - ::xotcl::myvar varName: return the fully qualified variable name + of the specified variable. + - ::xotcl::myproc methodName ?args?: call an xotcl method without the need + of using "[list [self] methodName ...]" + Both commands are namespace exported + + + added "subst" to the set of Tcl imported methods (like e.g. incr, append, ...) + On can do now: + % Object o + ::o + % o subst {I am [self]} + I am ::o + + + added new method for ::xotcl::Object named "contains": + This method is essentially a value added back-port + of the OpenACS version. It allows to create a nested + object structure with little syntactic overhead. See tutorial + or language reference for more details. + + * Improved code quality: + + fixed a bug with nonpositional arguments, some + positional arguments and "args" + + fixed a bug in nonpositional arguments when called without + arguments + + tested with Tcl 8.4.13 and 8.5a4 + + improved error messages in connection with nonpositional arguments + + fixed a bug in the xotcl trace module (many thanks to jima for reporting) + + fixed a namespace bug in ::xotcl::package require in connection with xotclide + (many thanks to Bill Paulsen and Artur Trzewik for identifying the problem and + suggesting a fix) + + improved documentation (e.g. new sections added, + some sections deleted, spelling improved, in total 8 pages longer) + + fixed documentation bugs (many thanks for Kristoffer for reporting) + + more regression tests added + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.5.1 =================================================================== diff -u --- library/xotcl/doc/Announce-1.5.1 (revision 0) +++ library/xotcl/doc/Announce-1.5.1 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,67 @@ +Announcing XOTcl 1.5.1 +************************* + +Hi everybody. We are pleased to announce the availability of XOTcl 1.5.1. +Major changes relative to 1.5.0 are: + + * Improved Functionality + + + Improved interface to develop XOTcl methods in C + (Many thanks to Scott Gargash for the constructive discussions + and suggestions). + + New functions imported through the XOTcl's stub interface: + - XOTclNextCmd() + - XOTclCallMethodWithArgs + + New constant XOTCL_NONLEAF_METHOD to allow C-implemented + methods to call next. This constant can be passed as 5th + argument to XOTclAddIMethod (or ...AddPMethod). The + following is a short example for defining and registering + a C-implemented constructor "init" to a class. + + static int MyClassInit( ClientData cdata, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[] ) { + int rc; + /*** before next ***/ + rc = XOTclNextObjCmd(cdata, interp, objc,objv); + /*** after next ***/ + return rc; + } + ... + MyClass = XOTclGetClass(interp, "MyClass" ); + XOTclAddIMethod(interp, MyClass, "init", MyClassInit, + XOTCL_NONLEAF_METHOD, 0 ); + + + * Improved code quality: + + fixed a bug with the backward-compatible and deprecated + "setter" interface (many thanks to Manfred Stelzhammer for + reporting the bug) + + fixed a bug in parsing nonpositional arguments, when + e.g. square brackets are used in type declarations for + parameters (Many thanks to Stefan Sobernig for reporting) + + fixed autoname crash under Windows NT (Many thanks to Mark + Janssen for reporting and providing a patch) + + fixed serializer to handle deeper stratification layers + + simplification and speedup of dispatcher + + Makefile.in improvements for genstubs + + Changed "test -e" to "test -f" in Makefile.in, since the + standard test command in Solaris does not understand + "test -e" (Many thanks to Andreas Kupries for reporting) + + improved 64-bit compatibility on POWER5+ + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.5.2 =================================================================== diff -u --- library/xotcl/doc/Announce-1.5.2 (revision 0) +++ library/xotcl/doc/Announce-1.5.2 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,37 @@ +Announcing XOTcl 1.5.2 +************************* + +Hi everybody. We are pleased to announce the availability of XOTcl 1.5.2. +Major changes relative to 1.5.2 are: + + * Improved Functionality + + + allowing to trace objects as well as classes via the + package xotcl::trace (many thanks to jima for suggesting this) + + * Improved code quality: + + terminating all vararg lists in C by ..., (char *) NULL + There was a problem with this on 64bit AMD on FreeBSD, + as some lists were terminated previously by an integer typed + zero-value. + + better handling of Tcl result objects. Make sure that + no changes happen on shared objects. Removed all + occurrences of Tcl_AppendResult() from xotcl.c + + Fixed memory corruption (accessing feed memory) in + the invalidation of transitive mixins (many thanks to + Don Porter for reporting) + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.5.3 =================================================================== diff -u --- library/xotcl/doc/Announce-1.5.3 (revision 0) +++ library/xotcl/doc/Announce-1.5.3 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,38 @@ +Announcing XOTcl 1.5.3 +************************* + +Hi everybody. We are pleased to announce the availability of XOTcl 1.5.3. +Major changes relative to 1.5.2 are: + + * Improved code quality: + + + provided compatibility with Tcl 8.5 + + + provided compatibility with Tcl 8.4.14 + + (fixed a nasty bug caused by a change in tcl 8.4.14, could + led to a crash due to freed Tcl_Objs in OpenACS, allthough + the xotcl regression test passed correctly) + + + reduced calling overhead of methods with nonpositional + arguments by about 10 percent by avoiding shimmering. + + + fixed handling of "return -code break" from xotcl methods + (thanks to Artur Trzewik for the bug report) + + + library/comm/Access.xotcl: fixed handling of chunked encoding + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.5.4 =================================================================== diff -u --- library/xotcl/doc/Announce-1.5.4 (revision 0) +++ library/xotcl/doc/Announce-1.5.4 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,46 @@ +Announcing XOTcl 1.5.4 +************************* + +Hi everybody. We are pleased to announce the availability of XOTcl 1.5.4. +Originally, this release was planned as a small bug fix release. However, +the total size of the (unified) diff between 1.5.3 and 1.5.4 is more +than 5000 lines, mostly due to the varRefom changes (see first +item below). + +Major changes relative to 1.5.4 are: + + * Improved code quality: + + + provided compatibility with Tcl 8.5 + (currently, this requires the verison of Tcl 8.5 + from CVS head, including the changes for VarReform + (For details, see http://groups.google.at/group/comp.lang.tcl/browse_frm/thread/bff391a7f1bd8f6c/3f214d088a28ed13?hl=de#3f214d088a28ed13) + + + improved serializer + (handling var traces for instances variables) + + + several small bug-fixes + (e.g. fixing empty variable names, error message + propagation for configure, fixing potential crashes, + when namespaces are added to objects during + eval, etc.) + + + improved portablility for more platforms + (more portable shell tests for e.g. FreeBSD) + + + extended regression test + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + + +Best regards, + +Gustaf Neumann +Uwe Zdun + + Index: library/xotcl/doc/Announce-1.5.5 =================================================================== diff -u --- library/xotcl/doc/Announce-1.5.5 (revision 0) +++ library/xotcl/doc/Announce-1.5.5 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,44 @@ +Dear XOTcl Community, + +XOTcl 1.5.5 is available. The main change is to achieve binary compatibility +between Tcl 8.5 and XOTcl compiled with Tcl 8.4. This is essential achieved +through a small emulation layer based on C-structures that will be available +in Tcl 8.5. + +best regards +-gustaf neumann + +Announcing XOTcl 1.5.5 +************************* + +We are pleased to announce the availability of XOTcl 1.5.5. + +Major changes relative to 1.5.4 are: + + * Improved binary compatibility: + + It is now possible to load XOTcl compiled for Tcl 8.4 + into a tclsh8.5 (again, substantial change). + + One can now test now 4 versions: + a) a native version for Tcl 8.4 (without compatibility layer) + b) a native version for Tcl 8.5 + c) a version compiled for Tcl 8.4 with compatibility layer in tclsh8.4 + d) a version compiled for Tcl 8.4 with compatibility layer in tclsh8.5 + + Tests showed that the overhead is for the compatibility + layer is between 1.1% and 2.3%, the difference between + tcl8.5 and tcl8.4 is much larger. + + The forward compatibility behavior behavior can be turned off by setting + FORWARD_COMPATIBLE to 0 during compilation (xotcl.h) to get + a small performance improvement. + + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + Index: library/xotcl/doc/Announce-1.5.6 =================================================================== diff -u --- library/xotcl/doc/Announce-1.5.6 (revision 0) +++ library/xotcl/doc/Announce-1.5.6 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,51 @@ +Dear XOTcl Community, + +XOTcl 1.5.6 is available. This version is mostly a fix release for +some problems that were apparently quite long in the code and could +cause crashes for threaded applications. + +best regards +-gustaf neumann + +Announcing XOTcl 1.5.6 +************************* + +We are pleased to announce the availability of XOTcl 1.5.6. + +Major changes relative to 1.5.4 are: + + * Fixes for treating global volatile objects (many thanks to Zoran + for his concise reports). The problem was that XOTcl uses + C-level var traces containing object pointers to objects. + If for some reason, these objects are destroyed earlier, this + results in dangling references. This problem caused especially + problems in the automatic cleanup of variables at the end + of a thread. + + * Fix for Tcl 8.4.* for situations, where Tcl variables + contained references to deleted XOTcl objects. The problem + was introduced by the VarReform changes between 1.5.3 and + 1.5.4 by a bad side effect of a Tcl_Obj based command + to look up Tcl command structurs. The problem did not + exist for xotcl compiled against Tcl 8.5 and is as well + fixed on the Tcl side in CVS (might become available, + when one more Tcl 8.4 release is eventually released) + + * Serializer: + - Added dependency rule in serializer to ensure slots of + super-classes are listed before subclasses. (Thanks to Stefan + Sobernig for reporting the problem) + + - Moved deactivation of traces into "Serializer all" + to get simpler results on "o serialize". + + * Extended regression tests + + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + Index: library/xotcl/doc/Announce-1.6.0 =================================================================== diff -u --- library/xotcl/doc/Announce-1.6.0 (revision 0) +++ library/xotcl/doc/Announce-1.6.0 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,105 @@ +Dear XOTcl Community, + +XOTcl 1.6.0 is available. This release provides in short: + - orthogonality improvements for introspection, + - more introspection methods (one can now e.g. query, into which + classes a mixin class is mixed into) and + - performance improvements (some methods are significantly + faster. e.g. by a factor of 1000 for larger systems). + +In addition, the XOTcl source code follows now closer the Tcl +source code guidelines (e.g. variable naming), a few potential +crashes have been fixed. + +See below for more details. +Best regards + +-gustaf neumann + +Announcing XOTcl 1.6.0 +************************* + +We are pleased to announce the availability of XOTcl 1.6.0. + +Major changes relative to 1.5.6 are: + + * Provide a uniform interface to the following info subcommands + + info superclass ?-closure? ?pattern? + info subclass ?-closure? ?pattern? + info instances ?-closure? ?pattern? + info instmixin ?-closure? ?pattern? + + The new option "-closure" returns the transitive set of the + relation (e.g. .. info subclass -closure) returns the subclasses + and the subclasses of the subclasses. For "info instances + -closure" the instances of the subclasses are returned as + well. For more details, please see the language reference manual. + + In cases, where a pattern is specified, and the pattern contains + meta-characters, a list of results is returned matching the + pattern (like "string match"). When no matching value is found, + an empty list is returned. + + In cases, where a pattern is specified, and the pattern contains + no meta-characters, a single value is returned corresponding to + the specified value. The pattern is used to lookup an object or + class, such it is not necessary to provide fully qualified + names). if there is no match, empty is returned. Previously, + "info superclass" and "info subclass" returned a boolean value + and performed always a transitive search. Returning "" is more + consistent and more in line with Tcl. + + Note that " info superclass -closure" is a replacement for + " info heritage", and " info instances -closure" + is a replacement for " allinstances". The old commands + will be marked as deprecated in the near future. + + Please note, that the behavior of the match pattern has + changed and is therefor not completely compatible with + prior versions. + + * New info subcommands: + + info instmixinof ?-closure? ?pattern? + info mixinof ?pattern? + + These info subcommands are used to determine, into + which classes a mixin class was mixed into. + + These inverse functions of mixin and instmixin are used as well + internally. These functions help to speed certain operations + (e.g. superclass, or registering a mixin class) up by a factor of + 1000 (!) or more, when a large number of objects exist. + + This functionality was primarily implemented by Martin Matuska. + Many thanks! + + * Made the behavior "pattern" in the following calls identical + concerning wild cards and object lookups + + mixin delete pattern + instmixin delete pattern + superclass delete pattern + info mixin ?pattern? + + * Fix to preserve var traces when copying objects + (Many thanks to Florian Murr for reporting) + + * Fix problem in Tcl 8.5.* when setting variables + from C (problem with Tcl_ObjSetVar2()?); many + thanks to Florian Murr and Neophytos Demetriou + for reporting) + + * Improved documentation + + * Extended regression tests + + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + Index: library/xotcl/doc/Announce-1.6.1 =================================================================== diff -u --- library/xotcl/doc/Announce-1.6.1 (revision 0) +++ library/xotcl/doc/Announce-1.6.1 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,43 @@ +Dear XOTcl Community, + +XOTcl 1.6.1 is available. This release provides in short: + - improved orthogonality for introspection, + - improvements in the serializer + - some minor fixes + +See below for more details. +Best regards + +-gustaf neumann + + +Announcing XOTcl 1.6.1 +************************* + +We are pleased to announce the availability of XOTcl 1.6.1 + +Major changes relative to 1.6.0 are: + + * Extended and generalized "info" method + + * Generalized serializing package: when deserializing code, now + consistenly no constructors are called. In previous versions, + constuctors were called on slots; due to the point above, this is + not needed; background: the previous solution had problems in + aolserver ns_eval, when a slot-constructor called db-functions, + since during ns_eval, the database handles are non-functional) + + * Fixes for potential crashes when methods were called + with invalid arguments + + * Improved documentation + + * Extended regression tests + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + Index: library/xotcl/doc/Announce-1.6.2 =================================================================== diff -u --- library/xotcl/doc/Announce-1.6.2 (revision 0) +++ library/xotcl/doc/Announce-1.6.2 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,54 @@ +Dear XOTcl Community, + +XOTcl 1.6.2 is available. See below for more details. + +Best regards +-gustaf neumann + + +Announcing XOTcl 1.6.2 +************************* + +We are pleased to announce the availability of XOTcl 1.6.2 + +Major changes relative to 1.6.1 are: + + * Functional extensions: + - handle nonposargs in method "copy" properly + + - new command ::xotcl::finalize + (for forcing cleanup and destuctor execution at a time in + a multi-threaded environment, where it is still safe to execute + all Tcl commands) + + * Extended and generalized "info" method + + - Added " mixinof -closure ?pattern?" + Query the objects for which is used as a per-object-mixin + (directly or indirectly) + + * Fixes for potential crashes + + - Implemented proper downgrading of Classes to Objects (handle + cases, where something was created first as an object and is + reclassed/recreated later as a class) and vice versa + + - Reset mixin order for per-object mixins, when the superclass of + a class is deleted, which is used as per-object mixin + + + * Improved documentation + + * Extended regression tests + + * Some code cleanup + + + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + Index: library/xotcl/doc/Announce-1.6.3 =================================================================== diff -u --- library/xotcl/doc/Announce-1.6.3 (revision 0) +++ library/xotcl/doc/Announce-1.6.3 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,52 @@ +Dear XOTcl Community, + +XOTcl 1.6.3 is available. See below for more details. + +Best regards +Gustaf Neumann + + +Announcing XOTcl 1.6.3 +************************* + +We are pleased to announce the availability of XOTcl 1.6.3 + +Major changes relative to 1.6.2 are: + + * Functional improvements: + + - simplified and generalized handling of namespaced instance + variables, where namespaced associative arrays could conflict + with global variables due to Tcl's default namespace + resolution. Many thanks to Stefan Sobernig for this + contribution! + + * Fixes: + - Corrected deletion of meta-classes. Before, it was possible + to create undestroyable objects via complex + meta-class structures + + * Speed improvements: + - Use of new interfaces in Tcl 8.5 (when compiled with Tcl 8.5) + - simplified interfaces for various C functions + - Speed improvement for method invocation: + * With Tcl 8.5: 10-15 % + * With Tcl 8.4: 5-10 % + + * Improve code quality: + - some more code cleanup + - factoring out common code + - using const in more cases + + * Extended regression tests + + * Improved documentation + + + For more details about the changes, please consult the ChangeLog and + documentation. + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + Index: library/xotcl/doc/Announce-1.6.4 =================================================================== diff -u --- library/xotcl/doc/Announce-1.6.4 (revision 0) +++ library/xotcl/doc/Announce-1.6.4 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,19 @@ + +Announcing XOTcl 1.6.4 +************************* + +Dear XOTcl Community, +We are pleased to announce the availability of XOTcl 1.6.4 + +Major changes relative to 1.6.3 are: + + * 2 fixes of potential crashes introduced in 1.6.3 + * Improved documentation (added "stack" as introductory example) + + For more details about the changes, please consult the ChangeLog and + documentation. The planned next release will be 2.0.0 + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + Index: library/xotcl/doc/Announce-1.6.5 =================================================================== diff -u --- library/xotcl/doc/Announce-1.6.5 (revision 0) +++ library/xotcl/doc/Announce-1.6.5 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,20 @@ + +Announcing XOTcl 1.6.5 +************************* + +Dear XOTcl Community, +We are pleased to announce the availability of XOTcl 1.6.5 + +Major changes relative to 1.6.4 are: + + * fixed namespace visibilty problem reported by Mykhaylo Sorochan + * fixed var resolver/memory leak problem reported by Victor Mayevski + (when XOTcl is compiled against Tcl 8.4.*, but loaded into 8.5.*) + + For more details about the changes, please consult the ChangeLog and + documentation. The planned next release will be 2.0.0 + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + Index: library/xotcl/doc/Announce-1.6.6 =================================================================== diff -u --- library/xotcl/doc/Announce-1.6.6 (revision 0) +++ library/xotcl/doc/Announce-1.6.6 (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,24 @@ + +Announcing XOTcl 1.6.6 +************************* + +Dear XOTcl Community, +We are pleased to announce the availability of XOTcl 1.6.6 + +Major changes relative to 1.6.5 are: + + * improved 64-bit compatibility (expat) + * fixed minor memory leaks (info methods, forward error case) + * fixed potential cyclic dependencies via namespace imports + during cleanup + * fixed potential crash with var-traces being fired twice + * compatibility with Tcl 8.6b1 + * fix for debian packaging + + For more details about the changes, please consult the ChangeLog and + documentation. The planned next release will be 2.0.0 + +MORE INFO + General and more detailed information about XOTcl and its components + can be found at http://www.xotcl.org + Index: library/xotcl/doc/cascaded-message-filter.gif =================================================================== diff -u Binary files differ Index: library/xotcl/doc/features.gif =================================================================== diff -u Binary files differ Index: library/xotcl/doc/filter-inheritance.gif =================================================================== diff -u Binary files differ Index: library/xotcl/doc/langRef.xotcl =================================================================== diff -u -rf3b7952aabc9e4f9079febd1f5b7f5fb833fd50c -re8715774bf274fbeadabf08a5a0777a968f71148 --- library/xotcl/doc/langRef.xotcl (.../langRef.xotcl) (revision f3b7952aabc9e4f9079febd1f5b7f5fb833fd50c) +++ library/xotcl/doc/langRef.xotcl (.../langRef.xotcl) (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -1,5 +1,5 @@ -# $Id: langRef.xotcl,v 1.14 2006/10/04 20:40:23 neumann Exp $ -package provide XOTcl-langRef 1.6.0 +# $Id: langRef.xotcl,v 1.18 2007/09/05 19:09:22 neumann Exp $ +package provide XOTcl-langRef 1.6.4 package require XOTcl @ @File { @@ -225,12 +225,13 @@ Turn on/off assertion checking. Options argument is the list of assertions, that should be checked on the object automatically. Per default assertion checking is turned - off. Examples: - <@pre class='code'> - o check {}; <@it># turn off assertion checking on object o - o check all; <@it># turn on all assertion checks on object o - o check {pre post}; <@it># only check pre/post assertions - <@a href="#Object-info">info check introspects check options. + off.
+ Examples:
+<@pre CLASS="code"> + o check {}; <@i># turn off assertion checking on object o + o check all; <@i># turn on all assertion checks on object o + o check {pre post}; <@i># only check pre/post assertions + } return "empty string" } @@ -251,7 +252,7 @@ } { Description { Resets an object or class into an initial state, as after construction. - Called during recreation process by the method recreate. + Called during recreation process by the method 'recreate' } return "empty string" } @@ -260,18 +261,11 @@ ?args? "'-' method calls" } { Description { - Calls the '-' (dash) methods. This method evaluates its argument list - and calls everything starting with '-' (followed by an alpha character) - as a method. Every list element until the next '-' is interpreted as an - argument of the called method. XOTcl supports argument lists with a variable - number of arguments. If an argument of a method called this way starts - with a "-", the call can be placed safely - into a list (e.g. "Class c [list -strangearg -a-] -simplearg 2") to avoid - the interpretation of "a-" as a method. -

The method configure is called automatically by - the default create and recreate methods after - the default values are set.

-

+ Calls the '-' (dash) methods. I.e. evaluates arguments and calls + everything starting with '-' (and not having a digit a + second char) as a method. Every list element until the next '-' + is interpreted as a method argument. configure is called + before the constructor init during initialization and recreation. In the following example, the variable set is called via configure before init: <@pre class='code'> Object o -set x 4 @@ -356,10 +350,10 @@ Description { Standard destructor. Can be overloaded for customized destruction process. Actual destruction - is done by dealloc. "destroy" in principal does: + is done by instdestroy. "destroy" in principal does: <@pre class='code'> Object instproc destroy args { - [my info class] dealloc [self] + [my info class] instdestroy [self] } } return "empty string" @@ -505,19 +499,7 @@ return "1 or 0" } -@ Object instproc init { - args "argument list" -} { - Description { - The method <@tt>init is called automatically by the default - <@tt>create method on initialized - objects (the default variables are set, the configure - methods are already performed). This method is solely a user hook for - applications to perform class specific initialzation after object creation. - } -} - @ Object instproc incr { varName "variable name" ?increment? "value to increment" @@ -606,9 +588,6 @@ contain wildcards, either the fully qualified name is returned, or empty, if no match exists. - <@li><@TT>objName info mixinguard name: Returns the guards - for the mixin identified by name. - <@li><@TT>objName info nonposargs methodName: Returns non-positional arg list of methodName @@ -981,7 +960,7 @@ } @ Class instproc alloc { obj "new obj/class name" - ?args? "arguments passed during creation" + ?args? "arguments passed to the new class after creation" } { description { @@ -995,7 +974,7 @@ objects via <@tt>alloc<@/tt>. } - return "fully qualified name of created instance" + return "new class name" } @ Class instproc allinstances { @@ -1013,18 +992,6 @@ description { Create user-defined classes or objects. If the class is a meta-class, a class is created, otherwise an object. - The object creation protocol implemened by create works as follows: -

    -
  • create firstly calls <@tt>alloc - in order to create an uninitialized object or class. -
  • In the second step, the - default values for parameters are searched on superclasses and set in the created object. -
  • In the third step, the method <@tt>configure - is called with the passed - argument list to configure the object/class. -
  • Finally the constructor <@tt>init is called on the object - with all arguments up to the first '-' argument (as returned by configure). -
The method <@tt>create<@/tt> is responsible for allocating and initializing objects. The method can be overloaded e.g. in a @@ -1052,9 +1019,17 @@

+ Create firstly calls <@tt>alloc in order to allocate memory for the + new object. Then default values for parameters are searched on superclasses (an set if found). + + Finally the constructor <@tt>init is called on the object + with all arguments up to the first '-' arg.<@p> + The <@tt>create method is often called implicitly through the - method. E.g. the following two commands are equivalent + <@tt>unknown + mechanism when a class (meta-class) is called with an unknown + method. E.g. the following two commands are equivalent <@pre class='code'> Car herby -color red @@ -1068,9 +1043,8 @@ <@pre class='code'> Class Car -init -superclass Vehicle <@/pre> - See also: <@tt>recreate } - return "fully qualified name of the created instance (result of alloc)" + return "name of the created instance (result of alloc)" } @ Class instproc info { @@ -1126,7 +1100,7 @@ all instfilterguards are integrated (<@TT> ClassName info instfilter -guards). - <@li><@TT>ClassName info instfilterguard name: Returns the guards + <@li><@TT>objName info instfilterguard name: Returns the guards for instfilter identified by name. <@li><@TT>objName info instforward ?-definition name? ?pattern?: @@ -1159,9 +1133,6 @@ either the fully qualified name is returned, or empty, if no match exists. - <@li><@TT>ClassName info isntmixinguard name: Returns the guards - for the instmixin identified by name. - <@li><@TT>ClassName info instnonposargs methodName: returns list of non-positional args of methodName @@ -1216,12 +1187,12 @@ return "Value of introspected option as a string." } -@ Class instproc dealloc { +@ Class instproc instdestroy { obj "obj/class name" ?args? "arguments passed to the destructor" } { Description { - Destroys XOTcl object physically from the memory. + Standard destructor. Destroys XOTcl object physically from the memory. Can be overloaded for customized destruction process. <@p> In XOTcl objects are not directly destroyed, when a destroy is @@ -1370,7 +1341,7 @@ @ Class instproc instproc { name "instance method name" - "?non-pos-args?" "optional non-positional arguments" + ?non-pos-args?" "optional non-positional arguments" args "instance method arguments" body "instance method body" "?preAssertion?" "optional assertions that must hold before the proc executes" @@ -1402,7 +1373,7 @@ If <@tt>-childof obj is specified, the new object is created as a child of the specified object. } - return "fully qualified name of the created instance" + return "new object name" } @ Class instproc parameter { @@ -1461,29 +1432,18 @@ ?args? "arbitrary arguments" } { description { - Hook called upon recreation of an object in cases where the user wants to distinguish - between creation and recreation of objects. A recreation occurs, when an Object is created - with a name that exists already. - A typical use-case is the redefinition - of classes in and IDE, where the relations between classes/classes and object/classes - should be preserved (this is different to a destroy of the object). - -

The method recreate does not need to call alloc - but calls instead cleanup - to reset to the object (or class) to its initial state (e.g. remove variables, child objects, - for classes remove instaces, etc.). Then it performs the standard initialization - for the object or class. - -

If recreate is overloaded and the default recreate method is called via next, - the pre-part - (before next) contains its old state of the object, - while during the part after next the - object is cleaned up. -

To ease recreation of classes, see ::xotcl::configure softrecreate. - - See also: <@tt>create + Methods called upon recreation of an object. Recreate is called, + when an object/class is created, but a same-named object/class + exists already. "recreate" is not called, when an object is trying + to be recreated as a class or vice versa. In these cases, + recreating is realized via destroy+create. The Methods "recreate" + performs standard object initialization, per default. May be + overloaded/-written. It calls another method cleanup which handles + actual cleanup of the object during next. That means, if you + overload recreate, in the pre-part the object still contains its + old state, after next it is cleaned up. } - return "fully qualified name of instance" + return "obj name" } @ Class instproc superclass { @@ -1594,7 +1554,7 @@

Example of a class definition with three attribute slots:

-
+<@pre CLASS="code">
   <@tt>Class Person -slots {
     Attribute name
     Attribute salary -default 0
Index: library/xotcl/doc/next-path-mixin-movement.gif
===================================================================
diff -u
Binary files differ
Index: library/xotcl/doc/next-path.gif
===================================================================
diff -u
Binary files differ
Index: library/xotcl/doc/obj_class_system.gif
===================================================================
diff -u
Binary files differ
Index: library/xotcl/doc/tutorial.html
===================================================================
diff -u
--- library/xotcl/doc/tutorial.html	(revision 0)
+++ library/xotcl/doc/tutorial.html	(revision e8715774bf274fbeadabf08a5a0777a968f71148)
@@ -0,0 +1,5011 @@
+
+
+
+
+	XOTcl - Tutorial
+	
+	
+	
+
+
+
+
+	
+		
+		
+	
+
+

XOTcl + - Tutorial - Index +

+
+
+

Version: 1.6.4

+ + + + + + + + + + +
+

Introduction + +

+
+
+ + +

 
Language Overview +

+ +

XOTcl [Neumann and Zdun 2000a] is an extension +to the object-oriented scripting language OTcl [Wetherall and Lindblad 1995] which itself extends +Tcl [Ousterhout 1990] (Tool Command Language) with +object-orientation. XOTcl is a value-added replacement for OTcl and +does not require OTcl to compile.

+ +

XOTcl runs in the tclsh and provides a few extension +commands. These are offered in a Tcl namespace ::xotcl, and +can be imported into the current namespace to reduce typing and +improve readability. All Tcl commands remain available (and are also +applicable on the extension constructs).

+ +

A central property of Tcl is, that it uses strings solely for the +representation of data. Internally it uses an dynamic type system with +automatic conversion (which enables efficient type handling). For +that reason all components (e.g. written in C) once integrated in Tcl +automatically fit together and the components can be reused in +unpredicted situations without change. The evolving component +frameworks provide a high degree of code reuse, rapid +application development, and ease of use. The application developer +may concentrate on the application task solely, rather than investing +efforts in fitting components together. Therefore, in certain +applications scripting languages like Tcl are very useful for a fast +and high-quality development of software (see [Ousterhout 1998] for more details). +

+

Tcl is equipped with appropriate functionalities for the easy +gluing of components, like dynamic typing, dynamic extensibility, and +read/write introspection. OTcl is an object-oriented extension to Tcl, +which encourages a Tcl-like programming style and is composed of +language constructs with properties similar to Tcl. It offers an +object-orientation with encapsulation of data and operation without +protection mechanisms and single and multiple inheritance. +Furthermore it enables to change the relationships dynamically, offers +read/write introspection, has a three level class system based on +meta-classes and offers method chaining. These abilities are +integrated in XOTcl with only slight changes to OTcl visible to the +programmer. +

+

Extended Object Tcl aims at complexity and adaptability issues that +may occur in context of large (object-oriented) software structures +and in the context of component glueing. In particular we added the +following support: +

+
    +
  • Filters as a means of + abstractions over method invocations to implement large program + structures, like design patterns. +

    +
  • Mixin Classes, as a + means to give an object or a classes' instances access to several different supplemental + classes, which may be changed dynamically. +

    +
  • Dynamic Object Aggregations, + to provide dynamic aggregations through nested namespaces. +

    +
  • Nested Classes, to reduce + the interference of independently developed program structures. +

    +
  • Assertions, to reduce the + interface and the reliability problems caused by dynamic typing and, + therefore, to ease the combination of components. +

    +
  • Forwarders, to delegate + calls efficiently to other objects or classes. +

    +
  • Slots, to manage values + of instance variables with a common interface. +

    +
  • Meta-data and Automatic Documentation, to enhance self-documentation of objects + and classes. +

    +
+ + + +


+

+

+   +

+

Figure 1: +Language Extensions of XOTcl +

+
+ + + + + +
+

+
+
+ +

 
Introductory Overview Example: Stack

+ +

+To give you an impression of the language before we go into the details of the extended language constructs, we present in this section a simple, classical example, familiar to many from introductory programming courses: the Stack example. In the later section, we will present the soccer club example, which focuses more on the dynamic features of the Extended Object Tcl. +

+ +

In a first step, we define a class Stack. A new class is defined in XOTcl via the command Class create yourclass. The stack will have a constructor (in XOTcl, the method init) and the methods push and pop. Methods which are inherited to objects are defined via instproc. In the following example, all predefined commands (some from Tcl, some from XOTcl) are emphasized. +

+ +
+#
+# Create a stack class 
+#
+Class create Stack 
+
+Stack instproc init {} {
+  # Constructor
+  my instvar things
+  set things ""
+}
+
+Stack instproc push {thing} {
+  my instvar things
+  set things [concat [list $thing] $things]
+  return $thing
+}
+  
+Stack instproc pop {} {
+  my instvar things
+  set top [lindex $things 0]
+  set things [lrange $things 1 end]
+  return $top
+}
+
+ +

+The definition of the class Stack is typically saved in a file (say stack.xotcl) +and can be used e.g. in an interactive Tcl shell (tclsh) as follows. The percent sign +indicates the prompt of the Tcl shell, the reminder of the line is typed in, the result +of the command is shown in the line below. Comments are lines starting with a hash symbol #. + +

+% package require XOTcl
+% namespace import xotcl::*
+% source stack.xotcl
+  
+# Create Object s1 of class Stack
+% Stack create s1
+::s1
+% s1 push a
+a
+% s1 push b
+b
+% s1 push c
+c
+% s1 pop
+c
+% s1 pop
+b
+# Delete object s1
+s1 destroy
+
+ +

In the session above, we load XOTcl into the current shell, import the names from the xotcl namespace and we load the file stack.xotcl. At this time, the class Stack is available in the scripting session. In the next step, we create an stack object named s1 and push into the stack the values a, b and c via separate push calls. Then we pop values from the stack and we destroy finally the stack s1. + +

 
Object specific methods

+ +

This definition is pretty similar to stack definitions in many other object oriented languages. The example below shows how to define purely object specific behavior. This way we can define an object stack without the need of a class Stack. Notice that the methods of the object stack are defined via proc and not via instproc in the example of the class Stack. + +

+#
+# Create an object named stack
+#
+Object create stack
+
+stack set things ""
+
+stack proc push {thing} {
+  my instvar things
+  set things [concat [list $thing] $things]
+  return $thing
+}
+  
+stack proc pop {} {
+  my instvar things
+  set top [lindex $things 0]
+  set things [lrange $things 1 end]
+  return $top
+}
+
+ +

The object stack can be used in exactly the same way as s1 (the instance of class Stack) before. + +

 
Refining the behavior of objects and classes

+ +

So far, the definition of stacks were pretty minimal. Suppose, we want to define safe stacks, that check e.g. for stack underruns (more pop the push operations are issued). Checking safety can be done mostly independent from the implementation details of the stack (usage of internal data structures). +With XOTcl, one can define stack-safety as a separate class using methods with the same names as the implementations before, and "mix" this behavior later into classes or objects. The implementation of Safety uses a counter to check for stack underruns.

+ +
+#
+# Create a safety class 
+#
+Class create Safety
+Safety instproc init {} {
+  my set count 0
+  next
+}
+Safety instproc push {thing} {
+  my incr count
+  next
+}
+  
+Safety instproc pop {} {
+  if {[my set count] == 0} then { error "Stack empty!" }
+  my incr count -1
+  next
+}
+
+ +

When we load the classes Stack and Safety into the same script, +we can define e.g. a certain stack s2 as a safe stack, while all other stacks +might be still "unsafe". This can be achieved via the option -mixin during +object creation. +

+
+% Stack create s2 -mixin Safety
+::s2
+% s2 push a
+a
+% s2 pop
+a
+% s2 pop
+Stack empty!
+
+ +Note that the definition of Saftey can be used not only for instances of the class Stack, but for arbitrary objects supporting the same interface. Therefore we could as well make the stack object stack (that we created before) safe at any time by adding the safety at arbitrary times with the method mixin, and we can remove the safety as well at any time. + +
+# Add Safety to the object stack
+% stack mixin Safety
+...
+% stack push a
+...
+# remove Safety
+% stack mixin {}
+
+We can as well use Saftey to create a new class SafeStack. In this case, all instances of SafeStack have the safety property defined above. +
+#
+# Create a safe stack class by using Stack and mixin 
+# Safety 
+#
+Class create SafeStack -superclass Stack -instmixin Safety
+
+SafeStack create s3
+
+ +

 
Stack of integers

+ +

The definition of Stack is generic and allows all kind of elements to be stacked. Suppose, we want to use the generic stack definition, but a certain stack (say, s4) should allow only stacking of integers. This behavior can be achieved by defining an object specific method for the stack s4 that checks the values to be pushed. In case the pushed value is ok, the push definition of Stack is called via next. +

+# 
+# Create a stack with a object-specific method 
+# to check the type of entries 
+#
+# s4 is a stack of integer 
+ 
+Stack create s4
+s4 proc  push {value} {
+   if  {![ string is integer $value]} {
+     error "value $value is not an integer"
+  }
+   next
+}
+
+ +

 
Class specifc methods

+ +

In extended object Tcl, classes are objects as well (objects with different properties). We will come to this later in more detail. However, we can define as well methods of classes, which are not inherited to the instances, +by defining class-specific methods using proc. This happens exactly like defining objects specific methods as shown before. In the following example, we will define a class-specific method available_stacks that returns the number of the currently existing stack instances. +

+ +
+Class create Stack
+# ...
+Stack proc available_stacks {} {
+   return [llength [my info instances]]
+}
+
+Stack create s1
+Stack create s2
+
+puts [Stack available_stacks]
+
+ +

 
Introductory Overview Example: Soccer Club +

+

+In our second example, we will focus on an application example where one can benefit substantially from the dynamic language constructs of XOTcl, the soccer club example (the full code can +be found in the xotcl/src/scripts/soccerClub.xotcl file. All +the persons and characters in this example are fictitious, and any resemblance to +actual persons, living or deceased, is coincidental. +

+ +

Before we start, we introduce an instrument for making the documentation of programs more easy. In order to document source code files, we can use the @ object, which is used generally to provide any kind of information, meta-data, and documentation on a running program. Here, we just give a file description. Then the makeDoc.xotcl tool can automatically document the program file later for us.

+ +
+  @ @File {
+    description {
+      This is a simple introductory example for the language XOTcl. 
+      It demonstrates the basic language constructs on the example of
+      a soccer club.
+    }
+  }
+
+

+ +All things and entities in XOTcl are objects. A special kind of objects +are classes. Classes define common properties for other objects. For a +soccer club, we firstly require a common class for all kinds of members. +

+

+Common to all members is that they have a name. Common properties +defined across all instances of a class are called 'parameter' in +XOTcl. In this example the instance variable name will be +initialized by default with an empty string. +

+
+  Class ClubMember -parameter {{name ""}}
+
+

+A special club member is a Player. Derived classes can be +build with inheritance (specified through +superclass). Players may have a playerRole (defaults +to NONE). +

+
+  Class Player -superclass ClubMember -parameter {{playerRole NONE}}
+
+

+Other club member types are trainers, player-trainers, and presidents: +

+
+  Class Trainer -superclass ClubMember
+  Class President -superclass ClubMember
+
+

+The PlayerTrainer uses multiple inheritances by being both a player +and a trainer: +

+
+  Class PlayerTrainer -superclass {Player Trainer}
+
+

+Now we define the SoccerTeam class: +

+
+  Class SoccerTeam -parameter {name location type}
+
+

+We may add a player. This is done by a method. Instance methods are +in XOTcl defined with instproc. All club members are aggregated in +the team (denoted by :: namespace syntax). +

+
+  SoccerTeam instproc newPlayer args {
+    # we create a new player who is part of the soccer team
+    # "eval" is needed to pass the provided arguments to the call of new
+    eval Player new -childof [self] $args
+  }
+
+

+A player can be transfered to another team. The player object does +not change internally (e.g. the playerRole stays the same). Therefore we +move it to the destination team. +

+
+  SoccerTeam instproc transferPlayer {playername destinationTeam} {
+    # We use the aggregation introspection option children in order
+    # to get all club members
+    foreach player [my info children] {
+      # But we only remove matching playernames of type "Player". We do
+      # not want to remove another club member type who has the same
+      # name.
+      if {[$player istype Player] && [$player name] == $playername} {
+        # We simply 'move' the player object to the destination team.
+        # Again we use a unique autoname in the new scope
+        $player move [set destinationTeam]::[$destinationTeam autoname player%02d]
+      }
+    }
+  }
+
+

+Finally we define two convenience to print the members/players to +the stdout with puts. +

+
+  SoccerTeam instproc printMembers {} {
+    puts "Members of [my name]:"
+    foreach m [my info children] {puts "  [$m name]"}
+  }
+  SoccerTeam instproc printPlayers {} {
+    puts "Players of [my name]:"
+    foreach m [my info children] {
+      if {[$m istype Player]} {puts "  [$m name]"}
+    }
+  }
+
+

+Now let us build to example soccer team objects. +

+
+  SoccerTeam chelsea -name "Chelsea FC" -location "Chelsea"
+  SoccerTeam bayernMunich -name "F.C. Bayern M�nchen" -location "Munich"
+
+

+ +With addPlayer we can create new aggregated player objects +

+Let us start some years in the past, when "Franz Beckenbauer" was +still a player. +

+
+  set fb [bayernMunich newPlayer -name "Franz Beckenbauer" \
+    -playerRole PLAYER]
+
+

+playerRole may not take any value. It may either be NONE, PLAYER, +or GOALY ... such rules may be given as assertions (here: an instinvar +gives an invariant covering all instances of a class). In XOTcl +the rules are syntactically identical to if statements: +

+
+  Player instinvar {
+      {[my playerRole] == "NONE" ||  
+       [my playerRole] == "PLAYER" || 
+       [my playerRole] == "GOALY"}
+  }
+
+

+If we break the invariant and turn assertions checking on, we should +get an error message: +

+
+  $fb check all
+  if {[catch {$fb set playerRole SINGER} errMsg]} {
+    puts "CAUGHT EXCEPTION: playerRole has either to be NONE, PLAYER, or TRAINER"
+    # turn assertion checking off again and reset to PLAYER
+    $fb check {}
+    $fb set playerRole PLAYER
+  }
+
+

+But soccer players may play quite different, orthogonal +roles. E.g. Franz Beckenbauer was also a singer (a remarkably bad +one). However, we can not simply add such orthogonal, extrinsic +extensions with multiple inheritance or delegation. Otherwise we +would have either to build a lot of unnecessary helper classes, like +PlayerSinger, PlayerTrainerSinger, etc., or we would have to build +such helper objects. This either leads to an unwanted combinatorial +explosion of class or object number +

+Here we can use a per-object mixin, which is a language construct +that expresses that a class is used as a role or as an extrinsic +extension to an object. +

+First we just define the Singer class. +

+
+  Class Singer
+  Singer instproc sing text {
+    puts "[my name] sings: $text, lala."
+  }
+
+

+Now we register this class as a per-object mixin on the player object: +

+
+  $fb mixin Singer
+
+

+And now Franz Beckenbauer is able to sing: +

+
+  $fb sing "lali"
+
+

+But Franz Beckenbauer has already retired. When a player retires, we +have an intrinsic change of the classification. He *is* not a player +anymore. But still he has the same name, is club member, and +is a singer (brrrrrr). +

+Before we perform the class change, we extend the Player class to +support it. I.e. the playerRole is not valid after class change +anymore (we unset the instance variable). +

+
+  Player instproc class args {
+    my unset playerRole
+    next
+  }
+
+

+Now we can re-class the player object to its new class (now Franz +Beckenbauer is President of Bayern Munich. +

+
+  $fb class President
+  # Check that the playerRole isn't there anymore.
+  if {[catch {$fb set playerRole} errMsg]} {
+    puts "CAUGHT EXCEPTION: The player role doesn't exist anymore \
+         (as it should be after the class change)"
+  }
+
+

+But still Franz Beckenbauer can entertain us with what he believes +is singing: +

+
+  $fb sing "lali"
+
+

+Now we define some new players for Bayern Munich: +

+
+  bayernMunich newPlayer -name "Oliver Kahn" -playerRole GOALY
+  bayernMunich newPlayer -name "Giovanne Elber" -playerRole PLAYER
+
+

+If we enlist the players of Munich Franz Beckenbauer is not enlisted +anymore: +

+
+  bayernMunich printPlayers
+
+

+But as a president he still appears in the list of members: +

+
+  bayernMunich printMembers
+
+

+Now consider an orthonogal extension of a transfer list. Every +transfer in the system should be notified. But since the transfer +list is orthogonal to SoccerTeams we do not want to interfere with +the existing implementation at all. Moreover, the targeted kind of +extension has also to work on all subclasses of SoccerTeam. Firstly, we +just create the extension as an ordinary class: +

+
+  Class TransferObserver
+  TransferObserver instproc transferPlayer {pname destinationTeam} {
+    puts "Player '$pname' is transfered to Team '[$destinationTeam name]'"
+    next
+  }
+
+

+Now we can apply the class as a per-class mixin, which functions +exactly like a per-object mixin, but on all instances of a class and +its subclasses. The next primitive ensures that the original +method on SoccerTeam is called after notifying the transfer (with +puts to stdout): +

+
+  SoccerTeam instmixin TransferObserver
+
+

+If we perform a transfer of one of the players, he is moved to the new +club and the transfer is reported to the stdout: +

+
+  bayernMunich transferPlayer "Giovanne Elber" chelsea
+
+

+Finally we verify the transfer by printing the players: +

+
+  chelsea printPlayers
+  bayernMunich printPlayers
+
+

+ +



+

+ + + + + +
+

Object + and Class System +

+
+
+

In XOTcl every object is associated with a class over the class +relationship. Classes are special objects with the purpose of +managing other objects. ``Managing'' means that a class controls the +creation and destruction of its instances and that it contains a +repository of methods (``instprocs'') accessible for the instances. +Object-specific methods are called ``procs'', instance methods are +called ``instprocs''. +

+

The instance methods common to all objects are defined in the root +class Object (predefined or user-defined). Since a class is a +special (managing) kind of object it is managed itself by a special +class called ``meta-class'' (which manages itself). Meta-Classes are +used to define classes and to provides methods for these. Most +classes are defined by the predefined meta-class Class. One +interesting aspect of meta-classes is that by providing a constructor +pre-configured classes can be derived. Meta-classes can be used to +instantiate large program structures, like some design patterns (see +[Neumann and Zdun 1999a] for more +details), where the meta-class may holds the generic parts of the +structures. Since a meta-class is an entity of the program, it is +possible to collect these entities in pattern libraries for later +reuse easily (more details about meta-classes are given in a later section). +

+

XOTcl supports single and multiple inheritance. Classes are ordered +by the relationship superclass in a directed acyclic +graph. The root of the class hierarchy is the class Object. +A single object can be instantiated directly from this class. An +inherent problem of multiple inheritance is the problem of name +resolution, when for example two super-classes contain an instance +method with the same name. XOTcl provides an intuitive and unambiguous +approach for name resolution by defining the precedence order along a +linear ``next-path'' incorporating the class and mixin +hierarchies, which is modeled after CLOS. A method can invoke +explicitly the shadowed methods by the predefined command +next. When this command is executed a shadowed method is +``mixed into'' the execution of the current method. Method chaining +without explicit naming of the targeted method is very important for +languages supporting a dynamic class system, because one cannot always +predict which classes are currently participating in the inheritance +hierarchy at design time (often necessary in inheritance models, like +C++). +

+

An important feature of all XOTcl +objects is the read/write introspection. The reading introspection +abilities of XOTcl are packed compactly into the info +instance method which is available for objects and classes. All +obtained information can be changed at run-time dynamically with +immediate effect. Unlike languages with a static class concept, XOTcl +supports dynamic class/superclass relationships. At any time the class +graph may be changed entirely using the superclass method, or +an object may change its class through the class method. This +feature can be used for an implementation of a life-cycle or other +intrinsic changes of object properties (in contrast to extrinsic +properties e.g. modeled through roles and implemented through +per-object and per-class mixins [Neumann and +Zdun 1999c] ) . These changes can be achieved without loosing the +object's identity, its inner state, and its per-object behavior (procs +and per-object mixins). +

+

+   +

+

Figure 2: +Object and Class System +

+
+ + + + + +
+

+
+
+ + + + + +
+

Basic + Functionalities +

+
+
+

 
Objects +

+

Initially XOTcl offers two new commands: Object and +Class. They represent hooks to the features of the language. +This section discusses both of them in detail and shows how they +function in the context of XOTcl. Note, that even if most of this is +compatible to OTcl, a few changes occur. For this reason, this +section is no introduction to plain OTcl. The Object command +provides access to the Object class, which holds the common +features of all objects, and allows us to define new objects. Objects +are always instances of classes, therefore, objects defined with the +Object command are (initially) instances of the Object +class. But since they have no user-defined type, they may be referred +to as singular objects. As all other objects they may be +specialized by object-operations and -data. +

+

The object command has the following syntax: +

+
+  Object objName ?args?
+

+A command of this form is a short-cut for a message to the create +instance method (forwarded automatically by the unknown +mechanism, which is invoked every time the message dispatch system +discovers an unknown message): +

+
+  Object create objName ?args?
+

+It creates a new object of type Object with the name objName +(in fact it invokes a create call on the Object class). +objName becomes a new command, which allows us to access the +created object. Similar to the Object command it may be +used like a normal Tcl-command (using sub-commands to access the +object's methods). Therefore, this form of access is called +object-command approach. A simple example is an object which +holds the information of a kitchen. It is created by: +

+
+  Object kitchen
+
+

+An object creation calls the constructor init of the +object's class. The destruction of an object is handled by the +destroy instance method. The general syntax of destroy +is: +

+
+  objName destroy
+

+E.g. the kitchen object is destroyed by: +

+
+  kitchen destroy
+

+To invoke a user-defined destruction process, it is possible to +overload this instance method in every class derived from object. +

+

+Note that the destruction of an object is performed by the +method destroy of Object (since every object is an instance +of Object, every object can call destroy). When an application class +overloads destroy, this method should contain a next in order +to reach the base class and to actually destroy the object. +

+

Data on Objects +

+

The Object class provides a range of operations to manage +objects, including those to manipulate data-structures on the +objects. They are similar to the same-named Tcl-commands: +

+
+  objName set varname ?value?
+  objName unset v1 ?v2 ... vn?
+
+

+The set instance method with given value option +allows us to manipulate an object-variable's value or to create a new +one, if the variable varname does not exist on the object so +far. Without value option the set operation queries +the variable and returns it's value, if the variable exists, +otherwise it produces an error message. The unset operation +deletes one or optionally a set of variables from an object. For +example the kitchen object can store information on the +color of the wall-paper by: +

+
+  kitchen set wallPaperColor white
+

+Similar to Tcl-variables the object variables are dynamical; they +may be set at run-time when they are needed and unset when they +become obsolete. E.g. the persons in the kitchen may be stored in an +array. If there are no persons in the kitchen the array is deleted: +

+
+  # Peter enters the kitchen to cook
+  kitchen set persons(cook) Peter
+  ...
+  # Marion enters the kitchen to take one of the seats
+  kitchen set persons(seat1) Marion 
+  ...
+  # Both Peter and Marion leave the kitchen
+  # the array is deleted by unset
+  kitchen unset persons
+

+Since XOTcl variables are internally realized through Tcl-variables +they may be treated like all Tcl-variables. For that reason they have +all Tcl-variable abilities, including the possibility to handle them +as lists or arrays (as seen in the last example). The array +command of Tcl is mapped to an XOTcl-command directly. An +object-oriented call to an object of the form +

+
+  objName array option arrayName args
+

+forwards its arguments to an array Tcl-command for the +object´s instance variable arrayName. It could be used like +the same-named Tcl-command, e.g. the command +

+
+  kitchen array names persons
+

+returns all indexes currently stored in the persons array. +

+

Similarly Tcl´s incr command is mapped to the +object system. A call with the syntax: +

+
+  objName incr varName ?value?
+

+increments varName with the given value (or without given +value with 1). +

+

Methods for Objects +

+

Methods in XOTcl resemble Tcl-procedures. On objects one can define +object-specific methods, called procs. Instance methods which are +defined on classes are called instprocs. A new proc is defined using +the proc instance method of the class Object: +

+
+  objName proc name args body
+

+The arguments of the proc instance method specify the name, +the arguments as a Tcl-list, and the body of the new proc. All of them +must be given, only one of args and body may be +empty. An example proc would be a method to let persons enter the +kitchen: +

+
+  kitchen proc enter {name} {
+    [self] set persons($name) [clock seconds]
+  }
+

+Here the predefined self command is used in one of three +possible ways, which allow us to access useful information when working +with XOTcl-methods, these are in particular: +

+
    +
  • self: returns the + name of the object, which is currently in execution. This + command is similar to this in C++. It is + automatically generated on each object. If it is called from + outside of an XOTcl method, it produces the error message + "Can't find self". +

    +
  • self class: the self + command with the argument class returns the name of the + class, which holds the currently executing instproc. Note, that this + may be different to the class of the current object. If it is called + from a proc it returns an empty string. +

    +
  • self proc: the self command with the argument + proc returns the name of the currently executing + method (proc or instproc). +

    +
+

The method enter can be written in XOTcl as well with +less syntactic overhead by using the predefined primitive my +instead of [self]:

+
+  kitchen proc enter {name} {
+    my set persons($name) [clock seconds]
+  }
+

+

Note, that there is a difference to the realization of these +object informations to OTcl. XOTcl uses commands in order to make +XOTcl-methods compatible to Tcl-procedures and accessible via +namespace-paths. OTcl uses the three variables self, class +and proc, which are filled automatically with proper values +by the interpreter each time a method is called. To gain backwards +compatibility XOTcl can be compiled with -DAUTOVARS to +provide these variables additionally. By default this option is turned off. +

+

Each XOTcl-method has its own scope for definition of local +variables for the executing method. In most cases when a method uses +object-variables, it is likely that the programmer wants to make one +or more of these variables part of the method's scope. Then the +Tcl-command for variable handling, like set, lindex, +array, ... work also on these variables. The +instvar instance method links a variable to the scope of +an executing method. It has the syntax: +

+
+  objName instvar v1 ?v2 ... vn?
+
+

+It makes the variables v1 ... vn, which must +be variables of the object, part of the current method's scope. A +special syntax is: +

+
+  objName instvar {varName aliasName} ...
+
+

+for one of the variables. This gives the variable with the name +varName the alias aliasName. This way the variables +can be linked to the methods scope, even if a variable with that name +already exists in the scope. Now the enter method can be +adapted slightly and a leave method can be added, which uses +Tcl's info command to check +whether the named person is in the object's persons array. To +demonstrate the alias-syntax this is done with the persons +array and the alias p. +

+
+  kitchen proc enter {name} {
+    my instvar persons
+    set persons($name) [clock seconds]
+  }
+
+  kitchen proc leave {name} {
+    my instvar {persons p}
+    if {[info exists p($name)]} {
+      puts "$name leaves after [expr {[clock seconds]-$p($name)}] seconds" 
+      unset p($name) 
+    } else {
+      puts "$name is not in the room"
+    }
+  }
+
+A method defined via proc can be deleted by proc using +an empty argument list and an empty body. The following example deletes the method +enter: +
+  Room proc enter {} {}
+
+ +

+Information about Objects +

+

XOTcl offers reading and writing +introspection. The reading introspection abilities are packed +compactly into the info instance method which is available +for objects and classes (there are special info options for object +aggregations, nested classes, mixins, filters, meta-data and +assertions, which are explained separately in the following +sections). +

+
+

+ Options for the info method on objects

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ objName info args methodName + +

Returns the arguments of the specified proc (object specific method).

+
+ objName info body methodName + +

Returns the body of the specified proc.

+
objName info class ?className? + +

Returns the name of the class of the current + object, if className was not specified. Otherwise it + returns 1 if className matches the object's class and 0 if + not. +

+
objName info commands ?pattern? + +

Returns all commands defined on the object + if pattern was not specified. Otherwise it + returns all commands that match the pattern.

+
objName info default methodName arg var

+
+

Returns 1 if the argument arg of + the specified proc has a default value, otherwise 0. If + the default value exists it is stored in var.

+
objName info precedence ?pattern? + +

Returns all classes in the precedence order + from which the specified object inherits methods. The + returned list of classes contains the mixin and instmixin + classes as well as the classes of the superclass chain in + linearized order (i.e., duplicate classes are removed). If + the pattern is specified, only matching classes are + returned.

+
objName info vars ?pattern? + +

Returns all variables defined on the object + if pattern was not specified, otherwise it returns + all variables that match the pattern.

+
+ +
+


+

For example on the kitchen object +

+
+  kitchen info procs
+

+returns enter and leave as a Tcl-list since these +are the procs defined on the object. +

+

Classes +

+

Creating Classes and deriving +Instances +

+

There are different ways to create a class in XOTcl. They have in +common that they derive the new class from a meta-class. Initially the +Class command provides access to the meta-class +Class, which holds the features common to all classes. It +also allows one to derive new meta-classes. The common way to create a +new class is: +

+
+  Class className ?args?
+
+ +

+Similar to the object short form, this is a short form of a call to +the create instance method of the meta-class Class, +which is also executed by the standard unknown mechanism. +This mechanism is always triggered when XOTcl does not know a method +called on an object. Supposed that there is no method with the name +className, defined on the class-object of Class, +XOTcl looks up the method unknown (which is found on the +Class Object) and executes it. The standard unknown-mechanism +of XOTcl calls create with all arguments stepping one step +to the right; in the general case: +

+
+  Class create className ?args?
+

+This may also be called directly. Besides the indirection when using +unknown, in most cases there is no difference in the action +performed: Firstly the memory is allocated, using the alloc +instance method; as the next step the constructor init is called +on the creating object, which is in this case the class-object of the +meta-class Class. In seldom cases the programmer may want to +suppress the init call. To do so the alloc instance +method may also be called directly: +

+
+  Class alloc className ?args?
+
+

+As seen in the preceding section objects are created in the same way. +The difference was, that the command Object, which accesses +a class, instead of the command Class, which accesses a +meta-class, was used. The user-defined classes may also be used in +the same way to create new objects: +

+
+  className objName ?args?
+
+

+Resembling the creation of classes this creates an object objName +of type className using the unknown mechanism. That +means the create instance method of the class is called. If +there is no other instance method defined on the class-path so far +(which would mean, an user defined creation process is invoked), the +create instance method of the class Object is +invoked. This method is similar to the create method of the +meta-class Class. It firstly calls the alloc +instance method on its (of the Class class) which allocates +memory for the object, and makes it an instance of it's class. +Afterwards a call to the constructor init is invoked. +

+

Now we can specify the object for the kitchen by the class to +which it belongs. In this case a kitchen is an instance of a room. +

+
+  Class Room
+  Room kitchen
+

+A set call on a class creates an instance variable on the +class-object. This variable is unique for all instances, therefore, +it may be referred to as a class variable. +

+

Methods Defined in Classes +

+

Methods which are defined in classes and which are provided to the +instances of these classes are called "instprocs". +The syntax for defining an instproc is: +

+
+  className instproc procname args body
+
+

+It is similar to the definition of procs on objects, but uses the +keyword instproc to distinguish between the methods defined +on the class-object and those defined on the class. Since all rooms +(in the modeled world) have ceilings, we may want to define a simple +convenience instproc, which is able to set the color: +

+
+  Room instproc setCeilingColor color {
+    my set ceilingColor $color
+  }
+

+A special instproc, the constructor init, was mentioned +already. Now we are able to define such an instproc. Defined on a +class it is responsible for all initialization tasks, which needed to +be performed, when constructing a new instance object of the class. +The constructor of the Room can initialize a variable for +the color, in which the ceiling is painted, to white as default, +since this is the color of ceilings without painting. +

+
+  Room instproc init args {
+    my setCeilingColor white
+    next
+  }
+
+

+After this definition, all instances derived from the Room +class have an instance variable ceilingColor with the value +white. The args argument used here is a special +argument in Tcl which allows us to use a list of arguments which may +change its length from call to call. +

+An instproc can be deleted by the method instproc as well. +If instproc is called with an empty argument list and an +empty body, the specified method is deleted, as the following example shows: +

+  Room instproc setCeilingColor {} {}
+
+ +

+

Information about Classes +

+

Resembling to objects, information on +classes may be gained through the info instance method of the +meta-class Class. Note that this instance method does not +only support the class info options, but also the object info options, +since the accessing command refers to the class-object, which itself +is an object and, therefore, offers its informations. The following +table summarizes the additional info options available on classes. +

+
+

Options for the info method on classes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
className info heritage ?pattern? +

Returns a list of all classes in the + precedence order of the class hierarchy matching + pattern or a list of all classes, if + pattern was not specified.

+
className info instances ?pattern? +

Returns a list of the instances of the + class matching pattern or of all instances, if + pattern was not specified. +

+
className info instargs methodName +

Returns the arguments of the specified instproc + (method provided to objects).

+
className info instbody methodName +

Returns the body of the specified instproc.

+
className info instcommands ?pattern? +

Returns all commands defined on the class, if + pattern was not specified, otherwise it returns all + commands provided to objects that match the pattern.

+
className info instdefault methodName arg var

+
+

Returns 1 if the argument arg of + the specified instproc has a default value, otherwise 0. If + the default value exists it is stored in var.

+
className info subclass ?className2? +

Returns a list of all subclasses of the class, if + className2 was not specified, otherwise it returns 1 if + className2 is a subclass and 0 if not.

+
className info superclass ?className2? +

Returns a list of all super-classes of the class, + if className2 was not specified, otherwise it returns 1 + if className2 is a superclass and 0 if not.

+
+
+

The full list of info options is provided in the language reference.

+

Inheritance +

+

Besides encapsulation of operations and state in objects, a second +central ability of object-orientation is inheritance. XOTcl supports +single and multiple inheritance with a directed acyclic class +graph. Automatically each new class created by the instance methods +create and alloc of Class inherits from +Object. Therefore, it is ensured that all instances of the +new class have access to the common features of objects stored in the +class Object. +

+

To specify further inheritance relationships the instance methods +superclass of Class is used: +

+
+  className -superclass classList
+

+E.g. in the example a kitchen may be seen as a +special room: +

+
+  Class Room
+  Class Kitchen -superclass Room
+

+Now all instances of Kitchen are able to access the +operations stored in the Room and in the Kitchen class. +Note the transition the kitchen was going through: firstly it was a +singular object, then it was an object with a user-defined class, +and now it is a class. This is possible (and not senseless) because +of the per-object specialization ability and the dual shape of a +class, which is at the same time object and class. Both lead to a +seamless connection of the run-time properties (the object features) +and their descriptive properties (the class features). It is possible +to avoid the strict distinction between them, known from static typed +languages, like C++, Java, etc. +

+

Moreover, since the syntaxes of constructs expressing the same +concern are nearly identical, we can re-factor a solution with very few +changes to the alternative. We will see similar "ease of refactoring" +throughout the XOTcl language. E.g., we can also easily re-factor the +class hierarchies or exchange class hierarchies against mixin +solutions with only slight changes in the code. +

+

Besides single inheritance, as seen, XOTcl provides also multiple +inheritance. This is syntactically solved by giving the superclass +instance method a list of classes instead of a single class as +argument. +

+
+  Class Room
+  Class 4WallsRoom -superclass Room
+  Class CookingPlace
+  Class Kitchen -superclass {4WallsRoom CookingPlace}
+

+Now the kitchen class is specialized a bit more. It is a special room +which has four walls and it is a cooking place. Multiple +inheritance, as seen here, is as simple to apply as single +inheritance. +

+ +Most often when the disadvantages of multiple inheritance are +discussed, the name resolution along the class graph is considered as +the biggest problem. The question is, which method is to be chosen and +which path through class graph is to be taken, if more then one method +of the specified name exist on the class graph. + +

+

In the example such questions +would arise for an object of the Kitchen class, if two +same-named methods are defined on CookingPlace and +4WallsRoom or if a method of the class Object is +called, which is reachable through two paths (along +CookingPlace or Room). +

+ +

Often - e.g. in the +inheritance model of C++ - the path through the graph is not clearly +determined and/or the rules are too complicated to be understood on +the first glance. The programmer often can only determine by trial +which method is found firstly. Than an explicit naming of the class is +necessary, which means storage of non-local information in +sub-classes. Often different compilers of one language behave +differently. All these issues make code reuse difficult. Moreover +understandability and portability are reduced. +

+


+

+

Figure 3: +The example classes and the following next-path

+
+ + + + + +
+
+
+

XOTcl goes an intuitive and unambiguous way to solve this problem. +It resolutes the precedence order along a ``next-path''. +Firstly the class of the object is searched, which is Kitchen +in example. Then the super-classes are searched in definition order, +which means at first 4WallsRoom, then CookingPlace. +Each branch is searched completely, before changing to the next +branch. That means, Room is searched, before the +CookingPlace branch is visited. At last the top of the +hierarchy, the class Object, is searched. +

+ +

The usage of next in XOTcl is different to OTcl: In OTcl, + next is defined as a method, in XOTcl it is a + primitive command. Furthermore, in OTcl, +it is always necessary to provide the full argument list for every +invocation explicitly. In XOTcl, a call of next without +arguments can be used to call the shadowed methods with the same +arguments (which is the most common case). When arguments should be +changed for the shadowed methods, they must be provided explicitly in +XOTcl as well. In the rare case that the shadowed method should +receive no argument, the flag --noArgs must be used. +

+ +

Destruction of Classes +

+

Classes are destroyed by the destruction of the class-object using +the destroy method of the Object class. The +destruction of super-classes does not destroy the sub-classes. The +super-class is simply removed from the sub-classes' super-class +lists. All classes have the super-class Object, if no +super-class is specified. Therefore, if all super-classes are +destroyed or removed, the new super-class is Object, not: no +super-class. The destruction of the class of an object does neither +delete the object nor leave it without class. In XOTcl a deleted class +leaves it's instances with the class Object. +

+

So all empty class- and superclass-relationships are automatically +reseted to Object. Note, that this are differences to OTcl, +where the destruction of an class destroys all instances and an empty +super-class list remains empty. +

+

Method Chaining +

+

A special feature of XOTcl is the method chaining without explicit +naming of the ``mix-in''-method. It allows one to mix the same-named +superclass methods into the current method (modeled after CLOS). The +previously described next-path is the basis for this functionality. +At the point marked by a call to the next primitive of XOTcl +the next shadowed method on the next path is searched and, when it is +found, it is mixed into the execution of the current method. When no +method is found, the call of next returns an empty string, +otherwise it returns the result of the called method. +The syntax is: +

+
+  next ?arguments|--noArgs?
+

+As stated earlier the usage of next in XOTcl differs from +OTcl, since the next call without arguments in OTcl means +per default that no arguments are passed. But most often all +arguments are passed through to the shadowed methods (since these will +most likely have the same signatures). When all +variables should be passed through, in OTcl it is necessary for +correct variable substitution to use: +

+
+  eval $self next $args
+

+To avoid such difficulties, we made the passing of all arguments the +default case; a simple +

+
+  next
+

+performs the task of passing all arguments to the shadowed methods. +These arguments are called the standard arguments. If the +standard argument feature should not be used, optionally arguments +can be given or the flag --noArgs could be set as sole +argument, which means that the shadowed method is called with no +arguments. +

+

+E.g. the following next call ignores the standard arguments +and sends the arguments 1 and 2 instead: +

+
+  next 1 2
+

+ +

As an example all classes involved in the previous example should +get a constructor instance method, which simply sets an instance +variable on the object: +

+
+  Room instproc init args {
+    my set roomNumber 0
+    next
+  }    
+  4WallsRoom instproc init args {
+    my set doorPosition 0
+    next
+  }
+  CookingPlace instproc init args {
+    my set stoveType electric
+    next
+  }
+  Kitchen instproc init args {
+    my set cookName -
+    next
+  }
+

+After creation an object of class Kitchen gets automatically +four instance variables cookName, roomNumber, +doorPosition and stoveType set up with default +values in this order (since this is the order of the classes in the +next-path). Note, that the order is important, because one missing +next call, in one of the init methods, means that succeeding +init methods will not be executed. This mechanism functions +equally on all kinds of instprocs, not only on constructors. +

+

The constructors use the args argument, which allows us to +give a list of variable length as arguments. To ensure reusability of +our classes the constructors should use args in most cases, +since they may pass through arguments for constructors further up the +class hierarchy. +

+

If a proc with the searched name exists on the object it +shadows all instprocs. A next call in a proc leads to +the normal next-paths search, starting with the object's class. +

+

By the way, an observant reader might notice that the example +above can be rewritten without explicit constructors, just by +using parameters with default values. +

+
+  Class Room -parameter {{roomNumber 0}}
+  Class 4WallsRoom -superclass Room -parameter {{doorPosition 0}}
+  Class CookingPlace -parameter {{stoveType electric}}
+  Class Kitchen -superclass {4WallsRoom CookingPlace} -parameter {{cookName -}}
+

+If an instance of a Kitchen is created it will contain instance +variables for doorPosition, cookName, +roomNumber, and stoveType, as the following +statements will show.

+
+  Kitchen k
+  puts [k info vars]
+
+ + +

Dynamic Class and Superclass +Relationships +

+

Another property of XOTcl that distinguishes it from statically typed +languages are dynamics of class relationships. The realization of the +definition of super-classes as seen above with the superclass +method suggests already, that it is not only available at the class +definition time. In the above example its appended to the class +definition with "-superclass" as a short syntax +for method invocation at definition time (all other available methods +can also be called with a preceding dash ("-") appended +to definitions). +

+

At any time the class graph may be changed entirely using the +superclass method. Suppose the rooms and kitchens created in +modeling of a house should be displayed to a screen, but it is not +determined, whether the user of the system has the possibilities for +graphical outputs. Two classes TextOutput and +GraphicalOutput may be defined, which handle the output. Both +have an instproc paint which does the painting of the virtual +world on the chosen display type. The common output requirements are +handled by a derived class VirtualWorldOutput which calls the +paint method of the superclass using next. In +statically typed languages it would need more sophisticated constructs +to change the output class at run-time. E.g. a delegation to another +object handling the intrinsic task of the output object would be +introduced solely for the purpose of configuring the output +form. With a dynamic class system we can use the superclass +method to do so easily: +

+
+  Class TextOutput
+  TextOutput instproc paint args {
+    # do the painting ...
+  }
+  Class GraphicalOutput
+  GraphicalOutput instproc paint args {
+    # do the painting ...
+  }
+
+  # initially we use textual output
+  Class VirtualWorldOutput -superclass TextOutput
+  VirtualWorldOutput instproc paint args {
+    # do the common computations for painting ...
+    next; # and call the actual output
+  }
+
+  # user decides to change to graphical output
+  VirtualWorldOutput superclass GraphicalOutput
+
+

+Sometimes, such a change to new intrinsic properties should not happen +for all instances of a class (or the class hierarchy), but only for +one specific object. Then the usage of a dynamic super-class +relationship is a too coarse-grained means. A second form of such +dynamics is the changing of the relationship between object and +class. This means, objects can also change their class dynamically at +run-time. This feature may be used to model a life-cycle of an object, +without loosing the object's identity, inner state or +per-object-specializations through procs. The class instance +method enables this functionality. +

+

An example would be an agent for the virtual world. Agents may be +placeholders for persons, who interactively travel the world, or +programs, which act automatically. When a person decides at run-time +to give a task it has performed formerly by hand to an automatic +agent, the agents nature changes from interactive agent to automatic +agent, but the identity and the local state (that means the parts of +the task, that are already fulfilled by the person) stay the same. +This is a scenario for changing class relationships, e.g.: +

+
+  Class Agent
+  Class AutomaticAgent -superclass Agent
+  Class InteractiveAgent -superclass Agent
+
+  # create a new agent for a person
+  InteractiveAgent agent1
+
+  # the person does something ...
+  # and decides the change to an automatic agent
+  agent1 class AutomaticAgent
+
+ +

+Meta-Classes +

+

Meta-classes are a special kind of classes. Similar as classes are +managing objects (where managing means: control the creation and +destruction of instances, know what instances exist, provide methods), +meta-classes are managing classes. So, meta-classes are used to define +classes. In other words, every Class in XOTcl is created by a +meta-class, in most cases by the meta-class named Class. New +user-defined meta-classes can be defined as subclasses of the +predefined meta-class Class, or by adding an instmixin class +(see below) containing Class +to the precedence chain of the class. By defining Object +instmixin Class one can even change the object system of XOTcl in +in a way such that every created Object is a meta-class. +

+

Since the concept of a meta-class are sometimes +confusing to people of a background of some other programming +languages, we explain meta-classes slowly with the analogy of classes +and objects. +

+

+When a class Foo is created via the command +

+   Class Foo
+
+ it has no private variables and no special methods. This is + somewhat similar as creating an object via Object: +
+   Object foo
+
+ This plain object foo can be configured directly, or + one can create a class that configures the object. + Instead of writing +
+   Object foo 
+   foo set x 1
+   foo proc hi {} {puts "hello"}
+
+ one can use +
+   Class C -superclass Object
+   C instproc init {} {my set x 1}
+   C instproc hi {} {puts "hello"}
+
+ and create an instance and call the method. +
+   C c1
+   c1 hi
+
+ The same holds for meta-classes and classes as well: Instead of writing +
+   Class Foo
+   Foo set x 1
+   Foo proc hi {} {puts "hello"}
+
+ the following can be used: +
+   Class MC -superclass Class
+   MC instproc init {} {my set x 1}
+   MC instproc hi {} {puts "hello"}
+
+ The instances of meta-classes are classes which can be + defined the usual way: +
+   MC Bar
+   Bar hi
+   Bar b1
+
+ Now we have a class names Bar which has a class-scoped + variable named x with the value of 1 (set via the + constructor); the class Bar has as well a class-method named + hi which prints, when called, the string "hello". The class + Bar can be used to create instances of the class like + b1, b2 and so on. +

+

Note that the command Class is a predefined definition +of the most general meta-class in XOTcl. Each time we are creating +a class, we use this meta-class. +In order to define a specialized meta-class, we can do this the +traditional object-oriented way: we subclass. Therefore, in to define +a specialized meta-class, we can use: +

+
+  Class myMetaClass -superclass Class
+
+

This defines a new meta-class myMetaClass, which has all the +abilities of meta-classes. That means that the programmer is able to +specify new class features or override old ones. Later she/he may +instantiate these into new classes. +

+

This is a very powerful language feature, since it allows one to give +some classes further abilities than the others (or to restrict +classes). This way large program structures, like certain design +pattern parts, may be instantiated. Meta-classes hold the common +abstract parts of the structures. They allow one to form libraries of +such structures very easily. +

+

Example 1: Overloading the info method of classes +

+

+As a simple example we can derive a new meta-class +NoClassInfo from Class. Later we override the +info method of Class. Thus the classes created with +NoClassInfo, have an info option that only produces +an error message. All classes created with NoClassInfo, like +Agent in the example below, are not capable of accessing the class +info method anymore: +

+
+  Class NoClassInfo -superclass Class
+  # redefine info ability
+  NoClassInfo instproc info args {
+    error "No class info available"
+  }
+  # derive agent class from meta-class, which
+  # can not access class info
+  NoClassInfo Agent
+
+Now a call like: +
+  Agent info superclass
+

+triggers the error message. +

+ +

Example 2: Defining Classes that Count Their Instances +

+

Meta-classes are frequently used to define some bookkeeping +about the number of instances on the class level. In the following +example we define a meta-class named CountedClass which +defines classes that count their instances: +

+  Class CountedClass -superclass Class -parameter {{counter 0}}
+  CountedClass instproc create args {
+    my incr counter
+    next
+  }
+  CountedClass instproc instdestroy args {
+    my incr counter -1
+    next
+  }
+  CountedClass Dog
+
+  Dog piffie
+  Dog idefix
+  puts "nr of dogs: [Dog counter]"
+
+  piffie destroy
+  puts "nr of dogs: [Dog counter]"
+
+Note that the behavior introduced by meta-classes +can be orthogonal to the behavior of the classes. One can +define Dog as a specialization of Animal +or defines a special kind of dog such as Poodle using +the method superclass as usual. +

+ +

Example 3: The Singleton Meta-Class +

+

Finally, a small example, which is more practical. Some +applications have the requirement that only one instance of a class +might be defined at a certain time. Such a behavior is frequently +called a "Singleton". In XOTcl we can define a class singleton by +overloading the create method of Class: when +create is called and there exists already an instance of the +singleton it is returned instead of a new instance. +

+  Class Singleton -superclass Class
+  Singleton instproc create args {
+    expr {[my exists instance] ? [my set instance] : [my set instance [next]]}
+  }
+
+ If someone wants to have a class e.g. Manager to be a + singleton, you can create it by e.g. +
+  Singleton Manager -superclass FOO
+
+

+ + +

+Create, Destroy, and Recreate Methods +

+

+

+XOTcl allows since version 0.84 for a flexible destroy and recreate scheme. +create and alloc are both Class instprocs +handling creation for their instances. I.e.: +

+
+ className alloc [self]
+
+and +
+ className create [self]
+
+

+are used for creating an instance. A similar method instdestroy +exists on Class that handles physical destruction of an object. The +method destroy on Object which lets an object destroy itself in fact +has the following behavior: +

+
+  Object instproc destroy args {
+   [my info class] instdestroy [self]
+  }
+
+

+However, this behavior is not implemented in XOTcl, but in C. +create distinguishes between the following situations: +

+
    +
  • Create a new object: + By default create calls alloc and then + doInitializations. +
  • Recreate an existing object: + When the specified object exists, it is recreated through the + recreate method: +
    +  givenClass recreate [self]
    +
    +

    + The method recreate can be customized like all other + XOTcl methods (e.g. by overloading or interception). + By default recreate calls cleanup followed by + doInitializations. +

    +

    + Note, that recreate is not called, when a someone tries + to recreate a class as an object or an object as a class. In these + cases, destroy + create are used. +

    +    Class c
    +    Object c ;# here, "c" is downgraded to an object, no "recreate" is called
    +
    +
+

+For create and recreate, the method doInitializations +is called automatically from C and has the following default behavior: +

+
    +
  • Search for parameter default values, +
  • Call parameter initialization methods, +
  • Call the constructor init. +
+

+Each step has a method call that can be changed, intercepted, etc. Of +course, cleanup, recreate, instdestroy, +etc. can also be overloaded or intercepted. +

+

+Consider a typical case for overloading recreate: a structure +preserving recreate that cleans up the class but +preserves the existing class hierarchy (subclass and instance relationships): +

+
+  Class StructurePreservingRecreate
+  StructurePreservingRecreate instproc recreate {cl args} {
+    if {[my isclass $cl]} {
+      set subclass [$cl info subclass]
+      set instances [$cl info instances]
+    }
+    next
+    if {[my isclass $cl]} {
+      foreach sc $subclass {
+        $sc superclass $cl
+      }
+      foreach i $instances {
+        $i class $cl
+      }
+    }
+  }
+  Object instmixin add StructurePreservingRecreate
+
+

+Now the following code does not change the superclass or instance +relationships of C: +

+
+  Class A
+  Class B
+  Class C -superclass {A B}
+  Class D
+  Class E -superclass {C D}
+  C c1
+  C c2
+
+  # recreate -> is structure preserving
+  Class C -superclass {A B}
+  C c2
+
+  # test
+  puts superclass=[C info superclass]
+  puts subclass=[C info subclass]
+  puts instances=[C info instances]
+  puts class=[c1 info class]
+  puts class=[c2 info class]
+
+ +Starting with XOTcl 1.4.0, xotcl provides also a user-friendly +way for a structure-prevering recreate implemented in C. Since this version, one +can configure "softrecreate" as follow. +
+::xotcl::configure softrecreate true
+
+This command causes that recreates are structure-conservative. + +

+Methods with Non-Positional Arguments +

+

+

+So far we have introduced methods only with positional arguments: that +is, the position of an argument in the argument list determines to +which local variable the argument is bound, when the method is +invoked. Sometimes non-positional arguments -- arguments that carry +both a name and a value when the method is invoked -- are +useful. Before a non-positional argument can be used, it must be +defined in the method definition using the following syntax: +

+
+ className instproc methodName ?non-pos-args? args body ?assertions
+ objName proc methodName ?non-pos-args? args body ?assertions
+
+

+The non-positional arguments are defined with the following syntax: +

+
+ {-name?:checkoption1, checkoption2, ...? default value} \
+     {-name?:checkoption1, checkoption2, ...? ?default value?} ...
+
+

+Only the name of the non-positional argument is really required, all +other parts of this syntax are optional. +

+

+Let's consider a simple example, where a method with two +non-positional args is defined; one has only a name ("a"), and one has +a name and a default value (b): +

+
+ Object o
+ o proc someproc {-a {-b {1 2 3}} x y} {
+     puts "$a $b $x $y"
+ }
+

+We can invoke this method as follows: +

+
+ o someproc -b {4 5} -a 1 3 4
+

+ +Here, the order of a and b can be changed; hence the name +non-positional arguments. As b has a default value, we do not need +to provide a value for it. In the following invocation b has the +value "1 2 3": +

+
+ o someproc -a 1 3 4
+

+The ordinary arguments start after the last non-positional argument +(here: "3 4"). We can explicitly end the non-positional arguments by +using "--". This is useful if we want to provide arguments that contain +dashes ("-"), e.g.: +

+
+ o someproc -a 1 -- -b -c
+

+ +Sometimes we want to check or control the non-positional +arguments. For instance, in the above invocation, we might want to +check that a is not forgotten, because otherwise the method cannot +execute properly. This is the role of the checkoptions. There are three +predefined checkoptions: required, boolean and +switch. required checks +whether a non-positional argument is given, boolean checks that a +non-positional argument is of boolean type. For instance: +

+
+ Class P
+ P instproc someproc {-a:required {-b:boolean true}} {
+     puts "$a $b"
+ }
+ P p
+

+ +This method requires a, and b needs to be +of type boolean (is has +the default value true). This invocation is valid: +

+
+ p someproc -a 1 -b 0
+

+ +This invocation is invalid, because a is missing, +and b is not a Tcl boolean type: +

+
+ p someproc -b " a b v"
+

+The checkoption switch is similar to boolean except +it does not require an additional argument. If the default value is +false, the switch can be turned on, if the default is true +it can be switched off. +

+The checkoptions are extensible. In fact, they are defined in an +object ::xotcl::nonposArgs. We can extend this object with new +methods. + +A check option method has the following syntax: +

+
+ someobject|someclass proc|instproc methodName {?optional nonpositional arguments? argName arg} {
+  ...
+ }
+
+

+ +argName is here used to denote the name of the argument, +and arg is the provided value. +

+ + + + +Of course, the non-positional arguments can also be introspected. The +following info options return the non-positional arguments of a +method: + +

+
+ objName info nonposargs methodName
+ className info instnonposargs methodName
+

+ + + + + + + + +
+

Message +Interception Techniques + +

+
+
+ +

Even though object-orientation orders program structures around +data, objects are characterized primarily by their behavior. +Object-oriented programming style encourages the access of +encapsulated data only through the methods of an object, since this +enables data abstractions. A method invocation can be interpreted as a +message exchange between the calling and the called object. +Therefore, objects are at runtime only traceable through their message +exchanges. At this point the message interceptors can be applied to +catch and manipulate all incoming and outgoing messages of an +object. +

+

Generally interceptors can be applied to attach additional or +extrinsic concerns to an object or a class or a class hierarchy. For +instance roles or aspects can be implemented this way on various +levels of scale. +

+ +

We have already discussed some interception techniques +implicitly. E.g., the unknown mechanism intercepts messages +that have not be found on the object. It can be used as a very useful +programming technique, e.g., the define a default behavior for an +object. The interceptors presented in this section have a different +character: They are applied before/after the original method even +if the method is defined for the target object. Thus these +interception techniques may be applied +

+ +

We will discuss the message interceptors in this section in +detail. The table below gives an impression, when which interceptor +may be applied. + +

Message + Interceptors Overview

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Applied When

Primary Target Structure

Coverage

Per-Object Filter

before/after a call

object hierarchies

all methods

Per-Class Filter

before/after a call

class and class hierarchies

all methods

Per-Object Mixin

before/after a call

object

specific methods

Per-Class Mixin

before/after a call

class and class hierarchies

specific methods

Unknown Mechanism

after method was not found

object

all unknown calls

+
+ +
+ +

Filter +

+ +

The filter (see [Neumann and Zdun +1999a] for more details) is a language construct to implement +broader extensional concerns either for a single object or for several +classes or class hierarchies. This way large program structures at the +scale of several classes or class hierarchies can be managed. It is a +very general interception mechanism which can be used in various +application areas. E.g. a very powerful programming language support +for certain design patterns is easily achievable, but there are also +several other domains which are covered, like tracing of program +structures, self-documentation at run-time, re-interpretation of the +running program, etc. +

+

A per-class filter is a special instance method that is +registered for a class C. A per-object filter is a +special instance method that is registered for a object +o. Every time an object of class, C or the object +o respectively, receives a message, +the filter method is invoked automatically. +

+

Usage of Filters +

+

All messages to a filtered object must go through the filter before +they reach their destination object. A simple example would be a sole +filter on the class of the object. To define such a filter two steps +are necessary. Firstly an filter method has to be defined, then the +filter has to be registered. The filter method consists of three parts +which are all optional. A filter method has the following form: +

+
+  className instproc FilterName args {
+    pre-part
+    next
+    post-part
+  }
+
+

+When a filter comes to execution at first the actions in the pre-part +are processed. The filter is free in what it does with the +message. Especially it can (a) pass the message, which was perhaps +modified in the pre-part, to other filters and finally to +the object. It can (b) redirect it to another destination. Or it can +(c) decide to handle the message on its own. The forward passing of +messages is implemented through the next primitive of XOTcl. +After the filter has passed its pre-part, the actual called method is +invoked through next. +

+

After the call of next is processed, the execution returns +to the point in the filter, where the next call is located +and resumes execution with the actions of the post-part. +These may contain arbitrary statements, but especially may take the +result of the actual called method (which is returned by the +next-call) and modify it. The caller then receives the result of the +filter, instead of the result of the actual called method. +

+

The pre- and post-part may be filled with any ordinary +XOTcl-statements. The distinction between the three parts is just a +naming convention for explanation purposes. +

+

The filter uses the args argument which lets us use a list of +variable length as arguments, since it must filter a lot of different +calls, which may have different argument lists. Furthermore, it may +pass through arguments to other filters and the preceding filters may +change the argument list. +

+

Since any proc/instproc may be a filter, a registration of the +filter is necessary, in order to tell XOTcl, which instprocs are +filters on which classes. The filter and instfilter +instance methods are able to handle this task for per-object filters +and per-class filters respectively. Similar to the XOTcl language +introduced so far, the filter registration is dynamic at run-time. By +supplying a new list of filters to +filter/instfilter, the programmer can change the +filters registered on a class at arbitrary times. The filter instance +method has the syntax: +

+
+  className instfilter filterList
+
+for per-class filters and: +
+  objName filter filterList
+
+for per-object filters. + +

+Now a simple example should show the filter's usage. In the preceding +examples we have defined several rooms. Every time a room action +occurs it is likely that the graphical sub-system has to change +something on the output of that particular room. Therefore, at first +we need a facility to be informed every time an action on a room +happens. This is quite easily done using filters: +

+
+  Class Room
+  Room r1; Room r2;       # just two test objects
+
+  Room instproc roomObservationFilter args {
+    puts "now a room action begins"
+    set result [next]
+    puts "now a room action ends - Result: $result"
+    return $result
+  }
+
+  Room instfilter roomObservationFilter
+

+Now every action performed on room objects is notified with a pre- +and a post-message to the standard output stream. We return the +result of the actual called method, since we don't want to change the +program behavior at all. E.g. we can set an instance variable on both +of the two room objects: +

+
+  r1 set name "room 1"
+  r2 set name "room 2"
+

+The output would be: +

+
+  now a room action begins
+  now a room action ends - Result: room 1
+  now a room action begins
+  now a room action ends - Result: room 2
+

+
+

+

+   +

+

Figure 4: +Cascaded Message Filtering

+
+ + + + + +
+

+
+
+



+

+

All classes may have more than one filter. In fact they may have a +whole filter chain, where the filters are cascaded through next. +The next method is responsible for the forwarding of +messages to the remaining filters in the chain one by one till all +pre-parts are executed. Then the actual method is executed and +then the post-parts come to turn. If one next-call is omitted the +chain ends in this filter method. As an example for an additional +filter we may register a filter that just counts the calls to +rooms. +

+
+  Room set callCounter 0;  # set class variable
+  Room instproc counterFilter args {
+    [self class] instvar callCounter
+    incr callCounter
+    puts "the call number callCounter to a room object"
+    next
+  }
+  Room instfilter {roomObservationFilter counterFilter}
+

+Filters are invoked in registration order. The order may be changed +by removing them and adding them in new order. Filters are inherited +by sub-classes. E.g. in the preceding example for the next path, an +OvalOffice was derived from the Room class. Without +a change to the program each OvalOffice object automatically +produces the same filter output as rooms. +

+


+

+

+   +

+

Figure 5: +Filter Inheritance

+
+ + + + + +
+

+
+
+


Filter chains can also be combined through (multiple) +inheritance using the next method. When the filter chain of +the object's class is passed, the filter chains of the superclasses +are invoked using the same precedence order as for inheritance. Since +on the subclass there may also be a another filter chain, without +sophisticated computing in the pre- and post-parts one can produce +easily a powerful tracing facility. E.g. if we want to distinguish an +OvalOffice from other rooms we may want to add a filter +solely for rooms of the type OvalOffice: +

+
+  Class OvalOffice -superclass Room
+  OvalOffice o1;  # test object
+  OvalOffice instproc ovalOfficeObservationFilter args {
+    puts "actions in an oval office"
+    next
+  }
+  OvalOffice instfilter ovalOfficeObservationFilter
+

+A simple call to the o1 object, like: +

+
+  o1 set location "Washington"
+

+produces the following output: +

+
+  actions in an oval office
+  now a room action begins
+  the call number 3 to a room object
+  now a room action ends - Result: Washington
+

+As seen already, filter registrations can be added dynamically at +runtime. But they may also be removed. Perhaps the counting on rooms +should stop after a while, then a simple call of the instfilter +method is sufficient: +

+
+  Room instfilter roomObservationFilter
+
+

Filters can be removed completely by giving an empty list to the +registration method:

+
+  Room instfilter {}
+
+ + +

Per-object filters operate on a single object. E.g. if we only +want to observe a single Room object room1, we can use the filter +method to register the roomObservationFilter only for this particular +instance:

+
+  room1 filter roomObservationFilter
+
+

As a filter we can register any method in the precedence order of +the class or object. Thus we can also register procs as per-object +filters. Additionally, meta-class methods may be registered as +per-class filters. Filters are linearized so that each filter is only +executed once, even if it is registered multiple times. +

+



+

+

Introspection on Filters +

+In order to gain information about the currently registered filters on +a certain object/class, the object info option filters and +the class info option instfilters may be +queried. It returns a list of the currently registered filters: +

+
+  className info instfilter
+  objName info filter
+
+

+ +A special call-stack info option for filters is self +filterreg. It returns the name of the object or class on which +the filter is registered. Since the filter may be registered on other +objects/classes than the one on which it is defined, this may vary from +self class in the filter. + +The command returns a list of the form: +

+  objName filter filterName
+
+or: +
+  className instfilter filterName
+
+respectively. +

+ +



+

+

Example: A Simple Trace Filter +

+

The trace example primarily demonstrates the inheritance of filter +chains. Since all classes inherit from Object, a filter on +this class is applied on all messages to objects. The Trace +object encapsulates methods for managing the tracing: +

+
+  Object Trace
+  Trace set traceStream stdout
+
+  Trace proc openTraceFile name {
+    my set traceStream [open $name w]
+  }
+
+  Trace proc closeTraceFile {} {
+    close $Trace::traceStream
+    my set traceStream stdout
+  }
+
+  Trace proc puts line {
+    puts $Trace::traceStream $line
+  }
+
+  Trace proc add className {
+    $className instfilter [concat [$className info filter] traceFilter]
+  }
+

+First we define the object and set a variable for the stream to which +we send the trace outputs (here: stdout). With a method for opening +and a method for closing a file we can redirect the trace stream to a +file. puts is helper method for the filter to print an +output to the selected output stream. In add the traceFilter +is appended to the existing filters of a specified class. The actual +filter method (see below) displays the calls and exits of methods +with an according message. The calls are supplied with the arguments, +the exit traces contain the result values. We have to avoid the +tracing of the trace methods explicitly. +

+
+  Object instproc traceFilter args {
+    # don't trace the Trace object
+    if {[string equal [self] ::Trace]} {return [next]}
+    set context "[self class]->[self callingproc]"
+    set method [self calledproc]
+    switch -- $method {
+      proc -
+      instproc {::set dargs [list [lindex $args 0] [lindex $args 1] ...] }
+      default  {::set dargs $args }
+    }
+    Trace::puts "CALL $context>  [self]->$method $dargs"
+    set result [next]
+    Trace::puts "EXIT $context>  [self]->$method ($result)"
+    return $result
+  }
+

+As trace message we write the callee´s context (class and +proc), the invoked method (using calledproc), and the given +arguments. In the switch statement we avoid to print whole method +bodies. +

+

With +

+
+  Trace add Room
+

+messages to all rooms, including all instances of Room´s +sub-classes, are surrounded with a CALL and an EXIT output. With +

+
+  Trace add Object
+

+messages to all objects in an XOTcl environment are surrounded with a +CALL and an EXIT output. In general, it is possible to restrict the +trace to instances of certain classes, or to produce trace output for +only certain methods. This requires registration methods and a more +sophisticated implementation of the filter method. +

+



+

+ +

Mixin Classes +

+ +

Per-object and per-class mixins (see [Neumann and Zdun 1999c] for more details) are +another interception technique of XOTcl to handle complex +data-structures dynamically. Here, we use mixin as a short form for +mixin class. All methods which are mixed into the execution of the +current method, by method chaining or through a mixin class, are +called mixin methods. Mixin classes resembles the filter +presented in the preceding section. While the filters work on all +calls to all methods of an object/class hierarchy, the mixin classes +are applied on specific methods. The filter is defined in a single +method, while the mixin is composes several method in a class. + +

+

Supplemental Classes +

+

Mixin classes cover a problem which is not solvable elegantly just +by the method chaining, introduced so far. To bring in an addition to +a class, the normal XOTcl way is to define a mixin method and chain +the methods through next, e.g.: +

+
+  Class Basic
+  Basic instproc someProc  {
+    # do the basic computations
+  }
+  Class Addition
+  Addition instproc someProc {
+    # do the additional computations
+    next
+  }
+

+In order to mix-in the additional functionality of the supplemental +class Addition a new helper class (sometimes called +intersection class) has to be defined, like: +

+
+  Basic+Addition -superclass {Addition Basic}
+

+This is even applicable in a dynamical manner, every object of the +class Basic may be changed to class Basic+Addition +at arbitrary times, e.g.: +

+
+  Basic basicObj
+  ...
+  basicObj class Basic+Addition
+

+Now consider a situation with two addition classes. Then following +set of classes has to be defined to cover all possible combinations: +

+
+  Class Basic
+  Class Addition1
+  Class Addition2
+  Class Basic+Addition1 -superclass {Addition1 Basic}
+  Class Basic+Addition2 -superclass {Addition2 Basic}
+  Class Basic+Addition1+Addition2 -superclass {Addition2 Addition1 Basic}
+

+The number of necessary helper classes rises exponential. For n +additions, 2n-1 (or their permutations if order +matters) artificially constructed helper-classes are needed to +provide all combinations of additional mix-in functionality. +Furthermore it is possible that the number of additions is unlimited, +since the additions may produce other additions as side-effects. This +demonstrates clearly that the sub-class mechanism provides only a +poor mechanism for mix-in of orthogonal functionality. Therefore we +provide an extension in the form of object mixin classes, which are +added in front of the search precedence of classes. +

+

Per-Object Mixins +

+

The mix-ins methods extend the next-path of shadowed methods. +Therefore, per-object mix-in methods use the next primitive +to access the next shadowed method. Consider the following example: +

+
+  Class Agent
+  Agent instproc move {x y} { 
+    # do the movement
+  }
+  Class InteractiveAgent -superclass Agent
+  # Addition-Classes
+  Class MovementLog
+  MovementLog instproc move {x y} { 
+    # movement logging
+    next
+  }
+  Class MovementTest
+  MovementTest instproc move {x y} {
+    # movement testing
+    next
+  }
+

+An agent class is defined, which allows agents to move around. Some +of the agents may need logging of the movements, some need a testing +of the movements, and some both (perhaps only for a while). These +functionalities are achieved through the additional classes, which we +will apply through per-object mixins. +

+

Before we can use the per-object mix-ins on a particular object, +we must register the mixins on it with the mixin instance +method. It has the syntax: +

+
+  objName mixin mixinList
+

+ +For example we may create two interactive agents, where one is logged +and one is tested: +

+
+  InteractiveAgent i1; InteractiveAgent i2
+  i1 mixin MovementLog
+  i2 mixin MovementTest
+

+At arbitrary times the mixins can be changed dynamically. For example +i2's movements can also be logged: +

+
+  i2 mixin MovementTest MovementLog
+

+
+

+

+   +

+

Figure 6: +Per-Object Mix-ins: Next-Path for the Example

+
+ + + + + +
+

+
+
+



+

+

The mixin option of the info instance method +allows us to introspect the per-object mixins. It has the syntax: +

+
+  objName info mixin ?pattern?
+
+

+It returns the list of all mix-ins of the object, if pattern +is not specified, otherwise it returns the matching per object mixin classes. +

+ +The inverse operation of info mixin is mixinof finds +out, into which objects an per-object mixin class is mixed into. + +
+  clsName info mixinof ?pattern?
+
+ +

Note, that the constructors (init methods) of per-object mixins (and per-class mixins) +are only called, if the mixin is registered already during object +initialization (when init is called). For per-object mixins, one can +achieve the initialization of a mixin via an idiom like +

+  Object o -mixin M -init
+
+that registers the mixin before init is called. When a mixin is registered +after object creation and it needs initializations, it is necessary to +define special methods for this. Note, that the behavior described +here is introduced in version 0.84 to ensure consistent behavior of +intrinsic classes, per-object and per-class mixins, and to achieve +predictable behavior for dynamic registration for all kind of mixins, +and as well during recreations of objects having mixins +registered. Older versions used heuristics for the initialization of +per-object mixins. +

+ +

Per-Class Mixins +

+ +

Per-class mixins are exactly identical in their behavior to +per-object mixins, but they operate on classes. Thus they are the +class-specific variant of the per-object mixins, like instprocs are a +class-specific variant of procs. Therefore, in the language the +per-class mixins are called instmixins. +

+ +

+In general a per-class mixin is a class which is mixed into the +precedence order of all instances of the class and all its subclasses +it is registered for. It is also searched before the object's class +itself is searched, but after per-object mixins. +

+

+Per-class mixins are linearized according to the +precedence order +like classes on the superclass hierarchy. I.e. from the full +list of per-object mixins, per-class mixins, and intrinsic classes +(and all the superclasses of all these classes) always the last +occurrence is used. +

+ +

+From the point of view of language expressibility instmixins are not +required, because they cannot express anything that per-object mixins +cannot express already (like procs can express any instproc +feature). As alternative to instmixins, we could simply register the +per-object mixins in the constructor of the class. +

+ +

+But there at least the following reasons for instmixins as an +additional language construct: +

    +
  1. we can at runtime determine with info mixin +and info instmixin whether it is a class- or object-specific +mixin. Thus we get a better structuring at runtime. +
  2. We have not to 'pollute' the constructors with per-class mixin +registrations. Therefore, the constructors get more understandable. +
  3. If it is required to add (and remove) dynamically interceptors +to a set of objects, which are instances of a certain type, per-class +mixins are much easier to handle (e.g. add an instmixin to Object +to intercept e.g. all calls to certain predefined methods). +
  4. The language is more 'symmetrical', since any object-specific +feature in XOTcl has a class-specific variant. +
+

+ +

The mix-ins methods of per-class mixins extend the next-path of +shadowed methods in the same way as per-object mixin methods. Before +we can use a per-class mix-in on a particular class, we must +register the mixin on it with the instmixin instance method. It +has the syntax: +

+
+  className instmixin mixinList
+
+The inverse operation of info inmixin is instmixinof finds +out, into which objects an per-object mixin class is mixed into. + +
+  className info instmixinof ?-closure? ?pattern?
+
+

+Now consider that in the given per-object mixin example all +interactive agents should be tested. We could either build a subclass +TestedInteractiveAgent or register the per-object mixin in +the constructor of the interactive agent class. The subclass solution +leads to the same combinatorial explosion of intersection classes as +discussed in the previous section, if more supplemental classes are +added. The per-object mixin solution pollutes the constructor and does +not prevail the structural semantics that the 'tested' property +belongs to the interactive agent class at runtime +

+

+Here, we can use a per-class mixin: +

+
+  Class Agent
+  Agent instproc move {x y} {# do the movement}
+  Class InteractiveAgent -superclass Agent
+  Class MovementTest
+  MovementTest instproc move {x y} {
+    # movement testing
+    next
+  }
+
+  # now register the instmixin
+  InteractiveAgent instmixin MovementTest
+
+
+ +

The per-class mixin now operates on all interactive agent +including the instances of subclasses. E.g. for interactive agents +i1 and i2 we automatically have movement +testing. i2 is also logged, since it has the logging class +as object-specific mixin: +

+
+  InteractiveAgent i1
+  InteractiveAgent i2 -mixin MovementLog
+
+  i1 move 3 4
+  i2 move 1 2 
+
+ +

+At arbitrary times the instmixins can be changed dynamically. +

+

The instmixin option of the class info instance +method allows us to introspect the per-class mixins. It has the +syntax: +

+
+  className info instmixin ?className2?
+
+

+It returns the list of all instmixins of the the class, if className2 +is not specified, otherwise it returns 1, if className2 +is a mixin of the object, or 0 if not. +

+ +

Per-class mixins are applied transitively. That means the per-class +mixin A of a per-class mixin B is also applied for an object in in B's +scope. This is exactly the same as how superclasses are applied for +instances. Consider the following example

+ +
+  Class X11 \
+     -instproc test args {
+	puts [self class]
+	next
+     }
+  Class X12 \
+    -instproc test args {
+	puts [self class]
+	next
+    }
+  Class X \
+    -instmixin {X11 X12} \
+    -instproc test args {
+	puts [self class]
+	next
+    }
+
+  Class Y \
+    -instmixin X
+
+  Y create y -test
+  X create x -test
+
+

Here the application as a superclass (for x) yields the same +result as the application as an instmixin (for y): +

+  ::X11 
+  ::X12 
+  ::X
+
+

Precedence Order +

+ +

The precedence order is composed by the precedence order of the +superclass hierarchy (as explained earlier) and the message +interceptors. In general, filters precede mixins and the superclass +hierarchy. They are applied in the order of the next path of the +object. Thus per-object filters are ordered before per-class +filters.

+ +

Mixins are processed after the filters. Again, they are applied in +the order of the next path of the object. Thus per-object mixins are +ordered before per-class mixins.

+ +

Finally, the object's own heritage order comes in the order: object, +class, superclasses.

+ +

The three precedence order lists (filters, mixins, and classes) are +pre-calculated and cached.

+ +

Filters as well as classes (mixins and ordinary classes) are +linearized. That means, each filter and each class can be only once on +a precedence order list. If a filter or class can be reached more than +once, than the last occurrence is used.

+ +

For instance, consider a class A is superclass, per-class mixin, +and per-object mixin. On the precedence order lists only the last +occurrence as a superclass is used after linearization.

+ + +

Guards for Filters and Mixins +

+ +Message interceptors, such as filters and mixins, are applied for +potentially huge number of messages. In many cases it is possible to +reduce the effective number of cases in which interceptors are +applied. Interceptor guards offer this functionality: they are boolean +conditions with which you can specify in which cases a registered +interceptor should be applied. + +

Filter Guards

+

+A filter guard is a set of conditions that determine whether a filter +is to be executed upon a certain invocation or not. Syntactically we can +append a filter guard to the filter registration, or it can be +registered using the methods filterguard for filters and +instfilterguard for instfilters. + +

Each filter guard is an ordinary condition. A filter guard is +executed in the call frame of the filter to be executed, if the filter +guard returns 1. Thus, the call-stack information are already set to +the values of the targeted filter - and these values can be used in +the filter guard. + +

+Let us consider a simple program: +

+
+Class Room
+Room instproc enter {name} {puts [self proc]}
+Room instproc leave {name} {puts [self proc]}
+Room instproc loggingFilter args {
+    puts [self calledproc]
+    next
+}
+Room instfilter loggingFilter
+
+ +

+Now consider we only want to apply the logging filter for enter and +leave, not for any other message sent to Room instances. In the +following example, for instance, we do not want to log the set +message: +

+ +
+Room r 
+r enter Uwe
+r leave Uwe
+r set roomName "Office"
+
+ +

+In this example a filterguard can be applied to restrict the +application of the filter to those two methods: +

+ +
+Room instfilterguard loggingFilter {
+  [self calledproc] == "enter" || 
+  [self calledproc] == "leave"}
+
+ +

+Here we limit the filter application of the logging filter on rooms to +calls to enter and leave. All other calls are not filtered at +all. Note that the same syntax can also be applied for +filterguard. Also, there is a short form to register filter +guards directly during filter registration. The following code has the +same semantics as the filter and filter guard definitions above: +

+ +
+Room instfilter {{loggingFilter -guard {
+    [self calledproc] == "enter" || 
+    [self calledproc] == "leave"}}}
+

+ +The filter guard language construct is registration centric. It only +applies for the class or object on which a filter is registered, not +for all applications of the filter method. That is, if we use +loggingFilter on another class we may give no or completely +different filter guards. +

+If no filter guard is given for a filter, we assume that it is to be +applied on all methods (equivalent to the filter guard '1' which is +always true). +

+ +

+There are introspection options for filter guards. In particular, we +can use info filterguard and info instfilterguard +for getting the filter guards for a particular filter or instfilter +respectively. For instance: +

+
+puts [Room info instfilterguard loggingFilter]
+

+This prints out the content of the above guard definition. +We can also append -guard to info filter or +info instfilter to obtain a filter definition with guards: +

+
+puts [Room info instfilter -guards]
+

+ +

+If we call a method from within a filter guard, as for instance +callsMethod, we might require some parameters from the guard's +context, such as calledproc. These parameters can be passed +as references, as in the following example: +

+ +
+  Room instfilter loggingFilter
+  Room instfilterguard loggingFilter {[my callsMethod openURL [self calledproc]]}
+

+This example works because the filterguard is already set to the scope of the guard. Now we can use this dynamic calledproc context in the called method: +

+
+  Room instproc callsMethod {method calledproc} {
+    return[string match $calledproc $method]
+  }
+

+We simply check whether the called method +matches the given method name or not. + +

Mixin Guards

+

+Similar to filters, there are mixin guards, defined with +mixinguard and instmixinguard, or with +-guard during mixin registration. Consider a simple example: +there are a number of birds who have two mixins: Fly and Sing. For Fly +there are limitations: a bird can only fly if it is at least two years +old and is not a Penguin. Such problems are be solved with +mixin guards: +

+ +
+  Class Fly
+  Fly instproc fly {} {puts "[my signature]: yippee, fly like an eagle!"}
+
+  Class Sing
+  Sing instproc sing {} {puts "[my signature]: what a difference a day makes"}
+
+  Class Animal -parameter age
+  Animal instproc unknown args { puts "[my signature]: how should I $args?"}
+  Animal instproc signature {} {
+    return "[self] [my info class] ([my age] years)"
+  }
+
+  Class Bird -superclass Animal
+  Class Penguine -superclass Bird
+  Class Parrot -superclass Bird
+  Class Duck -superclass Bird
+
+  Parrot tweedy -age 1
+  Penguine pingo -age 5
+  Duck donald -age 4
+  Parrot lora -age 6
+
+  Bird instmixin {{Fly -guard {[my age] > 2 && ![my istype Penguine]}} Sing}
+

+An invocation like: +

+ +
+foreach bird {tweedy pingo donald lora} { $bird fly }
+

+yields the following result: +

+
+::tweedy ::Parrot (1 years): how should I fly?
+::pingo ::Penguine (5 years): how should I fly?
+::donald ::Duck (4 years): yippee, fly like an eagle!
+::lora ::Parrot (6 years): yippee, fly like an eagle!
+
+ +

+There are similar introspection options for mixin guards as those for +filter guards. In particular, we can use info mixinguard and +info instmixinguard for getting the mixin guards for a +particular mixin or instmixin respectively. +

+ +

Querying, Setting, Altering Filter and Mixin Lists +

+ +The methods mixin, instmixin, filter and +instfilter are system slots +having the same query and update interface. +
    +
  • If one of those methods is called without argument, it returns the current +setting.
  • +
  • If it is called with one argument, the argument is used to +set the specified list as indicated in the above examples.
  • +
  • If these methods are called with more than one argument, the first argument +is used to specify the action. Possible values for the action are +set, get, add and delete. See below for +commonly used examples. +
+

+

+ + + + + + + + +
obj mixin same as: obj info mixin
obj mixin {C1 C2} same as: obj mixin assign {C1 C2}
obj mixin assign {C1 C2}sets the mixins for obj
obj mixin add C3 adds the mixin C3 on front of the mixin list
obj mixin add C3 end adds the mixin C3 at the end the mixin list
obj mixin add C3 3 adds the mixin C3 at the 3rd position
obj mixin delete ::C3removes the mixin C3 from the mixin list. +Use absolute class names. delete supports an optional flag -nocomplain that does not produce an error, when the specified class is not in the list. +
+
+

+

+Note, that the list of possible actions can be +extended by extending the class ::xotcl::Relations. +

+ +

+Querying Call-stack Information +

+

Since the presented interceptors are +normal XOTcl instprocs they can access all XOTcl introspection +abilities introduced so far. In instprocs all recent information is +accessible within their scope. But the interceptors are mechanisms, +which cover more then their sole scope. The meaningful usage of the +meta-programming abilities often requires to go further and to get +information from the caller's and the callee's scope (e.g for +delegation decisions). Therefore, we introduced rich call-stack +informations for the interceptors. Note, that these are also available +for ordinary methods, but the "called..." info options return empty +strings. +

+

All call-stack information are packed compactly into the +self primitive as additional options. Note, before XOTcl +version 0.84 these were implemented as a part of the info +method. They are part of the self command for conceptual +integrity: introspection options in info can be expected to +produce the same result, when they are not explicitly changed. In +contrast, all information provided by self are +call-stack dependent. +

+ +
+

Querying Call-stack Information via self

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
self activelevel + +

Returns the stack level from where the + current command was invoked from, or where the last next + was called (whatever is closer to the invocation). + If the current command was invoked from + an XOTcl method the absolute level is returned (e.g. #4) + which can be used in the uplevel or + upvar Tcl command or XOTcl method. If the current + command was not invoked from an XOTcl method, the value 1 + is returned. +

self calledproc + +

Returns the name of the method which was invoked in + the original call. +

self calledclass + +

Returns the name + of the class which presumably (if no dynamic class change occurs + afterwards) is invoked in + the original call. +

self callingclass + +

Returns the name of the class from which the + call was invoked (if one exists, otherwise an empty + string). +

self callinglevel + +

Returns the stack level from where the + current command was invoked from. In contrary to + activelevel next-calls are ignored in the + computation. If the current command was invoked from an + XOTcl method the absolute level is returned (e.g. #4) + which can be used in the uplevel or + upvar Tcl command or XOTcl method. If the current + command was not invoked from an XOTcl method, the value 1 is + returned. +

self callingproc + +

Returns the name of the method from which the + call was invoked (if one exists, otherwise an empty + string). +

self callingobject + +

Returns the name of the object from which the + call was invoked (if one exists, otherwise an empty + string). +

self filterreg + +

In a filter: returns the name + of the object/class on which the filter is registered. Returns either + 'objName filter filterName' or + 'className instfilter filterName'. +

self isnextcall + +

Return 1 if this method + was invoked via next, otherwise 0 +

self next + +

Return the + "next" method on the path as a string, i.e. the method which will be + called by [next]. +

+
+

+


+

Note, that three options with the prefix calling +represent the values of self, self proc, and self +class in the scope where the original call was invoked. In the +following section we will show a simple program in which all of the +info options have different values. + +


Filter Call-stack Information Example +

+

Now we discuss a simple example that shows that all filter +introspection options may have different values: +

+
+  Class InfoTrace
+  InfoTrace instproc infoTraceFilter args { 
+    puts "SELF:                [self]"
+    puts "SELF PROC:           [self proc]"
+    puts "SELF CLASS:          [self class]"
+    puts "INFO CLASS:          [my info class]"
+    puts "CALLED PROC:         [self calledproc]"
+    puts "CALLING PROC:        [self callingproc]"
+    puts "CALLING OBJECT:      [self callingobject]"
+    puts "CALLING CLASS:       [self callingclass]"
+    puts "REGISTRATION CLASS:  [self filterreg]"
+    puts "CALLING LEVEL:       [self callinglevel]"
+    puts "ACTIVE LEVEL:        [self activelevel]"
+    next
+  }
+
+  Class CallingObjectsClass
+  CallingObjectsClass callingObject
+
+  Class FilterRegClass -superclass InfoTrace
+  Class FilteredObjectsClass -superclass FilterRegClass 
+  FilteredObjectsClass  filteredObject 
+
+  CallingObjectsClass instproc callingProc args {
+     filteredObject set someVar 0
+  }    
+  FilterRegClass instfilter infoTraceFilter

+The invocation of callingObject callingProc produces the +following output: +

+
+  SELF:                ::filteredObject
+  SELF PROC:           infoTraceFilter
+  SELF CLASS:          ::InfoTrace
+  INFO CLASS:          ::FilteredObjectsClass
+  CALLED PROC:         set
+  CALLING PROC:        callingProc
+  CALLING OBJECT:      ::callingObject
+  CALLING CLASS:       ::CallingObjectsClass
+  REGISTRATION CLASS:  ::FilterRegClass instfilter infoTraceFilter
+  CALLING LEVEL:       #1
+  ACTIVE LEVEL:        #1

+The filter reports for self the value filteredObject, +since this is the object on which the set call is invoked; +infoTraceFilter is the method of the filter, and therefore, +the actual proc, while the actual class is InfoTrace, the +filter's class. The class of the actual object is +FilteredObjectsClass. +

+

The called procedure is set. While the program stays in a +XOTcl-instproc all calling-info-options are set, the calling +procedure is callingProc, the calling class is the class, +where the method is defined (namely CallingObjectsClass), +and the object from which the call invoked is callingObject. +

+

In this example, the calling level is equal to the active level, both +are #1. +

+ + + + + + + + +
+

Slots +

+
+
+ +

A slot is a meta-object that manages property-changes of objects. A +property is either an attribute or a role in an relation. In a +nutshell, a slot has among other attributes:

+ +
    +
  • a name (which it used to access it), +
  • a domain (object or class on which it can be used) , and +
  • can be multivalued or not. +
+ +

We distinguish between system slots (predefined slots + like class, superclass, mixin, + instmixin, filter, instfilter) and + attribute slots (e.g. attributes of classes).

+ +

System Slots

+

+System slots are predefined slots defining e.g. some relations +between classes, or between objects and classes. The predefined system slots +are: +

    + +
  • superclass: every class in XOTcl has one or more + superclasses. The name of this slot is superclass, the + domain is ::xotcl::Class, the slot is multivalued, since + one object might have multiple superclasses.

    + +

  • class: every object has a class; therefore, the domain + of the slot is ::xotcl::Class, the property is not multivalued.

    + +

  • mixin: every object in XOTcl can have one or more + mixin classes. The name of this slot is mixin, the domain + is ::xotcl::Object , the slot is multivalued.

    + +

  • instmixin: same as above, but the domain is + ::xotcl::Class.

    + +

  • filter, instfilter: similar to mixin + and instmixin. + +

The system slots were introduced earlier with their +semantics. Here we just point out, that they have all the same +interfaces for querying, setting, adding and removing of slot +values.

+ +

Every slot can be used set and query the property from its domain. +The syntax for setting values is +

+  object property newValue
+
+ and for getting its values is +
+   set x [object property]
+
+where property denotes the slot name. +Every multivalued slot provides the methods add and +delete. + +Here are a few examples for using the system slot mixin which we have introduced already in the section of the mixins +
+  Object o; Class M; Class N
+  o mixin ::M      ;# replacing the per-object mixins of o with M
+  o mixin reset ::M  ;# same as before
+  o mixin add ::N   ;# add N to the front of the mixin list
+  o mixin delete ::M ;# delete M from the mixin list
+  puts [o mixin]   ;# query the current mixin list
+
+ +Every system slot (e.g. superclass) has the exact same interface. + +

Attribute Slots

+ +

Attribute slots are used to manage the setting and querying of +instance variables. We define now a person with three attributes +name, salary and projects.

+ +
+  Class Person -slots {
+    Attribute name
+    Attribute salary -default 0
+    Attribute projects -default {} -multivalued true
+  }
+
+ +

These attributes might have a default value or they might be + multivalued. When an instance of class Person is created, the + slot names can be used for specifying values for the slots.

+ +
+  Person p1 -name "Joe"	
+
+ +

Object p1 has three instance variables, namely name, +salary and projects. Since slot projects is +multivalued, we can add a value to the list of values the add +subcommand.

+ +
+  Project project1 -name XOTcl \
+     -description "A highly flexible OO scripting language"
+
+  p1 projects add ::project1
+  p1 projects add some-other-value
+
+ +

The value of the instance variable project of Person +p1 is now the list {some-other-value ::project1}. +

+ +

Attribute slots are implemented via dynamic object aggregations +(see below), where the Class objects contain +the slot objects with the information like default etc. In order to +prevent name clashes between the slot objects and the methods of a +class (like e.g. create), an intermediary object named +slot is used as a container of the slot objects. In the example above +we create an object structure of the following form:

+
+  Person
+  Person slot name
+  Person slot salary
+  Person slot projects
+
+ +

This object structure can be used to to query and modify the slot +properties or to add additional methods to the slot objects. One +application is for example to used slot-specific methods for checking +slot values, as shown in the next section. + +

+  Person info vars  ;# results in the list of variables of ::Person
+  Person slot name info vars ;# list of variables of the slot object ::Person::slot::name
+
+Since slot objects are ordinary XOTcl objects, they can have their own slots as well (such as default, name etc.). + +The following example +sets and queries the default of the slot name of Person: +

+ +
+  Person slot name default "gustaf"
+  ? {Person slot name default} gustaf
+
+ +

However, due to the current implementation, it is necessary to +re-init the slot object when the slot properties (such as +e.g. default) are changed. This can be achieved by calling +the method init of the slot object. +

+ +

Note that a statement for creating a slot object like

+
+  ... {
+    Attribute name
+    ...
+  }
+
+

is a short hand notation for

+
+  ... {
+    Attribute create name
+    ...
+  }
+
+

This is exactly the same situation like every where else in XOTcl, +when an object/class is created. One has to use create explicitly, +when a name of a slot object conflicts with a method of the class +(e.g. one has to use "Attribute create class" if a slot named +class is created).

+ +

One cannot define on a meta-class an attribute named slot +or slots and use then "... MetaClass Foo -slots { +::xotcl::Attribute x}... to create the slot objects. To handle +this naming conflict, one has to create the slot objects outside of the +aggregation and to provide the values for the properties of Attribute +(domain, manager, .... ) by hand.

+ + +

Setter and Getter Methods for Slots

+ +

When a slot is called via its name, the call is delegated to the +slot object. Per default, the slot value is read via the get +method of the slot and it is set the assign method. By +redefining these methods, it is possible to provide custom setter and +getter methods. The following example redefines the setter methods +assign to check, whether an attribute value is within the +range between 1 and 99.

+ +
+  Class create A -slots {
+    Attribute foo -default 1 -proc assign {domain var value} {
+      if {$value < 0 || $value > 99} {
+        error "$value is not in the range of 0 .. 99"
+      }  
+      $domain set $var $value
+    }
+  }
+
+  A create a1
+  ? {a1 foo 10} 10
+  ? {a1 foo} 10
+  ? {catch {a1 foo -1}} 1
+
+ +

For the most common simple cases with single valued attributes, +where neither setter or getter are redefined, XOTcl optimizes the slot +access function and replaces the delegation to the slot object by the +the C-level implementation of instparametercmd. + +

Note that it is possible to subclass Attribute (e.g. in +order to store more properties for attributes, like when attributes +are stored in a relational database) or to register mixin-classes or +filters.

+ + +

Backward-compatible Short-Hand Notation +for Attribute Slots

+ +

XOTcl provides a short-hand notation for creating attribute slots, +which is backward compatible for the most important options of XOTcl +verison prior to 1.5.0. Instead of writing

+ +
+  Class Car -slots {
+    Attribute owner
+    Attribute doors -default 4
+  }
+
+

one can use as well

+
+  Class Car -parameter {
+    owner
+    {doors 4}
+  }
+
+

The various features of the prior implementation of parameter are +deprecated and will be removed in future versions. +

+ +

Experimental Slot Features

+

Value Checking

+ +

Attribute slots can have types assigned which are tested whenever +the instance variable is altered. The slot salary is defined +as integer whereas projects is defined to be a list of +instances of the class ::Project (a list of instances, since +projects is defined as multivalued).

+ +
+  Class Person -slots {
+    Attribute name
+    Attribute salary -default 0 -type integer
+    Attribute projects -default {} -multivalued true -type ::Project
+    ...
+  }
+
+  Person p2 -name "Sue"	-salary 1000
+
+ +

It is as well possible to define custom value checkers and to +normalize the input values. We extend the previous example and define +"my sex" as value for type. If the value checker +consists of multiple words, the type check compiler assumes that the +value is a Tcl command, to which the actual value is appended as +additional argument before invocation. my refers to the +slot object. In the example below, we define for the slot object an +object specific method that returns 1 or 0 depending on the success of the +check. This method (a) checks the values via switch +and (b) normalizes and resets the value via uplevel. +

+ +
+  Class Person -slots {
+    ...
+    Attribute sex -type "my sex" -proc sex {value} {
+      switch -glob $value {
+        m* {my uplevel {$obj set $var m}; return 1}
+        f* {my uplevel {$obj set $var f}; return 1}
+        default {return 0}
+      }
+    }
+  }
+
+ + +

The slot values are actually checked via Tcl variable traces whenever the +associated variable gets a new value assigned. This means that the values are +enforced now matter how the variables are set. Therefore, the +checks are performed in the following two commands as well, although +the slot values are not accessed via the slot names. The checks will +throw an error in the second command, since 1100x is not an +integer.

+ +
+  p2 incr salary 100
+  p2 append salary x
+
+ +

Similarly the second command below will throw an error, since +some-other-value is not an instance of ::Project. + +

+  p2 projects add ::project1
+  p2 projects add some-other-value     
+
+ +

When a check throws an error, the instance variables + are reset to the previous value. To restore the original + value, an associative array __oldvalue() is kept as + instance variable in the object. +

+ +

In general, checking of variables can be turned off globally + by +

+  ::xotcl::Slot instmixin add ::xotcl::Slot::Nocheck
+
+

+ This mixin replaces the methods check and + checkall as well as mk_type_checker by + no-ops. When the mixin is active and the Attribute definitions + are loaded, the specified type has no effect. +

+

+ Value checking can be turned off also selectively for each slot via + using ::xotcl::Slot::Nocheck as per-object-mixin; if + attributes are subclassed, + it is possible to register the Nocheck mixin on a + subclass of Attribute. +

+ +

Init Commands and Value Commands for Slot Values

+ +

An init command (initcmd) of a slot is similar to a +default and is a command to be executed when the value of the +associated variable is read the first time. That means that when an +object is created the associated variable has no value. On the +contrary, when a default is used, the variable is set to the default +value, when the object is created.

+ +The primary advantage of slot init commands is Lacy +initialization: When an object has many slots and the +initialization of all slots is costly (e.g. the value of each slot is +fetched from a relational database), and not all of the values are +needed for each instance, only the relevant variables of the object +are initialized on demand. + +
+  Class C -slots {
+    Attribute x -initcmd {puts {init}; set _ 101}
+  }
+
+  C c1
+  c1 info vars  ;# ==> returns ""
+  c1 set  x     ;# ==> puts init, returns 101
+  c1 info vars  ;# ==> returns "x"
+

+
+ +

The initcmd is executed only once, when the variable is read the first +time. For later reads of the variable contents, the values are returned. + +

A value command (valuecmd) of a slot is similar to a a +init command, except that it is executed whenever the value of the +variable is read. A value command can be used e.g. to implement live +updates for variables or for abstracting from sql sequences or the +like.

+ +

Finally the value changed command (valuechangedcmd) can be +used to specify the behavior, whenever the value of the variable is +altered. This option is used to implement the value checking described +in the last section.

+ +

The slot parameters default, initcmd and +valuecmd have to be used mutually exclusively. +

+ + + + + + + + + + +
+

Nested Classes + and Dynamic Object Aggregations +

+
+
+

Most object-oriented analysis and design methods are based on the +concepts of generalization and aggregation. Generalization is +achieved through class hierarchies and inheritance, while static +aggregation is provided through embedding. Since version 8.0 Tcl +offers a namespace concept which can be used as a mechanism to +provide dynamic aggregations. +

+

A namespace provides an encapsulation of variable and +procedure names in order to prevent unwanted name collisions with +other system components. Each namespace has a unique identifier which +becomes part of the fully qualified variable and procedure names. +Namespaces are therefore already object-based in the terminology of +Wegner. OTcl is object-oriented since it offers classes and class +inheritance. Its objects are also namespaces, but an object is more +than only a namespace. Therefore, two incompatible namespace concepts +have existed in OTcl in parallel. +

+

In XOTcl every object and every class is +logically implemented as a separate Tcl namespace. The biggest benefit of this +design decision aside from performance advantages is the ability to +aggregate objects and nest classes. Contrary in OTcl every object has +a global identifier. Through the introspection abilities of +namespaces nested classes are also traceable at runtime and can be +changed dynamically. In XOTcl objects are allowed to contain nested +objects, which are dynamically changeable aggregates of the +containing object. +

+ + +

Nested Classes

+ +

The notation for nested classes follows the syntax of Tcl +namespaces by using ``::'' as a delimiter. For example the +description of a oval carpet and a desk can nest inside of the +OvalOffice class: +

+
+  Class OvalOffice
+  # general carpet
+  Class Carpet
+  Class OvalOffice::Desk
+  # special oval carpet - no name collision
+  Class OvalOffice::Carpet -superclass ::Carpet
+

+Nested classes can be used exactly like ordinary classes, a user can +sub-class it, derive instances, etc. The information about the +nesting structure of classes is available through the info +instance method: +

+
+  className info classchildren ?pattern?
+  className info classparent
+

+The classchildren option returns a list of children, if one +or more exist, otherwise it returns an empty string. classparent +results in the name of the parent class, if the class is nested. +Since nested classes are realized through namespaces, all +functionality offered by Tcl's namespace command is usable +from XOTcl as well. +

+

Dynamic Object Aggregations

+ +

The nested classes only provide an aggregation of the descriptive +not of the runtime properties of an object. We have pointed out the +difference of object and class in XOTcl. Because of the splitting of a +class into class and class-object it is possible to give each object +its own namespace. The internal implementation of objects enable them +to contain nested objects, which are aggregates of the containing +object. In XOTcl these can be changed dynamically and introspected +through the language support of dynamic object aggregations [Neumann and Zdun 2000b]. Suppose an +object of the class Agent should aggregate some property +objects of an agent, such as head and body: +

+
+  ClassAgent
+  Agent myAgent
+
+  Class Agent::Head
+  Class Agent::Body
+
+  Agent::Head ::myAgent::myHead
+  Agent::Body ::myAgent::myBody
+

+Now the objects myHead and myBody are part of the +myAgent object and they are accessible through a +qualification using ``::'' (or through Tcl's namespace command). But +in the common case they will be accessed, as introduced so far: the +explicit full qualification is not necessary when such variables are +being accessed from within XOTcl methods, since the object changes to +its namespace. +

+

The information about the part-of relationship of objects can be +obtained exactly the same way as for classes through the +info interface: +

+
+  objName info children ?pattern?
+  objName info parent
+
+ +

Relationship between Class Nesting and Object Aggregation

+ +

The classes Head and Body are children of the +Agent class. It is likely that all agents, interactive or +not, have properties for head and body. This implies a static or +predetermined relationship between class nesting and object +aggregation. Such predetermination do not exist in XOTcl, but are +simply build, when specifying the relationship in the constructor, +e.g.: +

+
+  Agent instproc init args {
+    ::Agent::Head [self]::myHead
+    ::Agent::Body [self]::myBody
+  }
+

+Now all agents derived from the class have the two property objects +aggregated after creation. But still they are changeable in a +dynamical manner, e.g. with: +

+
+  Agent myAgent
+  myAgent::myHead destroy
+

+The agent turns into a headless agent. In companion of the +introspection mechanisms such constructions could be very useful. +Suppose, that in the virtual world the agents heads may be slashed +from their bodies. The graphical system simply needs to ask with info +children on the agent's object, whether it has a head or not and +can choose the appropriate graphical representation. +

+ +

Simplified Syntax for Creating Nested Object Structures

+ +To ease the generation of nested structures, one can use the +predefined method contains. In essence, contains +changes the namespace, where objects are created to the object, +on which it is executed. In the example below, we create three +nested rectangles, where two of these contain two more points. +The outer rectangle is r0 containing rectangle r1 +and r2. + +
+  Class Point -parameter {{x 100} {y 300}}
+  Class Rectangle -parameter {color}
+
+  Rectangle r0 -color pink -contains {
+    Rectangle r1 -color red -contains {
+      Point x1 -x 1 -y 2
+      Point x2 -x 1 -y 2
+    }
+    Rectangle r2 -color green -contains {
+      Point x1
+      Point x2
+    }
+  }
+
+  ? {r0 color} pink
+  ? {r0 r1 color} red
+  ? {r0 r1 x1 x} 1
+  ? {r0 r1 x2 y} 2
+  ? {r0 r2 color} green
+
+ +

Every object in XOTcl is realized as a Tcl command. If nested +objects are created, these commands are available as object specific +methods. So, instead of calling the contained rectangle r1 via the +fully qualfied name ::r0::r1, one can use r0 +r1. This is exactly the same situation as it arises, when e.g. a +global Tcl proc proc o1 {} {...} and an XOTcl object o1 +(created via Object o1) is created. Both commands cannot +coexist in the same namespace. + +

+ +

Copy/Move

+ +Often an object has to be copied/moved. This is a very useful +functionality when XOTcl should be used as a prototyping language. +The XOTcl method move provides this functionality. Another +common behavior is implemented by the copy method which +clones the actual object to a destination object via a deep copy operation. +The two methods have the syntax: + +
+  objName move destination
+  objName copy destination
+

+ +Copy and move operations work with all object/class information, i.e., +information on filters, mixins, parameters, etc. are +automatically copied. Copy and move are integrated with class nesting +and object aggregations. All copy/move operations are deep copy +operations: all nested objects/classes are automatically copied/moved, +too. + +E.g. if we want to reuse an imperial march object of star wars for +star wars 2, we can just copy the object: +

+  starWars::imperialMarch copy starWars2::imperialMarch
+
+ +Note that move is implemented in current versions of xotcl +as a copy plus subsequent destroy operation. +

+ + + + + + + + + + + + + +
+

Method Forwarding +

+
+
+

As you have seen from many previous examples, XOTcl's primary command for +method forwarding is the next primitive. next calls +the same-named method of the current object, usually with the same +argument list. However, frequently method forwarding is required +between different objects as well, commonly referred to as +delegation.

+ +

In general, delegation can be achieved in XOTcl without any special construct +using simple methods containing a few lines. However, In +several situations, forwarding is as well needed to plain +Tcl commands, for example, if object oriented stubs are implemented on +base of non-oo function calls. These functions might access instance +variables of the objects. XOTcl uses this functionality in various +situations, such as for instance in the implementation of the +set, unset, append, array methods among others.

+ +

The fowarding functionality is suppored by XOTcl be the methods +forward and instforward that address these requirements +and provide an efficient implementation for these tasks.

+ +

The forwarding command specifies that whenever methodName is called, +this invocation is delegated to callee, where the actual argument list +(from the invocation) is appended to the argument list specified in the forwarding command. +Like for procs and instprocs, we can distinguish between forward and +instforward, depending on we want to the method available for a single object +of for the instances of a class.

+ +

The general form of the forwarding commands is: +

+  obj  forward methodName ?options? callee ?arglist? 
+  cls  instforward methodName ?options? callee ?arglist? 
+
+ +where valid options are -objscope, -methodprefix, +-earlybinding and -default. The option +-objscope is used to specify that the command should be +executed in the scope of the calling object (i.e. instance variables apprear +as local varibales), -methodprefix means that the called +method should be prefixed with the specified string (to avoid name +clashes), -earlybinding means that the function pointer of +the specified command (callee) is take at invocation time (should only +be done for (builtin) commands inplemented in C), and +-default provides a means for providing default methods when +none are specifed.

+ +

Each of the arguments after the method name (including +callee) can be be substituted an invocation time, or they are +taken literally. The arguments to be substituted are starting always +with a percent sign. These arguemnts can be %self, +%proc, %1, %argclindex, or % +followed by a Tcl command, and it can be prefixed with a positional +prefix %@. We will introduce the usage of these options and +argument substitutions based on examples.

+ +

In our first example we define an object dog and an object +tail. If the dog receives the call wag it +delegates this call to the tail and returns its result. In +this introductory example, the method tail simply returns its +arguments.

+ +

In this example, forwarding is achieved through the method +forward that creates a forwarder command. This method +receives as first argument the name, under which the forwarder is +registered, followed by the object that receives the delegation (the +"callee"), followed my the (optional) method name and optional +arguments. More about this later. Here we register the forwarder under +the name wag, the callee is tail, and the method is +defined to have the name of the forwarder. We could have written here +dog forward wag tail wag as well, be we use %proc +which refers to the name of the forwarder. Using %proc is +slightly more general in cases the forwarder is renamed. +

+ +
+  ###########################################
+  # trivial object delegation
+  ###########################################
+  Object dog
+  Object tail
+  tail proc wag args { return $args }
+  dog forward wag tail %proc
+
+ +

With these definitions a call to "dog wag 100" calls +actually "tail wag 100" which returns the result of +100.

+ +

The following command shows the delegation to a Tcl command +(instead of delegation to an object). We define a simple forwarder +that forwards a call to the Tcl command expr with some +arguments.

+ +
+  ###########################################
+  # adding 
+  ###########################################
+  Object obj
+  obj forward addOne expr 1 +
+
+The invocation obj addOne 5 returns 6 as value.

+ + +

In our next example we want additionally that the Tcl command +should to be evaluated in the context of the current object. This +means that the method can easily access instance variables of the +delegating object. We define a forwarder for the class X with +the name Incr (to avoid confusion with the already defined +method incr), we use the -objscope option and +specify incr as the callee. Since the forwarder is defined +via instforward the forwarder is available to all instances +of the class. +

+  ###########################################
+  # evaluating in scope 
+  ###########################################
+  Class X -parameter {{x 1}}
+  X instforward Incr -objscope incr
+  
+  X x1 -x 100
+  x1 Incr x
+  x1 Incr x
+  x1 Incr x
+
+After the three calls to Incr the call x1 x +returns the value 103.

+ +

In our next example, we show the usage of the +%-substitution more advanced argument handling. This example +sketches the implementation of the mixin add, mixin +set methods as shown above. In order to obtain extensible +subcommands (such as mixin add, mixin delete, etc.), we +define an object for which the subcommands are defined as methods. We +will use this object as callee for the appropriate methods. So, we +define an object named mixin and define a forwarder with the +name Mixin (again we capitalize Mixin to avoid name clashes +with the already defined methodmixin ). +

+  ###########################################
+  # mixin example
+  ###########################################
+  Object create mixin
+  mixin proc unknown {m args} {return [concat [self] $m $args]}
+  obj forward Mixin mixin %1 %self
+
+We define here the method unknown to see what arguments are +passed. The following invocation will lead to the call in noted in the comment. +
+  obj Mixin add M1       ;# calls ::mixin add ::obj M1
+
+You see that %1 was substituted by the first argument of the +invocation (here add) and %self was substituted by +the name of the current object (here ::obj). The second +argument of the invocation (here M1) was appended as +usual. However, in calls like +
+  obj Mixin
+
+we have to deal with cases, where the used argument (%1) is +not given at the invocation. In this case we get either an +error message, or we can specify a default argument via the +option -default: +
+  obj forward Mixin -default {getter setter} mixin %1 %self
+
+This definition means that if no argument is specified in the +invocation we call the method getter, if one argument is +given the method setter, in other cases we use the specified +arguments. Therefore the following three invocations are delegated as +indicated in the comments. +
+  obj Mixin              ;# calls ::mixin getter ::obj
+  obj Mixin M1           ;# calls ::mixin setter ::obj M1
+  obj Mixin add M1       ;# calls ::mixin add ::obj M1
+
+ +

When we implement subcommands by delegating to other commands +(as shown in the last example), there can be situations where naming +conflicts might arise. For example, if we want to implement a +subcommand method class we might not want to implement a new +method class on the callee, since this would overwrite the +standard definition of class. To overcome such difficulties, +we provide the option -methodprefix. The following example +shows how to prefix every called method with the prefix @. +

+
+  ###########################################
+  # sketching extensible info
+  ###########################################
+  Object Info
+  Info proc @mixin {o} {
+    $o info mixin
+  }
+  Info proc @class {o} { ;# without prefix, doing here a [Info class] would be wrong
+    $o info class
+  }
+  Info proc @help {o} { ;# define a new subcommand for info
+    foreach c [my info procs] {lappend result [string range $c 1 end]}
+    return $result
+  }
+  Object instforward Info -methodprefix @ Info %1 %self 
+
+With this definitions, the following call is rewritten as indicated in the comment. +
+  x1 Info class          ;# ::Info @class ::x1
+
+ +

When a forwarder is defined, the callee (the target command) can be +omitted. When the callee is not specified, the method-name is used +instead. When the method-name has a namespace prefix, the method name +is the tail and the callee is the fully qualified name. +

+
+  ###########################################
+  # optional callee
+  ###########################################
+  obj set x 2
+  obj forward append -objscope
+  Object n; Object n::x
+  obj forward ::n::x
+
+With this definitions of the forwarder append and x, +the following calls are rewritten as indicated in the comment. +
+  obj append x y z        ;# ::append x y z ... returning  2yz
+  obj x self              ;# ::n::x self    ... returning  ::n::x
+
+

The forwarder append forwards the call to the Tcl command +append, which accesses the instance variable x and +appends the specified values.

+ +

The list of tokens executed by the forwarder might +contain Tcl commands executed during every invocations. This makes it +for instance possible to pass instances variables to the callee. In +the next example the object has the instvar named x which is +multiplied by a factor of 10 when the method x* is invoked. +

+  ###########################################
+  # command substitution
+  ###########################################
+  obj set x 10
+  obj forward x* expr {%my set x} *
+
+With this definitions, the following call is rewritten as indicated in the comment. +
+  obj x* 10               ;# expr 10 * 10 ... returning  100
+
+ +

In certain situations it is necessary to insert arguments always at +the same position (e.g. at the second to last position). The +positional addressing can be achieved by prefixing the arguments of +the forward specification by %@POS , where POS is +either a positive (argument positing from the beginning) or negative +integer (argument counting from the end) or the constant end +(denoting the last position). After POS a single space is +used as a delimiter for the rest of the argument, which might be +some other %-substitution or a constant. The positional arguments +are evaluated from left to right and should be used in ascending order. +

+ +

The following examples show a few usages of the positional arguments +in the forwarder. The forwarders f1 to f5 are created, followed by +one or more usages. The first argument of the usage is the call to +to forewarder, the second argument is the result. +

+
+  ###########################################
+  # forwarding with positional arguments
+  ###########################################
+  Object obj
+  obj forward f1 list {%@end 13}
+  ? {obj f1 1 2 3 } [list 1 2 3 13]
+
+  obj forward f2 list {%@-1 13}
+  ? {obj f2 1 2 3 } [list 1 2 13 3]
+
+  obj forward f3 list {%@1 13}
+  ? {obj f3 1 2 3 } [list 13 1 2 3]
+  ? {obj f3} [list 13]
+
+  obj forward f4 list {%@2 13}
+  ? {obj f4 1 2 3 } [list 1 13 2 3]
+
+  obj forward f5 {%@end 99} {%@0 list} 10
+  ? {obj f5} [list 10 99]
+  ? {obj f5 a b c} [list 10 a b c 99]
+
+ +

The construct %argclindex LIST can be used to substitute an argument +depending on the number of arguments when the forwarder is +invoked. For example, it is possible to call forward to a different +method depending on how many arguments are specified. The number of arguments +is used as an index in the specified list. When the number of arguments is larger +than the number of elements in the specified list, an error is generated.

+ +
+  ###############################################
+  # substitution depending on number of arguments
+  ###############################################
+  obj forward f %self [list %argclindex [list a b c]]
+  obj proc a args {return [list [self proc] $args]}
+  obj proc b args {return [list [self proc] $args]}
+  obj proc c args {return [list [self proc] $args]}
+  ? {obj f} [list a {}]
+  ? {obj f 1 } [list b 1]
+  ? {obj f 1 2} [list c {1 2}]
+  ? {catch {obj f 1 2 3}} 1
+
+ +

Finally, the concluding example defines a class chan to use the +I/O-commands in an OO-manner. The proc open is used to create a +chan instance. For the channel object we provide the method +close (to close a channel and to destroy the channel object), +puts (to write on a stream), blocked (to check +whether last command exhausted all input), and fconfigure (to +configure the stream). Note that for puts we specified that +the actual stream should be inserted as the second to last argument. +

+
+  Class chan -parameter stream
+  # create stream and object
+  chan proc open args { 
+    set stream [eval open $args]
+    my create $stream -stream $stream  ;# make an object
+  }
+  # close stream and destroy object
+  chan instproc close {} {
+    close [my stream]
+    [self] destroy
+  }
+  # handle other subcommands (methods) via unknown
+  chan instproc unknown {m args} {
+    set valid [lsort [chan info instcommands]]
+    stderr puts "unknown chan method '$m' $args called; 
+      	defined methods: $valid"
+  }
+  chan create stdout -stream stdout   ;# define standard stream
+  chan create stderr -stream stderr   ;# define standard stream
+
+  chan instforward puts puts {%@-1 %my stream}
+  chan instforward blocked fblocked {%my stream}
+  chan instforward fconfigure fconfigure {%my stream} 
+
+  set c [chan open /tmp/junk w]
+  $c puts -nonewline "hello"
+  $c puts -nonewline " world"
+  $c puts ""
+  $c xxx                                       ;# trigger unknown
+  # The stream instances denote the currently open streams
+  stderr puts "currently open streams: [chan info instances]" 
+  $c close
+  stderr puts "currently open streams: [chan info instances]"
+
+ + + + + + + + + +
+

Assertions + +

+
+
+

In order to improve reliability and self documentation we added +assertions to XOTcl. The implemented assertions are modeled after the +``design by contract'' concept of Bertrand Meyer. In XOTcl assertions +can be specified in form of formal and informal pre- and +post-conditions for each method. The conditions are defined as a list +of and-combined constraints. The formal conditions have the form of +normal Tcl conditions, while the informal conditions are defined as +comments (specified with a starting ``#''). The lists +containing the pre- and post-conditions are appended to the method +definition (see example below). +

+

Since XOTcl offers per-object specialization it is desirable to +specify conditions within objects as well (this is different to the +concept of Meyer). Furthermore there may be conditions which must be +valid for the whole class or object at any visible state (that means +in every pre- and post-condition). These are called invariants and +may be defined with following syntax for class invariants: +

+
+  className instinvar invariantList
+

+or for objects invariants: +

+
+  objName invar invariantList
+

+Logically all invariants are appended to the pre- and post-conditions +with a logical ``and''. All assertions can be introspected. +

+

Since assertions are contracts they need not to be tested if one +can be sure that the contracts are fulfilled by the partners. But for +example when a component has changed or a new one is developed the +assertions could be checked on demand. For this purpose the check +method can be used either to test the pre- or the post-conditions. +The syntax is: +

+
+  objName check ?all? ?instinvar? ?invar? ?pre? ?post?
+

+Per default all options are turned off. check all turns all +assertion options for an object on, an arbitrary list (maybe empty) +can be used for the selection of certain options. Assertion options +are introspected by the info check option. The following +class is equipped with assertions: +

+
+  Class Sensor -parameter {{value 1}}
+  Sensor instinvar {
+    {[regexp {^[0-9]$} [my value]] == 1}
+  }
+  Sensor instproc incrValue {} {
+    my incr value
+  } {
+    {# pre-condition:} 
+    {[my value] > 0}
+  } {
+    {# post-condition:} 
+    {[my value] > 1}
+  }
+

+The parameter instance method defines an instance variable +value with value 1. The invariant expresses the +condition (using the Tcl command regexp), that the value +must be a single decimal digit. The method definition expresses the +formal contract between the class and its clients that the method +incrValue only gets input-states in which the value of the +variable value is positive. If this contract is fulfilled by +the client, the class commits itself to supply a post-condition where +the variable's value is larger than 1. The formal conditions are +ordinary Tcl conditions. If checking is turned on for sensor s: +

+
+  s check all
+

+the pre-conditions and invariants are tested at the beginning and the +post-condition and invariants are tested at the end of the method +execution automatically. A broken assertion, like calling incrValue +9 times (would break the invariant of being a single digit) results +in an error message. +

+

+In assertions we do not check methods that modify or introspect +assertions. These are +check,info,proc,instproc,invar, +and instinvar. The reason for this is that we want to be able +to recover a malicious action in a catch error handler, like: +

+
+  ...
+  if {[catch {my assertionBreakingAction} errMsg]} {
+    puts "CAUGHT ERROR: $errMsg"
+    # remember checking options, for turning them on later again
+    set check [my info check]
+    my check {}
+    # recover from broken assertion
+    ...
+    # turning checking on again 
+    $fb check $check
+  }
+
+ + + + + + + + +
+

Meta-Data +and Automatic Documentation + +

+
+
+

To enhance the understandability and the consistency between +documentation and program it is useful to have a facility to make the +documentation a part of the program. There are several kinds of +meta-data which are interesting for a class, e.g. the author, a +description, the version, etc. +

+

+Older versions of XOTcl have contained a special meta-data command +metadata. This command is now (from version 0.83) deprecated +and replaced by an integrated solution with XOTcl's API documentation +functionality. The object @ is used for documentation and +metadata issues. Per default it is not evaluated at all. Everything +that is send to @ is simply ignored. That way we do not waste +memory/performance at runtime, if we do not require to parse the +metadata/documentation. +

+

+If we have to know the meta-data/documentation, as for instance in the +xoDoc component and the makeDoc tool, that handle +XOTcl's internal documentation, we have to re-define the documentation +object. Alternatively, we can partially parse the source code for +@ commands. +

+

+With @ the meta-data/documentation is handled by first class +XOTcl objects. By defining alternate @ implementations - as in +xoDoc/makeDoc - we can evaluate the +meta-data/documentation arbitrarily. xoDoc/makeDoc +are only an HTML back-end, but the basic idea is to provide support for +several other usages as well (e.g. XML, RDF, on-line help, +documentation of dynamic structures, etc). +

+

+The object@ handles comments via its unknown +method. xoDoc adds the appropriate instprocs to t@ to produce HTML +output. The appropriate command is: +

+
+  tclsh src/lib/makeDoc.xotcl DOCDIR DOCFILES
+

+ +The source of a documentation is structurally very similar to the +XOTcl constructs being commented. E.g. one can copy an instproc and +add comments at the right places, like: +

+
+    Class C
+    C instproc m {a1 a2} {
+       return [expr {$a1+$a2}]
+    }
+

+ + can be commented as follows +

+
+    @ Class C { description { "my sample class"} }
+    @ C instproc m {a1 "first number" a2 "second number"} {
+       description "add two numbers"
+       return "sum of a1 and a2"
+    }
+

+

+ One can do essentially a copy+paste of the source and add the + comments via attribute value pairs. Every basic language construct + can have a "description". If you want to include other properties to + the description, you can add them like: +

+
+    @ C instproc m {a1 "first number" a2 "second number"} {
+       author "GN+UZ"
+       date "Feb 31"
+       description "add two numbers"
+       return "sum of a1 and a2"
+    }
+

+ + This way, author and date are added automatically to the generated + HTML file. + + In addition, there is a @File hook for a per file +description, like: +

+
+@ @File {
+  description {
+    This is a file which provides a regression test
+    for the features of the XOTcl - Language. 
+  }
+}
+

+ + + + + + +
+

Additional + Functionalities +

+
+
+

Abstract Classes +

+

In XOTcl a class is defined abstract if at least one method of +this class is abstract. The instance method abstract defines +an abstract method and specifies its interface. Direct calls to +abstract methods produce an error message. E.g. a Storage class +provides an abstract interface for access to different storage forms: +

+
+  Class Storage
+  Storage abstract instproc open  {name}       
+  Storage abstract instproc store {key value}
+  Storage abstract instproc list  {}         
+  Storage abstract instproc fetch key        
+  Storage abstract instproc close {}         
+  Storage abstract instproc delete {k} 
+

+All kinds of storage have to implement every method from the +interface. E.g. a GNU Database Access, a relational database access, +and several other storage forms may be derived by sub-classing +(therefore, all conform to the same storage access interface). +

+ +

Checking Commands for being Objects, +Classes, or Meta-Classes +

+

Since XOTcl is a hybrid language containing several Tcl commands, +sometimes its necessary for applications to distinguish between Tcl +commands and object commands for XOTcl. method of the +Object class looks up an objName and returns 1 if it +is an object and 0 if not: + +

+  objName1 isobject objName2
+

+ +If one can be sure that a command represents an +object, it might be unsure if the command is only an object or also +class or even meta-class. The two instance methods isclass +and ismetaclass check in the same manner, whether a class or +meta-class is given (since ever XOTcl class is an object, they also +return 0, when objName is not an XOTcl object). + +

+  objName1 isclass objName2
+  objName1 ismetaclass objName2
+
+ +

+Exit Handler +

+

A task for a programming language, sometimes of similar importance +as object creation, is the object destruction. XOTcl ensures that all +objects are destroyed and their destructors are invoked when XOTcl +applications terminate. For that reason objects and classes are +destroyed in the order objects, classes, meta-classes. Sometimes +further destruction order is of importance. For these cases, the XOTcl +language provides an exit handler, which is a user-defined proc, which +invokes user-defined exit handling just before the destruction of +objects, classes, meta-classes is invoked. For instance, the exit +handler lets the user specify objects which have to be destroyed +before all other objects. +

+

The exit handler is defined as a proc of Object, which is per default empty: +

+  ::xotcl::Object proc __exitHandler {} {
+    # clients should append exit handlers to this proc body
+    ;
+  }
+
+ +

There are some procs of the Object class pre-defined, +which let us specify an exit handler conveniently: +

+
+   Object setExitHandler body
+   Object getExitHandler
+   Object unsetExitHandler
+

+setExitHandler lets us specify +a proc body that actually contains the user-defined exit handling: +

+   Object setExitHandler {
+     aObj destroy
+     puts "exiting"
+   }
+

+destroys the object aObj before +all other objects and prints the message existing to the screen. With +getExitHandler the exit +handler can be introspected. E.g. if we just want to append the +destruction of object bObj to +an existing exit handler, we use getExitHandler: +

+
+   Object setExitHandler "[Object getExitHandler]; bObj destroy"
+
+

+unsetExitHandler deletes the exit handler. +

+
+
+

Automatic Name Creation +

+The XOTcl autoname +instance method provides an simple way to take the task of +automatically creating names out of the responsibility of the +programmer. The example below shows how to create on each invocation +of method new an agent with a fresh name +(prefixed with agent): +

+
+  Agent proc new args {
+    eval my [my autoname agent] $args
+  }
+
+

+Autonames may have format strings as in the Tcl 'format' command. +E.g.: +

+
+  objName autoname a%06d
+
+

+produces +

+  a000000, a000001, a000002, ...
+
+

+ + + + + + + + +
+

Integrating XOTcl Programs with C Extensions (such as TK) + +

+
+
+ +

Because all XOTcl commands are in the ::xotcl namespace, it is +usually no problem to integrate XOTcl with other Tcl extensions. Most +often it works to import the XOTcl commands (like Object, Class) into +the current namespace because there are no name-clashes with the +commands defined by other extensions.

+ +

Consider you want to perform a deeper integration of an other +extension and XOTcl because you want to benefit from XOTcl's object +system. For instance, you might want to introduce composite TK widgets +(sometimes called mega-widgets) as classes and inherit from these +classes. Here, you have two options: you can change or extend the C +code of that other extension to provide XOTcl classes or objects, or +you can write an XOTcl wrapper in Tcl. For the first alternative, +there are some examples provided in the XOTcl distribution. XOTclGdbm +provides an OO Tcl interface to the GDBM database, for +instance. XOTclSdbm does the same for SDBM, and the TclExpat wrapper +provides a class-based interface to the TclExpat XML parser.

+ +

Consider you do not want to change the C code of a Tcl +extension. Then you can write an OO wrapper in XOTcl for the commands +of the other extension. For stateless commands, you can simply write +forwarder methods. If the extension maintains some state, you +typically associate the state handle with an XOTcl parameter, acquire +the state in the XOTcl constructor, and align the XOTcl destructor +with the stateful instance.

+ +

Consider you want to wrap the Tk button widget. You can acquire the +widget in the constructor, and maintain the widget ID in a +parameter. You now can forward invocations to this widget ID +(e.g. when using "pack"), or register command callbacks (like +buttonPressed). Note that we let the "self" command be replaced in the +scope of the current method so that TK receives the correct object ID +for the callback. In the destructor we destroy the widget as well (we +use "catch" because sometimes widgets can destroyed by other means as +well (e.g. by their parent widget, when a widget/object hierarchy is +destroyed at once).

+ +
+  Class MyButton -parameter {button}
+  MyButton instproc buttonPressed args {
+    puts "pressed [my button]"
+  }
+  MyButton instproc init args {
+    set ID [namespace tail [self]]
+    my instvar button
+    set button [button .$ID \
+      -text "My Button $ID" \
+      -command [list [self] buttonPressed]] 
+    pack $button
+    next
+  }
+  MyButton instproc destroy args {
+     catch {destroy [my button]}
+     next
+  }
+
+  # a test -> 3 buttons, destroy one of them
+  foreach b {a b c} {
+    MyButton $b
+  }
+  b destroy
+
+ +

The "trick" to substitute "self" within the current method scope +works for all kinds of command callbacks. Extensions such as TK, +however, often work with bindings to (global) variables as well. Using +global variables is frowned upon in the OO community. Instead you +should use instance variables of objects. As Tcl can only bind to +existing namespace variables (and XOTcl acquires the namespace of an +object on demand), you have to make sure that the namespace of an +object exists before binding a variable. That can be done with +"requireNamespace":

+
+  GUIClass instproc buildEntry win {
+    my requireNamespace
+    entry $win -textvariable [self]::entryValue
+    my set entryValue {Init Value}
+  }
+
+ +

Note that in the above example we have used to tail of the object ID +as ID for the widget. Usually, it is a good idea to the object name, +if possible, for TK (and other extensions) IDs as well. Another option +is to use a autoname to get a unique name for the ID.

+ +

Sometimes you want to simply send all invocations, not implemented by +XOTcl, to the wrapped command. Here, it is tedious to write a wrapper +for each of these methods. Instead you can use "unknown" to handle +automatic forwarding. Consider you want to wrap TK commands like pack +and replace XOTcl object names with their TK widget ID, so that you can +use both IDs synonymously. You can rename the respective TK commands in +the following way: + +

+  foreach tkCommand {bell bind bindtags clipboard event 
+    focus font grid image lower option pack place raise 
+    selection send tk tkwait winfo wm} { 
+    rename ::$tkCommand __tk_$tkCommand
+    TkCommand ::$tkCommand
+    ::$tkCommand set wrapped __tk_$tkCommand
+  }
+
+ +

The XOTcl class handling the ID substitution for the TK command +might look as follows:

+ +
+  Class TkCommand -parameter wrapped
+  TkCommand instproc unknown args {
+      my instvar wrapped
+      set args [Widget replaceWithWidgetIDs $args]
+      # now call the command
+      eval $wrapped $args
+  }
+
+ +

+ + + + + + + + +
+

References + +

+
+
+ + +

[Zdun, Strembeck, Neumann 2007] U. Zdun, +M. Strembeck, G. Neumann: Object-Based and Class-Based Composition of +Transitive Mixins, Information and Software Technology, 49(8) 2007 . + +

+[Neumann and Zdun 1999a] +G. Neumann and U. Zdun. +Filters as a language support for design patterns in object-oriented + scripting languages. +In Proceedings of COOTS'99, 5th Conference on Object-Oriented + Technologies and Systems, San Diego, May 1999. + +

[Neumann and Zdun 1999b] +G. Neumann and U. Zdun. +Implementing object-specific design patterns using per-object mixins. +In Proc. of NOSA`99, Second Nordic Workshop on Software + Architecture, Ronneby, Sweden, August 1999. + +

[Neumann and Zdun 1999c] +G. Neumann and U. Zdun. +Enhancing object-based system composition through per-object mixins. +In Proceedings of Asia-Pacific Software Engineering Conference + (APSEC), Takamatsu, Japan, December 1999. + +

[Neumann and Zdun 2000a] +G. Neumann and U. Zdun. + XOTCL, an object-oriented scripting language. +In Proceedings of Tcl2k: The 7th USENIX Tcl/Tk Conference, + Austin, Texas, February 2000. + +

[Neumann and Zdun 2000b] +G. Neumann and U. Zdun. Towards the Usage of Dynamic Object + Aggregations as a Form of Composition +In: Proceedings of Symposium of Applied Computing (SAC'00), Como, Italy, Mar 19-21, 2000. + + +

[Ousterhout 1990] +J. K. Ousterhout. +Tcl: An embeddable command language. +In Proc. of the 1990 Winter USENIX Conference, January 1990. + +

[Ousterhout 1998] +J. K. Ousterhout. +Scripting: Higher Level Programming for the 21st Century, IEEE Computer 31(3), March 1998. + +

[Wetherall and Lindblad 1995] +D. Wetherall and C. J. Lindblad. Extending Tcl for Dynamic + Object-Oriented Programming. Proc. of the Tcl/Tk Workshop '95, July 1995. + + + + + + + + Index: library/xotcl/doc/xotcl-doc.css =================================================================== diff -u --- library/xotcl/doc/xotcl-doc.css (revision 0) +++ library/xotcl/doc/xotcl-doc.css (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,48 @@ +BODY { + font-family: Verdana, Arial, Helvetica, sans-serif; + font-weight: normal; + background-color : white; + color: black; +} +tt { + font-family: courier, monospace; +} +A { + font-family: Verdana, Arial, Helvetica, sans-serif; + font-weight: 100; + background-color : white; +} +A em { + font-weight: 900; +} + +pre.code { + font-size: 90%; + font-family: courier, monospace; + PADDING-RIGHT: 10px; + PADDING-LEFT: 10px; + PADDING-BOTTOM: 10px; + PADDING-TOP: 10px; + BORDER: #cccccc 1px solid; + BACKGROUND-COLOR: #eeeeee; + MARGIN-BOTTOM: 15px; +} +pre em { + font-family: cursive; + color: #888888; +} +pre tt { + font-family: helvetica; + font-weight: 900; +} +pre it { + font-style: italic; + color: green; +} +tt em { + font-family: cursive; + color: #888888; +} +table { + font-size: 80%; +} Index: library/xotcl/library/rdf/rdfExample.xotcl =================================================================== diff -u --- library/xotcl/library/rdf/rdfExample.xotcl (revision 0) +++ library/xotcl/library/rdf/rdfExample.xotcl (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,76 @@ +#!/usr/bin/env tclsh +# $Id: rdfExample.xotcl,v 1.2 2006/02/18 22:17:33 neumann Exp $ +# +# small Example for usage of xoXML +# +package require XOTcl; namespace import -force xotcl::* +package require xotcl::package +package require xotcl::trace +package require xotcl::rdf::parser +package require xotcl::rdf::recreatorVisitor +package require xotcl::xml::printVisitor + +# +# instantiate parser and parser an example text into a node tree +# +RDFParser x +x parse { + + + + + Mary Andrew + Jacky Crystal + + + + + + + + + + + + + The Coolest Web Page + Il Pagio di Web Fuba + + + + + some text + + + + +} + +proc run {} { + # + # print the node treee to the std output + # + puts ************************************************************************ + puts "Node Tree:" + puts ************************************************************************ + PrintVisitor pv + foreach tn [x info children topNode*] { + pv interpretNodeTree $tn + } + + # + # recreate xml text and print it to the std output + # + puts \n + puts ************************************************************************ + puts "Recreated RDF Text:" + puts ************************************************************************ + RDFRecreatorVisitor rv + foreach tn [x info children topNode*] { + set result [rv interpretNodeTree $tn] + puts $result + } +} +run Index: library/xotcl/library/serialize/RecoveryPoint.xotcl =================================================================== diff -u --- library/xotcl/library/serialize/RecoveryPoint.xotcl (revision 0) +++ library/xotcl/library/serialize/RecoveryPoint.xotcl (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,441 @@ +# $Id: RecoveryPoint.xotcl,v 1.4 2006/02/18 22:17:33 neumann Exp $ + +package provide xotcl::scriptCreation::recoveryPoint 0.8 +package require XOTcl + +namespace eval ::xotcl::scriptCreation::recoveryPoint { + namespace import ::xotcl::* + + ## fehlt noch: filter, mixins, metadata, ass, assoption, etc + ## beim recover Class's,Object's proc instproc vars nicht ueberschreiben + ## filter dann anhaengen etc ... + ## der Recovery Filter darf durch Object filter "" nicht gelöscht werden + + # + # filter to ensure that recovering doesn't overwrite + # existing objs/classes + # + + Object instproc recoveryFilter args { + ::set method [self calledproc] + + switch -- $method { + create { + # don't overwrite objects + if {![::Object isobject [lindex $args 0]]} { + next + } else { + # puts stderr "Recovery Filter: omitting [lindex $args 0]" + } + } + proc { + if {[lsearch [my info procs] [lindex $args 0]] == -1} { + next + } else { + # puts stderr "Recovery Filter: omitting proc [self]::[lindex $args 0]" + } + } + instproc { + if {[lsearch [my info instprocs] [lindex $args 0]] == -1} { + next + } else { + # puts stderr "Recovery Filter: omitting instproc [self]::[lindex $args 0]" + } + } + set { + if {[lsearch [my info vars] [lindex $args 0]] == -1} { + next + } else { + # puts stderr "Recovery Filter: omitting var [self]::[lindex $args 0]" + } + } + default {next} + } + } + + # + # remove filter from object + # + Object instproc filterremove f { + ::set fl [my info filter] + puts stderr "filterremove on [self] with $f; fullName: [my filtersearch $f]" + while {[::set index [lsearch $fl [my filtersearch $f]]] != -1} { + ::set fl [lreplace $fl $index $index] + } + my filter $fl + } + + # + # remove mixin from object + # + Object instproc mixinremove m { + puts stderr "mixinremove on [self] with $m" + ::set ml [my info mixins] + while {[::set index [lsearch $ml $m]] != -1} { + ::set ml [lreplace $ml $index $index] + } + my mixin $ml + } + + Class RecoveryPoint \ + -parameter { + {appendedObjs ""} + {appendedCls ""} + {appendedNamespaces ""} + {withState 0} + {appendToFile 0} + {definedObjs [list Object \ + Class \ + Class::Parameter]} + {excludeNames ""} + } + + # + # queries the definedObjs variable whether a given object + # is already defined/predefined or not + # -> a way to exclude classes/objs from saving + # + RecoveryPoint instproc isDefined {n} { + my instvar definedObjs + puts stderr "Checking Defined: $n in $definedObjs" + if {[lsearch $definedObjs [string trimleft $n :]] == -1} { + return 0 + } else { + return 1 + } + } + + RecoveryPoint instproc appendDefined {n} { + my instvar definedObjs + lappend definedObjs [string trimleft $n :] + } + + # + # check whether an obj/cls/namespace is appended already + # append obj/cls/namespace + # + foreach method {Obj Cl Namespace} { + set r { + my instvar {appended${method}s name}} + set r [subst -nocommands -nobackslash $r] + + set s $r + append s { + if {[lsearch $name [string trimleft $n :]] == -1} { + return 0 + } else { + return 1 + } + } + + RecoveryPoint instproc isAppended$method {n} $s + + append r { + lappend name [string trimleft $n :] + } + RecoveryPoint instproc append$method {n} $r + } + + + # + # compare command for lsort + # + RecoveryPoint instproc namespaceDepth {a b} { + set aCount 0 + set bCount 0 + for {set i 0} {$i < [string length $a]} {incr i} { + if {[string index $a $i] eq ":"} { + incr aCount + } + } + for {set i 0} {$i < [string length $b]} {incr i} { + if {[string index $b $i] eq ":"} { + incr bCount + } + } + if {$aCount == $bCount} { + return 0 + } elseif {$aCount > $bCount} { + return 1 + } + + return -1 + } + + # + # produces a script containing the current state of + # the given obj + # + RecoveryPoint instproc stateScript {obj} { + set script "" + foreach v [$obj info vars] { + if {[lsearch [my set excludeNames] $v] == -1} { + $obj instvar $v + if {[array exists $v]} { + foreach name [array names $v] { + set arr ${v}($name) + set value [$obj set $arr] + append script "$obj set $arr \"$value\"\n" + } + } else { + set value [set $v] + append script "$obj set $v \"$value\"\n" + } + } + } + return $script + } + + # + # produces a script containing the procs of the given obj + # + RecoveryPoint instproc procScript {obj} { + set script "" + foreach p [$obj info procs] { + if {[lsearch [my set excludeNames] $v] == -1} { + append script \ + "$obj proc $p \{[$obj info args $p]\} \{[$obj info body $p]\}\n" + } + } + return $script + } + + # + # produces a script containing the instprocs of the given class + # + RecoveryPoint instproc instprocScript {cl} { + set script "" + foreach p [$cl info instprocs] { + if {[lsearch [my set excludeNames] $v] == -1} { + append script \ + "$cl instproc $p \{[$cl info instargs $p]\} \{[$cl info instbody $p]\}\n" + } + } + return $script + } + + # + # append parent obj/classes/namespaces of an object completly + # + + RecoveryPoint instproc appendParents {name} { + # puts stderr "Recovery -- appendParents $name " + set p "" + set script "" + + set n $name + while {[set np [namespace parent ::$n]] != "::"} { + lappend p $np + set n $np + } + set p [lsort -command {[self] namespaceDepth} $p] + + foreach n $p { + if {[Object isobject $n]} { + if {[$n isclass]} { + append script [my classScript $n] + } else { + append script [my objectScript $n] + } + } else { + if {![my isAppendedNamespace $n]} { + append script "namespace eval $n \{\}\n" + # puts stderr "Recovery -- Appending Namespace: $n" + my appendedNamespace $n + } + } + } + return $script + } + + + # + # produces a script recovering the given obj with all children + # without state + # + RecoveryPoint instproc objectScript {obj} { + # puts stderr "Recovery -- Object Script $obj" + my instvar withState + set script "" + if {![my isDefined $obj] && + ![my isAppendedObj $obj]} { + # if the object's class is not yet appended => do it now + set objClass [$obj info class] + append script [my classScript $objClass] + + # append all parent namespaces + append script [my appendParents $obj] + + # append the obj + append script "$objClass $obj\n" + append script [my procScript $obj] + if {$withState == 1} { + append script [my stateScript $obj] + } + # puts stderr "Recovery -- Appending Object: $obj" + my appendObj $obj + + # append its children + foreach o [$obj info children] { + append script [my objectScript $o] + } + } + return $script + } + + # + # produces a script recovering the given class with all children + # without state + # + RecoveryPoint instproc classScript {cl} { + # puts stderr "Recovery -- Class Script $cl" + my instvar withState + set script "" + if {![my isDefined $cl] && + ![my isAppendedCl $cl]} { + # if the class's meta-class is not yet appended => do it now + set metaClass [$cl info class] + append script [my classScript $metaClass] + + # append all parent namespaces + append script [my appendParents $cl] + + # append the class + append script "$metaClass $cl" + + set sl [$cl info superclass] + if {$sl ne ""} { + append script " -superclass \{$sl\}\n" + } else { + append script "\n" + } + + append script [my instprocScript $cl] + append script [my procScript $cl] + + if {$withState == 1} { + append script [my stateScript $cl] + } + + # puts stderr "Recovery -- Appending Class: $cl \n $script" + my appendCl $cl + + # append children + set children [$cl info children] + set classChildren [$cl info classchildren] + + foreach c $children { + if {[lsearch $classChildren $c] != -1} { + append script [my classScript $c] + } else { + append script [my objectScript $c] + } + } + } + return $script + } + + # + # produces a script recovering the given class and all subclasses + # with all their children and all instances + # + # + RecoveryPoint instproc hierarchyScript {cl} { + set script [my classScript $cl] + set sortedInstances \ + [lsort -command {[self] namespaceDepth} [$cl info instances]] + + foreach o $sortedInstances { + append script [my objectScript $o] + } + + foreach c [$cl info subclass] { + append script [my hierarchyScript $c] + } + + return $script + } + + # + # saves a script to a file + # + RecoveryPoint instproc saveScript {filename script} { + my instvar appendToFile + if {$appendToFile} { + set mode a + } else { + set mode w + } + set f [open $filename $mode] + puts $f $script + close $f + } + + # + # load a script from a file + # + RecoveryPoint instproc loadScript {filename} { + set f [open $filename r] + set r [read $f] + close $f + return $r + } + + # + # produce methods to save/recover an object script to/from a file + # with/without state/only state + # + + foreach method { + Object ObjectState ObjectWithState Class ClassWithState \ + Hierarchy HierarchyWithState + } { + set s { + my set withState + } + + if {[regexp {(.*)WithState} $method _ m]} { + set call $m + append s "1" + } else { + set call $method + append s "0" + } + + scan $call %c l + set ::low "[format %c [expr {$l + 32}]][string range $call 1 end]" + + append s { + my appendedObjs "" + my appendedCls "" + my appendedNamespaces "" + } + append s " + foreach a \$args \{" + set r { + set script [my ${low}Script } + set r [subst -nocommands -nobackslash $r] + append s $r + append s {$a] + my saveScript $filename $script} + append s " + \} + " + + RecoveryPoint instproc save$method {filename args} $s + } + + RecoveryPoint instproc recover {filename} { + set r [my loadScript $filename] + Object filterappend recoveryFilter + # puts stderr "RecoveryFilter appended for $filename" + eval $r + Object filterremove recoveryFilter + # puts stderr "RecoveryFilter removed for $filename" + return + } + + namespace export RecoveryPoint +} + +namespace import ::xotcl::scriptCreation::recoveryPoint::* Index: library/xotcl/library/serialize/ScriptCreator.xotcl =================================================================== diff -u --- library/xotcl/library/serialize/ScriptCreator.xotcl (revision 0) +++ library/xotcl/library/serialize/ScriptCreator.xotcl (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,228 @@ +# $Id: ScriptCreator.xotcl,v 1.4 2006/02/18 22:17:33 neumann Exp $ + +package provide xotcl::scriptCreation::scriptCreator 0.8 +package require XOTcl + +namespace eval ::xotcl::scriptCreation::scriptCreator { + namespace import ::xotcl::* + + Class ScriptCreator \ + -parameter { + {excludedObjs {Object Class Class::Parameter}} + {excludeNames ""} + {dependencyChecking 1} + } + + + # + # queries the excludedObjs variable whether a given object + # is already defined/predefined or not + # -> a way to exclude classes/objs from saving + # + ScriptCreator instproc isExcluded {n} { + my instvar excludedObjs + #puts stderr "Checking Excluded: $n in $excludedObjs" + if {[lsearch $excludedObjs [string trimleft $n :]] == -1} { + return 0 + } else { + return 1 + } + } + + ScriptCreator instproc appendExcluded {n} { + my instvar excludedObjs + lappend excludedObjs [string trimleft $n :] + } + + # + # compare command for lsort + # + ScriptCreator instproc namespaceDepth {a b} { + set aCount 0 + set bCount 0 + for {set i 0} {$i < [string length $a]} {incr i} { + if {[string index $a $i] eq ":"} { + incr aCount + } + } + for {set i 0} {$i < [string length $b]} {incr i} { + if {[string index $b $i] eq ":"} { + incr bCount + } + } + if {$aCount == $bCount} { + return 0 + } elseif {$aCount > $bCount} { + return 1 + } + + return -1 + } + + # + # produces a script containing the current state of + # the given obj + # + ScriptCreator instproc stateScript {obj} { + set script "" + foreach v [$obj info vars] { + if {[lsearch [my set excludeNames] $v] == -1} { + if {[$obj array exists $v]} { + foreach name [$obj array names $v] { + set arr ${v}($name) + set value [$obj set $arr] + append script "$obj set $arr \"$value\"\n" + } + } else { + set value [$obj set $v] + append script "$obj set $v \"$value\"\n" + } + } + } + return $script + } + + # + # produces a script containing the procs of the given obj + # + ScriptCreator instproc procScript {obj} { + set script "" + foreach p [$obj info procs] { + if {[lsearch [my set excludeNames] $p] == -1} { + append script \ + "$obj proc $p \{[$obj info args $p]\} \{[$obj info body $p]\}\n" + } + } + return $script + } + + # + # produces a script containing the instprocs of the given class + # + ScriptCreator instproc instprocScript {cl} { + set script "" + foreach p [$cl info instprocs] { + if {[lsearch [my set excludeNames] $p] == -1} { + append script \ + "$cl instproc $p \{[$cl info instargs $p]\} \{[$cl info instbody $p]\}\n" + } + } + return $script + } + + + + # + # saves a script to a file + # + ScriptCreator instproc saveScript {filename script} { + set f [open $filename w] + puts $f $script + close $f + } + + # + # load a script from a file + # + ScriptCreator instproc loadScript {filename} { + set f [open $filename r] + set r [read $f] + close $f + return $r + } + + # + # check parent obj/classes/namespaces of an object completly + # + ScriptCreator instproc checkParents {name} { + set p "" + + set n $name + while {[set np [namespace parent ::$n]] != "::"} { + lappend p $np + set n $np + } + set p [lsort -command {my namespaceDepth} $p] + + foreach n $p { + if {![my isExcluded $n] && + ![my isAppended $n]} { + error "ScriptCreator: $name needs parent $n, neither appended nor excluded yet." + } + } + } + + ScriptCreator instproc checkClass {obj class} { + if {![my isExcluded $class] && + ![my isAppended $class]} { + error "ScriptCreator: $obj depends on $class, neither appended nor excluded yet." + } + } + + ScriptCreator instproc isAppended name { + set n [string trimleft $name :] + if {[lsearch [my set appendedNames] $n]!=-1} { + return 1 + } else { + return 0 + } + } + + ScriptCreator instproc appendName name { + set n [string trimleft $name :] + my lappend appendedNames $n + } + + ScriptCreator instproc makeScript args { + my instvar dependencyChecking + my set appendedNames "" + set script "" + foreach name $args { + #puts stderr "Script Creator -- $name" + if {![my isExcluded $name] && + ![my isAppended $name]} { + + if {$dependencyChecking} { + my checkParents $name + } + if {[Object isobject $name]} { + set class [$name info class] + if {$dependencyChecking} { + my checkClass $name $class + } + if {[Object isclass $name]} { + # append the class + #puts stderr "Appending Class: $name" + append script "[$name info class] $name" + set sl [$name info superclass] + if {$dependencyChecking} { + foreach c $sl { + my checkClass $name $c + } + } + if {$sl ne ""} { + append script " -superclass \{$sl\}\n" + } else { + append script "\n" + } + append script [my instprocScript $name] + } else { + # append the obj + #puts stderr "Appending Object: $name" + append script "[$name info class] $name\n" + } + append script [my procScript $name] + } else { + append script "namespace eval $name \{\}\n" + #puts stderr "Appending Namespace: $name" + } + my appendName $name + } + } + return $script + } + + namespace export ScriptCreator +} + +namespace import ::xotcl::scriptCreation::scriptCreator::* Index: library/xotcl/library/serialize/Serializer.xotcl =================================================================== diff -u --- library/xotcl/library/serialize/Serializer.xotcl (revision 0) +++ library/xotcl/library/serialize/Serializer.xotcl (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,3 @@ +# offer old package name for backward minimal compatibility +package provide xotcl::serializer 1.0 +package require nx::serializer \ No newline at end of file Index: library/xotcl/library/xml/xmlExample.xotcl =================================================================== diff -u --- library/xotcl/library/xml/xmlExample.xotcl (revision 0) +++ library/xotcl/library/xml/xmlExample.xotcl (revision e8715774bf274fbeadabf08a5a0777a968f71148) @@ -0,0 +1,115 @@ +#!../../src/xotclsh +# +# small Example for usage of xoXML +package require xotcl::package +package require xotcl::trace +package require xotcl::xml::parser +package require xotcl::xml::recreatorVisitor +package require xotcl::xml::printVisitor + +# +# instantiate parser and parser an example text into a node tree +# +XMLParser x +#x parse { +# + +x parse { + + + a + b + c + + + b + c + + + a + b + c + b + d + + + + + + Mary Andrew + Jacky Crystal + + + + + + + + + + + + + The Coolest Web Page + Il Pagio di Web Fuba + + + + + some text + + + + +} + +proc run {} { + # + # print the node treee to the std output + # + puts ************************************************************************ + puts "Node Tree:" + puts ************************************************************************ + PrintVisitor pv + pv interpretAll x + + # + # recreate xml text and print it to the std output + # + puts \n + puts ************************************************************************ + puts "Recreated XML Text:" + puts ************************************************************************ + XMLRecreatorVisitor rv + puts [rv interpretAll x] + +} +run + +XMLParser y +y parse { + + + + + + + + + + + + + olla + + + + + hallo + + +} +XMLRecreatorVisitor rv +puts [rv interpretAll y]