Index: doc/index.html =================================================================== diff -u -r782b1f820f03b0f09c3e333a5e03f9ad2808fcac -rbb58b68431fe35dd6ff16e69044705e1246d0dda --- doc/index.html (.../index.html) (revision 782b1f820f03b0f09c3e333a5e03f9ad2808fcac) +++ doc/index.html (.../index.html) (revision bb58b68431fe35dd6ff16e69044705e1246d0dda) @@ -23,7 +23,7 @@

Index: generic/gentclAPI.decls =================================================================== diff -u -r3f0573cc75724179f416942b974373e5a62ec05e -rbb58b68431fe35dd6ff16e69044705e1246d0dda --- generic/gentclAPI.decls (.../gentclAPI.decls) (revision 3f0573cc75724179f416942b974373e5a62ec05e) +++ generic/gentclAPI.decls (.../gentclAPI.decls) (revision bb58b68431fe35dd6ff16e69044705e1246d0dda) @@ -1,8 +1,21 @@ # -*- Tcl -*- # # This script is sourced by the C-code generator gentclAPI.tcl in the -# same directory +# same directory. It is also used by the next::doc toolkit to generate +# the authorative language reference documents. +# @package next +# +# "Next" is a compact and expressive object-oriented language +# extension for Tcl. The object system model is highly influenced by +# CLOS. This package provides the basic object system for the Next +# language. It defines the basic language entities {{@object ::nx::Object}} and +# {{@object ::nx::Class}}, as well as essential language primitives +# (e.g., {{@command ::nx::next}} and {{@command ::nx::self}}). +# +# @require Tcl +# @version 1.0.0a + # namespaces for types of methods array set ns { xotclCmd "::nx::core" @@ -29,6 +42,72 @@ {-argName "assertionsubcmd" -required 1 -type "check|object-invar|class-invar"} {-argName "arg" -required 0 -type tclobj} } + +# @command ::nx::core::configure +# +# A top-level configuration facility which allows you modify +# properties of the "Next" object system for the scope of an entire +# {{{interp}}}. + +# @subcommand ::nx::core::configure#filter +# +# Allows turning on or off filters globally for the current +# interpreter. By default, the filter state is turned off. This +# function returns the old filter state. This filterless {{{interp}}} +# state is needed for the serializer which should introspect and stream the +# objects and classes without being affected by active filter. +# +# @param toggle Accepts either "on" or "off" +# @return The current filter activation state + +# @subcommand ::nx::core::configure#softrecreate +# +# Allows controlling the scheme applied when recreating an object or a +# class. By default, it is set to {{{off}}}. This means that the +# object/class is destroyed and all relations +# (e.g. subclass/superclass) to other objects/classes are revoked as +# well. If softrecreate is set to {{{on}}}, the object is re-set, but not +# destroyed, the relations are +# kept. +# +# A "soft" recreation is important for e.g. reloading a file with +# class definitions (e.g. when used in OpenACS with file watching and +# reloading). With softrecreate set, it is not necessary to recreate +# dependent subclasses etc. Consider the example of a class hierarchy +# {{{A <- B <- C}}}. Without {{{softrecreate}}} set, a reload of +# {{{B}}} means first a destroy of B, leading to {{{A <- C}}}, and +# instances of {{{B}}} are re-classed to {{@object +# ::nx::Object}}. When softrecreate is set, the class hierarchy +# remains untouched. +# +# @param toggle Accepts either "on" or "off" +# @return The current toggle value + + +# @subcommand ::nx::core::configure#objectsystems +# +# A mere introspection subcommand. It gives you the top level of the +# current object system, i.e., the ruling root class and root +# meta-class. For "Next": +# +# {{{ +# ::nx::core::configure objectsystems; # returns "::nx::Object ::nx::Class" +# }}} +# +# @return The active pair of root class and root meta-class + +# @subcommand ::nx::core::configure#keepinitcmd +# +# Usually, initcmd scripts are discarded by the {{{interp}}} once +# having been evaluated (in contrast to {{{proc}}} and {{{method}}} +# bodies). If you need them preserved for later introspection and +# processing (as in the "Next" documentation system), set this option +# to {{{true}}}. Then, the initcmd scripts are retained as a +# particular object variable ({{{__initcmd}}}) of classes and +# objects. It defaults to {{{false}}}. +# +# @param value:boolean Either {{{true}}} or {{{false}}} +# @return The current setting xotclCmd configure XOTclConfigureCmd { {-argName "configureoption" -required 1 -type "filter|softrecreate|objectsystems|keepinitcmd"} {-argName "value" -required 0 -type tclobj} @@ -58,6 +137,7 @@ } xotclCmd finalize XOTclFinalizeObjCmd { } + xotclCmd forward XOTclForwardCmd { {-argName "object" -required 1 -type object} {-argName "-per-object"} @@ -109,6 +189,23 @@ {-argName "method" -required 1 -type tclobj} {-argName "args" -type args} } + +# @command ::nx::next +# +# Invokes the shadowed (i.e, same-named) method which is next along +# the precedence path and returns the results of this invocation. If +# {{{next}}} is called without arguments, the arguments of the current +# method (i.e., the arguments as present at the current callframe) are +# passed through to the shadowed method. If next is invoked with the +# flag --noArgs, the shadowed method is called without the active +# callframe arguments. If other arguments are specified for {{{next}}} +# explicitly, these will be passed instead. +# +# @param --noArgs:optional Deactivates the forward-passing of the current callframe's arguments +# @param args Explicitly declared arguments to pass to shadowed methods + +# TODO: shouldn't next be defined here? + xotclCmd namespace_copycmds XOTclNSCopyCmds { {-argName "fromNs" -required 1 -type tclobj} {-argName "toNs" -required 1 -type tclobj} @@ -138,6 +235,31 @@ xotclCmd current XOTclCurrentCmd { {-argName "currentoption" -required 0 -type "proc|method|object|class|activelevel|args|activemixin|calledproc|calledmethod|calledclass|callingproc|callingmethod|callingclass|callinglevel|callingobject|filterreg|isnextcall|next"} } + +# @command ::nx::current +# +# An introspective command which allows you to explore the "Next" +# callstack from within the scope of a method (or procif bound to an +# object via {{{alias}}}). {{{current}}} computes callstack related +# information. If executed without specifying a subcommand, +# i.e. {{{[current]}}}, returns the name of the object, which is +# currently in execution. If called from outside a proc, it returns +# the error message "No current object". +# +# It comes with a variety of subcommands to query different bits of +# callstack information. See below. +# +# @subcommand class Returns the name of the class holding the currently executing per-class method, if and only if called from within a per-class method. Note, that this method-owning class may be different to the class of the current object. If called from within a per-object method, it returns an empty string. +# @subcommand proc Returns the name of the currently executing method. +# @subcommand callingclass Returns the name of the class which is calling into the executing method. +# @subcommand callingobject Returns the name of the object which is calling into the executing method. +# @subcommand calledclass Returns the name of the class that holds the originally (and now shadowed) target method (applicable in mixin classes and filters). +# @subcommand calledproc Returns the name of the target method (applicable in a filter only). +# @subcommand isnextcall Returns 1 if the executing method was invoked via {{@command ::nx::next}}, 0 otherwise. +# @subcommand next Returns the name of the method next on the precedence path as a string. +# @subcommand filterreg In a method serving as active filter, returns the name of the object (class) on which the method is registered as a filter. +# @subcommand callinglevel Returns the "original" callstack level calling into the executing method. Intermediary {{{next}}} calls are ignored in this computation. The level is returned in a form so that it can be used as first argument in {{@method ::nx::Object class uplevel}} or {{@method ::nx::Object class upvar}}. +# @subcommand activelevel Returns the actual callstack level calling into the executing method. The active might correspond the {{{callinglevel}}}, but this is not necessarily the case. The {{{activelevel}}} counts {{@command ::nx::next}} call. The level is returned in a form so that it can be used as first argument in {{@method ::nx::Object class uplevel}} or {{@method ::nx::Object class upvar}}. xotclCmd self XOTclSelfCmd { {-argName "selfoption" -required 0 -type "proc|method|object|class|activelevel|args|activemixin|calledproc|calledmethod|calledclass|callingproc|callingmethod|callingclass|callinglevel|callingobject|filterreg|isnextcall|next"} } @@ -151,73 +273,395 @@ {-argName "-per-object"} {-argName "parameter" -type tclobj} } + # # object methods # + +# @object ::nx::Object +# +# "Next" programs are constructed out of objects. This class +# describes common structural and behavioural features for all "Next" +# objects. It is the root object-class in the "Next" object system. + +# @method ::nx::Object#autoname +# +# Provides a facility for auto-generating object identifiers. It is +# constructed from a seeding string which is appended a numeric +# index. This numeric index is incremented upon each call to +# {{{autoname}}}. +# {{{ +# set obj [Object new] +# $obj autoname a; # yields "a1" +# $obj autoname -instance B; # yields "b1" +# $obj autoname a; # yields "a2" +# $obj autoname b; # yields "b1" +# $obj autoname -reset a; # "" +# $obj autoname -reset -instance B; # "" +# $obj autoname -instance a; # yields "a1", and NOT "a3"! +# $obj autoname -instance B; # yields "b1" +# $obj autoname b; # yields "b2" +# }}} +# The seeding string may also contain {{{[format]}}} expressions (see ...): +# {{{ +# $obj autoname a%06d; # gives you "a000001", ... +# }}} +# +# @param -instance Have the generated name start with a lower letter (though the seed string has a major first letter) +# @param -reset Reset the object-internal counter for a given seed string +# @param name The seeding string which is used as a base for name generation +# @return The generated name string objectMethod autoname XOTclOAutonameMethod { {-argName "-instance"} {-argName "-reset"} {-argName "name" -required 1 -type tclobj} } + +# @method ::nx::Object#cleanup +# +# Resets an object or class to its initial state, as after object +# allocation (see {{@method ::nx::Class class alloc}}). This method +# participates in recreating objects, i.e, it is called during the +# recreation process by {{@method ::nx::Class class recreate}}. +# Depending on the recreation scheme applied (see {{@command +# ::nx::core::configure}}, object variables are deleted, per-object +# namespaces are cleared, and the object's relationsships (e.g., mixin +# relations) are reset. objectMethod cleanup XOTclOCleanupMethod { } + +# @method ::nx::Object#configure +# +# This method participates in the object creation process. It is +# automatically invoked after having produced a new object by +# {{@method ::nx::Class class create}}. +# Upon its invocation, the variable argument vector {{{args}}} +# contains a list of parameters and parameter values passed in +# from the call site of object creation. They are matched against +# an object parameter definition. This definition, and so the +# actual method parameter definition of this method, is assembled +# from configuration values of the classes along the precedence +# order (see also {{@method ::nx::Object class objectparameter}}). +# The method {{{configure}}} can be called at arbitrary times to +# "re-set" an object. +# +# @param args The variable argument vector stores the object parameters and their values objectMethod configure XOTclOConfigureMethod { {-argName "args" -type allargs} } + +# @method ::nx::Object#destroy +# +# The method lays out the default object destruction process. By +# calling {{{destroy}}} on an object, you request its destruction: +# {{{ +# Object create anObject +# anObject destroy +# }}} +# Upon calling {{{destroy}}} on a given object, {{{destroy}}} +# delegates the actual destruction to {{@method ::nx::Class class dealloc}} +# which clears the memory object storage. +# {{{ +# [anObject destroy] .-----------------. .----------------. +# .......>|Object->destroy()|.....>|Class->dealloc()| +# `-----------------' `----------------' +# }}} +# Essentially, the behaviour could be scripted as: +# {{{ +# Object method destroy {} { +# [:info class] dealloc [self] +# } +# }}} +# Note, however, that {{{destroy}}} is protected against +# application-level redefinition. You must refine it in a subclass +# or mixin class. By doing so, {{{destroy}}} may be used to hook +# into the destruction process (e.g., to realise +# application-specific cleanup tasks). objectMethod destroy XOTclODestroyMethod { } + +# @method ::nx::Object#exists +# +# A helper method for checking whether the variable {{{var}}} is +# defined on the object and assigned a value. You may use a variable +# name with or without prefix, both will resolve to the object scope: +# {{{ +# $obj eval { +# set :foo 1 +# set bar 2 +# } +# +# $obj exists foo; # returns 1 +# $obj exists :foo; # returns 1 +# $obj exists bar; # returns 0 +# $obj exists :bar; # returns 0 +# }}} +# +# @param var The name of the variable to verify +# @return :boolean 1 if the variable exists, 0 otherwise objectMethod exists XOTclOExistsMethod { {-argName "var" -required 1} } + +# @method ::nx::Object#filter +# +# Adds gateway conditions to guard a filter registration point. The +# filter will only execute, if the guards evaluate to true. Otherwise, +# the filters are ignored the filter. If no guards are given, we +# always execute the filter. +# +# @param filter Handle to identify and address a filter once registered +# @param guard A list of guard expressions objectMethod filterguard XOTclOFilterGuardMethod { {-argName "filter" -required 1} {-argName "guard" -required 1 -type tclobj} } + +# @method ::nx::Object#filtersearch +# +# +# +# @param filter Handle to identify and address a filter once registered +# @param guard A list of guard expressions +# @return A string which describes a fully qualified method handle objectMethod filtersearch XOTclOFilterSearchMethod { {-argName "filter" -required 1} } + +# @method ::nx::Object#instvar +# +# @param args objectMethod instvar XOTclOInstVarMethod { {-argName "args" -type allargs} } + +# @method ::nx::Object#mixinguard +# +# @param mixin +# @param guard objectMethod mixinguard XOTclOMixinGuardMethod { {-argName "mixin" -required 1} {-argName "guard" -required 1 -type tclobj} } objectMethod __next XOTclONextMethod { {-argName "args" -type allargs} } + +# @method ::nx::Object#mixinguard +# +# @param mixin +# @param guard objectMethod noinit XOTclONoinitMethod { } + +# @method ::nx::Object#requireNamespace +# +# This method allows you to request the creation of a namespace for +# the given object, a per-object namespace. The namespace is then used +# to store instance variables, methods and nested objects. Per-object +# namespaces are needed for using and binding object variables to +# non-object scopes in Tcl and Tk. For instance, you may use an +# per-object namespace to have object variables accessible Tk widgets +# and Tk callbacks. To verify whether a per-object namespace is +# available for an object, see ... +# +# Beware that there is a difference between per-object namespaces and +# Tcl namespaces which shadow an existing object (i.e., carry the same +# name): +# {{{ +# Object create Foo +# Foo requireNamespace +# namespace exists Foo; # returns 1 +# Foo info hasnamespace; # returns 1 +# +# Object create Bar +# namespace eval ::Bar {} +# namespace exists Bar; # returns 1 +# Bar info hasnamespace; # returns 0 +# }}} objectMethod requireNamespace XOTclORequireNamespaceMethod { } + +# @method ::nx::Object#residualargs +# +# @param args objectMethod residualargs XOTclOResidualargsMethod { {-argName "args" -type allargs} } + +# @method ::nx::Object#uplevel +# +# This helper allows you to evaluate a script in the context of +# another callstack level (i.e., callstack frame). +# +# @param level:optional The starting callstack level (defaults to the value of {{{[current callinglevel]}}}) +# @param script:list The script to be evaluated in the targeted callstack level objectMethod uplevel XOTclOUplevelMethod { {-argName "args" -type allargs} } + +# @method ::nx::Object#upvar +# +# This helper allows you to bind a local variable to a variable +# residing at a different callstack level (frame). +# +# @param level:optional The starting callstack level (defaults to the value of {{{[current callinglevel]}}}) +# @param sourceVar A variable which should be linked to a ... +# @param targetVar ... which is a local variable in a method scope +# @see ... objectMethod upvar XOTclOUpvarMethod { {-argName "args" -type allargs} } + +# @method ::nx::Object#volatile +# +# By calling on this method, the object is bound in its lifetime to +# the one of call site (e.g., the given Tcl proc or method scope): +# {{{ +# proc foo {} { +# info vars; # shows "" +# set x [Object create Bar -volatile] +# info vars; # shows "x Bar" +# } +# }}} +# Behind the scenes, {{{volatile}}} registers a C-level variable trace +# ({{{Tcl_TraceVar()}}}) on the hiddenly created local variable (e.g., +# {{{Bar}}}), firing upon unset events and deleting the referenced +# object ({{{Bar}}}). That is, once the callframe context of {{{foo}}} +# is left, the local variable {{{Bar}}} is unset and so the bound +# object is destroyed. objectMethod volatile XOTclOVolatileMethod { } + +# @method ::nx::Object#vwait +# +# A method variant of the Tcl {{{vwait}}} command. You can use it to +# have the {{{interp}}} enter an event loop until the specified +# variable {{{varname}}} is set on the object. +# +# @param varname The name of the signalling object variable. objectMethod vwait XOTclOVwaitMethod { {-argName "varname" -required 1} } # # class methods # + +# @object ::nx::Class +# +# A class defines a family of object types which own a common set of +# attributes (see {{@object ::nx::Attribute}}) and methods. Classes +# are organised according to their similarities and differences in +# classification hierarchies. This object represents the root +# meta-class in the "Next" object system. +# +# @superclass ::nx::doc::entities::object::nx::Object + +# @method ::nx::Class#alloc +# +# Creates a bare object or class which is not +# fully initialized. {{{alloc}}} is used by {{@method ::nx::Class class create}} to +# request a memory object storage. In subsequent steps, +# {{{create}}} invokes {{{configure}}} and {{{init}}} to further +# set up the object. Only in rare situations, you may consider +# bypassing the overall {{{create}}} mechanism by just allocating +# uninitialized objects using {{{alloc}}}. +# +# @param name The object identifier assigned to the object storage to be allocated. +# @return The name of the allocated, uninitialized object classMethod alloc XOTclCAllocMethod { {-argName "name" -required 1 -type tclobj} } + +# @method ::nx::Class#create +# +# Provides for creating application-level classes and objects. If +# the method receiver is a meta-class, a class will be +# created. Otherwise, {{{create}}} yields an object. {{{create}}} +# is responsible a multi-phase object creation scheme. This +# creation scheme involves three major steps: +# {{{ +# [Object create anObject] (1) +# ---------------. .--------------. +# -------------->|Class->create()|-->|Class->alloc()| +# `---------------' `--------------' +# | | (2) .-------------------. +# | .----->|Object->configure()| +# | `-------------------' +# | (3) .------. +# .........>|init()| +# `------' +# }}} +# (1) A call to {{@method ::nx::Class class alloc}} to create a raw, +# uninitalized object. +# +# (2) The newly allocated object receives a method call upon +# {{@method ::nx::Object class configure}}. This will establish the +# object's initial state, by applying object parameter values +# provided at object creation time and default values defined at +# object definition time. +# +# (3) Finally, {{{create}}} emits a call to the initialization +# method {{{init}}} (i.e., the actual "constructor"), if +# available. An {{{init}}} method can be defined by a class on +# behalf of its objects, to lay out class-specific initialisation +# behaviour. Alternatively, each single object may define an +# {{{init}}} method on its own. +# +# By overloading the method in a meta-class, you can refine or +# replace this default object creation scheme (e.g., for applying +# application-specific naming schemes). +# +# For creating an object or a class, you must name {{{create}}} +# explicitly, i.e.: +# {{{ +# ::nx::Object create anObject +# ::nx::Class create AClass +# ::nx::Class AnotherClass; # This fails: "Method 'AnotherClass' unknown for ::nx::Class." +# }}} +# +# @param name The designated identifier on the class or the object to be created. +# @param args Arguments to be passed down to the object creation procedure used to initialize the object. +# @return The name of the created, fully initialized object. classMethod create XOTclCCreateMethod { {-argName "name" -required 1} {-argName "args" -type allargs} } + +# @method ::nx::Class#dealloc +# +# Marks objects for physical deletion in memory. Beware the fact +# that calling {{{dealloc}}} does not necessarily cause the object +# to be deleted immediately. Depending on the lifecycle of the the +# object's environment (e.g., the {{{interp}}}, the containing +# namespace) and on call references down the callstack, the actual +# memory freeing operation may occur time-shifted (that is, +# later). While {{{dealloc}}} itself cannot be redefined for +# {{{::nx::Class}}}, you may consider refining it in a subclass or +# mixin class for customizing the destruction process. +# +# @param object The name of the object to be scheduled for deletion. classMethod dealloc XOTclCDeallocMethod { {-argName "object" -required 1 -type tclobj} } + +# @method ::nx::Class#new +# +# A convenience method to create auto-named objects and classes. It is +# a front-end to {{@method ::nx::Class class create}}. For instance: +# {{{ +# set obj [Object new] +# set cls [Class new] +# }}} +# +# This will provide object identifiers of the form +# e.g. {{{::nx::core::__#0}}}. In contrast to {{@method ::nx::Object class autoname}}, +# the uniqueness of auto-generated identifiers is guaranteed for the +# scope of the {{{interp}}}. +# +# @param -childof If provided, the new object is created as a child of the specified object. +# @param args The variable arguments passed down to {{@method ::nx::Class class create}}. classMethod new XOTclCNewMethod { {-argName "-childof" -type object -nrargs 1} {-argName "args" -required 0 -type args} @@ -232,6 +676,40 @@ } classMethod __invalidateobjectparameter XOTclCInvalidateObjectParameterMethod { } + +# @method ::nx::Class#recreate +# +# This method is called upon recreating an object. Recreation is the +# scheme for resolving object naming conflicts in the dynamic and +# scripted programming environment of "Next": An object or class is +# created while an object or class with an identical object identifier +# already exists. The method {{{recreate}}} performs standard object +# initialization, per default, after re-setting the state and +# relationships of the object under recreation. This re-set is +# achieved by invoking {{@method ::nx::Object class cleanup}}. +# {{{ +# Object create Bar +# \# ... +# Object create Bar; # calls Object->recreate(::Bar, ...) + ::Bar->cleanup() +# }}} +# By refining {{{recreate}}} in an application-level subclass or mixin +# class, you can intercept the recreation process. In the pre-part the +# refined {{{recreate}}} method, the recreated object has its old +# state, after calling {{@command ::nx::next}} it is cleaned up. +# +# If the name conflict occurs between an existing class and a newly +# created object (or vice versa), {{{recreate}}} is not +# performed. Rather, a sequence of {{@method ::nx::Object class destroy}} +# and {{@method ::nx::Class class create}} is triggered: +# {{{ +# Object create Bar +# \# ... +# Class create Bar; # calls Bar->destroy() + Class->create(::Bar, ...) +# }}} +# +# @param name The name (identifier) of the object under recreation +# @param args Arbitrary vector of arguments +# @return The name of the recreated object classMethod recreate XOTclCRecreateMethod { {-argName "name" -required 1 -type tclobj} {-argName "args" -type allargs} Index: generic/predefined.h =================================================================== diff -u -rfb73930aa9ecf6ce966e512e6f899acb5784ea8c -rbb58b68431fe35dd6ff16e69044705e1246d0dda --- generic/predefined.h (.../predefined.h) (revision fb73930aa9ecf6ce966e512e6f899acb5784ea8c) +++ generic/predefined.h (.../predefined.h) (revision bb58b68431fe35dd6ff16e69044705e1246d0dda) @@ -1,5 +1,4 @@ static char cmd[] = -"\n" "namespace eval ::nx {\n" "set bootstrap 1\n" "::nx::core::createobjectsystem ::nx::Object ::nx::Class {\n" @@ -36,12 +35,14 @@ "::nx::core::methodproperty Class alloc redefine-protected true\n" "::nx::core::methodproperty Class dealloc redefine-protected true\n" "::nx::core::methodproperty Class create redefine-protected true\n" +"# anInstance foo; # invokes \"foo\"\n" "::nx::core::method Class method {\n" "name arguments body -precondition -postcondition} {\n" "set conditions [list]\n" "if {[info exists precondition]} {lappend conditions -precondition $precondition}\n" "if {[info exists postcondition]} {lappend conditions -postcondition $postcondition}\n" "::nx::core::method [::nx::core::current object] $name $arguments $body {*}$conditions}\n" +"#\n" "::nx::core::method Object method {\n" "name arguments body -precondition -postcondition} {\n" "set conditions [list]\n" @@ -81,7 +82,11 @@ ":protected method init args {}\n" ":protected method defaultmethod {} {::nx::core::current object}\n" ":protected method objectparameter {} {;}}\n" +"# argument list on position POS, where POS can be a positive or\n" +"# left to right and should be used in ascending order.\n" "::nx::core::forward Object forward ::nx::core::forward %self -per-object\n" +"# {{{ {%@POS value} }}} substitute the specified value in the\n" +"# integer or the word end. The positional arguments are evaluated from\n" "::nx::core::forward Class forward ::nx::core::forward %self\n" "Class protected object method __unknown {name} {}\n" "Object public method alias {-nonleaf:switch -objscope:switch methodName cmd} {\n" Index: generic/predefined.xotcl =================================================================== diff -u -rfb73930aa9ecf6ce966e512e6f899acb5784ea8c -rbb58b68431fe35dd6ff16e69044705e1246d0dda --- generic/predefined.xotcl (.../predefined.xotcl) (revision fb73930aa9ecf6ce966e512e6f899acb5784ea8c) +++ generic/predefined.xotcl (.../predefined.xotcl) (revision bb58b68431fe35dd6ff16e69044705e1246d0dda) @@ -1,4 +1,3 @@ - namespace eval ::nx { # # By setting the variable bootstrap, we can check later, whether we @@ -16,8 +15,8 @@ -class.create create -class.dealloc dealloc -class.recreate recreate - -class.requireobject __unknown - -object.configure configure + -class.requireobject __unknown + -object.configure configure -object.defaultmethod defaultmethod -object.destroy destroy -object.init init @@ -34,6 +33,8 @@ namespace export next self \ my is relation interp } + + namespace import ::nx::core::next ::nx::core::self # @@ -58,6 +59,7 @@ foreach cmd [list __next cleanup noinit residualargs uplevel upvar] { ::nx::core::methodproperty Object $cmd protected 1 } + foreach cmd [list recreate] { ::nx::core::methodproperty Class $cmd protected 1 } @@ -70,6 +72,31 @@ ::nx::core::methodproperty Class create redefine-protected true # define method "method" for Class and Object + + # @method ::nx::Class#method + # + # Defines a per-class method, similarly to Tcl specifying + # {{{procs}}}. Optionally assertions may be specified by two + # additional arguments. Therefore, to specify only post-assertions + # an empty pre-assertion list must be given. All assertions are a + # list of ordinary Tcl {{{expr}}} statements. When {{{method}}} is + # called with an empty argument list and an empty body, the + # specified method is deleted. + # {{{ + # Class create AClass { + # :method foo args {;} + # } + # + # AClass create anInstance + # anInstance foo; # invokes "foo" + # }}} + # + # @param name The method name + # @param arguments:list A list specifying non-positional and positional parameters + # @param body The script which forms the method body + # @param preAssertion Optional assertions that must hold before the proc executes + # @param postAssertion Optional assertions that must hold after the proc executes + ::nx::core::method Class method { name arguments body -precondition -postcondition } { @@ -79,6 +106,27 @@ ::nx::core::method [::nx::core::current object] $name $arguments $body {*}$conditions } + # @method ::nx::Object#method + # + # Defines a per-object method, similarly to Tcl specifying + # {{{procs}}}. Optionally assertions may be specified by two + # additional arguments. Therefore, to specify only post-assertions + # an empty pre-assertion list must be given. All assertions are a + # list of ordinary Tcl {{{expr}}} statements. When {{{method}}} is + # called with an empty argument list and an empty body, the + # specified method is deleted. + # {{{ + # Object create anObject { + # :method foo args {;} + # } + # anObject foo; # invokes "foo" + # }}} + # + # @param name The method name + # @param arguments:list A list specifying non-positional and positional parameters + # @param body The script which forms the method body + # @param preAssertion Optional assertions that must hold before the proc executes + # @param postAssertion Optional assertions that must hold after the proc executes ::nx::core::method Object method { name arguments body -precondition -postcondition } { @@ -156,7 +204,92 @@ } # define forward methods + + # @method ::nx::Object#forward + # + # Register a per-object method (similar to a {{{proc}}}) for + # forward-delegating calls to a callee (target Tcl command, other + # object). When the forwarder method is called, the actual arguments + # of the invocation are appended to the specified arguments. In + # callee an arguments certain substitutions can take place: + # + # {{{%proc}}} substituted by name of the forwarder method + # + # {{{%self}}} substitute by name of the object + # + # {{{%1}}} substitute by first argument of the invocation + # + # {{{ {%@POS value} }}} substitute the specified value in the + # argument list on position POS, where POS can be a positive or + # negative integer or end. Positive integers specify the position + # from the begin of the list, while negative integer specify the + # position from the end. + # + # {{{ {%argclindex LIST} }}} take the nth argument of the specified + # list as substitution value, where n is the number of arguments + # from the invocation. + # + # {{{%%}}} a single percent. + # + # {{{%Tcl-command}}} command to be executed; substituted by result. + # Additionally each argument can be prefixed by the positional prefix + # %@POS (note the delimiting space at the end) that can be used to + # specify an explicit position. POS can be a positive or negative + # integer or the word end. The positional arguments are evaluated from + # left to right and should be used in ascending order. + # + # @param name The name of the delegating or forward method + # @param -objscope:optional Causes the target to be evaluated in the scope of the object. + # @param -methodprefix Prepends the specified prefix to the second argument of the invocation. + # @param -default Is used for default method names (only in connection with %1) + # @param -earlybinding 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, no scripted procs + # @param -verbose Print the substituted command to stderr before executing + # @param callee + # @param args ::nx::core::forward Object forward ::nx::core::forward %self -per-object + + # @method ::nx::Class#forward + # + # Register a per-class method (similar to a {{{proc}}}) for + # forward-delegating calls to a callee (target Tcl command, other + # object). When the forwarder method is called on an instance of the + # class, the actual arguments of the invocation are appended to the + # specified arguments. In callee an arguments certain substitutions + # can take place: + # + # {{{%proc}}} substituted by name of the forwarder method + # + # {{{%self}}} substitute by name of the object + # + # {{{%1}}} substitute by first argument of the invocation + # + # {{{ {%@POS value} }}} substitute the specified value in the + # argument list on position POS, where POS can be a positive or + # negative integer or end. Positive integers specify the position + # from the begin of the list, while negative integer specify the + # position from the end. + # + # {{{ {%argclindex LIST} }}} take the nth argument of the specified + # list as substitution value, where n is the number of arguments + # from the invocation. + # + # {{{%%}}} a single percent. + # + # {{{%Tcl-command}}} command to be executed; substituted by result. + # Additionally each argument can be prefixed by the positional prefix + # %@POS (note the delimiting space at the end) that can be used to + # specify an explicit position. POS can be a positive or negative + # integer or the word end. The positional arguments are evaluated from + # left to right and should be used in ascending order. + # + # @param name The name of the delegating or forward method + # @param -objscope:optional Causes the target to be evaluated in the scope of the object. + # @param -methodprefix Prepends the specified prefix to the second argument of the invocation. + # @param -default Is used for default method names (only in connection with %1) + # @param -earlybinding 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, no scripted procs + # @param -verbose Print the substituted command to stderr before executing + # @param callee + # @param args ::nx::core::forward Class forward ::nx::core::forward %self # The method __unknown is called in cases, where we try to resolve @@ -356,12 +489,27 @@ return [::nx::core::cmd::${info}::method $target name $name] } + # @object ::nx::Slot + # + # A slot is a meta-object that manages property changes of + # objects. A property is either an attribute or a role taken by an + # object in an inter-object relation (e.g., in system slots). The + # predefined system slots are {{{class}}}, {{{superclass}}}, + # {{{mixin}}}, and {{{filter}}}. These slots appear as methods of + # {{@object ::nx::Object}} or {{@object ::nx::Class}}. The slots + # provide a common getter and setter interface. Every multivalued + # slot provides e.g. a method {{{add}}} to append a value to the + # list of values, and a method {{{delete}}} which removes it. + # + # @superclass ::nx::doc::entities::object::nx::Object ::nx::MetaSlot create ::nx::Slot - ::nx::MetaSlot create ::nx::ObjectParameterSlot - ::nx::core::relation ::nx::ObjectParameterSlot superclass ::nx::Slot + # @object ::nx::ObjectParameterSlot # - # create class and object for method parameter slots + # @superclass ::nx::doc::entities::object::nx::Slot + ::nx::MetaSlot create ::nx::ObjectParameterSlot + ::nx::core::relation ::nx::ObjectParameterSlot superclass ::nx::Slot + ::nx::MetaSlot create ::nx::MethodParameterSlot ::nx::core::relation ::nx::MethodParameterSlot superclass ::nx::Slot @@ -414,6 +562,27 @@ ############################################ # Define slots for slots ############################################ + + # @param ::nx::Slot#name + # + # Name of the slot which can be used to access the slot from an object + + # @param ::nx::Slot#multivalued + # + # Boolean value for specifying single or multiple values (lists) + + # @param ::nx::Slot#required + # + # Denotes whether a value must be provided + + # @param ::nx::Slot#default + # + # Allows you to define a default value (to be set upon object creation) + + # @param ::nx::Slot#type + # + # You may specify a type constraint on the value range to managed by the slot + createBootstrapAttributeSlots ::nx::Slot { {name} {multivalued false} @@ -422,6 +591,34 @@ type } + # @param ::nx::ObjectParameterSlot#name + # + # Name of the slot which can be used to access the slot from an + # object. It defaults to unqualified name of an instance. + + # @param ::nx::ObjectParameterSlot#methodname + # + # The name of the accessor methods to be registed on behalf of the + # slot object with its domains can vary from the slot name. + + # @param ::nx::ObjectParameterSlot#domain + # + # The domain (object or class) of a slot on which it can be used + + # @param ::nx::ObjectParameterSlot#defaultmethods + # + # A list of two elements for specifying which methods are called per + # default, when no slot method is explicitly specified in a call. + + # @param ::nx::ObjectParameterSlot#manager + # + # The manager object of the slot (per default, the slot object takes + # this role, i.e. {{{[self]}}}) + + # @param ::nx::ObjectParameterSlot#per-object + # + # If set to {{{true}}}, the accessor methods are registered with the + # domain object scope only. It defaults to {{{false}}}. createBootstrapAttributeSlots ::nx::ObjectParameterSlot { {name "[namespace tail [::nx::core::current object]]"} {methodname} @@ -593,6 +790,7 @@ return $parameterdefinitions } + # @method ::nx::Object#objectparameter ::nx::Object protected method objectparameter {{lastparameter __initcmd:initcmd,optional}} { #puts stderr "... objectparameter [::nx::core::current object]" set parameterdefinitions [::nx::core::parametersFromSlots [::nx::core::current object]] @@ -682,16 +880,69 @@ proc ::nx::core::register_system_slots {os} { ${os}::Object alloc ${os}::Class::slot ${os}::Object alloc ${os}::Object::slot - + + # @param ::nx::Class#superclass + # + # Specifies superclasses for a given class. As a setter, + # {{{superclass}}} changes the list of superclasses. When used as + # a getter, the method returns the current superclasses. + # + # @return :list If called as a getter (without arguments), + # {{{superclass}}} returns the current superclasses of the object ::nx::RelationSlot create ${os}::Class::slot::superclass ::nx::core::alias ${os}::Class::slot::superclass assign ::nx::core::relation + + # @param ::nx::Object#class + # + # Sets or retrieves the class of an object. When {{{class}}} is + # called without arguments, it returns the current class of the + # object. + # + # @return If called as a getter (without arguments), {{{class}}} returns the current class of the object ::nx::RelationSlot create ${os}::Object::slot::class -multivalued false ::nx::core::alias ${os}::Object::slot::class assign ::nx::core::relation - + + # @param ::nx::Object#mixin + # + # As a setter, {{{mixin}}} specifies a list of mixins to + # set. Every mixin must be an existing class. In getter mode, you + # can retrieve the list of mixins active for the given object. + # + # @return :list If called as a getter (without arguments), {{{mixin}}} returns the list of current mixin classes registered with the object ::nx::RelationSlot create ${os}::Object::slot::mixin -methodname object-mixin + + # @param ::nx::Object#filter + # + # In its setter mode, {{{filter}}} allows you to register methods + # as per-object filters. Every filter must be an existing method + # in the scope of the object. When acting as a getter, you can + # retrieve the list of filter methods active for the given object. + # + # @return :list If called as a getter (without arguments), + # {{{filter}}} returns the list of current filters + # registered with the object ::nx::RelationSlot create ${os}::Object::slot::filter -elementtype "" + # @param ::nx::Class#mixin + # + # As a setter, {{{mixin}}} specifies a list of mixins to set for + # the class. Every mixin must be an existing class. In getter + # mode, you can retrieve the list of mixins active for the given + # class. + # + # @return :list If called as a getter (without arguments), {{{mixin}}} returns the list of current mixin classes registered with the class ::nx::RelationSlot create ${os}::Class::slot::mixin -methodname class-mixin + + # @param ::nx::Class#filter + # + # In its setter mode, {{{filter}}} allows you to register methods + # as per-class filters. Every filter must be an existing method + # in the scope of the class. When acting as a getter, you can + # retrieve the list of filter methods active for the given class. + # + # @return :list If called as a getter (without arguments), + # {{{filter}}} returns the list of current filters + # registered with the class ::nx::RelationSlot create ${os}::Class::slot::filter -elementtype "" \ -methodname class-filter @@ -707,6 +958,29 @@ # Attribute slots ############################################ ::nx::MetaSlot __invalidateobjectparameter + + # @object ::nx::Attribute + # + # Attribute slots are used to manage the access, mutation, and + # querying of instance variables. There is a helper method {{@method + # ::nx::Object class attribute}} to define the attributes of classes + # (and objects). Consider the example of a class definition with + # three attribute slots: + # {{{ + # Class create Person { + # :attribute name + # :attribute {salary 0} + # :attribute {projects ""} { + # set :multivalued true + # } + # } + # }}} + # + # @param incremental Allows for using the fine-grained modification (i.e., setting) of the managed variable {e.g., through an incremental {{{add}}}) + # @param valuecmd A Tcl command to be executed whenever the managed object variable is read + # @param valuechangedcmd A Tcl command to be executed whenever the value of the managed object variable changes + # @param arg + # @superclass ::nx::doc::entities::object::nx::ObjectParameterSlot ::nx::MetaSlot create ::nx::Attribute -superclass ::nx::ObjectParameterSlot createBootstrapAttributeSlots ::nx::Attribute { Index: library/lib/doc-assets/ac-js =================================================================== diff -u -r2c490ff6c40c296798a08edce62d5cea6cb968ea -rbb58b68431fe35dd6ff16e69044705e1246d0dda --- library/lib/doc-assets/ac-js (.../ac-js) (revision 2c490ff6c40c296798a08edce62d5cea6cb968ea) +++ library/lib/doc-assets/ac-js (.../ac-js) (revision bb58b68431fe35dd6ff16e69044705e1246d0dda) @@ -49,7 +49,7 @@ return checked; }; - var els = ['show_private'], + var els = ['show_protected'], reapplyHash = false; for (var i = 0; i < els.length; i++) { Index: library/lib/doc-assets/command.html.tmpl =================================================================== diff -u -r5dcd186af36657d206cc32709e40b8d681ce1d0e -rbb58b68431fe35dd6ff16e69044705e1246d0dda --- library/lib/doc-assets/command.html.tmpl (.../command.html.tmpl) (revision 5dcd186af36657d206cc32709e40b8d681ce1d0e) +++ library/lib/doc-assets/command.html.tmpl (.../command.html.tmpl) (revision bb58b68431fe35dd6ff16e69044705e1246d0dda) @@ -19,31 +19,35 @@

[$sub name]

+ [:? {[$sub exists @return] && [[$sub @return] spec] ne ""} {<[[$sub @return] spec]>} ] + ${:name} + [$sub name] + [$sub parameters] +
[$sub text] -
- [:? {[$sub exists :@param]} { -
-
Parameters:
+ [:? {[$sub exists :@param]} { +
+
Subcommand parameters:
[:for param [$sub @param] {
[$param name] - <[:? {[$param exists spec]} {[$param spec]}]> + [:? {[$param exists spec] && [$param spec] ne ""} {<[$param spec]>}] [$param text]
}]
}] - - [:? {[$sub exists :@return]} { + [:? {[$sub exists :@return]} {
Returns:
[[$sub @return] text]
}] +

Index: library/lib/doc-assets/object.html.tmpl =================================================================== diff -u -r2c490ff6c40c296798a08edce62d5cea6cb968ea -rbb58b68431fe35dd6ff16e69044705e1246d0dda --- library/lib/doc-assets/object.html.tmpl (.../object.html.tmpl) (revision 2c490ff6c40c296798a08edce62d5cea6cb968ea) +++ library/lib/doc-assets/object.html.tmpl (.../object.html.tmpl) (revision bb58b68431fe35dd6ff16e69044705e1246d0dda) @@ -1,7 +1,7 @@
Filters - +

@@ -28,7 +28,7 @@
[:?var :@param {
-

Attributes

+

Slots

[:for attr ${:@param} {
@@ -67,7 +67,7 @@ [:let attrs [dict get $iattrs $superclass]]
-

Attributes inherited +

Slots inherited from [$superclass name]:

Index: library/lib/doc-assets/package.html.tmpl =================================================================== diff -u -rcda7278a163020684b886f41aec71c90a2c39535 -rbb58b68431fe35dd6ff16e69044705e1246d0dda --- library/lib/doc-assets/package.html.tmpl (.../package.html.tmpl) (revision cda7278a163020684b886f41aec71c90a2c39535) +++ library/lib/doc-assets/package.html.tmpl (.../package.html.tmpl) (revision bb58b68431fe35dd6ff16e69044705e1246d0dda) @@ -1,6 +1,6 @@ -

Module: ${:name} +

Package: ${:name}

Index: library/lib/doc-tools.xotcl =================================================================== diff -u -r783648c4c7132adc4a447faa69d6e4e12b621c46 -rbb58b68431fe35dd6ff16e69044705e1246d0dda --- library/lib/doc-tools.xotcl (.../doc-tools.xotcl) (revision 783648c4c7132adc4a447faa69d6e4e12b621c46) +++ library/lib/doc-tools.xotcl (.../doc-tools.xotcl) (revision bb58b68431fe35dd6ff16e69044705e1246d0dda) @@ -466,6 +466,19 @@ :attribute @subcommand -slotclass ::nx::doc::PartAttribute { set :part_class @subcommand } + :method parameters {} { + set params [list] + if {[info exists :@param]} { + foreach p [:@param] { + set value [$p name] + if {[$p exists default] || [$p name] eq "args" } { + set value "?[$p name]?" + } + lappend params $value + } + } + return $params + } } EntityClass create @object \ @@ -627,7 +640,7 @@ # # @param partof Refers to the entity object which contains this part # @param name Stores the name of the documented parameter - # @modifier private + # @modifier protected set partof_fragment [:get_unqualified_name ${partof}] return [:root_namespace]::${:tag}::${partof_fragment}::${name} @@ -803,10 +816,13 @@ set id [$entity_type id {*}$args] if {![::nx::core::is $id object]} return; set pof "" - if {[$id info is type ::nx::core::Part]} { + if {[$id info is type ::nx::doc::Part]} { set pof "[[$id partof] name]#" + set filename [[$id partof] filename] + } else { + set filename [$id filename] } - return "$pof[$id name]" + return "$pof[$id name]" } :method text {} { @@ -974,7 +990,7 @@ # b. intrinsic: 'thing' is a arbitrary string block describing # a script. # - :method process {thing args} { + :method process {{-noeval false} thing args} { # 1) in-situ processing: a class object if {[::nx::core::objectproperty $thing object]} { if {[$thing exists __initcmd]} { @@ -1022,7 +1038,8 @@ :log "error reading the file '$thing', i.e.: '$msg'" } close $fh - doc analyze $script {*}$args + doc analyze -noeval $noeval $script {*}$args + #doc process -noeval $noeval $script {*}$args } else { :log "file '$thing' not readable" } @@ -1032,27 +1049,29 @@ set cmd [subst { package req next::doc namespace import -force ::nx::doc::* - doc analyze [list $thing] + doc analyze -noeval $noeval [list $thing] }] interp eval $i $cmd #interp delete $i return $i } } - :method analyze {script additions:optional} { + :method analyze {{-noeval false} script {additions ""}} { # NOTE: This method is to be executed in a child/ slave # interpreter. - uplevel #0 [list namespace import -force ::nx::doc::*] - set pre_commands [:list_commands] - uplevel #0 [list eval $script] - set post_commands [:list_commands] - if {![info exists additions]} { - set additions [dict keys [dict remove [dict create {*}"[join $post_commands " _ "] _"] {*}$pre_commands]] - } else { - set additions [dict keys [dict get $additions objects]] + if {!$noeval} { + uplevel #0 [list namespace import -force ::nx::doc::*] + set pre_commands [:list_commands] + uplevel #0 [list eval $script] + set post_commands [:list_commands] + if {$additions eq ""} { + set additions [dict keys [dict remove [dict create {*}"[join $post_commands " _ "] _"] {*}$pre_commands]] + } else { + set additions [dict keys [dict get $additions objects]] + } + # puts stderr ADDITIONS=$additions } - puts stderr ADDITIONS=$additions set blocks [:comment_blocks $script] # :log "blocks: '$blocks'" # 1) eval the script in a dedicated interp; provide for @@ -1330,7 +1349,7 @@ } if {$failure ne ""} { - puts stderr ERRORINFO=$::errorInfo + #puts stderr ERRORINFO=$::errorInfo error $failure } @@ -1401,7 +1420,6 @@ The entity type '$tag' is not available }]] throw } - puts stderr "$tag new -name $nq_name {*}$args" set :current_entity [$tag new -name $nq_name {*}$args] } } else { Index: tests/doc.xotcl =================================================================== diff -u -r783648c4c7132adc4a447faa69d6e4e12b621c46 -rbb58b68431fe35dd6ff16e69044705e1246d0dda --- tests/doc.xotcl (.../doc.xotcl) (revision 783648c4c7132adc4a447faa69d6e4e12b621c46) +++ tests/doc.xotcl (.../doc.xotcl) (revision bb58b68431fe35dd6ff16e69044705e1246d0dda) @@ -505,7 +505,6 @@ if {[catch {set i [doc process next::doc]} msg]} { if {[Exception behind? $msg]} { puts stderr [$msg info class]->[$msg message] - exit } else { error $msg } @@ -522,6 +521,28 @@ -outdir /tmp \ -project {name nextdoc url http://www.next-scripting.org/ version 0.1d}] interp delete $i + + # + # core documentation + # + set path [file join /tmp NextLanguageCore] + if {[file exists $path]} { + file delete -force $path + } + + set i [interp create] + $i eval { + package req next::doc + namespace import ::nx::* + namespace import ::nx::doc::* + doc process -noeval true /Users/ssoberni/Documents/dev/xotcl/generic/gentclAPI.decls + doc process -noeval true /Users/ssoberni/Documents/dev/xotcl/generic/predefined.xotcl + ::nx::doc::make doc \ + -renderer ::nx::doc::TemplateData \ + -outdir /tmp \ + -project {name NextLanguageCore url http://www.next-scripting.org/ version 1.0.0a} + } + interp delete $i } @@ -549,7 +570,71 @@ o method bar {arg1:object,type=::some::unknown::Class} {;} ? {o bar ::o} "expected object of type ::some::unknown::Class but got \"::o\" for parameter arg1"; # the error should rather reflect that ::some::unknown::Class is a non-existing class object! + ? {o info is type ::xyz::Bar} 0; # similarly, [info is] 0 for non-existing class objects! It should rather report the non-existance of a valid class object, as otherwise, the introspective act is misleading + + ? {o autoname -reset a} ""; # why does autoname with -reset flag does not return anything, e.g., "a1" here; "name", though required, does not make any sense there. why not return a result after resetting? + + # TODO: is [autoname -instance] really needed? + + # TODO: why is XOTclNextObjCmd/::nx::core::next not in gentclAPI.decls? + + # TODO: where to locate the @ comments (in predefined.xotcl, in + # gentclAPI.decls)? how to deal with ::nx::core::* vs. ::nx::* + # TODO: which values are returned from Object->configure() and + # passed to init()? how to document residualargs()? + + # TODO: Object->cleanup() said: "Resets an object or class into an + # initial state, as after construction." If by construction it means + # after create(), then cleanup() is missing a configure() call to + # set defaults, etc! + + # TODO: exists and bestandteil von info() oder selbstständig? + # ausserdem: erlauben von :-präfix?! + + # TODO: should we keep a instvar variant (i support this!) + + # TODO: verify the use of filtersearch()? should it return a method + # handle and the filter name? how to deal with it when refactoring + # procsearch()? + + # TODO: mixinguard doc is missing in old doc + + # TODO: what is Object->__next() for? + + # TODO: what to do with hasNamespace()? [Object info is namespace]? + + # TODO: why is XOTclOUplevelMethodStub/XOTclOUplevelMethod defined + # with "args" while it logically uses the stipulated parameter + # signature (level ...). is this because of the first pos, optional + # parameter? ... same goes for upvar() ... + + # TODO: is Object->uplevel still needed with an integrated cs management? + + # TODO: how is upvar affected by the ":"-prefixing? -> AVOID_RESOLVERS ... + + # TODO: do all member-creating operations return valid, canonical handles! + + # TODO: the objectsystems subcommand of ::nx::core::configure does + # not really fit in there because it does not allow for configuring + # anything. it is a mere introspection-only command. relocate (can + # we extend standard [info] somehow, i.e., [info objectsystems] + + # TODO: extend [info level] & [info frame]! + + # TODO: there is still --noArgs on [next], which does not correspond + # to single-dashed flags used elsewhere. Why? + + # TODO: renaming of self to current? + + # TODO: is [self callingclass] == [[self callingobject] info class]? + + # TODO: "# @subcommand next Returns the name of the method next on + # the precedence path as a string" shouldn't these kinds of + # introspective commands return method handles (in the sense of + # alias)? Retrieving the name from a handle is the more specific + # operation (less generic). ... same for "filterreg" + } if {$log} {