Tcl Source Code

Check-in [8ef09a1e8a]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:more comments
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | mig-tailcall-cleanup
Files: files | file ages | folders
SHA1: 8ef09a1e8a1a6c7f6e7131ce3180136033180232
User & Date: msofer 2015-03-23 13:43:37
Context
2015-03-23
13:46
fix comments describing tailcall implementation check-in: 654bad187e user: msofer tags: trunk
13:43
more comments Closed-Leaf check-in: 8ef09a1e8a user: msofer tags: mig-tailcall-cleanup
02:11
updated, improved tailcall comments check-in: cf96e3ae67 user: msofer tags: mig-tailcall-cleanup
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclBasic.c.

8177
8178
8179
8180
8181
8182
8183

8184
8185
8186
8187
8188
8189
8190
8191
8192
 * The steps of the tailcall dance are as follows:
 *
 *   1. when [tailcall] is invoked, it stores the corresponding callback in
 *      the current CallFrame and returns TCL_RETURN
 *   2. when the CallFrame is popped, it calls TclSetTailcall to store the
 *      callback in the proper NRCommand callback - the spot where the command
 *      that pushed the CallFrame is completely cleaned up

 *   3. The NRCommand schedules the tailcall callback to run immediately after
 *      NRCommand returns
 *
 *   One delicate point is to properly define the NRCommand where the tailcall
 *   will execute. There are functions whose purpose is to help define the
 *   precise spot: TclMarkTailcall ("this is the spot") and TclSkipTailcall
 *   ("skip the next command: we are redirecting to it, tailcalls should run
 *   after WE return"), TclPushTailcallPoint (special for OO).
 */







>
|
<







8177
8178
8179
8180
8181
8182
8183
8184
8185

8186
8187
8188
8189
8190
8191
8192
 * The steps of the tailcall dance are as follows:
 *
 *   1. when [tailcall] is invoked, it stores the corresponding callback in
 *      the current CallFrame and returns TCL_RETURN
 *   2. when the CallFrame is popped, it calls TclSetTailcall to store the
 *      callback in the proper NRCommand callback - the spot where the command
 *      that pushed the CallFrame is completely cleaned up
 *   3. when the NRCommand callback runs, it schedules the tailcall callback
 *      to run immediately after it returns

 *
 *   One delicate point is to properly define the NRCommand where the tailcall
 *   will execute. There are functions whose purpose is to help define the
 *   precise spot: TclMarkTailcall ("this is the spot") and TclSkipTailcall
 *   ("skip the next command: we are redirecting to it, tailcalls should run
 *   after WE return"), TclPushTailcallPoint (special for OO).
 */
8218
8219
8220
8221
8222
8223
8224












8225
8226
8227
8228
8229
8230
8231
TclPushTailcallPoint(
    Tcl_Interp *interp)
{
    TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL);
    ((Interp *) interp)->numLevels++;
}













void
TclSetTailcall(
    Tcl_Interp *interp,
    Tcl_Obj *listPtr)
{
    /*
     * Find the splicing spot: right before the NRCommand of the thing







>
>
>
>
>
>
>
>
>
>
>
>







8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
TclPushTailcallPoint(
    Tcl_Interp *interp)
{
    TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL);
    ((Interp *) interp)->numLevels++;
}


/*
 *----------------------------------------------------------------------
 *
 * TclSetTailcall --
 *
 *	Splice a tailcall command in the proper spot of the NRE callback
 *	stack, so that it runs at the right time.
 *
 *----------------------------------------------------------------------
 */

void
TclSetTailcall(
    Tcl_Interp *interp,
    Tcl_Obj *listPtr)
{
    /*
     * Find the splicing spot: right before the NRCommand of the thing
8242
8243
8244
8245
8246
8247
8248

















8249
8250
8251
8252
8253
8254
8255
    }
    if (!runPtr) {
        Tcl_Panic("tailcall cannot find the right splicing spot: should not happen!");
    }
    runPtr->data[1] = listPtr;
}


















int
TclNRTailcallObjCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
    }
    if (!runPtr) {
        Tcl_Panic("tailcall cannot find the right splicing spot: should not happen!");
    }
    runPtr->data[1] = listPtr;
}


/*
 *----------------------------------------------------------------------
 *
 * TclNRTailcallObjCmd --
 *
 *	Prepare the tailcall as a list and store it in the current
 *	varFrame. When the frame is later popped the tailcall will be spliced
 *	at the proper place.
 *
 * Results:
 *	The first NRCommand callback that is not marked to be skipped is
 *	updated so that its data[1] field contains the tailcall list.
 *
 *----------------------------------------------------------------------
 */

int
TclNRTailcallObjCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
8301
8302
8303
8304
8305
8306
8307











8308
8309
8310
8311
8312
8313
8314
 	TclListObjSetElement(interp, listPtr, 0, nsObjPtr);
        
        iPtr->varFramePtr->tailcallPtr = listPtr;
    }
    return TCL_RETURN;
}












int
TclNRTailcallEval(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;







>
>
>
>
>
>
>
>
>
>
>







8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351
8352
8353
8354
 	TclListObjSetElement(interp, listPtr, 0, nsObjPtr);
        
        iPtr->varFramePtr->tailcallPtr = listPtr;
    }
    return TCL_RETURN;
}


/*
 *----------------------------------------------------------------------
 *
 * TclNRTailcallEval --
 *
 *	This NREcallback actually causes the tailcall to be evaluated.
 *
 *----------------------------------------------------------------------
 */

int
TclNRTailcallEval(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;