summaryrefslogtreecommitdiffstats
path: root/generic/tclExecute.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2004-10-08 15:39:37 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2004-10-08 15:39:37 (GMT)
commitb8ad7e6569c1ac14d88d993310013ae3095d00b1 (patch)
tree8013273a78ab046ca1744309207ab85ea5ab26c9 /generic/tclExecute.c
parent4b9c1da0d3b0ca6029c1fe83989006927422d95d (diff)
downloadtcl-b8ad7e6569c1ac14d88d993310013ae3095d00b1.zip
tcl-b8ad7e6569c1ac14d88d993310013ae3095d00b1.tar.gz
tcl-b8ad7e6569c1ac14d88d993310013ae3095d00b1.tar.bz2
Core of implementation of TIP#201 ('in' and 'ni' operators)
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r--generic/tclExecute.c67
1 files changed, 66 insertions, 1 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index 65a57dd..60b9344 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.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: tclExecute.c,v 1.155 2004/10/06 20:09:37 dkf Exp $
+ * RCS: @(#) $Id: tclExecute.c,v 1.156 2004/10/08 15:39:53 dkf Exp $
*/
#ifdef STDC_HEADERS
@@ -2913,6 +2913,71 @@ TclExecuteByteCode(interp, codePtr)
NEXT_INST_F(9, 1, 1);
}
+ case INST_LIST_IN:
+ case INST_LIST_NOT_IN: {
+ /*
+ * Basic list containment operators.
+ */
+ int found, s1len, s2len, llen, i;
+ Tcl_Obj *valuePtr, *value2Ptr, *o;
+ char *s1, *s2;
+
+ value2Ptr = *tosPtr;
+ valuePtr = *(tosPtr - 1);
+
+ s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
+ result = Tcl_ListObjLength(interp, value2Ptr, &llen);
+ if (result != TCL_OK) {
+ TRACE_WITH_OBJ(("\"%.30s\" \"%.30s\" => ERROR: ", O2S(valuePtr),
+ O2S(value2Ptr)), Tcl_GetObjResult(interp));
+ goto checkForCatch;
+ }
+ found = 0;
+ if (llen > 0) {
+ /* An empty list doesn't match anything */
+ i = 0;
+ do {
+ Tcl_ListObjIndex(NULL, value2Ptr, i, &o);
+ if (o != NULL) {
+ s2 = Tcl_GetStringFromObj(o, &s2len);
+ } else {
+ s2 = "";
+ }
+ if (s1len == s2len) {
+ found = (strcmp(s1, s2) == 0);
+ }
+ i++;
+ } while (i < llen && found == 0);
+ }
+
+ if (*pc == INST_LIST_NOT_IN) {
+ found = !found;
+ }
+
+ TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), found));
+
+ /*
+ * Peep-hole optimisation: if you're about to jump, do jump
+ * from here.
+ */
+
+ pc++;
+#ifndef TCL_COMPILE_DEBUG
+ switch (*pc) {
+ case INST_JUMP_FALSE1:
+ NEXT_INST_F((found ? 2 : TclGetInt1AtPtr(pc+1)), 2, 0);
+ case INST_JUMP_TRUE1:
+ NEXT_INST_F((found ? TclGetInt1AtPtr(pc+1) : 2), 2, 0);
+ case INST_JUMP_FALSE4:
+ NEXT_INST_F((found ? 5 : TclGetInt4AtPtr(pc+1)), 2, 0);
+ case INST_JUMP_TRUE4:
+ NEXT_INST_F((found ? TclGetInt4AtPtr(pc+1) : 5), 2, 0);
+ }
+#endif
+ objResultPtr = Tcl_NewBooleanObj(found);
+ NEXT_INST_F(0, 2, 1);
+ }
+
/*
* End of INST_LIST and related instructions.
* ---------------------------------------------------------