Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch oo-accelerate-90 Excluding Merge-Ins
This is equivalent to a diff from 7247e77c5f to 58f6207e0b
|
2025-08-23
| ||
| 08:00 | Backported accelerations to TclOO's startup code check-in: b5fd1d37ba user: dkf tags: core-9-0-branch | |
| 07:57 | corrections (createhashentry is different in 9.1) and cleanup (I like command tables) Closed-Leaf check-in: 58f6207e0b user: dkf tags: oo-accelerate-90 | |
|
2025-08-22
| ||
| 20:27 | Merge-mark check-in: fe1b51914d user: jan.nijtmans tags: core-9-0-branch | |
| 19:36 | Make code style be a bit closer to the one used in 9.0 check-in: 838a10310d user: dkf tags: oo-accelerate-90 | |
| 15:02 | Start making TclOO faster to initialise (backport) check-in: 096119c82d user: dkf tags: oo-accelerate-90 | |
| 14:54 | Create new branch named "oo-accelerate-90" Closed-Leaf check-in: a034cc4f97 user: dkf tags: mistake | |
| 14:52 | Fix memory debugging info check-in: 7247e77c5f user: dkf tags: core-9-0-branch | |
|
2025-08-21
| ||
| 15:53 | Eliminate clang compiler warning: use of logical '&&' with constant operand check-in: d038315568 user: jan.nijtmans tags: core-9-0-branch | |
Changes to generic/tclInt.h.
| ︙ | ︙ | |||
3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 | */ #if TCL_MAJOR_VERSION > 8 MODULE_SCOPE void TclAdvanceContinuations(Tcl_Size *line, Tcl_Size **next, int loc); MODULE_SCOPE void TclAdvanceLines(Tcl_Size *line, const char *start, const char *end); MODULE_SCOPE void TclAppendBytesToByteArray(Tcl_Obj *objPtr, const unsigned char *bytes, Tcl_Size len); MODULE_SCOPE void TclAppendUtfToUtf(Tcl_Obj *objPtr, const char *bytes, Tcl_Size numBytes); MODULE_SCOPE void TclArgumentEnter(Tcl_Interp *interp, Tcl_Obj *objv[], Tcl_Size objc, CmdFrame *cf); MODULE_SCOPE void TclArgumentRelease(Tcl_Interp *interp, | > > > > | 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 | */ #if TCL_MAJOR_VERSION > 8 MODULE_SCOPE void TclAdvanceContinuations(Tcl_Size *line, Tcl_Size **next, int loc); MODULE_SCOPE void TclAdvanceLines(Tcl_Size *line, const char *start, const char *end); MODULE_SCOPE int TclAliasCreate(Tcl_Interp *interp, Tcl_Interp *childInterp, Tcl_Interp *parentInterp, Tcl_Obj *namePtr, Tcl_Obj *targetPtr, Tcl_Size objc, Tcl_Obj *const objv[]); MODULE_SCOPE void TclAppendBytesToByteArray(Tcl_Obj *objPtr, const unsigned char *bytes, Tcl_Size len); MODULE_SCOPE void TclAppendUtfToUtf(Tcl_Obj *objPtr, const char *bytes, Tcl_Size numBytes); MODULE_SCOPE void TclArgumentEnter(Tcl_Interp *interp, Tcl_Obj *objv[], Tcl_Size objc, CmdFrame *cf); MODULE_SCOPE void TclArgumentRelease(Tcl_Interp *interp, |
| ︙ | ︙ |
Changes to generic/tclInterp.c.
| ︙ | ︙ | |||
217 218 219 220 221 222 223 | #define INTERP_INFO(interp) \ ((InterpInfo *) ((Interp *) (interp))->interpInfo) /* * Prototypes for local static functions: */ | < < < < | 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | #define INTERP_INFO(interp) \ ((InterpInfo *) ((Interp *) (interp))->interpInfo) /* * Prototypes for local static functions: */ static int AliasDelete(Tcl_Interp *interp, Tcl_Interp *childInterp, Tcl_Obj *namePtr); static int AliasDescribe(Tcl_Interp *interp, Tcl_Interp *childInterp, Tcl_Obj *objPtr); static int AliasList(Tcl_Interp *interp, Tcl_Interp *childInterp); static Tcl_ObjCmdProc AliasNRCmd; static Tcl_CmdDeleteProc AliasObjCmdDeleteProc; |
| ︙ | ︙ | |||
697 698 699 700 701 702 703 |
}
if (objc > 5) {
parentInterp = GetInterp(interp, objv[4]);
if (parentInterp == NULL) {
return TCL_ERROR;
}
| | | 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 |
}
if (objc > 5) {
parentInterp = GetInterp(interp, objv[4]);
if (parentInterp == NULL) {
return TCL_ERROR;
}
return TclAliasCreate(interp, childInterp, parentInterp, objv[3],
objv[5], objc - 6, objv + 6);
}
aliasArgs:
Tcl_WrongNumArgs(interp, 2, objv,
"childPath childCmd ?parentPath parentCmd? ?arg ...?");
return TCL_ERROR;
|
| ︙ | ︙ | |||
1228 1229 1230 1231 1232 1233 1234 |
childObjPtr = Tcl_NewStringObj(childCmd, -1);
Tcl_IncrRefCount(childObjPtr);
targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
Tcl_IncrRefCount(targetObjPtr);
| | | 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 |
childObjPtr = Tcl_NewStringObj(childCmd, -1);
Tcl_IncrRefCount(childObjPtr);
targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
Tcl_IncrRefCount(targetObjPtr);
result = TclAliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
targetObjPtr, argc, objv);
for (i = 0; i < argc; i++) {
Tcl_DecrRefCount(objv[i]);
}
TclStackFree(childInterp, objv);
Tcl_DecrRefCount(targetObjPtr);
|
| ︙ | ︙ | |||
1275 1276 1277 1278 1279 1280 1281 |
childObjPtr = Tcl_NewStringObj(childCmd, -1);
Tcl_IncrRefCount(childObjPtr);
targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
Tcl_IncrRefCount(targetObjPtr);
| | | 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 |
childObjPtr = Tcl_NewStringObj(childCmd, -1);
Tcl_IncrRefCount(childObjPtr);
targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
Tcl_IncrRefCount(targetObjPtr);
result = TclAliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
targetObjPtr, objc, objv);
Tcl_DecrRefCount(childObjPtr);
Tcl_DecrRefCount(targetObjPtr);
return result;
}
|
| ︙ | ︙ | |||
1448 1449 1450 1451 1452 1453 1454 |
nextAliasPtr = (Alias *) aliasCmdPtr->objClientData;
}
}
/*
*----------------------------------------------------------------------
*
| | | | | 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 |
nextAliasPtr = (Alias *) aliasCmdPtr->objClientData;
}
}
/*
*----------------------------------------------------------------------
*
* TclAliasCreate --
*
* Helper function to do the work to actually create an alias.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* An alias command is created and entered into the alias table for the
* child interpreter.
*
*----------------------------------------------------------------------
*/
int
TclAliasCreate(
Tcl_Interp *interp, /* Interp for error reporting. */
Tcl_Interp *childInterp, /* Interp where alias cmd will live or from
* which alias will be deleted. */
Tcl_Interp *parentInterp, /* Interp in which target command will be
* invoked. */
Tcl_Obj *namePtr, /* Name of alias cmd. */
Tcl_Obj *targetCmdPtr, /* Name of target cmd. */
|
| ︙ | ︙ | |||
2464 2465 2466 2467 2468 2469 2470 |
if (safe) {
Tcl_Obj *clockObj;
int status;
TclNewLiteralStringObj(clockObj, "clock");
Tcl_IncrRefCount(clockObj);
| | | 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 |
if (safe) {
Tcl_Obj *clockObj;
int status;
TclNewLiteralStringObj(clockObj, "clock");
Tcl_IncrRefCount(clockObj);
status = TclAliasCreate(interp, childInterp, parentInterp, clockObj,
clockObj, 0, NULL);
Tcl_DecrRefCount(clockObj);
if (status != TCL_OK) {
goto error2;
}
}
|
| ︙ | ︙ | |||
2554 2555 2556 2557 2558 2559 2560 |
return AliasDescribe(interp, childInterp, objv[2]);
}
if (TclGetString(objv[3])[0] == '\0') {
if (objc == 4) {
return AliasDelete(interp, childInterp, objv[2]);
}
} else {
| | | 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 |
return AliasDescribe(interp, childInterp, objv[2]);
}
if (TclGetString(objv[3])[0] == '\0') {
if (objc == 4) {
return AliasDelete(interp, childInterp, objv[2]);
}
} else {
return TclAliasCreate(interp, childInterp, interp, objv[2],
objv[3], objc - 4, objv + 4);
}
}
Tcl_WrongNumArgs(interp, 2, objv, "aliasName ?targetName? ?arg ...?");
return TCL_ERROR;
case OPT_ALIASES:
if (objc != 2) {
|
| ︙ | ︙ |
Changes to generic/tclOO.c.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 | #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tclInt.h" #include "tclOOInt.h" /* * Commands in oo::define and oo::objdefine. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "tclInt.h"
#include "tclOOInt.h"
/*
* Commands in oo and oo::Helpers.
*/
static const struct StdCommands {
const char *name;
Tcl_ObjCmdProc *objProc;
Tcl_ObjCmdProc *nreProc;
CompileProc *compileProc;
} ooCmds[] = {
{"define", TclOODefineObjCmd, NULL, NULL},
{"objdefine", TclOOObjDefObjCmd, NULL, NULL},
{"copy", TclOOCopyObjectCmd, NULL, NULL},
{"DelegateName", TclOODelegateNameObjCmd, NULL, NULL},
{NULL, NULL, NULL, NULL}
}, helpCmds[] = {
{"callback", TclOOCallbackObjCmd, NULL, NULL},
{"mymethod", TclOOCallbackObjCmd, NULL, NULL},
{"classvariable", TclOOClassVariableObjCmd, NULL, NULL},
{"link", TclOOLinkObjCmd, NULL, NULL},
{"next", NULL, TclOONextObjCmd, TclCompileObjectNextCmd},
{"nextto", NULL, TclOONextToObjCmd, TclCompileObjectNextToCmd},
{"self", TclOOSelfObjCmd, NULL, TclCompileObjectSelfCmd},
{NULL, NULL, NULL, NULL}
};
/*
* Commands in oo::define and oo::objdefine.
*/
static const struct DefineCommands {
const char *name;
Tcl_ObjCmdProc *objProc;
int flag;
} defineCmds[] = {
{"classmethod", TclOODefineClassMethodObjCmd, 0},
{"constructor", TclOODefineConstructorObjCmd, 0},
{"definitionnamespace", TclOODefineDefnNsObjCmd, 0},
{"deletemethod", TclOODefineDeleteMethodObjCmd, 0},
{"destructor", TclOODefineDestructorObjCmd, 0},
{"export", TclOODefineExportObjCmd, 0},
{"forward", TclOODefineForwardObjCmd, 0},
{"initialise", TclOODefineInitialiseObjCmd, 0},
{"initialize", TclOODefineInitialiseObjCmd, 0},
{"method", TclOODefineMethodObjCmd, 0},
{"private", TclOODefinePrivateObjCmd, 0},
{"renamemethod", TclOODefineRenameMethodObjCmd, 0},
{"self", TclOODefineSelfObjCmd, 0},
{"unexport", TclOODefineUnexportObjCmd, 0},
{NULL, NULL, 0}
}, objdefCmds[] = {
|
| ︙ | ︙ | |||
362 363 364 365 366 367 368 |
TclNewLiteralStringObj(fPtr->unknownMethodNameObj, "unknown");
TclNewLiteralStringObj(fPtr->constructorName, "<constructor>");
TclNewLiteralStringObj(fPtr->destructorName, "<destructor>");
TclNewLiteralStringObj(fPtr->clonedName, "<cloned>");
TclNewLiteralStringObj(fPtr->defineName, "::oo::define");
TclNewLiteralStringObj(fPtr->myName, "my");
| | > > > | > > > | 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 |
TclNewLiteralStringObj(fPtr->unknownMethodNameObj, "unknown");
TclNewLiteralStringObj(fPtr->constructorName, "<constructor>");
TclNewLiteralStringObj(fPtr->destructorName, "<destructor>");
TclNewLiteralStringObj(fPtr->clonedName, "<cloned>");
TclNewLiteralStringObj(fPtr->defineName, "::oo::define");
TclNewLiteralStringObj(fPtr->myName, "my");
TclNewLiteralStringObj(fPtr->slotGetName, "Get");
TclNewLiteralStringObj(fPtr->slotSetName, "Set");
TclNewLiteralStringObj(fPtr->slotResolveName, "Resolve");
TclNewLiteralStringObj(fPtr->slotDefOpName, "--default-operation");
Tcl_IncrRefCount(fPtr->unknownMethodNameObj);
Tcl_IncrRefCount(fPtr->constructorName);
Tcl_IncrRefCount(fPtr->destructorName);
Tcl_IncrRefCount(fPtr->clonedName);
Tcl_IncrRefCount(fPtr->defineName);
Tcl_IncrRefCount(fPtr->myName);
Tcl_IncrRefCount(fPtr->slotGetName);
Tcl_IncrRefCount(fPtr->slotSetName);
Tcl_IncrRefCount(fPtr->slotResolveName);
Tcl_IncrRefCount(fPtr->slotDefOpName);
TclCreateObjCommandInNs(interp, "UnknownDefinition", fPtr->ooNs,
TclOOUnknownDefinition, NULL, NULL);
TclNewLiteralStringObj(namePtr, "::oo::UnknownDefinition");
Tcl_SetNamespaceUnknownHandler(interp, define, namePtr);
Tcl_SetNamespaceUnknownHandler(interp, objdef, namePtr);
Tcl_BounceRefCount(namePtr);
|
| ︙ | ︙ | |||
424 425 426 427 428 429 430 |
(Tcl_Class) fPtr->classCls, NULL, 0, &classConstructor, NULL);
/*
* Create non-object commands and plug ourselves into the Tcl [info]
* ensemble.
*/
| | < | > | > > | > | | < < < | 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 |
(Tcl_Class) fPtr->classCls, NULL, 0, &classConstructor, NULL);
/*
* Create non-object commands and plug ourselves into the Tcl [info]
* ensemble.
*/
for (i = 0 ; helpCmds[i].name ; i++) {
CreateCmdInNS(interp, fPtr->helpersNs, helpCmds[i].name,
helpCmds[i].objProc, helpCmds[i].nreProc,
helpCmds[i].compileProc);
}
for (i = 0 ; ooCmds[i].name ; i++) {
CreateCmdInNS(interp, fPtr->ooNs, ooCmds[i].name,
ooCmds[i].objProc, ooCmds[i].nreProc,
ooCmds[i].compileProc);
}
TclOOInitInfo(interp);
/*
* Now make the class of slots.
*/
|
| ︙ | ︙ | |||
608 609 610 611 612 613 614 |
TclDecrRefCount(fPtr->unknownMethodNameObj);
TclDecrRefCount(fPtr->constructorName);
TclDecrRefCount(fPtr->destructorName);
TclDecrRefCount(fPtr->clonedName);
TclDecrRefCount(fPtr->defineName);
TclDecrRefCount(fPtr->myName);
| | > > > | 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 |
TclDecrRefCount(fPtr->unknownMethodNameObj);
TclDecrRefCount(fPtr->constructorName);
TclDecrRefCount(fPtr->destructorName);
TclDecrRefCount(fPtr->clonedName);
TclDecrRefCount(fPtr->defineName);
TclDecrRefCount(fPtr->myName);
TclDecrRefCount(fPtr->slotGetName);
TclDecrRefCount(fPtr->slotSetName);
TclDecrRefCount(fPtr->slotResolveName);
TclDecrRefCount(fPtr->slotDefOpName);
TclOODecrRefCount(fPtr->objectCls->thisPtr);
TclOODecrRefCount(fPtr->classCls->thisPtr);
Tcl_Free(fPtr);
/*
* Don't leave the interpreter field pointing to freed data.
|
| ︙ | ︙ | |||
792 793 794 795 796 797 798 799 800 801 802 803 804 805 |
tracePtr->refCount = 1;
oPtr->myCommand = TclNRCreateCommandInNs(interp, "my", oPtr->namespacePtr,
TclOOPrivateObjectCmd, PrivateNRObjectCmd, oPtr, MyDeleted);
oPtr->myclassCommand = TclNRCreateCommandInNs(interp, "myclass",
oPtr->namespacePtr, TclOOMyClassObjCmd, MyClassNRObjCmd, oPtr,
MyClassDeleted);
return oPtr;
}
/*
* ----------------------------------------------------------------------
*
* SquelchCachedName --
| > | 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 |
tracePtr->refCount = 1;
oPtr->myCommand = TclNRCreateCommandInNs(interp, "my", oPtr->namespacePtr,
TclOOPrivateObjectCmd, PrivateNRObjectCmd, oPtr, MyDeleted);
oPtr->myclassCommand = TclNRCreateCommandInNs(interp, "myclass",
oPtr->namespacePtr, TclOOMyClassObjCmd, MyClassNRObjCmd, oPtr,
MyClassDeleted);
oPtr->linkedCmdsList = NULL;
return oPtr;
}
/*
* ----------------------------------------------------------------------
*
* SquelchCachedName --
|
| ︙ | ︙ | |||
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 |
static void
MyDeleted(
void *clientData) /* Reference to the object whose [my] has been
* squelched. */
{
Object *oPtr = (Object *) clientData;
oPtr->myCommand = NULL;
}
static void
MyClassDeleted(
void *clientData)
{
| > > > > > > > > > > > | 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 |
static void
MyDeleted(
void *clientData) /* Reference to the object whose [my] has been
* squelched. */
{
Object *oPtr = (Object *) clientData;
Tcl_Size linkc, i;
Tcl_Obj **linkv, *link;
if (oPtr->linkedCmdsList) {
TclListObjGetElements(NULL, oPtr->linkedCmdsList, &linkc, &linkv);
for (i=0 ; i<linkc ; i++) {
link = linkv[i];
(void) Tcl_DeleteCommand(oPtr->fPtr->interp, TclGetString(link));
}
Tcl_DecrRefCount(oPtr->linkedCmdsList);
oPtr->linkedCmdsList = NULL;
}
oPtr->myCommand = NULL;
}
static void
MyClassDeleted(
void *clientData)
{
|
| ︙ | ︙ | |||
3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 |
Tcl_Obj *
Tcl_GetObjectName(
Tcl_Interp *interp,
Tcl_Object object)
{
return TclOOObjectName(interp, (Object *) object);
}
/*
* ----------------------------------------------------------------------
*
* assorted trivial 'getter' functions
*
* ----------------------------------------------------------------------
| > > > > > > > > > > > > > > > > > > > > > > > > | 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 |
Tcl_Obj *
Tcl_GetObjectName(
Tcl_Interp *interp,
Tcl_Object object)
{
return TclOOObjectName(interp, (Object *) object);
}
/*
* ----------------------------------------------------------------------
*
* TclOOObjectMyName --
*
* Utility function that returns the name of the object's [my], or NULL
* if it has been deleted (or otherwise doesn't exist).
*
* ----------------------------------------------------------------------
*/
Tcl_Obj *
TclOOObjectMyName(
Tcl_Interp *interp,
Object *oPtr)
{
Tcl_Obj *namePtr;
if (!oPtr->myCommand) {
return NULL;
}
TclNewObj(namePtr);
Tcl_GetCommandFullName(interp, oPtr->myCommand, namePtr);
return namePtr;
}
/*
* ----------------------------------------------------------------------
*
* assorted trivial 'getter' functions
*
* ----------------------------------------------------------------------
|
| ︙ | ︙ |
Changes to generic/tclOOBasic.c.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 | #endif #include "tclInt.h" #include "tclOOInt.h" #include "tclTomMath.h" static inline Tcl_Object *AddConstructionFinalizer(Tcl_Interp *interp); static Tcl_NRPostProc AfterNRDestructor; | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #endif #include "tclInt.h" #include "tclOOInt.h" #include "tclTomMath.h" static inline Tcl_Object *AddConstructionFinalizer(Tcl_Interp *interp); static Tcl_NRPostProc AfterNRDestructor; static Tcl_NRPostProc PostClassConstructor; static Tcl_NRPostProc FinalizeConstruction; static Tcl_NRPostProc FinalizeEval; static Tcl_NRPostProc NextRestoreFrame; /* * ---------------------------------------------------------------------- * |
| ︙ | ︙ | |||
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
Tcl_SetObjResult(interp, TclOOObjectName(interp, oPtr));
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOO_Class_Constructor --
*
* Implementation for oo::class constructor.
*
* ----------------------------------------------------------------------
*/
int
TclOO_Class_Constructor(
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_ObjectContext context,
int objc,
Tcl_Obj *const *objv)
{
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < | > | < > > > | | | > > > > | > < < | | < | | < < < < < < | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
Tcl_SetObjResult(interp, TclOOObjectName(interp, oPtr));
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* MixinClassDelegates --
*
* Internal utility for setting up the class delegate.
* Runs after the class has called [oo::define] on its argument.
*
* ----------------------------------------------------------------------
*/
/*
* Look up the delegate for a class.
*/
static inline Class *
GetClassDelegate(
Tcl_Interp *interp,
Class *clsPtr)
{
Tcl_Obj *delegateName = Tcl_ObjPrintf("%s:: oo ::delegate",
clsPtr->thisPtr->namespacePtr->fullName);
Class *delegatePtr = TclOOGetClassFromObj(interp, delegateName);
Tcl_DecrRefCount(delegateName);
return delegatePtr;
}
/*
* Patches in the appropriate class delegates' superclasses.
* Sonewhat nessy because the list of superclasses isn't modified frequently.
*/
static inline void
SetDelegateSuperclasses(
Tcl_Interp *interp,
Class *clsPtr,
Class *delegatePtr)
{
/* Build new list of superclasses */
int i, j = delegatePtr->superclasses.num, k;
Class *superPtr, **supers = (Class **) Tcl_Alloc(sizeof(Class *) *
(delegatePtr->superclasses.num + clsPtr->superclasses.num));
if (delegatePtr->superclasses.num) {
memcpy(supers, delegatePtr->superclasses.list,
sizeof(Class *) * delegatePtr->superclasses.num);
}
FOREACH(superPtr, clsPtr->superclasses) {
Class *superDelegatePtr = GetClassDelegate(interp, superPtr);
if (!superDelegatePtr) {
continue;
}
for (k=0 ; k<=j ; k++) {
if (k == j) {
supers[j++] = superDelegatePtr;
TclOOAddToSubclasses(delegatePtr, superDelegatePtr);
AddRef(superDelegatePtr->thisPtr);
break;
} else if (supers[k] == superDelegatePtr) {
break;
}
}
}
/* Install new list of superclasses */
if (delegatePtr->superclasses.num) {
Tcl_Free(delegatePtr->superclasses.list);
}
delegatePtr->superclasses.list = supers;
delegatePtr->superclasses.num = j;
/* Definitely don't need to bump any epoch here */
}
/*
* Mixes the delegate into its controlling class.
*/
static inline void
InstallDelegateAsMixin(
Tcl_Interp *interp,
Class *clsPtr,
Class *delegatePtr)
{
Class **mixins;
int i;
if (clsPtr->thisPtr->mixins.num == 0) {
TclOOObjectSetMixins(clsPtr->thisPtr, 1, &delegatePtr);
return;
}
mixins = (Class **) TclStackAlloc(interp,
sizeof(Class *) * (clsPtr->thisPtr->mixins.num + 1));
for (i = 0; i < clsPtr->thisPtr->mixins.num; i++) {
mixins[i] = clsPtr->thisPtr->mixins.list[i];
if (mixins[i] == delegatePtr) {
TclStackFree(interp, (void *) mixins);
return;
}
}
mixins[clsPtr->thisPtr->mixins.num] = delegatePtr;
TclOOObjectSetMixins(clsPtr->thisPtr, clsPtr->thisPtr->mixins.num + 1, mixins);
TclStackFree(interp, mixins);
}
/*
* Patches in the appropriate class delegates.
*/
static void
MixinClassDelegates(
Tcl_Interp *interp,
Object *oPtr,
Tcl_Obj *delegateName)
{
Class *clsPtr = oPtr->classPtr, *delegatePtr;
if (clsPtr) {
delegatePtr = TclOOGetClassFromObj(interp, delegateName);
if (delegatePtr) {
SetDelegateSuperclasses(interp, clsPtr, delegatePtr);
InstallDelegateAsMixin(interp, clsPtr, delegatePtr);
}
}
}
/*
* ----------------------------------------------------------------------
*
* TclOO_Class_Constructor --
*
* Implementation for oo::class constructor.
*
* ----------------------------------------------------------------------
*/
int
TclOO_Class_Constructor(
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_ObjectContext context,
int objc,
Tcl_Obj *const *objv)
{
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
size_t skip = Tcl_ObjectContextSkippedArgs(context);
Tcl_Obj **invoke, *delegateName;
if ((size_t) objc > skip + 1) {
Tcl_WrongNumArgs(interp, skip, objv,
"?definitionScript?");
return TCL_ERROR;
}
/*
* Make the class definition delegate. This is special; it doesn't reenter
* here (and the class definition delegate doesn't run any constructors).
*
* This needs to be done before consideration of whether to pass the script
* argument to [oo::define]. [Bug 680503]
*/
delegateName = Tcl_ObjPrintf("%s:: oo ::delegate",
oPtr->namespacePtr->fullName);
Tcl_IncrRefCount(delegateName);
Tcl_NewObjectInstance(interp, (Tcl_Class) oPtr->fPtr->classCls,
TclGetString(delegateName), NULL, TCL_INDEX_NONE, NULL, 0);
/*
* If there's nothing else to do, we're done.
*/
if ((size_t) objc == skip) {
Tcl_InterpState saved = Tcl_SaveInterpState(interp, TCL_OK);
MixinClassDelegates(interp, oPtr, delegateName);
Tcl_DecrRefCount(delegateName);
return Tcl_RestoreInterpState(interp, saved);
}
/*
* Delegate to [oo::define] to do the work.
*/
invoke = (Tcl_Obj **) TclStackAlloc(interp, 3 * sizeof(Tcl_Obj *));
invoke[0] = oPtr->fPtr->defineName;
invoke[1] = TclOOObjectName(interp, oPtr);
invoke[2] = objv[objc - 1];
/*
* Must add references or errors in configuration script will cause
* trouble.
*/
Tcl_IncrRefCount(invoke[0]);
Tcl_IncrRefCount(invoke[1]);
Tcl_IncrRefCount(invoke[2]);
TclNRAddCallback(interp, PostClassConstructor,
invoke, oPtr, delegateName, NULL);
/*
* Tricky point: do not want the extra reported level in the Tcl stack
* trace, so use TCL_EVAL_NOERR.
*/
return TclNREvalObjv(interp, 3, invoke, TCL_EVAL_NOERR, NULL);
}
/*
* Called *after* [oo::define] inside the constructor of a class.
* Cleans up some temporary storage and sets up the delegate.
*/
static int
PostClassConstructor(
void *data[],
Tcl_Interp *interp,
int result)
{
Tcl_Obj **invoke = (Tcl_Obj **) data[0];
Object *oPtr = (Object *) data[1];
Tcl_Obj *delegateName = (Tcl_Obj *) data[2];
Tcl_InterpState saved;
TclDecrRefCount(invoke[0]);
TclDecrRefCount(invoke[1]);
TclDecrRefCount(invoke[2]);
TclStackFree(interp, invoke);
saved = Tcl_SaveInterpState(interp, result);
MixinClassDelegates(interp, oPtr, delegateName);
Tcl_DecrRefCount(delegateName);
return Tcl_RestoreInterpState(interp, saved);
}
/*
* ----------------------------------------------------------------------
*
* TclOO_Class_Create --
|
| ︙ | ︙ | |||
900 901 902 903 904 905 906 907 908 909 910 911 912 913 |
Tcl_SetObjResult(interp, varNamePtr);
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOONextObjCmd, TclOONextToObjCmd --
*
* Implementation of the [next] and [nextto] commands. Note that these
* commands are only ever to be used inside the body of a procedure-like
* method.
*
* ----------------------------------------------------------------------
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 |
Tcl_SetObjResult(interp, varNamePtr);
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOOLinkObjCmd --
*
* Implementation of the [link] command, that makes a command that
* invokes a method on the current object. The name of the command and
* the name of the method match by default. Note that this command is
* only ever to be used inside the body of a procedure-like method,
* and is typically intended for constructors.
*
* ----------------------------------------------------------------------
*/
int
TclOOLinkObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
{
/* Set up common bits. */
CallFrame *framePtr = ((Interp *) interp)->varFramePtr;
CallContext *context;
Object *oPtr;
Tcl_Obj *myCmd, **linkv, *src, *dst;
Tcl_Size linkc;
const char *srcStr;
int i;
if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"%s may only be called from inside a method",
TclGetString(objv[0])));
OO_ERROR(interp, CONTEXT_REQUIRED);
return TCL_ERROR;
}
context = (CallContext *) framePtr->clientData;
oPtr = context->oPtr;
if (!oPtr->myCommand) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"cannot link to non-existent callback handle"));
OO_ERROR(interp, MY_GONE);
return TCL_ERROR;
}
myCmd = Tcl_NewObj();
Tcl_GetCommandFullName(interp, oPtr->myCommand, myCmd);
if (!oPtr->linkedCmdsList) {
oPtr->linkedCmdsList = Tcl_NewListObj(0, NULL);
Tcl_IncrRefCount(oPtr->linkedCmdsList);
}
/* For each argument */
for (i=1; i<objc; i++) {
/* Parse as list of (one or) two items: source and destination names */
if (TclListObjGetElements(interp, objv[i], &linkc, &linkv) != TCL_OK) {
Tcl_BounceRefCount(myCmd);
return TCL_ERROR;
}
switch (linkc) {
case 1:
/* Degenerate case */
src = dst = linkv[0];
break;
case 2:
src = linkv[0];
dst = linkv[1];
break;
default:
Tcl_BounceRefCount(myCmd);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad link description; must only have one or two elements"));
OO_ERROR(interp, CMDLINK_FORMAT);
return TCL_ERROR;
}
/* Qualify the source if necessary */
srcStr = TclGetString(src);
if (srcStr[0] != ':' || srcStr[1] != ':') {
src = Tcl_ObjPrintf("%s::%s",
context->oPtr->namespacePtr->fullName, srcStr);
}
/* Make the alias command */
if (TclAliasCreate(interp, interp, interp, src, myCmd, 1, &dst) != TCL_OK) {
Tcl_BounceRefCount(myCmd);
Tcl_BounceRefCount(src);
return TCL_ERROR;
}
/* Remember the alias for cleanup if necessary */
Tcl_ListObjAppendElement(NULL, oPtr->linkedCmdsList, src);
}
Tcl_BounceRefCount(myCmd);
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOONextObjCmd, TclOONextToObjCmd --
*
* Implementation of the [next] and [nextto] commands. Note that these
* commands are only ever to be used inside the body of a procedure-like
* method.
*
* ----------------------------------------------------------------------
|
| ︙ | ︙ | |||
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 |
/*
* Return the name of the cloned object.
*/
Tcl_SetObjResult(interp, TclOOObjectName(interp, (Object *) o2Ptr));
return TCL_OK;
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 |
/*
* Return the name of the cloned object.
*/
Tcl_SetObjResult(interp, TclOOObjectName(interp, (Object *) o2Ptr));
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOOCallbackObjCmd --
*
* Implementation of the [callback] command, which constructs callbacks
* into the current object.
*
* ----------------------------------------------------------------------
*/
int
TclOOCallbackObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
{
Interp *iPtr = (Interp *) interp;
CallFrame *framePtr = iPtr->varFramePtr;
CallContext *contextPtr;
Tcl_Obj *namePtr, *listPtr;
/*
* Start with sanity checks on the calling context to make sure that we
* are invoked from a suitable method context. If so, we can safely
* retrieve the handle to the object call context.
*/
if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"%s may only be called from inside a method",
TclGetString(objv[0])));
OO_ERROR(interp, CONTEXT_REQUIRED);
return TCL_ERROR;
}
contextPtr = (CallContext *) framePtr->clientData;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "method ...");
return TCL_ERROR;
}
/* Get the [my] real name. */
namePtr = TclOOObjectMyName(interp, contextPtr->oPtr);
if (!namePtr) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"no possible safe callback without my", TCL_AUTO_LENGTH));
OO_ERROR(interp, NO_MY);
return TCL_ERROR;
}
/* No check that the method exists; could be dynamically added. */
listPtr = Tcl_NewListObj(1, &namePtr);
(void) TclListObjAppendElements(NULL, listPtr, objc-1, objv+1);
Tcl_SetObjResult(interp, listPtr);
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOOClassVariableObjCmd --
*
* Implementation of the [classvariable] command, which links to
* variables in the class of the current object.
*
* ----------------------------------------------------------------------
*/
int
TclOOClassVariableObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
{
Interp *iPtr = (Interp *) interp;
CallFrame *framePtr = iPtr->varFramePtr;
CallContext *contextPtr;
Class *clsPtr;
Tcl_Namespace *clsNsPtr, *ourNsPtr;
Var *arrayPtr, *otherPtr;
int i;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "name ...");
return TCL_ERROR;
}
/*
* Start with sanity checks on the calling context to make sure that we
* are invoked from a suitable method context. If so, we can safely
* retrieve the handle to the object call context.
*/
if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"%s may only be called from inside a method",
TclGetString(objv[0])));
OO_ERROR(interp, CONTEXT_REQUIRED);
return TCL_ERROR;
}
/* Get a reference to the class's namespace */
contextPtr = (CallContext *) framePtr->clientData;
clsPtr = CurrentlyInvoked(contextPtr).mPtr->declaringClassPtr;
if (clsPtr == NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"method not defined by a class", TCL_AUTO_LENGTH));
OO_ERROR(interp, UNMATCHED_CONTEXT);
return TCL_ERROR;
}
clsNsPtr = clsPtr->thisPtr->namespacePtr;
/* Check the list of variable names */
for (i = 1; i < objc; i++) {
const char *varName = TclGetString(objv[i]);
if (Tcl_StringMatch(varName, "*(*)")) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad variable name \"%s\": can't create a %s",
varName, "scalar variable that looks like an array element"));
Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", NULL);
return TCL_ERROR;
}
if (Tcl_StringMatch(varName, "*::*")) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad variable name \"%s\": can't create a %s",
varName, "local variable with a namespace separator in it"));
Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", NULL);
return TCL_ERROR;
}
}
/* Lastly, link the caller's local variables to the class's variables */
ourNsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
for (i = 1; i < objc; i++) {
/* Locate the other variable. */
iPtr->varFramePtr->nsPtr = (Namespace *) clsNsPtr;
otherPtr = TclObjLookupVarEx(interp, objv[i], NULL,
(TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG|TCL_AVOID_RESOLVERS),
"access", /*createPart1*/ 1, /*createPart2*/ 0, &arrayPtr);
iPtr->varFramePtr->nsPtr = (Namespace *) ourNsPtr;
if (otherPtr == NULL) {
return TCL_ERROR;
}
/* Create the new variable and link it to otherPtr. */
if (TclPtrObjMakeUpvarIdx(interp, otherPtr, objv[i], 0,
TCL_INDEX_NONE) != TCL_OK) {
return TCL_ERROR;
}
}
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOODelegateNameObjCmd --
*
* Implementation of the [oo::DelegateName] command, which is a utility
* that gets the name of the class delegate for a class. It's trivial,
* but makes working with them much easier as delegate names are
* intentionally hard to create by accident.
*
* Not part of TclOO public API. No public documentation.
*
* ----------------------------------------------------------------------
*/
int
TclOODelegateNameObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
{
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "class");
return TCL_ERROR;
}
Class *clsPtr = TclOOGetClassFromObj(interp, objv[1]);
if (clsPtr == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s:: oo ::delegate",
clsPtr->thisPtr->namespacePtr->fullName));
return TCL_OK;
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
|
Changes to generic/tclOODefineCmds.c.
| ︙ | ︙ | |||
35 36 37 38 39 40 41 |
typedef struct DeclaredSlot {
const char *name;
const Tcl_MethodType getterType;
const Tcl_MethodType setterType;
const Tcl_MethodType resolverType;
} DeclaredSlot;
| | | | | > > > > > > > > > > | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
typedef struct DeclaredSlot {
const char *name;
const Tcl_MethodType getterType;
const Tcl_MethodType setterType;
const Tcl_MethodType resolverType;
} DeclaredSlot;
#define SLOT(name,getter,setter,resolver) \
{"::oo::" name, \
{TCL_OO_METHOD_VERSION_1, "core method: " name " Getter", \
getter, NULL, NULL}, \
{TCL_OO_METHOD_VERSION_1, "core method: " name " Setter", \
setter, NULL, NULL}, \
{TCL_OO_METHOD_VERSION_1, "core method: " name " Resolver", \
resolver, NULL, NULL}}
typedef struct DeclaredSlotMethod {
const char *name;
int flags;
const Tcl_MethodType implType;
} DeclaredSlotMethod;
#define SLOT_METHOD(name,impl,flags) \
{name, flags, {TCL_OO_METHOD_VERSION_1, \
"core method: " name " slot", impl, NULL, NULL}}
/*
* A [string match] pattern used to determine if a method should be exported.
*/
#define PUBLIC_PATTERN "[a-z]*"
/*
|
| ︙ | ︙ | |||
74 75 76 77 78 79 80 81 82 83 84 85 86 87 | static inline int InitDefineContext(Tcl_Interp *interp, Tcl_Namespace *namespacePtr, Object *oPtr, int objc, Tcl_Obj *const objv[]); static inline void RecomputeClassCacheFlag(Object *oPtr); static int RenameDeleteMethod(Tcl_Interp *interp, Object *oPtr, int useClass, Tcl_Obj *const fromPtr, Tcl_Obj *const toPtr); static int ClassFilter_Get(void *clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ClassFilter_Set(void *clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ClassMixin_Get(void *clientData, | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | static inline int InitDefineContext(Tcl_Interp *interp, Tcl_Namespace *namespacePtr, Object *oPtr, int objc, Tcl_Obj *const objv[]); static inline void RecomputeClassCacheFlag(Object *oPtr); static int RenameDeleteMethod(Tcl_Interp *interp, Object *oPtr, int useClass, Tcl_Obj *const fromPtr, Tcl_Obj *const toPtr); static int Slot_Append(void *, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int Slot_AppendNew(void *, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int Slot_Clear(void *, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int Slot_Prepend(void *, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int Slot_Remove(void *, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int Slot_Resolve(void *, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int Slot_Set(void *, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int Slot_Unimplemented(void *, Tcl_Interp *interp, Tcl_ObjectContext, int, Tcl_Obj *const *); static int Slot_Unknown(void *, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ClassFilter_Get(void *clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ClassFilter_Set(void *clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ClassMixin_Get(void *clientData, |
| ︙ | ︙ | |||
170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
Configurable_ObjectReadableProps_Get,
Configurable_ObjectReadableProps_Set, NULL),
SLOT("configuresupport::objwritableproperties",
Configurable_ObjectWritableProps_Get,
Configurable_ObjectWritableProps_Set, NULL),
{NULL, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}
};
/*
* How to build the in-namespace name of a private variable. This is a pattern
* used with Tcl_ObjPrintf().
*/
#define PRIVATE_VARIABLE_PATTERN "%d : %s"
| > > > > > > > > > > > > > > | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
Configurable_ObjectReadableProps_Get,
Configurable_ObjectReadableProps_Set, NULL),
SLOT("configuresupport::objwritableproperties",
Configurable_ObjectWritableProps_Get,
Configurable_ObjectWritableProps_Set, NULL),
{NULL, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}
};
static const DeclaredSlotMethod slotMethods[] = {
SLOT_METHOD("Get", Slot_Unimplemented, 0),
SLOT_METHOD("Resolve", Slot_Resolve, 0),
SLOT_METHOD("Set", Slot_Unimplemented, 0),
SLOT_METHOD("-append", Slot_Append, PUBLIC_METHOD),
SLOT_METHOD("-appendifnew", Slot_AppendNew, PUBLIC_METHOD),
SLOT_METHOD("-clear", Slot_Clear, PUBLIC_METHOD),
SLOT_METHOD("-prepend", Slot_Prepend, PUBLIC_METHOD),
SLOT_METHOD("-remove", Slot_Remove, PUBLIC_METHOD),
SLOT_METHOD("-set", Slot_Set, PUBLIC_METHOD),
SLOT_METHOD("unknown", Slot_Unknown, 0),
{NULL, 0, {0, 0, 0, 0, 0}}
};
/*
* How to build the in-namespace name of a private variable. This is a pattern
* used with Tcl_ObjPrintf().
*/
#define PRIVATE_VARIABLE_PATTERN "%d : %s"
|
| ︙ | ︙ | |||
2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 |
}
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOODefineMethodObjCmd --
*
* Implementation of the "method" subcommand of the "oo::define" and
* "oo::objdefine" commands.
*
* ----------------------------------------------------------------------
*/
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 |
}
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOODefineInitialiseObjCmd --
*
* Implementation of the "initialise" subcommand of the "oo::define"
* command.
*
* ----------------------------------------------------------------------
*/
int
TclOODefineInitialiseObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
{
Tcl_Object object;
Tcl_Obj *lambdaWords[3], *applyArgs[2];
int result;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "body");
return TCL_ERROR;
}
/* Build the lambda */
object = TclOOGetDefineCmdContext(interp);
if (object == NULL) {
return TCL_ERROR;
}
lambdaWords[0] = Tcl_NewObj();
lambdaWords[1] = objv[1];
lambdaWords[2] = TclNewNamespaceObj(Tcl_GetObjectNamespace(object));
/* Delegate to [apply] to run it */
applyArgs[0] = Tcl_NewStringObj("apply", -1);
applyArgs[1] = Tcl_NewListObj(3, lambdaWords);
Tcl_IncrRefCount(applyArgs[0]);
Tcl_IncrRefCount(applyArgs[1]);
result = Tcl_ApplyObjCmd(NULL, interp, 2, applyArgs);
Tcl_DecrRefCount(applyArgs[0]);
Tcl_DecrRefCount(applyArgs[1]);
return result;
}
/*
* ----------------------------------------------------------------------
*
* TclOODefineMethodObjCmd --
*
* Implementation of the "method" subcommand of the "oo::define" and
* "oo::objdefine" commands.
*
* ----------------------------------------------------------------------
*/
|
| ︙ | ︙ | |||
2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 |
return TCL_ERROR;
}
} else {
if (TclOONewProcMethod(interp, oPtr->classPtr, isPublic, objv[1],
objv[objc - 2], objv[objc - 1], NULL) == NULL) {
return TCL_ERROR;
}
}
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 |
return TCL_ERROR;
}
} else {
if (TclOONewProcMethod(interp, oPtr->classPtr, isPublic, objv[1],
objv[objc - 2], objv[objc - 1], NULL) == NULL) {
return TCL_ERROR;
}
}
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOODefineClassMethodObjCmd --
*
* Implementation of the "classmethod" subcommand of the "oo::define"
* command. Defines a class method. See define(n) for details.
*
* ----------------------------------------------------------------------
*/
int
TclOODefineClassMethodObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
{
Class *clsPtr;
int isPublic;
Tcl_Obj *forwardArgs[2], *prefixObj;
Method *mPtr;
if (objc != 2 && objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv, "name ?args body?");
return TCL_ERROR;
}
clsPtr = TclOOGetClassDefineCmdContext(interp);
if (!clsPtr) {
return TCL_ERROR;
}
isPublic = Tcl_StringMatch(TclGetString(objv[1]), PUBLIC_PATTERN)
? PUBLIC_METHOD : 0;
/*
* Create the method on the delegate class if the caller gave arguments
* and body.
*/
if (objc == 4) {
Tcl_Obj *delegateName = Tcl_ObjPrintf("%s:: oo ::delegate",
clsPtr->thisPtr->namespacePtr->fullName);
Class *delegatePtr = TclOOGetClassFromObj(interp, delegateName);
Tcl_DecrRefCount(delegateName);
if (!delegatePtr) {
return TCL_ERROR;
}
if (IsPrivateDefine(interp)) {
isPublic = 0;
}
if (TclOONewProcMethod(interp, delegatePtr, isPublic, objv[1],
objv[2], objv[3], NULL) == NULL) {
return TCL_ERROR;
}
}
/* Make the connection to the delegate by forwarding */
if (IsPrivateDefine(interp)) {
isPublic = TRUE_PRIVATE_METHOD;
}
forwardArgs[0] = Tcl_NewStringObj("myclass", -1);
forwardArgs[1] = objv[1];
prefixObj = Tcl_NewListObj(2, forwardArgs);
mPtr = TclOONewForwardMethod(interp, clsPtr, isPublic, objv[1], prefixObj);
if (mPtr == NULL) {
Tcl_DecrRefCount(prefixObj);
return TCL_ERROR;
}
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
2346 2347 2348 2349 2350 2351 2352 |
* ----------------------------------------------------------------------
*/
int
TclOODefineSlots(
Foundation *fPtr)
{
| < < | > > | > | | > > > | | | < | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > | > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > | > > | > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 |
* ----------------------------------------------------------------------
*/
int
TclOODefineSlots(
Foundation *fPtr)
{
Tcl_Interp *interp = fPtr->interp;
Tcl_Object object = Tcl_NewObjectInstance(interp, (Tcl_Class)
fPtr->classCls, "::oo::Slot", NULL, TCL_INDEX_NONE, NULL, 0);
Tcl_Class slotCls;
const DeclaredSlotMethod *smPtr;
const DeclaredSlot *slotPtr;
if (object == NULL) {
return TCL_ERROR;
}
slotCls = (Tcl_Class) ((Object *) object)->classPtr;
if (slotCls == NULL) {
return TCL_ERROR;
}
for (smPtr = slotMethods; smPtr->name; smPtr++) {
Tcl_Obj *name = Tcl_NewStringObj(smPtr->name, -1);
Tcl_NewMethod(interp, slotCls, name, smPtr->flags,
&smPtr->implType, NULL);
Tcl_BounceRefCount(name);
}
for (slotPtr = slots ; slotPtr->name ; slotPtr++) {
Tcl_Object slotObject = Tcl_NewObjectInstance(interp,
slotCls, slotPtr->name, NULL, TCL_INDEX_NONE, NULL, 0);
if (slotObject == NULL) {
continue;
}
TclNewInstanceMethod(interp, slotObject, fPtr->slotGetName, 0,
&slotPtr->getterType, NULL);
TclNewInstanceMethod(interp, slotObject, fPtr->slotSetName, 0,
&slotPtr->setterType, NULL);
if (slotPtr->resolverType.callProc) {
TclNewInstanceMethod(interp, slotObject, fPtr->slotResolveName, 0,
&slotPtr->resolverType, NULL);
}
}
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* CallSlotGet, CallSlotSet, CallSlotResolve, ResolveAll --
*
* How to call the standard low-level methods of a slot.
* ResolveAll is the lifting of CallSlotResolve to work over a whole
* list of items.
*
* ----------------------------------------------------------------------
*/
/* Call [$slot Get] to retrieve the list of contents of the slot */
static inline Tcl_Obj *
CallSlotGet(
Tcl_Interp *interp,
Object *slot)
{
Tcl_Obj *getArgs[2];
int code;
getArgs[0] = slot->fPtr->myName;
getArgs[1] = slot->fPtr->slotGetName;
code = TclOOPrivateObjectCmd(slot, interp, 2, getArgs);
if (code != TCL_OK) {
return NULL;
}
return Tcl_GetObjResult(interp);
}
/* Call [$slot Set $list] to set the list of contents of the slot */
static inline int
CallSlotSet(
Tcl_Interp *interp,
Object *slot,
Tcl_Obj *list)
{
Tcl_Obj *setArgs[3];
setArgs[0] = slot->fPtr->myName;
setArgs[1] = slot->fPtr->slotSetName;
setArgs[2] = list;
return TclOOPrivateObjectCmd(slot, interp, 3, setArgs);
}
/* Call [$slot Resolve $item] to convert a slot item into canonical form */
static inline Tcl_Obj *
CallSlotResolve(
Tcl_Interp *interp,
Object *slot,
Tcl_Obj *item)
{
Tcl_Obj *resolveArgs[3];
int code;
resolveArgs[0] = slot->fPtr->myName;
resolveArgs[1] = slot->fPtr->slotResolveName;
resolveArgs[2] = item;
code = TclOOPrivateObjectCmd(slot, interp, 3, resolveArgs);
if (code != TCL_OK) {
return NULL;
}
return Tcl_GetObjResult(interp);
}
static inline Tcl_Obj *
ResolveAll(
Tcl_Interp *interp,
Object *slot,
int objc,
Tcl_Obj *const *objv)
{
Tcl_Obj **resolvedItems = (Tcl_Obj **) TclStackAlloc(interp,
sizeof(Tcl_Obj *) * objc);
Tcl_Obj *resolvedList;
int i;
for (i = 0; i < objc; i++) {
resolvedItems[i] = CallSlotResolve(interp, slot, objv[i]);
if (resolvedItems[i] == NULL) {
for (int j = 0; j < i; j++) {
Tcl_DecrRefCount(resolvedItems[j]);
}
TclStackFree(interp, (void *) resolvedItems);
return NULL;
}
Tcl_IncrRefCount(resolvedItems[i]);
Tcl_ResetResult(interp);
}
resolvedList = Tcl_NewListObj(objc, resolvedItems);
for (i = 0; i < objc; i++) {
TclDecrRefCount(resolvedItems[i]);
}
TclStackFree(interp, (void *) resolvedItems);
return resolvedList;
}
/*
* ----------------------------------------------------------------------
*
* Slot_Append --
*
* Implementation of the "-append" slot operation.
*
* ----------------------------------------------------------------------
*/
static int
Slot_Append(
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_ObjectContext context,
int objc,
Tcl_Obj *const *objv)
{
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
int skip = Tcl_ObjectContextSkippedArgs(context), code;
Tcl_Obj *resolved, *list;
if (skip == objc) {
return TCL_OK;
}
/* Resolve all values */
resolved = ResolveAll(interp, oPtr, objc - skip, objv + skip);
if (resolved == NULL) {
return TCL_ERROR;
}
/* Get slot contents; store in list */
list = CallSlotGet(interp, oPtr);
if (list == NULL) {
Tcl_DecrRefCount(resolved);
return TCL_ERROR;
}
Tcl_IncrRefCount(list);
Tcl_ResetResult(interp);
/* Append */
if (Tcl_IsShared(list)) {
Tcl_Obj *dup = Tcl_DuplicateObj(list);
Tcl_IncrRefCount(dup);
Tcl_DecrRefCount(list);
list = dup;
}
if (Tcl_ListObjAppendList(interp, list, resolved) != TCL_OK) {
Tcl_DecrRefCount(list);
Tcl_DecrRefCount(resolved);
return TCL_ERROR;
}
Tcl_DecrRefCount(resolved);
/* Set slot contents */
code = CallSlotSet(interp, oPtr, list);
Tcl_DecrRefCount(list);
return code;
}
/*
* ----------------------------------------------------------------------
*
* Slot_AppendNew --
*
* Implementation of the "-appendifnew" slot operation.
*
* ----------------------------------------------------------------------
*/
static int
Slot_AppendNew(
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_ObjectContext context,
int objc,
Tcl_Obj *const *objv)
{
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
int skip = Tcl_ObjectContextSkippedArgs(context), code, isNew;
Tcl_Obj *resolved, *list, **listv;
Tcl_Size listc, i;
Tcl_HashTable unique;
if (skip == objc) {
return TCL_OK;
}
/* Resolve all values */
resolved = ResolveAll(interp, oPtr, objc - skip, objv + skip);
if (resolved == NULL) {
return TCL_ERROR;
}
/* Get slot contents; store in list */
list = CallSlotGet(interp, oPtr);
if (list == NULL) {
Tcl_DecrRefCount(resolved);
return TCL_ERROR;
}
Tcl_IncrRefCount(list);
Tcl_ResetResult(interp);
/* Prepare a set of items in the list to set */
if (TclListObjGetElements(interp, list, &listc, &listv) != TCL_OK) {
Tcl_DecrRefCount(list);
Tcl_DecrRefCount(resolved);
return TCL_ERROR;
}
Tcl_InitObjHashTable(&unique);
for (i=0 ; i<listc; i++) {
Tcl_CreateHashEntry(&unique, listv[i], &isNew);
}
/* Append the new items if they're not already there */
if (Tcl_IsShared(list)) {
Tcl_Obj *dup = Tcl_DuplicateObj(list);
Tcl_IncrRefCount(dup);
Tcl_DecrRefCount(list);
list = dup;
}
TclListObjGetElements(NULL, resolved, &listc, &listv);
for (i=0 ; i<listc; i++) {
Tcl_CreateHashEntry(&unique, listv[i], &isNew);
if (isNew) {
Tcl_ListObjAppendElement(interp, list, listv[i]);
}
}
Tcl_DecrRefCount(resolved);
Tcl_DeleteHashTable(&unique);
/* Set slot contents */
code = CallSlotSet(interp, oPtr, list);
Tcl_DecrRefCount(list);
return code;
}
/*
* ----------------------------------------------------------------------
*
* Slot_Clear --
*
* Implementation of the "-clear" slot operation.
*
* ----------------------------------------------------------------------
*/
static int
Slot_Clear(
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_ObjectContext context,
int objc,
Tcl_Obj *const *objv)
{
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
int skip = Tcl_ObjectContextSkippedArgs(context), code;
Tcl_Obj *list;
if (skip != objc) {
Tcl_WrongNumArgs(interp, skip, objv, NULL);
return TCL_ERROR;
}
list = Tcl_NewObj();
Tcl_IncrRefCount(list);
code = CallSlotSet(interp, oPtr, list);
Tcl_DecrRefCount(list);
return code;
}
/*
* ----------------------------------------------------------------------
*
* Slot_Prepend --
*
* Implementation of the "-prepend" slot operation.
*
* ----------------------------------------------------------------------
*/
static int
Slot_Prepend(
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_ObjectContext context,
int objc,
Tcl_Obj *const *objv)
{
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
int skip = Tcl_ObjectContextSkippedArgs(context), code;
Tcl_Obj *list, *oldList;
if (skip == objc) {
return TCL_OK;
}
/* Resolve all values */
list = ResolveAll(interp, oPtr, objc - skip, objv + skip);
if (list == NULL) {
return TCL_ERROR;
}
Tcl_IncrRefCount(list);
/* Get slot contents and append to list */
oldList = CallSlotGet(interp, oPtr);
if (oldList == NULL) {
Tcl_DecrRefCount(list);
return TCL_ERROR;
}
Tcl_ListObjAppendList(NULL, list, oldList);
Tcl_ResetResult(interp);
/* Set slot contents */
code = CallSlotSet(interp, oPtr, list);
Tcl_DecrRefCount(list);
return code;
}
/*
* ----------------------------------------------------------------------
*
* Slot_Remove --
*
* Implementation of the "-remove" slot operation.
*
* ----------------------------------------------------------------------
*/
static int
Slot_Remove(
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_ObjectContext context,
int objc,
Tcl_Obj *const *objv)
{
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
int skip = Tcl_ObjectContextSkippedArgs(context), code, isNew;
Tcl_Size listc, i;
Tcl_Obj *resolved, *oldList, *newList, **listv;
Tcl_HashTable removeSet;
if (skip == objc) {
return TCL_OK;
}
/* Resolve all values */
resolved = ResolveAll(interp, oPtr, objc - skip, objv + skip);
if (resolved == NULL) {
return TCL_ERROR;
}
/* Get slot contents; store in list */
oldList = CallSlotGet(interp, oPtr);
if (oldList == NULL) {
Tcl_DecrRefCount(resolved);
return TCL_ERROR;
}
Tcl_IncrRefCount(oldList);
Tcl_ResetResult(interp);
/* Prepare a set of items in the list to remove */
TclListObjGetElements(NULL, resolved, &listc, &listv);
Tcl_InitObjHashTable(&removeSet);
for (i=0 ; i<listc; i++) {
Tcl_CreateHashEntry(&removeSet, listv[i], &isNew);
}
Tcl_DecrRefCount(resolved);
/* Append the new items from the old items if they're not in the remove set */
if (TclListObjGetElements(interp, oldList, &listc, &listv) != TCL_OK) {
Tcl_DecrRefCount(oldList);
Tcl_DeleteHashTable(&removeSet);
return TCL_ERROR;
}
newList = Tcl_NewObj();
for (i=0 ; i<listc; i++) {
if (Tcl_FindHashEntry(&removeSet, listv[i]) == NULL) {
Tcl_ListObjAppendElement(NULL, newList, listv[i]);
}
}
Tcl_DecrRefCount(oldList);
Tcl_DeleteHashTable(&removeSet);
/* Set slot contents */
Tcl_IncrRefCount(newList);
code = CallSlotSet(interp, oPtr, newList);
Tcl_DecrRefCount(newList);
return code;
}
/*
* ----------------------------------------------------------------------
*
* Slot_Resolve --
*
* Default implementation of the "Resolve" slot accessor. Just returns
* its argument unchanged; particular slots may override.
*
* ----------------------------------------------------------------------
*/
static int
Slot_Resolve(
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_ObjectContext context,
int objc,
Tcl_Obj *const *objv)
{
int skip = Tcl_ObjectContextSkippedArgs(context);
if (skip + 1 != objc) {
Tcl_WrongNumArgs(interp, skip, objv, "list");
return TCL_ERROR;
}
Tcl_SetObjResult(interp, objv[objc - 1]);
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* Slot_Set --
*
* Implementation of the "-set" slot operation.
*
* ----------------------------------------------------------------------
*/
static int
Slot_Set(
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_ObjectContext context,
int objc,
Tcl_Obj *const *objv)
{
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
int skip = Tcl_ObjectContextSkippedArgs(context), code;
Tcl_Obj *list;
/* Resolve all values */
if (skip == objc) {
list = Tcl_NewObj();
} else {
list = ResolveAll(interp, oPtr, objc - skip, objv + skip);
if (list == NULL) {
return TCL_ERROR;
}
}
Tcl_IncrRefCount(list);
/* Set slot contents */
code = CallSlotSet(interp, oPtr, list);
Tcl_DecrRefCount(list);
return code;
}
/*
* ----------------------------------------------------------------------
*
* Slot_Unimplemented --
*
* Default implementation of the "Get" and "Set" slot accessors. Just
* returns an error; actual slots must override.
*
* ----------------------------------------------------------------------
*/
static int
Slot_Unimplemented(
TCL_UNUSED(void *),
Tcl_Interp *interp,
TCL_UNUSED(Tcl_ObjectContext),
TCL_UNUSED(int),
TCL_UNUSED(Tcl_Obj *const *))
{
Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1));
OO_ERROR(interp, ABSTRACT_SLOT);
return TCL_ERROR;
}
/*
* ----------------------------------------------------------------------
*
* Slot_Unknown --
*
* Unknown method name handler for slots. Delegates to the default slot
* operation (--default-operation forwarded method) unless the first
* argument starts with a dash.
*
* ----------------------------------------------------------------------
*/
static int
Slot_Unknown(
TCL_UNUSED(void *),
Tcl_Interp *interp,
Tcl_ObjectContext context,
int objc,
Tcl_Obj *const *objv)
{
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
int skip = Tcl_ObjectContextSkippedArgs(context), code;
if (skip >= objc) {
Tcl_Obj *args[2];
args[0] = oPtr->fPtr->myName;
args[1] = oPtr->fPtr->slotDefOpName;
return TclOOPrivateObjectCmd(oPtr, interp, 2, args);
} else if (TclGetString(objv[skip])[0] != '-') {
Tcl_Obj **args = (Tcl_Obj **) TclStackAlloc(interp,
sizeof(Tcl_Obj *) * (objc - skip + 2));
args[0] = oPtr->fPtr->myName;
args[1] = oPtr->fPtr->slotDefOpName;
memcpy(args+2, objv+skip, sizeof(Tcl_Obj*) * (objc - skip));
code = TclOOPrivateObjectCmd(oPtr, interp, objc - skip + 2, args);
TclStackFree(interp, args);
return code;
}
return TclNRObjectContextInvokeNext(interp, context, objc, objv, skip);
}
/*
* ----------------------------------------------------------------------
*
* ClassFilter_Get, ClassFilter_Set --
*
|
| ︙ | ︙ |
Changes to generic/tclOOInt.h.
| ︙ | ︙ | |||
251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
/* Configurations for the variable resolver
* used inside methods. */
Tcl_Command myclassCommand; /* Reference to this object's class dispatcher
* command. */
PropertyStorage properties; /* Information relating to the lists of
* properties that this object *claims* to
* support. */
};
enum ObjectFlags {
OBJECT_DESTRUCTING = 1, /* Indicates that an object is being or has
* been destroyed */
DESTRUCTOR_CALLED = 2, /* Indicates that evaluation of destructor
* script for the object has began */
| > | 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
/* Configurations for the variable resolver
* used inside methods. */
Tcl_Command myclassCommand; /* Reference to this object's class dispatcher
* command. */
PropertyStorage properties; /* Information relating to the lists of
* properties that this object *claims* to
* support. */
Tcl_Obj *linkedCmdsList; /* List of names of linked commands. */
};
enum ObjectFlags {
OBJECT_DESTRUCTING = 1, /* Indicates that an object is being or has
* been destroyed */
DESTRUCTOR_CALLED = 2, /* Indicates that evaluation of destructor
* script for the object has began */
|
| ︙ | ︙ | |||
401 402 403 404 405 406 407 |
* constructor. */
Tcl_Obj *destructorName; /* Shared object containing the "name" of a
* destructor. */
Tcl_Obj *clonedName; /* Shared object containing the name of a
* "<cloned>" pseudo-constructor. */
Tcl_Obj *defineName; /* Fully qualified name of oo::define. */
Tcl_Obj *myName; /* The "my" shared object. */
| | | > > | 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 |
* constructor. */
Tcl_Obj *destructorName; /* Shared object containing the "name" of a
* destructor. */
Tcl_Obj *clonedName; /* Shared object containing the name of a
* "<cloned>" pseudo-constructor. */
Tcl_Obj *defineName; /* Fully qualified name of oo::define. */
Tcl_Obj *myName; /* The "my" shared object. */
Tcl_Obj *slotGetName; /* The "Get" name used by slots. */
Tcl_Obj *slotSetName; /* The "Set" name used by slots. */
Tcl_Obj *slotResolveName; /* The "Resolve" name used by slots. */
Tcl_Obj *slotDefOpName; /* The "--default-operation" name used by slots. */
};
/*
* The number of MInvoke records in the CallChain before we allocate
* separately.
*/
#define CALL_CHAIN_STATIC_SIZE 4
|
| ︙ | ︙ | |||
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 | * Commands relating to OO support. *---------------------------------------------------------------- */ MODULE_SCOPE int TclOOInit(Tcl_Interp *interp); MODULE_SCOPE Tcl_ObjCmdProc TclOODefineObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOOObjDefObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineConstructorObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineDefnNsObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineDeleteMethodObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineDestructorObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineExportObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineForwardObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineMethodObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineRenameMethodObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineUnexportObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineClassObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineSelfObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineObjSelfObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefinePrivateObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefinePropertyCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOOUnknownDefinition; MODULE_SCOPE Tcl_ObjCmdProc TclOOCopyObjectCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOONextObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOONextToObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOOSelfObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOOInfoObjectPropCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOOInfoClassPropCmd; /* | > > > > > > | 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 | * Commands relating to OO support. *---------------------------------------------------------------- */ MODULE_SCOPE int TclOOInit(Tcl_Interp *interp); MODULE_SCOPE Tcl_ObjCmdProc TclOODefineObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOOObjDefObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineClassMethodObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineConstructorObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineDefnNsObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineDeleteMethodObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineDestructorObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineExportObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineForwardObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineInitialiseObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineMethodObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineRenameMethodObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineUnexportObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineClassObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineSelfObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefineObjSelfObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefinePrivateObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODefinePropertyCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOOUnknownDefinition; MODULE_SCOPE Tcl_ObjCmdProc TclOOCallbackObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOOClassVariableObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOOCopyObjectCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOODelegateNameObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOOLinkObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOONextObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOONextToObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOOSelfObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOOInfoObjectPropCmd; MODULE_SCOPE Tcl_ObjCmdProc TclOOInfoClassPropCmd; /* |
| ︙ | ︙ | |||
604 605 606 607 608 609 610 611 612 613 614 615 616 617 | Tcl_Var *aryPtr); MODULE_SCOPE int TclNRObjectContextInvokeNext(Tcl_Interp *interp, Tcl_ObjectContext context, Tcl_Size objc, Tcl_Obj *const *objv, Tcl_Size skip); MODULE_SCOPE void TclOODefineBasicMethods(Class *clsPtr, const DeclaredClassMethod *dcm); MODULE_SCOPE Tcl_Obj * TclOOObjectName(Tcl_Interp *interp, Object *oPtr); MODULE_SCOPE void TclOOReleaseClassContents(Tcl_Interp *interp, Object *oPtr); MODULE_SCOPE int TclOORemoveFromInstances(Object *oPtr, Class *clsPtr); MODULE_SCOPE int TclOORemoveFromMixins(Class *mixinPtr, Object *oPtr); MODULE_SCOPE int TclOORemoveFromMixinSubs(Class *subPtr, Class *mixinPtr); MODULE_SCOPE int TclOORemoveFromSubclasses(Class *subPtr, | > | 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 | Tcl_Var *aryPtr); MODULE_SCOPE int TclNRObjectContextInvokeNext(Tcl_Interp *interp, Tcl_ObjectContext context, Tcl_Size objc, Tcl_Obj *const *objv, Tcl_Size skip); MODULE_SCOPE void TclOODefineBasicMethods(Class *clsPtr, const DeclaredClassMethod *dcm); MODULE_SCOPE Tcl_Obj * TclOOObjectName(Tcl_Interp *interp, Object *oPtr); MODULE_SCOPE Tcl_Obj * TclOOObjectMyName(Tcl_Interp *interp, Object *oPtr); MODULE_SCOPE void TclOOReleaseClassContents(Tcl_Interp *interp, Object *oPtr); MODULE_SCOPE int TclOORemoveFromInstances(Object *oPtr, Class *clsPtr); MODULE_SCOPE int TclOORemoveFromMixins(Class *mixinPtr, Object *oPtr); MODULE_SCOPE int TclOORemoveFromMixinSubs(Class *subPtr, Class *mixinPtr); MODULE_SCOPE int TclOORemoveFromSubclasses(Class *subPtr, |
| ︙ | ︙ |
Changes to generic/tclOOScript.h.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 |
* contains the commented version of everything; *this* file is automatically
* generated.
*/
static const char *tclOOSetupScript =
/* !BEGIN!: Do not edit below this line. */
"::namespace eval ::oo {\n"
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < | < | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
* contains the commented version of everything; *this* file is automatically
* generated.
*/
static const char *tclOOSetupScript =
/* !BEGIN!: Do not edit below this line. */
"::namespace eval ::oo {\n"
"\tdefine Slot forward --default-operation my -append\n"
"\tdefine Slot unexport destroy\n"
"\tobjdefine define::superclass forward --default-operation my -set\n"
"\tobjdefine define::mixin forward --default-operation my -set\n"
"\tobjdefine objdefine::mixin forward --default-operation my -set\n"
"\tdefine object method <cloned> -unexport {originObject} {\n"
"\t\tforeach p [info procs [info object namespace $originObject]::*] {\n"
"\t\t\tset args [info args $p]\n"
"\t\t\tset idx -1\n"
|
| ︙ | ︙ | |||
226 227 228 229 230 231 232 233 |
"\t\t\t\t} else {\n"
"\t\t\t\t\tset vNew $vOrigin\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t}\n"
"\t}\n"
"\tdefine class method <cloned> -unexport {originObject} {\n"
"\t\tnext $originObject\n"
| > | > > > > > > > > > > > | | | | | | | | | | | | | | | < < > | | | < | < | | | | | | | | | | | | < | | | | | | | < | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
"\t\t\t\t} else {\n"
"\t\t\t\t\tset vNew $vOrigin\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t}\n"
"\t}\n"
"\tdefine class method <cloned> -unexport {originObject} {\n"
"\t\tset targetObject [self]\n"
"\t\tnext $originObject\n"
"\t\tset originDelegate [::oo::DelegateName $originObject]\n"
"\t\tset targetDelegate [::oo::DelegateName $targetObject]\n"
"\t\tif {\n"
"\t\t\t[info object isa class $originDelegate]\n"
"\t\t\t&& ![info object isa class $targetDelegate]\n"
"\t\t} then {\n"
"\t\t\t::oo::copy $originDelegate $targetDelegate\n"
"\t\t\t::oo::objdefine $targetObject mixin -set \\\n"
"\t\t\t\t{*}[lmap c [info object mixin $targetObject] {\n"
"\t\t\t\t\tif {$c eq $originDelegate} {set targetDelegate} {set c}\n"
"\t\t\t\t}]\n"
"\t\t}\n"
"\t}\n"
"\tclass create singleton\n"
"\tdefine singleton superclass -set class\n"
"\tdefine singleton variable -set object\n"
"\tdefine singleton unexport create createWithNamespace\n"
"\tdefine singleton method new args {\n"
"\t\tif {![info exists object] || ![info object isa object $object]} {\n"
"\t\t\tset object [next {*}$args]\n"
"\t\t\t::oo::objdefine $object {\n"
"\t\t\t\tmethod destroy {} {\n"
"\t\t\t\t\treturn -code error -errorcode {TCL OO SINGLETON} \\\n"
"\t\t\t\t\t\t\"may not destroy a singleton object\"\n"
"\t\t\t\t}\n"
"\t\t\t\tmethod <cloned> -unexport {originObject} {\n"
"\t\t\t\t\treturn -code error -errorcode {TCL OO SINGLETON} \\\n"
"\t\t\t\t\t\t\"may not clone a singleton object\"\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t}\n"
"\t\treturn $object\n"
"\t}\n"
"\tclass create abstract\n"
"\tdefine abstract superclass -set class\n"
"\tdefine abstract unexport create createWithNamespace new\n"
"\tnamespace eval configuresupport::configurableclass {\n"
"\t\t::proc properties args {::tailcall property {*}$args}\n"
"\t\t::namespace path ::oo::define\n"
"\t\t::namespace export property\n"
"\t}\n"
"\tnamespace eval configuresupport::configurableobject {\n"
"\t\t::proc properties args {::tailcall property {*}$args}\n"
"\t\t::namespace path ::oo::objdefine\n"
"\t\t::namespace export property\n"
"\t}\n"
"\tdefine configuresupport::configurable {\n"
"\t\tdefinitionnamespace -instance configuresupport::configurableobject\n"
"\t\tdefinitionnamespace -class configuresupport::configurableclass\n"
"\t}\n"
"\tclass create configurable\n"
"\tdefine configurable superclass -set class\n"
"\tdefine configurable constructor {{definitionScript \"\"}} {\n"
"\t\too::define [self] {mixin -append ::oo::configuresupport::configurable}\n"
"\t\tnext $definitionScript\n"
"\t}\n"
"\tdefine configurable definitionnamespace -class configuresupport::configurableclass\n"
"}\n"
/* !END!: Do not edit above this line. */
;
#endif /* TCL_OO_SCRIPT_H */
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
|
Changes to tests/ooUtil.test.
| ︙ | ︙ | |||
362 363 364 365 366 367 368 |
lappend ::result {*}$args
}
set result {}
} -body {
trace add execution oo::define::initialise enter appendToResultVar
oo::class create ::cls {
superclass parent
| | | < < < < < < | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
lappend ::result {*}$args
}
set result {}
} -body {
trace add execution oo::define::initialise enter appendToResultVar
oo::class create ::cls {
superclass parent
initialise {proc xyzzy {} {}}
}
return $result
} -cleanup {
catch {
trace remove execution oo::define::initialise enter appendToResultVar
}
rename ::appendToResultVar {}
parent destroy
} -result {{initialise {proc xyzzy {} {}}} enter}
test ooUtil-4.1 {TIP 478: singleton} -setup {
oo::class create parent
} -body {
oo::singleton create xyz {
superclass parent
}
|
| ︙ | ︙ |
Changes to tools/tclOOScript.tcl.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 |
# Copyright © 2013 Andreas Kupries
# Copyright © 2017 Gerald Lester
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
::namespace eval ::oo {
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# Copyright © 2013 Andreas Kupries
# Copyright © 2017 Gerald Lester
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
::namespace eval ::oo {
# ----------------------------------------------------------------------
#
# Slot --
#
# The class of slot operations, which are basically lists at the low
# level of TclOO; this provides a more consistent interface to them.
#
# ----------------------------------------------------------------------
# ------------------------------------------------------------------
#
# Slot --default-operation --
#
# If a slot can't figure out what method to call directly, it
# uses --default-operation.
#
# ------------------------------------------------------------------
define Slot forward --default-operation my -append
# Hide destroy
define Slot unexport destroy
# Set the default operation differently for these slots
objdefine define::superclass forward --default-operation my -set
objdefine define::mixin forward --default-operation my -set
objdefine objdefine::mixin forward --default-operation my -set
# ----------------------------------------------------------------------
|
| ︙ | ︙ | |||
404 405 406 407 408 409 410 411 412 |
# oo::class <cloned> --
#
# Handler for cloning classes, which fixes up the delegates.
#
# ----------------------------------------------------------------------
define class method <cloned> -unexport {originObject} {
next $originObject
# Rebuild the class inheritance delegation class
| > | > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | < | | | < | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# oo::class <cloned> --
#
# Handler for cloning classes, which fixes up the delegates.
#
# ----------------------------------------------------------------------
define class method <cloned> -unexport {originObject} {
set targetObject [self]
next $originObject
# Rebuild the class inheritance delegation class
set originDelegate [::oo::DelegateName $originObject]
set targetDelegate [::oo::DelegateName $targetObject]
if {
[info object isa class $originDelegate]
&& ![info object isa class $targetDelegate]
} then {
::oo::copy $originDelegate $targetDelegate
::oo::objdefine $targetObject mixin -set \
{*}[lmap c [info object mixin $targetObject] {
if {$c eq $originDelegate} {set targetDelegate} {set c}
}]
}
}
# ----------------------------------------------------------------------
#
# oo::singleton --
#
# A metaclass that is used to make classes that only permit one instance
# of them to exist. See singleton(n).
#
# ----------------------------------------------------------------------
class create singleton
define singleton superclass -set class
define singleton variable -set object
define singleton unexport create createWithNamespace
define singleton method new args {
if {![info exists object] || ![info object isa object $object]} {
set object [next {*}$args]
::oo::objdefine $object {
method destroy {} {
return -code error -errorcode {TCL OO SINGLETON} \
"may not destroy a singleton object"
}
method <cloned> -unexport {originObject} {
return -code error -errorcode {TCL OO SINGLETON} \
"may not clone a singleton object"
}
}
}
return $object
}
# ----------------------------------------------------------------------
#
# oo::abstract --
#
# A metaclass that is used to make classes that can't be directly
# instantiated. See abstract(n).
#
# ----------------------------------------------------------------------
class create abstract
define abstract superclass -set class
define abstract unexport create createWithNamespace new
# ----------------------------------------------------------------------
#
# oo::configuresupport --
#
# Namespace that holds all the implementation details of TIP #558.
# Also includes the commands:
|
| ︙ | ︙ | |||
479 480 481 482 483 484 485 |
# These cause very fast basic implementation methods for a property
# following the standard model of property implementation naming.
# Property schemes that use other models (such as to be more Tk-like)
# should not use these (or the oo::cconfigurable metaclass).
#
# ----------------------------------------------------------------------
| < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | < | | | | | < | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# These cause very fast basic implementation methods for a property
# following the standard model of property implementation naming.
# Property schemes that use other models (such as to be more Tk-like)
# should not use these (or the oo::cconfigurable metaclass).
#
# ----------------------------------------------------------------------
# ------------------------------------------------------------------
#
# oo::configuresupport::configurableclass,
# oo::configuresupport::configurableobject --
#
# Namespaces used as implementation vectors for oo::define and
# oo::objdefine when the class/instance is configurable.
# Note that these also contain commands implemented in C,
# especially the [property] definition command.
#
# ------------------------------------------------------------------
namespace eval configuresupport::configurableclass {
# Plural alias just in case; deliberately NOT documented!
::proc properties args {::tailcall property {*}$args}
::namespace path ::oo::define
::namespace export property
}
namespace eval configuresupport::configurableobject {
# Plural alias just in case; deliberately NOT documented!
::proc properties args {::tailcall property {*}$args}
::namespace path ::oo::objdefine
::namespace export property
}
# ------------------------------------------------------------------
#
# oo::configuresupport::configurable --
#
# The class that contains the implementation of the actual
# 'configure' method (mixed into actually configurable classes).
# The 'configure' method is in tclOOBasic.c.
#
# ------------------------------------------------------------------
define configuresupport::configurable {
definitionnamespace -instance configuresupport::configurableobject
definitionnamespace -class configuresupport::configurableclass
}
# ----------------------------------------------------------------------
#
# oo::configurable --
#
# A metaclass that is used to make classes that can be configured in
# their creation phase (and later too). All the metaclass itself does is
# arrange for the class created to have a 'configure' method and for
# oo::define and oo::objdefine (on the class and its instances) to have
# a property definition for setting things up for 'configure'.
#
# ----------------------------------------------------------------------
class create configurable
define configurable superclass -set class
define configurable constructor {{definitionScript ""}} {
::oo::define [self] {mixin -append ::oo::configuresupport::configurable}
next $definitionScript
}
define configurable definitionnamespace -class configuresupport::configurableclass
}
# Local Variables:
# mode: tcl
# c-basic-offset: 4
# fill-column: 78
# End:
|