diff options
author | apnadkarni <apnmbx-wits@yahoo.com> | 2022-11-03 17:04:07 (GMT) |
---|---|---|
committer | apnadkarni <apnmbx-wits@yahoo.com> | 2022-11-03 17:04:07 (GMT) |
commit | f768eb3bf2d09ebf310ed07f664dc114e1c1412d (patch) | |
tree | 0654108b366eb7baaf8c4e36a83ae1de9327f2bd /generic/tclExecute.c | |
parent | d9a19f95121e4fd846211083cc7c3b0d22c7a564 (diff) | |
download | tcl-f768eb3bf2d09ebf310ed07f664dc114e1c1412d.zip tcl-f768eb3bf2d09ebf310ed07f664dc114e1c1412d.tar.gz tcl-f768eb3bf2d09ebf310ed07f664dc114e1c1412d.tar.bz2 |
Rewrite lreplace4 implementation not to need extra immediate operands.
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r-- | generic/tclExecute.c | 129 |
1 files changed, 81 insertions, 48 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 2713093..a8d9d57 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5246,61 +5246,94 @@ TEBCresume( case INST_LREPLACE4: { - int firstIdx, lastIdx, numToDelete, numNewElems, end_indicator; - opnd = TclGetInt4AtPtr(pc + 1); - 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) { + int numToDelete, numNewElems, end_indicator; + int haveSecondIndex, flags; + Tcl_Obj *fromIdxObj, *toIdxObj; + opnd = TclGetInt4AtPtr(pc + 1); + flags = TclGetInt1AtPtr(pc + 5); + + /* Stack: ... listobj index1 ?index2? new1 ... newN */ + valuePtr = OBJ_AT_DEPTH(opnd-1); + + /* haveSecondIndex==0 => pure insert */ + haveSecondIndex = (flags & TCL_LREPLACE4_SINGLE_INDEX) == 0; + numNewElems = opnd - 2 - haveSecondIndex; + + /* end_indicator==1 => "end" is last element's index, 0=>index beyond */ + end_indicator = (flags & TCL_LREPLACE4_END_IS_LAST) != 0; + fromIdxObj = OBJ_AT_DEPTH(opnd - 2); + toIdxObj = haveSecondIndex ? OBJ_AT_DEPTH(opnd - 3) : NULL; + if (Tcl_ListObjLength(interp, valuePtr, &length) != TCL_OK) { + TRACE_ERROR(interp); + goto gotError; + } + + DECACHE_STACK_INFO(); + + if (TclGetIntForIndexM( + interp, fromIdxObj, length - end_indicator, &fromIdx) + != TCL_OK) { + CACHE_STACK_INFO(); + TRACE_ERROR(interp); + goto gotError; + } + if (fromIdx == TCL_INDEX_NONE) { + fromIdx = 0; + } + else if (fromIdx > length) { + fromIdx = length; + } + numToDelete = 0; + if (toIdxObj) { + if (TclGetIntForIndexM( + interp, toIdxObj, length - end_indicator, &toIdx) + != TCL_OK) { + CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } - firstIdx = TclIndexDecode(firstIdx, length-end_indicator); - if (firstIdx == TCL_INDEX_NONE) { - firstIdx = 0; - } else if (firstIdx > length) { - firstIdx = length; - } - numToDelete = 0; - if (lastIdx != TCL_INDEX_NONE) { - lastIdx = TclIndexDecode(lastIdx, length - end_indicator); - if (lastIdx >= firstIdx) { - numToDelete = lastIdx - firstIdx + 1; - } + if (toIdx > length) { + toIdx = length; } - if (Tcl_IsShared(valuePtr)) { - objResultPtr = Tcl_DuplicateObj(valuePtr); - if (Tcl_ListObjReplace(interp, - objResultPtr, - firstIdx, - numToDelete, - numNewElems, - &OBJ_AT_DEPTH(numNewElems-1)) - != TCL_OK) { - TRACE_ERROR(interp); - Tcl_DecrRefCount(objResultPtr); - goto gotError; - } - TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); - NEXT_INST_V(17, opnd, 1); - } else { - if (Tcl_ListObjReplace(interp, - valuePtr, - firstIdx, - numToDelete, - numNewElems, - &OBJ_AT_DEPTH(numNewElems-1)) - != TCL_OK) { - TRACE_ERROR(interp); - goto gotError; - } - TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr))); - NEXT_INST_V(17, opnd-1, 0); + if (toIdx >= fromIdx) { + numToDelete = toIdx - fromIdx + 1; } } + CACHE_STACK_INFO(); + + if (Tcl_IsShared(valuePtr)) { + objResultPtr = Tcl_DuplicateObj(valuePtr); + if (Tcl_ListObjReplace(interp, + objResultPtr, + fromIdx, + numToDelete, + numNewElems, + &OBJ_AT_DEPTH(numNewElems - 1)) + != TCL_OK) { + TRACE_ERROR(interp); + Tcl_DecrRefCount(objResultPtr); + goto gotError; + } + TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); + NEXT_INST_V(6, opnd, 1); + } + else { + if (Tcl_ListObjReplace(interp, + valuePtr, + fromIdx, + numToDelete, + numNewElems, + &OBJ_AT_DEPTH(numNewElems - 1)) + != TCL_OK) { + TRACE_ERROR(interp); + goto gotError; + } + TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr))); + NEXT_INST_V(6, opnd - 1, 0); + } + } + /* * End of INST_LIST and related instructions. * ----------------------------------------------------------------- |