1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
-
+
+
-
-
+
+
+
-
+
+
+
+
+
+
|
/*
* tclProc.c --
*
* This file contains routines that implement Tcl procedures, including
* the "proc" and "uplevel" commands.
*
* Copyright (c) 1987-1993 The Regents of the University of California.
* Copyright (c) 1994-1998 Sun Microsystems, Inc.
* Copyright (c) 2004-2006 Miguel Sofer
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: tclProc.c,v 1.86.2.1 2006/07/12 15:32:27 dkf Exp $
* RCS: @(#) $Id: tclProc.c,v 1.86.2.2 2006/08/18 22:28:44 dkf Exp $
*/
#include "tclInt.h"
#include "tclCompile.h"
#include "tclOO.h"
/*
* Prototypes for static functions in this file
*/
static int ObjInterpProcEx(ClientData clientData,register Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[], int skip);
static int ObjInterpProcEx(ClientData clientData,
register Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[], int skip);
static void ProcBodyDup(Tcl_Obj *srcPtr, Tcl_Obj *dupPtr);
static void ProcBodyFree(Tcl_Obj *objPtr);
static int ProcessProcResultCode(Tcl_Interp *interp,
char *procName, int nameLen, int returnCode);
char *procName, int nameLen, int returnCode,
int isMethod);
static int TclCompileNoOp(Tcl_Interp *interp, Tcl_Parse *parsePtr,
struct CompileEnv *envPtr);
static void InitCompiledLocals(Tcl_Interp *interp,
ByteCode *codePtr, CompiledLocal *localPtr,
Var *varPtr, Namespace *nsPtr);
static void DupLambdaInternalRep(Tcl_Obj *objPtr,
Tcl_Obj *copyPtr);
static void FreeLambdaInternalRep(Tcl_Obj *objPtr);
static int SetLambdaFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
/*
* The ProcBodyObjType type
*/
Tcl_ObjType tclProcBodyType = {
"procbody", /* name for this type */
|
| ︙ | | |
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
* rep; it's just a cache type.
*/
static Tcl_ObjType levelReferenceType = {
"levelReference",
NULL, NULL, NULL, NULL
};
/*
* The type of "lambda expression" terms (i.e., the first arguments to the
* [apply] command). A lambdaType Tcl_Obj has the form:
*
* ptr1 is a *Proc: pointer to a proc structure
* ptr2 is a *Tcl_Obj: the lambda's namespace
*/
Tcl_ObjType lambdaType = {
"lambdaExpr", /* name */
FreeLambdaInternalRep, /* freeIntRepProc */
DupLambdaInternalRep, /* dupIntRepProc */
NULL, /* updateStringProc */
SetLambdaFromAny /* setFromAnyProc */
};
/*
*----------------------------------------------------------------------
*
* Tcl_ProcObjCmd --
*
* This object-based function is invoked to process the "proc" Tcl
|
| ︙ | | |
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
-
+
-
+
|
/* ARGSUSED */
int
Tcl_ProcObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *CONST objv[]) /* Argument objects. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
register Interp *iPtr = (Interp *) interp;
Proc *procPtr;
char *fullName;
CONST char *procName, *procArgs, *procBody;
const char *procName, *procArgs, *procBody;
Namespace *nsPtr, *altNsPtr, *cxtNsPtr;
Tcl_Command cmd;
Tcl_DString ds;
if (objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv, "name args body");
return TCL_ERROR;
|
| ︙ | | |
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
|
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
|
-
+
-
+
-
+
|
*----------------------------------------------------------------------
*/
int
TclCreateProc(
Tcl_Interp *interp, /* interpreter containing proc */
Namespace *nsPtr, /* namespace containing this proc */
CONST char *procName, /* unqualified name of this proc */
const char *procName, /* unqualified name of this proc */
Tcl_Obj *argsPtr, /* description of arguments */
Tcl_Obj *bodyPtr, /* command body */
Proc **procPtrPtr) /* returns: pointer to proc data */
{
Interp *iPtr = (Interp*)interp;
CONST char **argArray = NULL;
const char **argArray = NULL;
register Proc *procPtr;
int i, length, result, numArgs;
CONST char *args, *bytes, *p;
const char *args, *bytes, *p;
register CompiledLocal *localPtr = NULL;
Tcl_Obj *defPtr;
int precompiled = 0;
if (bodyPtr->typePtr == &tclProcBodyType) {
/*
* Because the body is a TclProProcBody, the actual body is already
|
| ︙ | | |
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
|
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
|
-
+
|
} else {
procPtr->numArgs = numArgs;
procPtr->numCompiledLocals = numArgs;
}
for (i = 0; i < numArgs; i++) {
int fieldCount, nameLength, valueLength;
CONST char **fieldValues;
const char **fieldValues;
/*
* Now divide the specifier up into name and default.
*/
result = Tcl_SplitList(interp, argArray[i], &fieldCount,
&fieldValues);
|
| ︙ | | |
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
|
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
|
-
+
|
/*
* Check that the formal parameter name is a scalar.
*/
p = fieldValues[0];
while (*p != '\0') {
if (*p == '(') {
CONST char *q = p;
const char *q = p;
do {
q++;
} while (*q != '\0');
q--;
if (*q == ')') { /* we have an array element */
Tcl_AppendResult(interp, "formal parameter \"",
fieldValues[0],
|
| ︙ | | |
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
|
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
|
-
+
|
*
*----------------------------------------------------------------------
*/
int
TclGetFrame(
Tcl_Interp *interp, /* Interpreter in which to find frame. */
CONST char *name, /* String describing frame. */
const char *name, /* String describing frame. */
CallFrame **framePtrPtr) /* Store pointer to frame here (or NULL if
* global frame indicated). */
{
register Interp *iPtr = (Interp *) interp;
int curLevel, level, result;
CallFrame *framePtr;
|
| ︙ | | |
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
|
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
|
-
+
|
Tcl_Obj *objPtr, /* Object describing frame. */
CallFrame **framePtrPtr) /* Store pointer to frame here (or NULL if
* global frame indicated). */
{
register Interp *iPtr = (Interp *) interp;
int curLevel, level, result;
CallFrame *framePtr;
CONST char *name = TclGetString(objPtr);
const char *name = TclGetString(objPtr);
/*
* Parse object to figure out which level number to go to.
*/
result = 1;
curLevel = (iPtr->varFramePtr == NULL) ? 0 : iPtr->varFramePtr->level;
|
| ︙ | | |
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
|
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
|
-
+
|
/* ARGSUSED */
int
Tcl_UplevelObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *CONST objv[]) /* Argument objects. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
register Interp *iPtr = (Interp *) interp;
int result;
CallFrame *savedVarFramePtr, *framePtr;
if (objc < 2) {
uplevelSyntax:
|
| ︙ | | |
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
|
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
|
-
+
|
*
*----------------------------------------------------------------------
*/
Proc *
TclFindProc(
Interp *iPtr, /* Interpreter in which to look. */
CONST char *procName) /* Name of desired procedure. */
const char *procName) /* Name of desired procedure. */
{
Tcl_Command cmd;
Tcl_Command origCmd;
Command *cmdPtr;
cmd = Tcl_FindCommand((Tcl_Interp *) iPtr, procName, NULL, /*flags*/ 0);
if (cmd == (Tcl_Command) NULL) {
|
| ︙ | | |
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
|
1135
1136
1137
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
|
-
+
-
+
|
TclObjInterpProc(
ClientData clientData, /* Record describing procedure to be
* interpreted. */
register Tcl_Interp *interp,/* Interpreter in which procedure was
* invoked. */
int objc, /* Count of number of arguments to this
* procedure. */
Tcl_Obj *CONST objv[]) /* Argument value objects. */
Tcl_Obj *const objv[]) /* Argument value objects. */
{
return ObjInterpProcEx(clientData, interp, objc, objv, /*skip*/ 1);
}
static int
ObjInterpProcEx(
ClientData clientData, /* Record describing procedure to be
* interpreted. */
register Tcl_Interp *interp,/* Interpreter in which procedure was
* invoked. */
int objc, /* Count of number of arguments to this
* procedure. */
Tcl_Obj *CONST objv[], /* Argument value objects. */
Tcl_Obj *const objv[], /* Argument value objects. */
int skip) /* Number of initial arguments to be skipped,
* i.e., words in the "command name" */
{
register Proc *procPtr = (Proc *) clientData;
Namespace *nsPtr = procPtr->cmdPtr->nsPtr;
CallFrame *framePtr, **framePtrPtr;
int result;
|
| ︙ | | |
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
|
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
1223
1224
|
-
+
-
-
+
+
+
-
+
-
+
+
|
framePtr->objc = objc;
framePtr->objv = objv; /* ref counts for args are incremented below */
framePtr->procPtr = procPtr;
return TclObjInterpProcCore(interp, framePtr, objv[0], skip);
}
static int
int
TclObjInterpProcCore(
register Tcl_Interp *interp,/* Interpreter in which procedure was
* invoked. */
CallFrame *framePtr,
Tcl_Obj *procNameObj,
CallFrame *framePtr, /* The context to execute. The procPtr field
* must be non-NULL. */
Tcl_Obj *procNameObj, /* Procedure name for error reporting. */
int skip) /* Number of initial arguments to be skipped,
* i.e., words in the "command name" */
* i.e., words in the "command name". */
{
register Proc *procPtr = framePtr->procPtr;
register Var *varPtr;
register CompiledLocal *localPtr;
int localCt, numArgs, argCt, i, imax, result;
Var *compiledLocals;
Tcl_Obj *CONST *argObjs;
Tcl_Obj *const *argObjs;
int isMethod = (framePtr->ooContextPtr != NULL);
/*
* Create the "compiledLocals" array. Make sure it is large enough to hold
* all the procedure's compiled local variables, including its formal
* parameters.
*/
|
| ︙ | | |
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
|
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
|
-
+
+
|
TclProcCleanupProc(procPtr);
}
if (result != TCL_OK) {
int nameLen;
char *procName = Tcl_GetStringFromObj(procNameObj, &nameLen);
result = ProcessProcResultCode(interp, procName, nameLen, result);
result = ProcessProcResultCode(interp, procName, nameLen, result,
isMethod);
}
/*
* Pop and free the call frame for this procedure invocation, then free
* the compiledLocals array if malloc'ed storage was used.
*/
|
| ︙ | | |
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
|
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
|
-
-
+
+
|
TclProcCompileProc(
Tcl_Interp *interp, /* Interpreter containing procedure. */
Proc *procPtr, /* Data associated with procedure. */
Tcl_Obj *bodyPtr, /* Body of proc. (Usually procPtr->bodyPtr,
* but could be any code fragment compiled in
* the context of this procedure.) */
Namespace *nsPtr, /* Namespace containing procedure. */
CONST char *description, /* string describing this body of code. */
CONST char *procName) /* Name of this procedure. */
const char *description, /* string describing this body of code. */
const char *procName) /* Name of this procedure. */
{
Interp *iPtr = (Interp*)interp;
int result;
Tcl_CallFrame *framePtr;
Proc *saveProcPtr;
ByteCode *codePtr = (ByteCode *) bodyPtr->internalRep.otherValuePtr;
|
| ︙ | | |
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
|
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
|
-
+
+
-
-
-
+
+
+
|
static int
ProcessProcResultCode(
Tcl_Interp *interp, /* The interpreter in which the procedure was
* called and returned returnCode. */
char *procName, /* Name of the procedure. Used for error
* messages and trace information. */
int nameLen, /* Number of bytes in procedure's name. */
int returnCode) /* The unexpected result code. */
int returnCode, /* The unexpected result code. */
int isMethod) /* Whether this is a method. */
{
Interp *iPtr = (Interp *) interp;
int overflow, limit = 60;
if (returnCode == TCL_OK) {
return TCL_OK;
}
if ((returnCode > TCL_CONTINUE) || (returnCode < TCL_OK)) {
return returnCode;
}
if (returnCode == TCL_RETURN) {
return TclUpdateReturnInfo(iPtr);
}
if (returnCode != TCL_ERROR) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "invoked \"",
((returnCode == TCL_BREAK) ? "break" : "continue"),
"\" outside of a loop", NULL);
}
overflow = (nameLen > limit);
TclFormatToErrorInfo(interp, "\n (procedure \"%.*s%s\" line %d)",
(overflow ? limit : nameLen), procName,
(overflow ? "..." : ""), interp->errorLine);
TclFormatToErrorInfo(interp, "\n (%s \"%.*s%s\" line %d)",
(isMethod ? "method" : "procedure"), (overflow ? limit : nameLen),
procName, (overflow ? "..." : ""), interp->errorLine);
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* TclProcDeleteProc --
|
| ︙ | | |
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
|
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
-
+
+
+
|
envPtr->currStackDepth = savedStackDepth;
TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
return TCL_OK;
}
/*
* LAMBDA and APPLY implementation
*
*/
static void DupLambdaInternalRep(Tcl_Obj *objPtr,
Tcl_Obj *copyPtr);
static void FreeLambdaInternalRep(
Tcl_Obj *objPtr);
static int SetLambdaFromAny(Tcl_Interp *interp,
Tcl_Obj *objPtr);
Tcl_ObjType lambdaType = {
"lambdaExpr", /* name */
FreeLambdaInternalRep, /* freeIntRepProc */
DupLambdaInternalRep, /* dupIntRepProc */
(Tcl_UpdateStringProc *) NULL, /* updateStringProc */
SetLambdaFromAny /* setFromAnyProc */
};
/*
* a lambdaType Tcl_Obj has the form
*
* ptr1 is a *Proc: pointer to a proc structure
* ptr2 is a *Tcl_Obj: the lambda's namespace
*/
static void
DupLambdaInternalRep(srcPtr, copyPtr)
Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
register Tcl_Obj *copyPtr; /* Object with internal rep to set. */
DupLambdaInternalRep(
Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
register Tcl_Obj *copyPtr) /* Object with internal rep to set. */
{
Proc *procPtr = (Proc *) srcPtr->internalRep.twoPtrValue.ptr1;
Tcl_Obj *nsObjPtr = (Tcl_Obj *) srcPtr->internalRep.twoPtrValue.ptr2;
Proc *procPtr = srcPtr->internalRep.twoPtrValue.ptr1;
Tcl_Obj *nsObjPtr = srcPtr->internalRep.twoPtrValue.ptr2;
copyPtr->internalRep.twoPtrValue.ptr1 = (VOID *) procPtr;
copyPtr->internalRep.twoPtrValue.ptr2 = (VOID *) nsObjPtr;
copyPtr->internalRep.twoPtrValue.ptr1 = procPtr;
copyPtr->internalRep.twoPtrValue.ptr2 = nsObjPtr;
procPtr->refCount++;
Tcl_IncrRefCount(nsObjPtr);
copyPtr->typePtr = &lambdaType;
}
static void
FreeLambdaInternalRep(objPtr)
register Tcl_Obj *objPtr; /* CmdName object with internal
* representation to free. */
FreeLambdaInternalRep(
register Tcl_Obj *objPtr) /* CmdName object with internal representation
* to free. */
{
Proc *procPtr = (Proc *) objPtr->internalRep.twoPtrValue.ptr1;
Tcl_Obj *nsObjPtr = (Tcl_Obj *) objPtr->internalRep.twoPtrValue.ptr2;
Proc *procPtr = objPtr->internalRep.twoPtrValue.ptr1;
Tcl_Obj *nsObjPtr = objPtr->internalRep.twoPtrValue.ptr2;
procPtr->refCount--;
if (procPtr->refCount == 0) {
TclProcCleanupProc(procPtr);
}
TclDecrRefCount(nsObjPtr);
}
static int
SetLambdaFromAny(interp, objPtr)
Tcl_Interp *interp; /* Used for error reporting if not NULL. */
register Tcl_Obj *objPtr; /* The object to convert. */
SetLambdaFromAny(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
register Tcl_Obj *objPtr) /* The object to convert. */
{
char *name;
Tcl_Obj *argsPtr, *bodyPtr, *nsObjPtr, **objv, *errPtr;
int objc;
Proc *procPtr;
int result;
|
| ︙ | | |
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
|
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
|
-
+
-
+
-
+
-
+
|
/*
* Create and initialize the Proc struct. The cmdPtr field is
* set to NULL to signal that this is an anonymous function.
*/
name = TclGetString(objPtr);
if (TclCreateProc(interp, /*ignored nsPtr*/ NULL, name, argsPtr,
bodyPtr, &procPtr) != TCL_OK) {
bodyPtr, &procPtr) != TCL_OK) {
TclFormatToErrorInfo(interp,
"\n (parsing lambda expression \"%s\")",
Tcl_GetString(objPtr), NULL);
TclGetString(objPtr), NULL);
return TCL_ERROR;
}
procPtr->refCount++;
procPtr->cmdPtr = (Command *) NULL;
/*
* Set the namespace for this lambda: given by objv[2] understood
* as a global reference, or else global per default.
*/
if (objc == 2) {
nsObjPtr = Tcl_NewStringObj("::", 2);
} else {
char *nsName = Tcl_GetString(objv[2]);
if ((*nsName != ':') || (*(nsName+1) != ':')) {
nsObjPtr = Tcl_NewStringObj("::", 2);
Tcl_AppendObjToObj(nsObjPtr, objv[2]);
|
| ︙ | | |
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
|
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
|
-
-
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
-
+
-
-
+
+
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
-
+
-
+
-
+
-
+
-
-
+
-
-
+
+
-
+
|
* Free the list internalrep of objPtr - this will free argsPtr, but
* bodyPtr retains a reference from the Proc structure. Then finish
* the conversion to lambdaType.
*/
objPtr->typePtr->freeIntRepProc(objPtr);
objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) procPtr;
objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) nsObjPtr;
objPtr->internalRep.twoPtrValue.ptr1 = procPtr;
objPtr->internalRep.twoPtrValue.ptr2 = nsObjPtr;
objPtr->typePtr = &lambdaType;
return TCL_OK;
}
int
Tcl_ApplyObjCmd(dummy, interp, objc, objv)
ClientData dummy; /* Not used. */
Tcl_Interp *interp; /* Current interpreter. */
int objc; /* Number of arguments. */
Tcl_Obj *CONST objv[]; /* Argument objects. */
Tcl_ApplyObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Interp *iPtr = (Interp *) interp;
Proc *procPtr = NULL;
Tcl_Obj *lambdaPtr, *nsObjPtr, *errPtr;
int result;
Command cmd;
Tcl_Namespace *nsPtr;
#define JOE_EXTENSION 0
#if JOE_EXTENSION
Tcl_Obj *elemPtr;
int numElem;
#endif
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "lambdaExpr ?arg1 arg2 ...?");
return TCL_ERROR;
}
/*
* Set lambdaPtr, convert it to lambdaType in the current
* interp if necessary.
* Set lambdaPtr, convert it to lambdaType in the current interp if
* necessary.
*/
lambdaPtr = objv[1];
if (lambdaPtr->typePtr == &lambdaType) {
procPtr = (Proc *) lambdaPtr->internalRep.twoPtrValue.ptr1;
procPtr = lambdaPtr->internalRep.twoPtrValue.ptr1;
}
#if JOE_EXTENSION
/*
* Joe English's suggestion to allow cmdNames to function as lambdas. Requires
* also making tclCmdNameType non-static in tclObj.c
/*
* Joe English's suggestion to allow cmdNames to function as lambdas.
* Requires also making tclCmdNameType non-static in tclObj.c
*
*/
} else if ((lambdaPtr->typePtr == &tclCmdNameType)
|| (TCL_OK == (Tcl_ListObjGetElements(interp, lambdaPtr, &numElem, &elemPtr))
&& (numElem == 1))) {
*/
else if ((lambdaPtr->typePtr == &tclCmdNameType) ||
(Tcl_ListObjLength(interp, lambdaPtr, &numElem) == TCL_OK &&
(numElem == 1))) {
return Tcl_EvalObjv(interp, objc-1, objv+1, 0);
#endif
}
#endif
if ((procPtr == NULL) || (procPtr->iPtr != iPtr)) {
result = SetLambdaFromAny(interp, lambdaPtr);
if (result != TCL_OK) {
return result;
}
procPtr = (Proc *) lambdaPtr->internalRep.twoPtrValue.ptr1;
procPtr = lambdaPtr->internalRep.twoPtrValue.ptr1;
}
procPtr->cmdPtr = &cmd;
/*
* Find the namespace where this lambda should run, and
* Find the namespace where this lambda should run, and push a call frame
* push a call frame for that namespace. Note that
* TclObjInterpProc() will pop it.
* for that namespace. Note that TclObjInterpProc() will pop it.
*/
nsObjPtr = (Tcl_Obj *) lambdaPtr->internalRep.twoPtrValue.ptr2;
nsObjPtr = lambdaPtr->internalRep.twoPtrValue.ptr2;
result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr);
if (result != TCL_OK) {
return result;
}
if (nsPtr == (Tcl_Namespace *) NULL) {
errPtr = Tcl_NewStringObj("cannot find namespace \"",-1);
Tcl_AppendObjToObj(errPtr, nsObjPtr);
Tcl_AppendToObj(errPtr, "\"", -1);
Tcl_SetObjResult(interp, errPtr);
return TCL_ERROR;
}
cmd.nsPtr = (Namespace *) nsPtr;
return ObjInterpProcEx((ClientData) procPtr, interp, objc, objv, 2);
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
|