Index: TODO =================================================================== diff -u -r13d14668e746b4f8c6461288cdd29673db4604dd -red6c291a4217ee648c4fb8264ce45c757a51578f --- TODO (.../TODO) (revision 13d14668e746b4f8c6461288cdd29673db4604dd) +++ TODO (.../TODO) (revision ed6c291a4217ee648c4fb8264ce45c757a51578f) @@ -2501,7 +2501,19 @@ * allow specification of system method handles in nsf::createobjectsystem * automatically register alias, when system-method handle was provided and a same-named method is defined - + +* provided a fast path implementation for "defaultmethod" +* provided default system methods for "init", "defaultmethod" and "unknown" +* provided handles for system methods "alloc", "dealloc", "recreate", and + "defaultmethod" +* strip in dispatch invocations of "unknown" potental leading colons +* removed c-level implementation of init again, since scripted one can + be used now as well in registration of createobjectsystem +* reduced verbosity +* added defintions such that these methods can be loaded via + ::nsf::method::require ::nx::Object unknown + + TODO: - when alloc|dealloc are loaded via require, we have Index: generic/gentclAPI.decls =================================================================== diff -u -r13d14668e746b4f8c6461288cdd29673db4604dd -red6c291a4217ee648c4fb8264ce45c757a51578f --- generic/gentclAPI.decls (.../gentclAPI.decls) (revision 13d14668e746b4f8c6461288cdd29673db4604dd) +++ generic/gentclAPI.decls (.../gentclAPI.decls) (revision ed6c291a4217ee648c4fb8264ce45c757a51578f) @@ -187,10 +187,6 @@ {-argName "guard" -required 1 -type tclobj} } -objectMethod init NsfOInitMethod { - {-argName "args" -type allargs} -} - objectMethod instvar NsfOInstvarMethod { {-argName "args" -type allargs} } Index: generic/nsf.c =================================================================== diff -u -r13d14668e746b4f8c6461288cdd29673db4604dd -red6c291a4217ee648c4fb8264ce45c757a51578f --- generic/nsf.c (.../nsf.c) (revision 13d14668e746b4f8c6461288cdd29673db4604dd) +++ generic/nsf.c (.../nsf.c) (revision ed6c291a4217ee648c4fb8264ce45c757a51578f) @@ -2199,6 +2199,7 @@ * Mark the method das defined */ osPtr->definedMethods |= flag; + /*fprintf(stderr, "+++ %s %.6x defining %s.%s %s\n", ClassName(defOsPtr->rootClass), osPtr->definedMethods, ObjectName(object), methodName, Nsf_SytemMethodOpts[i]);*/ @@ -2547,8 +2548,10 @@ */ static CONST char * MethodName(Tcl_Obj *methodObj) { - char *methodName = ObjStr(methodObj); + char *methodName;; + assert(methodObj); + methodName = ObjStr(methodObj); if (FOR_COLON_RESOLVER(methodName)) { methodName ++; } @@ -7937,7 +7940,7 @@ * we pass the object as first argument of the unknown * handler. */ - fprintf(stderr, "next calls DispatchUnknownMethod\n"); + /*fprintf(stderr, "next calls DispatchUnknownMethod\n");*/ result = DispatchUnknownMethod(self, interp, objc, objv, object, objv[1], NSF_CM_NO_OBJECT_METHOD|NSF_CSC_IMMEDIATE); } @@ -8421,17 +8424,24 @@ DispatchDefaultMethod(ClientData clientData, Tcl_Interp *interp, Tcl_Obj *obj, int flags) { int result; - Tcl_Obj *methodObj = NsfMethodObj((NsfObject *)clientData, NSF_o_defaultmethod_idx); + Tcl_Obj *methodObj; + NsfObject *object = clientData; - if (methodObj) { + assert(clientData); + + if (CallDirectly(interp, object, NSF_o_defaultmethod_idx, &methodObj)) { + + Tcl_SetObjResult(interp, object->cmdName); + result = TCL_OK; + + } else { Tcl_Obj *tov[2]; + tov[0] = obj; tov[1] = methodObj; - result = ObjectDispatch(clientData, interp, 2, tov, flags|NSF_CM_NO_UNKNOWN); - } else { - result = TCL_OK; } + return result; } @@ -8525,17 +8535,20 @@ int result; NsfObject *object = (NsfObject*)clientData; Tcl_Obj *unknownObj = NsfMethodObj(object, NSF_o_unknown_idx); + CONST char *methodName = MethodName(methodObj); - /*fprintf(stderr, "compare unknownObj %p with methodObj %p '%s' %p %p %s\n", + /*fprintf(stderr, "compare unknownObj %p with methodObj %p '%s' %p %p %s -- %s\n", unknownObj, methodObj, ObjStr(methodObj), delegator, delegator?objv[1]:NULL, - delegator?ObjStr(objv[1]) : NULL );*/ + delegator?ObjStr(objv[1]) : NULL, + methodName);*/ - if (unknownObj && methodObj != unknownObj && (flags & NSF_CSC_CALL_NO_UNKNOWN) == 0) { + if (unknownObj && methodObj != unknownObj && (flags & NSF_CSC_CALL_NO_UNKNOWN) == 0) { /* * back off and try unknown; */ - int offset; + int offset, mustCopy = *(ObjStr(methodObj)) == ':'; + ALLOC_ON_STACK(Tcl_Obj*, objc+3, tov); /*fprintf(stderr, "calling unknown for %s %s, flgs=%.6x,%.6x/%.6x isClass=%d %p %s objc %d\n", @@ -8549,19 +8562,27 @@ tov[2] = delegator->cmdName; offset ++; } - if (objc>0) { - memcpy(tov + offset, objv, sizeof(Tcl_Obj *)*(objc)); + tov[offset] = mustCopy ? Tcl_NewStringObj(methodName, -1) : methodObj; + if (objc>1) { + memcpy(tov + offset + 1, objv + 1, sizeof(Tcl_Obj *) * (objc - 1)); } flags &= ~NSF_CM_NO_SHIFT; + + /*fprintf(stderr, "call unknown via dispatch mustCopy %d delegator %p method %s (%s)\n", + mustCopy, delegator, ObjStr(tov[offset]), ObjStr(methodObj));*/ + + INCR_REF_COUNT(tov[offset]); result = ObjectDispatch(clientData, interp, objc+offset, tov, flags|NSF_CM_NO_UNKNOWN); + DECR_REF_COUNT(tov[offset]); FREE_ON_STACK(Tcl_Obj*, tov); } else { /* no unknown called, this is the built-in unknown handler */ + + /*fprintf(stderr, "--- default error message for unknown method '%s' " + "to be dispatched on %s, objv[%d] %s\n", + ObjStr(methodObj), ObjectName(object), 1, ObjStr(objv[1]));*/ - /*fprintf(stderr, "--- default error message for unknown method '%s' " - "to be dispatched on %s, objv[%d] %s\n", - ObjStr(methodObj), ObjectName(object), 1, ObjStr(objv[1]));*/ result = NsfPrintError(interp, "%s: unable to dispatch method '%s'", ObjectName(object), MethodName(objv[1])); } @@ -14533,7 +14554,6 @@ fprintf(stderr, "DEBUG obj %p %s activationcount %d on stack %d; " "might be from non-stacked but active callstack content\n", object, ObjectName(object), object->activationCount, count); - fprintf(stderr, "fixed count %d\n", count); /*NsfShowStack(interp);*/ /*return NsfPrintError(interp, "wrong activation count for object %s", ObjectName(object));*/ @@ -14654,7 +14674,7 @@ /* * Flush old byte code */ - fprintf(stderr, "flush byte code\n"); + /*fprintf(stderr, "flush byte code\n");*/ bodyObj->typePtr->freeIntRepProc(bodyObj); } } @@ -17199,17 +17219,6 @@ } /* -objectMethod init NsfOInitMethod { - {-argName "args" -type allargs} -} -*/ -static int -NsfOInitMethod(Tcl_Interp *UNUSED(interp), NsfObject *UNUSED(object), - int UNUSED(objc), Tcl_Obj *CONST UNUSED(objv[])) { - return TCL_OK; -} - -/* objectMethod instvar NsfOInstvarMethod { {-argName "args" -type allargs} } Index: generic/tclAPI.h =================================================================== diff -u -r13d14668e746b4f8c6461288cdd29673db4604dd -red6c291a4217ee648c4fb8264ce45c757a51578f --- generic/tclAPI.h (.../tclAPI.h) (revision 13d14668e746b4f8c6461288cdd29673db4604dd) +++ generic/tclAPI.h (.../tclAPI.h) (revision ed6c291a4217ee648c4fb8264ce45c757a51578f) @@ -255,7 +255,6 @@ static int NsfODestroyMethodStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfOExistsMethodStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfOFilterGuardMethodStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); -static int NsfOInitMethodStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfOInstvarMethodStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfOMixinGuardMethodStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfONoinitMethodStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); @@ -341,7 +340,6 @@ static int NsfODestroyMethod(Tcl_Interp *interp, NsfObject *obj); static int NsfOExistsMethod(Tcl_Interp *interp, NsfObject *obj, CONST char *varName); static int NsfOFilterGuardMethod(Tcl_Interp *interp, NsfObject *obj, CONST char *filter, Tcl_Obj *guard); -static int NsfOInitMethod(Tcl_Interp *interp, NsfObject *obj, int objc, Tcl_Obj *CONST objv[]); static int NsfOInstvarMethod(Tcl_Interp *interp, NsfObject *obj, int objc, Tcl_Obj *CONST objv[]); static int NsfOMixinGuardMethod(Tcl_Interp *interp, NsfObject *obj, Tcl_Obj *mixin, Tcl_Obj *guard); static int NsfONoinitMethod(Tcl_Interp *interp, NsfObject *obj); @@ -428,7 +426,6 @@ NsfODestroyMethodIdx, NsfOExistsMethodIdx, NsfOFilterGuardMethodIdx, - NsfOInitMethodIdx, NsfOInstvarMethodIdx, NsfOMixinGuardMethodIdx, NsfONoinitMethodIdx, @@ -1590,16 +1587,6 @@ } static int -NsfOInitMethodStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - NsfObject *obj = (NsfObject *)clientData; - if (!obj) return NsfObjErrType(interp, NULL, clientData ? ((NsfObject*)clientData)->cmdName : NsfGlobalObjs[NSF_EMPTY], "Object", NULL); - - - return NsfOInitMethod(interp, obj, objc, objv); - -} - -static int NsfOInstvarMethodStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { NsfObject *obj = (NsfObject *)clientData; if (!obj) return NsfObjErrType(interp, NULL, clientData ? ((NsfObject*)clientData)->cmdName : NsfGlobalObjs[NSF_EMPTY], "Object", NULL); @@ -2351,9 +2338,6 @@ {"filter", NSF_ARG_REQUIRED, 0, ConvertToString, NULL,NULL,NULL,NULL,NULL,NULL,NULL}, {"guard", NSF_ARG_REQUIRED, 0, ConvertToTclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL}} }, -{"::nsf::methods::object::init", NsfOInitMethodStub, 1, { - {"args", 0, 0, ConvertToNothing, NULL,NULL,NULL,NULL,NULL,NULL,NULL}} -}, {"::nsf::methods::object::instvar", NsfOInstvarMethodStub, 1, { {"args", 0, 0, ConvertToNothing, NULL,NULL,NULL,NULL,NULL,NULL,NULL}} }, Index: library/nx/nx.tcl =================================================================== diff -u -r13d14668e746b4f8c6461288cdd29673db4604dd -red6c291a4217ee648c4fb8264ce45c757a51578f --- library/nx/nx.tcl (.../nx.tcl) (revision 13d14668e746b4f8c6461288cdd29673db4604dd) +++ library/nx/nx.tcl (.../nx.tcl) (revision ed6c291a4217ee648c4fb8264ce45c757a51578f) @@ -9,16 +9,18 @@ set ::nsf::bootstrap ::nx # - # First create the ::nx object system. + # First create the ::nx object system. The interally called methods, + # which are not defined by default (from this script), must have + # method handles included. # ::nsf::createobjectsystem ::nx::Object ::nx::Class { - -class.alloc alloc + -class.alloc {alloc ::nsf::methods::class::alloc} -class.create create - -class.dealloc dealloc - -class.recreate recreate + -class.dealloc {dealloc ::nsf::methods::class::dealloc} + -class.recreate {recreate ::nsf::methods::class::recreate} -class.requireobject __unknown -object.configure configure - -object.defaultmethod defaultmethod + -object.defaultmethod {defaultmethod ::nsf::methods::object::defaultmethod} -object.destroy destroy -object.init {init ::nsf::methods::object::init} -object.move move @@ -42,11 +44,29 @@ "noinit" "requirenamespace" "residualargs"]} continue ::nsf::method::alias Object $cmdName $cmd } - + + # # provide ::eval as method for ::nx::Object + # ::nsf::method::alias Object eval -frame method ::eval # + # Default Methods (referenced via createobjectsystem) + # + # Actually, we do not need an unknown handler, but if someone + # defines his own unknwon handler we define it automatically + proc ::nsf::methods::object::unknown {m args} { + error "[::nsf::self]: unable to dispatch method '$m'" + } + + # The default constructor + proc ::nsf::methods::object::init args {} + + # This method can be called on calls to object without a specified + # method. + proc ::nsf::methods::object::defaultmethod {} {::nsf::self} + + # # class methods # @@ -80,6 +100,7 @@ ::nsf::method::provide dealloc {::nsf::method::alias dealloc ::nsf::methods::class::dealloc} ::nsf::method::provide recreate {::nsf::method::alias recreate ::nsf::methods::class::recreate} ::nsf::method::provide configure {::nsf::method::alias configure ::nsf::methods::object::configure} + ::nsf::method::provide unknown {::nsf::method::alias unknown ::nsf::methods::object::unknown} # # The method __resolve_method_path resolves a space separated path @@ -257,21 +278,6 @@ Object eval { - # Default unknown-handler for Object - # - # Actually, we do not need this unknown handler, but we could - # define it as follows: - # - # :protected method unknown {m args} { - # error "[::nsf::self]: unable to dispatch method '$m'" - # } - - # "init" must exist on Object. per default it is empty. - #:protected method init args {} - - # this method is called on calls to object without a specified method - :protected method defaultmethod {} {::nsf::self} - # provide a placeholder for the bootup process. The real definition # is based on slots, which are not available at this point. :protected method objectparameter {} {;} Index: library/xotcl/library/xotcl2.tcl =================================================================== diff -u -re3a84e351aaf79c02a63cc0741dde7b9bd550849 -red6c291a4217ee648c4fb8264ce45c757a51578f --- library/xotcl/library/xotcl2.tcl (.../xotcl2.tcl) (revision e3a84e351aaf79c02a63cc0741dde7b9bd550849) +++ library/xotcl/library/xotcl2.tcl (.../xotcl2.tcl) (revision ed6c291a4217ee648c4fb8264ce45c757a51578f) @@ -833,7 +833,7 @@ # resue some definitions from next scripting ::nsf::method::alias ::xotcl::Object copy ::nsf::classes::nx::Object::copy ::nsf::method::alias ::xotcl::Object move ::nsf::classes::nx::Object::move - ::nsf::method::alias ::xotcl::Object defaultmethod ::nsf::classes::nx::Object::defaultmethod + #::nsf::method::alias ::xotcl::Object defaultmethod ::nsf::classes::nx::Object::defaultmethod ::nsf::method::alias ::xotcl::Class -per-object __unknown ::nx::Class::__unknown Index: tests/interceptor-slot.test =================================================================== diff -u -re756bf87414d3f6376327b3a126e5e8ae619302d -red6c291a4217ee648c4fb8264ce45c757a51578f --- tests/interceptor-slot.test (.../interceptor-slot.test) (revision e756bf87414d3f6376327b3a126e5e8ae619302d) +++ tests/interceptor-slot.test (.../interceptor-slot.test) (revision ed6c291a4217ee648c4fb8264ce45c757a51578f) @@ -160,6 +160,7 @@ ? {Foo create ob} ::ob # make sure, no unknown handler exists + #? {::ob info lookup method unknown} "::nsf::classes::nx::Object::unknown" ? {::ob info lookup method unknown} "" ? {ob bar} {::ob: unable to dispatch method 'bar'}