Index: generic/predefined.h =================================================================== diff -u -r782f6b060b16282799fe936bc528f512e562362a -re45455a7ad52d4d849a0408243d175b4b4a52bb3 --- generic/predefined.h (.../predefined.h) (revision 782f6b060b16282799fe936bc528f512e562362a) +++ generic/predefined.h (.../predefined.h) (revision e45455a7ad52d4d849a0408243d175b4b4a52bb3) @@ -339,6 +339,7 @@ "::xotcl::MetaSlot create ::xotcl::Attribute -superclass ::xotcl::ObjectParameterSlot\n" "createBootstrapAttributeSlots ::xotcl::Attribute {\n" "{value_check once}\n" +"incremental\n" "initcmd\n" "valuecmd\n" "valuechangedcmd\n" @@ -423,13 +424,30 @@ "::xotcl2::Class create ::xotcl::Attribute::Optimizer {\n" ":method method args {::xotcl::next; :optimize}\n" ":method forward args {::xotcl::next; :optimize}\n" -":protected method init args {::xotcl::next; :optimize}\n" +":protected method init args {::xotcl::next; :optimize}\n" ":public method optimize {} {\n" -"if {[set :multivalued]} return\n" +"set object [expr {${:per-object} ? {object} : {}}]\n" +"if {${:per-object}} {\n" +"set perObject -per-object\n" +"set infokind Object} else {\n" +"set perObject \"\"\n" +"set infokind Class}\n" +"if {[::xotcl::cmd::${infokind}Info::method ${:domain} name ${:name}] ne \"\"} {\n" +"::xotcl::forward ${:domain} {*}$perObject ${:name} \\\n" +"${:manager} \\\n" +"[list %1 [${:manager} defaultmethods]] %self \\\n" +"${:methodname}}\n" +"if {[info exists :incremental] && ${:incremental}} return\n" "if {[set :defaultmethods] ne {get assign}} return\n" -"if {[:info callable -which assign] ne \"::xotcl::ObjectParameterSlot alias assign ::xotcl::setinstvar\"} return\n" +"set assignInfo [:info callable -which assign]\n" +"if {$assignInfo ne \"::xotcl::ObjectParameterSlot alias assign ::xotcl::setinstvar\" &&\n" +"[lindex $assignInfo {end 0}] ne \"::xotcl::setinstvar\" } return\n" "if {[:info callable -which get] ne \"::xotcl::ObjectParameterSlot alias get ::xotcl::setinstvar\"} return\n" -"::xotcl::setter ${:domain} {*}[expr {${:per-object} ? \"-per-object\" : \"\"}] ${:name}}}\n" +"array set \"\" [:toParameterSyntax ${:name}]\n" +"if {$(mparam) ne \"\"} {\n" +"set setterParam [lindex $(oparam) 0]} else {\n" +"set setterParam ${:name}}\n" +"::xotcl::setter ${:domain} {*}$perObject $setterParam}}\n" "::xotcl::Attribute mixin add ::xotcl::Attribute::Optimizer\n" "::xotcl2::Class public method parameter arglist {\n" "if {![::xotcl::is [::xotcl::self]::slot object]} {\n" Index: generic/predefined.xotcl =================================================================== diff -u -r782f6b060b16282799fe936bc528f512e562362a -re45455a7ad52d4d849a0408243d175b4b4a52bb3 --- generic/predefined.xotcl (.../predefined.xotcl) (revision 782f6b060b16282799fe936bc528f512e562362a) +++ generic/predefined.xotcl (.../predefined.xotcl) (revision e45455a7ad52d4d849a0408243d175b4b4a52bb3) @@ -654,6 +654,7 @@ createBootstrapAttributeSlots ::xotcl::Attribute { {value_check once} + incremental initcmd valuecmd valuechangedcmd @@ -779,6 +780,8 @@ } else { #puts stderr "adding assign [list obj var value:$(mparam)] // for [self] with $(mparam)" :method assign [list obj var value:$(mparam),slot=[self]] {::xotcl::setinstvar $obj $var $value} + #::xotcl::setter ${:domain} ${:name}:$(mparam),slot=[self] + #puts stderr "::xotcl::setter ${:domain} ${:name}:$(mparam),slot=[self]" } } #append __initcmd [:mk_type_checker] @@ -801,16 +804,43 @@ ::xotcl2::Class create ::xotcl::Attribute::Optimizer { :method method args {::xotcl::next; :optimize} :method forward args {::xotcl::next; :optimize} - :protected method init args {::xotcl::next; :optimize} + :protected method init args {::xotcl::next; :optimize} :public method optimize {} { - #puts stderr OPTIMIZER - if {[set :multivalued]} return + #puts stderr OPTIMIZER-[info exists :incremental] + set object [expr {${:per-object} ? {object} : {}}] + if {${:per-object}} { + set perObject -per-object + set infokind Object + } else { + set perObject "" + set infokind Class + } + if {[::xotcl::cmd::${infokind}Info::method ${:domain} name ${:name}] ne ""} { + #puts stderr "RESETTING ${:domain} name ${:name}" + ::xotcl::forward ${:domain} {*}$perObject ${:name} \ + ${:manager} \ + [list %1 [${:manager} defaultmethods]] %self \ + ${:methodname} + } + #if {[set :multivalued]} return + if {[info exists :incremental] && ${:incremental}} return if {[set :defaultmethods] ne {get assign}} return - #puts stderr assign=[:info callable -which assign] - if {[:info callable -which assign] ne "::xotcl::ObjectParameterSlot alias assign ::xotcl::setinstvar"} return + set assignInfo [:info callable -which assign] + #puts stderr assign=$assignInfo//[lindex $assignInfo {end 0}] + if {$assignInfo ne "::xotcl::ObjectParameterSlot alias assign ::xotcl::setinstvar" && + [lindex $assignInfo {end 0}] ne "::xotcl::setinstvar" } return if {[:info callable -which get] ne "::xotcl::ObjectParameterSlot alias get ::xotcl::setinstvar"} return #puts stderr "**** optimizing [${:domain} info method definition ${:name}]" - ::xotcl::setter ${:domain} {*}[expr {${:per-object} ? "-per-object" : ""}] ${:name} + + array set "" [:toParameterSyntax ${:name}] + if {$(mparam) ne ""} { + set setterParam [lindex $(oparam) 0] + #puts stderr "setterParam=$setterParam, op=$(oparam)" + } else { + set setterParam ${:name} + } + ::xotcl::setter ${:domain} {*}$perObject $setterParam + #puts stderr "::xotcl::setter ${:domain} {*}$perObject $setterParam" } } # register the optimizer per default @@ -853,12 +883,14 @@ } return $value } + ::xotcl::Slot method type=baseclass {name value} { if {![::xotcl::is $value baseclass]} { error "expected baseclass but got \"$value\" for parameter $name" } return $value } + ::xotcl::Slot method type=metaclass {name value} { if {![::xotcl::is $value metaclass]} { error "expected metaclass but got \"$value\" for parameter $name" Index: tests/parameters.xotcl =================================================================== diff -u -r496ffe8fb5e5bdaba56fe3a939d32634bdbcb088 -re45455a7ad52d4d849a0408243d175b4b4a52bb3 --- tests/parameters.xotcl (.../parameters.xotcl) (revision 496ffe8fb5e5bdaba56fe3a939d32634bdbcb088) +++ tests/parameters.xotcl (.../parameters.xotcl) (revision e45455a7ad52d4d849a0408243d175b4b4a52bb3) @@ -308,6 +308,11 @@ ? {Foo create foo -ints {1 2}} "::foo" ? {Foo create foo -ints {1 a 2}} {invalid value in "1 a 2": expected integer but got "a" for parameter -ints} +# make slot incremental +Foo slot ints eval { + set :incremental 1 + :optimize +} Foo create foo -ints {1 2} ? {foo ints add 0} "0 1 2" ? {foo ints add a} {expected integer but got "a" for parameter value} @@ -706,6 +711,10 @@ ? {ParamTest create p -u c1} {expected upper but got "c1" for parameter -u} ? {ParamTest create p -us {A B c}} \ {invalid value in "A B c": expected upper but got "c" for parameter -us} +ParamTest slot us eval { + set :incremental 1 + :optimize +} ? {ParamTest create p -us {A B}} ::p ? {p us add C end} "A B C" @@ -725,7 +734,7 @@ "o" \ "value is an object" ? {p o xxx} \ - {expected object but got "xxx" for parameter value} \ + {expected object but got "xxx" for parameter o} \ "value is not an object" ParamTest slots { @@ -740,7 +749,7 @@ "value is a list of objects (multiple elements)" ? {p os {o xxx d1}} \ - {invalid value in "o xxx d1": expected object but got "xxx" for parameter value} \ + {invalid value in "o xxx d1": expected object but got "xxx" for parameter os} \ "list with invalid object" ####################################################### @@ -825,7 +834,30 @@ ? {::xotcl::setter o {d default}} {parameter "d" is not allowed to have default "default"} ? {::xotcl::setter o -x} {method name "-x" must not start with a dash} +o destroy +####################################################### +# test for slot-optimizer +####################################################### +Test case slot-optimizer + +Class create C -parameter {a b:integer c:integer,multivalued} + +C create c1 +? {c1 a 1} 1 +? {c1 b 1} 1 +? {c1 c 1} 1 + +# before: 1st case: setter, 2&3: forward +#slot-optimizer.001: 1.50 mms, c1 a 1 +#slot-optimizer.002: 3.30 mms, c1 b 1 +#slot-optimizer.003: 3.40 mms, c1 c 1 +# +# after: 1st, 2nd, 3rd case: setter +#slot-optimizer.001: 1.50 mms, c1 a 1 +#slot-optimizer.002: 1.50 mms, c1 b 1 +#slot-optimizer.003: 1.60 mms, c1 c 1 + ## TODO regression test for type checking, parameter options (initcmd, ## substdefault, combinations with defaults, ...), etc. puts stderr =====END Index: tests/slottest.xotcl =================================================================== diff -u -rc942f4e117d2aa3c8594702e0476a3f73a4147df -re45455a7ad52d4d849a0408243d175b4b4a52bb3 --- tests/slottest.xotcl (.../slottest.xotcl) (revision c942f4e117d2aa3c8594702e0476a3f73a4147df) +++ tests/slottest.xotcl (.../slottest.xotcl) (revision e45455a7ad52d4d849a0408243d175b4b4a52bb3) @@ -342,7 +342,7 @@ Class Person -slots { Attribute create name Attribute create age -default 0 - Attribute create projects -default {} -multivalued true + Attribute create projects -default {} -multivalued true -incremental true } Person p1 -name "Gustaf" @@ -386,7 +386,7 @@ } Person slots { - Attribute create projects -default "" -multivalued true -type ::Project + Attribute create projects -default "" -multivalued true -incremental true -type ::Project Attribute create salary -type integer }