Index: generic/predefined.xotcl =================================================================== diff -u -r9cec079eb9f4ce69a8ecad865ea6ca12fff0bd45 -r6fa467e12f7a039c928b3096175a73414b5f26ff --- generic/predefined.xotcl (.../predefined.xotcl) (revision 9cec079eb9f4ce69a8ecad865ea6ca12fff0bd45) +++ generic/predefined.xotcl (.../predefined.xotcl) (revision 6fa467e12f7a039c928b3096175a73414b5f26ff) @@ -16,7 +16,7 @@ ::xotcl::alias Object [namespace tail $cmd] $cmd } - # provide some Tcl-commands as methods for ::xotcl::Object + # provide some Tcl-commands as methods for ::xotcl2::Object #foreach cmd {array append eval incr lappend set subst unset trace} { # ::xotcl::alias Object $cmd -objscope ::$cmd #} @@ -99,7 +99,7 @@ return "valid options are: [join [lsort $methods] {, }]" } objectInfo method unknown {method args} { - error "unknown info option \"$method\"; [.info info]" + error "[::xotcl::self] unknown info option \"$method\"; [.info info]" } classInfo method info {cl} { @@ -112,261 +112,12 @@ return "valid options are: [join [lsort $methods] {, }]" } classInfo method unknown {method args} { - error "unknown info option \"$method\"; [.info info]" + error "[::xotcl::self] unknown info option \"$method\"; [.info info]" } namespace export Object Class } -namespace eval ::xotcl { - # - # Perform the basic setup of XOTcl 1.x. First, let us allocate the - # basic classes of XOTcl. This call creates the classes - # ::xotcl::Object and ::xotcl::Class and defines these as root class - # of the object system and as root meta class. - # - ::xotcl::createobjectsystem ::xotcl::Object ::xotcl::Class - - # provide the standard command set for ::xotcl::Object - foreach cmd [info command ::xotcl::cmd::Object::*] { - ::xotcl::alias Object [namespace tail $cmd] $cmd - } - - # provide some Tcl-commands as methods for ::xotcl::Object - foreach cmd {array append eval incr lappend set subst unset trace} { - ::xotcl::alias Object $cmd -objscope ::$cmd - } - - # provide the standard command set for ::xotcl::Class - foreach cmd [info command ::xotcl::cmd::Class::*] { - ::xotcl::alias Class [namespace tail $cmd] $cmd - } - unset cmd - - # protect some methods against redefinition - ::xotcl::methodproperty Object destroy static true - ::xotcl::methodproperty Class alloc static true - ::xotcl::methodproperty Class dealloc static true - ::xotcl::methodproperty Class create static true - - Class method unknown {args} { - #puts stderr "use '[self] create $args', not '[self] $args'" - eval my create $args - } - - Object method unknown {m args} { - if {![self isnext]} { - error "[self]: unable to dispatch method '$m'" - } - } - - # "init" must exist on Object. per default it is empty. - Object method init args {} - - # provide a placeholder for the bootup process. The real definition - # is based on slots, which are not available at this point. - Object method objectparameter {} {;} - - # - # create class and object for nonpositional argument processing - Class create ::xotcl::ParameterType - foreach cmd [info command ::xotcl::cmd::ParameterType::*] { - ::xotcl::alias ::xotcl::ParameterType [namespace tail $cmd] $cmd - } - # register type boolean as checker for "switch" - ::xotcl::alias ::xotcl::ParameterType type=switch ::xotcl::cmd::ParameterType::type=boolean - # create an object for dispatching - ::xotcl::ParameterType create ::xotcl::parameterType - - ######################## - # Info definition - ######################## - Object create ::xotcl::objectInfo - Object create ::xotcl::classInfo - - foreach cmd [info command ::xotcl::cmd::ObjectInfo::*] { - ::xotcl::alias ::xotcl::objectInfo [namespace tail $cmd] $cmd - ::xotcl::alias ::xotcl::classInfo [namespace tail $cmd] $cmd - } - foreach cmd [info command ::xotcl::cmd::ClassInfo::*] { - ::xotcl::alias ::xotcl::classInfo [namespace tail $cmd] $cmd - } - unset cmd - ::xotcl::alias ::xotcl::objectInfo is ::xotcl::is - ::xotcl::alias ::xotcl::classInfo is ::xotcl::is - ::xotcl::alias ::xotcl::classInfo classparent ::xotcl::cmd::ObjectInfo::parent - ::xotcl::alias ::xotcl::classInfo classchildren ::xotcl::cmd::ObjectInfo::children - - Object instforward info -onerror ::xotcl::infoError ::xotcl::objectInfo %1 {%@2 %self} - Class instforward info -onerror ::xotcl::infoError ::xotcl::classInfo %1 {%@2 %self} - - # TODO: the following method is defined redundantly - proc ::xotcl::infoError msg { - #puts stderr "INFO ERROR: <$msg>\n$::errorInfo" - regsub -all " " $msg "" msg - regsub -all " " $msg "" msg - regsub {\"} $msg "\"info " msg - error $msg "" - } - objectInfo method info {obj} { - set methods [list] - foreach m [::info commands ::xotcl::objectInfo::*] { - set name [namespace tail $m] - if {$name eq "unknown"} continue - lappend methods $name - } - return "valid options are: [join [lsort $methods] {, }]" - } - objectInfo method unknown {method args} { - error "unknown info option \"$method\"; [.info info]" - } - - classInfo method info {cl} { - set methods [list] - foreach m [::info commands ::xotcl::classInfo::*] { - set name [namespace tail $m] - if {$name eq "unknown"} continue - lappend methods $name - } - return "valid options are: [join [lsort $methods] {, }]" - } - classInfo method unknown {method args} { - error "unknown info option \"$method\"; [.info info]" - } - - # - # Backward compatibility info subcommands; - # - # TODO: should go finally into a library. - # - # Obsolete methods - # - # already emulated: - # - # => info params .... replaces - # info args - # info nonposargs - # info default - # - # => info instparams .... replaces - # info instargs - # info instnonposargs - # info instdefault - # - # => maybe instead of "info params" and "info instparams" - # info params ?-per-object? - # - # => TODO: use "params" in serializer, and all other occurances - # - # TODO: not yet emulated: - # - # => info is (bzw. ::xotcl::is) replaces - # isobject - # isclass - # ismetaclass - # ismixin - # istype - # - # => method (should get pre- and postconditions via positional params) - # proc - # instproc - # - # TODO mark all absolete calls at least as deprecated in library - # - # TODO move unknown handler for Class into a library, make sure that - # regression test and library function use explicit "creates". - # - - proc ::xotcl::info_args {inst o method} { - set result [list] - foreach \ - argName [::xotcl::classInfo ${inst}params $o $method -varNames] \ - flag [::xotcl::classInfo ${inst}params $o $method] { - if {[string match -* $flag]} continue - lappend result $argName - } - #puts stderr "+++ get ${inst}args for $o $method => $result" - return $result - } - - proc ::xotcl::info_nonposargs {inst o method} { - set result [list] - foreach flag [::xotcl::classInfo ${inst}params $o $method] { - if {![string match -* $flag]} continue - lappend result $flag - } - #puts stderr "+++ get ${inst}nonposargs for $o $method => $result" - return $result - } - proc ::xotcl::info_default {inst o method arg varName} { - foreach \ - argName [::xotcl::classInfo ${inst}params $o $method -varNames] \ - flag [::xotcl::classInfo ${inst}params $o $method] { - if {$argName eq $arg} { - upvar 3 $varName default - if {[llength $flag] == 2} { - set default [lindex $flag 1] - #puts stderr "--- get ${inst}default for $o $method $arg => $default" - return 1 - } - #puts stderr "--- get ${inst}default for $o $method $arg fails" - set default "" - return 0 - } - } - error "procedure \"$method\" doesn't have an argument \"$varName\"" - } - - classInfo method instargs {o method} {::xotcl::info_args inst $o $method} - classInfo method args {o method} {::xotcl::info_args "" $o $method} - objectInfo method args {o method} {::xotcl::info_args "" $o $method} - - classInfo method instnonposargs {o method} {::xotcl::info_nonposargs inst $o $method} - classInfo method nonposargs {o method} {::xotcl::info_nonposargs "" $o $method} - objectInfo method nonposargs {o method} {::xotcl::info_nonposargs "" $o $method} - - classInfo method instdefault {o method arg var} {::xotcl::info_default inst $o $method $arg $var} - classInfo method default {o method arg var} {::xotcl::info_default "" $o $method $arg $var} - objectInfo method default {o method arg var} {::xotcl::info_default "" $o $method $arg $var} - - # emulation of isobject, ... - Object method isobject {{object:substdefault "[self]"}} {::xotcl::is $object object} - Object method isclass {{class:substdefault "[self]"}} {::xotcl::is $class class} - Object method ismetaclass {{class:substdefault "[self]"}} {::xotcl::is $class metaclass} - Object method ismixin {class} {::xotcl::is [self] mixin $class} - Object method istype {class} {::xotcl::is [self] type $class} - - # - Object method proc {name arglist body precondition:optional postcondition:optional} { - set cmd [list my method $name $arglist $body] - if {[info exists precondition]} {lappend cmd -precondition $precondition} - if {[info exists postcondition]} {lappend cmd -postcondition $postcondition} - eval $cmd - } - Class method proc {name arglist body precondition:optional postcondition:optional} { - set cmd [list my method -per-object $name $arglist $body] - if {[info exists precondition]} {lappend cmd -precondition $precondition} - if {[info exists postcondition]} {lappend cmd -postcondition $postcondition} - eval $cmd - } - Class method instproc {name arglist body precondition:optional postcondition:optional} { - set cmd [list my method $name $arglist $body] - if {[info exists precondition]} {lappend cmd -precondition $precondition} - if {[info exists postcondition]} {lappend cmd -postcondition $postcondition} - eval $cmd - } - - # documentation stub object -> just ignore per default. - # if xoDoc is loaded, documentation will be activated - Object create ::xotcl::@ - @ method unknown args {} - - proc myproc {args} {linsert $args 0 [::xotcl::self]} - proc myvar {var} {.requireNamespace; return [::xotcl::self]::$var} - - namespace export Object Class @ myproc myvar Attribute -} - ################## # Slot definitions ################## @@ -431,12 +182,6 @@ return $parameterdefinitions } -::xotcl::Object method objectparameter {} { - set parameterdefinitions [::xotcl::parametersFromSlots [self]] - lappend parameterdefinitions args - #puts stderr "*** parameter definition for [self]: $parameterdefinitions" - return $parameterdefinitions -} ::xotcl2::Object method objectparameter {} { set parameterdefinitions [::xotcl::parametersFromSlots [self]] if {[::xotcl::is [self] class]} { @@ -473,7 +218,8 @@ if {[llength $att]>1} {foreach {att default} $att break} if {[info exists default]} { # checking subclasses is not required during bootstrap - foreach i [$class info instances] { + # todo: do we really need $class twice? + foreach i [::xotcl::dispatch $class ::xotcl::cmd::ClassInfo::instances $class] { if {![$i exists $att]} { if {[string match {*[*]*} $default]} { #set default [$i eval subst $default] @@ -491,22 +237,6 @@ # -# TODO: -# - are createBootstrapAttributeSlots for ::xotcl::Class still needed? -# - Defaults for objectparameter seem more natural. -# - no definition yet for xotcl2::Class -# - -# We provide a default value for superclass (when no superclass is specified explicitely) -# for defining the top-level class of the object system, such that different -# object systems might co-exist. - -createBootstrapAttributeSlots ::xotcl::Class { - {__default_superclass ::xotcl::Object} - {__default_metaclass ::xotcl::Class} -} - -# # Define slots for slots # createBootstrapAttributeSlots ::xotcl::Slot { @@ -568,10 +298,9 @@ set forwarder [expr {${.per-object} ? "forward" : "instforward"}] if {${.domain} eq ""} { set .domain [::xotcl::self callingobject] - } else { - ${.domain} invalidateobjectparameter } if {${.domain} ne ""} { + ${.domain} invalidateobjectparameter ${.domain} $forwarder ${.name} -default [${.manager} defaultmethods] ${.manager} %1 %self %proc } } @@ -639,11 +368,10 @@ ###################### # system slots ###################### -# register the system slots on both, xotcl and xotcl2 -foreach os {::xotcl ::xotcl2} { +proc ::xotcl::register_system_slots {os} { ${os}::Object alloc ${os}::Class::slot ${os}::Object alloc ${os}::Object::slot - + ::xotcl::InfoSlot create ${os}::Class::slot::superclass -type relation ::xotcl::alias ${os}::Class::slot::superclass assign ::xotcl::relation ::xotcl::InfoSlot create ${os}::Object::slot::class -type relation @@ -659,18 +387,13 @@ -elementtype "" \ -type relation } +::xotcl::register_system_slots ::xotcl2 # +# Attribute slots # -# Attribute -# -# TODO: why does -superclass not work here? -# before, the subsequent ::xotcl::relation was not needed. - ::xotcl::MetaSlot invalidateobjectparameter - ::xotcl::MetaSlot create ::xotcl::Attribute -superclass ::xotcl::Slot -::xotcl::relation ::xotcl::Attribute superclass ::xotcl::Slot createBootstrapAttributeSlots ::xotcl::Attribute { {value_check once} @@ -760,7 +483,7 @@ } } -# mixin class for decativating all checks +# mixin class for decativating all value checks in slots ::xotcl2::Class create ::xotcl::Slot::Nocheck { .method check_single_value args {;} .method check_multiple_values args {;} @@ -834,28 +557,6 @@ ::xotcl2::Class instforward slots %self contains \ -object {%::xotcl::dispatch [::xotcl::self] -objscope ::subst [::xotcl::self]::slot} -# this will go into the optional xotcl block -::xotcl::Object method contains { - {-withnew:boolean true} - -object - {-class ::xotcl2::Object} - cmds - } { - if {![info exists object]} {set object [::xotcl::self]} - if {![::xotcl::is $object object]} {$class create $object} - $object requireNamespace - if {$withnew} { - set m [::xotcl::ScopedNew new \ - -inobject $object -withclass $class -volatile] - ::xotcl2::Class instmixin add $m end - namespace eval $object $cmds - ::xotcl2::Class instmixin delete $m - } else { - namespace eval $object $cmds - } -} -::xotcl::Class instforward slots %self contains \ - -object {%::xotcl::dispatch [::xotcl::self] -objscope ::subst [::xotcl::self]::slot} # # define parameter for backward compatibility and convenience # @@ -933,79 +634,18 @@ ::xotcl::setinstvar [::xotcl::self]::slot __parameter $arglist } -# -# utilities -# -::xotcl::Object method self {} {::xotcl::self} -::xotcl::Object method defaultmethod {} { - return [::xotcl::self] -} -# support for XOTcl specific convenience routines -::xotcl::Object method hasclass cl { - if {[::xotcl::is [self] mixin $cl]} {return 1} - ::xotcl::is [self] type $cl -} -::xotcl::Class method allinstances {} { - # TODO: mark it deprecated - return [.info instances -closure] -} - -# reuse definitions from xotcl in xotcl2 -# TODO: can this be done with interp aliases? -::xotcl::alias ::xotcl::Class parameter ::xotcl::classes::xotcl2::Class::parameter -#::xotcl::alias ::xotcl::Object contains ::xotcl::classes::xotcl2::Object::contains -::xotcl::alias ::xotcl2::Object defaultmethod ::xotcl::classes::xotcl::Object::defaultmethod - -#interp alias {} ::xotcl::classes::xotcl::Class::parameter {} ::xotcl::classes::xotcl2::Class::parameter -#interp alias {} ::xotcl::classes::xotcl::Object::defaultmethod {} ::xotcl::classes::xotcl2::Object::defaultmethod - # -# TODO remainder should move from ::xotcl::Object -> xotcl2::* -# - -# Exit Handler -::xotcl::Object method -per-object unsetExitHandler {} { - ::xotcl::Object method -per-object __exitHandler {} { - # clients should append exit handlers to this proc body - ; - } -} -# pre-defined as empty method -::xotcl::Object unsetExitHandler -::xotcl::Object method -per-object setExitHandler {newbody} { - ::xotcl::Object method -per-object __exitHandler {} $newbody -} -::xotcl::Object method -per-object getExitHandler {} { - ::xotcl::Object info body __exitHandler -} -# provide a global handler to avoid a proc on the global object. -proc ::xotcl::__exitHandler {} { - ::xotcl::Object __exitHandler -} -::xotcl::Object method abstract {methtype methname arglist} { - if {$methtype ne "proc" && $methtype ne "instproc" && $methtype ne "method"} { - error "invalid method type '$methtype', \ - must be either 'proc', 'instproc' or 'method'." - } - .$methtype $methname $arglist " - if {!\[::xotcl::self isnextcall\]} { - error \"Abstract method $methname $arglist called\" - } else {::xotcl::next} - " -} - -# # copy/move implementation # -::xotcl2::Class create ::xotcl::Object::CopyHandler -parameter { +::xotcl2::Class create ::xotcl::CopyHandler -parameter { {targetList ""} {dest ""} objLength } # targets are all namspaces and objs part-of the copied obj -::xotcl::Object::CopyHandler method makeTargetList t { +::xotcl::CopyHandler method makeTargetList t { lappend .targetList $t # if it is an object without namespace, it is a leaf if {[::xotcl::is $t object]} { @@ -1032,18 +672,18 @@ } } -::xotcl::Object::CopyHandler method copyNSVarsAndCmds {orig dest} { +::xotcl::CopyHandler method copyNSVarsAndCmds {orig dest} { ::xotcl::namespace_copyvars $orig $dest ::xotcl::namespace_copycmds $orig $dest } # construct destination obj name from old qualified ns name -::xotcl::Object::CopyHandler method getDest origin { +::xotcl::CopyHandler method getDest origin { set tail [string range $origin [set .objLength] end] return ::[string trimleft [set .dest]$tail :] } -::xotcl::Object::CopyHandler method copyTargets {} { +::xotcl::CopyHandler method copyTargets {} { #puts stderr "COPY will copy targetList = [set .targetList]" foreach origin [set .targetList] { set dest [.getDest $origin] @@ -1111,17 +751,387 @@ } } -::xotcl::Object::CopyHandler method copy {obj dest} { +::xotcl::CopyHandler method copy {obj dest} { #puts stderr "[::xotcl::self] copy <$obj> <$dest>" set .objLength [string length $obj] set .dest $dest .makeTargetList $obj .copyTargets } + + +####################################################################### +namespace eval ::xotcl { + # + # Perform the basic setup of XOTcl 1.x. First, let us allocate the + # basic classes of XOTcl. This call creates the classes + # ::xotcl::Object and ::xotcl::Class and defines these as root class + # of the object system and as root meta class. + # + ::xotcl::createobjectsystem ::xotcl::Object ::xotcl::Class + + # provide the standard command set for ::xotcl::Object + foreach cmd [info command ::xotcl::cmd::Object::*] { + ::xotcl::alias Object [namespace tail $cmd] $cmd + } + + # provide some Tcl-commands as methods for ::xotcl::Object + foreach cmd {array append eval incr lappend set subst unset trace} { + ::xotcl::alias Object $cmd -objscope ::$cmd + } + + # provide the standard command set for ::xotcl::Class + foreach cmd [info command ::xotcl::cmd::Class::*] { + ::xotcl::alias Class [namespace tail $cmd] $cmd + } + unset cmd + + # protect some methods against redefinition + ::xotcl::methodproperty Object destroy static true + ::xotcl::methodproperty Class alloc static true + ::xotcl::methodproperty Class dealloc static true + ::xotcl::methodproperty Class create static true + + Class method unknown {args} { + #puts stderr "use '[self] create $args', not '[self] $args'" + eval my create $args + } + + Object method unknown {m args} { + if {![self isnext]} { + error "[self]: unable to dispatch method '$m'" + } + } + + # "init" must exist on Object. per default it is empty. + Object method init args {} + + # provide a placeholder for the bootup process. The real definition + # is based on slots, which are not available at this point. + Object method objectparameter {} {;} + + # + # create class and object for nonpositional argument processing + Class create ::xotcl::ParameterType + foreach cmd [info command ::xotcl::cmd::ParameterType::*] { + ::xotcl::alias ::xotcl::ParameterType [namespace tail $cmd] $cmd + } + # register type boolean as checker for "switch" + ::xotcl::alias ::xotcl::ParameterType type=switch ::xotcl::cmd::ParameterType::type=boolean + # create an object for dispatching + ::xotcl::ParameterType create ::xotcl::parameterType + + # + # object-parameter definition, backwards compatible + # + ::xotcl::Object method objectparameter {} { + set parameterdefinitions [::xotcl::parametersFromSlots [self]] + lappend parameterdefinitions args + #puts stderr "*** parameter definition for [self]: $parameterdefinitions" + return $parameterdefinitions + } + + # + # TODO: + # - are createBootstrapAttributeSlots for ::xotcl::Class still needed? + # - Defaults for objectparameter seem more natural. + # - no definition yet for xotcl2::Class + # + + # We provide a default value for superclass (when no superclass is specified explicitely) + # for defining the top-level class of the object system, such that different + # object systems might co-exist. + + createBootstrapAttributeSlots ::xotcl::Class { + {__default_superclass ::xotcl::Object} + {__default_metaclass ::xotcl::Class} + } + + ::xotcl::register_system_slots ::xotcl + + ######################## + # Info definition + ######################## + Object create ::xotcl::objectInfo + Object create ::xotcl::classInfo + + foreach cmd [::info command ::xotcl::cmd::ObjectInfo::*] { + ::xotcl::alias ::xotcl::objectInfo [namespace tail $cmd] $cmd + ::xotcl::alias ::xotcl::classInfo [namespace tail $cmd] $cmd + } + foreach cmd [::info command ::xotcl::cmd::ClassInfo::*] { + ::xotcl::alias ::xotcl::classInfo [namespace tail $cmd] $cmd + } + unset cmd + ::xotcl::alias ::xotcl::objectInfo is ::xotcl::is + ::xotcl::alias ::xotcl::classInfo is ::xotcl::is + ::xotcl::alias ::xotcl::classInfo classparent ::xotcl::cmd::ObjectInfo::parent + ::xotcl::alias ::xotcl::classInfo classchildren ::xotcl::cmd::ObjectInfo::children + + Object instforward info -onerror ::xotcl::infoError ::xotcl::objectInfo %1 {%@2 %self} + Class instforward info -onerror ::xotcl::infoError ::xotcl::classInfo %1 {%@2 %self} + + # TODO: the following method is defined redundantly + proc ::xotcl::infoError msg { + #puts stderr "INFO ERROR: <$msg>\n$::errorInfo" + regsub -all " " $msg "" msg + regsub -all " " $msg "" msg + regsub {\"} $msg "\"info " msg + error $msg "" + } + objectInfo method info {obj} { + set methods [list] + foreach m [::info commands ::xotcl::objectInfo::*] { + set name [namespace tail $m] + if {$name eq "unknown"} continue + lappend methods $name + } + return "valid options are: [join [lsort $methods] {, }]" + } + objectInfo method unknown {method args} { + error "[::xotcl::self] unknown info option \"$method\"; [.info info]" + } + + classInfo method info {cl} { + set methods [list] + foreach m [::info commands ::xotcl::classInfo::*] { + set name [namespace tail $m] + if {$name eq "unknown"} continue + lappend methods $name + } + return "valid options are: [join [lsort $methods] {, }]" + } + classInfo method unknown {method args} { + error "[::xotcl::self] unknown info option \"$method\"; [.info info]" + } + + # + # Backward compatibility info subcommands; + # + # TODO: should go finally into a library. + # + # Obsolete methods + # + # already emulated: + # + # => info params .... replaces + # info args + # info nonposargs + # info default + # + # => info instparams .... replaces + # info instargs + # info instnonposargs + # info instdefault + # + # => maybe instead of "info params" and "info instparams" + # info params ?-per-object? + # + # => TODO: use "params" in serializer, and all other occurances + # + # TODO: not yet emulated: + # + # => info is (bzw. ::xotcl::is) replaces + # isobject + # isclass + # ismetaclass + # ismixin + # istype + # + # => method (should get pre- and postconditions via positional params) + # proc + # instproc + # + # TODO mark all absolete calls at least as deprecated in library + # + # TODO move unknown handler for Class into a library, make sure that + # regression test and library function use explicit "creates". + # + + proc ::xotcl::info_args {inst o method} { + set result [list] + foreach \ + argName [::xotcl::classInfo ${inst}params $o $method -varNames] \ + flag [::xotcl::classInfo ${inst}params $o $method] { + if {[string match -* $flag]} continue + lappend result $argName + } + #puts stderr "+++ get ${inst}args for $o $method => $result" + return $result + } + + proc ::xotcl::info_nonposargs {inst o method} { + set result [list] + foreach flag [::xotcl::classInfo ${inst}params $o $method] { + if {![string match -* $flag]} continue + lappend result $flag + } + #puts stderr "+++ get ${inst}nonposargs for $o $method => $result" + return $result + } + proc ::xotcl::info_default {inst o method arg varName} { + foreach \ + argName [::xotcl::classInfo ${inst}params $o $method -varNames] \ + flag [::xotcl::classInfo ${inst}params $o $method] { + if {$argName eq $arg} { + upvar 3 $varName default + if {[llength $flag] == 2} { + set default [lindex $flag 1] + #puts stderr "--- get ${inst}default for $o $method $arg => $default" + return 1 + } + #puts stderr "--- get ${inst}default for $o $method $arg fails" + set default "" + return 0 + } + } + error "procedure \"$method\" doesn't have an argument \"$varName\"" + } + + classInfo method instargs {o method} {::xotcl::info_args inst $o $method} + classInfo method args {o method} {::xotcl::info_args "" $o $method} + objectInfo method args {o method} {::xotcl::info_args "" $o $method} + + classInfo method instnonposargs {o method} {::xotcl::info_nonposargs inst $o $method} + classInfo method nonposargs {o method} {::xotcl::info_nonposargs "" $o $method} + objectInfo method nonposargs {o method} {::xotcl::info_nonposargs "" $o $method} + + classInfo method instdefault {o method arg var} {::xotcl::info_default inst $o $method $arg $var} + classInfo method default {o method arg var} {::xotcl::info_default "" $o $method $arg $var} + objectInfo method default {o method arg var} {::xotcl::info_default "" $o $method $arg $var} + + # emulation of isobject, ... + Object method isobject {{object:substdefault "[self]"}} {::xotcl::is $object object} + Object method isclass {{class:substdefault "[self]"}} {::xotcl::is $class class} + Object method ismetaclass {{class:substdefault "[self]"}} {::xotcl::is $class metaclass} + Object method ismixin {class} {::xotcl::is [self] mixin $class} + Object method istype {class} {::xotcl::is [self] type $class} + + + # todo: it should be possible to use an alias for the xotcl2 implementation + ::xotcl::Object method contains { + {-withnew:boolean true} + -object + {-class ::xotcl2::Object} + cmds + } { + if {![info exists object]} {set object [::xotcl::self]} + if {![::xotcl::is $object object]} {$class create $object} + $object requireNamespace + if {$withnew} { + set m [::xotcl::ScopedNew new \ + -inobject $object -withclass $class -volatile] + ::xotcl2::Class instmixin add $m end + namespace eval $object $cmds + ::xotcl2::Class instmixin delete $m + } else { + namespace eval $object $cmds + } + } + ::xotcl::Class instforward slots %self contains \ + -object {%::xotcl::dispatch [::xotcl::self] -objscope ::subst [::xotcl::self]::slot} + + # + Object method proc {name arglist body precondition:optional postcondition:optional} { + set cmd [list my method $name $arglist $body] + if {[info exists precondition]} {lappend cmd -precondition $precondition} + if {[info exists postcondition]} {lappend cmd -postcondition $postcondition} + eval $cmd + } + Class method proc {name arglist body precondition:optional postcondition:optional} { + set cmd [list my method -per-object $name $arglist $body] + if {[info exists precondition]} {lappend cmd -precondition $precondition} + if {[info exists postcondition]} {lappend cmd -postcondition $postcondition} + eval $cmd + } + Class method instproc {name arglist body precondition:optional postcondition:optional} { + set cmd [list my method $name $arglist $body] + if {[info exists precondition]} {lappend cmd -precondition $precondition} + if {[info exists postcondition]} {lappend cmd -postcondition $postcondition} + eval $cmd + } + + # documentation stub object -> just ignore per default. + # if xoDoc is loaded, documentation will be activated + Object create ::xotcl::@ + @ method unknown args {} + + proc myproc {args} {linsert $args 0 [::xotcl::self]} + proc myvar {var} {.requireNamespace; return [::xotcl::self]::$var} + + namespace export Object Class @ myproc myvar Attribute +} +####################################################################### + + + +# +# utilities +# +::xotcl::Object method self {} {::xotcl::self} +::xotcl2::Object method defaultmethod {} { + return [::xotcl::self] +} + +# support for XOTcl specific convenience routines +::xotcl::Object method hasclass cl { + if {[::xotcl::is [self] mixin $cl]} {return 1} + ::xotcl::is [self] type $cl +} +::xotcl::Class method allinstances {} { + # TODO: mark it deprecated + return [.info instances -closure] +} + +# reuse definitions from xotcl in xotcl2 +# TODO: can this be done with interp aliases? +::xotcl::alias ::xotcl::Class parameter ::xotcl::classes::xotcl2::Class::parameter +#::xotcl::alias ::xotcl::Object contains ::xotcl::classes::xotcl2::Object::contains +::xotcl::alias ::xotcl::Object defaultmethod ::xotcl::classes::xotcl2::Object::defaultmethod + +#interp alias {} ::xotcl::classes::xotcl::Class::parameter {} ::xotcl::classes::xotcl2::Class::parameter +#interp alias {} ::xotcl::classes::xotcl::Object::defaultmethod {} ::xotcl::classes::xotcl2::Object::defaultmethod + +# +# TODO remainder should move from ::xotcl::Object -> xotcl2::* +# + +# Exit Handler +::xotcl::Object method -per-object unsetExitHandler {} { + ::xotcl::Object method -per-object __exitHandler {} { + # clients should append exit handlers to this proc body + ; + } +} +# pre-defined as empty method +::xotcl::Object unsetExitHandler +::xotcl::Object method -per-object setExitHandler {newbody} { + ::xotcl::Object method -per-object __exitHandler {} $newbody +} +::xotcl::Object method -per-object getExitHandler {} { + ::xotcl::Object info body __exitHandler +} +# provide a global handler to avoid a proc on the global object. +proc ::xotcl::__exitHandler {} { + ::xotcl::Object __exitHandler +} +::xotcl::Object method abstract {methtype methname arglist} { + if {$methtype ne "proc" && $methtype ne "instproc" && $methtype ne "method"} { + error "invalid method type '$methtype', \ + must be either 'proc', 'instproc' or 'method'." + } + .$methtype $methname $arglist " + if {!\[::xotcl::self isnextcall\]} { + error \"Abstract method $methname $arglist called\" + } else {::xotcl::next} + " +} + + ::xotcl::Object method copy newName { if {[string compare [string trimleft $newName :] [string trimleft [::xotcl::self] :]]} { - [[::xotcl::self class]::CopyHandler new -volatile] copy [::xotcl::self] $newName + [::xotcl::CopyHandler new -volatile] copy [::xotcl::self] $newName } }