Check-in [955265f9a0]
Not logged in
Tcl 2014 Conference, Portland/OR, US, Nov 10-14
Browse the schedule online.

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

Overview
SHA1 Hash:955265f9a0d235b25cc61066745180ea3709fa96
Date: 2013-12-18 18:23:20
User: dgp
Comment:[0b874c344d] Fix for nested coroutines ability to stitch together multiple parts of the CmdFrame chain traversed by [info frame].
Tags And Properties
Changes

Changes to generic/tclCmdIL.c

1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
....
1227
1228
1229
1230
1231
1232
1233


1234

1235
1236


1237
1238
1239


1240
1241
1242
1243
1244
1245
1246

1247

1248
1249
1250
1251
1252
1253
1254
InfoFrameCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    int level, topLevel, code = TCL_OK;
    CmdFrame *runPtr, *framePtr;
    CoroutineData *corPtr = iPtr->execEnvPtr->corPtr;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?number?");
	return TCL_ERROR;
    }

    topLevel = ((iPtr->cmdFramePtr == NULL)
	    ? 0
	    : iPtr->cmdFramePtr->level);

    if (corPtr) {
	/*
	 * A coroutine: must fix the level computations AND the cmdFrame chain,
	 * which is interrupted at the base.
	 */

	CmdFrame *lastPtr = NULL;

	runPtr = iPtr->cmdFramePtr;

	/* TODO - deal with overflow */
	topLevel += corPtr->caller.cmdFramePtr->level;
	while (runPtr) {
	    runPtr->level += corPtr->caller.cmdFramePtr->level;
	    lastPtr = runPtr;
	    runPtr = runPtr->nextPtr;
	}
	if (lastPtr) {
	    lastPtr->nextPtr = corPtr->caller.cmdFramePtr;
	} else {
	    iPtr->cmdFramePtr = corPtr->caller.cmdFramePtr;
	}
    }

    if (objc == 1) {
	/*
	 * Just "info frame".
	 */

................................................................................
	    goto levelError;
	}
    }

    Tcl_SetObjResult(interp, TclInfoFrame(interp, framePtr));

  done:


    if (corPtr) {


	if (iPtr->cmdFramePtr == corPtr->caller.cmdFramePtr) {


	    iPtr->cmdFramePtr = NULL;
	} else {
	    runPtr = iPtr->cmdFramePtr;


	    while (runPtr->nextPtr != corPtr->caller.cmdFramePtr) {
	    	runPtr->level -= corPtr->caller.cmdFramePtr->level;
		runPtr = runPtr->nextPtr;
	    }
	    runPtr->level = 1;
	    runPtr->nextPtr = NULL;
	}



    }
    return code;
}
 
/*
 *----------------------------------------------------------------------
 *







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<







 







>
>
|
>

<
>
>
|
|
<
>
>
|
|
|
|
|
|
|
>
|
>







1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181



1182
1183
1184
1185
1186
1187
1188
....
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235

1236
1237
1238
1239

1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
InfoFrameCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    int level, code = TCL_OK;
    CmdFrame *framePtr, **cmdFramePtrPtr = &iPtr->cmdFramePtr;
    CoroutineData *corPtr = iPtr->execEnvPtr->corPtr;
    int topLevel = 0;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?number?");
	return TCL_ERROR;
    }

    while (corPtr) {
	while (*cmdFramePtrPtr) {
	    topLevel++;
	    cmdFramePtrPtr = &((*cmdFramePtrPtr)->nextPtr);
	}
	if (corPtr->caller.cmdFramePtr) {
	    *cmdFramePtrPtr = corPtr->caller.cmdFramePtr;
	}
	corPtr = corPtr->callerEEPtr->corPtr;
    }
    topLevel += (*cmdFramePtrPtr)->level;

    if (topLevel != iPtr->cmdFramePtr->level) {
	framePtr = iPtr->cmdFramePtr;
	while (framePtr) {
	    framePtr->level = topLevel--;
	    framePtr = framePtr->nextPtr;
	}
	if (topLevel) {
	    Tcl_Panic("Broken frame level calculation");
	}
	topLevel = iPtr->cmdFramePtr->level;



    }

    if (objc == 1) {
	/*
	 * Just "info frame".
	 */

................................................................................
	    goto levelError;
	}
    }

    Tcl_SetObjResult(interp, TclInfoFrame(interp, framePtr));

  done:
    cmdFramePtrPtr = &iPtr->cmdFramePtr;
    corPtr = iPtr->execEnvPtr->corPtr;
    while (corPtr) {
	CmdFrame *endPtr = corPtr->caller.cmdFramePtr;


	if (endPtr) {
	    if (*cmdFramePtrPtr == endPtr) {
		*cmdFramePtrPtr = NULL;
	    } else {

		CmdFrame *runPtr = *cmdFramePtrPtr;

		while (runPtr->nextPtr != endPtr) {
		    runPtr->level -= endPtr->level;
		    runPtr = runPtr->nextPtr;
		}
		runPtr->level = 1;
		runPtr->nextPtr = NULL;
	    }
	    cmdFramePtrPtr = &corPtr->caller.cmdFramePtr;
	}
	corPtr = corPtr->callerEEPtr->corPtr;
    }
    return code;
}
 
/*
 *----------------------------------------------------------------------
 *

Changes to tests/coroutine.test

338
339
340
341
342
343
344



345
346
347
348
349
350
351
    proc a {} stack
} -body {
    coroutine aa a
} -cleanup {
    rename stack {}
    rename a {}
} -result {}




test coroutine-4.1 {bug #2093188} -setup {
    proc foo {} {
	set v 1
	trace add variable v {write unset} bar
	yield
	set v 2







>
>
>







338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
    proc a {} stack
} -body {
    coroutine aa a
} -cleanup {
    rename stack {}
    rename a {}
} -result {}
test coroutine-3.7 {bug 0b874c344d} {
    dict get [coroutine X coroutine Y info frame 0] cmd
} {coroutine X coroutine Y info frame 0}

test coroutine-4.1 {bug #2093188} -setup {
    proc foo {} {
	set v 1
	trace add variable v {write unset} bar
	yield
	set v 2