Index: TODO =================================================================== diff -u -r77f50f6c6304355d638d5bf6f172d404940447de -ra866226c4ca39c65f5f98539c140326c617da884 --- TODO (.../TODO) (revision 77f50f6c6304355d638d5bf6f172d404940447de) +++ TODO (.../TODO) (revision a866226c4ca39c65f5f98539c140326c617da884) @@ -4258,19 +4258,54 @@ the smae way from "configure" and "cget" - extended regression test +nx.tcl: +- property has now a boolean non-positional argument "-config" + /obj|cls/ property ?-accessor value? ?-config boolean? ?-incremental? ?-class value? spec ?initblock? + in symmetry with "-accessor" (parameter option "noconfig" is still needed + to flag nsf for variables that should be initialized, which are + not configurable +- "/obj|cls/ info slot definitions" returns a full command + (containing flags and property|variable) +- extended regression test + ======================================================================== TODO: -- "/obj|cls/ info slot definition" should return a full command - (containing flags and property|variable) +- flatten out interface asymmetry between methods and properties + + methods: + query defined: "/obj|cls/ info methods ?pattern?" -> names + obtain definition: "/obj|cls/ info method definition /name|handle/" -> single definiton + query callable: "/obj|cls/ info lookup method /name/" -> handle (where is the method defined) + query callable: "/obj|cls/ info lookup methods ?pattern?" -> names (what methods can be called) + + properties|variables + query defined: "/obj|cls/ info slot names ?pattern?" -> names + obtain definition: "/obj|cls/ info slot definitions ?pattern?" -> list of definitions + query callable: "/obj|cls/ info lookup slots -source .. ?pattern?" -> slot objects (where are parameters defined) + + + more detail queries for "info method" and "info slot" + + alternative: + - drop term "slot" from the public vocabulary, use property instead (also for variable cases) + - properties|variables: + query defined: "/obj|cls/ info properties ?pattern?" -> names + obtain definition: "/obj|cls/ info property definition /name|slotobj/"-> single definiton + query callable: "/obj|cls/ info lookup property /name/" -> slotobj + query callable: "/obj|cls/ info lookup properties ?pattern?" -> names (what properties are available) + we could certainly stick with slot/slots. + + pro: same logic + contra: needs often 2 steps: find the handle|slotobj, get the detail info from there. + + +- maybe rename nonpos arg "-config" of property/variable + to "-configurable"? (pro: more clearly, contra: longer) - regression tests for "/obj/ info lookup parameter ...." - handling of "required" in reconfigure (see parameter-object-mixin-dependency in parameters.test) - handling of recreate (see regression test for class-level properties) - maybe "::nsf::object::property /obj/ volatile 0|1" to alter volatile state. -- check noconfig -- "/obj/ configure" returns values which can't be read via "/obj/ cget" - (but altered properly via "configure"). - Property reform part 3: change defaultPropertyAccessor or nx to none - update documentation with property reform Index: library/nx/nx.tcl =================================================================== diff -u -r3b5d2f4e0bc018420ebea39e54ad3212ade2a5bd -ra866226c4ca39c65f5f98539c140326c617da884 --- library/nx/nx.tcl (.../nx.tcl) (revision 3b5d2f4e0bc018420ebea39e54ad3212ade2a5bd) +++ library/nx/nx.tcl (.../nx.tcl) (revision a866226c4ca39c65f5f98539c140326c617da884) @@ -1030,9 +1030,10 @@ } else { #puts stderr "*** Class for '$target $name' is $class // [$class info heritage]" } - - #puts stderr "*** [list $class create [::nx::slotObj -container $container $target $slotname] {*}$opts $initblock]" - set r [$class create [::nx::slotObj -container $container $target $slotname] {*}$opts $initblock] + + set slotObj [::nx::slotObj -container $container $target $slotname] + #puts stderr "*** [list $class create $slotObj] {*}$opts $initblock]" + set r [$class create $slotObj {*}$opts $initblock] #puts stderr "*** returned $r" return $r } @@ -1086,14 +1087,19 @@ ::nsf::parameter:invalidate::classcache $class } - ObjectParameterSlot public method namedParameterSpec {prefix name options} { + ObjectParameterSlot public method namedParameterSpec {-map-private:switch prefix name options} { # # Build a pos/nonpos parameter specification from name and option list # + if {${map-private} && [info exists :accessor] && ${:accessor} eq "private"} { + set pName ${:settername} + } else { + set pName $name + } if {[llength $options]>0} { - return $prefix${name}:[join $options ,] + return $prefix${pName}:[join $options ,] } else { - return $prefix${name} + return $prefix${pName} } } @@ -1328,15 +1334,30 @@ return ${:parameterSpec} } + ObjectParameterSlot public method getPropertyDefinitionOptions {parameterSpec} { + if {${:config}} { + if {${:accessor} ne "public"} {set opts [list -accessor ${:accessor}]} {set opts ""} + if {!${:config}} {lappend opts -config false} + if {[info exists :default]} { + return [list ${:domain} property {*}$opts [list $parameterSpec ${:default}]] + } + set methodName property + } else { + if {${:accessor} ne "none"} {set opts [list -accessor ${:accessor}]} {set opts ""} + if {${:config}} {lappend opts -config true} + if {[info exists :default]} { + return [list ${:domain} variable {*}$opts $parameterSpec ${:default}] + } + set methodName variable + } + return [list ${:domain} $methodName {*}$opts $parameterSpec] + } + ObjectParameterSlot public method getPropertyDefinition {} { set options [:getParameterOptions -withMultiplicity true] if {[info exists :positional]} {lappend options positional} - if {!${:config}} {lappend options noconfig} - if {[info exists :default]} { - return [list [:namedParameterSpec "" ${:name} $options] ${:default}] - } else { - return [list [:namedParameterSpec "" ${:name} $options]] - } + #if {!${:config}} {lappend options noconfig} + return [:getPropertyDefinitionOptions [:namedParameterSpec -map-private "" ${:name} $options]] } ###################################################################### @@ -1714,6 +1735,7 @@ $handle call-private true set :config 0 } elseif {${:accessor} ne "public"} { + :destroy error "accessor value '${:accessor}' invalid; might be one of public|protected|private or none" } return 1 @@ -1871,7 +1893,7 @@ {-accessor "none"} {-incremental:switch} {-class ""} - {-config:switch} + {-config:boolean false} {-initblock ""} {-nocomplain:switch} spec:parameter @@ -1960,6 +1982,7 @@ Object method property { {-accessor ""} + {-config:boolean true} {-incremental:switch} {-class ""} {-nocomplain:switch} @@ -1977,7 +2000,7 @@ -incremental=$incremental \ -class $class \ -initblock $initblock \ - -config=true \ + -config $config \ -nocomplain=$nocomplain \ {*}$spec] return $r @@ -1987,7 +2010,7 @@ {-accessor "none"} {-incremental:switch} {-class ""} - {-config:switch} + {-config:boolean false} {-initblock ""} spec:parameter defaultValue:optional @@ -2011,6 +2034,7 @@ nx::Class method property { {-accessor ""} + {-config:boolean true} {-incremental:switch} {-class ""} spec:parameter @@ -2025,7 +2049,7 @@ -accessor $accessor \ -incremental=$incremental \ -class $class \ - -config=true \ + -config $config \ -initblock $initblock \ {*}$spec] return $r Index: tests/parameters.test =================================================================== diff -u -r7a302c7ea09da154a41bf29edf2b3f941ff9a03e -ra866226c4ca39c65f5f98539c140326c617da884 --- tests/parameters.test (.../parameters.test) (revision 7a302c7ea09da154a41bf29edf2b3f941ff9a03e) +++ tests/parameters.test (.../parameters.test) (revision a866226c4ca39c65f5f98539c140326c617da884) @@ -26,7 +26,7 @@ ? {::nsf::method::alias C foo ::set 1} \ {invalid argument '1', maybe too many arguments; should be "::nsf::method::alias object ?-per-object? methodName ?-frame method|object|default? cmdName"} - ? {C eval {:property x -class D}} {invalid argument 'D', maybe too many arguments; should be "::C property ?-accessor value? ?-incremental? ?-class value? spec ?initblock?"} "Test whether the colon prefix is suppressed" + ? {C eval {:property x -class D}} {invalid argument 'D', maybe too many arguments; should be "::C property ?-accessor value? ?-config boolean? ?-incremental? ?-class value? spec ?initblock?"} "Test whether the colon prefix is suppressed" } ####################################################### @@ -2261,7 +2261,7 @@ ? {C info parameter syntax a} "?-a value?" ? {C info parameter definitions v} "" - ? {C info slot definitions v} "{v:noconfig v0}" + ? {C info slot definitions v} "{::C variable v v0}" ? {C info parameter list v} "" ? {C info parameter syntax v} "" @@ -2441,7 +2441,7 @@ # "v" does show up in "info slot ..." ? {C info slot objects} "::C::slot::v" - ? {C info slot definitions} "{v:noconfig 100}" + ? {C info slot definitions} "{::C variable v 100}" nx::Class create D { :property {p0 200} @@ -2459,7 +2459,7 @@ # all properties show up in "info slot" ? {D info slot objects} "::D::slot::p0 ::D::slot::p1 ::D::slot::p2 ::D::slot::p3" - ? {D info slot definitions} "{p0 200} {p1 201} {p2:noconfig 202} {p3:noconfig 203}" + ? {D info slot definitions} "{::D property {p0 200}} {::D property -accessor none {p1 201}} {::D variable p2 202} {::D variable -accessor public p3 203}" #? {D info properties} "{p0 200} {p1 201} {p2:noconfig 202} {p3:noconfig 203}" } @@ -2480,7 +2480,7 @@ # only the variables with slots show up in "info slot ..." ? {o1 info slot objects} "::o1::per-object-slot::v2 ::o1::per-object-slot::v1" - ? {o1 info slot definitions} "{v2:0..n,noconfig 100} {v1:noconfig 100}" + ? {o1 info slot definitions} "{::o1 variable -accessor public v2:0..n 100} {::o1 variable -accessor public v1 100}" nx::Object create o2 { :property {p0 200} @@ -2494,7 +2494,7 @@ # all properties with slots show up in "info slot" ? {o2 info slot objects} "::o2::per-object-slot::p0 ::o2::per-object-slot::p1 ::o2::per-object-slot::p3" - ? {o2 info slot definitions} "{p0 200} {p1 201} {p3:noconfig 203}" + ? {o2 info slot definitions} "{::o2 property {p0 200}} {::o2 property -accessor none {p1 201}} {::o2 variable -accessor public p3 203}" #? {o2 info properties} "{p0 200} {p1 201} {p3:noconfig 203}" } @@ -2511,7 +2511,7 @@ :property {b 1} } - ? {Foo info slot definitions} "a {b 1}" + ? {Foo info slot definitions} "{::Foo property a} {::Foo property {b 1}}" #? {Foo info properties} "a {b 1}" @@ -2520,22 +2520,22 @@ :property a:boolean :property {b:integer 1} } - ? {Foo info slot definitions} "a:boolean {b:integer 1}" + ? {Foo info slot definitions} "{::Foo property a:boolean} {::Foo property {b:integer 1}}" # required/optional properties nx::Class create Foo { :property a:required :property b:boolean,required } - ? {Foo info slot definitions} "a:required b:boolean,required" + ? {Foo info slot definitions} "{::Foo property a:required} {::Foo property b:boolean,required}" # properties with multiplicity nx::Class create Foo { :property {ints:integer,0..n ""} :property objs:object,1..n :property obj:object,0..1 } - ? {Foo info slot definitions} "objs:object,1..n {ints:integer,0..n {}} obj:object,0..1" + ? {Foo info slot definitions} "{::Foo property objs:object,1..n} {::Foo property {ints:integer,0..n {}}} {::Foo property obj:object,0..1}" } # Index: tests/properties.test =================================================================== diff -u -rbcf03cdfc173ac31e6c104985b9a5f88e16e7ea8 -ra866226c4ca39c65f5f98539c140326c617da884 --- tests/properties.test (.../properties.test) (revision bcf03cdfc173ac31e6c104985b9a5f88e16e7ea8) +++ tests/properties.test (.../properties.test) (revision a866226c4ca39c65f5f98539c140326c617da884) @@ -30,6 +30,7 @@ :variable -accessor protected vc vc1 :variable -accessor private vd vd1 :variable -accessor none ve ve1 + :property -accessor none -config false {vf vf1} :public method call-local {v} {: -local $v} @@ -40,6 +41,8 @@ # just the public properties are accessible via the configure interface # ? {c1 configure} { ?-e value? ?-a value? ?-b value? ?-volatile? ?-noinit? ?-mixin mixinreg ...? ?-class class? ?-filter filterreg ...? ?__initcmd?} + + ? {lsort [C info slot definitions]} {{::C property -accessor none {a a1}} {::C property -accessor none {e e1}} {::C property {b b1}} {::C variable -accessor private d d1} {::C variable -accessor private vd vd1} {::C variable -accessor protected c c1} {::C variable -accessor protected vc vc1} {::C variable -accessor public vb vb1} {::C variable va va1} {::C variable ve ve1} {::C variable vf vf1}} ? {c1 cget -a} a1 ? {c1 cget -b} b1 @@ -49,23 +52,29 @@ ? {c1 cget -vb} {cannot lookup parameter value for -vb} ? {c1 cget -vc} {cannot lookup parameter value for -vc} ? {c1 cget -vd} {cannot lookup parameter value for -vd} + ? {c1 cget -ve} {cannot lookup parameter value for -ve} + ? {c1 cget -vf} {cannot lookup parameter value for -vf} # - # The use of "-incremental" implies an accessor + # No incremental used, so "a" and "e" have no slots # ? {c1 info lookup method a} "" ? {c1 info lookup method b} "::nsf::classes::C::b" ? {c1 info lookup method c} "::nsf::classes::C::c" ? {c1 info lookup method d} "::nsf::classes::C::d" + ? {c1 info lookup method e} "" + ? {c1 info lookup method f} "" ? {c1 info lookup method va} "" ? {c1 info lookup method vb} "::nsf::classes::C::vb" ? {c1 info lookup method vc} "::nsf::classes::C::vc" ? {c1 info lookup method vd} "::nsf::classes::C::vd" + ? {c1 info lookup method ve} "" + ? {c1 info lookup method vf} "" # - # The use of "-incremental" implies an accessor, which is public + # Check protection of accessors # ? {nsf::method::property C b call-protected} 0 @@ -94,6 +103,8 @@ ? {c1 eval "info exists :vb"} 1 ? {c1 eval "info exists :vc"} 1 ? {c1 eval "info exists :vd"} 0 + ? {c1 eval "info exists :ve"} 1 + ? {c1 eval "info exists :vf"} 1 # # can we call the accessor directly or via "eval" @@ -126,11 +137,12 @@ ? {c1 call-local d} d1 ? {c1 call-local vd} vd1 - ? {lsort [c1 info vars]} "__private a b c e va vb vc ve" + ? {lsort [c1 info vars]} "__private a b c e va vb vc ve vf" ? {c1 eval "array get :__private"} "::C,vd vd1 ::C,d d1" # - # check incremental operations for properties + # check incremental operations for properties (should fail in all + # cases) # ? {c1 b add x} {wrong # args should be "::c1 b ?value?"} @@ -141,7 +153,8 @@ ? {c1 e add x} {::c1: unable to dispatch method 'e'} # - # check incremental operations for variables + # check incremental operations for variables (should fail in all + # cases) # ? {c1 va add x} {::c1: unable to dispatch method 'va'} @@ -154,7 +167,7 @@ # - # The accessor should be a forwarder due to incremental + # The accessor should be a setter due to incremental # ? {C info method definition b} {::C public setter b} @@ -166,12 +179,10 @@ ? {C property -accessor proceted {b b1}} {accessor value 'proceted' invalid; might be one of public|protected|private or none} # - # The accessor should be still a forwarder (or maybe non-existent) + # The accessor is deleted due to the error # - #? {CC info method definition b} {::CC public forward b ::CC::slot::b {%1 {get assign}} %self b} - # TODO: ... but not a setter - ? {C info method definition b} {::C public setter b} + ? {C info method definition b} {} } @@ -335,17 +346,14 @@ # # check error message # - ? {CC property -accessor proceted {b b1}} {accessor value 'proceted' invalid; might be one of public|protected|private or none} + ? {CC property -accessor proceted -incremental {b b1}} {accessor value 'proceted' invalid; might be one of public|protected|private or none} # - # The accessor should be still a forwarder (or maybe non-existent) + # The accessor is deleted due to the error # + ? {CC info method definition b} {} - #? {CC info method definition b} {::CC public forward b ::CC::slot::b {%1 {get assign}} %self b} - # TODO: ... but not a setter - ? {CC info method definition b} {::CC public setter b} - } ##################################################################### @@ -644,12 +652,10 @@ ? {o1 property -accessor proceted {b b1}} {accessor value 'proceted' invalid; might be one of public|protected|private or none} # - # The accessor should be still a forwarder (or maybe non-existent) + # The accessor is deleted due to the error # - #? {CC info method definition b} {::CC public forward b ::CC::slot::b {%1 {get assign}} %self b} - # TODO: ... but not a setter - ? {o1 info method definition b} {::o1 public setter b} + ? {o1 info method definition b} {} }