From 13181f107dff6f47161fb25bc780155172c1c112 Mon Sep 17 00:00:00 2001 From: dkf Date: Thu, 7 Dec 2006 15:02:41 +0000 Subject: More #174 bits and pieces --- ChangeLog | 15 +- generic/tclCompCmds.c | 667 +++++++++++++++++++------------------------------- generic/tclMathOp.c | 11 +- tests/mathop.test | 117 ++++++++- 4 files changed, 394 insertions(+), 416 deletions(-) diff --git a/ChangeLog b/ChangeLog index 55c8ecd..a368cf2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2006-12-07 Donal K. Fellows + + * tests/mathop.test: Added tests for ! ~ eq operators. + * generic/tclMathOp.c (TclInvertOpCmd): Add in check for non-integral + numeric values. + * generic/tclCompCmds.c (CompileCompareOpCmd): Factor out the code + generation for the chained comparison operators. + 2006-12-07 Pat Thoyts * tests/exec.test: Fixed line endings (caused win32 problems). @@ -5,14 +13,14 @@ 2006-12-06 Don Porter * generic/tclCompCmds.c: Revised and consolidated into utility - * tests/mathop.c: routines some of routines that compile - the new TIP 174 commands. This corrects some known bugs. More to come. + * tests/mathop.test: routines some of routines that compile + the new TIP 174 commands. This corrects some known bugs. More to come. 2006-12-06 Kevin Kenny * tests/expr.test (expr-47.12): Improved error reporting in hopes of having more information to pursue [Bug 1609936]. - + 2006-12-05 Andreas Kupries TIP#291 IMPLEMENTATION @@ -47,6 +55,7 @@ causing old TM versions to be provided in preference to newer TM versions. Thanks to Julian Noble for discovering the issue. +>>>>>>> 1.3290 2006-12-04 Donal K. Fellows TIP#267 IMPLEMENTATION diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index e1b15cd..5954394 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclCompCmds.c,v 1.95 2006/12/06 21:25:32 dgp Exp $ + * RCS: @(#) $Id: tclCompCmds.c,v 1.96 2006/12/07 15:02:45 dkf Exp $ */ #include "tclInt.h" @@ -31,7 +31,7 @@ TclEmitPush(TclRegisterNewLiteral((envPtr), (tokenPtr)[1].start, \ (tokenPtr)[1].size), (envPtr)); \ } else { \ - envPtr->line = mapPtr->loc [eclIndex].line [word]; \ + envPtr->line = mapPtr->loc[eclIndex].line[word]; \ TclCompileTokens((interp), (tokenPtr)+1, (tokenPtr)->numComponents, \ (envPtr)); \ } @@ -136,10 +136,16 @@ static int PushVarName(Tcl_Interp *interp, int flags, int *localIndexPtr, int *simpleVarNamePtr, int *isScalarPtr, int line); static int CompileAssociativeBinaryOpCmd(Tcl_Interp *interp, - Tcl_Parse *parsePtr, CONST char *identity, - unsigned char instruction, CompileEnv *envPtr); + Tcl_Parse *parsePtr, const char *identity, + int instruction, CompileEnv *envPtr); +static int CompileComparisonOpCmd(Tcl_Interp *interp, + Tcl_Parse *parsePtr, int instruction, + CompileEnv *envPtr); +static int CompileStrictlyBinaryOpCmd(Tcl_Interp *interp, + Tcl_Parse *parsePtr, int instruction, + CompileEnv *envPtr); static int CompileUnaryOpCmd(Tcl_Interp *interp, - Tcl_Parse *parsePtr, unsigned char instruction, + Tcl_Parse *parsePtr, int instruction, CompileEnv *envPtr); /* @@ -192,8 +198,7 @@ TclCompileAppendCmd( { Tcl_Token *varTokenPtr, *valueTokenPtr; int simpleVarName, isScalar, localIndex, numWords; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ numWords = parsePtr->numWords; if (numWords == 1) { @@ -222,7 +227,7 @@ TclCompileAppendCmd( PushVarName(interp, varTokenPtr, envPtr, TCL_CREATE_VAR, &localIndex, &simpleVarName, &isScalar, - mapPtr->loc [eclIndex].line [1]); + mapPtr->loc[eclIndex].line[1]); /* * We are doing an assignment, otherwise TclCompileSetCmd was called, so @@ -328,11 +333,10 @@ TclCompileCatchCmd( { JumpFixup jumpFixup; Tcl_Token *cmdTokenPtr, *resultNameTokenPtr, *optsNameTokenPtr; - CONST char *name; + const char *name; int resultIndex, optsIndex, nameChars, range; int savedStackDepth = envPtr->currStackDepth; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ /* * If syntax does not match what we expect for [catch], do not compile. @@ -407,7 +411,7 @@ TclCompileCatchCmd( * range so that errors in the substitution are not catched [Bug 219184] */ - envPtr->line = mapPtr->loc [eclIndex].line [1]; + envPtr->line = mapPtr->loc[eclIndex].line[1]; if (cmdTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { ExceptionRangeStarts(envPtr, range); CompileBody(envPtr, cmdTokenPtr, interp); @@ -571,8 +575,7 @@ TclCompileDictCmd( int numWords, size, i; const char *cmd; Proc *procPtr = envPtr->procPtr; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ /* * There must be at least one argument after the command. @@ -701,8 +704,7 @@ TclCompileDictCmd( const char **argv; Tcl_DString buffer; int savedStackDepth = envPtr->currStackDepth; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ if (numWords != 3 || procPtr == NULL) { return TCL_ERROR; @@ -802,7 +804,7 @@ TclCompileDictCmd( * Compile the loop body itself. It should be stack-neutral. */ - envPtr->line = mapPtr->loc [eclIndex].line [4]; + envPtr->line = mapPtr->loc[eclIndex].line[4]; CompileBody(envPtr, bodyTokenPtr, interp); envPtr->currStackDepth = savedStackDepth + 1; TclEmitOpcode( INST_POP, envPtr); @@ -1076,9 +1078,13 @@ TclCompileExprCmd( return TCL_ERROR; } - /* TIP #280 : Use the per-word line information of the current command. + /* + * TIP #280 : Use the per-word line information of the current command. */ - envPtr->line = envPtr->extCmdMapPtr->loc [envPtr->extCmdMapPtr->nuloc - 1].line [1]; + + envPtr->line = envPtr->extCmdMapPtr->loc[ + envPtr->extCmdMapPtr->nuloc-1].line[1]; + firstWordPtr = TokenAfter(parsePtr->tokenPtr); TclCompileExprWords(interp, firstWordPtr, parsePtr->numWords-1, envPtr); return TCL_OK; @@ -1114,8 +1120,7 @@ TclCompileForCmd( int testCodeOffset, bodyCodeOffset, nextCodeOffset, jumpDist; int bodyRange, nextRange; int savedStackDepth = envPtr->currStackDepth; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 5) { return TCL_ERROR; @@ -1158,7 +1163,7 @@ TclCompileForCmd( * Inline compile the initial command. */ - envPtr->line = mapPtr->loc [eclIndex].line [1]; + envPtr->line = mapPtr->loc[eclIndex].line[1]; CompileBody(envPtr, startTokenPtr, interp); TclEmitOpcode(INST_POP, envPtr); @@ -1181,7 +1186,7 @@ TclCompileForCmd( */ bodyCodeOffset = ExceptionRangeStarts(envPtr, bodyRange); - envPtr->line = mapPtr->loc [eclIndex].line [4]; + envPtr->line = mapPtr->loc[eclIndex].line[4]; CompileBody(envPtr, bodyTokenPtr, interp); ExceptionRangeEnds(envPtr, bodyRange); envPtr->currStackDepth = savedStackDepth + 1; @@ -1194,7 +1199,7 @@ TclCompileForCmd( envPtr->currStackDepth = savedStackDepth; nextCodeOffset = ExceptionRangeStarts(envPtr, nextRange); - envPtr->line = mapPtr->loc [eclIndex].line [3]; + envPtr->line = mapPtr->loc[eclIndex].line[3]; CompileBody(envPtr, nextTokenPtr, interp); ExceptionRangeEnds(envPtr, nextRange); envPtr->currStackDepth = savedStackDepth + 1; @@ -1215,7 +1220,7 @@ TclCompileForCmd( testCodeOffset += 3; } - envPtr->line = mapPtr->loc [eclIndex].line [2]; + envPtr->line = mapPtr->loc[eclIndex].line[2]; envPtr->currStackDepth = savedStackDepth; TclCompileExprWords(interp, testTokenPtr, 1, envPtr); envPtr->currStackDepth = savedStackDepth + 1; @@ -1290,9 +1295,8 @@ TclCompileForeachCmd( int jumpBackDist, jumpBackOffset, infoIndex, range; int numWords, numLists, numVars, loopIndex, tempVar, i, j, code; int savedStackDepth = envPtr->currStackDepth; - - DefineLineInformation; /* TIP #280 */ - int bodyIndex; + DefineLineInformation; /* TIP #280 */ + int bodyIndex; /* * We parse the variable list argument words and create two arrays: @@ -1302,9 +1306,9 @@ TclCompileForeachCmd( #define STATIC_VAR_LIST_SIZE 5 int varcListStaticSpace[STATIC_VAR_LIST_SIZE]; - CONST char **varvListStaticSpace[STATIC_VAR_LIST_SIZE]; + const char **varvListStaticSpace[STATIC_VAR_LIST_SIZE]; int *varcList = varcListStaticSpace; - CONST char ***varvList = varvListStaticSpace; + const char ***varvList = varvListStaticSpace; /* * If the foreach command isn't in a procedure, don't compile it inline: @@ -1341,7 +1345,7 @@ TclCompileForeachCmd( numLists = (numWords - 2)/2; if (numLists > STATIC_VAR_LIST_SIZE) { varcList = (int *) ckalloc(numLists * sizeof(int)); - varvList = (CONST char ***) ckalloc(numLists * sizeof(CONST char **)); + varvList = (const char ***) ckalloc(numLists * sizeof(const char **)); } for (loopIndex = 0; loopIndex < numLists; loopIndex++) { varcList[loopIndex] = 0; @@ -1384,7 +1388,7 @@ TclCompileForeachCmd( } numVars = varcList[loopIndex]; for (j = 0; j < numVars; j++) { - CONST char *varName = varvList[loopIndex][j]; + const char *varName = varvList[loopIndex][j]; if (!TclIsLocalScalar(varName, (int) strlen(varName))) { code = TCL_ERROR; goto done; @@ -1433,7 +1437,7 @@ TclCompileForeachCmd( sizeof(ForeachVarList) + numVars*sizeof(int)); varListPtr->numVars = numVars; for (j = 0; j < numVars; j++) { - CONST char *varName = varvList[loopIndex][j]; + const char *varName = varvList[loopIndex][j]; int nameChars = strlen(varName); varListPtr->varIndexes[j] = TclFindCompiledLocal(varName, @@ -1458,7 +1462,7 @@ TclCompileForeachCmd( i < numWords-1; i++, tokenPtr = TokenAfter(tokenPtr)) { if ((i%2 == 0) && (i > 0)) { - envPtr->line = mapPtr->loc [eclIndex].line [i]; + envPtr->line = mapPtr->loc[eclIndex].line[i]; CompileTokens(envPtr, tokenPtr, interp); tempVar = (firstValueTemp + loopIndex); if (tempVar <= 255) { @@ -1490,7 +1494,7 @@ TclCompileForeachCmd( * Inline compile the loop body. */ - envPtr->line = mapPtr->loc [eclIndex].line [bodyIndex]; + envPtr->line = mapPtr->loc[eclIndex].line[bodyIndex]; ExceptionRangeStarts(envPtr, range); CompileBody(envPtr, bodyTokenPtr, interp); ExceptionRangeEnds(envPtr, range); @@ -1689,7 +1693,7 @@ TclCompileIfCmd( int jumpFalseDist; int jumpIndex = 0; /* Avoid compiler warning. */ int numWords, wordIdx, numBytes, j, code; - CONST char *word; + const char *word; int savedStackDepth = envPtr->currStackDepth; /* Saved stack depth at the start of the first * test; the envPtr current depth is restored @@ -1698,8 +1702,7 @@ TclCompileIfCmd( * "if 0 {..}" */ int boolVal; /* Value of static condition */ int compileScripts = 1; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ /* * Only compile the "if" command if all arguments are simple words, in @@ -1776,7 +1779,7 @@ TclCompileIfCmd( compileScripts = 0; } } else { - envPtr->line = mapPtr->loc [eclIndex].line [wordIdx]; + envPtr->line = mapPtr->loc[eclIndex].line[wordIdx]; Tcl_ResetResult(interp); TclCompileExprWords(interp, testTokenPtr, 1, envPtr); if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) { @@ -1819,7 +1822,7 @@ TclCompileIfCmd( */ if (compileScripts) { - envPtr->line = mapPtr->loc [eclIndex].line [wordIdx]; + envPtr->line = mapPtr->loc[eclIndex].line[wordIdx]; envPtr->currStackDepth = savedStackDepth; CompileBody(envPtr, tokenPtr, interp); } @@ -1907,7 +1910,7 @@ TclCompileIfCmd( * Compile the else command body. */ - envPtr->line = mapPtr->loc [eclIndex].line [wordIdx]; + envPtr->line = mapPtr->loc[eclIndex].line[wordIdx]; CompileBody(envPtr, tokenPtr, interp); } @@ -1998,8 +2001,7 @@ TclCompileIncrCmd( { Tcl_Token *varTokenPtr, *incrTokenPtr; int simpleVarName, isScalar, localIndex, haveImmValue, immValue; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) { return TCL_ERROR; @@ -2009,7 +2011,7 @@ TclCompileIncrCmd( PushVarName(interp, varTokenPtr, envPtr, TCL_NO_LARGE_INDEX|TCL_CREATE_VAR, &localIndex, &simpleVarName, &isScalar, - mapPtr->loc [eclIndex].line [1]); + mapPtr->loc[eclIndex].line[1]); /* * If an increment is given, push it, but see first if it's a small @@ -2021,7 +2023,7 @@ TclCompileIncrCmd( if (parsePtr->numWords == 3) { incrTokenPtr = TokenAfter(varTokenPtr); if (incrTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { - CONST char *word = incrTokenPtr[1].start; + const char *word = incrTokenPtr[1].start; int numBytes = incrTokenPtr[1].size; int code; Tcl_Obj *intObj = Tcl_NewStringObj(word, numBytes); @@ -2035,7 +2037,7 @@ TclCompileIncrCmd( PushLiteral(envPtr, word, numBytes); } } else { - envPtr->line = mapPtr->loc [eclIndex].line [2]; + envPtr->line = mapPtr->loc[eclIndex].line[2]; CompileTokens(envPtr, incrTokenPtr, interp); } } else { /* No incr amount given so use 1 */ @@ -2116,8 +2118,7 @@ TclCompileLappendCmd( { Tcl_Token *varTokenPtr; int simpleVarName, isScalar, localIndex, numWords; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ /* * If we're not in a procedure, don't compile. @@ -2149,7 +2150,7 @@ TclCompileLappendCmd( PushVarName(interp, varTokenPtr, envPtr, TCL_CREATE_VAR, &localIndex, &simpleVarName, &isScalar, - mapPtr->loc [eclIndex].line [1]); + mapPtr->loc[eclIndex].line[1]); /* * If we are doing an assignment, push the new value. In the no values @@ -2221,8 +2222,7 @@ TclCompileLassignCmd( { Tcl_Token *tokenPtr; int simpleVarName, isScalar, localIndex, numWords, idx; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ numWords = parsePtr->numWords; /* @@ -2249,7 +2249,7 @@ TclCompileLassignCmd( */ PushVarName(interp, tokenPtr, envPtr, TCL_CREATE_VAR, &localIndex, &simpleVarName, &isScalar, - mapPtr->loc [eclIndex].line [idx+2]); + mapPtr->loc[eclIndex].line[idx+2]); /* * Emit instructions to get the idx'th item out of the list value on @@ -2329,8 +2329,7 @@ TclCompileLindexCmd( { Tcl_Token *varTokenPtr; int i, numWords = parsePtr->numWords; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ /* * Quit if too few args @@ -2419,7 +2418,7 @@ TclCompileListCmd( * created by Tcl_ParseCommand. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ /* * If we're not in a procedure, don't compile. @@ -2480,8 +2479,7 @@ TclCompileLlengthCmd( CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *varTokenPtr; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 2) { return TCL_ERROR; @@ -2548,8 +2546,7 @@ TclCompileLsetCmd( int simpleVarName; /* Flag == 1 if var name is simple */ int isScalar; /* Flag == 1 if scalar, 0 if array */ int i; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ /* * Check argument count. @@ -2574,7 +2571,7 @@ TclCompileLsetCmd( varTokenPtr = TokenAfter(parsePtr->tokenPtr); PushVarName(interp, varTokenPtr, envPtr, TCL_CREATE_VAR, &localIndex, &simpleVarName, &isScalar, - mapPtr->loc [eclIndex].line [1]); + mapPtr->loc[eclIndex].line[1]); /* * Push the "index" args and the new element value. @@ -2701,8 +2698,7 @@ TclCompileRegexpCmd( * parse of the RE or string */ int i, len, nocase, anchorLeft, anchorRight, start; char *str; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ /* * We are only interested in compiling simple regexp cases. Currently @@ -2914,8 +2910,7 @@ TclCompileReturnCmd( #define NUM_STATIC_OBJS 20 int objc; Tcl_Obj *staticObjArray[NUM_STATIC_OBJS], **objv; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ /* * Check for special case which can always be compiled: @@ -3069,8 +3064,7 @@ TclCompileSetCmd( { Tcl_Token *varTokenPtr, *valueTokenPtr; int isAssignment, isScalar, simpleVarName, localIndex, numWords; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ numWords = parsePtr->numWords; if ((numWords != 2) && (numWords != 3)) { @@ -3089,7 +3083,7 @@ TclCompileSetCmd( varTokenPtr = TokenAfter(parsePtr->tokenPtr); PushVarName(interp, varTokenPtr, envPtr, TCL_CREATE_VAR, &localIndex, &simpleVarName, &isScalar, - mapPtr->loc [eclIndex].line [1]); + mapPtr->loc[eclIndex].line[1]); /* * If we are doing an assignment, push the new value. @@ -3167,11 +3161,12 @@ TclCompileStringCmd( * created by Tcl_ParseCommand. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { + DefineLineInformation; /* TIP #280 */ Tcl_Token *opTokenPtr, *varTokenPtr; Tcl_Obj *opObj; int i, index; - static CONST char *options[] = { + static const char *options[] = { "bytelength", "compare", "equal", "first", "index", "is", "last", "length", "map", "match", "range", "repeat", @@ -3188,8 +3183,6 @@ TclCompileStringCmd( STR_WORDEND, STR_WORDSTART }; - DefineLineInformation; /* TIP #280 */ - if (parsePtr->numWords < 2) { /* * Fail at run time, not in compilation. @@ -3257,7 +3250,7 @@ TclCompileStringCmd( return TCL_OK; case STR_MATCH: { int length, exactMatch = 0, nocase = 0; - CONST char *str; + const char *str; if (parsePtr->numWords < 4 || parsePtr->numWords > 5) { /* @@ -3304,7 +3297,7 @@ TclCompileStringCmd( } PushLiteral(envPtr, str, length); } else { - envPtr->line = mapPtr->loc [eclIndex].line [i]; + envPtr->line = mapPtr->loc[eclIndex].line[i]; CompileTokens(envPtr, varTokenPtr, interp); } varTokenPtr = TokenAfter(varTokenPtr); @@ -3340,7 +3333,7 @@ TclCompileStringCmd( PushLiteral(envPtr, buf, len); return TCL_OK; } else { - envPtr->line = mapPtr->loc [eclIndex].line [2]; + envPtr->line = mapPtr->loc[eclIndex].line[2]; CompileTokens(envPtr, varTokenPtr, interp); } TclEmitOpcode(INST_STR_LEN, envPtr); @@ -3413,9 +3406,8 @@ TclCompileSwitchCmd( int foundMode = 0; /* Have we seen a mode flag yet? */ int isListedArms = 0; int i; - - DefineLineInformation; /* TIP #280 */ - int valueIndex; + DefineLineInformation; /* TIP #280 */ + int valueIndex; /* * Only handle the following versions: @@ -3447,7 +3439,7 @@ TclCompileSwitchCmd( mode = Switch_Exact; for (; numWords>=3 ; tokenPtr=TokenAfter(tokenPtr),numWords--) { register unsigned size = tokenPtr[1].size; - register CONST char *chrs = tokenPtr[1].start; + register const char *chrs = tokenPtr[1].start; /* * We only process literal options, and we assume that -e, -g and -n @@ -3527,17 +3519,18 @@ TclCompileSwitchCmd( if (numWords == 1) { Tcl_DString bodyList; - CONST char **argv = NULL; + const char **argv = NULL; int isTokenBraced; - CONST char *tokenStartPtr; + const char *tokenStartPtr; - /* TIP #280: line of the pattern/action list, and start of list for + /* + * TIP #280: line of the pattern/action list, and start of list for * when tracking the location. This list comes immediately after the * value we switch on. */ - int bline = mapPtr->loc [eclIndex].line [valueIndex+1]; - CONST char* p; + int bline = mapPtr->loc[eclIndex].line[valueIndex+1]; + const char* p; /* * Test that we've got a suitable body list as a simple (i.e. braced) @@ -3570,9 +3563,9 @@ TclCompileSwitchCmd( } isListedArms = 1; - bodyTokenArray = (Tcl_Token *) ckalloc(sizeof(Tcl_Token) * numWords); - bodyToken = (Tcl_Token **) ckalloc(sizeof(Tcl_Token *) * numWords); - bodyLines = (int*) ckalloc(sizeof(int) * numWords); + bodyTokenArray = (Tcl_Token *) ckalloc(sizeof(Tcl_Token) * numWords); + bodyToken = (Tcl_Token **) ckalloc(sizeof(Tcl_Token *) * numWords); + bodyLines = (int *) ckalloc(sizeof(int) * numWords); /* * Locate the start of the arms within the overall word. @@ -3589,7 +3582,10 @@ TclCompileSwitchCmd( isTokenBraced = 0; } - /* TIP #280. Count lines within the literal list */ + /* + * TIP #280. Count lines within the literal list. + */ + for (i=0 ; iloc [eclIndex].line [valueIndex+1+i]; + + /* + * TIP#280: Copy line information from regular cmd info. + */ + + bodyLines[i] = mapPtr->loc[eclIndex].line[valueIndex+1+i]; tokenPtr = TokenAfter(tokenPtr); } } @@ -3709,7 +3711,7 @@ TclCompileSwitchCmd( * First, we push the value we're matching against on the stack. */ - envPtr->line = mapPtr->loc [eclIndex].line [valueIndex]; + envPtr->line = mapPtr->loc[eclIndex].line[valueIndex]; CompileTokens(envPtr, valueTokenPtr, interp); /* @@ -3830,8 +3832,7 @@ TclCompileSwitchCmd( * Compile the body of the arm. */ - /* #280 */ - envPtr->line = bodyLines [i+1]; + envPtr->line = bodyLines[i+1]; /* TIP#280 */ TclCompileCmdWord(interp, bodyToken[i+1], 1, envPtr); /* @@ -3982,8 +3983,7 @@ TclCompileSwitchCmd( TclEmitOpcode(INST_POP, envPtr); envPtr->currStackDepth = savedStackDepth + 1; - /* #280 */ - envPtr->line = bodyLines [i+1]; + envPtr->line = bodyLines[i+1]; /* #280 */ TclCompileCmdWord(interp, bodyToken[i+1], 1, envPtr); if (!foundDefault) { @@ -4130,7 +4130,7 @@ TclCompileVariableCmd( { Tcl_Token *varTokenPtr; int i, numWords; - CONST char *varName, *tail; + const char *varName, *tail; if (envPtr->procPtr == NULL) { return TCL_ERROR; @@ -4204,8 +4204,7 @@ TclCompileWhileCmd( * infinite loop. */ Tcl_Obj *boolObj; int boolVal; - - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 3) { return TCL_ERROR; @@ -4286,7 +4285,7 @@ TclCompileWhileCmd( * Compile the loop body. */ - envPtr->line = mapPtr->loc [eclIndex].line [2]; + envPtr->line = mapPtr->loc[eclIndex].line[2]; bodyCodeOffset = ExceptionRangeStarts(envPtr, range); CompileBody(envPtr, bodyTokenPtr, interp); ExceptionRangeEnds(envPtr, range); @@ -4306,7 +4305,7 @@ TclCompileWhileCmd( testCodeOffset += 3; } envPtr->currStackDepth = savedStackDepth; - envPtr->line = mapPtr->loc [eclIndex].line [1]; + envPtr->line = mapPtr->loc[eclIndex].line[1]; TclCompileExprWords(interp, testTokenPtr, 1, envPtr); envPtr->currStackDepth = savedStackDepth + 1; @@ -4375,8 +4374,8 @@ PushVarName( int *isScalarPtr, /* Must not be NULL */ int line) /* line the token starts on */ { - register CONST char *p; - CONST char *name, *elName; + register const char *p; + const char *name, *elName; register int i, n; int nameChars, elNameChars, simpleVarName, localIndex; @@ -4606,11 +4605,11 @@ static int CompileUnaryOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, - unsigned char instruction, + int instruction, CompileEnv *envPtr) { Tcl_Token *tokenPtr; - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 2) { return TCL_ERROR; @@ -4647,12 +4646,12 @@ static int CompileAssociativeBinaryOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, - CONST char *identity, - unsigned char instruction, + const char *identity, + int instruction, CompileEnv *envPtr) { Tcl_Token *tokenPtr = parsePtr->tokenPtr; - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ int words; if (parsePtr->numWords == 1) { @@ -4692,7 +4691,7 @@ static int CompileStrictlyBinaryOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, - unsigned char instruction, + int instruction, CompileEnv *envPtr) { if (parsePtr->numWords != 3) { @@ -4705,6 +4704,100 @@ CompileStrictlyBinaryOpCmd( /* *---------------------------------------------------------------------- * + * CompileComparisonOpCmd -- + * + * Utility routine to compile the n-ary comparison operator commands. + * + * Results: + * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer + * evaluation to runtime. + * + * Side effects: + * Instructions are added to envPtr to execute the compiled command at + * runtime. + * + *---------------------------------------------------------------------- + */ + +static int +CompileComparisonOpCmd( + Tcl_Interp *interp, + Tcl_Parse *parsePtr, + int instruction, + CompileEnv *envPtr) +{ + Tcl_Token *tokenPtr; + DefineLineInformation; /* TIP #280 */ + + if (parsePtr->numWords < 3) { + PushLiteral(envPtr, "1", 1); + } else if (parsePtr->numWords == 3) { + tokenPtr = TokenAfter(parsePtr->tokenPtr); + CompileWord(envPtr, tokenPtr, interp, 1); + tokenPtr = TokenAfter(tokenPtr); + CompileWord(envPtr, tokenPtr, interp, 2); + TclEmitOpcode(instruction, envPtr); + } else if (envPtr->procPtr == NULL) { + /* + * No local variable space! + */ + + return TCL_ERROR; + } else { + int tmpIndex = TclFindCompiledLocal(NULL, 0, 1, VAR_SCALAR, + envPtr->procPtr); + int words; + + tokenPtr = TokenAfter(parsePtr->tokenPtr); + CompileWord(envPtr, tokenPtr, interp, 1); + tokenPtr = TokenAfter(tokenPtr); + CompileWord(envPtr, tokenPtr, interp, 2); + if (tmpIndex <= 255) { + TclEmitInstInt1(INST_STORE_SCALAR1, tmpIndex, envPtr); + } else { + TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); + } + TclEmitOpcode(instruction, envPtr); + for (words=3 ; wordsnumWords ;) { + if (tmpIndex <= 255) { + TclEmitInstInt1(INST_LOAD_SCALAR1, tmpIndex, envPtr); + } else { + TclEmitInstInt4(INST_LOAD_SCALAR4, tmpIndex, envPtr); + } + tokenPtr = TokenAfter(tokenPtr); + CompileWord(envPtr, tokenPtr, interp, words); + if (++words < parsePtr->numWords) { + if (tmpIndex <= 255) { + TclEmitInstInt1(INST_STORE_SCALAR1, tmpIndex, envPtr); + } else { + TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); + } + } + TclEmitOpcode(instruction, envPtr); + } + for (; words>3 ; words--) { + TclEmitOpcode(INST_BITAND, envPtr); + } + + /* + * Drop the value from the temp variable; retaining that reference + * might be expensive elsewhere. + */ + + PushLiteral(envPtr, "", 0); + if (tmpIndex <= 255) { + TclEmitInstInt1(INST_STORE_SCALAR1, tmpIndex, envPtr); + } else { + TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); + } + TclEmitOpcode(INST_POP, envPtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * TclCompile*OpCmd -- * * Procedures called to compile the corresponding @@ -4729,7 +4822,7 @@ TclCompileInvertOpCmd( { return CompileUnaryOpCmd(interp, parsePtr, INST_BITNOT, envPtr); } - + int TclCompileNotOpCmd( Tcl_Interp *interp, @@ -4745,50 +4838,50 @@ TclCompileAddOpCmd( Tcl_Parse *parsePtr, CompileEnv *envPtr) { - return CompileAssociativeBinaryOpCmd(interp, parsePtr, - "0", INST_ADD, envPtr); + return CompileAssociativeBinaryOpCmd(interp, parsePtr, "0", INST_ADD, + envPtr); } - + int TclCompileMulOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr) { - return CompileAssociativeBinaryOpCmd(interp, parsePtr, - "1", INST_MULT, envPtr); + return CompileAssociativeBinaryOpCmd(interp, parsePtr, "1", INST_MULT, + envPtr); } - + int TclCompileAndOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr) { - return CompileAssociativeBinaryOpCmd(interp, parsePtr, - "-1", INST_BITAND, envPtr); + return CompileAssociativeBinaryOpCmd(interp, parsePtr, "-1", INST_BITAND, + envPtr); } - + int TclCompileOrOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr) { - return CompileAssociativeBinaryOpCmd(interp, parsePtr, - "0", INST_BITOR, envPtr); + return CompileAssociativeBinaryOpCmd(interp, parsePtr, "0", INST_BITOR, + envPtr); } - + int TclCompileXorOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr) { - return CompileAssociativeBinaryOpCmd(interp, parsePtr, - "0", INST_BITXOR, envPtr); + return CompileAssociativeBinaryOpCmd(interp, parsePtr, "0", INST_BITXOR, + envPtr); } - + int TclCompilePowOpCmd( Tcl_Interp *interp, @@ -4796,11 +4889,12 @@ TclCompilePowOpCmd( CompileEnv *envPtr) { /* - * The ** operator isn't associative, but the right to left - * calculation order of the called routine is correct + * The ** operator isn't associative, but the right to left calculation + * order of the called routine is correct. */ - return CompileAssociativeBinaryOpCmd(interp, parsePtr, - "1", INST_EXPON, envPtr); + + return CompileAssociativeBinaryOpCmd(interp, parsePtr, "1", INST_EXPON, + envPtr); } /* @@ -4817,14 +4911,13 @@ TclCompilePowOpCmd( * = - ((d + c + b) - a) * = (a - (d + c + b)) * - * So after word compilation puts the substituted arguments on the - * stack in reverse order, we don't have to turn them around again - * and apply repeated INST_SUB instructions. Instead we keep them - * in reverse order and apply a different sequence of instructions. - * For N arguments, we apply N-2 INST_ADDs, then one INST_SUB. - * Note that this does the right thing for N=2, a single INST_SUB. - * When N=1, we can add a phony leading "0" argument and get the - * right result from the same algorithm as well. + * So after word compilation puts the substituted arguments on the stack in + * reverse order, we don't have to turn them around again and apply repeated + * INST_SUB instructions. Instead we keep them in reverse order and apply a + * different sequence of instructions. For N arguments, we apply N-2 + * INST_ADDs, then one INST_SUB. Note that this does the right thing for N=2, + * a single INST_SUB. When N=1, we can add a phony leading "0" argument and + * get the right result from the same algorithm as well. */ int @@ -4834,7 +4927,7 @@ TclCompileMinusOpCmd( CompileEnv *envPtr) { Tcl_Token *tokenPtr = parsePtr->tokenPtr; - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ int words; if (parsePtr->numWords == 1) { @@ -4864,7 +4957,7 @@ TclCompileDivOpCmd( CompileEnv *envPtr) { Tcl_Token *tokenPtr; - DefineLineInformation; /* TIP #280 */ + DefineLineInformation; /* TIP #280 */ int words; if (parsePtr->numWords == 1) { @@ -4894,7 +4987,7 @@ TclCompileLshiftOpCmd( { return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_LSHIFT, envPtr); } - + int TclCompileRshiftOpCmd( Tcl_Interp *interp, @@ -4903,7 +4996,7 @@ TclCompileRshiftOpCmd( { return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_RSHIFT, envPtr); } - + int TclCompileModOpCmd( Tcl_Interp *interp, @@ -4912,7 +5005,7 @@ TclCompileModOpCmd( { return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_MOD, envPtr); } - + int TclCompileNeqOpCmd( Tcl_Interp *interp, @@ -4921,7 +5014,7 @@ TclCompileNeqOpCmd( { return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_NEQ, envPtr); } - + int TclCompileStrneqOpCmd( Tcl_Interp *interp, @@ -4930,7 +5023,7 @@ TclCompileStrneqOpCmd( { return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_STR_NEQ, envPtr); } - + int TclCompileInOpCmd( Tcl_Interp *interp, @@ -4939,15 +5032,15 @@ TclCompileInOpCmd( { return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_LIST_IN, envPtr); } - + int TclCompileNiOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr) { - return CompileStrictlyBinaryOpCmd(interp, parsePtr, - INST_LIST_NOT_IN, envPtr); + return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_LIST_NOT_IN, + envPtr); } int @@ -4956,298 +5049,52 @@ TclCompileLessOpCmd( Tcl_Parse *parsePtr, CompileEnv *envPtr) { - Tcl_Token *tokenPtr; - DefineLineInformation; /* TIP #280 */ - - if (parsePtr->numWords < 3) { - PushLiteral(envPtr, "1", 1); - } else if (parsePtr->numWords == 3) { - tokenPtr = TokenAfter(parsePtr->tokenPtr); - CompileWord(envPtr, tokenPtr, interp,1); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,2); - TclEmitOpcode(INST_LT, envPtr); - } else if (envPtr->procPtr == NULL) { - /* - * No local variable space! - */ - - return TCL_ERROR; - } else { - int tmpIndex = TclFindCompiledLocal(NULL, 0, 1, VAR_SCALAR, - envPtr->procPtr); - int words; - - tokenPtr = TokenAfter(parsePtr->tokenPtr); - CompileWord(envPtr, tokenPtr, interp,1); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,2); - TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); - TclEmitOpcode(INST_LT, envPtr); - for (words=3 ; wordsnumWords ;) { - TclEmitInstInt4(INST_LOAD_SCALAR4, tmpIndex, envPtr); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp, words); - if (++words < parsePtr->numWords) { - TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); - } - TclEmitOpcode(INST_LT, envPtr); - } - for (; words>3 ; words--) { - TclEmitOpcode(INST_BITAND, envPtr); - } - } - return TCL_OK; + return CompileComparisonOpCmd(interp, parsePtr, INST_LT, envPtr); } - + int TclCompileLeqOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr) { - Tcl_Token *tokenPtr; - DefineLineInformation; /* TIP #280 */ - - if (parsePtr->numWords < 3) { - PushLiteral(envPtr, "1", 1); - } else if (parsePtr->numWords == 3) { - tokenPtr = TokenAfter(parsePtr->tokenPtr); - CompileWord(envPtr, tokenPtr, interp,1); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,2); - TclEmitOpcode(INST_LE, envPtr); - } else if (envPtr->procPtr == NULL) { - /* - * No local variable space! - */ - - return TCL_ERROR; - } else { - int tmpIndex = TclFindCompiledLocal(NULL, 0, 1, VAR_SCALAR, - envPtr->procPtr); - int words; - - tokenPtr = TokenAfter(parsePtr->tokenPtr); - CompileWord(envPtr, tokenPtr, interp,1); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,2); - TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); - TclEmitOpcode(INST_LE, envPtr); - for (words=3 ; wordsnumWords ;) { - TclEmitInstInt4(INST_LOAD_SCALAR4, tmpIndex, envPtr); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,words); - if (++words < parsePtr->numWords) { - TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); - } - TclEmitOpcode(INST_LE, envPtr); - } - for (; words>3 ; words--) { - TclEmitOpcode(INST_BITAND, envPtr); - } - } - return TCL_OK; + return CompileComparisonOpCmd(interp, parsePtr, INST_LE, envPtr); } - + int TclCompileGreaterOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr) { - Tcl_Token *tokenPtr; - DefineLineInformation; /* TIP #280 */ - - if (parsePtr->numWords < 3) { - PushLiteral(envPtr, "1", 1); - } else if (parsePtr->numWords == 3) { - tokenPtr = TokenAfter(parsePtr->tokenPtr); - CompileWord(envPtr, tokenPtr, interp,1); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,2); - TclEmitOpcode(INST_GT, envPtr); - } else if (envPtr->procPtr == NULL) { - /* - * No local variable space! - */ - - return TCL_ERROR; - } else { - int tmpIndex = TclFindCompiledLocal(NULL, 0, 1, VAR_SCALAR, - envPtr->procPtr); - int words; - - tokenPtr = TokenAfter(parsePtr->tokenPtr); - CompileWord(envPtr, tokenPtr, interp,1); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,2); - TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); - TclEmitOpcode(INST_GT, envPtr); - for (words=3 ; wordsnumWords ;) { - TclEmitInstInt4(INST_LOAD_SCALAR4, tmpIndex, envPtr); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,words); - if (++words < parsePtr->numWords) { - TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); - } - TclEmitOpcode(INST_GT, envPtr); - } - for (; words>3 ; words--) { - TclEmitOpcode(INST_BITAND, envPtr); - } - } - return TCL_OK; + return CompileComparisonOpCmd(interp, parsePtr, INST_GT, envPtr); } - + int TclCompileGeqOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr) { - Tcl_Token *tokenPtr; - DefineLineInformation; /* TIP #280 */ - - if (parsePtr->numWords < 3) { - PushLiteral(envPtr, "1", 1); - } else if (parsePtr->numWords == 3) { - tokenPtr = TokenAfter(parsePtr->tokenPtr); - CompileWord(envPtr, tokenPtr, interp,1); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,2); - TclEmitOpcode(INST_GE, envPtr); - } else if (envPtr->procPtr == NULL) { - /* - * No local variable space! - */ - - return TCL_ERROR; - } else { - int tmpIndex = TclFindCompiledLocal(NULL, 0, 1, VAR_SCALAR, - envPtr->procPtr); - int words; - - tokenPtr = TokenAfter(parsePtr->tokenPtr); - CompileWord(envPtr, tokenPtr, interp,1); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,2); - TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); - TclEmitOpcode(INST_GE, envPtr); - for (words=3 ; wordsnumWords ;) { - TclEmitInstInt4(INST_LOAD_SCALAR4, tmpIndex, envPtr); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp, words); - if (++words < parsePtr->numWords) { - TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); - } - TclEmitOpcode(INST_GE, envPtr); - } - for (; words>3 ; words--) { - TclEmitOpcode(INST_BITAND, envPtr); - } - } - return TCL_OK; + return CompileComparisonOpCmd(interp, parsePtr, INST_GE, envPtr); } - + int TclCompileEqOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr) { - Tcl_Token *tokenPtr; - DefineLineInformation; /* TIP #280 */ - - if (parsePtr->numWords < 3) { - PushLiteral(envPtr, "1", 1); - } else if (parsePtr->numWords == 3) { - tokenPtr = TokenAfter(parsePtr->tokenPtr); - CompileWord(envPtr, tokenPtr, interp,1); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,2); - TclEmitOpcode(INST_EQ, envPtr); - } else if (envPtr->procPtr == NULL) { - /* - * No local variable space! - */ - - return TCL_ERROR; - } else { - int tmpIndex = TclFindCompiledLocal(NULL, 0, 1, VAR_SCALAR, - envPtr->procPtr); - int words; - - tokenPtr = TokenAfter(parsePtr->tokenPtr); - CompileWord(envPtr, tokenPtr, interp,1); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,2); - TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); - TclEmitOpcode(INST_EQ, envPtr); - for (words=3 ; wordsnumWords ;) { - TclEmitInstInt4(INST_LOAD_SCALAR4, tmpIndex, envPtr); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp, words); - if (++words < parsePtr->numWords) { - TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); - } - TclEmitOpcode(INST_EQ, envPtr); - } - for (; words>3 ; words--) { - TclEmitOpcode(INST_BITAND, envPtr); - } - } - return TCL_OK; + return CompileComparisonOpCmd(interp, parsePtr, INST_EQ, envPtr); } - + int TclCompileStreqOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr) { - Tcl_Token *tokenPtr; - DefineLineInformation; /* TIP #280 */ - - if (parsePtr->numWords < 3) { - PushLiteral(envPtr, "1", 1); - } else if (parsePtr->numWords == 3) { - tokenPtr = TokenAfter(parsePtr->tokenPtr); - CompileWord(envPtr, tokenPtr, interp,1); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,2); - TclEmitOpcode(INST_STR_EQ, envPtr); - } else if (envPtr->procPtr == NULL) { - /* - * No local variable space! - */ - - return TCL_ERROR; - } else { - int tmpIndex = TclFindCompiledLocal(NULL, 0, 1, VAR_SCALAR, - envPtr->procPtr); - int words; - - tokenPtr = TokenAfter(parsePtr->tokenPtr); - CompileWord(envPtr, tokenPtr, interp,1); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp,2); - TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); - TclEmitOpcode(INST_STR_EQ, envPtr); - for (words=3 ; wordsnumWords ;) { - TclEmitInstInt4(INST_LOAD_SCALAR4, tmpIndex, envPtr); - tokenPtr = TokenAfter(tokenPtr); - CompileWord(envPtr, tokenPtr, interp, words); - if (++words < parsePtr->numWords) { - TclEmitInstInt4(INST_STORE_SCALAR4, tmpIndex, envPtr); - } - TclEmitOpcode(INST_STR_EQ, envPtr); - } - for (; words>3 ; words--) { - TclEmitOpcode(INST_BITAND, envPtr); - } - } - return TCL_OK; + return CompileComparisonOpCmd(interp, parsePtr, INST_STR_EQ, envPtr); } /* diff --git a/generic/tclMathOp.c b/generic/tclMathOp.c index 1a1ebe9..375a546 100644 --- a/generic/tclMathOp.c +++ b/generic/tclMathOp.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclMathOp.c,v 1.2 2006/12/01 14:31:19 dgp Exp $ + * RCS: @(#) $Id: tclMathOp.c,v 1.3 2006/12/07 15:02:46 dkf Exp $ */ #include "tclInt.h" @@ -1066,6 +1066,15 @@ TclInvertOpCmd( return TCL_ERROR; } switch (type) { + case TCL_NUMBER_NAN: + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't use %s as operand of \"~\"", + "non-numeric floating-point value")); + return TCL_ERROR; + case TCL_NUMBER_DOUBLE: + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't use %s as operand of \"~\"", "floating-point value")); + return TCL_ERROR; case TCL_NUMBER_LONG: { long l = *((const long *) val); diff --git a/tests/mathop.test b/tests/mathop.test index 4f10b48..e59011d 100644 --- a/tests/mathop.test +++ b/tests/mathop.test @@ -9,7 +9,7 @@ # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: mathop.test,v 1.2 2006/12/06 18:05:27 dgp Exp $ +# RCS: @(#) $Id: mathop.test,v 1.3 2006/12/07 15:02:46 dkf Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2.1 @@ -20,6 +20,7 @@ if {[lsearch [namespace children] ::tcltest] == -1} { namespace eval ::testmathop { namespace path ::tcl::mathop + variable op ;# stop surprises! test mathop-1.1 {compiled +} { + } 0 test mathop-1.2 {compiled +} { + 1 } 1 @@ -171,7 +172,119 @@ namespace eval ::testmathop { } msg] $msg $x } -result {1 expected 2} - # TODO: ! ~ & | ^ % ** << >> - / == != < <= > >= eq ne in ni + test mathop-3.1 {compiled !} {! 0} 1 + test mathop-3.2 {compiled !} {! 1} 0 + test mathop-3.3 {compiled !} {! false} 1 + test mathop-3.4 {compiled !} {! true} 0 + test mathop-3.5 {compiled !} {! 0.0} 1 + test mathop-3.6 {compiled !} {! 10000000000} 0 + test mathop-3.7 {compiled !} {! 10000000000000000000000000} 0 + test mathop-3.8 {compiled !: errors} -body { + ! foobar + } -returnCodes error -result {expected boolean value but got "foobar"} + test mathop-3.9 {compiled !: errors} -body { + ! 0 0 + } -returnCodes error -result "wrong # args: should be \"! boolean\"" + test mathop-3.10 {compiled !: errors} -body { + ! + } -returnCodes error -result "wrong # args: should be \"! boolean\"" + set op ! + test mathop-3.11 {interpreted !} {$op 0} 1 + test mathop-3.12 {interpreted !} {$op 1} 0 + test mathop-3.13 {interpreted !} {$op false} 1 + test mathop-3.14 {interpreted !} {$op true} 0 + test mathop-3.15 {interpreted !} {$op 0.0} 1 + test mathop-3.16 {interpreted !} {$op 10000000000} 0 + test mathop-3.17 {interpreted !} {$op 10000000000000000000000000} 0 + test mathop-3.18 {interpreted !: errors} -body { + $op foobar + } -returnCodes error -result {expected boolean value but got "foobar"} + test mathop-3.19 {interpreted !: errors} -body { + $op 0 0 + } -returnCodes error -result "wrong # args: should be \"! boolean\"" + test mathop-3.20 {interpreted !: errors} -body { + $op + } -returnCodes error -result "wrong # args: should be \"! boolean\"" + test mathop-3.21 {compiled !: error} -returnCodes error -body { + ! NaN + } -result {floating point value is Not a Number} + test mathop-3.21 {interpreted !: error} -returnCodes error -body { + $op NaN + } -result {floating point value is Not a Number} + + test mathop-4.1 {compiled ~} {~ 0} -1 + test mathop-4.2 {compiled ~} {~ 1} -2 + test mathop-4.3 {compiled ~} {~ 31} -32 + test mathop-4.4 {compiled ~} {~ -127} 126 + test mathop-4.5 {compiled ~} {~ -0} -1 + test mathop-4.6 {compiled ~} {~ 10000000000} -10000000001 + test mathop-4.7 {compiled ~} {~ 10000000000000000000000000} -10000000000000000000000001 + test mathop-4.8 {compiled ~: errors} -body { + ~ foobar + } -returnCodes error -result {expected number but got "foobar"} + test mathop-4.9 {compiled ~: errors} -body { + ~ 0 0 + } -returnCodes error -result "wrong # args: should be \"~ number\"" + test mathop-4.10 {compiled ~: errors} -body { + ~ + } -returnCodes error -result "wrong # args: should be \"~ number\"" + test mathop-4.11 {compiled ~: errors} -returnCodes error -body { + ~ 0.0 + } -result {can't use floating-point value as operand of "~"} + test mathop-4.12 {compiled ~: errors} -returnCodes error -body { + ~ NaN + } -result {can't use non-numeric floating-point value as operand of "~"} + set op ~ + test mathop-4.13 {interpreted ~} {$op 0} -1 + test mathop-4.14 {interpreted ~} {$op 1} -2 + test mathop-4.15 {interpreted ~} {$op 31} -32 + test mathop-4.16 {interpreted ~} {$op -127} 126 + test mathop-4.17 {interpreted ~} {$op -0} -1 + test mathop-4.18 {interpreted ~} {$op 10000000000} -10000000001 + test mathop-4.19 {interpreted ~} {$op 10000000000000000000000000} -10000000000000000000000001 + test mathop-4.20 {interpreted ~: errors} -body { + $op foobar + } -returnCodes error -result {expected number but got "foobar"} + test mathop-4.21 {interpreted ~: errors} -body { + $op 0 0 + } -returnCodes error -result "wrong # args: should be \"~ number\"" + test mathop-4.22 {interpreted ~: errors} -body { + $op + } -returnCodes error -result "wrong # args: should be \"~ number\"" + test mathop-4.23 {interpreted ~: errors} -returnCodes error -body { + $op 0.0 + } -result {can't use floating-point value as operand of "~"} + test mathop-4.24 {interpreted ~: errors} -returnCodes error -body { + $op NaN + } -result {can't use non-numeric floating-point value as operand of "~"} + + test mathop-5.1 {compiled eq} {eq {} a} 0 + test mathop-5.2 {compiled eq} {eq a a} 1 + test mathop-5.3 {compiled eq} {eq a {}} 0 + test mathop-5.4 {compiled eq} {eq a b} 0 + test mathop-5.5 {compiled eq} { eq } 1 + test mathop-5.6 {compiled eq} {eq a} 1 + test mathop-5.7 {compiled eq} {eq a a a} 1 + test mathop-5.8 {compiled eq} {eq a a b} 0 + test mathop-5.9 {compiled eq} -body { + eq a b [error foobar] + } -returnCodes error -result foobar + test mathop-5.10 {compiled eq} {eq NaN Na NaN} 0 + set op eq + test mathop-5.11 {interpreted eq} {$op {} a} 0 + test mathop-5.12 {interpreted eq} {$op a a} 1 + test mathop-5.13 {interpreted eq} {$op a {}} 0 + test mathop-5.14 {interpreted eq} {$op a b} 0 + test mathop-5.15 {interpreted eq} { $op } 1 + test mathop-5.16 {interpreted eq} {$op a} 1 + test mathop-5.17 {interpreted eq} {$op a a a} 1 + test mathop-5.18 {interpreted eq} {$op a a b} 0 + test mathop-5.19 {interpreted eq} -body { + $op a b [error foobar] + } -returnCodes error -result foobar + test mathop-5.20 {interpreted eq} {$op NaN Na NaN} 0 + + # TODO: & | ^ % ** << >> - / == != < <= > >= ne in ni } # cleanup -- cgit v0.12