4
* This file contains code to create and manage methods.
6
* Copyright (c) 2007 by Arnulf P. Wiedemann
8
* See the file "license.terms" for information on usage and redistribution of
9
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
17
Itcl_GetCurrentCallbackPtr(
20
return TOP_CB(interp);
28
return TclNRRunCallbacks(interp, TCL_OK, rootPtr);
37
Tcl_Namespace *nsPtr = data[0];
38
TclOO_PostCallProc *postCallProc = (TclOO_PostCallProc *)data[1];
39
ClientData clientData = data[2];
42
* Give the post-call callback a chance to do some cleanup. Note that at
43
* this point the call frame itself is invalid; it's already been popped.
46
return postCallProc(clientData, interp, NULL, nsPtr, result);
55
Command *cmdPtr = data[0];
56
Proc *procPtr = data[1];
59
procPtr->cmdPtr = NULL;
65
Tcl_InvokeClassProcedureMethod(
67
Tcl_Obj *namePtr, /* name of the method */
68
Tcl_Namespace *nsPtr, /* namespace for calling method */
69
ProcedureMethod *pmPtr, /* method type specific data */
70
int objc, /* Number of arguments. */
71
Tcl_Obj *const *objv) /* Arguments as actually seen. */
73
Proc *procPtr = pmPtr->procPtr;
74
CallFrame *framePtr = NULL;
75
CallFrame **framePtrPtr1 = &framePtr;
76
Tcl_CallFrame **framePtrPtr = (Tcl_CallFrame **)framePtrPtr1;
79
if (procPtr->cmdPtr == NULL) {
80
Command *cmdPtr = ckalloc(sizeof(Command));
82
memset(cmdPtr, 0, sizeof(Command));
83
cmdPtr->nsPtr = (Namespace *) nsPtr;
84
cmdPtr->clientData = NULL;
85
procPtr->cmdPtr = cmdPtr;
86
Tcl_NRAddCallback(interp, FreeCommand, cmdPtr, procPtr, NULL, NULL);
89
result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr,
90
(Namespace *) nsPtr, "body of method", Tcl_GetString(namePtr));
91
if (result != TCL_OK) {
95
* Make the stack frame and fill it out with information about this call.
96
* This operation may fail.
100
result = TclPushStackFrame(interp, framePtrPtr, nsPtr, FRAME_IS_PROC);
101
if (result != TCL_OK) {
105
framePtr->clientData = NULL;
106
framePtr->objc = objc;
107
framePtr->objv = objv;
108
framePtr->procPtr = procPtr;
111
* Give the pre-call callback a chance to do some setup and, possibly,
115
if (pmPtr->preCallProc != NULL) {
118
result = pmPtr->preCallProc(pmPtr->clientData, interp, NULL,
119
(Tcl_CallFrame *) framePtr, &isFinished);
120
if (isFinished || result != TCL_OK) {
121
Tcl_PopCallFrame(interp);
122
TclStackFree(interp, framePtr);
128
* Now invoke the body of the method. Note that we need to take special
129
* action when doing unknown processing to ensure that the missing method
130
* name is passed as an argument.
133
if (pmPtr->postCallProc) {
134
Tcl_NRAddCallback(interp, CallFinalizePMCall, nsPtr,
135
(Tcl_NRPostProc *)pmPtr->postCallProc, pmPtr->clientData, NULL);
137
return TclNRInterpProcCore(interp, namePtr, 1, pmPtr->errProc);
144
Itcl_InvokeProcedureMethod(
145
ClientData clientData, /* Pointer to some per-method context. */
147
int objc, /* Number of arguments. */
148
Tcl_Obj *const *objv) /* Arguments as actually seen. */
150
Tcl_Namespace *nsPtr;
154
if (mPtr->declaringClassPtr == NULL) {
155
/* that is the case for typemethods */
156
nsPtr = mPtr->declaringObjectPtr->namespacePtr;
158
nsPtr = mPtr->declaringClassPtr->thisPtr->namespacePtr;
161
return Tcl_InvokeClassProcedureMethod(interp, mPtr->namePtr, nsPtr,
162
mPtr->clientData, objc, objv);
171
ProcedureMethod *pmPtr = data[0];
177
Itcl_InvokeEnsembleMethod(
179
Tcl_Namespace *nsPtr, /* namespace to call the method in */
180
Tcl_Obj *namePtr, /* name of the method */
182
int objc, /* Number of arguments. */
183
Tcl_Obj *const *objv) /* Arguments as actually seen. */
185
ProcedureMethod *pmPtr = ckalloc(sizeof(ProcedureMethod));
187
memset(pmPtr, 0, sizeof(ProcedureMethod));
188
pmPtr->version = TCLOO_PROCEDURE_METHOD_VERSION;
189
pmPtr->procPtr = (Proc *)procPtr;
190
pmPtr->flags = USE_DECLARER_NS;
192
Tcl_NRAddCallback(interp, FreeProcedureMethod, pmPtr, NULL, NULL, NULL);
193
return Tcl_InvokeClassProcedureMethod(interp, namePtr, nsPtr,
199
* ----------------------------------------------------------------------
201
* Itcl_PublicObjectCmd, Itcl_PrivateObjectCmd --
203
* Main entry point for object invokations. The Public* and Private*
204
* wrapper functions are just thin wrappers around the main ObjectCmd
205
* function that does call chain creation, management and invokation.
207
* ----------------------------------------------------------------------
211
Itcl_PublicObjectCmd(
212
ClientData clientData,
216
Tcl_Obj *const *objv)
218
Tcl_Object oPtr = (Tcl_Object)clientData;
221
result = TclOOInvokeObject(interp, oPtr, clsPtr, PUBLIC_METHOD,
227
* ----------------------------------------------------------------------
229
* Itcl_NewProcClassMethod --
231
* Create a new procedure-like method for a class for Itcl.
233
* ----------------------------------------------------------------------
237
Itcl_NewProcClassMethod(
238
Tcl_Interp *interp, /* The interpreter containing the class. */
239
Tcl_Class clsPtr, /* The class to modify. */
240
TclOO_PreCallProc *preCallPtr,
241
TclOO_PostCallProc *postCallPtr,
242
ProcErrorProc *errProc,
243
ClientData clientData,
244
Tcl_Obj *nameObj, /* The name of the method, which may be NULL;
245
* if so, up to caller to manage storage
246
* (e.g., because it is a constructor or
248
Tcl_Obj *argsObj, /* The formal argument list for the method,
249
* which may be NULL; if so, it is equivalent
250
* to an empty list. */
251
Tcl_Obj *bodyObj, /* The body of the method, which must not be
253
ClientData *clientData2)
257
result = TclOONewProcMethodEx(interp, clsPtr, preCallPtr, postCallPtr,
258
errProc, clientData, nameObj, argsObj, bodyObj,
259
PUBLIC_METHOD | USE_DECLARER_NS, clientData2);
264
* ----------------------------------------------------------------------
266
* Itcl_NewProcMethod --
268
* Create a new procedure-like method for an object for Itcl.
270
* ----------------------------------------------------------------------
275
Tcl_Interp *interp, /* The interpreter containing the object. */
276
Tcl_Object oPtr, /* The object to modify. */
277
TclOO_PreCallProc *preCallPtr,
278
TclOO_PostCallProc *postCallPtr,
279
ProcErrorProc *errProc,
280
ClientData clientData,
281
Tcl_Obj *nameObj, /* The name of the method, which must not be
283
Tcl_Obj *argsObj, /* The formal argument list for the method,
284
* which must not be NULL. */
285
Tcl_Obj *bodyObj, /* The body of the method, which must not be
287
ClientData *clientData2)
289
return TclOONewProcInstanceMethodEx(interp, oPtr, preCallPtr, postCallPtr,
290
errProc, clientData, nameObj, argsObj, bodyObj,
291
PUBLIC_METHOD | USE_DECLARER_NS, clientData2);
295
* ----------------------------------------------------------------------
297
* Itcl_NewForwardClassMethod --
299
* Create a new forwarded method for a class for Itcl.
301
* ----------------------------------------------------------------------
305
Itcl_NewForwardClassMethod(
312
return (Tcl_Method)TclOONewForwardMethod(interp, (Class *)clsPtr,
313
flags, nameObj, prefixObj);
318
Itcl_TclOOObjectName(
324
if (oPtr->cachedNameObj) {
325
return oPtr->cachedNameObj;
327
namePtr = Tcl_NewObj();
328
Tcl_GetCommandFullName(interp, oPtr->command, namePtr);
329
Tcl_IncrRefCount(namePtr);
330
oPtr->cachedNameObj = namePtr;
336
ClientData clientData,
339
Tcl_Obj *const *objv)
341
Interp *iPtr = (Interp *) interp;
342
CallFrame *framePtr = iPtr->varFramePtr;
343
CallContext *contextPtr;
345
if (!Itcl_IsMethodCallFrame(interp)) {
346
Tcl_AppendResult(interp, TclGetString(objv[0]),
347
" may only be called from inside a method", NULL);
351
contextPtr = framePtr->clientData;
354
Tcl_SetObjResult(interp, Itcl_TclOOObjectName(interp, contextPtr->oPtr));
361
Itcl_IsMethodCallFrame(
364
Interp *iPtr = (Interp *) interp;
365
CallFrame *framePtr = iPtr->varFramePtr;
366
if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
372
/* needed as work around for problem in Tcl 8.6.2 TclOO */
374
Itcl_IncrObjectRefCount(Tcl_Object ptr) {
375
Object * oPtr = (Object *) ptr;