Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Use new routine TclGetLambdaFromObj to better isolate the "lambdaExpr" ObjType. Then convert it to use the proposed routines. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | tip-445 |
Files: | files | file ages | folders |
SHA1: |
0af5b906900a4892732157026fb257fd |
User & Date: | dgp 2016-04-04 22:00:02.249 |
Context
2016-04-04
| ||
22:01 | merge trunk check-in: 759669541e user: dgp tags: tip-445 | |
22:00 | Use new routine TclGetLambdaFromObj to better isolate the "lambdaExpr" ObjType. Then convert it to u... check-in: 0af5b90690 user: dgp tags: tip-445 | |
19:41 | Use simple name for file static struct. check-in: 0170c0056c user: dgp tags: tip-445 | |
Changes
Changes to generic/tclDisassemble.c.
︙ | ︙ | |||
1321 1322 1323 1324 1325 1326 1327 | case DISAS_LAMBDA: { Command cmd; Tcl_Obj *nsObjPtr; Tcl_Namespace *nsPtr; /* * Compile (if uncompiled) and disassemble a lambda term. | < < < < | > | < < | < < < | 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 | case DISAS_LAMBDA: { Command cmd; Tcl_Obj *nsObjPtr; Tcl_Namespace *nsPtr; /* * Compile (if uncompiled) and disassemble a lambda term. */ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "lambdaTerm"); return TCL_ERROR; } procPtr = TclGetLambdaFromObj(interp, objv[2], &nsObjPtr); if (procPtr == NULL) { return TCL_ERROR; } memset(&cmd, 0, sizeof(Command)); result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr); if (result != TCL_OK) { return result; } cmd.nsPtr = (Namespace *) nsPtr; procPtr->cmdPtr = &cmd; result = TclPushProcCallFrame(procPtr, interp, objc, objv, 1); |
︙ | ︙ |
Changes to generic/tclInt.h.
︙ | ︙ | |||
2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 | MODULE_SCOPE int * TclGetAsyncReadyPtr(void); MODULE_SCOPE Tcl_Obj * TclGetBgErrorHandler(Tcl_Interp *interp); MODULE_SCOPE int TclGetChannelFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Channel *chanPtr, int *modePtr, int flags); MODULE_SCOPE int TclGetCompletionCodeFromObj(Tcl_Interp *interp, Tcl_Obj *value, int *code); MODULE_SCOPE int TclGetNumberFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, ClientData *clientDataPtr, int *typePtr); MODULE_SCOPE int TclGetOpenModeEx(Tcl_Interp *interp, const char *modeString, int *seekFlagPtr, int *binaryPtr); MODULE_SCOPE Tcl_Obj * TclGetProcessGlobalValue(ProcessGlobalValue *pgvPtr); | > > | 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 | MODULE_SCOPE int * TclGetAsyncReadyPtr(void); MODULE_SCOPE Tcl_Obj * TclGetBgErrorHandler(Tcl_Interp *interp); MODULE_SCOPE int TclGetChannelFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Channel *chanPtr, int *modePtr, int flags); MODULE_SCOPE int TclGetCompletionCodeFromObj(Tcl_Interp *interp, Tcl_Obj *value, int *code); MODULE_SCOPE Proc * TclGetLambdaFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **nsObjPtrPtr); MODULE_SCOPE int TclGetNumberFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, ClientData *clientDataPtr, int *typePtr); MODULE_SCOPE int TclGetOpenModeEx(Tcl_Interp *interp, const char *modeString, int *seekFlagPtr, int *binaryPtr); MODULE_SCOPE Tcl_Obj * TclGetProcessGlobalValue(ProcessGlobalValue *pgvPtr); |
︙ | ︙ |
Changes to generic/tclProc.c.
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" /* * Variables that are part of the [apply] command implementation and which * have to be passed to the other side of the NRE call. */ typedef struct { | > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" #include <assert.h> /* * Variables that are part of the [apply] command implementation and which * have to be passed to the other side of the NRE call. */ typedef struct { |
︙ | ︙ | |||
87 88 89 90 91 92 93 | * representation. * * Internally, ptr1 is a pointer to a Proc instance that is not bound to a * command name, and ptr2 is a pointer to the namespace that the Proc instance * will execute within. IF YOU CHANGE THIS, CHECK IN tclDisassemble.c TOO. */ | | > > > > > > > > > > > > > > > > > > | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | * representation. * * Internally, ptr1 is a pointer to a Proc instance that is not bound to a * command name, and ptr2 is a pointer to the namespace that the Proc instance * will execute within. IF YOU CHANGE THIS, CHECK IN tclDisassemble.c TOO. */ static const Tcl_ObjType lambdaType = { "lambdaExpr", /* name */ FreeLambdaInternalRep, /* freeIntRepProc */ DupLambdaInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ SetLambdaFromAny /* setFromAnyProc */ }; #define LambdaSetIntRep(objPtr, procPtr, nsObjPtr) \ do { \ Tcl_ObjIntRep ir; \ ir.twoPtrValue.ptr1 = (procPtr); \ ir.twoPtrValue.ptr2 = (nsObjPtr); \ Tcl_IncrRefCount((nsObjPtr)); \ Tcl_StoreIntRep((objPtr), &lambdaType, &ir); \ } while (0) #define LambdaGetIntRep(objPtr, procPtr, nsObjPtr) \ do { \ const Tcl_ObjIntRep *irPtr; \ irPtr = Tcl_FetchIntRep((objPtr), &lambdaType); \ (procPtr) = irPtr ? irPtr->twoPtrValue.ptr1 : NULL; \ (nsObjPtr) = irPtr ? irPtr->twoPtrValue.ptr2 : NULL; \ } while (0) /* *---------------------------------------------------------------------- * * Tcl_ProcObjCmd -- * * This object-based function is invoked to process the "proc" Tcl |
︙ | ︙ | |||
2419 2420 2421 2422 2423 2424 2425 | */ static void DupLambdaInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ register Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { | | | | | | | | | > > > < | | 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 | */ static void DupLambdaInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ register Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { Proc *procPtr; Tcl_Obj *nsObjPtr; LambdaGetIntRep(srcPtr, procPtr, nsObjPtr); assert(procPtr != NULL); procPtr->refCount++; LambdaSetIntRep(copyPtr, procPtr, nsObjPtr); } static void FreeLambdaInternalRep( register Tcl_Obj *objPtr) /* CmdName object with internal representation * to free. */ { Proc *procPtr; Tcl_Obj *nsObjPtr; LambdaGetIntRep(objPtr, procPtr, nsObjPtr); assert(procPtr != NULL); if (procPtr->refCount-- == 1) { TclProcCleanupProc(procPtr); } TclDecrRefCount(nsObjPtr); } static int SetLambdaFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr) /* The object to convert. */ { Interp *iPtr = (Interp *) interp; const char *name; Tcl_Obj *argsPtr, *bodyPtr, *nsObjPtr, **objv; int isNew, objc, result; CmdFrame *cfPtr = NULL; Proc *procPtr; if (interp == NULL) { return TCL_ERROR; } /* * Convert objPtr to list type first; if it cannot be converted, or if its * length is not 2, then it cannot be converted to lambdaType. */ result = TclListObjGetElements(NULL, objPtr, &objc, &objv); if ((result != TCL_OK) || ((objc != 2) && (objc != 3))) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't interpret \"%s\" as a lambda expression", Tcl_GetString(objPtr))); |
︙ | ︙ | |||
2604 2605 2606 2607 2608 2609 2610 | TclNewLiteralStringObj(nsObjPtr, "::"); Tcl_AppendObjToObj(nsObjPtr, objv[2]); } else { nsObjPtr = objv[2]; } } | < < | | > | | > > > > > > > > | > | > > | | > > > > > > > > > > > | 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 | TclNewLiteralStringObj(nsObjPtr, "::"); Tcl_AppendObjToObj(nsObjPtr, objv[2]); } else { nsObjPtr = objv[2]; } } /* * 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. */ LambdaSetIntRep(objPtr, procPtr, nsObjPtr); return TCL_OK; } Proc * TclGetLambdaFromObj( Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **nsObjPtrPtr) { Proc *procPtr; Tcl_Obj *nsObjPtr; LambdaGetIntRep(objPtr, procPtr, nsObjPtr); if (procPtr == NULL) { if (SetLambdaFromAny(interp, objPtr) != TCL_OK) { return NULL; } LambdaGetIntRep(objPtr, procPtr, nsObjPtr); } assert(procPtr != NULL); if (procPtr->iPtr != (Interp *)interp) { return NULL; } *nsObjPtrPtr = nsObjPtr; return procPtr; } /* *---------------------------------------------------------------------- * * Tcl_ApplyObjCmd -- * * This object-based function is invoked to process the "apply" Tcl |
︙ | ︙ | |||
2672 2673 2674 2675 2676 2677 2678 | /* * Set lambdaPtr, convert it to tclLambdaType in the current interp if * necessary. */ lambdaPtr = objv[1]; | < | | | < < < < < < | < < | | < | 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 | /* * Set lambdaPtr, convert it to tclLambdaType in the current interp if * necessary. */ lambdaPtr = objv[1]; procPtr = TclGetLambdaFromObj(interp, lambdaPtr, &nsObjPtr); if (procPtr == NULL) { #define JOE_EXTENSION 0 /* * Note: this code is NOT FUNCTIONAL due to the NR implementation; DO NOT * ENABLE! Leaving here as reminder to (a) TIP the suggestion, and (b) adapt * the code. (MS) */ #if JOE_EXTENSION /* * Joe English's suggestion to allow cmdNames to function as lambdas. */ Tcl_Obj *elemPtr; int numElem; if ((lambdaPtr->typePtr == &tclCmdNameType) || (TclListObjGetElements(interp, lambdaPtr, &numElem, &elemPtr) == TCL_OK && numElem == 1)) { return Tcl_EvalObjv(interp, objc-1, objv+1, 0); } #endif return TCL_ERROR; } /* * Push a call frame for the lambda namespace. * Note that TclObjInterpProc() will pop it. */ result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr); if (result != TCL_OK) { return TCL_ERROR; } extraPtr = TclStackAlloc(interp, sizeof(ApplyExtraData)); memset(&extraPtr->cmd, 0, sizeof(Command)); |
︙ | ︙ |