From 5da6b8e3c356a3786e96336ea19a8c4fabcb17fa Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Sun, 30 Oct 2022 04:27:03 +0000 Subject: New bytecode for linsert --- generic/tclCompCmdsGR.c | 41 +++++------------------------------------ generic/tclCompile.c | 8 ++++++-- generic/tclCompile.h | 2 +- generic/tclExecute.c | 15 ++++++++------- 4 files changed, 20 insertions(+), 46 deletions(-) diff --git a/generic/tclCompCmdsGR.c b/generic/tclCompCmdsGR.c index 4aa454b..ddb9746 100644 --- a/generic/tclCompCmdsGR.c +++ b/generic/tclCompCmdsGR.c @@ -1391,48 +1391,16 @@ TclCompileLinsertCmd( */ CompileWord(envPtr, listTokenPtr, interp, 1); - if (parsePtr->numWords == 3) { - TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr); - TclEmitInt4( (int)TCL_INDEX_END, envPtr); - return TCL_OK; - } for (i=3 ; inumWords ; i++) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, i); } - TclEmitInstInt4( INST_LIST, i - 3, envPtr); - if (idx == (int)TCL_INDEX_START) { - TclEmitInstInt4( INST_REVERSE, 2, envPtr); - TclEmitOpcode( INST_LIST_CONCAT, envPtr); - } else if (idx == (int)TCL_INDEX_END) { - TclEmitOpcode( INST_LIST_CONCAT, envPtr); - } else { - /* - * Here we handle two ranges for idx. First when idx > 0, we - * want the first half of the split to end at index idx-1 and - * the second half to start at index idx. - * Second when idx < TCL_INDEX_END, indicating "end-N" indexing, - * we want the first half of the split to end at index end-N and - * the second half to start at index end-N+1. We accomplish this - * with a pre-adjustment of the end-N value. - * The root of this is that the commands [lrange] and [linsert] - * differ in their interpretation of the "end" index. - */ - - if (idx < (int)TCL_INDEX_END) { - idx++; - } - TclEmitInstInt4( INST_OVER, 1, envPtr); - TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr); - TclEmitInt4( idx - 1, envPtr); - TclEmitInstInt4( INST_REVERSE, 3, envPtr); - TclEmitInstInt4( INST_LIST_RANGE_IMM, idx, envPtr); - TclEmitInt4( (int)TCL_INDEX_END, envPtr); - TclEmitOpcode( INST_LIST_CONCAT, envPtr); - TclEmitOpcode( INST_LIST_CONCAT, envPtr); - } + TclEmitInstInt4(INST_LREPLACE4, parsePtr->numWords - 2, envPtr); + TclEmitInt4(0, envPtr); + TclEmitInt4(idx, envPtr); + TclEmitInt4(idx-1, envPtr); return TCL_OK; } @@ -3086,6 +3054,7 @@ TclCompileXxCmd( } TclEmitInstInt4(INST_LREPLACE4, parsePtr->numWords - 2, envPtr); + TclEmitInt4(0, envPtr); TclEmitInt4(idx, envPtr); TclEmitInt4(idx-1, envPtr); diff --git a/generic/tclCompile.c b/generic/tclCompile.c index 2535167..c01ddb8 100644 --- a/generic/tclCompile.c +++ b/generic/tclCompile.c @@ -675,8 +675,12 @@ InstructionDesc const tclInstructionTable[] = { /* String Less or equal: push (stknext <= stktop) */ {"strge", 1, -1, 0, {OPERAND_NONE}}, /* String Greater or equal: push (stknext >= stktop) */ - {"lreplace4", 13, INT_MIN, 3, {OPERAND_UINT4, OPERAND_INT4, OPERAND_INT4}}, - /* Stack: ... listobj num_elems first last new1 ... newN => ... newlistobj */ + {"lreplace4", 17, INT_MIN, 4, {OPERAND_UINT4, OPERAND_UINT4, OPERAND_INT4, OPERAND_INT4}}, + /* Operands: number of arguments, end_indicator, firstIdx, lastIdx + * end_indicator: 0 if "end" is treated as index of last element, + * 1 if "end" is position after last element + * firstIdx,lastIdx: range of elements to delete + * Stack: ... listobj new1 ... newN => ... newlistobj */ {NULL, 0, 0, 0, {OPERAND_NONE}} }; diff --git a/generic/tclCompile.h b/generic/tclCompile.h index c82dc6e..9633050 100644 --- a/generic/tclCompile.h +++ b/generic/tclCompile.h @@ -862,7 +862,7 @@ typedef struct ByteCode { * instruction. */ -#define MAX_INSTRUCTION_OPERANDS 3 +#define MAX_INSTRUCTION_OPERANDS 4 typedef enum InstOperandType { OPERAND_NONE, diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 629df59..2713093 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5246,17 +5246,18 @@ TEBCresume( case INST_LREPLACE4: { - int firstIdx, lastIdx, numToDelete, numNewElems; + int firstIdx, lastIdx, numToDelete, numNewElems, end_indicator; opnd = TclGetInt4AtPtr(pc + 1); - firstIdx = TclGetInt4AtPtr(pc + 5); /* First delete position */ - lastIdx = TclGetInt4AtPtr(pc + 9); /* Last delete position */ + end_indicator = TclGetInt4AtPtr(pc + 5); + firstIdx = TclGetInt4AtPtr(pc + 9); + lastIdx = TclGetInt4AtPtr(pc + 13); numNewElems = opnd - 1; valuePtr = OBJ_AT_DEPTH(numNewElems); if (Tcl_ListObjLength(interp, valuePtr, &length) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } - firstIdx = TclIndexDecode(firstIdx, length-1); + firstIdx = TclIndexDecode(firstIdx, length-end_indicator); if (firstIdx == TCL_INDEX_NONE) { firstIdx = 0; } else if (firstIdx > length) { @@ -5264,7 +5265,7 @@ TEBCresume( } numToDelete = 0; if (lastIdx != TCL_INDEX_NONE) { - lastIdx = TclIndexDecode(lastIdx, length - 1); + lastIdx = TclIndexDecode(lastIdx, length - end_indicator); if (lastIdx >= firstIdx) { numToDelete = lastIdx - firstIdx + 1; } @@ -5283,7 +5284,7 @@ TEBCresume( goto gotError; } TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); - NEXT_INST_V(13, opnd, 1); + NEXT_INST_V(17, opnd, 1); } else { if (Tcl_ListObjReplace(interp, valuePtr, @@ -5296,7 +5297,7 @@ TEBCresume( goto gotError; } TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr))); - NEXT_INST_V(13, opnd-1, 0); + NEXT_INST_V(17, opnd-1, 0); } } -- cgit v0.12