From af0efce59e0440d75633b2dac8ab9ecd39806a30 Mon Sep 17 00:00:00 2001 From: dkf Date: Wed, 20 Oct 2010 13:34:09 +0000 Subject: * generic/tclCompCmds.c (TclCompileDictForCmd): Update the compilation * generic/tclCompile.c (tclInstructionTable): of [dict for] so that * generic/tclExecute.c (TEBCresume): it no longer makes any use of INST_DICT_DONE now that's not needed, and make it clearer in the implementation of the instruction that it's just a deprecated form of unset operation. Followup to my commit of 2010-10-16. --- ChangeLog | 9 +++++++++ generic/tclCompCmds.c | 11 +++++++---- generic/tclCompile.c | 10 ++++++---- generic/tclExecute.c | 43 ++++++++++++++++++++++++------------------- 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index d07a302..95d6896 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-10-20 Donal K. Fellows + + * generic/tclCompCmds.c (TclCompileDictForCmd): Update the compilation + * generic/tclCompile.c (tclInstructionTable): of [dict for] so that + * generic/tclExecute.c (TEBCresume): it no longer makes any + use of INST_DICT_DONE now that's not needed, and make it clearer in + the implementation of the instruction that it's just a deprecated form + of unset operation. Followup to my commit of 2010-10-16. + 2010-10-19 Donal K. Fellows * generic/tclZlib.c (Tcl_ZlibStreamGet): [Bug 3081008]: Ensure that diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index 473dcb4..a5e1074 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclCompCmds.c,v 1.169 2010/04/30 09:23:06 dkf Exp $ + * RCS: @(#) $Id: tclCompCmds.c,v 1.170 2010/10/20 13:34:10 dkf Exp $ */ #include "tclInt.h" @@ -876,7 +876,8 @@ TclCompileDictForCmd( */ ExceptionRangeTarget(envPtr, loopRange, breakOffset); - TclEmitInstInt4( INST_DICT_DONE, infoIndex, envPtr); + TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr); + TclEmitInt4( infoIndex, envPtr); TclEmitOpcode( INST_END_CATCH, envPtr); endTargetOffset = CurrentOffset(envPtr); TclEmitInstInt4( INST_JUMP4, 0, envPtr); @@ -889,7 +890,8 @@ TclCompileDictForCmd( ExceptionRangeTarget(envPtr, catchRange, catchOffset); TclEmitOpcode( INST_PUSH_RETURN_OPTIONS, envPtr); TclEmitOpcode( INST_PUSH_RESULT, envPtr); - TclEmitInstInt4( INST_DICT_DONE, infoIndex, envPtr); + TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr); + TclEmitInt4( infoIndex, envPtr); TclEmitOpcode( INST_END_CATCH, envPtr); TclEmitOpcode( INST_RETURN_STK, envPtr); @@ -905,7 +907,8 @@ TclCompileDictForCmd( envPtr->codeStart + emptyTargetOffset); TclEmitOpcode( INST_POP, envPtr); TclEmitOpcode( INST_POP, envPtr); - TclEmitInstInt4( INST_DICT_DONE, infoIndex, envPtr); + TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr); + TclEmitInt4( infoIndex, envPtr); /* * Final stage of the command (normal case) is that we push an empty diff --git a/generic/tclCompile.c b/generic/tclCompile.c index dd92f27..7781066 100644 --- a/generic/tclCompile.c +++ b/generic/tclCompile.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclCompile.c,v 1.191 2010/10/13 17:10:57 dgp Exp $ + * RCS: @(#) $Id: tclCompile.c,v 1.192 2010/10/20 13:34:11 dkf Exp $ */ #include "tclInt.h" @@ -343,14 +343,16 @@ InstructionDesc const tclInstructionTable[] = { * Stack: ... key valueToAppend => ... newDict */ {"dictFirst", 5, +2, 1, {OPERAND_LVT4}}, /* Begin iterating over the dictionary, using the local scalar - * indicated by op4 to hold the iterator state. If doneBool is true, - * dictDone *must* be called later on. + * indicated by op4 to hold the iterator state. The local scalar + * should not refer to a named variable as the value is not wholly + * managed correctly. * Stack: ... dict => ... value key doneBool */ {"dictNext", 5, +3, 1, {OPERAND_LVT4}}, /* Get the next iteration from the iterator in op4's local scalar. * Stack: ... => ... value key doneBool */ {"dictDone", 5, 0, 1, {OPERAND_LVT4}}, - /* Terminate the iterator in op4's local scalar. */ + /* Terminate the iterator in op4's local scalar. Use unsetScalar + * instead (with 0 for flags). */ {"dictUpdateStart", 9, 0, 2, {OPERAND_LVT4, OPERAND_AUX4}}, /* Create the variables (described in the aux data referred to by the * second immediate argument) to mirror the state of the dictionary in diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 65e0b22..5343ecd 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -14,7 +14,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclExecute.c,v 1.507 2010/10/16 20:27:39 dkf Exp $ + * RCS: @(#) $Id: tclExecute.c,v 1.508 2010/10/20 13:34:11 dkf Exp $ */ #include "tclInt.h" @@ -3772,6 +3772,29 @@ TEBCresume( CACHE_STACK_INFO(); TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; + + /* + * This is really an unset operation these days. Do not issue. + */ + + case INST_DICT_DONE: + opnd = TclGetUInt4AtPtr(pc+1); + TRACE(("%u\n", opnd)); + varPtr = LOCAL(opnd); + while (TclIsVarLink(varPtr)) { + varPtr = varPtr->value.linkPtr; + } + if (TclIsVarDirectUnsettable(varPtr) && !TclIsVarInHash(varPtr)) { + if (!TclIsVarUndefined(varPtr)) { + TclDecrRefCount(varPtr->value.objPtr); + } + varPtr->value.objPtr = NULL; + } else { + DECACHE_STACK_INFO(); + TclPtrUnsetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd); + CACHE_STACK_INFO(); + } + NEXT_INST_F(5, 0, 0); } /* @@ -5972,24 +5995,6 @@ TEBCresume( /* TODO: consider opt like INST_FOREACH_STEP4 */ NEXT_INST_F(5, 0, 1); - case INST_DICT_DONE: - opnd = TclGetUInt4AtPtr(pc+1); - TRACE(("%u => ", opnd)); - statePtr = (*LOCAL(opnd)).value.objPtr; - - if (statePtr != NULL && statePtr->typePtr == &dictIteratorType) { - /* - * Set the internal variable to an empty object to signify that we - * don't hold an iterator. - */ - - TclDecrRefCount(statePtr); - TclNewObj(emptyPtr); - (*LOCAL(opnd)).value.objPtr = emptyPtr; - Tcl_IncrRefCount(emptyPtr); - } - NEXT_INST_F(5, 0, 0); - case INST_DICT_UPDATE_START: opnd = TclGetUInt4AtPtr(pc+1); opnd2 = TclGetUInt4AtPtr(pc+5); -- cgit v0.12