Tcl Source Code

Artifact [e8e175572a]
Login

Artifact e8e175572ae3e00786d99c12f6b6b5155d05c5d3:

Attachment "CallFrameResolvers.txt" to ticket [1779249fff] added by wiede 2007-08-22 15:23:05.
Index: tcl.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tcl.h,v
retrieving revision 1.234
diff -d -u -r1.234 tcl.h
--- tcl.h	31 Jul 2007 17:03:35 -0000	1.234
+++ tcl.h	19 Aug 2007 09:14:33 -0000
@@ -835,6 +835,21 @@
 				 * namespace. */
 } Tcl_Namespace;
 
+#ifdef ARNULF_FOR_ITCL_CODE
+struct Tcl_Resolve;
+typedef Tcl_Command (Tcl_CmdAliasProc)(Tcl_Interp *interp,
+        Tcl_Namespace *nsPtr, CONST char *cmdName,
+	struct Tcl_Resolve *resolvePtr);
+typedef Tcl_Var (Tcl_VarAliasProc)(Tcl_Interp *interp,
+        Tcl_Namespace *nsPtr, CONST char *varName,
+	struct Tcl_Resolve *resolvePtr);
+typedef struct Tcl_Resolve {
+    Tcl_VarAliasProc *varProcPtr;
+    Tcl_CmdAliasProc *cmdProcPtr;
+    ClientData clientData;
+} Tcl_Resolve;
+#endif
+
 /*
  * The following structure represents a call frame, or activation record. A
  * call frame defines a naming context for a procedure call: its local scope
@@ -871,6 +886,9 @@
     char *dummy10;
     char *dummy11;
     char *dummy12;
+#ifdef ARNULF_FOR_ITCL_CODE
+    char *dummy13;
+#endif
 } Tcl_CallFrame;
 
 /*
Index: tclInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v
retrieving revision 1.329
diff -d -u -r1.329 tclInt.h
--- tclInt.h	7 Aug 2007 17:28:39 -0000	1.329
+++ tclInt.h	19 Aug 2007 09:15:16 -0000
@@ -320,6 +320,9 @@
     NamespacePathEntry *commandPathSourceList;
 				/* Linked list of path entries that point to
 				 * this namespace. */
+#ifdef ARNULF_FOR_ITCL_CODE
+    Tcl_Resolve *resolvePtr;
+#endif
 } Namespace;
 
 /*
@@ -960,6 +963,7 @@
     ClientData clientData;	/* Value to pass to proc. */
 } AssocData;
 
+
 /*
  * The structure below defines a call frame. A call frame defines a naming
  * context for a procedure call: its local naming scope (for local variables)
@@ -1044,10 +1048,21 @@
 				 * meaning of the value is, which we do not
 				 * specify. */
     LocalCache *localCachePtr;
+#ifdef ARNULF_FOR_ITCL_CODE
+    Tcl_Resolve *resolvePtr;
+                                /* points to a struct with info for command
+				 * and variable resolving, may be NULL.
+				 * Only relevant if flag FRAME_HAS_RESOLVER in
+				 * isProcCallFrame is set
+				 */
+#endif
 } CallFrame;
 
 #define FRAME_IS_PROC   0x1
 #define FRAME_IS_LAMBDA 0x2
+#ifdef ARNULF_FOR_ITCL_CODE
+#define FRAME_HAS_RESOLVER 0x100
+#endif
 
 /*
  * TIP #280
Index: tclNamesp.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclNamesp.c,v
retrieving revision 1.148
diff -d -u -r1.148 tclNamesp.c
--- tclNamesp.c	3 Aug 2007 13:51:40 -0000	1.148
+++ tclNamesp.c	19 Aug 2007 09:16:19 -0000
@@ -813,6 +813,9 @@
     nsPtr->commandPathLength = 0;
     nsPtr->commandPathArray = NULL;
     nsPtr->commandPathSourceList = NULL;
+#ifdef ARNULF_FOR_ITCL_CODE
+    nsPtr->resolvePtr = NULL;
+#endif
 
     if (parentPtr != NULL) {
 	entryPtr = Tcl_CreateHashEntry(&parentPtr->childTable, simpleName,
@@ -2354,6 +2357,13 @@
     register Command *cmdPtr;
     const char *simpleName;
     int result;
+#ifdef ARNULF_FOR_ITCL_CODE
+    int frame_has_resolver = 0;
+    if (iPtr->varFramePtr != NULL) {
+        frame_has_resolver = iPtr->varFramePtr->isProcCallFrame &
+	        FRAME_HAS_RESOLVER;
+    }
+#endif
 
     /*
      * If this namespace has a command resolver, then give it first crack at
@@ -2396,6 +2406,18 @@
 	    return (Tcl_Command) NULL;
 	}
     }
+#ifdef ARNULF_FOR_ITCL_CODE
+    if (frame_has_resolver && (iPtr->varFramePtr->resolvePtr)) {
+	Tcl_Command resolvedCmdPtr = NULL;
+	Tcl_Resolve *resolvePtr = iPtr->varFramePtr->resolvePtr;
+	if (resolvePtr->cmdProcPtr != NULL) {
+	    resolvedCmdPtr = (resolvePtr->cmdProcPtr)(interp, (Tcl_Namespace *)iPtr->varFramePtr->nsPtr, name, resolvePtr);
+	    if (resolvedCmdPtr != NULL) {
+	        return resolvedCmdPtr;
+	    }
+        }
+    }
+#endif
 
     /*
      * Find the namespace(s) that contain the command.
@@ -3269,6 +3291,12 @@
 	 */
 
 	Interp *iPtr = (Interp *) interp;
+#ifdef ARNULF_FOR_ITCL_CODE
+        if (((Namespace *)namespacePtr)->resolvePtr != NULL) {
+	    framePtr->isProcCallFrame |= FRAME_HAS_RESOLVER;
+	    framePtr->resolvePtr = ((Namespace *)namespacePtr)->resolvePtr;
+	}
+#endif
 
 	result = TclEvalObjEx(interp, objv[3], 0, iPtr->cmdFramePtr, 3);
     } else {
@@ -3284,6 +3312,12 @@
 	 * TIP #280: Make invoking context available to eval'd script.
 	 */
 
+#ifdef ARNULF_FOR_ITCL_CODE
+        if (((Namespace *)namespacePtr)->resolvePtr != NULL) {
+	    framePtr->isProcCallFrame |= FRAME_HAS_RESOLVER;
+	    framePtr->resolvePtr = ((Namespace *)namespacePtr)->resolvePtr;
+	}
+#endif
 	result = TclEvalObjEx(interp, objPtr, TCL_EVAL_DIRECT, NULL, 0);
     }
 
@@ -5984,6 +6018,11 @@
     int reparseCount = 0;	/* Number of reparses. */
 
     if (objc < 2) {
+#ifdef ARNULF_FOR_ITCL_CODE
+        if (ensemblePtr->unknownHandler != NULL) {
+            goto unknownOrAmbiguousSubcommand;
+        }
+#endif
 	Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?argument ...?");
 	return TCL_ERROR;
     }
Index: tclProc.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclProc.c,v
retrieving revision 1.127
diff -d -u -r1.127 tclProc.c
--- tclProc.c	4 Aug 2007 18:32:27 -0000	1.127
+++ tclProc.c	19 Aug 2007 09:16:35 -0000
@@ -1114,6 +1114,7 @@
  *
  *----------------------------------------------------------------------
  */
+
 void
 TclInitCompiledLocals(
     Tcl_Interp *interp,		/* Current interpreter. */
@@ -1170,6 +1171,10 @@
     int haveResolvers = (nsPtr->compiledVarResProc || iPtr->resolverPtr);
     CompiledLocal *firstLocalPtr, *localPtr;
     int varNum;
+#ifdef ARNULF_FOR_ITCL_CODE
+    int frame_has_resolver = iPtr->varFramePtr->isProcCallFrame & FRAME_HAS_RESOLVER;
+#endif
+
 
     /*
      * Find the localPtr corresponding to varPtr
@@ -1186,7 +1191,11 @@
         //maybe for VAR_TEMPORARY? Who cares really?) A job for tbcload, not us.
     */
     
-    if (!(haveResolvers && (codePtr->flags & TCL_BYTECODE_RESOLVE_VARS))) {
+    if (!(haveResolvers && (codePtr->flags & TCL_BYTECODE_RESOLVE_VARS))
+#ifdef ARNULF_FOR_ITCL_CODE
+       && !frame_has_resolver
+#endif
+    ) {
 	/*
 	 * Initialize the array of local variables stored in the call frame.
 	 * Some variables may have special resolution rules. In that case, we
@@ -1195,7 +1204,11 @@
 	 */
 
     doInitCompiledLocals:
-	if (!haveResolvers) {
+	if (!haveResolvers
+#ifdef ARNULF_FOR_ITCL_CODE
+            && !frame_has_resolver
+#endif
+	) {
 	    /*
 	     * Should not be called: deadwood.
 	     */
@@ -1223,7 +1236,7 @@
 			    (*resVarInfo->fetchProc)(interp, resVarInfo);
 		    if (resolvedVarPtr) {
 			VarHashRefCount(resolvedVarPtr)++;
-			varPtr->flags = VAR_LINK;
+			TclSetVarLink(varPtr);
 			varPtr->value.linkPtr = resolvedVarPtr;
 		    }
 		}
@@ -1275,6 +1288,25 @@
 		    localPtr->flags |= VAR_RESOLVED;
 		}
 	    }
+#ifdef ARNULF_FOR_ITCL_CODE
+                if (frame_has_resolver &&
+                        !(localPtr->flags & (VAR_ARGUMENT|VAR_TEMPORARY)) &&
+                        (iPtr->varFramePtr->resolvePtr != NULL)) {
+		    Tcl_Resolve *resolvePtr = iPtr->varFramePtr->resolvePtr;
+		    varPtr->flags = localPtr->flags;
+		    varPtr->value.objPtr = NULL;
+		    if (resolvePtr->varProcPtr != NULL) {
+	                Var *resolvedVarPtr;
+		        resolvedVarPtr = (Var *)(resolvePtr->varProcPtr)(interp, (Tcl_Namespace*)iPtr->varFramePtr->nsPtr, localPtr->name, resolvePtr);
+	                if (resolvedVarPtr != NULL) {
+			    VarHashRefCount(resolvedVarPtr)++;
+			    TclSetVarLink(varPtr);
+		            varPtr->value.linkPtr = resolvedVarPtr;
+                        }
+		    }
+		    varPtr++;
+                }
+#endif
 	}
 	localPtr = firstLocalPtr;
 	codePtr->flags &= ~TCL_BYTECODE_RESOLVE_VARS;
@@ -1373,6 +1405,9 @@
     register Var *varPtr, *defPtr;
     int localCt = procPtr->numCompiledLocals, numArgs, argCt, i, imax;
     Tcl_Obj *const *argObjs;
+#ifdef ARNULF_FOR_ITCL_CODE
+    int haveFrameResolver = framePtr->isProcCallFrame & FRAME_HAS_RESOLVER;
+#endif
         
     /*
      * Make sure that the local cache of variable names and initial values has
@@ -1482,7 +1517,11 @@
 
   correctArgs:
     if (numArgs < localCt) {
-	if (!framePtr->nsPtr->compiledVarResProc && !((Interp *)interp)->resolverPtr) {
+	if (!framePtr->nsPtr->compiledVarResProc && !((Interp *)interp)->resolverPtr
+#ifdef ARNULF_FOR_ITCL_CODE
+            && !haveFrameResolver
+#endif
+	) {
 	    memset(varPtr, 0, (localCt - numArgs)*sizeof(Var));
 	} else {
 	    InitCompiledLocals(interp, codePtr, varPtr, framePtr->nsPtr);
@@ -2711,6 +2750,9 @@
 	    (overflow ? limit : nameLen), procName,
 	    (overflow ? "..." : ""), interp->errorLine));
 }
 
 /*
  * Local Variables:
Index: tclVar.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclVar.c,v
retrieving revision 1.149
diff -d -u -r1.149 tclVar.c
--- tclVar.c	4 Aug 2007 18:32:28 -0000	1.149
+++ tclVar.c	19 Aug 2007 09:17:05 -0000
@@ -880,6 +880,50 @@
 	}
     }
 
+#ifdef ARNULF_FOR_ITCL_CODE
+    int frame_has_resolver = 0;
+    if (iPtr->varFramePtr != NULL) {
+        frame_has_resolver = iPtr->varFramePtr->isProcCallFrame &
+	        FRAME_HAS_RESOLVER;
+    }
+    /*
+     * If this namespace has a call frame variable resolver, then give it
+     * first crack at the variable resolution. It may return a Tcl_Var value,
+     * otherwise just continue
+     */
+
+    if (frame_has_resolver && (iPtr->varFramePtr->resolvePtr) &&
+            !(flags & LOOKUP_FOR_UPVAR)) {
+	Var *resolvedVarPtr = NULL;
+	Tcl_Resolve *resolvePtr = iPtr->varFramePtr->resolvePtr;
+	if (resolvePtr->varProcPtr != NULL) {
+	    resolvedVarPtr = (Var *)(resolvePtr->varProcPtr)(interp, (Tcl_Namespace *)iPtr->varFramePtr->nsPtr, varName, resolvePtr);
+	    if (resolvedVarPtr != NULL) {
+	        CompiledLocal *lPtr;
+		if (iPtr->varFramePtr->procPtr != NULL) {
+		    lPtr = iPtr->varFramePtr->procPtr->firstLocalPtr;
+
+		    int j = 0;
+	            for (;lPtr != NULL; lPtr = lPtr->nextPtr, j++) {
+		        if ((varName[0] == lPtr->name[0])
+			        && (strcmp(varName, lPtr->name) == 0)) {
+		            if (j > varFramePtr->procPtr->numArgs) {
+                                break;
+		            } else {
+			        resolvedVarPtr = NULL;
+				break;
+			    }
+		        }
+	            }
+	        }
+		if (resolvedVarPtr != NULL) {
+		    return resolvedVarPtr;
+		}
+	    }
+        }
+    }
+#endif
+
     /*
      * Look up varName. Look it up as either a namespace variable or as a
      * local variable in a procedure call frame (varFramePtr). Interpret