Tcl Source Code

Check-in [b1eea13a69]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Use interp==NULL argument to PushVarName to signal that only an index into the CLT is sought, and no time should be wasted compiling other cases which the caller is just going to discard.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | bug-e711ffb458
Files: files | file ages | folders
SHA1: b1eea13a6929e097df7e0af829b249dfb3739d24
User & Date: dgp 2014-12-19 15:13:11
Context
2014-12-19
15:55
New utility routine GetLocalScalarIndex() reduces common caller boilerplate (and fixes a bug!) Closed-Leaf check-in: 8fefc24942 user: dgp tags: bug-e711ffb458
15:13
Use interp==NULL argument to PushVarName to signal that only an index into the CLT is sought, and no... check-in: b1eea13a69 user: dgp tags: bug-e711ffb458
14:21
With no callers left, TclIsLocalScalar() is removed. check-in: b052f09dbe user: dgp tags: bug-e711ffb458
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclCompCmds.c.

398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
     * refer to local scalars.
     */

    resultIndex = optsIndex = -1;
    cmdTokenPtr = TokenAfter(parsePtr->tokenPtr);
    if (parsePtr->numWords >= 3) {
	resultNameTokenPtr = TokenAfter(cmdTokenPtr);
	PushVarNameWord(interp, resultNameTokenPtr, envPtr, TCL_CREATE_VAR,
		&resultIndex, &isSimple, &isScalar, 2);
	if (!isScalar || resultIndex < 0) {
	    return TCL_ERROR;
	}

	if (parsePtr->numWords == 4) {
	    optsNameTokenPtr = TokenAfter(resultNameTokenPtr);
	    PushVarNameWord(interp, optsNameTokenPtr, envPtr, TCL_CREATE_VAR,
		    &optsIndex, &isSimple, &isScalar, 3);
	    if (!isScalar || resultIndex < 0) {
		return TCL_ERROR;
	    }
	}
    }








|







|







398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
     * refer to local scalars.
     */

    resultIndex = optsIndex = -1;
    cmdTokenPtr = TokenAfter(parsePtr->tokenPtr);
    if (parsePtr->numWords >= 3) {
	resultNameTokenPtr = TokenAfter(cmdTokenPtr);
	PushVarNameWord(NULL, resultNameTokenPtr, envPtr, TCL_CREATE_VAR,
		&resultIndex, &isSimple, &isScalar, 2);
	if (!isScalar || resultIndex < 0) {
	    return TCL_ERROR;
	}

	if (parsePtr->numWords == 4) {
	    optsNameTokenPtr = TokenAfter(resultNameTokenPtr);
	    PushVarNameWord(NULL, optsNameTokenPtr, envPtr, TCL_CREATE_VAR,
		    &optsIndex, &isSimple, &isScalar, 3);
	    if (!isScalar || resultIndex < 0) {
		return TCL_ERROR;
	    }
	}
    }

669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
    /*
     * 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);
    PushVarNameWord(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
	    &dictVarIndex, &isSimple, &isScalar, 1);
    if (!isScalar || dictVarIndex < 0) {
	return TCL_ERROR;
    }

    /*
     * Remaining words (key path and value to set) can be handled normally.







|







669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
    /*
     * 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);
    PushVarNameWord(NULL, varTokenPtr, envPtr, TCL_CREATE_VAR,
	    &dictVarIndex, &isSimple, &isScalar, 1);
    if (!isScalar || dictVarIndex < 0) {
	return TCL_ERROR;
    }

    /*
     * Remaining words (key path and value to set) can be handled normally.
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
    /*
     * 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);
    PushVarNameWord(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
	    &dictVarIndex, &isSimple, &isScalar, 1);
    if (!isScalar || dictVarIndex < 0) {
	return TCL_ERROR;
    }

    keyTokenPtr = TokenAfter(varTokenPtr);








|







722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
    /*
     * 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);
    PushVarNameWord(NULL, varTokenPtr, envPtr, TCL_CREATE_VAR,
	    &dictVarIndex, &isSimple, &isScalar, 1);
    if (!isScalar || dictVarIndex < 0) {
	return TCL_ERROR;
    }

    keyTokenPtr = TokenAfter(varTokenPtr);

845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
	    numVars != 2) {
	Tcl_DecrRefCount(varListObj);
	return TCL_ERROR;
    }

    Tcl_ListObjIndex(NULL, varListObj, 0, &varNameObj);
    token[1].start = Tcl_GetStringFromObj(varNameObj, &token[1].size);
    PushVarNameWord(interp, token, envPtr, TCL_CREATE_VAR,
	    &keyVarIndex, &isSimple, &isScalar, 0 /* ignored */);
    if (!isScalar || keyVarIndex < 0) {
	Tcl_DecrRefCount(varListObj);
	return TCL_ERROR;
    }

    Tcl_ListObjIndex(NULL, varListObj, 1, &varNameObj);
    token[1].start = Tcl_GetStringFromObj(varNameObj, &token[1].size);
    PushVarNameWord(interp, token, envPtr, TCL_CREATE_VAR,
	    &valueVarIndex, &isSimple, &isScalar, 0 /* ignored */);
    if (!isScalar || valueVarIndex < 0) {
	Tcl_DecrRefCount(varListObj);
	return TCL_ERROR;
    }

    Tcl_DecrRefCount(varListObj);







|








|







845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
	    numVars != 2) {
	Tcl_DecrRefCount(varListObj);
	return TCL_ERROR;
    }

    Tcl_ListObjIndex(NULL, varListObj, 0, &varNameObj);
    token[1].start = Tcl_GetStringFromObj(varNameObj, &token[1].size);
    PushVarNameWord(NULL, token, envPtr, TCL_CREATE_VAR,
	    &keyVarIndex, &isSimple, &isScalar, 0 /* ignored */);
    if (!isScalar || keyVarIndex < 0) {
	Tcl_DecrRefCount(varListObj);
	return TCL_ERROR;
    }

    Tcl_ListObjIndex(NULL, varListObj, 1, &varNameObj);
    token[1].start = Tcl_GetStringFromObj(varNameObj, &token[1].size);
    PushVarNameWord(NULL, token, envPtr, TCL_CREATE_VAR,
	    &valueVarIndex, &isSimple, &isScalar, 0 /* ignored */);
    if (!isScalar || valueVarIndex < 0) {
	Tcl_DecrRefCount(varListObj);
	return TCL_ERROR;
    }

    Tcl_DecrRefCount(varListObj);
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
    /*
     * 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);
    PushVarNameWord(interp, dictVarTokenPtr, envPtr, TCL_CREATE_VAR,
	    &dictIndex, &isSimple, &isScalar, 1);
    if (!isScalar || dictIndex < 0) {
	return TCL_ERROR;
    }

    /*
     * Assemble the instruction metadata. This is complex enough that it is







|







1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
    /*
     * 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);
    PushVarNameWord(NULL, dictVarTokenPtr, envPtr, TCL_CREATE_VAR,
	    &dictIndex, &isSimple, &isScalar, 1);
    if (!isScalar || dictIndex < 0) {
	return TCL_ERROR;
    }

    /*
     * Assemble the instruction metadata. This is complex enough that it is
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
	keyTokenPtrs[i] = tokenPtr;

	/*
	 * Variables first need to be checked for sanity.
	 */

	tokenPtr = TokenAfter(tokenPtr);
	PushVarNameWord(interp, tokenPtr, envPtr, TCL_CREATE_VAR,
	    &index, &isSimple, &isScalar, 1);
	if (!isScalar || index < 0) {
	    ckfree((char *) duiPtr);
	    TclStackFree(interp, keyTokenPtrs);
	    return TCL_ERROR;
	}








|







1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
	keyTokenPtrs[i] = tokenPtr;

	/*
	 * Variables first need to be checked for sanity.
	 */

	tokenPtr = TokenAfter(tokenPtr);
	PushVarNameWord(NULL, tokenPtr, envPtr, TCL_CREATE_VAR,
	    &index, &isSimple, &isScalar, 1);
	if (!isScalar || index < 0) {
	    ckfree((char *) duiPtr);
	    TclStackFree(interp, keyTokenPtrs);
	    return TCL_ERROR;
	}

1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
    }

    /*
     * Get the index of the local variable that we will be working with.
     */

    tokenPtr = TokenAfter(parsePtr->tokenPtr);
    PushVarNameWord(interp, tokenPtr, envPtr, TCL_CREATE_VAR,
	    &dictVarIndex, &isSimple, &isScalar, 1);
    if (!isScalar || dictVarIndex < 0) {
	return TCL_ERROR;
    }

    /*
     * Produce the string to concatenate onto the dictionary entry.







|







1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
    }

    /*
     * Get the index of the local variable that we will be working with.
     */

    tokenPtr = TokenAfter(parsePtr->tokenPtr);
    PushVarNameWord(NULL, tokenPtr, envPtr, TCL_CREATE_VAR,
	    &dictVarIndex, &isSimple, &isScalar, 1);
    if (!isScalar || dictVarIndex < 0) {
	return TCL_ERROR;
    }

    /*
     * Produce the string to concatenate onto the dictionary entry.
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
    if (parsePtr->numWords != 4) {
	return TCL_ERROR;
    }

    varTokenPtr = TokenAfter(parsePtr->tokenPtr);
    keyTokenPtr = TokenAfter(varTokenPtr);
    valueTokenPtr = TokenAfter(keyTokenPtr);
    PushVarNameWord(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
	    &dictVarIndex, &isSimple, &isScalar, 1);
    if (!isScalar || dictVarIndex < 0) {
	return TCL_ERROR;
    }
    CompileWord(envPtr, keyTokenPtr, interp, 2);
    CompileWord(envPtr, valueTokenPtr, interp, 3);
    TclEmitInstInt4( INST_DICT_LAPPEND, dictVarIndex, envPtr);







|







1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
    if (parsePtr->numWords != 4) {
	return TCL_ERROR;
    }

    varTokenPtr = TokenAfter(parsePtr->tokenPtr);
    keyTokenPtr = TokenAfter(varTokenPtr);
    valueTokenPtr = TokenAfter(keyTokenPtr);
    PushVarNameWord(NULL, varTokenPtr, envPtr, TCL_CREATE_VAR,
	    &dictVarIndex, &isSimple, &isScalar, 1);
    if (!isScalar || dictVarIndex < 0) {
	return TCL_ERROR;
    }
    CompileWord(envPtr, keyTokenPtr, interp, 2);
    CompileWord(envPtr, valueTokenPtr, interp, 3);
    TclEmitInstInt4( INST_DICT_LAPPEND, dictVarIndex, envPtr);
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642

	for (j = 0;  j < numVars;  j++) {
	    Tcl_Obj *varNameObj;
	    int varIndex, isSimple, isScalar;

	    Tcl_ListObjIndex(NULL, varListObj, j, &varNameObj);
	    token[1].start = Tcl_GetStringFromObj(varNameObj, &token[1].size);
	    PushVarNameWord(interp, token, envPtr, TCL_CREATE_VAR,
		&varIndex, &isSimple, &isScalar, 0 /* ignored */);
	    if (!isScalar || varIndex < 0) {
		code = TCL_ERROR;
		goto done;
	    }
	    varListPtr->varIndexes[j] = varIndex;
	}







|







1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642

	for (j = 0;  j < numVars;  j++) {
	    Tcl_Obj *varNameObj;
	    int varIndex, isSimple, isScalar;

	    Tcl_ListObjIndex(NULL, varListObj, j, &varNameObj);
	    token[1].start = Tcl_GetStringFromObj(varNameObj, &token[1].size);
	    PushVarNameWord(NULL, token, envPtr, TCL_CREATE_VAR,
		&varIndex, &isSimple, &isScalar, 0 /* ignored */);
	    if (!isScalar || varIndex < 0) {
		code = TCL_ERROR;
		goto done;
	    }
	    varListPtr->varIndexes[j] = varIndex;
	}
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
		elemTokenPtr->type = TCL_TOKEN_TEXT;
		elemTokenPtr->start = elName;
		elemTokenPtr->size = elNameChars;
		elemTokenPtr->numComponents = 0;
		elemTokenCount = 1;
	    }
	}
    } else if (((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.
	 */







|







4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
		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.
	 */
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
		/*
		 * We'll push the name.
		 */

		localIndex = -1;
	    }
	}
	if (localIndex < 0) {
	    PushLiteral(envPtr, name, nameChars);
	}

	/*
	 * Compile the element script, if any.
	 */

	if (elName != NULL) {
	    if (elNameChars) {
		envPtr->line = line;
		envPtr->clNext = clNext;
		TclCompileTokens(interp, elemTokenPtr, elemTokenCount, envPtr);
	    } else {
		PushLiteral(envPtr, "", 0);
	    }
	}
    } else {
	/*
	 * The var name isn't simple: compile and push it.
	 */

	envPtr->line = line;
	envPtr->clNext = clNext;
	CompileTokens(envPtr, varTokenPtr, interp);







|







|








|







4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
		/*
		 * 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);
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
     * be called at runtime.
     */

    for(; i<numWords; i+=2, otherTokenPtr = TokenAfter(localTokenPtr)) {
	localTokenPtr = TokenAfter(otherTokenPtr);

	CompileWord(envPtr, otherTokenPtr, interp, i);
	PushVarNameWord(interp, localTokenPtr, envPtr, TCL_CREATE_VAR,
			&localIndex, &simpleVarName, &isScalar, i+1);

	if((localIndex < 0) || !isScalar) {
	    return TCL_ERROR;
	}
	TclEmitInstInt4(INST_UPVAR, localIndex, envPtr);
    }







|







5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
     * be called at runtime.
     */

    for(; i<numWords; i+=2, otherTokenPtr = TokenAfter(localTokenPtr)) {
	localTokenPtr = TokenAfter(otherTokenPtr);

	CompileWord(envPtr, otherTokenPtr, interp, i);
	PushVarNameWord(NULL, localTokenPtr, envPtr, TCL_CREATE_VAR,
			&localIndex, &simpleVarName, &isScalar, i+1);

	if((localIndex < 0) || !isScalar) {
	    return TCL_ERROR;
	}
	TclEmitInstInt4(INST_UPVAR, localIndex, envPtr);
    }
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810

    localTokenPtr = tokenPtr;
    for(i=3; i<numWords; i+=2) {
	otherTokenPtr = TokenAfter(localTokenPtr);
	localTokenPtr = TokenAfter(otherTokenPtr);

	CompileWord(envPtr, otherTokenPtr, interp, i);
	PushVarNameWord(interp, localTokenPtr, envPtr, TCL_CREATE_VAR,
			&localIndex, &simpleVarName, &isScalar, i+1);

	if((localIndex < 0) || !isScalar) {
	    return TCL_ERROR;
	}
	TclEmitInstInt4(INST_NSUPVAR, localIndex, envPtr);
    }







|







5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810

    localTokenPtr = tokenPtr;
    for(i=3; i<numWords; i+=2) {
	otherTokenPtr = TokenAfter(localTokenPtr);
	localTokenPtr = TokenAfter(otherTokenPtr);

	CompileWord(envPtr, otherTokenPtr, interp, i);
	PushVarNameWord(NULL, localTokenPtr, envPtr, TCL_CREATE_VAR,
			&localIndex, &simpleVarName, &isScalar, i+1);

	if((localIndex < 0) || !isScalar) {
	    return TCL_ERROR;
	}
	TclEmitInstInt4(INST_NSUPVAR, localIndex, envPtr);
    }