Compare commits

...
Author SHA1 Message Date
dkf a744556f14 merge main working branch 2014-02-02 15:08:40 +00:00
dkf fd4bc0f106 compilation of [string is] 2014-02-02 14:43:48 +00:00
dkf cca7f018e0 improve the disassembly 2014-02-02 14:42:12 +00:00
dkf 6597355ad8 Compile [string is] with character classes in a non-awful way. Needs more work to make resulting bytecode disassemble nicely. 2014-01-29 13:59:32 +00:00
dkf f4549b8fc4 merge principal development branch 2014-01-25 09:02:30 +00:00
dkf c9ae8d64d3 minor tidying up 2014-01-22 09:14:57 +00:00
dkf 7716fd3e46 [a90d9331bc]: must not crash when yieldto called in vanishing namespace 2014-01-22 09:07:45 +00:00
dkf 128e4211ae implementation of [yieldto] in bytecode 2014-01-21 15:07:59 +00:00
dkf 88b2f7f06e added compilation for [nextto] 2014-01-19 18:39:24 +00:00
dkf 12945e9a16 extend [string is] to booleans 2014-01-13 08:06:43 +00:00
dkf 2803a8a055 a different approach 2014-01-10 15:58:41 +00:00
dkf 29ae06c2d3 use compact form 2014-01-09 10:49:04 +00:00
dkf 8f95efa4cf merge main working branch 2014-01-07 14:25:22 +00:00
dkf cbc312324e make function static once more; not needed outside of source file 2014-01-07 14:13:37 +00:00
dkf 03ecb591a6 reduce the overhead of NR-enabled TclOO [next] 2014-01-07 13:59:30 +00:00
dkf 6bb7b1e15d factor out a common stanza 2014-01-05 17:31:38 +00:00
dkf a2e12b4377 merge main working branch 2014-01-05 17:00:15 +00:00
dkf 6d9846f8c9 merge trunk 2014-01-05 16:57:05 +00:00
mig 666deab1ea fix arraySet compiler to set -errorcode instead of -errorCode in return options 2014-01-05 15:01:52 +00:00
mig bb9e19e6eb skip the switch(result) on returning TCL_OK from a proc 2014-01-05 14:10:42 +00:00
mig ea8a9ba071 reducing TEBCdata: pc and cleanup now passed in the NREcallback 2014-01-05 12:01:04 +00:00
dkf 430c9bc178 redevelop code to have more in common with the interpreted [string is] and to remove non-working types 2014-01-02 15:30:53 +00:00
jan.nijtmans e7e7bafe96 merge-mark 2014-01-02 10:11:42 +00:00
dkf 9c349ce2e2 more fixes to instruction tracing; ensure all places that need DECACHE_STACK_INFO have it 2014-01-02 10:01:35 +00:00
dkf e7f9c9c822 merge main working branch 2014-01-02 09:38:03 +00:00
dkf e7d2bb4c60 merge main working branch 2014-01-02 09:35:43 +00:00
dkf 83fcae9bbe implement TclOO's [next] in bytecode 2014-01-02 09:17:07 +00:00
dkf d5961a83e0 merge main working branch; made opcode work by getting callback ordering right 2014-01-02 09:15:18 +00:00
dkf 9c6b83d5b1 merge trunk 2014-01-02 08:51:04 +00:00
dkf 8a115927af ... and more silly errors 2014-01-02 08:50:08 +00:00
dkf 68cab10668 merge trunk 2014-01-02 08:35:48 +00:00
dkf c28c2d5b9a oops... 2014-01-02 08:35:01 +00:00
dkf 78f85049ff merge main working branch 2014-01-02 08:32:36 +00:00
dkf a30f092ea3 merge trunk 2014-01-02 03:27:16 +00:00
dkf 4f13f826e4 more fixes to instruction tracing; ensure all places that need DECACHE_STACK_INFO have it. jan.nijtmans: Branch moved aside an hidden, so future bisects are not affected by this branch mistakes. 2014-01-02 03:10:43 +00:00
dkf 1c54736c0d factor out a common peephole stanza 2014-01-01 16:19:14 +00:00
dkf f9dd75e79c another jump peephole, this time with string comparisons 2013-12-31 23:34:57 +00:00
dkf d423ce0c06 more cleaning up of error-case instruction tracing 2013-12-31 17:28:16 +00:00
dkf 76b954ec41 merge trunk 2013-12-31 16:28:15 +00:00
dkf c45f1130d1 more peephole optimizations in TEBC, and better instruction execution traces 2013-12-31 16:26:55 +00:00
mig 0891bbbcbb clarify the resume sequence in TEBCresume; make checkInterp a local variable, remove it from the saved struct 2013-12-31 12:14:50 +00:00
dkf 05feb2c73f merge trunk 2013-12-31 10:49:07 +00:00
dkf 0e49a49b8f remove ill-advised change to assembler
What made sense for the compiler does not for the assembler, as that can (and does) build code blocks entirely out of order.
2013-12-31 10:47:19 +00:00
dkf 9daddcaad7 Now gets the stack depth about right, but still many test failures. 2013-12-31 10:37:31 +00:00
dgp 57dc79f34e merge trunk 2013-12-30 16:36:12 +00:00
dkf 6799b19771 merge main working branch 2013-12-30 11:58:08 +00:00
dkf 413a0c2501 put the other definition of a trim set in the header file too 2013-12-30 11:56:54 +00:00
dkf 8a7b73aed2 merge main working branch 2013-12-30 11:44:34 +00:00
dkf 76007824cc Factor out the definition of the default string trim set; define it once only. 2013-12-30 11:40:44 +00:00
dkf db5995b2b8 merge main working branch 2013-12-30 10:24:20 +00:00
dkf 9083b5bf61 merge main working branch 2013-12-30 08:50:28 +00:00
dkf 7f1d218ef8 merge main working branch 2013-12-30 08:49:03 +00:00
dkf 4ad593f2bf implement [namespace origin] in bytecode 2013-12-30 08:37:49 +00:00
dkf cdacc33cbb allow generation by assembler 2013-12-30 08:16:21 +00:00
dkf f7157671ce corrected comment 2013-12-30 08:12:52 +00:00
dkf b004b21242 Improved general case of [string replace] implementation. 2013-12-29 18:49:20 +00:00
dkf fad447d516 Take advantage of new concatenation opcode. 2013-10-26 09:41:31 +00:00
dkf 437c149fe1 merge 2013-10-26 08:27:34 +00:00
dgp ffb2a3d9b4 merge trunk 2013-10-23 15:34:01 +00:00
dkf 4b5edf953c merge fix 2013-10-23 08:34:30 +00:00
dkf 01a1be21e0 Possible compilation of [eval]. 2013-10-23 08:18:11 +00:00
dkf 0eb33efc7a merge main dev branch 2013-01-03 14:08:49 +00:00
dkf 53baa9e5c4 merge main dev branch 2013-01-03 14:07:24 +00:00
dkf af735a0ba9 merge main dev branch 2012-12-19 11:43:40 +00:00
dkf a7b60b26f1 merge main dev branch 2012-12-19 11:42:46 +00:00
dkf d6bd07fecc merge dkf-compile-misc-info 2012-11-20 12:14:18 +00:00
dkf f497ce9a95 merge dkf-compile-misc-info 2012-11-20 12:13:43 +00:00
dkf 414163addc merge main dev branch 2012-11-05 21:56:13 +00:00
dkf 71fd534215 merge main dev branch 2012-11-05 21:55:40 +00:00
dkf b8bcc352ea merge main dev branch 2012-11-05 15:33:44 +00:00
dkf f04eef80d7 merge main dev branch 2012-11-05 15:28:01 +00:00
dkf 2de2d8678f reorder to preserve main BC development branch sequence better 2012-11-02 20:39:10 +00:00
dkf d5e04d6200 merge dkf-compile-misc-info 2012-11-02 20:25:57 +00:00
dkf 6d14b815b2 Work on compilation of [string is].
Hit some problem edge cases with differences in strictness of edge cases that
will force a rethink ([string is boolean] is significantly more strict than
Tcl_GetBooleanFromObj).
2012-11-02 16:50:06 +00:00
dkf ed18777278 Working towards a BCCed [next].
This version <i>almost</i> works, except for a problem with restoring the
context namespace upon return (which produces very strange results!)
2012-11-01 20:40:55 +00:00
18 changed files with 1780 additions and 641 deletions
+10 -4
View File
@@ -26,6 +26,7 @@
*- jumpTable testing
*- syntax (?)
*- returnCodeBranch
*- tclooNext, tclooNextClass
*/
#include "tclInt.h"
@@ -437,6 +438,8 @@ static const TalInstDesc TalInstructionTable[] = {
{"nop", ASSEM_1BYTE, INST_NOP, 0, 0},
{"not", ASSEM_1BYTE, INST_LNOT, 1, 1},
{"nsupvar", ASSEM_LVT4, INST_NSUPVAR, 2, 1},
{"numericType", ASSEM_1BYTE, INST_NUM_TYPE, 1, 1},
{"originCmd", ASSEM_1BYTE, INST_ORIGIN_COMMAND, 1, 1},
{"over", ASSEM_OVER, INST_OVER, INT_MIN,-1-1},
{"pop", ASSEM_1BYTE, INST_POP, 1, 0},
{"pushReturnCode", ASSEM_1BYTE, INST_PUSH_RETURN_CODE, 0, 1},
@@ -453,9 +456,9 @@ static const TalInstDesc TalInstructionTable[] = {
| INST_STORE_ARRAY4), 2, 1},
{"storeArrayStk", ASSEM_1BYTE, INST_STORE_ARRAY_STK, 3, 1},
{"storeStk", ASSEM_1BYTE, INST_STORE_STK, 2, 1},
{"strLower", ASSEM_1BYTE, INST_STR_LOWER, 1, 1},
{"strTitle", ASSEM_1BYTE, INST_STR_TITLE, 1, 1},
{"strUpper", ASSEM_1BYTE, INST_STR_UPPER, 1, 1},
{"strcaseLower", ASSEM_1BYTE, INST_STR_LOWER, 1, 1},
{"strcaseTitle", ASSEM_1BYTE, INST_STR_TITLE, 1, 1},
{"strcaseUpper", ASSEM_1BYTE, INST_STR_UPPER, 1, 1},
{"strcmp", ASSEM_1BYTE, INST_STR_CMP, 2, 1},
{"strcat", ASSEM_CONCAT1, INST_STR_CONCAT1, INT_MIN,1},
{"streq", ASSEM_1BYTE, INST_STR_EQ, 2, 1},
@@ -466,6 +469,7 @@ static const TalInstDesc TalInstructionTable[] = {
{"strmatch", ASSEM_BOOL, INST_STR_MATCH, 2, 1},
{"strneq", ASSEM_1BYTE, INST_STR_NEQ, 2, 1},
{"strrange", ASSEM_1BYTE, INST_STR_RANGE, 3, 1},
{"strreplace", ASSEM_1BYTE, INST_STR_REPLACE, 4, 1},
{"strrfind", ASSEM_1BYTE, INST_STR_FIND_LAST, 2, 1},
{"strtrim", ASSEM_1BYTE, INST_STR_TRIM, 2, 1},
{"strtrimLeft", ASSEM_1BYTE, INST_STR_TRIM_LEFT, 2, 1},
@@ -475,6 +479,7 @@ static const TalInstDesc TalInstructionTable[] = {
{"tclooIsObject", ASSEM_1BYTE, INST_TCLOO_IS_OBJECT, 1, 1},
{"tclooNamespace", ASSEM_1BYTE, INST_TCLOO_NS, 1, 1},
{"tclooSelf", ASSEM_1BYTE, INST_TCLOO_SELF, 0, 1},
{"tryCvtToBoolean", ASSEM_1BYTE, INST_TRY_CVT_TO_BOOLEAN,1, 2},
{"tryCvtToNumeric", ASSEM_1BYTE, INST_TRY_CVT_TO_NUMERIC,1, 1},
{"uminus", ASSEM_1BYTE, INST_UMINUS, 1, 1},
{"unset", ASSEM_BOOL_LVT4,INST_UNSET_SCALAR, 0, 0},
@@ -514,7 +519,8 @@ static const unsigned char NonThrowingByteCodes[] = {
INST_RESOLVE_COMMAND, /* 154 */
INST_STR_TRIM, INST_STR_TRIM_LEFT, INST_STR_TRIM_RIGHT, /* 166-168 */
INST_CONCAT_STK, /* 169 */
INST_STR_UPPER, INST_STR_LOWER, INST_STR_TITLE /* 170-172 */
INST_STR_UPPER, INST_STR_LOWER, INST_STR_TITLE, /* 170-172 */
INST_NUM_TYPE /* 180 */
};
/*
+10 -15
View File
@@ -215,7 +215,7 @@ static const CmdInfo builtInCmds[] = {
{"continue", Tcl_ContinueObjCmd, TclCompileContinueCmd, NULL, CMD_IS_SAFE},
{"coroutine", NULL, NULL, TclNRCoroutineObjCmd, CMD_IS_SAFE},
{"error", Tcl_ErrorObjCmd, TclCompileErrorCmd, NULL, CMD_IS_SAFE},
{"eval", Tcl_EvalObjCmd, NULL, TclNREvalObjCmd, CMD_IS_SAFE},
{"eval", Tcl_EvalObjCmd, TclCompileEvalCmd, TclNREvalObjCmd, CMD_IS_SAFE},
{"expr", Tcl_ExprObjCmd, TclCompileExprCmd, TclNRExprObjCmd, CMD_IS_SAFE},
{"for", Tcl_ForObjCmd, TclCompileForCmd, TclNRForObjCmd, CMD_IS_SAFE},
{"foreach", Tcl_ForeachObjCmd, TclCompileForeachCmd, TclNRForeachCmd, CMD_IS_SAFE},
@@ -259,7 +259,7 @@ static const CmdInfo builtInCmds[] = {
{"variable", Tcl_VariableObjCmd, TclCompileVariableCmd, NULL, CMD_IS_SAFE},
{"while", Tcl_WhileObjCmd, TclCompileWhileCmd, TclNRWhileObjCmd, CMD_IS_SAFE},
{"yield", NULL, TclCompileYieldCmd, TclNRYieldObjCmd, CMD_IS_SAFE},
{"yieldto", NULL, NULL, TclNRYieldToObjCmd, CMD_IS_SAFE},
{"yieldto", NULL, TclCompileYieldToCmd, TclNRYieldToObjCmd, CMD_IS_SAFE},
/*
* Commands in the OS-interface. Note that many of these are unsafe.
@@ -8416,8 +8416,7 @@ TclNRYieldToObjCmd(
{
CoroutineData *corPtr = iPtr->execEnvPtr->corPtr;
Tcl_Obj *listPtr, *nsObjPtr;
Tcl_Namespace *nsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
Tcl_Namespace *ns1Ptr;
Tcl_Namespace *nsPtr = TclGetCurrentNamespace(interp);
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "command ?arg ...?");
@@ -8431,11 +8430,13 @@ TclNRYieldToObjCmd(
return TCL_ERROR;
}
/*
* Add the tailcall in the caller env, then just yield.
*
* This is essentially code from TclNRTailcallObjCmd
*/
if (((Namespace *) nsPtr)->flags & NS_DYING) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"yieldto called in deleted namespace", -1));
Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "YIELDTO_IN_DELETED",
NULL);
return TCL_ERROR;
}
/*
* Add the tailcall in the caller env, then just yield.
@@ -8444,15 +8445,9 @@ TclNRYieldToObjCmd(
*/
listPtr = Tcl_NewListObj(objc, objv);
nsObjPtr = Tcl_NewStringObj(nsPtr->fullName, -1);
if ((TCL_OK != TclGetNamespaceFromObj(interp, nsObjPtr, &ns1Ptr))
|| (nsPtr != ns1Ptr)) {
Tcl_Panic("yieldto failed to find the proper namespace");
}
TclListObjSetElement(interp, listPtr, 0, nsObjPtr);
/*
* Add the callback in the caller's env, then instruct TEBC to yield.
*/
+2 -35
View File
@@ -18,6 +18,7 @@
#include "tclInt.h"
#include "tclRegexp.h"
#include "tclStringTrim.h"
static inline Tcl_Obj * During(Tcl_Interp *interp, int resultCode,
Tcl_Obj *oldOptions, Tcl_Obj *errorInfo);
@@ -31,40 +32,6 @@ static int TryPostHandler(ClientData data[], Tcl_Interp *interp,
int result);
static int UniCharIsAscii(int character);
static int UniCharIsHexDigit(int character);
/*
* Default set of characters to trim in [string trim] and friends. This is a
* UTF-8 literal string containing all Unicode space characters [TIP #413]
*
* Synch with tclCompCmdsSZ.c
*/
#define DEFAULT_TRIM_SET \
"\x09\x0a\x0b\x0c\x0d " /* ASCII */\
"\xc0\x80" /* nul (U+0000) */\
"\xc2\x85" /* next line (U+0085) */\
"\xc2\xa0" /* non-breaking space (U+00a0) */\
"\xe1\x9a\x80" /* ogham space mark (U+1680) */ \
"\xe1\xa0\x8e" /* mongolian vowel separator (U+180e) */\
"\xe2\x80\x80" /* en quad (U+2000) */\
"\xe2\x80\x81" /* em quad (U+2001) */\
"\xe2\x80\x82" /* en space (U+2002) */\
"\xe2\x80\x83" /* em space (U+2003) */\
"\xe2\x80\x84" /* three-per-em space (U+2004) */\
"\xe2\x80\x85" /* four-per-em space (U+2005) */\
"\xe2\x80\x86" /* six-per-em space (U+2006) */\
"\xe2\x80\x87" /* figure space (U+2007) */\
"\xe2\x80\x88" /* punctuation space (U+2008) */\
"\xe2\x80\x89" /* thin space (U+2009) */\
"\xe2\x80\x8a" /* hair space (U+200a) */\
"\xe2\x80\x8b" /* zero width space (U+200b) */\
"\xe2\x80\xa8" /* line separator (U+2028) */\
"\xe2\x80\xa9" /* paragraph separator (U+2029) */\
"\xe2\x80\xaf" /* narrow no-break space (U+202f) */\
"\xe2\x81\x9f" /* medium mathematical space (U+205f) */\
"\xe2\x81\xa0" /* word joiner (U+2060) */\
"\xe3\x80\x80" /* ideographic space (U+3000) */\
"\xef\xbb\xbf" /* zero width no-break space (U+feff) */
/*
*----------------------------------------------------------------------
@@ -3332,7 +3299,7 @@ TclInitStringCmd(
{"equal", StringEqualCmd, TclCompileStringEqualCmd, NULL, NULL, 0},
{"first", StringFirstCmd, TclCompileStringFirstCmd, NULL, NULL, 0},
{"index", StringIndexCmd, TclCompileStringIndexCmd, NULL, NULL, 0},
{"is", StringIsCmd, NULL, NULL, NULL, 0},
{"is", StringIsCmd, TclCompileStringIsCmd, NULL, NULL, 0},
{"last", StringLastCmd, TclCompileStringLastCmd, NULL, NULL, 0},
{"length", StringLenCmd, TclCompileStringLenCmd, NULL, NULL, 0},
{"map", StringMapCmd, TclCompileStringMapCmd, NULL, NULL, 0},
+66 -9
View File
@@ -65,13 +65,6 @@ const AuxDataType tclDictUpdateInfoType = {
FreeDictUpdateInfo, /* freeProc */
PrintDictUpdateInfo /* printProc */
};
/*
* The definition of what whitespace is stripped when [concat]enating. Must be
* kept in synch with tclUtil.c
*/
#define CONCAT_WS " \f\v\r\t\n"
/*
*----------------------------------------------------------------------
@@ -285,7 +278,7 @@ TclCompileArraySetCmd(
if (isDataValid && !isDataEven) {
PushStringLiteral(envPtr, "list must have an even number of elements");
PushStringLiteral(envPtr, "-errorCode {TCL ARGUMENT FORMAT}");
PushStringLiteral(envPtr, "-errorcode {TCL ARGUMENT FORMAT}");
TclEmitInstInt4(INST_RETURN_IMM, TCL_ERROR, envPtr);
TclEmitInt4( 0, envPtr);
goto done;
@@ -380,7 +373,7 @@ TclCompileArraySetCmd(
offsetFwd = CurrentOffset(envPtr);
TclEmitInstInt1(INST_JUMP_FALSE1, 0, envPtr);
PushStringLiteral(envPtr, "list must have an even number of elements");
PushStringLiteral(envPtr, "-errorCode {TCL ARGUMENT FORMAT}");
PushStringLiteral(envPtr, "-errorcode {TCL ARGUMENT FORMAT}");
TclEmitInstInt4(INST_RETURN_IMM, TCL_ERROR, envPtr);
TclEmitInt4( 0, envPtr);
TclAdjustStackDepth(-1, envPtr);
@@ -2213,6 +2206,70 @@ TclCompileErrorCmd(
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclCompileEvalCmd --
*
* Procedure called to compile the "eval" command.
*
* 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 "eval" command at
* runtime.
*
*----------------------------------------------------------------------
*/
int
TclCompileEvalCmd(
Tcl_Interp *interp, /* Used for context. */
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;
DefineLineInformation; /* TIP #280 */
int i;
/*
* Error case: no arguments at all.
*/
if (parsePtr->numWords < 2) {
return TCL_ERROR;
}
tokenPtr = TokenAfter(parsePtr->tokenPtr);
/*
* Must push, concatenate (when more than one word) and eval. Note that
* when we evaluate, we must first duplicate to ensure that a reference to
* the script is kept for the duration of the evaluation.
*/
for (i=1 ; i<parsePtr->numWords ; i++) {
CompileWord(envPtr, tokenPtr, interp, i);
tokenPtr = TokenAfter(tokenPtr);
}
if (i > 2) {
TclEmitInstInt4( INST_CONCAT_STK, i-1, envPtr);
}
TclEmitOpcode( INST_DUP, envPtr);
TclEmitOpcode( INST_EVAL_STK, envPtr);
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
TclEmitOpcode( INST_POP, envPtr);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
+82
View File
@@ -1955,6 +1955,28 @@ TclCompileNamespaceCodeCmd(
return TCL_OK;
}
int
TclCompileNamespaceOriginCmd(
Tcl_Interp *interp, /* Used for error reporting. */
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;
DefineLineInformation; /* TIP #280 */
if (parsePtr->numWords != 2) {
return TCL_ERROR;
}
tokenPtr = TokenAfter(parsePtr->tokenPtr);
CompileWord(envPtr, tokenPtr, interp, 1);
TclEmitOpcode( INST_ORIGIN_COMMAND, envPtr);
return TCL_OK;
}
int
TclCompileNamespaceQualifiersCmd(
Tcl_Interp *interp, /* Used for error reporting. */
@@ -3017,6 +3039,66 @@ IndexTailVarIfKnown(
return localIndex;
}
/*
* ----------------------------------------------------------------------
*
* TclCompileObjectNextCmd, TclCompileObjectSelfCmd --
*
* Compilations of the TclOO utility commands [next] and [self].
*
* ----------------------------------------------------------------------
*/
int
TclCompileObjectNextCmd(
Tcl_Interp *interp, /* Used for error reporting. */
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. */
{
DefineLineInformation; /* TIP #280 */
Tcl_Token *tokenPtr = parsePtr->tokenPtr;
int i;
if (parsePtr->numWords > 255) {
return TCL_ERROR;
}
for (i=0 ; i<parsePtr->numWords ; i++) {
CompileWord(envPtr, tokenPtr, interp, i);
tokenPtr = TokenAfter(tokenPtr);
}
TclEmitInstInt1( INST_TCLOO_NEXT, i, envPtr);
return TCL_OK;
}
int
TclCompileObjectNextToCmd(
Tcl_Interp *interp, /* Used for error reporting. */
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. */
{
DefineLineInformation; /* TIP #280 */
Tcl_Token *tokenPtr = parsePtr->tokenPtr;
int i;
if (parsePtr->numWords < 2 || parsePtr->numWords > 255) {
return TCL_ERROR;
}
for (i=0 ; i<parsePtr->numWords ; i++) {
CompileWord(envPtr, tokenPtr, interp, i);
tokenPtr = TokenAfter(tokenPtr);
}
TclEmitInstInt1( INST_TCLOO_NEXT_CLASS, i, envPtr);
return TCL_OK;
}
int
TclCompileObjectSelfCmd(
Tcl_Interp *interp, /* Used for error reporting. */
+364 -36
View File
@@ -17,6 +17,7 @@
#include "tclInt.h"
#include "tclCompile.h"
#include "tclStringTrim.h"
/*
* Prototypes for procedures defined later in this file:
@@ -423,6 +424,284 @@ TclCompileStringIndexCmd(
return TCL_OK;
}
int
TclCompileStringIsCmd(
Tcl_Interp *interp, /* Used for error reporting. */
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. */
{
DefineLineInformation; /* TIP #280 */
Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
static const char *const isClasses[] = {
"alnum", "alpha", "ascii", "control",
"boolean", "digit", "double", "entier",
"false", "graph", "integer", "list",
"lower", "print", "punct", "space",
"true", "upper", "wideinteger", "wordchar",
"xdigit", NULL
};
enum isClasses {
STR_IS_ALNUM, STR_IS_ALPHA, STR_IS_ASCII, STR_IS_CONTROL,
STR_IS_BOOL, STR_IS_DIGIT, STR_IS_DOUBLE, STR_IS_ENTIER,
STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INT, STR_IS_LIST,
STR_IS_LOWER, STR_IS_PRINT, STR_IS_PUNCT, STR_IS_SPACE,
STR_IS_TRUE, STR_IS_UPPER, STR_IS_WIDE, STR_IS_WORD,
STR_IS_XDIGIT
};
int t, range, allowEmpty = 0, end;
InstStringClassType strClassType;
Tcl_Obj *isClass;
if (parsePtr->numWords < 3 || parsePtr->numWords > 6) {
return TCL_ERROR;
}
isClass = Tcl_NewObj();
if (!TclWordKnownAtCompileTime(tokenPtr, isClass)) {
Tcl_DecrRefCount(isClass);
return TCL_ERROR;
} else if (Tcl_GetIndexFromObj(interp, isClass, isClasses, "class", 0,
&t) != TCL_OK) {
Tcl_DecrRefCount(isClass);
TclCompileSyntaxError(interp, envPtr);
return TCL_OK;
}
Tcl_DecrRefCount(isClass);
#define GotLiteral(tokenPtr, word) \
((tokenPtr)->type == TCL_TOKEN_SIMPLE_WORD && \
(tokenPtr)[1].size > 1 && \
(tokenPtr)[1].start[0] == word[0] && \
strncmp((tokenPtr)[1].start, (word), (tokenPtr)[1].size) == 0)
/*
* Cannot handle the -failindex option at all, and that's the only legal
* way to have more than 4 arguments.
*/
if (parsePtr->numWords != 3 && parsePtr->numWords != 4) {
return TCL_ERROR;
}
tokenPtr = TokenAfter(tokenPtr);
if (parsePtr->numWords == 3) {
allowEmpty = 1;
} else {
if (!GotLiteral(tokenPtr, "-strict")) {
return TCL_ERROR;
}
tokenPtr = TokenAfter(tokenPtr);
}
#undef GotLiteral
/*
* Compile the code. There are several main classes of check here.
* 1. Character classes
* 2. Booleans
* 3. Integers
* 4. Floats
* 5. Lists
*/
CompileWord(envPtr, tokenPtr, interp, parsePtr->numWords-1);
switch ((enum isClasses) t) {
case STR_IS_ALNUM:
strClassType = STR_CLASS_ALNUM;
goto compileStrClass;
case STR_IS_ALPHA:
strClassType = STR_CLASS_ALPHA;
goto compileStrClass;
case STR_IS_ASCII:
strClassType = STR_CLASS_ASCII;
goto compileStrClass;
case STR_IS_CONTROL:
strClassType = STR_CLASS_CONTROL;
goto compileStrClass;
case STR_IS_DIGIT:
strClassType = STR_CLASS_DIGIT;
goto compileStrClass;
case STR_IS_GRAPH:
strClassType = STR_CLASS_GRAPH;
goto compileStrClass;
case STR_IS_LOWER:
strClassType = STR_CLASS_LOWER;
goto compileStrClass;
case STR_IS_PRINT:
strClassType = STR_CLASS_PRINT;
goto compileStrClass;
case STR_IS_PUNCT:
strClassType = STR_CLASS_PUNCT;
goto compileStrClass;
case STR_IS_SPACE:
strClassType = STR_CLASS_SPACE;
goto compileStrClass;
case STR_IS_UPPER:
strClassType = STR_CLASS_UPPER;
goto compileStrClass;
case STR_IS_WORD:
strClassType = STR_CLASS_WORD;
goto compileStrClass;
case STR_IS_XDIGIT:
strClassType = STR_CLASS_XDIGIT;
compileStrClass:
if (allowEmpty) {
OP1( STR_CLASS, strClassType);
} else {
int over, over2;
OP( DUP);
OP1( STR_CLASS, strClassType);
JUMP1( JUMP_TRUE, over);
OP( POP);
PUSH( "0");
JUMP1( JUMP, over2);
FIXJUMP1(over);
PUSH( "");
OP( STR_NEQ);
FIXJUMP1(over2);
}
return TCL_OK;
case STR_IS_BOOL:
case STR_IS_FALSE:
case STR_IS_TRUE:
OP( TRY_CVT_TO_BOOLEAN);
switch (t) {
int over, over2;
case STR_IS_BOOL:
if (allowEmpty) {
JUMP1( JUMP_TRUE, over);
PUSH( "");
OP( STR_EQ);
JUMP1( JUMP, over2);
FIXJUMP1(over);
OP( POP);
PUSH( "1");
FIXJUMP1(over2);
} else {
OP4( REVERSE, 2);
OP( POP);
}
return TCL_OK;
case STR_IS_TRUE:
JUMP1( JUMP_TRUE, over);
if (allowEmpty) {
PUSH( "");
OP( STR_EQ);
} else {
OP( POP);
PUSH( "0");
}
FIXJUMP1( over);
OP( LNOT);
OP( LNOT);
return TCL_OK;
case STR_IS_FALSE:
JUMP1( JUMP_TRUE, over);
if (allowEmpty) {
PUSH( "");
OP( STR_NEQ);
} else {
OP( POP);
PUSH( "1");
}
FIXJUMP1( over);
OP( LNOT);
return TCL_OK;
}
case STR_IS_DOUBLE: {
int satisfied, isEmpty;
if (allowEmpty) {
OP( DUP);
PUSH( "");
OP( STR_EQ);
JUMP1( JUMP_TRUE, isEmpty);
OP( NUM_TYPE);
JUMP1( JUMP_TRUE, satisfied);
PUSH( "0");
JUMP1( JUMP, end);
FIXJUMP1( isEmpty);
OP( POP);
FIXJUMP1( satisfied);
} else {
OP( NUM_TYPE);
JUMP1( JUMP_TRUE, satisfied);
PUSH( "0");
JUMP1( JUMP, end);
TclAdjustStackDepth(-1, envPtr);
FIXJUMP1( satisfied);
}
PUSH( "1");
FIXJUMP1( end);
return TCL_OK;
}
case STR_IS_INT:
case STR_IS_WIDE:
case STR_IS_ENTIER:
if (allowEmpty) {
int testNumType;
OP( DUP);
OP( NUM_TYPE);
OP( DUP);
JUMP1( JUMP_TRUE, testNumType);
OP( POP);
PUSH( "");
OP( STR_EQ);
JUMP1( JUMP, end);
TclAdjustStackDepth(1, envPtr);
FIXJUMP1( testNumType);
OP4( REVERSE, 2);
OP( POP);
} else {
OP( NUM_TYPE);
OP( DUP);
JUMP1( JUMP_FALSE, end);
}
switch (t) {
case STR_IS_INT:
PUSH( "1");
OP( EQ);
break;
case STR_IS_WIDE:
PUSH( "2");
OP( LE);
break;
case STR_IS_ENTIER:
PUSH( "3");
OP( LE);
break;
}
FIXJUMP1( end);
return TCL_OK;
case STR_IS_LIST:
range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
OP4( BEGIN_CATCH4, range);
ExceptionRangeStarts(envPtr, range);
OP( DUP);
OP( LIST_LENGTH);
OP( POP);
ExceptionRangeEnds(envPtr, range);
ExceptionRangeTarget(envPtr, range, catchOffset);
OP( POP);
OP( PUSH_RETURN_CODE);
OP( END_CATCH);
OP( LNOT);
return TCL_OK;
}
return TclCompileBasicMin0ArgCmd(interp, parsePtr, cmdPtr, envPtr);
}
int
TclCompileStringMatchCmd(
Tcl_Interp *interp, /* Used for error reporting. */
@@ -700,8 +979,8 @@ TclCompileStringReplaceCmd(
/*
* We handle these replacements specially: first character (where
* idx1=idx2=0) and suffixes (where idx1=idx2=INDEX_END). Anything else
* and the semantics get rather screwy.
* idx1=idx2=0) and last character (where idx1=idx2=INDEX_END). Anything
* else and the semantics get rather screwy.
*/
if (idx1 == 0 && idx2 == 0) {
@@ -787,37 +1066,6 @@ TclCompileStringReplaceCmd(
}
}
/*
* Synch with tclCmdMZ.c
*/
#define DEFAULT_TRIM_SET \
"\x09\x0a\x0b\x0c\x0d " /* ASCII */\
"\xc0\x80" /* nul (U+0000) */\
"\xc2\x85" /* next line (U+0085) */\
"\xc2\xa0" /* non-breaking space (U+00a0) */\
"\xe1\x9a\x80" /* ogham space mark (U+1680) */ \
"\xe1\xa0\x8e" /* mongolian vowel separator (U+180e) */\
"\xe2\x80\x80" /* en quad (U+2000) */\
"\xe2\x80\x81" /* em quad (U+2001) */\
"\xe2\x80\x82" /* en space (U+2002) */\
"\xe2\x80\x83" /* em space (U+2003) */\
"\xe2\x80\x84" /* three-per-em space (U+2004) */\
"\xe2\x80\x85" /* four-per-em space (U+2005) */\
"\xe2\x80\x86" /* six-per-em space (U+2006) */\
"\xe2\x80\x87" /* figure space (U+2007) */\
"\xe2\x80\x88" /* punctuation space (U+2008) */\
"\xe2\x80\x89" /* thin space (U+2009) */\
"\xe2\x80\x8a" /* hair space (U+200a) */\
"\xe2\x80\x8b" /* zero width space (U+200b) */\
"\xe2\x80\xa8" /* line separator (U+2028) */\
"\xe2\x80\xa9" /* paragraph separator (U+2029) */\
"\xe2\x80\xaf" /* narrow no-break space (U+202f) */\
"\xe2\x81\x9f" /* medium mathematical space (U+205f) */\
"\xe2\x81\xa0" /* word joiner (U+2060) */\
"\xe3\x80\x80" /* ideographic space (U+3000) */\
"\xef\xbb\xbf" /* zero width no-break space (U+feff) */
int
TclCompileStringTrimLCmd(
Tcl_Interp *interp, /* Used for error reporting. */
@@ -840,7 +1088,7 @@ TclCompileStringTrimLCmd(
tokenPtr = TokenAfter(tokenPtr);
CompileWord(envPtr, tokenPtr, interp, 2);
} else {
PushLiteral(envPtr, DEFAULT_TRIM_SET, strlen(DEFAULT_TRIM_SET));
PushStringLiteral(envPtr, DEFAULT_TRIM_SET);
}
OP( STR_TRIM_LEFT);
return TCL_OK;
@@ -868,7 +1116,7 @@ TclCompileStringTrimRCmd(
tokenPtr = TokenAfter(tokenPtr);
CompileWord(envPtr, tokenPtr, interp, 2);
} else {
PushLiteral(envPtr, DEFAULT_TRIM_SET, strlen(DEFAULT_TRIM_SET));
PushStringLiteral(envPtr, DEFAULT_TRIM_SET);
}
OP( STR_TRIM_RIGHT);
return TCL_OK;
@@ -896,7 +1144,7 @@ TclCompileStringTrimCmd(
tokenPtr = TokenAfter(tokenPtr);
CompileWord(envPtr, tokenPtr, interp, 2);
} else {
PushLiteral(envPtr, DEFAULT_TRIM_SET, strlen(DEFAULT_TRIM_SET));
PushStringLiteral(envPtr, DEFAULT_TRIM_SET);
}
OP( STR_TRIM);
return TCL_OK;
@@ -968,6 +1216,41 @@ TclCompileStringToTitleCmd(
return TCL_OK;
}
/*
* Support definitions for the [string is] compilation.
*/
static int
UniCharIsAscii(
int character)
{
return (character >= 0) && (character < 0x80);
}
static int
UniCharIsHexDigit(
int character)
{
return (character >= 0) && (character < 0x80) && isxdigit(character);
}
StringClassDesc const tclStringClassTable[] = {
{"alnum", Tcl_UniCharIsAlnum},
{"alpha", Tcl_UniCharIsAlpha},
{"ascii", UniCharIsAscii},
{"control", Tcl_UniCharIsControl},
{"digit", Tcl_UniCharIsDigit},
{"graph", Tcl_UniCharIsGraph},
{"lower", Tcl_UniCharIsLower},
{"print", Tcl_UniCharIsPrint},
{"punct", Tcl_UniCharIsPunct},
{"space", Tcl_UniCharIsSpace},
{"upper", Tcl_UniCharIsUpper},
{"word", Tcl_UniCharIsWordChar},
{"xdigit", UniCharIsHexDigit},
{NULL, NULL}
};
/*
*----------------------------------------------------------------------
*
@@ -3474,6 +3757,51 @@ TclCompileYieldCmd(
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclCompileYieldToCmd --
*
* Procedure called to compile the "yieldto" command.
*
* 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 "yieldto" command at
* runtime.
*
*----------------------------------------------------------------------
*/
int
TclCompileYieldToCmd(
Tcl_Interp *interp, /* Used for error reporting. */
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. */
{
DefineLineInformation; /* TIP #280 */
Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
int i;
if (parsePtr->numWords < 2) {
return TCL_ERROR;
}
OP( NS_CURRENT);
for (i = 1 ; i < parsePtr->numWords ; i++) {
CompileWord(envPtr, tokenPtr, interp, i);
tokenPtr = TokenAfter(tokenPtr);
}
OP4( LIST, i);
OP( YIELD_TO_INVOKE);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
+48 -4
View File
@@ -493,6 +493,7 @@ InstructionDesc const tclInstructionTable[] = {
* qualified version, or produces the empty string if no such command
* exists. Never generates errors.
* Stack: ... cmdName => ... fullCmdName */
{"tclooSelf", 1, +1, 0, {OPERAND_NONE}},
/* Push the identity of the current TclOO object (i.e., the name of
* its current public access command) on the stack. */
@@ -594,23 +595,61 @@ InstructionDesc const tclInstructionTable[] = {
* is number of values to concatenate.
* Operation: push concat(stk1 stk2 ... stktop) */
{"strUpper", 1, 0, 0, {OPERAND_NONE}},
{"strcaseUpper", 1, 0, 0, {OPERAND_NONE}},
/* [string toupper] core: converts whole string to upper case using
* the default (extended "C" locale) rules.
* Stack: ... string => ... newString */
{"strLower", 1, 0, 0, {OPERAND_NONE}},
{"strcaseLower", 1, 0, 0, {OPERAND_NONE}},
/* [string tolower] core: converts whole string to upper case using
* the default (extended "C" locale) rules.
* Stack: ... string => ... newString */
{"strTitle", 1, 0, 0, {OPERAND_NONE}},
{"strcaseTitle", 1, 0, 0, {OPERAND_NONE}},
/* [string totitle] core: converts whole string to upper case using
* the default (extended "C" locale) rules.
* Stack: ... string => ... newString */
{"strReplace", 1, -3, 0, {OPERAND_NONE}},
{"strreplace", 1, -3, 0, {OPERAND_NONE}},
/* [string replace] core: replaces a non-empty range of one string
* with the contents of another.
* Stack: ... string fromIdx toIdx replacement => ... newString */
{"originCmd", 1, 0, 0, {OPERAND_NONE}},
/* Reports which command was the origin (via namespace import chain)
* of the command named on the top of the stack.
* Stack: ... cmdName => ... fullOriginalCmdName */
{"tclooNext", 2, INT_MIN, 1, {OPERAND_UINT1}},
/* Call the next item on the TclOO call chain, passing opnd arguments
* (min 1, max 255, *includes* "next"). The result of the invoked
* method implementation will be pushed on the stack in place of the
* arguments (similar to invokeStk).
* Stack: ... "next" arg2 arg3 -- argN => ... result */
{"tclooNextClass", 2, INT_MIN, 1, {OPERAND_UINT1}},
/* Call the following item on the TclOO call chain defined by class
* className, passing opnd arguments (min 2, max 255, *includes*
* "nextto" and the class name). The result of the invoked method
* implementation will be pushed on the stack in place of the
* arguments (similar to invokeStk).
* Stack: ... "nextto" className arg3 arg4 -- argN => ... result */
{"yieldToInvoke", 1, 0, 0, {OPERAND_NONE}},
/* Makes the current coroutine yield the value at the top of the
* stack, invoking the given command/args with resolution in the given
* namespace (all packed into a list), and places the list of values
* that are the response back on top of the stack when it resumes.
* Stack: ... [list ns cmd arg1 ... argN] => ... resumeList */
{"numericType", 1, 0, 0, {OPERAND_NONE}},
/* Pushes the numeric type code of the word at the top of the stack.
* Stack: ... value => ... typeCode */
{"tryCvtToBoolean", 1, +1, 0, {OPERAND_NONE}},
/* Try converting stktop to boolean if possible. No errors.
* Stack: ... value => ... value isStrictBool */
{"strclass", 2, 0, 1, {OPERAND_SCLS1}},
/* See if all the characters of the given string are a member of the
* specified (by opnd) character class. Note that an empty string will
* satisfy the class check (standard definition of "all").
* Stack: ... stringValue => ... boolean */
{NULL, 0, 0, 0, {OPERAND_NONE}}
};
@@ -5058,6 +5097,11 @@ FormatInstruction(
}
Tcl_AppendPrintfToObj(bufferObj, "%%v%u ", (unsigned) opnd);
break;
case OPERAND_SCLS1:
opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
Tcl_AppendPrintfToObj(bufferObj, "%s ",
tclStringClassTable[opnd].name);
break;
case OPERAND_NONE:
default:
break;
+50 -2
View File
@@ -751,6 +751,8 @@ typedef struct ByteCode {
#define INST_INFO_LEVEL_NUM 152
#define INST_INFO_LEVEL_ARGS 153
#define INST_RESOLVE_COMMAND 154
/* For compilation relating to TclOO */
#define INST_TCLOO_SELF 155
#define INST_TCLOO_CLASS 156
#define INST_TCLOO_NS 157
@@ -786,8 +788,19 @@ typedef struct ByteCode {
#define INST_STR_TITLE 176
#define INST_STR_REPLACE 177
#define INST_ORIGIN_COMMAND 178
#define INST_TCLOO_NEXT 179
#define INST_TCLOO_NEXT_CLASS 180
#define INST_YIELD_TO_INVOKE 181
#define INST_NUM_TYPE 182
#define INST_TRY_CVT_TO_BOOLEAN 183
#define INST_STR_CLASS 184
/* The last opcode */
#define LAST_INST_OPCODE 177
#define LAST_INST_OPCODE 184
/*
* Table describing the Tcl bytecode instructions: their name (for displaying
@@ -812,8 +825,9 @@ typedef enum InstOperandType {
* variable table. */
OPERAND_LVT4, /* Four byte unsigned index into the local
* variable table. */
OPERAND_AUX4 /* Four byte unsigned index into the aux data
OPERAND_AUX4, /* Four byte unsigned index into the aux data
* table. */
OPERAND_SCLS1 /* Index into tclStringClassTable. */
} InstOperandType;
typedef struct InstructionDesc {
@@ -831,6 +845,40 @@ typedef struct InstructionDesc {
MODULE_SCOPE InstructionDesc const tclInstructionTable[];
/*
* Constants used by INST_STRING_CLASS to indicate character classes. These
* correspond closely by name with what [string is] can support, but there is
* no requirement to keep the values the same.
*/
typedef enum InstStringClassType {
STR_CLASS_ALNUM, /* Unicode alphabet or digit characters. */
STR_CLASS_ALPHA, /* Unicode alphabet characters. */
STR_CLASS_ASCII, /* Characters in range U+000000..U+00007F. */
STR_CLASS_CONTROL, /* Unicode control characters. */
STR_CLASS_DIGIT, /* Unicode digit characters. */
STR_CLASS_GRAPH, /* Unicode printing characters, excluding
* space. */
STR_CLASS_LOWER, /* Unicode lower-case alphabet characters. */
STR_CLASS_PRINT, /* Unicode printing characters, including
* spaces. */
STR_CLASS_PUNCT, /* Unicode punctuation characters. */
STR_CLASS_SPACE, /* Unicode space characters. */
STR_CLASS_UPPER, /* Unicode upper-case alphabet characters. */
STR_CLASS_WORD, /* Unicode word (alphabetic, digit, connector
* punctuation) characters. */
STR_CLASS_XDIGIT /* Characters that can be used as digits in
* hexadecimal numbers ([0-9A-Fa-f]). */
} InstStringClassType;
typedef struct StringClassDesc {
const char *name; /* Name of the class. */
int (*comparator)(int); /* Function to test if a single unicode
* character is a member of the class. */
} StringClassDesc;
MODULE_SCOPE StringClassDesc const tclStringClassTable[];
/*
* Compilation of some Tcl constructs such as if commands and the logical or
* (||) and logical and (&&) operators in expressions requires the generation
+896 -459
View File
File diff suppressed because it is too large Load Diff
+18
View File
@@ -3493,6 +3493,9 @@ MODULE_SCOPE int TclCompileEnsemble(Tcl_Interp *interp,
MODULE_SCOPE int TclCompileErrorCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileEvalCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileExprCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
@@ -3571,6 +3574,9 @@ MODULE_SCOPE int TclCompileNamespaceCodeCmd(Tcl_Interp *interp,
MODULE_SCOPE int TclCompileNamespaceCurrentCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileNamespaceOriginCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileNamespaceQualifiersCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
@@ -3586,6 +3592,12 @@ MODULE_SCOPE int TclCompileNamespaceWhichCmd(Tcl_Interp *interp,
MODULE_SCOPE int TclCompileNoOp(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileObjectNextCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileObjectNextToCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileObjectSelfCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
@@ -3613,6 +3625,9 @@ MODULE_SCOPE int TclCompileStringFirstCmd(Tcl_Interp *interp,
MODULE_SCOPE int TclCompileStringIndexCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileStringIsCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileStringLastCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
@@ -3679,6 +3694,9 @@ MODULE_SCOPE int TclCompileWhileCmd(Tcl_Interp *interp,
MODULE_SCOPE int TclCompileYieldCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileYieldToCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
MODULE_SCOPE int TclCompileBasic0ArgCmd(Tcl_Interp *interp,
Tcl_Parse *parsePtr, Command *cmdPtr,
struct CompileEnv *envPtr);
+1 -1
View File
@@ -171,7 +171,7 @@ static const EnsembleImplMap defaultNamespaceMap[] = {
{"forget", NamespaceForgetCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0},
{"import", NamespaceImportCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0},
{"inscope", NamespaceInscopeCmd, NULL, NRNamespaceInscopeCmd, NULL, 0},
{"origin", NamespaceOriginCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
{"origin", NamespaceOriginCmd, TclCompileNamespaceOriginCmd, NULL, NULL, 0},
{"parent", NamespaceParentCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
{"path", NamespacePathCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
{"qualifiers", NamespaceQualifiersCmd, TclCompileNamespaceQualifiersCmd, NULL, NULL, 0},
+6 -4
View File
@@ -437,10 +437,12 @@ InitFoundation(
* ensemble.
*/
Tcl_CreateObjCommand(interp, "::oo::Helpers::next", TclOONextObjCmd, NULL,
NULL);
Tcl_CreateObjCommand(interp, "::oo::Helpers::nextto", TclOONextToObjCmd,
NULL, NULL);
cmdPtr = (Command *) Tcl_NRCreateCommand(interp, "::oo::Helpers::next",
NULL, TclOONextObjCmd, NULL, NULL);
cmdPtr->compileProc = TclCompileObjectNextCmd;
cmdPtr = (Command *) Tcl_NRCreateCommand(interp, "::oo::Helpers::nextto",
NULL, TclOONextToObjCmd, NULL, NULL);
cmdPtr->compileProc = TclCompileObjectNextToCmd;
cmdPtr = (Command *) Tcl_CreateObjCommand(interp, "::oo::Helpers::self",
TclOOSelfObjCmd, NULL, NULL);
cmdPtr->compileProc = TclCompileObjectSelfCmd;
+25 -18
View File
@@ -17,16 +17,11 @@
#include "tclOOInt.h"
static inline Tcl_Object *AddConstructionFinalizer(Tcl_Interp *interp);
static int AfterNRDestructor(ClientData data[],
Tcl_Interp *interp, int result);
static int DecrRefsPostClassConstructor(ClientData data[],
Tcl_Interp *interp, int result);
static int FinalizeConstruction(ClientData data[],
Tcl_Interp *interp, int result);
static int FinalizeEval(ClientData data[],
Tcl_Interp *interp, int result);
static int RestoreFrame(ClientData data[],
Tcl_Interp *interp, int result);
static Tcl_NRPostProc AfterNRDestructor;
static Tcl_NRPostProc DecrRefsPostClassConstructor;
static Tcl_NRPostProc FinalizeConstruction;
static Tcl_NRPostProc FinalizeEval;
static Tcl_NRPostProc NextRestoreFrame;
/*
* ----------------------------------------------------------------------
@@ -808,7 +803,7 @@ TclOONextObjCmd(
* that this is like [uplevel 1] and not [eval].
*/
TclNRAddCallback(interp, RestoreFrame, framePtr, NULL, NULL, NULL);
TclNRAddCallback(interp, NextRestoreFrame, framePtr, NULL,NULL,NULL);
iPtr->varFramePtr = framePtr->callerVarPtr;
return TclNRObjectContextInvokeNext(interp, context, objc, objv, 1);
}
@@ -826,6 +821,7 @@ TclOONextToObjCmd(
CallContext *contextPtr;
int i;
Tcl_Object object;
const char *methodType;
/*
* Start with sanity checks on the calling context to make sure that we
@@ -877,8 +873,8 @@ TclOONextToObjCmd(
* context. Note that this is like [uplevel 1] and not [eval].
*/
TclNRAddCallback(interp, RestoreFrame, framePtr, contextPtr,
INT2PTR(contextPtr->index), NULL);
TclNRAddCallback(interp, NextRestoreFrame, framePtr,
contextPtr, INT2PTR(contextPtr->index), NULL);
contextPtr->index = i-1;
iPtr->varFramePtr = framePtr->callerVarPtr;
return TclNRObjectContextInvokeNext(interp,
@@ -891,24 +887,35 @@ TclOONextToObjCmd(
* is on the chain but unreachable, or not on the chain at all.
*/
if (contextPtr->callPtr->flags & CONSTRUCTOR) {
methodType = "constructor";
} else if (contextPtr->callPtr->flags & DESTRUCTOR) {
methodType = "destructor";
} else {
methodType = "method";
}
for (i=contextPtr->index ; i>=0 ; i--) {
struct MInvoke *miPtr = contextPtr->callPtr->chain + i;
if (!miPtr->isFilter && miPtr->mPtr->declaringClassPtr == classPtr) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"method implementation by \"%s\" not reachable from here",
TclGetString(objv[1])));
"%s implementation by \"%s\" not reachable from here",
methodType, TclGetString(objv[1])));
Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_REACHABLE",
NULL);
return TCL_ERROR;
}
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"method has no non-filter implementation by \"%s\"",
TclGetString(objv[1])));
"%s has no non-filter implementation by \"%s\"",
methodType, TclGetString(objv[1])));
Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_THERE", NULL);
return TCL_ERROR;
}
static int
RestoreFrame(
NextRestoreFrame(
ClientData data[],
Tcl_Interp *interp,
int result)
+32 -40
View File
@@ -1855,9 +1855,39 @@ InterpProcNR2(
}
/*
* Process the result code.
* Free the stack-allocated compiled locals and CallFrame. It is important
* to pop the call frame without freeing it first: the compiledLocals
* cannot be freed before the frame is popped, as the local variables must
* be deleted. But the compiledLocals must be freed first, as they were
* allocated later on the stack.
*/
if (result != TCL_OK) {
goto process;
}
done:
if (TCL_DTRACE_PROC_RESULT_ENABLED()) {
int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
Tcl_Obj *r = Tcl_GetObjResult(interp);
TCL_DTRACE_PROC_RESULT(l < iPtr->varFramePtr->objc ?
TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result,
TclGetString(r), r);
}
freePtr = iPtr->framePtr;
Tcl_PopCallFrame(interp); /* Pop but do not free. */
TclStackFree(interp, freePtr->compiledLocals);
/* Free compiledLocals. */
TclStackFree(interp, freePtr); /* Free CallFrame. */
return result;
/*
* Process any non-TCL_OK result code.
*/
process:
switch (result) {
case TCL_RETURN:
/*
@@ -1892,46 +1922,8 @@ InterpProcNR2(
*/
errorProc(interp, procNameObj);
default:
/*
* Process other results (OK and non-standard) by doing nothing
* special, skipping directly to the code afterwards that cleans up
* associated memory.
*
* Non-standard results are processed by passing them through quickly.
* This means they all work as exceptions, unwinding the stack quickly
* and neatly. Who knows how well they are handled by third-party code
* though...
*/
(void) 0; /* do nothing */
}
if (TCL_DTRACE_PROC_RESULT_ENABLED()) {
int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
Tcl_Obj *r = Tcl_GetObjResult(interp);
TCL_DTRACE_PROC_RESULT(l < iPtr->varFramePtr->objc ?
TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result,
TclGetString(r), r);
}
/*
* Free the stack-allocated compiled locals and CallFrame. It is important
* to pop the call frame without freeing it first: the compiledLocals
* cannot be freed before the frame is popped, as the local variables must
* be deleted. But the compiledLocals must be freed first, as they were
* allocated later on the stack.
*/
freePtr = iPtr->framePtr;
Tcl_PopCallFrame(interp); /* Pop but do not free. */
TclStackFree(interp, freePtr->compiledLocals);
/* Free compiledLocals. */
TclStackFree(interp, freePtr); /* Free CallFrame. */
return result;
goto done;
}
/*
+68
View File
@@ -0,0 +1,68 @@
/*
* tclStringTrim.h --
*
* This file contains the definition of what characters are to be trimmed
* from a string by [string trim] by default. It's only needed by Tcl's
* implementation; it does not form a public or private API at all.
*
* Copyright (c) 1987-1993 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
* Copyright (c) 1998-2000 Scriptics Corporation.
* Copyright (c) 2002 ActiveState Corporation.
* Copyright (c) 2003-2013 Donal K. Fellows.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#ifndef TCL_STRING_TRIM_H
#define TCL_STRING_TRIM_H
/*
* Default set of characters to trim in [string trim] and friends. This is a
* UTF-8 literal string containing all Unicode space characters. [TIP #413]
*/
#define DEFAULT_TRIM_SET \
"\x09\x0a\x0b\x0c\x0d " /* ASCII */\
"\xc0\x80" /* nul (U+0000) */\
"\xc2\x85" /* next line (U+0085) */\
"\xc2\xa0" /* non-breaking space (U+00a0) */\
"\xe1\x9a\x80" /* ogham space mark (U+1680) */ \
"\xe1\xa0\x8e" /* mongolian vowel separator (U+180e) */\
"\xe2\x80\x80" /* en quad (U+2000) */\
"\xe2\x80\x81" /* em quad (U+2001) */\
"\xe2\x80\x82" /* en space (U+2002) */\
"\xe2\x80\x83" /* em space (U+2003) */\
"\xe2\x80\x84" /* three-per-em space (U+2004) */\
"\xe2\x80\x85" /* four-per-em space (U+2005) */\
"\xe2\x80\x86" /* six-per-em space (U+2006) */\
"\xe2\x80\x87" /* figure space (U+2007) */\
"\xe2\x80\x88" /* punctuation space (U+2008) */\
"\xe2\x80\x89" /* thin space (U+2009) */\
"\xe2\x80\x8a" /* hair space (U+200a) */\
"\xe2\x80\x8b" /* zero width space (U+200b) */\
"\xe2\x80\xa8" /* line separator (U+2028) */\
"\xe2\x80\xa9" /* paragraph separator (U+2029) */\
"\xe2\x80\xaf" /* narrow no-break space (U+202f) */\
"\xe2\x81\x9f" /* medium mathematical space (U+205f) */\
"\xe2\x81\xa0" /* word joiner (U+2060) */\
"\xe3\x80\x80" /* ideographic space (U+3000) */\
"\xef\xbb\xbf" /* zero width no-break space (U+feff) */
/*
* The whitespace trimming set used when [concat]enating. This is a subset of
* the above, and deliberately so.
*/
#define CONCAT_TRIM_SET " \f\v\r\t\n"
#endif /* TCL_STRING_TRIM_H */
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
+10 -6
View File
@@ -14,6 +14,7 @@
#include "tclInt.h"
#include "tclParse.h"
#include "tclStringTrim.h"
#include <math.h>
/*
@@ -1768,8 +1769,7 @@ TclTrimLeft(
*/
/* The whitespace characters trimmed during [concat] operations */
#define CONCAT_WS " \f\v\r\t\n"
#define CONCAT_WS_SIZE (int) (sizeof(CONCAT_WS "") - 1)
#define CONCAT_WS_SIZE (int) (sizeof(CONCAT_TRIM_SET "") - 1)
char *
Tcl_Concat(
@@ -1825,7 +1825,8 @@ Tcl_Concat(
* Trim away the leading whitespace.
*/
trim = TclTrimLeft(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
trim = TclTrimLeft(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE);
element += trim;
elemLength -= trim;
@@ -1834,7 +1835,8 @@ Tcl_Concat(
* a final backslash character.
*/
trim = TclTrimRight(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
trim = TclTrimRight(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE);
trim -= trim && (element[elemLength - trim - 1] == '\\');
elemLength -= trim;
@@ -1959,7 +1961,8 @@ Tcl_ConcatObj(
* Trim away the leading whitespace.
*/
trim = TclTrimLeft(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
trim = TclTrimLeft(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE);
element += trim;
elemLength -= trim;
@@ -1968,7 +1971,8 @@ Tcl_ConcatObj(
* a final backslash character.
*/
trim = TclTrimRight(element, elemLength, CONCAT_WS, CONCAT_WS_SIZE);
trim = TclTrimRight(element, elemLength, CONCAT_TRIM_SET,
CONCAT_WS_SIZE);
trim -= trim && (element[elemLength - trim - 1] == '\\');
elemLength -= trim;
+87 -5
View File
@@ -1,4 +1,4 @@
# Commands covered: coroutine, yield, [info coroutine]
# Commands covered: coroutine, yield, yieldto, [info coroutine]
#
# This file contains a collection of tests for experimental commands that are
# found in ::tcl::unsupported. The tests will migrate to normal test files
@@ -612,7 +612,6 @@ test coroutine-7.3 {yielding between coroutines} -body {
} -cleanup {
catch {rename juggler ""}
} -result {{{a b c d e} ::j1 {a b c d} ::j2 {a b c} ::j3 {a b} ::j1 a ::j2} {} {} {}}
test coroutine-7.4 {Bug 8ff0cb9fe1} -setup {
proc foo {a b} {catch yield; return 1}
} -cleanup {
@@ -620,7 +619,6 @@ test coroutine-7.4 {Bug 8ff0cb9fe1} -setup {
} -body {
coroutine demo lsort -command foo {a b}
} -result {b a}
test coroutine-7.5 {return codes} {
set result {}
foreach code {0 1 2 3 4 5} {
@@ -628,14 +626,12 @@ test coroutine-7.5 {return codes} {
}
set result
} {0 1 2 3 4 5}
test coroutine-7.6 {Early yield crashes} {
proc foo args {}
trace add execution foo enter {catch yield}
coroutine demo foo
rename foo {}
} {}
test coroutine-7.7 {Bug 2486550} -setup {
interp hide {} yield
} -body {
@@ -644,6 +640,92 @@ test coroutine-7.7 {Bug 2486550} -setup {
demo
interp expose {} yield
} -result ok
test coroutine-7.8 {yieldto context nuke: Bug a90d9331bc} -setup {
namespace eval cotest {}
set ::result ""
} -body {
proc cotest::body {} {
lappend ::result a
yield OUT
lappend ::result b
yieldto ::return -level 0 123
lappend ::result c
return
}
lappend ::result [coroutine cotest cotest::body]
namespace delete cotest
namespace eval cotest {}
lappend ::result [cotest]
cotest
return $result
} -returnCodes error -cleanup {
catch {namespace delete ::cotest}
catch {rename cotest ""}
} -result {yieldto called in deleted namespace}
test coroutine-7.9 {yieldto context nuke: Bug a90d9331bc} -setup {
namespace eval cotest {}
set ::result ""
} -body {
proc cotest::body {} {
set y ::yieldto
lappend ::result a
yield OUT
lappend ::result b
$y ::return -level 0 123
lappend ::result c
return
}
lappend ::result [coroutine cotest cotest::body]
namespace delete cotest
namespace eval cotest {}
lappend ::result [cotest]
cotest
return $result
} -returnCodes error -cleanup {
catch {namespace delete ::cotest}
catch {rename cotest ""}
} -result {yieldto called in deleted namespace}
test coroutine-7.10 {yieldto context nuke: Bug a90d9331bc} -setup {
namespace eval cotest {}
set ::result ""
} -body {
proc cotest::body {} {
lappend ::result a
yield OUT
lappend ::result b
yieldto ::return -level 0 -cotest [namespace delete ::cotest] 123
lappend ::result c
return
}
lappend ::result [coroutine cotest cotest::body]
lappend ::result [cotest]
cotest
return $result
} -returnCodes error -cleanup {
catch {namespace delete ::cotest}
catch {rename cotest ""}
} -result {yieldto called in deleted namespace}
test coroutine-7.11 {yieldto context nuke: Bug a90d9331bc} -setup {
namespace eval cotest {}
set ::result ""
} -body {
proc cotest::body {} {
set y ::yieldto
lappend ::result a
yield OUT
lappend ::result b
$y ::return -level 0 -cotest [namespace delete ::cotest] 123
lappend ::result c
return
}
lappend ::result [coroutine cotest cotest::body]
lappend ::result [cotest]
cotest
return $result
} -returnCodes error -cleanup {
catch {namespace delete ::cotest}
catch {rename cotest ""}
} -result {yieldto called in deleted namespace}
# cleanup
+5 -3
View File
@@ -1035,6 +1035,7 @@ IOHDR=$(GENERIC_DIR)/tclIO.h
MATHHDRS=$(GENERIC_DIR)/tommath.h $(GENERIC_DIR)/tclTomMath.h
PARSEHDR=$(GENERIC_DIR)/tclParse.h
NREHDR=$(GENERIC_DIR)/tclInt.h
TRIMHDR=$(GENERIC_DIR)/tclStringTrim.h
regcomp.o: $(REGHDRS) $(GENERIC_DIR)/regcomp.c $(GENERIC_DIR)/regc_lex.c \
$(GENERIC_DIR)/regc_color.c $(GENERIC_DIR)/regc_locale.c \
@@ -1080,7 +1081,7 @@ tclCmdAH.o: $(GENERIC_DIR)/tclCmdAH.c
tclCmdIL.o: $(GENERIC_DIR)/tclCmdIL.c $(TCLREHDRS)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdIL.c
tclCmdMZ.o: $(GENERIC_DIR)/tclCmdMZ.c $(TCLREHDRS)
tclCmdMZ.o: $(GENERIC_DIR)/tclCmdMZ.c $(TCLREHDRS) $(TRIMHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdMZ.c
tclDate.o: $(GENERIC_DIR)/tclDate.c
@@ -1092,7 +1093,7 @@ tclCompCmds.o: $(GENERIC_DIR)/tclCompCmds.c $(COMPILEHDR)
tclCompCmdsGR.o: $(GENERIC_DIR)/tclCompCmdsGR.c $(COMPILEHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompCmdsGR.c
tclCompCmdsSZ.o: $(GENERIC_DIR)/tclCompCmdsSZ.c $(COMPILEHDR)
tclCompCmdsSZ.o: $(GENERIC_DIR)/tclCompCmdsSZ.c $(COMPILEHDR) $(TRIMHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompCmdsSZ.c
tclCompExpr.o: $(GENERIC_DIR)/tclCompExpr.c $(COMPILEHDR)
@@ -1195,6 +1196,7 @@ tclLoadDld.o: $(UNIX_DIR)/tclLoadDld.c
$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadDld.c
tclLoadDyld.o: $(UNIX_DIR)/tclLoadDyld.c
@echo Warnings are expected from compiling tclLoadDyld.c: deprecated API use
$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadDyld.c
tclLoadNone.o: $(GENERIC_DIR)/tclLoadNone.c
@@ -1308,7 +1310,7 @@ tclStubInit.o: $(GENERIC_DIR)/tclStubInit.c
tclTrace.o: $(GENERIC_DIR)/tclTrace.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclTrace.c
tclUtil.o: $(GENERIC_DIR)/tclUtil.c $(PARSEHDR)
tclUtil.o: $(GENERIC_DIR)/tclUtil.c $(PARSEHDR) $(TRIMHDR)
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclUtil.c
tclUtf.o: $(GENERIC_DIR)/tclUtf.c $(GENERIC_DIR)/tclUniData.c