Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | [e711ffb458] Eliminate TclIsLocalScalar() and revise all callers to use more appropriate facilities. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | core-8-5-branch |
Files: | files | file ages | folders |
SHA1: |
05f7d1ec038b103b9a2e90837496e8db |
User & Date: | dgp 2014-12-19 16:09:20 |
Context
2014-12-19
| ||
17:09 | Revise name and interface of new utility routines to match work already in place on the trunk. check-in: 632abe2721 user: dgp tags: core-8-5-branch | |
16:09 | [e711ffb458] Eliminate TclIsLocalScalar() and revise all callers to use more appropriate facilities. check-in: 05f7d1ec03 user: dgp tags: core-8-5-branch | |
15:55 | New utility routine GetLocalScalarIndex() reduces common caller boilerplate (and fixes a bug!) Closed-Leaf check-in: 8fefc24942 user: dgp tags: bug-e711ffb458 | |
2014-12-13
| ||
02:50 | Add header install flag to OS X GNUMakefile; thanks to Stephan Houben for patch check-in: 89931ded2d user: kevin_walzer tags: core-8-5-branch | |
Changes
Changes to generic/tclCompCmds.c.
︙ | ︙ | |||
148 149 150 151 152 153 154 155 156 157 158 159 160 161 | Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset); static ClientData DupJumptableInfo(ClientData clientData); static void FreeJumptableInfo(ClientData clientData); static void PrintJumptableInfo(ClientData clientData, Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset); static int PushVarName(Tcl_Interp *interp, Tcl_Token *varTokenPtr, CompileEnv *envPtr, int flags, int *localIndexPtr, int *simpleVarNamePtr, int *isScalarPtr, int line, int* clNext); static int CompileAssociativeBinaryOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, const char *identity, | > > | 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset); static ClientData DupJumptableInfo(ClientData clientData); static void FreeJumptableInfo(ClientData clientData); static void PrintJumptableInfo(ClientData clientData, Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset); static int GetLocalScalarIndex(Tcl_Token *tokenPtr, CompileEnv *envPtr, int *indexPtr); static int PushVarName(Tcl_Interp *interp, Tcl_Token *varTokenPtr, CompileEnv *envPtr, int flags, int *localIndexPtr, int *simpleVarNamePtr, int *isScalarPtr, int line, int* clNext); static int CompileAssociativeBinaryOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, const char *identity, |
︙ | ︙ | |||
375 376 377 378 379 380 381 | * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { JumpFixup jumpFixup; Tcl_Token *cmdTokenPtr, *resultNameTokenPtr, *optsNameTokenPtr; | < | < < < < < < < < < < | < < < < < < < < < < < < < < < | < < < < < < < | 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 | * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { JumpFixup jumpFixup; Tcl_Token *cmdTokenPtr, *resultNameTokenPtr, *optsNameTokenPtr; int resultIndex, optsIndex, range; int initStackDepth = envPtr->currStackDepth; int savedStackDepth; DefineLineInformation; /* TIP #280 */ /* * If syntax does not match what we expect for [catch], do not compile. * Let runtime checks determine if syntax has changed. */ if ((parsePtr->numWords < 2) || (parsePtr->numWords > 4)) { return TCL_ERROR; } /* * Make sure the variable names, if any, have no substitutions and just * refer to local scalars. */ resultIndex = optsIndex = -1; cmdTokenPtr = TokenAfter(parsePtr->tokenPtr); if (parsePtr->numWords >= 3) { resultNameTokenPtr = TokenAfter(cmdTokenPtr); if (!GetLocalScalarIndex(resultNameTokenPtr, envPtr, &resultIndex)) { return TCL_ERROR; } if (parsePtr->numWords == 4) { optsNameTokenPtr = TokenAfter(resultNameTokenPtr); if (!GetLocalScalarIndex(optsNameTokenPtr, envPtr, &optsIndex)) { return TCL_ERROR; } } } /* * We will compile the catch command. Declare the exception range |
︙ | ︙ | |||
678 679 680 681 682 683 684 | Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { | | | < < < | | < < < | < < < | 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 | Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr, *varTokenPtr; int i, dictVarIndex; DefineLineInformation; /* TIP #280 */ /* * There must be at least three arguments after the (sub-)command. */ if (parsePtr->numWords < 4) { return TCL_ERROR; } /* * The dictionary variable must be a local scalar that is knowable at * compile time; anything else exceeds the complexity of the opcode. So * discover what the index is. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); if (!GetLocalScalarIndex(varTokenPtr, envPtr, &dictVarIndex)) { return TCL_ERROR; } /* * Remaining words (key path and value to set) can be handled normally. */ tokenPtr = TokenAfter(varTokenPtr); for (i=2 ; i< parsePtr->numWords ; i++) { |
︙ | ︙ | |||
738 739 740 741 742 743 744 | Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { | < < | < > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | > | > | > > > | > > > > > > > | | < > > > | 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 | Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *varTokenPtr, *keyTokenPtr; int dictVarIndex, incrAmount; DefineLineInformation; /* TIP #280 */ /* * There must be at least two arguments after the command. */ if (parsePtr->numWords < 3 || parsePtr->numWords > 4) { return TCL_ERROR; } /* * The dictionary variable must be a local scalar that is knowable at * compile time; anything else exceeds the complexity of the opcode. So * discover what the index is. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); if (!GetLocalScalarIndex(varTokenPtr, envPtr, &dictVarIndex)) { return TCL_ERROR; } keyTokenPtr = TokenAfter(varTokenPtr); /* * Parse the increment amount, if present. */ if (parsePtr->numWords == 4) { Tcl_Token *incrTokenPtr = TokenAfter(keyTokenPtr); Tcl_Obj *intObj = Tcl_NewObj(); int fail = (!TclWordKnownAtCompileTime(incrTokenPtr, intObj) || TCL_ERROR == TclGetIntFromObj(NULL, intObj, &incrAmount)); Tcl_DecrRefCount(intObj); if (fail) { return TCL_ERROR; } } else { incrAmount = 1; } /* * Emit the key and the code to actually do the increment. */ CompileWord(envPtr, keyTokenPtr, interp, 2); TclEmitInstInt4( INST_DICT_INCR_IMM, incrAmount, envPtr); |
︙ | ︙ | |||
853 854 855 856 857 858 859 | Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Proc *procPtr = envPtr->procPtr; | < | | | > > | | | | | < | < < < < | < > < > > | < > < < > > | < > | < > | 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 | Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Proc *procPtr = envPtr->procPtr; Tcl_Token *varsTokenPtr, *dictTokenPtr, *bodyTokenPtr; int keyVarIndex, valueVarIndex, loopRange, catchRange; int infoIndex, jumpDisplacement, bodyTargetOffset, emptyTargetOffset; int numVars, endTargetOffset; int savedStackDepth = envPtr->currStackDepth; /* Needed because jumps confuse the stack * space calculator. */ Tcl_Obj *varNameObj, *varListObj = NULL; Tcl_Token token[2] = {{TCL_TOKEN_SIMPLE_WORD, NULL, 0, 1}, {TCL_TOKEN_TEXT, NULL, 0, 0}}; DefineLineInformation; /* TIP #280 */ /* * There must be exactly three arguments after the command. */ if (parsePtr->numWords != 4 || procPtr == NULL) { return TCL_ERROR; } varsTokenPtr = TokenAfter(parsePtr->tokenPtr); dictTokenPtr = TokenAfter(varsTokenPtr); bodyTokenPtr = TokenAfter(dictTokenPtr); if (bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TCL_ERROR; } /* * Check we've got a pair of variables and that they are local variables. * Then extract their indices in the LVT. */ varListObj = Tcl_NewObj(); if (!TclWordKnownAtCompileTime(varsTokenPtr, varListObj) || TCL_OK != Tcl_ListObjLength(NULL, varListObj, &numVars) || numVars != 2) { Tcl_DecrRefCount(varListObj); return TCL_ERROR; } Tcl_ListObjIndex(NULL, varListObj, 0, &varNameObj); token[1].start = Tcl_GetStringFromObj(varNameObj, &token[1].size); if (!GetLocalScalarIndex(token, envPtr, &keyVarIndex)) { Tcl_DecrRefCount(varListObj); return TCL_ERROR; } Tcl_ListObjIndex(NULL, varListObj, 1, &varNameObj); token[1].start = Tcl_GetStringFromObj(varNameObj, &token[1].size); if (!GetLocalScalarIndex(token, envPtr, &valueVarIndex)) { Tcl_DecrRefCount(varListObj); return TCL_ERROR; } Tcl_DecrRefCount(varListObj); /* * Allocate a temporary variable to store the iterator reference. The * variable will contain a Tcl_DictSearch reference which will be * allocated by INST_DICT_FIRST and disposed when the variable is unset * (at which point it should also have been finished with). */ |
︙ | ︙ | |||
1051 1052 1053 1054 1055 1056 1057 | Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { | < < < | | < < < < < < < > > > < < < | < < < > > < < < < < < < | | < | 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 | Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { int i, dictIndex, numVars, range, infoIndex; Tcl_Token **keyTokenPtrs, *dictVarTokenPtr, *bodyTokenPtr, *tokenPtr; DictUpdateInfo *duiPtr; JumpFixup jumpFixup; DefineLineInformation; /* TIP #280 */ /* * Parse the command. Expect the following: * dict update <lit(eral)> <any> <lit> ?<any> <lit> ...? <lit> */ if ((parsePtr->numWords - 1) & 1) { return TCL_ERROR; } numVars = (parsePtr->numWords - 3) / 2; if (numVars < 1) { return TCL_ERROR; } /* * The dictionary variable must be a local scalar that is knowable at * compile time; anything else exceeds the complexity of the opcode. So * discover what the index is. */ dictVarTokenPtr = TokenAfter(parsePtr->tokenPtr); if (!GetLocalScalarIndex(dictVarTokenPtr, envPtr, &dictIndex)) { return TCL_ERROR; } /* * Assemble the instruction metadata. This is complex enough that it is * represented as auxData; it holds an ordered list of variable indices * that are to be used. */ duiPtr = (DictUpdateInfo *) ckalloc(sizeof(DictUpdateInfo) + sizeof(int) * (numVars - 1)); duiPtr->length = numVars; keyTokenPtrs = (Tcl_Token **) TclStackAlloc(interp, sizeof(Tcl_Token *) * numVars); tokenPtr = TokenAfter(dictVarTokenPtr); for (i=0 ; i<numVars ; i++) { int index; /* * Put keys to one side for later compilation to bytecode. */ keyTokenPtrs[i] = tokenPtr; /* * Variables first need to be checked for sanity. */ tokenPtr = TokenAfter(tokenPtr); if (!GetLocalScalarIndex(tokenPtr, envPtr, &index)) { ckfree((char *) duiPtr); TclStackFree(interp, keyTokenPtrs); return TCL_ERROR; } /* * Stash the index in the auxiliary data. */ duiPtr->varIndices[i] = index; tokenPtr = TokenAfter(tokenPtr); } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { ckfree((char *) duiPtr); TclStackFree(interp, keyTokenPtrs); return TCL_ERROR; } |
︙ | ︙ | |||
1218 1219 1220 1221 1222 1223 1224 | Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { | < < > | < > | | < < < < < | < | < < | 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 | Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; int i, dictVarIndex; DefineLineInformation; /* TIP #280 */ /* * There must be at least two argument after the command. Since we * implement using INST_CONCAT1, make sure the number of arguments * stays within its range. */ if (parsePtr->numWords<4 || parsePtr->numWords>258) { return TCL_ERROR; } /* * Get the index of the local variable that we will be working with. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); if (!GetLocalScalarIndex(tokenPtr, envPtr, &dictVarIndex)) { return TCL_ERROR; } /* * Produce the string to concatenate onto the dictionary entry. */ tokenPtr = TokenAfter(tokenPtr); |
︙ | ︙ | |||
1280 1281 1282 1283 1284 1285 1286 | Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { | < < | < > | < < < | < < < | 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 | Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *varTokenPtr, *keyTokenPtr, *valueTokenPtr; int dictVarIndex; DefineLineInformation; /* TIP #280 */ /* * There must be three arguments after the command. */ if (parsePtr->numWords != 4) { return TCL_ERROR; } varTokenPtr = TokenAfter(parsePtr->tokenPtr); keyTokenPtr = TokenAfter(varTokenPtr); valueTokenPtr = TokenAfter(keyTokenPtr); if (!GetLocalScalarIndex(varTokenPtr, envPtr, &dictVarIndex)) { return TCL_ERROR; } CompileWord(envPtr, keyTokenPtr, interp, 2); CompileWord(envPtr, valueTokenPtr, interp, 3); TclEmitInstInt4( INST_DICT_LAPPEND, dictVarIndex, envPtr); return TCL_OK; } /* |
︙ | ︙ | |||
1611 1612 1613 1614 1615 1616 1617 | Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Proc *procPtr = envPtr->procPtr; | | < < < < > | > < < < < < < < < < | 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 | Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Proc *procPtr = envPtr->procPtr; ForeachInfo *infoPtr = NULL;/* Points to the structure describing this * foreach command. Stored in a AuxData * record in the ByteCode. */ Tcl_Token *tokenPtr, *bodyTokenPtr; Tcl_Token token[2]; unsigned char *jumpPc; JumpFixup jumpFalseFixup; int jumpBackDist, jumpBackOffset, infoIndex, range; int numWords, numLists, tempVar, i, j, code = TCL_OK; int savedStackDepth = envPtr->currStackDepth; Tcl_Obj *varListObj = NULL; DefineLineInformation; /* TIP #280 */ /* * If the foreach command isn't in a procedure, don't compile it inline: * the payoff is too small. */ if (procPtr == NULL) { return TCL_ERROR; |
︙ | ︙ | |||
1663 1664 1665 1666 1667 1668 1669 | } bodyTokenPtr = tokenPtr; if (bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TCL_ERROR; } /* | | > > | | < | < | | > > | > < < < < < < < < < < < < < < < < < < < < > > | > > > > > > | > > | > | | < < < < | < < | < < > | < | < < < < < < < < < < | < < < < < < < < < < < < < < < < | | 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 | } bodyTokenPtr = tokenPtr; if (bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TCL_ERROR; } /* * Create and initialize the ForeachInfo and ForeachVarList data * structures describing this command. Then create a AuxData record * pointing to the ForeachInfo structure. */ numLists = (numWords - 2)/2; infoPtr = (ForeachInfo *) ckalloc((unsigned) sizeof(ForeachInfo) + numLists*sizeof(ForeachVarList *)); infoPtr->numLists = 0; /* Count this up as we go */ /* * Parse each var list into sequence of var names. Don't * compile the foreach inline if any var name needs substitutions or isn't * a scalar, or if any var list needs substitutions. */ varListObj = Tcl_NewObj(); token[0].type = TCL_TOKEN_SIMPLE_WORD; token[0].numComponents = 1; for (i = 0, tokenPtr = parsePtr->tokenPtr; i < numWords-1; i++, tokenPtr = TokenAfter(tokenPtr)) { ForeachVarList *varListPtr; int numVars; if (i%2 != 1) { continue; } /* * If the variable list is empty, we can enter an infinite loop when * the interpreted version would not. Take care to ensure this does * not happen. [Bug 1671138] */ if (!TclWordKnownAtCompileTime(tokenPtr, varListObj) || TCL_OK != Tcl_ListObjLength(NULL, varListObj, &numVars) || numVars == 0) { code = TCL_ERROR; goto done; } varListPtr = (ForeachVarList *) ckalloc((unsigned) sizeof(ForeachVarList) + numVars*sizeof(int)); varListPtr->numVars = numVars; infoPtr->varLists[i/2] = varListPtr; infoPtr->numLists++; for (j = 0; j < numVars; j++) { Tcl_Obj *varNameObj; Tcl_ListObjIndex(NULL, varListObj, j, &varNameObj); token[1].start = Tcl_GetStringFromObj(varNameObj, &token[1].size); if (!GetLocalScalarIndex(token, envPtr, varListPtr->varIndexes + j)) { code = TCL_ERROR; goto done; } } Tcl_SetObjLength(varListObj, 0); } /* * Reserve (numLists + 1) temporary variables: * - numLists temps to hold each value list * - 1 temp for the loop counter (index of next element in each list) * * At this time we don't try to reuse temporaries; if there are two * nonoverlapping foreach loops, they don't share any temps. */ tempVar = TclFindCompiledLocal(NULL, 0, 1, procPtr); infoPtr->firstValueTemp = tempVar; for (i= 1; i < numLists; i++) { TclFindCompiledLocal(NULL, 0, 1, procPtr); } infoPtr->loopCtTemp = TclFindCompiledLocal(NULL, 0, 1, procPtr); infoIndex = TclCreateAuxData(infoPtr, &tclForeachInfoType, envPtr); /* * Create an exception record to handle [break] and [continue]. */ range = DeclareExceptionRange(envPtr, LOOP_EXCEPTION_RANGE); /* * Evaluate then store each value list in the associated temporary. */ for (i = 0, tokenPtr = parsePtr->tokenPtr; i < numWords-1; i++, tokenPtr = TokenAfter(tokenPtr)) { if ((i%2 == 0) && (i > 0)) { SetLineInformation (i); CompileTokens(envPtr, tokenPtr, interp); if (tempVar <= 255) { TclEmitInstInt1(INST_STORE_SCALAR1, tempVar, envPtr); } else { TclEmitInstInt4(INST_STORE_SCALAR4, tempVar, envPtr); } TclEmitOpcode(INST_POP, envPtr); tempVar++; } } /* * Initialize the temporary var that holds the count of loop iterations. */ |
︙ | ︙ | |||
1891 1892 1893 1894 1895 1896 1897 | */ envPtr->currStackDepth = savedStackDepth; PushLiteral(envPtr, "", 0); envPtr->currStackDepth = savedStackDepth + 1; done: | | | | | | > | 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 | */ envPtr->currStackDepth = savedStackDepth; PushLiteral(envPtr, "", 0); envPtr->currStackDepth = savedStackDepth + 1; done: if (code == TCL_ERROR) { if (infoPtr) { FreeForeachInfo(infoPtr); } } if (varListObj) { Tcl_DecrRefCount(varListObj); } return code; } /* *---------------------------------------------------------------------- * * DupForeachInfo -- |
︙ | ︙ | |||
4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 | PushLiteral(envPtr, "", 0); return TCL_OK; } /* *---------------------------------------------------------------------- * * PushVarName -- * * Procedure used in the compiling where pushing a variable name is * necessary (append, lappend, set). * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 | PushLiteral(envPtr, "", 0); return TCL_OK; } /* *---------------------------------------------------------------------- * * GetLocalScalarIndex -- * * Procedure used in the compiling where pushing a variable name is * necessary (append, lappend, set). * * 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 "set" command at * runtime. * *---------------------------------------------------------------------- */ static int GetLocalScalarIndex( Tcl_Token *tokenPtr, CompileEnv *envPtr, int *indexPtr) { int isSimple, isScalar; PushVarName(NULL, tokenPtr, envPtr, TCL_CREATE_VAR, indexPtr, &isSimple, &isScalar, 0 /* ignored */, NULL /* ignored */); return (isScalar && *indexPtr >= 0); } /* *---------------------------------------------------------------------- * * PushVarName -- * * Procedure used in the compiling where pushing a variable name is * necessary (append, lappend, set). * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer |
︙ | ︙ | |||
4926 4927 4928 4929 4930 4931 4932 | elemTokenPtr->type = TCL_TOKEN_TEXT; elemTokenPtr->start = elName; elemTokenPtr->size = elNameChars; elemTokenPtr->numComponents = 0; elemTokenCount = 1; } } | | | 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 | elemTokenPtr->type = TCL_TOKEN_TEXT; elemTokenPtr->start = elName; elemTokenPtr->size = elNameChars; elemTokenPtr->numComponents = 0; elemTokenCount = 1; } } } else if (interp && ((n = varTokenPtr->numComponents) > 1) && (varTokenPtr[1].type == TCL_TOKEN_TEXT) && (varTokenPtr[n].type == TCL_TOKEN_TEXT) && (varTokenPtr[n].start[varTokenPtr[n].size - 1] == ')')) { /* * Check for parentheses inside first token. */ |
︙ | ︙ | |||
5028 5029 5030 5031 5032 5033 5034 | /* * We'll push the name. */ localIndex = -1; } } | | | | | 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 | /* * We'll push the name. */ localIndex = -1; } } if (interp && localIndex < 0) { PushLiteral(envPtr, name, nameChars); } /* * Compile the element script, if any. */ if (interp && elName != NULL) { if (elNameChars) { envPtr->line = line; envPtr->clNext = clNext; TclCompileTokens(interp, elemTokenPtr, elemTokenCount, envPtr); } else { PushLiteral(envPtr, "", 0); } } } else if (interp) { /* * The var name isn't simple: compile and push it. */ envPtr->line = line; envPtr->clNext = clNext; CompileTokens(envPtr, varTokenPtr, interp); |
︙ | ︙ | |||
5766 5767 5768 5769 5770 5771 5772 | Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr, *otherTokenPtr, *localTokenPtr; | | | 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 | Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr, *otherTokenPtr, *localTokenPtr; int localIndex, numWords, i; DefineLineInformation; /* TIP #280 */ Tcl_Obj *objPtr; if (envPtr->procPtr == NULL) { return TCL_ERROR; } |
︙ | ︙ | |||
5829 5830 5831 5832 5833 5834 5835 | * be called at runtime. */ for(; i<numWords; i+=2, otherTokenPtr = TokenAfter(localTokenPtr)) { localTokenPtr = TokenAfter(otherTokenPtr); CompileWord(envPtr, otherTokenPtr, interp, i); | | < < < | 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 | * be called at runtime. */ for(; i<numWords; i+=2, otherTokenPtr = TokenAfter(localTokenPtr)) { localTokenPtr = TokenAfter(otherTokenPtr); CompileWord(envPtr, otherTokenPtr, interp, i); if (!GetLocalScalarIndex(localTokenPtr, envPtr, &localIndex)) { return TCL_ERROR; } TclEmitInstInt4(INST_UPVAR, localIndex, envPtr); } /* * Pop the frame index, and set the result to empty |
︙ | ︙ | |||
5876 5877 5878 5879 5880 5881 5882 | Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr, *otherTokenPtr, *localTokenPtr; | | | 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 | Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr, *otherTokenPtr, *localTokenPtr; int localIndex, numWords, i; DefineLineInformation; /* TIP #280 */ if (envPtr->procPtr == NULL) { return TCL_ERROR; } /* |
︙ | ︙ | |||
5921 5922 5923 5924 5925 5926 5927 | localTokenPtr = tokenPtr; for(i=3; i<numWords; i+=2) { otherTokenPtr = TokenAfter(localTokenPtr); localTokenPtr = TokenAfter(otherTokenPtr); CompileWord(envPtr, otherTokenPtr, interp, i); | | < < < | 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 | localTokenPtr = tokenPtr; for(i=3; i<numWords; i+=2) { otherTokenPtr = TokenAfter(localTokenPtr); localTokenPtr = TokenAfter(otherTokenPtr); CompileWord(envPtr, otherTokenPtr, interp, i); if (!GetLocalScalarIndex(localTokenPtr, envPtr, &localIndex)) { return TCL_ERROR; } TclEmitInstInt4(INST_NSUPVAR, localIndex, envPtr); } /* * Pop the namespace, and set the result to empty |
︙ | ︙ |
Changes to generic/tclCompile.c.
︙ | ︙ | |||
2284 2285 2286 2287 2288 2289 2290 | int TclFindCompiledLocal( register const char *name, /* Points to first character of the name of a * scalar or array variable. If NULL, a * temporary var should be created. */ int nameBytes, /* Number of bytes in the name. */ | | | | 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 | int TclFindCompiledLocal( register const char *name, /* Points to first character of the name of a * scalar or array variable. If NULL, a * temporary var should be created. */ int nameBytes, /* Number of bytes in the name. */ int create, /* If non-zero, allocate a local frame entry * for the variable if it is new. */ register Proc *procPtr) /* Points to structure describing procedure * containing the variable reference. */ { register CompiledLocal *localPtr; int localVar = -1; register int i; |
︙ | ︙ |
Changes to generic/tclInt.h.
︙ | ︙ | |||
2602 2603 2604 2605 2606 2607 2608 | MODULE_SCOPE void TclInitIOSubsystem(void); MODULE_SCOPE void TclInitLimitSupport(Tcl_Interp *interp); MODULE_SCOPE void TclInitNamespaceSubsystem(void); MODULE_SCOPE void TclInitNotifier(void); MODULE_SCOPE void TclInitObjSubsystem(void); MODULE_SCOPE void TclInitSubsystems(void); MODULE_SCOPE int TclInterpReady(Tcl_Interp *interp); | < | 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 | MODULE_SCOPE void TclInitIOSubsystem(void); MODULE_SCOPE void TclInitLimitSupport(Tcl_Interp *interp); MODULE_SCOPE void TclInitNamespaceSubsystem(void); MODULE_SCOPE void TclInitNotifier(void); MODULE_SCOPE void TclInitObjSubsystem(void); MODULE_SCOPE void TclInitSubsystems(void); MODULE_SCOPE int TclInterpReady(Tcl_Interp *interp); MODULE_SCOPE int TclIsSpaceProc(char byte); MODULE_SCOPE int TclIsBareword(char byte); MODULE_SCOPE int TclJoinThread(Tcl_ThreadId id, int *result); MODULE_SCOPE void TclLimitRemoveAllHandlers(Tcl_Interp *interp); MODULE_SCOPE Tcl_Obj * TclLindexList(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *argPtr); MODULE_SCOPE Tcl_Obj * TclLindexFlat(Tcl_Interp *interp, Tcl_Obj *listPtr, |
︙ | ︙ |
Changes to generic/tclParse.c.
︙ | ︙ | |||
2557 2558 2559 2560 2561 2562 2563 | * check. */ { int length; const char *script = Tcl_GetStringFromObj(objPtr, &length); return CommandComplete(script, length); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 | * check. */ { int length; const char *script = Tcl_GetStringFromObj(objPtr, &length); return CommandComplete(script, length); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: |
︙ | ︙ |