Index: Makefile.in =================================================================== diff -u -r8bfe3ac01fe62c1917587fc5fe76952d3ff8f397 -rc4db8ed59a42cf23cc9a7eac511e556d6b077f14 --- Makefile.in (.../Makefile.in) (revision 8bfe3ac01fe62c1917587fc5fe76952d3ff8f397) +++ Makefile.in (.../Makefile.in) (revision c4db8ed59a42cf23cc9a7eac511e556d6b077f14) @@ -404,6 +404,7 @@ $(TCLSH) $(src_test_dir_native)/forward.test -libdir $(PLATFORM_DIR) $(TESTFLAGS) $(TCLSH) $(src_test_dir_native)/mixinof.test -libdir $(PLATFORM_DIR) $(TESTFLAGS) $(TCLSH) $(src_test_dir_native)/tcl86.test -libdir $(PLATFORM_DIR) $(TESTFLAGS) + $(TCLSH) $(src_test_dir_native)/contains.test -libdir $(PLATFORM_DIR) $(TESTFLAGS) test-xotcl: $(TCLSH_PROG) $(TCLSH) $(xotcl_src_test_dir)/testo.xotcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) Index: TODO =================================================================== diff -u -r110b3365dd642ce09d4b4392591ea0e5b19f6d60 -rc4db8ed59a42cf23cc9a7eac511e556d6b077f14 --- TODO (.../TODO) (revision 110b3365dd642ce09d4b4392591ea0e5b19f6d60) +++ TODO (.../TODO) (revision c4db8ed59a42cf23cc9a7eac511e556d6b077f14) @@ -1855,8 +1855,16 @@ created, the namespace path of the parent object is copied to the child as default value. +- added new contains definition based on "apply" instead of + "namespace eval". Main intention is to replace SKIP_LEVELS + by SKIP_LAMBDA +- added functionality to use ":attribute contains:method,nosetter" +- added regression test for contains and attributes of type method + TODO: +- add "nosetter" automatically, when attribute ...:method is used + - "-returns" * leave syntax as is for method? * add flag to alias and forward? Index: generic/nsf.c =================================================================== diff -u -r110b3365dd642ce09d4b4392591ea0e5b19f6d60 -rc4db8ed59a42cf23cc9a7eac511e556d6b077f14 --- generic/nsf.c (.../nsf.c) (revision 110b3365dd642ce09d4b4392591ea0e5b19f6d60) +++ generic/nsf.c (.../nsf.c) (revision c4db8ed59a42cf23cc9a7eac511e556d6b077f14) @@ -436,7 +436,7 @@ int NsfCallMethodWithArgs(ClientData clientData, Tcl_Interp *interp, Tcl_Obj *methodObj, Tcl_Obj *arg, - int givenobjc, Tcl_Obj *CONST objv[], int flags) { + int givenobjc, Tcl_Obj *CONST objv[], int flags) { NsfObject *object = (NsfObject*) clientData; int objc = givenobjc + 2; int result; @@ -448,11 +448,14 @@ if (objc>2) { tov[2] = arg; } - if (objc>3) + if (objc>3) { memcpy(tov+3, objv, sizeof(Tcl_Obj *)*(objc-3)); + } - /*fprintf(stderr, "%%%% CallMethodWithArgs cmdname=%s, method=%s, objc=%d\n", - ObjStr(tov[0]), ObjStr(tov[1]), objc);*/ + /*fprintf(stderr, "%%%% CallMethodWithArgs cmdname=%s, method=%s, arg1 %s objc=%d\n", + ObjStr(tov[0]), ObjStr(tov[1]), + objc>2 ? ObjStr(tov[2]) : "", + objc);*/ result = ObjectDispatch(clientData, interp, objc, tov, flags); FREE_ON_STACK(Tcl_Obj*, tov); @@ -6732,7 +6735,8 @@ Tcl_ObjCmdProc *proc = Tcl_Command_objProc(cmd); int result; - /*fprintf(stderr, "MethodDispatch method '%s' cmd %p cp=%p objc=%d\n", methodName, cmd, cp, objc);*/ + /*fprintf(stderr, "MethodDispatch method '%s' cmd %p cp=%p objc=%d\n", + methodName, cmd, cp, objc);*/ assert(object->teardown); if (proc == TclObjInterpProc) { @@ -14775,7 +14779,7 @@ for (i=1, paramPtr = paramDefs->paramsPtr; paramPtr->name; paramPtr++, i++) { newValue = pc.full_objv[i]; - /*fprintf(stderr, "new Value of %s = %p '%s', type %s", + /*fprintf(stderr, "new Value of %s = %p '%s', type %s\n", ObjStr(paramPtr->nameObj), newValue, newValue ? ObjStr(newValue) : "(null)", paramPtr->type); */ @@ -14830,17 +14834,8 @@ if (paramPtr->flags & NSF_ARG_INITCMD) { /* cscPtr->cmdPtr = NSFindCommand(interp, "::eval"); */ - - //cscPtr->flags = 0; - //CscInit(cscPtr, object, NULL /*cl*/, NULL/*cmd*/, NSF_CSC_TYPE_PLAIN, 0); - //Nsf_PushFrameCsc(interp, cscPtr, framePtr2); - result = Tcl_EvalObjEx(interp, newValue, TCL_EVAL_DIRECT); - //Nsf_PopFrameCsc(interp, framePtr2); - //CscListRemove(interp, cscPtr); - //CscFinish(interp, cscPtr, "converter object frame"); - } else /* must be NSF_ARG_METHOD */ { Tcl_Obj *ov[3]; int oc = 0; @@ -14864,9 +14859,9 @@ ov[0], oc, &ov[1], NSF_CSC_IMMEDIATE); } /* - Pop previously stacked frame for eval context and set the - varFramePtr to the previous value. - */ + * Pop previously stacked frame for eval context and set the + * varFramePtr to the previous value. + */ Nsf_PopFrameCsc(interp, framePtr2); CscListRemove(interp, cscPtr); CscFinish(interp, cscPtr, "converter object frame"); Index: generic/nsf.h =================================================================== diff -u -r0f5513cd0b35c79689a0d04b967ea340577889e8 -rc4db8ed59a42cf23cc9a7eac511e556d6b077f14 --- generic/nsf.h (.../nsf.h) (revision 0f5513cd0b35c79689a0d04b967ea340577889e8) +++ generic/nsf.h (.../nsf.h) (revision c4db8ed59a42cf23cc9a7eac511e556d6b077f14) @@ -88,8 +88,6 @@ #define NSF_MEM_COUNT 1 */ -//#define VAR_RESOLVER_TRACE 1 - /* turn tracing output on/off #define NSFOBJ_TRACE 1 Index: library/nx/nx.tcl =================================================================== diff -u -ref1f9efa0bc697404c0aa5322bbd5cc2d7796c2c -rc4db8ed59a42cf23cc9a7eac511e556d6b077f14 --- library/nx/nx.tcl (.../nx.tcl) (revision ef1f9efa0bc697404c0aa5322bbd5cc2d7796c2c) +++ library/nx/nx.tcl (.../nx.tcl) (revision c4db8ed59a42cf23cc9a7eac511e556d6b077f14) @@ -596,14 +596,19 @@ set properties [string range $value [expr {$colonPos+1}] end] set name [string range $value 0 [expr {$colonPos -1}]] foreach property [split $properties ,] { - if {$property in [list "required" "multivalued" "allowempty" "convert" "nosetter"]} { + if {$property in [list "required" "multivalued" "allowempty" \ + "convert" "nosetter"]} { lappend opts -$property 1 } elseif {[string match type=* $property]} { set type [string range $property 5 end] if {![string match ::* $type]} {set type ::$type} } elseif {[string match arg=* $property]} { set argument [string range $property 4 end] lappend opts -arg $argument + } elseif {$property eq "optional"} { + lappend opts -required 0 + } elseif {$property eq "method"} { + lappend opts -ismethod 1 } else { set type $property } @@ -703,6 +708,7 @@ {manager "[::nsf::self]"} {per-object false} {nosetter} + {ismethod} } # maybe add the following slots at some later time here @@ -853,7 +859,11 @@ # provided values, not for defaults. if {$type ne "substdefault"} {set methodopts [linsert $methodopts 0 $type]} } - lappend objopts slot=[::nsf::self] + if {[info exists :ismethod]} { + set objopts [linsert $objopts 0 method] + } else { + lappend objopts slot=[::nsf::self] + } if {[llength $objopts] > 0} { append objparamdefinition :[join $objopts ,] @@ -1189,17 +1199,21 @@ ############################################ Class method attribute {spec {-slotclass ::nx::Attribute} {initblock ""}} { set r [$slotclass createFromParameterSyntax [::nsf::self] -initblock $initblock {*}$spec] - set o [::nsf::self] - ::nsf::methodproperty $o $r call-protected \ - [::nsf::dispatch $o __default_attribute_call_protection] - return $r + if {$r ne ""} { + set o [::nsf::self] + ::nsf::methodproperty $o $r call-protected \ + [::nsf::dispatch $o __default_attribute_call_protection] + return $r + } } Object method attribute {spec {-slotclass ::nx::Attribute} {initblock ""}} { set r [$slotclass createFromParameterSyntax [::nsf::self] -per-object -initblock $initblock {*}$spec] - set o [::nsf::self] - ::nsf::methodproperty $o -per-object $r call-protected \ - [::nsf::dispatch $o __default_attribute_call_protection] + if {$r ne ""} { + set o [::nsf::self] + ::nsf::methodproperty $o -per-object $r call-protected \ + [::nsf::dispatch $o __default_attribute_call_protection] + } return $r } @@ -1273,18 +1287,19 @@ # reused in XOTcl, no "require" there, so use nsf primitiva ::nsf::dispatch $object ::nsf::methods::object::requirenamespace if {$withnew} { - set m [ScopedNew new \ - -container $object -withclass $class] + set m [ScopedNew new -container $object -withclass $class] $m volatile Class mixin add $m end # TODO: the following is not pretty; however, contains might # build xotcl and next objects. if {[::nsf::is class ::xotcl::Class]} {::xotcl::Class instmixin add $m end} - namespace eval $object $cmds + ::nsf::dispatch $object -frame method ::apply [list {} $cmds $object] + #namespace eval $object $cmds Class mixin delete $m if {[::nsf::is class ::xotcl::Class]} {::xotcl::Class instmixin delete $m} } else { - namespace eval $object $cmds + ::nsf::dispatch $object -frame method ::apply [list {} $cmds $object] + #namespace eval $object $cmds } } Index: tests/contains.test =================================================================== diff -u --- tests/contains.test (revision 0) +++ tests/contains.test (revision c4db8ed59a42cf23cc9a7eac511e556d6b077f14) @@ -0,0 +1,52 @@ +# -*- Tcl -*- +package require nx +namespace path nx + +# Don't use test, since test and contains redefines new, +# so we ahe a conflict.... +#package require nx::test + +proc ? {cmd expected {msg ""}} { + #puts "??? $cmd" + set r [uplevel $cmd] + if {$msg eq ""} {set msg $cmd} + if {$r ne $expected} { + puts stderr "ERROR $msg returned '$r' ne '$expected'" + error "FAILED $msg returned '$r' ne '$expected'" + } else { + puts stderr "OK $msg" + } +} + +# +# We define here a few attributes of type method, such we can add +# arbitrary "-" calls +# +Class create Tree { + :attribute label + :attribute contains:method,optional,nosetter + :attribute foo:method,optional,nosetter + :public method foo {arg} {set :x $arg} +} +set y [Tree new -foo hu] +? [list $y eval {set :x}] hu + +# +# actually, the intention was to define an xotcl-like -contains +# +set x [Tree create 1 -label 1 -contains { + ? {self} ::1 + Tree create 1.1 -label 1.1 + Tree create 1.2 -label 1.2 -contains { + ? {self} ::1::1.2 + Tree create 1.2.1 -label 1.2.1 + Tree create 1.2.2 -label 1.2.2 -contains { + Tree create 1.2.2.1 -label 1.2.2.1 + ? {self} ::1::1.2::1.2.2 + } + Tree create 1.2.3 -label 1.2.3 + } + Tree create 1.3 -label 1.3 +}] + +puts stderr ===EXIT \ No newline at end of file