summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgriffin <briang42@easystreet.net>2022-10-28 06:13:11 (GMT)
committergriffin <briang42@easystreet.net>2022-10-28 06:13:11 (GMT)
commita89453a9e9aceb89b934f8d59bcfaceaf34acd86 (patch)
treee2ee09bfc8c72803377ff757a4b9f90cf35b72b2
parent119e80fb283c3918232f8d9802d6908783d5f401 (diff)
downloadtcl-a89453a9e9aceb89b934f8d59bcfaceaf34acd86.zip
tcl-a89453a9e9aceb89b934f8d59bcfaceaf34acd86.tar.gz
tcl-a89453a9e9aceb89b934f8d59bcfaceaf34acd86.tar.bz2
Expand AbstractList regression testing.
-rw-r--r--generic/tclCmdIL.c3
-rw-r--r--generic/tclTestABSList.c291
-rw-r--r--tests/abstractlist.test399
-rw-r--r--win/Makefile.in3
4 files changed, 669 insertions, 27 deletions
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index 0a4c9f4..1bf8b0a 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -4388,8 +4388,7 @@ Tcl_LsetObjCmd(
* unshared copy of it.
*/
- if (TclHasInternalRep(listPtr,&tclAbstractListType) &&
- TclAbstractListHasProc(listPtr, TCL_ABSL_SETELEMENT) &&
+ if (TclAbstractListHasProc(listPtr, TCL_ABSL_SETELEMENT) &&
objc == 4) {
finalValuePtr = Tcl_AbstractListSetElement(interp, listPtr, objv[2], objv[3]);
if (finalValuePtr) Tcl_IncrRefCount(finalValuePtr);
diff --git a/generic/tclTestABSList.c b/generic/tclTestABSList.c
index 1ddc442..2ccd713 100644
--- a/generic/tclTestABSList.c
+++ b/generic/tclTestABSList.c
@@ -2,6 +2,7 @@
#include <string.h>
#include <limits.h>
#include "tcl.h"
+#include "tclAbstractList.h"
/*
* Forward references
@@ -31,6 +32,10 @@ static int my_LStringReplace(Tcl_Interp *interp,
Tcl_WideInt numToDelete,
Tcl_WideInt numToInsert,
Tcl_Obj *const insertObjs[]);
+static int my_LStringGetElements(Tcl_Interp *interp,
+ Tcl_Obj *listPtr,
+ int *objcptr,
+ Tcl_Obj ***objvptr);
/*
* Internal Representation of an lstring type value
@@ -40,12 +45,105 @@ typedef struct LString {
char *string; // NULL terminated utf-8 string
Tcl_WideInt strlen; // num bytes in string
Tcl_WideInt allocated; // num bytes allocated
+ Tcl_Obj**elements; // elements array, allocated when GetElements is
+ // called
} LString;
/*
* AbstractList definition of an lstring type
*/
-static Tcl_AbstractListType lstringType = {
+static Tcl_AbstractListType lstringTypes[12] = {
+ {
+ TCL_ABSTRACTLIST_VERSION_1,
+ "lstring",
+/**/ NULL, /*default NULL,*/
+ DupLStringRep,
+ my_LStringObjLength,
+ my_LStringObjIndex,
+ my_LStringObjRange,/*ObjRange*/
+ my_LStringObjReverse,
+ my_LStringGetElements,
+ freeRep,
+ NULL /*toString*/,
+ my_LStringObjSetElem, /* use default update string */
+ my_LStringReplace
+ },
+ {
+ TCL_ABSTRACTLIST_VERSION_1,
+ "lstring",
+ NULL,
+/**/ NULL, /*default DupLStringRep,*/
+ my_LStringObjLength,
+ my_LStringObjIndex,
+ my_LStringObjRange,/*ObjRange*/
+ my_LStringObjReverse,
+ my_LStringGetElements,
+ freeRep,
+ NULL /*toString*/,
+ my_LStringObjSetElem, /* use default update string */
+ my_LStringReplace
+ },
+ {
+ TCL_ABSTRACTLIST_VERSION_1,
+ "lstring",
+ NULL,
+ DupLStringRep,
+/**/ NULL, /*default my_LStringObjLength,*/
+ my_LStringObjIndex,
+ my_LStringObjRange,/*ObjRange*/
+ my_LStringObjReverse,
+ my_LStringGetElements,
+ freeRep,
+ NULL /*toString*/,
+ my_LStringObjSetElem, /* use default update string */
+ my_LStringReplace
+ },
+ {
+ TCL_ABSTRACTLIST_VERSION_1,
+ "lstring",
+ NULL,
+ DupLStringRep,
+ my_LStringObjLength,
+/**/ NULL, /*default my_LStringObjIndex,*/
+ my_LStringObjRange,/*ObjRange*/
+ my_LStringObjReverse,
+ my_LStringGetElements,
+ freeRep,
+ NULL /*toString*/,
+ my_LStringObjSetElem, /* use default update string */
+ my_LStringReplace
+ },
+ {
+ TCL_ABSTRACTLIST_VERSION_1,
+ "lstring",
+ NULL,
+ DupLStringRep,
+ my_LStringObjLength,
+ my_LStringObjIndex,
+/**/ NULL, /*default my_LStringObjRange,*/
+ my_LStringObjReverse,
+ my_LStringGetElements,
+ freeRep,
+ NULL /*toString*/,
+ my_LStringObjSetElem, /* use default update string */
+ my_LStringReplace
+ },
+ {
+ TCL_ABSTRACTLIST_VERSION_1,
+ "lstring",
+ NULL,
+ DupLStringRep,
+ my_LStringObjLength,
+ my_LStringObjIndex,
+ my_LStringObjRange,/*ObjRange*/
+/**/ NULL, /*defaults my_LStringObjReverse,*/
+ my_LStringGetElements,
+ freeRep,
+ NULL /*toString*/,
+ my_LStringObjSetElem, /* use default update string */
+ my_LStringReplace
+ },
+ {
TCL_ABSTRACTLIST_VERSION_1,
"lstring",
NULL,
@@ -54,15 +152,89 @@ static Tcl_AbstractListType lstringType = {
my_LStringObjIndex,
my_LStringObjRange,/*ObjRange*/
my_LStringObjReverse,
- NULL/*my_LStringGetElements*/,
+/**/ NULL, /*default NULL / *my_LStringGetElements,*/
freeRep,
NULL /*toString*/,
my_LStringObjSetElem, /* use default update string */
my_LStringReplace
+ },
+ {
+ TCL_ABSTRACTLIST_VERSION_1,
+ "lstring",
+ NULL,
+ DupLStringRep,
+ my_LStringObjLength,
+ my_LStringObjIndex,
+ my_LStringObjRange,/*ObjRange*/
+ my_LStringObjReverse,
+ my_LStringGetElements,
+/**/ NULL, /*default freeRep,*/
+ NULL /*toString*/,
+ my_LStringObjSetElem, /* use default update string */
+ my_LStringReplace
+ },
+ {
+ TCL_ABSTRACTLIST_VERSION_1,
+ "lstring",
+ NULL,
+ DupLStringRep,
+ my_LStringObjLength,
+ my_LStringObjIndex,
+ my_LStringObjRange,/*ObjRange*/
+ my_LStringObjReverse,
+ my_LStringGetElements,
+ freeRep,
+/**/ NULL, /*toString*/
+ my_LStringObjSetElem, /* use default update string */
+ my_LStringReplace
+ },
+ {
+ TCL_ABSTRACTLIST_VERSION_1,
+ "lstring",
+ NULL,
+ DupLStringRep,
+ my_LStringObjLength,
+ my_LStringObjIndex,
+ my_LStringObjRange,/*ObjRange*/
+ my_LStringObjReverse,
+ my_LStringGetElements,
+ freeRep,
+ NULL /*toString*/,
+/**/ NULL, /*default my_LStringObjSetElem, / * use default update string */
+ NULL, /*default my_LStringReplace*/
+ },
+ {
+ TCL_ABSTRACTLIST_VERSION_1,
+ "lstring",
+ NULL,
+ DupLStringRep,
+ my_LStringObjLength,
+ my_LStringObjIndex,
+ my_LStringObjRange,/*ObjRange*/
+ my_LStringObjReverse,
+ my_LStringGetElements,
+ freeRep,
+ NULL /*toString*/,
+ my_LStringObjSetElem, /* use default update string */
+/**/ NULL, /*default my_LStringReplace*/
+ },
+ {
+ TCL_ABSTRACTLIST_VERSION_1,
+ "lstring",
+ NULL,
+ DupLStringRep,
+ my_LStringObjLength,
+ my_LStringObjIndex,
+ my_LStringObjRange,/*ObjRange*/
+ my_LStringObjReverse,
+ my_LStringGetElements,
+ freeRep,
+ NULL /*toString*/,
+ my_LStringObjSetElem, /* use default update string */
+ my_LStringReplace
+ }
};
-
-
/*
*----------------------------------------------------------------------
@@ -158,6 +330,7 @@ DupLStringRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr)
memcpy(copyLString, srcLString, sizeof(LString));
copyLString->string = (char*)Tcl_Alloc(srcLString->allocated);
strcpy(copyLString->string, srcLString->string);
+ copyLString->elements = NULL;
Tcl_AbstractListSetConcreteRep(copyPtr,copyLString);
return;
@@ -268,8 +441,6 @@ static int my_LStringObjRange(
return TCL_ERROR;
}
- rangeObj = Tcl_AbstractListObjNew(interp, &lstringType);
-
if (len <= 0) {
// Return empty value;
*newObjPtr = Tcl_NewObj();
@@ -280,6 +451,8 @@ static int my_LStringObjRange(
rangeRep->string = (char*)Tcl_Alloc(rangeRep->allocated);
strncpy(rangeRep->string,&lstringRepPtr->string[fromIdx],len);
rangeRep->string[len] = 0;
+ rangeRep->elements = NULL;
+ rangeObj = Tcl_AbstractListObjNew(interp, Tcl_AbstractListGetType(lstringObj));
Tcl_AbstractListSetConcreteRep(rangeObj, rangeRep);
*newObjPtr = rangeObj;
}
@@ -306,8 +479,8 @@ static int my_LStringObjRange(
static int
my_LStringObjReverse(Tcl_Interp *interp, Tcl_Obj *srcObj, Tcl_Obj **newObjPtr)
{
- Tcl_Obj *revObj = Tcl_AbstractListObjNew(interp, &lstringType);
LString *srcRep = (LString*)Tcl_AbstractListGetConcreteRep(srcObj);
+ Tcl_Obj *revObj;
LString *revRep = (LString*)Tcl_Alloc(sizeof(LString));
Tcl_WideInt len;
char *srcp, *dstp, *endp;
@@ -315,6 +488,7 @@ my_LStringObjReverse(Tcl_Interp *interp, Tcl_Obj *srcObj, Tcl_Obj **newObjPtr)
revRep->strlen = len;
revRep->allocated = len+1;
revRep->string = (char*)Tcl_Alloc(revRep->allocated);
+ revRep->elements = NULL;
srcp = srcRep->string;
endp = &srcRep->string[len];
dstp = &revRep->string[len];
@@ -322,6 +496,7 @@ my_LStringObjReverse(Tcl_Interp *interp, Tcl_Obj *srcObj, Tcl_Obj **newObjPtr)
while (srcp < endp) {
*dstp-- = *srcp++;
}
+ revObj = Tcl_AbstractListObjNew(interp, Tcl_AbstractListGetType(srcObj));
Tcl_AbstractListSetConcreteRep(revObj, revRep);
*newObjPtr = revObj;
return TCL_OK;
@@ -439,6 +614,17 @@ my_LStringReplace(
return TCL_OK;
}
+static Tcl_AbstractListType *
+my_SetAbstractProc(Tcl_AbstractListProcType ptype)
+{
+ Tcl_AbstractListType *typePtr = &lstringTypes[11];
+ if (TCL_ABSL_NEW <= ptype && ptype <= TCL_ABSL_REPLACE) {
+ typePtr = &lstringTypes[ptype];
+ }
+ return typePtr;
+}
+
+
/*
*----------------------------------------------------------------------
*
@@ -465,19 +651,46 @@ my_NewLStringObj(
size_t repSize;
Tcl_Obj *lstringPtr;
const char *string;
+ static const char* procTypeNames[] = {
+ "NEW", "DUPREP", "LENGTH", "INDEX",
+ "SLICE", "REVERSE", "GETELEMENTS", "FREEREP",
+ "TOSTRING", "SETELEMENT", "REPLACE", NULL
+ };
+ int i = 0;
+ Tcl_AbstractListProcType ptype;
+ Tcl_AbstractListType *lstringTypePtr = &lstringTypes[11];
+
+ repSize = sizeof(LString);
+ lstringRepPtr = (LString*)Tcl_Alloc(repSize);
- if (objc != 1) {
+ while (i<objc) {
+ const char *s = Tcl_GetString(objv[i]);
+ if (strcmp(s, "-not")==0) {
+ i++;
+ if (Tcl_GetIndexFromObj(interp, objv[i], procTypeNames, "proctype", 0, &ptype)==TCL_OK) {
+ lstringTypePtr = my_SetAbstractProc(ptype);
+ }
+ } else if (strcmp(s, "--") == 0) {
+ // End of options
+ i++;
+ break;
+ } else {
+ break;
+ }
+ i++;
+ }
+ if (i != objc-1) {
+ Tcl_WrongNumArgs(interp, 0, objv, "lstring string");
return NULL;
}
- string = Tcl_GetString(objv[0]);
+ string = Tcl_GetString(objv[i]);
- repSize = sizeof(LString);
- lstringPtr = Tcl_AbstractListObjNew(interp, &lstringType);
- lstringRepPtr = (LString*)Tcl_Alloc(repSize);
+ lstringPtr = Tcl_AbstractListObjNew(interp, lstringTypePtr);
lstringRepPtr->strlen = strlen(string);
lstringRepPtr->allocated = lstringRepPtr->strlen + 1;
lstringRepPtr->string = (char*)Tcl_Alloc(lstringRepPtr->allocated);
strcpy(lstringRepPtr->string, string);
+ lstringRepPtr->elements = NULL;
Tcl_AbstractListSetConcreteRep(lstringPtr, lstringRepPtr);
if (lstringRepPtr->strlen > 0) {
Tcl_InvalidateStringRep(lstringPtr);
@@ -511,6 +724,14 @@ freeRep(Tcl_Obj* lstringObj)
if (lstringRepPtr->string) {
Tcl_Free(lstringRepPtr->string);
}
+ if (lstringRepPtr->elements) {
+ Tcl_Obj **objptr = lstringRepPtr->elements;
+ while (objptr < &lstringRepPtr->elements[lstringRepPtr->strlen]) {
+ Tcl_DecrRefCount(*objptr++);
+ }
+ Tcl_Free((char*)lstringRepPtr->elements);
+ lstringRepPtr->elements = NULL;
+ }
Tcl_Free((char*)lstringRepPtr);
Tcl_AbstractListSetConcreteRep(lstringObj, NULL);
}
@@ -518,6 +739,49 @@ freeRep(Tcl_Obj* lstringObj)
/*
*----------------------------------------------------------------------
*
+ * my_LStringGetElements --
+ *
+ * Get the elements of the list in an array.
+ *
+ * Results:
+ * objc, objv return values
+ *
+ * Side effects:
+ * A Tcl_Obj is stored for every element of the abstract list
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int my_LStringGetElements(Tcl_Interp *interp,
+ Tcl_Obj *lstringObj,
+ int *objcptr,
+ Tcl_Obj ***objvptr)
+{
+ LString *lstringRepPtr = (LString*)Tcl_AbstractListGetConcreteRep(lstringObj);
+ Tcl_Obj **objPtr;
+ char *cptr = lstringRepPtr->string;
+ (void)interp;
+ if (lstringRepPtr->strlen == 0) {
+ *objcptr = 0;
+ *objvptr = NULL;
+ return TCL_OK;
+ }
+ if (lstringRepPtr->elements == NULL) {
+ lstringRepPtr->elements = (Tcl_Obj**)Tcl_Alloc(sizeof(Tcl_Obj*) * lstringRepPtr->strlen);
+ objPtr=lstringRepPtr->elements;
+ while (objPtr<&lstringRepPtr->elements[lstringRepPtr->strlen]) {
+ *objPtr = Tcl_NewStringObj(cptr++,1);
+ Tcl_IncrRefCount(*objPtr++);
+ }
+ }
+ *objvptr = lstringRepPtr->elements;
+ *objcptr = lstringRepPtr->strlen;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* lLStringObjCmd --
*
* Script level command that creats an lstring Obj value.
@@ -539,8 +803,9 @@ lLStringObjCmd(
Tcl_Obj * const objv[])
{
Tcl_Obj *lstringObj;
+
(void)clientData;
- if (objc != 2) {
+ if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "string");
return TCL_ERROR;
}
diff --git a/tests/abstractlist.test b/tests/abstractlist.test
index 7b9b2c5..c71c74b 100644
--- a/tests/abstractlist.test
+++ b/tests/abstractlist.test
@@ -10,6 +10,8 @@ if {"::tcltest" ni [namespace children]} {
namespace import -force ::tcltest::*
}
+set abstractlisttestvars [info var *]
+
proc value-isa {var {expected ""}} {
upvar $var v
set t [lindex [tcl::unsupported::representation $v] 3]
@@ -18,7 +20,15 @@ proc value-isa {var {expected ""}} {
} else {
set fail ""
}
- return "value in $var is a $t$fail"
+ return "$var is a $t$fail"
+}
+
+proc value-cmp {vara varb} {
+ upvar $vara a
+ upvar $varb b
+ set ta [tcl::unsupported::representation $a]
+ set tb [tcl::unsupported::representation $b]
+ return [string compare $ta $tb]
}
set str "My name is Inigo Montoya. You killed my father. Prepare to die!"
@@ -41,7 +51,7 @@ test abstractlist-2.0 {no shimmer llength} {
set len [llength $l]
set l-isa2 [value-isa l]
list $l ${l-isa} ${len} ${l-isa2}
-} {{M y { } n a m e { } i s { } I n i g o { } M o n t o y a . { } Y o u { } k i l l e d { } m y { } f a t h e r . { } P r e p a r e { } t o { } d i e !} {value in l is a lstring} 63 {value in l is a lstring}}
+} {{M y { } n a m e { } i s { } I n i g o { } M o n t o y a . { } Y o u { } k i l l e d { } m y { } f a t h e r . { } P r e p a r e { } t o { } d i e !} {l is a lstring} 63 {l is a lstring}}
test abstractlist-2.1 {no shimmer lindex} {
set l [lstring $str]
@@ -49,7 +59,7 @@ test abstractlist-2.1 {no shimmer lindex} {
set ele [lindex $l 22]
set l-isa2 [value-isa l]
list $l ${l-isa} ${ele} ${l-isa2}
-} {{M y { } n a m e { } i s { } I n i g o { } M o n t o y a . { } Y o u { } k i l l e d { } m y { } f a t h e r . { } P r e p a r e { } t o { } d i e !} {value in l is a lstring} y {value in l is a lstring}}
+} {{M y { } n a m e { } i s { } I n i g o { } M o n t o y a . { } Y o u { } k i l l e d { } m y { } f a t h e r . { } P r e p a r e { } t o { } d i e !} {l is a lstring} y {l is a lstring}}
test abstractlist-2.2 {no shimmer lreverse} {
set l [lstring $str]
@@ -58,7 +68,7 @@ test abstractlist-2.2 {no shimmer lreverse} {
set r-isa [value-isa r]
set l-isa2 [value-isa l]
list $r ${l-isa} ${r-isa} ${l-isa2}
-} {{! e i d { } o t { } e r a p e r P { } . r e h t a f { } y m { } d e l l i k { } u o Y { } . a y o t n o M { } o g i n I { } s i { } e m a n { } y M} {value in l is a lstring} {value in r is a lstring} {value in l is a lstring}}
+} {{! e i d { } o t { } e r a p e r P { } . r e h t a f { } y m { } d e l l i k { } u o Y { } . a y o t n o M { } o g i n I { } s i { } e m a n { } y M} {l is a lstring} {r is a lstring} {l is a lstring}}
test abstractlist-2.3 {no shimmer lrange} {
set l [lstring $str]
@@ -74,7 +84,7 @@ test abstractlist-2.3 {no shimmer lrange} {
}]
set l-isa3 [value-isa l]
list ${l-isa} $il ${l-isa2} ${l-isa3} $words
-} {{value in l is a lstring} {2 7 10 16 25 29 36 39 47 55 58 63} {value in l is a lstring} {value in l is a lstring} {My name is Inigo Montoya. You killed my father. Prepare to die!}}
+} {{l is a lstring} {2 7 10 16 25 29 36 39 47 55 58 63} {l is a lstring} {l is a lstring} {My name is Inigo Montoya. You killed my father. Prepare to die!}}
test abstractlist-2.4 {no shimmer foreach} {
set l [lstring $str]
@@ -94,7 +104,7 @@ test abstractlist-2.4 {no shimmer foreach} {
}
set l-isa2 [value-isa l]
list ${l-isa} ${l-isa2} $words
-} {{value in l is a lstring} {value in l is a lstring} {My name is Inigo Montoya. You killed my father. Prepare to die!}}
+} {{l is a lstring} {l is a lstring} {My name is Inigo Montoya. You killed my father. Prepare to die!}}
#
# The TBCE implements lreplace as a lrange + lappend operation, so, in this case, $m results is a list, not an lstring.
@@ -106,7 +116,7 @@ test abstractlist-2.5 {!no shimmer lreplace} {
set m-isa [value-isa m]
set l-isa1 [value-isa l]
list ${l-isa} $m ${m-isa} ${l-isa1}
-} {{value in l is a lstring} {V i z z i n i : { } H E { } D I D N ' T { } f a i l ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {value in m is a list} {value in l is a lstring}}
+} {{l is a lstring} {V i z z i n i : { } H E { } D I D N ' T { } f a i l ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {m is a list} {l is a lstring}}
test abstractlist-2.6 {no shimmer ledit} {
# "ledit m 9 8 S"
@@ -114,10 +124,8 @@ test abstractlist-2.6 {no shimmer ledit} {
set l-isa [value-isa l]
set e [ledit l 9 8 S]
set e-isa [value-isa e]
- #puts [list linsert {$m} 13 {*}[split "almost " {}]]
- #puts [linsert $m 13 {*}[split "almost " {}]]
list ${l-isa} $e ${e-isa}
-} {{value in l is a lstring} {V i z z i n i : { } S H E { } D I D N ' T { } F A L L ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {value in e is a lstring}}
+} {{l is a lstring} {V i z z i n i : { } S H E { } D I D N ' T { } F A L L ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {e is a lstring}}
test abstractlist-2.7 {no shimmer linsert} {
# "ledit m 9 8 S"
@@ -130,4 +138,373 @@ test abstractlist-2.7 {no shimmer linsert} {
set p-isa [value-isa p]
set i-isa2 [value-isa i]
lappend res $p ${p-isa} $i ${i-isa2}
-} {{value in l is a lstring} {V i z z i n i : { } H E { } a l m o s t { } D I D N ' T { } F A L L ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {value in i is a lstring} ' {value in p is a pure} {V i z z i n i : { } H E { } a l m o s t { } D I D N T { } F A L L ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {value in i is a list}}
+} {{l is a lstring} {V i z z i n i : { } H E { } a l m o s t { } D I D N ' T { } F A L L ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {i is a lstring} ' {p is a pure} {V i z z i n i : { } H E { } a l m o s t { } D I D N T { } F A L L ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {i is a lstring}}
+
+test abstractlist-2.8 {shimmer lassign} {
+ set l [lstring Inconceivable]
+ set l-isa [value-isa l]
+ set l2 [lassign $l i n c]
+ set l-isa2 [value-isa l]
+ set l2-isa [value-isa l2]
+ list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
+} {{I n c o n c e i v a b l e} {l is a lstring} {o n c e i v a b l e} {l is a lstring} {l2 is a lstring}}
+
+test abstractlist-2.9 {no shimmer lremove} {
+ set l [lstring Inconceivable]
+ set l-isa [value-isa l]
+ set l2 [lremove $l 0 1]
+ set l-isa2 [value-isa l]
+ set l2-isa [value-isa l2]
+ list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
+} {{I n c o n c e i v a b l e} {l is a lstring} {c o n c e i v a b l e} {l is a lstring} {l2 is a lstring}}
+
+test abstractlist-2.10 {shimmer lreverse} {
+ set l [lstring Inconceivable]
+ set l-isa [value-isa l]
+ set l2 [lreverse $l]
+ set l-isa2 [value-isa l]
+ set l2-isa [value-isa l2]
+ list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
+} {{I n c o n c e i v a b l e} {l is a lstring} {e l b a v i e c n o c n I} {l is a lstring} {l2 is a lstring}}
+
+test abstractlist-2.11 {shimmer lset} {
+ set l [lstring Inconceivable]
+ set l-isa [value-isa l]
+ set m [lset l 2 k]
+ set m-isa [value-isa m]
+ list $l ${l-isa} $m ${m-isa} [value-cmp l m]
+} {{I n k o n c e i v a b l e} {l is a lstring} {I n k o n c e i v a b l e} {m is a lstring} 0}
+
+# lrepeat
+test abstractlist-2.12 {shimmer lrepeat} {
+ set l [lstring Inconceivable]
+ set l-isa [value-isa l]
+ set m [lrepeat 3 $l]
+ set m-isa [value-isa m]
+ set n [lindex $m 1]
+ list $l ${l-isa} $m ${m-isa} [value-isa n] [value-cmp l n]
+} {{I n c o n c e i v a b l e} {l is a lstring} {{I n c o n c e i v a b l e} {I n c o n c e i v a b l e} {I n c o n c e i v a b l e}} {m is a list} {n is a lstring} 0}
+
+test abstractlist-2.13 {no shimmer join llength==1} {
+ set l [lstring G]
+ set l-isa [value-isa l]
+ set j [join $l :]
+ set j-isa [value-isa j]
+ list ${l-isa} $l ${j-isa} $j
+} {{l is a lstring} G {j is a pure} G}
+
+# lsort
+
+test abstractlist-3.0 {no shimmer llength} {
+ set l [lstring -not SLICE $str]
+ set l-isa [value-isa l]
+ set len [llength $l]
+ set l-isa2 [value-isa l]
+ list $l ${l-isa} ${len} ${l-isa2}
+} {{M y { } n a m e { } i s { } I n i g o { } M o n t o y a . { } Y o u { } k i l l e d { } m y { } f a t h e r . { } P r e p a r e { } t o { } d i e !} {l is a lstring} 63 {l is a lstring}}
+
+test abstractlist-3.1 {no shimmer lindex} {
+ set l [lstring -not SLICE $str]
+ set l-isa [value-isa l]
+ set ele [lindex $l 22]
+ set l-isa2 [value-isa l]
+ list $l ${l-isa} ${ele} ${l-isa2}
+} {{M y { } n a m e { } i s { } I n i g o { } M o n t o y a . { } Y o u { } k i l l e d { } m y { } f a t h e r . { } P r e p a r e { } t o { } d i e !} {l is a lstring} y {l is a lstring}}
+
+test abstractlist-3.2 {no shimmer lreverse} {
+ set l [lstring -not SLICE $str]
+ set l-isa [value-isa l]
+ set r [lreverse $l]
+ set r-isa [value-isa r]
+ set l-isa2 [value-isa l]
+ list $r ${l-isa} ${r-isa} ${l-isa2}
+} {{! e i d { } o t { } e r a p e r P { } . r e h t a f { } y m { } d e l l i k { } u o Y { } . a y o t n o M { } o g i n I { } s i { } e m a n { } y M} {l is a lstring} {r is a lstring} {l is a lstring}}
+
+test abstractlist-3.3 {shimmer lrange} {
+ set l [lstring -not SLICE $str]
+ set l-isa [value-isa l]
+ set il [lsearch -all [lstring -not SLICE $str] { }]
+ set l-isa2 [value-isa l]
+ lappend il [llength $l]
+ set start 0
+ set words [lmap i $il {
+ set w [join [lrange $l $start $i-1] {} ]
+ set start [expr {$i+1}]
+ set w
+ }]
+ set l-isa3 [value-isa l]; # lrange defaults to list behavior
+ list ${l-isa} $il ${l-isa2} ${l-isa3} $words
+} {{l is a lstring} {2 7 10 16 25 29 36 39 47 55 58 63} {l is a lstring} {l is a list} {My name is Inigo Montoya. You killed my father. Prepare to die!}}
+
+test abstractlist-3.4 {no shimmer foreach} {
+ set l [lstring -not SLICE $str]
+ set l-isa [value-isa l]
+ set word {}
+ set words {}
+ foreach c $l {
+ if {$c eq { }} {
+ lappend words $word
+ set word {}
+ } else {
+ append word $c
+ }
+ }
+ if {$word ne ""} {
+ lappend words $word
+ }
+ set l-isa2 [value-isa l]
+ list ${l-isa} ${l-isa2} $words
+} {{l is a lstring} {l is a lstring} {My name is Inigo Montoya. You killed my father. Prepare to die!}}
+
+#
+# The TBCE implements lreplace as a lrange + lappend operation, so, in this case, $m results is a list, not an lstring.
+#
+test abstractlist-3.5 {!no shimmer lreplace} {
+ set l [lstring -not SLICE $str2]
+ set l-isa [value-isa l]
+ set m [lreplace $l 18 23 { } f a i l ?]
+ set m-isa [value-isa m]
+ set l-isa1 [value-isa l]
+ list ${l-isa} $m ${m-isa} ${l-isa1}
+} {{l is a lstring} {V i z z i n i : { } H E { } D I D N ' T { } f a i l ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {m is a list} {l is a lstring}}
+
+test abstractlist-3.6 {no shimmer ledit} {
+ # "ledit m 9 8 S"
+ set l [lstring -not SLICE $str2]
+ set l-isa [value-isa l]
+ set e [ledit l 9 8 S]
+ set e-isa [value-isa e]
+ list ${l-isa} $e ${e-isa}
+} {{l is a lstring} {V i z z i n i : { } S H E { } D I D N ' T { } F A L L ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {e is a lstring}}
+
+test abstractlist-3.7 {no shimmer linsert} {
+ # "ledit m 9 8 S"
+ set res {}
+ set l [lstring -not SLICE $str2]
+ set l-isa [value-isa l]
+ set i [linsert $l 12 {*}[split "almost " {}]]
+ set i-isa [value-isa i]
+ set res [list ${l-isa} $i ${i-isa}]
+ set p [lpop i 23]
+ set p-isa [value-isa p]
+ set i-isa2 [value-isa i]
+ lappend res $p ${p-isa} $i ${i-isa2}
+} {{l is a lstring} {V i z z i n i : { } H E { } a l m o s t { } D I D N ' T { } F A L L ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {i is a lstring} ' {p is a pure} {V i z z i n i : { } H E { } a l m o s t { } D I D N T { } F A L L ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {i is a lstring}}
+
+test abstractlist-3.8 {shimmer lassign} {
+ set l [lstring -not SLICE Inconceivable]
+ set l-isa [value-isa l]
+ set l2 [lassign $l i n c] ;# must be using lrange internally
+ set l-isa2 [value-isa l]
+ set l2-isa [value-isa l2]
+ list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
+} {{I n c o n c e i v a b l e} {l is a lstring} {o n c e i v a b l e} {l is a lstring} {l2 is a list}}
+
+test abstractlist-3.9 {no shimmer lremove} {
+ set l [lstring -not SLICE Inconceivable]
+ set l-isa [value-isa l]
+ set l2 [lremove $l 0 1]
+ set l-isa2 [value-isa l]
+ set l2-isa [value-isa l2]
+ list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
+} {{I n c o n c e i v a b l e} {l is a lstring} {c o n c e i v a b l e} {l is a lstring} {l2 is a lstring}}
+
+test abstractlist-3.10 {shimmer lreverse} {
+ set l [lstring -not SLICE Inconceivable]
+ set l-isa [value-isa l]
+ set l2 [lreverse $l]
+ set l-isa2 [value-isa l]
+ set l2-isa [value-isa l2]
+ list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
+} {{I n c o n c e i v a b l e} {l is a lstring} {e l b a v i e c n o c n I} {l is a lstring} {l2 is a lstring}}
+
+test abstractlist-3.11 {shimmer lset} {
+ set l [lstring -not SLICE Inconceivable]
+ set l-isa [value-isa l]
+ set m [lset l 2 k]
+ set m-isa [value-isa m]
+ list $l ${l-isa} $m ${m-isa} [value-cmp l m]
+} {{I n k o n c e i v a b l e} {l is a lstring} {I n k o n c e i v a b l e} {m is a lstring} 0}
+
+# lrepeat
+test abstractlist-3.12 {shimmer lrepeat} {
+ set l [lstring -not SLICE Inconceivable]
+ set l-isa [value-isa l]
+ set m [lrepeat 3 $l]
+ set m-isa [value-isa m]
+ set n [lindex $m 1]
+ list $l ${l-isa} $m ${m-isa} [value-isa n] [value-cmp l n]
+} {{I n c o n c e i v a b l e} {l is a lstring} {{I n c o n c e i v a b l e} {I n c o n c e i v a b l e} {I n c o n c e i v a b l e}} {m is a list} {n is a lstring} 0}
+
+# lsort
+foreach not {{} REVERSE SLICE SETELEMENT REPLACE GETELEMENTS} {
+
+ testConstraint [format "%sShimmer" [string totitle $not]] [expr {$not eq ""}]
+ set options [expr {$not ne "" ? "-not $not" : ""}]
+
+test abstractlist-$not-4.0 {no shimmer llength} {
+ set l [lstring {*}$options $str]
+ set l-isa [value-isa l]
+ set len [llength $l]
+ set l-isa2 [value-isa l]
+ list $l ${l-isa} ${len} ${l-isa2}
+} {{M y { } n a m e { } i s { } I n i g o { } M o n t o y a . { } Y o u { } k i l l e d { } m y { } f a t h e r . { } P r e p a r e { } t o { } d i e !} {l is a lstring} 63 {l is a lstring}}
+
+test abstractlist-$not-4.1 {no shimmer lindex} {
+ set l [lstring {*}$options $str]
+ set l-isa [value-isa l]
+ set ele [lindex $l 22]
+ set l-isa2 [value-isa l]
+ list $l ${l-isa} ${ele} ${l-isa2}
+} {{M y { } n a m e { } i s { } I n i g o { } M o n t o y a . { } Y o u { } k i l l e d { } m y { } f a t h e r . { } P r e p a r e { } t o { } d i e !} {l is a lstring} y {l is a lstring}}
+
+test abstractlist-$not-4.2 {lreverse} ReverseShimmer {
+ set l [lstring {*}$options $str]
+ set l-isa [value-isa l]
+ set r [lreverse $l]
+ set r-isa [value-isa r]
+ set l-isa2 [value-isa l]
+ list $r ${l-isa} ${r-isa} ${l-isa2}
+} {{! e i d { } o t { } e r a p e r P { } . r e h t a f { } y m { } d e l l i k { } u o Y { } . a y o t n o M { } o g i n I { } s i { } e m a n { } y M} {l is a lstring} {r is a lstring} {l is a lstring}}
+
+test abstractlist-$not-4.3 {no shimmer lrange} RangeShimmer {
+ set l [lstring {*}$options $str]
+ set l-isa [value-isa l]
+ set il [lsearch -all [lstring {*}$options $str] { }]
+ set l-isa2 [value-isa l]
+ lappend il [llength $l]
+ set start 0
+ set words [lmap i $il {
+ set w [join [lrange $l $start $i-1] {} ]
+ set start [expr {$i+1}]
+ set w
+ }]
+ set l-isa3 [value-isa l]
+ list ${l-isa} $il ${l-isa2} ${l-isa3} $words
+} {{l is a lstring} {2 7 10 16 25 29 36 39 47 55 58 63} {l is a lstring} {l is a lstring} {My name is Inigo Montoya. You killed my father. Prepare to die!}}
+
+test abstractlist-$not-4.4 {no shimmer foreach} {
+ set l [lstring {*}$options $str]
+ set l-isa [value-isa l]
+ set word {}
+ set words {}
+ foreach c $l {
+ if {$c eq { }} {
+ lappend words $word
+ set word {}
+ } else {
+ append word $c
+ }
+ }
+ if {$word ne ""} {
+ lappend words $word
+ }
+ set l-isa2 [value-isa l]
+ list ${l-isa} ${l-isa2} $words
+} {{l is a lstring} {l is a lstring} {My name is Inigo Montoya. You killed my father. Prepare to die!}}
+
+#
+# The TBCE implements lreplace as a lrange + lappend operation, so, in this case, $m results is a list, not an lstring.
+#
+test abstractlist-$not-4.5 {!no shimmer lreplace} {
+ set l [lstring {*}$options $str2]
+ set l-isa [value-isa l]
+ set m [lreplace $l 18 23 { } f a i l ?]
+ set m-isa [value-isa m]
+ set l-isa1 [value-isa l]
+ list ${l-isa} $m ${m-isa} ${l-isa1}
+} {{l is a lstring} {V i z z i n i : { } H E { } D I D N ' T { } f a i l ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {m is a list} {l is a lstring}}
+
+test abstractlist-$not-4.6 {no shimmer ledit} {SetelementShimmer ReplaceShimmer} {
+ # "ledit m 9 8 S"
+ set l [lstring {*}$options $str2]
+ set l-isa [value-isa l]
+ set e [ledit l 9 8 S]
+ set e-isa [value-isa e]
+ list ${l-isa} $e ${e-isa}
+} {{l is a lstring} {V i z z i n i : { } S H E { } D I D N ' T { } F A L L ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {e is a lstring}}
+
+test abstractlist-$not-4.7 {no shimmer linsert} ReplaceShimmer {
+ # "ledit m 9 8 S"
+ set l [lstring {*}$options $str2]
+ set l-isa [value-isa l]
+ set i [linsert $l 12 {*}[split "almost " {}]]
+ set i-isa [value-isa i]
+ set res [list ${l-isa} $i ${i-isa}]
+ set p [lpop i 23]
+ set p-isa [value-isa p]
+ set i-isa2 [value-isa i]
+ lappend res $p ${p-isa} $i ${i-isa2}
+} {{l is a lstring} {V i z z i n i : { } H E { } a l m o s t { } D I D N ' T { } F A L L ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {i is a lstring} ' {p is a pure} {V i z z i n i : { } H E { } a l m o s t { } D I D N T { } F A L L ? { } I N C O N C E I V A B L E . { } I n i g o { } M o n t o y a : { } Y o u { } k e e p { } u s i n g { } t h a t { } w o r d . { } I { } d o { } n o t { } t h i n k { } i t { } m e a n s { } w h a t { } y o u { } t h i n k { } i t { } m e a n s .} {i is a list}}
+
+# lassign probably uses lrange internally
+test abstractlist-$not-4.8 {shimmer lassign} RangeShimmer {
+ set l [lstring {*}$options Inconceivable]
+ set l-isa [value-isa l]
+ set l2 [lassign $l i n c]
+ set l-isa2 [value-isa l]
+ set l2-isa [value-isa l2]
+ list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
+} {{I n c o n c e i v a b l e} {l is a lstring} {o n c e i v a b l e} {l is a lstring} {l2 is a lstring}}
+
+test abstractlist-$not-4.9 {no shimmer lremove} ReplaceShimmer {
+ set l [lstring {*}$options Inconceivable]
+ set l-isa [value-isa l]
+ set l2 [lremove $l 0 1]
+ set l-isa2 [value-isa l]
+ set l2-isa [value-isa l2]
+ list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
+} {{I n c o n c e i v a b l e} {l is a lstring} {c o n c e i v a b l e} {l is a lstring} {l2 is a lstring}}
+
+test abstractlist-$not-4.10 {shimmer lreverse} ReverseShimmer {
+ set l [lstring {*}$options Inconceivable]
+ set l-isa [value-isa l]
+ set l2 [lreverse $l]
+ set l-isa2 [value-isa l]
+ set l2-isa [value-isa l2]
+ list $l ${l-isa} $l2 ${l-isa2} ${l2-isa}
+} {{I n c o n c e i v a b l e} {l is a lstring} {e l b a v i e c n o c n I} {l is a lstring} {l2 is a lstring}}
+
+test abstractlist-$not-4.11 {shimmer lset} SetelementShimmer {
+ set l [lstring {*}$options Inconceivable]
+ set l-isa [value-isa l]
+ set m [lset l 2 k]
+ set m-isa [value-isa m]
+ list $l ${l-isa} $m ${m-isa} [value-cmp l m]
+} {{I n k o n c e i v a b l e} {l is a lstring} {I n k o n c e i v a b l e} {m is a lstring} 0}
+
+# lrepeat
+test abstractlist-$not-4.12 {shimmer lrepeat} {
+ set l [lstring {*}$options Inconceivable]
+ set l-isa [value-isa l]
+ set m [lrepeat 3 $l]
+ set m-isa [value-isa m]
+ set n [lindex $m 1]
+ list $l ${l-isa} $m ${m-isa} [value-isa n] [value-cmp l n]
+} {{I n c o n c e i v a b l e} {l is a lstring} {{I n c o n c e i v a b l e} {I n c o n c e i v a b l e} {I n c o n c e i v a b l e}} {m is a list} {n is a lstring} 0}
+
+memory tag {}
+memory trace off
+
+# Disable constraint
+testConstraint [format "%sShimmer" [string totitle $not]] 1
+
+}
+
+# lsort
+
+# cleanup
+::tcltest::cleanupTests
+
+proc my_abstl_cleanup {vars} {
+ set nowvars [uplevel info vars]
+ foreach var $nowvars {
+ if {$var ni $vars} {
+ uplevel unset $var
+ lappend clean-list $var
+ }
+ }
+ return ${clean-list}
+}
+
+my_abstl_cleanup $abstractlisttestvars
diff --git a/win/Makefile.in b/win/Makefile.in
index 9a25029..a4bc90e 100644
--- a/win/Makefile.in
+++ b/win/Makefile.in
@@ -270,7 +270,8 @@ TCLTEST_OBJS = \
tclTestObj.$(OBJEXT) \
tclTestProcBodyObj.$(OBJEXT) \
tclThreadTest.$(OBJEXT) \
- tclWinTest.$(OBJEXT)
+ tclWinTest.$(OBJEXT) \
+ tclTestABSList.$(OBJEXT)
GENERIC_OBJS = \
regcomp.$(OBJEXT) \