Index: TODO =================================================================== diff -u -r183cd0a9a3d2a37133ac51bb86952e1b522dbf6f -r6a55e4e48e5431b7b76916a8dbfb550b4cdc6edb --- TODO (.../TODO) (revision 183cd0a9a3d2a37133ac51bb86952e1b522dbf6f) +++ TODO (.../TODO) (revision 6a55e4e48e5431b7b76916a8dbfb550b4cdc6edb) @@ -5735,6 +5735,7 @@ - hardened serializer (use e.g. "::namespace" instead of "namespace" when there is a potential conflict with a method named "namespace", prefer nsf::directdispatch, etc.) +- extended regression test ======================================================================== Index: library/serialize/serializer.tcl =================================================================== diff -u -r63fb7c118c69ff1a2753b65d222f59151b6a6906 -r6a55e4e48e5431b7b76916a8dbfb550b4cdc6edb --- library/serialize/serializer.tcl (.../serializer.tcl) (revision 63fb7c118c69ff1a2753b65d222f59151b6a6906) +++ library/serialize/serializer.tcl (.../serializer.tcl) (revision 6a55e4e48e5431b7b76916a8dbfb550b4cdc6edb) @@ -298,9 +298,9 @@ } elseif {$ns ne [namespace origin $ns] } { append pre_cmds "namespace eval $ns {}\n" } - set exp [namespace eval $ns {namespace export}] + set exp [namespace eval $ns {::namespace export}] if {$exp ne ""} { - append exports "namespace eval $ns {namespace export $exp}" \n + append exports "namespace eval $ns {::namespace export $exp}" \n } } return $pre_cmds$result${:post_cmds}$exports @@ -322,7 +322,7 @@ :public object method allChildren o { # return o and all its children fully qualified set set [::nsf::directdispatch $o -frame method ::nsf::current] - foreach c [$o info children] { + foreach c [::nsf::directdispatch $o ::nsf::methods::object::info::children] { lappend set {*}[:allChildren $c] } return $set @@ -618,6 +618,27 @@ return [list $cmd ${:targetName} $relation $v]\n } + :method extraMethodProperties {o perObject m} { + # + # Perserve special method properties like "debug" and + # "deprecated" for arbitrary kind of methods via + # "nsf::method::property" calls. + # + set extra "" + if {[::nsf::method::property $o {*}$perObject $m exists]} { + if {[::nsf::method::property $o {*}$perObject $m debug]} { + append extra "\n::nsf::method::property [list ${:targetName}] $perObject $m debug true" + } + if {[::nsf::method::property $o {*}$perObject $m deprecated]} { + append extra "\n::nsf::method::property [list ${:targetName}] $perObject $m deprecated true" + } + } else { + nsf::log warning "method <$o> <$perObject> <$m> does not exist" + #catch {nsf::__db_show_stack} + } + return $extra + } + :method serializeExportedMethods {s} { set r "" foreach k [array names :exportMethods] { @@ -731,8 +752,8 @@ } :method Object-needsNothing {x s} { - set p [$x info parent] - set cl [$x info class] + set p [::nsf::directdispatch $x ::nsf::methods::object::info::parent] + set cl [::nsf::directdispatch $x ::nsf::methods::object::info::class] if {$p ne "::" && [$s needsOneOf $p]} {return 0} if {[$s needsOneOf $cl]} {return 0} if {[$s needsOneOf [$cl ::nsf::methods::class::info::slotobjects -closure -source application]]} {return 0} @@ -777,11 +798,13 @@ expr {[$object info method type $name] ne ""} } - :public object method serializeExportedMethod {object kind name s} { + :public object method -debug serializeExportedMethod {object kind name s} { # todo: object modifier is missing set :targetName $object - if {$kind eq "inst"} { + if {$kind eq "method"} { set modifier "" + } elseif {$kind eq "nsfproc"} { + return [::nsf::cmd::info definition $name] } else { set modifier "object" } @@ -790,6 +813,7 @@ :object method method-serialize {o m modifier s} { if {![::nsf::is class $o]} {set modifier "object"} + set perObject [expr {$modifier eq "object" ? "-per-object" : ""}] set methodType [$o info {*}$modifier method type $m] #puts stderr "methodType (*o $modifier $m) = $methodType" set def [$o info {*}$modifier method definition $m] @@ -810,7 +834,6 @@ # (but not necessarily only there). # if {${:targetName} ne $o} { - set perObject [expr {$modifier eq "object" ? "-per-object" : ""}] set forwardTarget [nsf::method::forward::property $o {*}$perObject $m target] set mappedForwardTarget [$s getTargetName $forwardTarget] if {$forwardTarget ne $mappedForwardTarget} { @@ -824,7 +847,7 @@ if {${:targetName} ne $o} { set def [lreplace $def 0 0 ${:targetName}] } - return $def + return $def[:extraMethodProperties $o $perObject $m] } ############################### @@ -971,8 +994,10 @@ :object method method-serialize {o m prefix s} { if {![nsf::is class $o] || $prefix eq ""} { set scope object + set perObject "-per-object" } else { set scope class + set perObject "" } set arglist [$o ::nsf::methods::${scope}::info::method parameter $m] @@ -990,7 +1015,7 @@ foreach p {pre post} { if {[$o info ${prefix}$p $m] ne ""} {lappend r [$o info ${prefix}$p $m]} } - return $r + return $r[:extraMethodProperties $o $perObject $m] } ############################### @@ -1061,7 +1086,7 @@ } namespace export Serializer - namespace eval :: "namespace import -force [namespace current]::*" + namespace eval :: "::namespace import -force [namespace current]::*" } # Index: library/xotcl/tests/slottest.xotcl =================================================================== diff -u -rd9344280c05990c0254aa652a08a09da3e5822b1 -r6a55e4e48e5431b7b76916a8dbfb550b4cdc6edb --- library/xotcl/tests/slottest.xotcl (.../slottest.xotcl) (revision d9344280c05990c0254aa652a08a09da3e5822b1) +++ library/xotcl/tests/slottest.xotcl (.../slottest.xotcl) (revision 6a55e4e48e5431b7b76916a8dbfb550b4cdc6edb) @@ -8,15 +8,15 @@ # what's new: # - slots instances are manager objects for slot values # - generalization of slots to have different kind of domains and managers -# - slots for objects and classes (slot parameter 'per-object' true|false, +# - slots for objects and classes (slot parameter 'per-object' true|false, # when to used on a class object) # - works for mixins/filters/class/superclass (e.g ... superclass add ::M) -# - defaultcmd and valuecmd +# - defaultcmd and valuecmd # defaultcmd: is executed when the instance variable is read the first time # valuecmd: is executed whenever the instance variable is read # (implemented via trace; alternate approach for similar behavior # is to define per-object procs for get/assign, see e.g. slots for -# class and superclass; slots require methods to be invoked, +# class and superclass; slots require methods to be invoked, # not var references; # otoh, trace are somewhat more fragile and harder to debug) # default, defaultcmd and valuecmd are to be used mutually exclusively @@ -33,8 +33,8 @@ proc T2 {var sub op} {c1 set $var t2} Class C -slots { - Attribute create x -defaultcmd {set x 1} - Attribute create y -defaultcmd {incr ::hu} + Attribute create x -defaultcmd {set x 1} + Attribute create y -defaultcmd {incr ::hu} Attribute create z -defaultcmd {my trace add variable z read T1} } @@ -48,7 +48,7 @@ ? {set ::hu} 1 proc ?? {cmd expected {msg ""}} { - #puts "??? $cmd" + #puts "??? $cmd" set r [uplevel $cmd] if {$msg eq ""} {set msg $cmd} if {$r ne $expected} { @@ -60,7 +60,7 @@ } Class D -slots { - Attribute create x -defaultcmd {set x 2} + Attribute create x -defaultcmd {set x 2} Attribute create z -defaultcmd {my trace add variable z read T2} ?? self ::D ?? {namespace current} ::D::slot @@ -73,7 +73,7 @@ ? {set ::hu} 2 ####################################################### -# +# # a small helper Object instproc slots cmds { if {![my isobject [self]::slot]} {Object create [self]::slot} @@ -101,12 +101,12 @@ ? {O mixin} ::M ? {O mixin ""} "" -# with slots like class etc. we have to option to +# with slots like class etc. we have to option to # a) rename the original command like in the following # b) provide a no-op value, such that we define only meta-data in the slot # c) define a low-level tcl command like setrelation (or extend it) to handle the setter -# "class" is not multivalued, therefore we should not add (or remove) add/delete +# "class" is not multivalued, therefore we should not add (or remove) add/delete # from the set of subcommands... ? {::nx::RelationSlot info class} "::nx::MetaSlot" O o1 @@ -153,7 +153,7 @@ ? {info exists default0} 1 ? {::Test info default m0 x default1} 0 - + unset -nocomplain default0 default1 ? {::Test info instdefault m1 y default0} 1 @@ -174,7 +174,7 @@ ? {C info heritage} "::xotcl::Object" ? {D info heritage} "::C ::xotcl::Object" - + # xotcl info heritage should not see the mixins C instmixin [::xotcl::Class create M] ? {C info superclass -closure} "::xotcl::Object" @@ -219,7 +219,6 @@ p1 age 123 ? {p1 age} 123 - Object o1 o1 set i 0 ::nsf::method::alias o1 Incr -frame object ::incr @@ -317,11 +316,11 @@ ? {c1 b} 10 ? {c1 c} "Hello World" -##### is short form of +##### is short form of Class C2 -slots { - Attribute create a + Attribute create a Attribute create b -default 10 Attribute create c -default "Hello World" } @@ -338,7 +337,7 @@ #::nx::VariableSlot mixin add ::nx::VariableSlot::Optimizer Class C3 -slots { - Attribute create a + Attribute create a Attribute create b -default 10 Attribute create c -default "Hello World" } @@ -425,10 +424,10 @@ ? {p1 projects} {} Class Project -slots { - Attribute create name + Attribute create name Attribute create description } - + Project project1 -name XOTcl -description "A highly flexible OO scripting language" p1 projects add ::project1 @@ -437,7 +436,7 @@ #? {p1 projects} "some-other-value ::project1" ::nx::ObjectParameterSlot method check { - {-keep_old_value:boolean true} + {-keep_old_value:boolean true} value predicate type obj var } { puts "+++ checking $value with $predicate ==> [expr $predicate]" @@ -600,7 +599,7 @@ # # 1) old-style Attribute creation # - + Class Window -slots { Attribute scrollbar; # old style Attribute create title; # new style @@ -649,7 +648,7 @@ Attribute foo -default 1 -proc value=set {domain var value} { if {$value < 0 || $value > 99} { error "$value is not in the range of 0 .. 99" - } + } $domain set $var $value } } @@ -659,12 +658,50 @@ ? {aa1 foo} 10 ? {catch {aa1 foo -1}} 1 + +nx::test case nx-serialize-debug-deprecated { + ::xotcl::Object create o + o proc ofoo {} {return 1} + o proc obar {} {return 1} + + ? {::nsf::method::property o ofoo deprecated} 0 + ? {::nsf::method::property o ofoo debug} 0 + ? {::nsf::method::property o obar deprecated} 0 + ? {::nsf::method::property o obar debug} 0 + + ::nsf::method::property o ofoo deprecated 1 + ::nsf::method::property o obar debug 1 + + ? {::nsf::method::property o ofoo deprecated} 1 + ? {::nsf::method::property o ofoo debug} 0 + ? {::nsf::method::property o obar deprecated} 0 + ? {::nsf::method::property o obar debug} 1 + + set script [o serialize] + o destroy + ? {::nsf::object::exists ::o} 0 + + eval $script + + ? {::nsf::method::property o ofoo deprecated} 1 + ? {::nsf::method::property o ofoo debug} 0 + ? {::nsf::method::property o obar deprecated} 0 + ? {::nsf::method::property o obar debug} 1 +} + + + exit - #puts [Person array get __defaults] - #puts [Person serialize] - puts [Serializer all] - eval [Serializer all] +###################################################################### +# +# Obsolete content +# +###################################################################### +#puts [Person array get __defaults] +#puts [Person serialize] +puts [Serializer all] +eval [Serializer all] ? {p2 salary} 1009 ? {catch {p2 append salary b}} 1 @@ -741,8 +778,8 @@ Slot create Project::fullbudget \ -defaultcmd {$obj set __x 100} \ -valuechangedcmd { - puts "budget is now [$obj set fullbudget]" - $obj set __x [$obj set fullbudget] + puts "budget is now [$obj set fullbudget]" + $obj set __x [$obj set fullbudget] } Slot create Project::currentbudget -valuecmd {$obj incr __x -1} Index: tests/serialize.test =================================================================== diff -u -rf31c1a01c6a389f693b8db0f2204cbb46180fef1 -r6a55e4e48e5431b7b76916a8dbfb550b4cdc6edb --- tests/serialize.test (.../serialize.test) (revision f31c1a01c6a389f693b8db0f2204cbb46180fef1) +++ tests/serialize.test (.../serialize.test) (revision 6a55e4e48e5431b7b76916a8dbfb550b4cdc6edb) @@ -263,6 +263,69 @@ } # +# Check handling of method properties "debug" and "deprecated" +# in serializer +# +nx::test case nx-serialize-debug-deprecated { + + # + # Check on object o + # + nx::Object create o { + :public object method -deprecated ofoo {} {return 1} + :public object method -debug obar {} {return 1} + :public object alias -deprecated -debug obaz ::nsf::is + } + ? {::nsf::method::property o ofoo deprecated} 1 + ? {::nsf::method::property o ofoo debug} 0 + ? {::nsf::method::property o obar deprecated} 0 + ? {::nsf::method::property o obar debug} 1 + ? {::nsf::method::property o obaz deprecated} 1 + ? {::nsf::method::property o obaz debug} 1 + + + set script [o serialize] + o destroy + ? {::nsf::object::exists ::o} 0 + + eval $script + + ? {::nsf::method::property o ofoo deprecated} 1 + ? {::nsf::method::property o ofoo debug} 0 + ? {::nsf::method::property o obar deprecated} 0 + ? {::nsf::method::property o obar debug} 1 + ? {::nsf::method::property o obaz deprecated} 1 + ? {::nsf::method::property o obaz debug} 1 + # + # Now the same for a class + # + nx::Class create C { + :public method -deprecated foo {} {return 1} + :public method -debug bar {} {return 1} + :public alias -deprecated -debug baz ::nsf::is + } + + ? {::nsf::method::property C foo deprecated} 1 + ? {::nsf::method::property C foo debug} 0 + ? {::nsf::method::property C bar deprecated} 0 + ? {::nsf::method::property C bar debug} 1 + ? {::nsf::method::property C baz deprecated} 1 + ? {::nsf::method::property C baz debug} 1 + + set script [C serialize] + C destroy + ? {::nsf::object::exists ::C} 0 + + eval $script + ? {::nsf::method::property C foo deprecated} 1 + ? {::nsf::method::property C foo debug} 0 + ? {::nsf::method::property C bar deprecated} 0 + ? {::nsf::method::property C bar debug} 1 + ? {::nsf::method::property C baz deprecated} 1 + ? {::nsf::method::property C baz debug} 1 +} + +# # Local variables: # mode: tcl # tcl-indent-level: 2