diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2018-09-27 08:22:07 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2018-09-27 08:22:07 (GMT) |
commit | 1146932b9e2a98b035d9d39b49497e9bc38a9fc6 (patch) | |
tree | 1205f3b9d15db48fa516b96342dcb33e92bff7f3 /generic/tclCompCmdsGR.c | |
parent | 00d5f9266b21832cc397c092a4b85e8a6d7b3659 (diff) | |
parent | 6cdb3193ec55c1fa18fb9f6c73f290e60f6ddd1d (diff) | |
download | tcl-1146932b9e2a98b035d9d39b49497e9bc38a9fc6.zip tcl-1146932b9e2a98b035d9d39b49497e9bc38a9fc6.tar.gz tcl-1146932b9e2a98b035d9d39b49497e9bc38a9fc6.tar.bz2 |
Implementation of TIP 505: Make [lreplace] Accept All Out-of-Range Index Values
Diffstat (limited to 'generic/tclCompCmdsGR.c')
-rw-r--r-- | generic/tclCompCmdsGR.c | 59 |
1 files changed, 4 insertions, 55 deletions
diff --git a/generic/tclCompCmdsGR.c b/generic/tclCompCmdsGR.c index 1209caf..f9cf3d8 100644 --- a/generic/tclCompCmdsGR.c +++ b/generic/tclCompCmdsGR.c @@ -1474,7 +1474,7 @@ TclCompileLreplaceCmd( { Tcl_Token *tokenPtr, *listTokenPtr; DefineLineInformation; /* TIP #280 */ - int idx1, idx2, i, offset, offset2; + int idx1, idx2, i; int emptyPrefix=1, suffixStart = 0; if (parsePtr->numWords < 4) { @@ -1495,23 +1495,6 @@ TclCompileLreplaceCmd( } /* - * idx1, idx2 are the conventional encoded forms of the tokens parsed - * as all forms of index values. Values of idx1 that come before the - * list are treated the same as if they were the start of the list. - * Values of idx2 that come after the list are treated the same as if - * they were the end of the list. - */ - - if (idx1 == TCL_INDEX_AFTER) { - /* - * [lreplace] treats idx1 value end+1 differently from end+2, etc. - * The operand encoding cannot distinguish them, so we must bail - * out to direct evaluation. - */ - return TCL_ERROR; - } - - /* * General structure of the [lreplace] result is * prefix replacement suffix * In a few cases we can predict various parts will be empty and @@ -1522,7 +1505,9 @@ TclCompileLreplaceCmd( * we must defer to direct evaluation. */ - if (idx2 == TCL_INDEX_BEFORE) { + if (idx1 == TCL_INDEX_AFTER) { + suffixStart = idx1; + } else if (idx2 == TCL_INDEX_BEFORE) { suffixStart = idx1; } else if (idx2 == TCL_INDEX_END) { suffixStart = TCL_INDEX_AFTER; @@ -1554,42 +1539,6 @@ TclCompileLreplaceCmd( emptyPrefix = 0; } - /* - * [lreplace] raises an error when idx1 points after the list, but - * only when the list is not empty. This is maximum stupidity. - * - * TODO: TIP this nonsense away! - */ - if (idx1 >= TCL_INDEX_START) { - if (emptyPrefix) { - TclEmitOpcode( INST_DUP, envPtr); - } else { - TclEmitInstInt4( INST_OVER, 1, envPtr); - } - TclEmitOpcode( INST_LIST_LENGTH, envPtr); - TclEmitOpcode( INST_DUP, envPtr); - offset = CurrentOffset(envPtr); - TclEmitInstInt1( INST_JUMP_FALSE1, 0, envPtr); - - /* List is not empty */ - TclEmitPush(TclAddLiteralObj(envPtr, Tcl_NewIntObj(idx1), - NULL), envPtr); - TclEmitOpcode( INST_GT, envPtr); - offset2 = CurrentOffset(envPtr); - TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr); - - /* Idx1 >= list length ===> raise an error */ - TclEmitPush(TclAddLiteralObj(envPtr, Tcl_ObjPrintf( - "list doesn't contain element %d", idx1), NULL), envPtr); - CompileReturnInternal(envPtr, INST_RETURN_IMM, TCL_ERROR, 0, - Tcl_ObjPrintf("-errorcode {TCL OPERATION LREPLACE BADIDX}")); - TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset, - envPtr->codeStart + offset + 1); - TclEmitOpcode( INST_POP, envPtr); - TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset2, - envPtr->codeStart + offset2 + 1); - } - if ((idx1 == suffixStart) && (parsePtr->numWords == 4)) { /* * This is a "no-op". Example: [lreplace {a b c} 2 0] |