diff options
| author | Stefan Monnier | 2010-12-12 23:04:15 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2010-12-12 23:04:15 -0500 |
| commit | f07a954eeb0930029104402e706165bf89853576 (patch) | |
| tree | 143d5c5a95904a0559d555ae6fe97eaed7839211 /src/eval.c | |
| parent | 2c302df3a13236bfbf8ea1b771d13618fcda8d71 (diff) | |
| download | emacs-f07a954eeb0930029104402e706165bf89853576.tar.gz emacs-f07a954eeb0930029104402e706165bf89853576.zip | |
Make the effect of (defvar foo) local.
* src/eval.c (apply_lambda): Make static. Remove eval_flag arg.
(Fsetq): Don't check declared_special.
(Fdefun, Fdefmacro): Use Ffunction.
(Fdefvar): Don't set declared_special for (defvar foo).
(FletX): Check locally-special vars. Only do specbind once.
(Flet): Check locally-special vars.
(Feval): Don't check declared_special.
(funcall_lambda): Check locally-special vars.
* src/lisp.h (apply_lambda): Remove extern declaration.
* src/lread.c (readevalloop): CSE.
* lisp/subr.el (with-lexical-binding): Remove.
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 116 |
1 files changed, 66 insertions, 50 deletions
diff --git a/src/eval.c b/src/eval.c index 574c4ebf361..63ea95513b3 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -81,9 +81,12 @@ Lisp_Object Vrun_hooks; | |||
| 81 | Lisp_Object Vautoload_queue; | 81 | Lisp_Object Vautoload_queue; |
| 82 | 82 | ||
| 83 | /* When lexical binding is being used, this is non-nil, and contains an | 83 | /* When lexical binding is being used, this is non-nil, and contains an |
| 84 | alist of lexically-bound variable, or t, indicating an empty | 84 | alist of lexically-bound variable, or (t), indicating an empty |
| 85 | environment. The lisp name of this variable is | 85 | environment. The lisp name of this variable is |
| 86 | `internal-interpreter-lexical-environment'. */ | 86 | `internal-interpreter-environment'. Every element of this list |
| 87 | can be either a cons (VAR . VAL) specifying a lexical binding, | ||
| 88 | or a single symbol VAR indicating that this variable should use | ||
| 89 | dynamic scoping. */ | ||
| 87 | 90 | ||
| 88 | Lisp_Object Vinternal_interpreter_environment; | 91 | Lisp_Object Vinternal_interpreter_environment; |
| 89 | 92 | ||
| @@ -175,6 +178,8 @@ int handling_signal; | |||
| 175 | 178 | ||
| 176 | Lisp_Object Vmacro_declaration_function; | 179 | Lisp_Object Vmacro_declaration_function; |
| 177 | 180 | ||
| 181 | static Lisp_Object apply_lambda (Lisp_Object fun, Lisp_Object args, | ||
| 182 | Lisp_Object lexenv) | ||
| 178 | static Lisp_Object funcall_lambda (Lisp_Object, int, Lisp_Object *, | 183 | static Lisp_Object funcall_lambda (Lisp_Object, int, Lisp_Object *, |
| 179 | Lisp_Object); | 184 | Lisp_Object); |
| 180 | static void unwind_to_catch (struct catchtag *, Lisp_Object) NO_RETURN; | 185 | static void unwind_to_catch (struct catchtag *, Lisp_Object) NO_RETURN; |
| @@ -505,10 +510,12 @@ usage: (setq [SYM VAL]...) */) | |||
| 505 | val = Feval (Fcar (Fcdr (args_left))); | 510 | val = Feval (Fcar (Fcdr (args_left))); |
| 506 | sym = Fcar (args_left); | 511 | sym = Fcar (args_left); |
| 507 | 512 | ||
| 508 | if (!NILP (Vinternal_interpreter_environment) | 513 | /* Like for Feval, we do not check declared_special here since |
| 514 | it's been done when let-binding. */ | ||
| 515 | if (!NILP (Vinternal_interpreter_environment) /* Mere optimization! */ | ||
| 509 | && SYMBOLP (sym) | 516 | && SYMBOLP (sym) |
| 510 | && !XSYMBOL (sym)->declared_special | 517 | && !NILP (lex_binding |
| 511 | && !NILP (lex_binding = Fassq (sym, Vinternal_interpreter_environment))) | 518 | = Fassq (sym, Vinternal_interpreter_environment))) |
| 512 | XSETCDR (lex_binding, val); /* SYM is lexically bound. */ | 519 | XSETCDR (lex_binding, val); /* SYM is lexically bound. */ |
| 513 | else | 520 | else |
| 514 | Fset (sym, val); /* SYM is dynamically bound. */ | 521 | Fset (sym, val); /* SYM is dynamically bound. */ |
| @@ -667,8 +674,8 @@ usage: (defun NAME ARGLIST [DOCSTRING] BODY...) */) | |||
| 667 | fn_name = Fcar (args); | 674 | fn_name = Fcar (args); |
| 668 | CHECK_SYMBOL (fn_name); | 675 | CHECK_SYMBOL (fn_name); |
| 669 | defn = Fcons (Qlambda, Fcdr (args)); | 676 | defn = Fcons (Qlambda, Fcdr (args)); |
| 670 | if (! NILP (Vinternal_interpreter_environment)) | 677 | if (!NILP (Vinternal_interpreter_environment)) /* Mere optimization! */ |
| 671 | defn = Fcons (Qclosure, Fcons (Vinternal_interpreter_environment, defn)); | 678 | defn = Ffunction (Fcons (defn, Qnil)); |
| 672 | if (!NILP (Vpurify_flag)) | 679 | if (!NILP (Vpurify_flag)) |
| 673 | defn = Fpurecopy (defn); | 680 | defn = Fpurecopy (defn); |
| 674 | if (CONSP (XSYMBOL (fn_name)->function) | 681 | if (CONSP (XSYMBOL (fn_name)->function) |
| @@ -742,8 +749,8 @@ usage: (defmacro NAME ARGLIST [DOCSTRING] [DECL] BODY...) */) | |||
| 742 | tail = Fcons (lambda_list, Fcons (doc, tail)); | 749 | tail = Fcons (lambda_list, Fcons (doc, tail)); |
| 743 | 750 | ||
| 744 | defn = Fcons (Qlambda, tail); | 751 | defn = Fcons (Qlambda, tail); |
| 745 | if (! NILP (Vinternal_interpreter_environment)) | 752 | if (!NILP (Vinternal_interpreter_environment)) /* Mere optimization! */ |
| 746 | defn = Fcons (Qclosure, Fcons (Vinternal_interpreter_environment, defn)); | 753 | defn = Ffunction (Fcons (defn, Qnil)); |
| 747 | defn = Fcons (Qmacro, defn); | 754 | defn = Fcons (Qmacro, defn); |
| 748 | 755 | ||
| 749 | if (!NILP (Vpurify_flag)) | 756 | if (!NILP (Vpurify_flag)) |
| @@ -888,16 +895,23 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */) | |||
| 888 | Fput (sym, Qvariable_documentation, tem); | 895 | Fput (sym, Qvariable_documentation, tem); |
| 889 | } | 896 | } |
| 890 | LOADHIST_ATTACH (sym); | 897 | LOADHIST_ATTACH (sym); |
| 898 | |||
| 899 | if (SYMBOLP (sym)) | ||
| 900 | XSYMBOL (sym)->declared_special = 1; | ||
| 891 | } | 901 | } |
| 902 | else if (!NILP (Vinternal_interpreter_environment) | ||
| 903 | && !XSYMBOL (sym)->declared_special) | ||
| 904 | /* A simple (defvar foo) with lexical scoping does "nothing" except | ||
| 905 | declare that var to be dynamically scoped *locally* (i.e. within | ||
| 906 | the current file or let-block). */ | ||
| 907 | Vinternal_interpreter_environment = | ||
| 908 | Fcons (sym, Vinternal_interpreter_environment); | ||
| 892 | else | 909 | else |
| 893 | /* Simple (defvar <var>) should not count as a definition at all. | 910 | /* Simple (defvar <var>) should not count as a definition at all. |
| 894 | It could get in the way of other definitions, and unloading this | 911 | It could get in the way of other definitions, and unloading this |
| 895 | package could try to make the variable unbound. */ | 912 | package could try to make the variable unbound. */ |
| 896 | ; | 913 | ; |
| 897 | 914 | ||
| 898 | if (SYMBOLP (sym)) | ||
| 899 | XSYMBOL (sym)->declared_special = 1; | ||
| 900 | |||
| 901 | return sym; | 915 | return sym; |
| 902 | } | 916 | } |
| 903 | 917 | ||
| @@ -1038,12 +1052,21 @@ usage: (let* VARLIST BODY...) */) | |||
| 1038 | val = Feval (Fcar (Fcdr (elt))); | 1052 | val = Feval (Fcar (Fcdr (elt))); |
| 1039 | } | 1053 | } |
| 1040 | 1054 | ||
| 1041 | if (!NILP (lexenv) && SYMBOLP (var) && !XSYMBOL (var)->declared_special) | 1055 | if (!NILP (lexenv) && SYMBOLP (var) |
| 1056 | && !XSYMBOL (var)->declared_special | ||
| 1057 | && NILP (Fmemq (var, Vinternal_interpreter_environment))) | ||
| 1042 | /* Lexically bind VAR by adding it to the interpreter's binding | 1058 | /* Lexically bind VAR by adding it to the interpreter's binding |
| 1043 | alist. */ | 1059 | alist. */ |
| 1044 | { | 1060 | { |
| 1045 | lexenv = Fcons (Fcons (var, val), lexenv); | 1061 | Lisp_Object newenv |
| 1046 | specbind (Qinternal_interpreter_environment, lexenv); | 1062 | = Fcons (Fcons (var, val), Vinternal_interpreter_environment); |
| 1063 | if (EQ (Vinternal_interpreter_environment, lexenv)) | ||
| 1064 | /* Save the old lexical environment on the specpdl stack, | ||
| 1065 | but only for the first lexical binding, since we'll never | ||
| 1066 | need to revert to one of the intermediate ones. */ | ||
| 1067 | specbind (Qinternal_interpreter_environment, newenv); | ||
| 1068 | else | ||
| 1069 | Vinternal_interpreter_environment = newenv; | ||
| 1047 | } | 1070 | } |
| 1048 | else | 1071 | else |
| 1049 | specbind (var, val); | 1072 | specbind (var, val); |
| @@ -1110,7 +1133,9 @@ usage: (let VARLIST BODY...) */) | |||
| 1110 | var = SYMBOLP (elt) ? elt : Fcar (elt); | 1133 | var = SYMBOLP (elt) ? elt : Fcar (elt); |
| 1111 | tem = temps[argnum++]; | 1134 | tem = temps[argnum++]; |
| 1112 | 1135 | ||
| 1113 | if (!NILP (lexenv) && SYMBOLP (var) && !XSYMBOL (var)->declared_special) | 1136 | if (!NILP (lexenv) && SYMBOLP (var) |
| 1137 | && !XSYMBOL (var)->declared_special | ||
| 1138 | && NILP (Fmemq (var, Vinternal_interpreter_environment))) | ||
| 1114 | /* Lexically bind VAR by adding it to the lexenv alist. */ | 1139 | /* Lexically bind VAR by adding it to the lexenv alist. */ |
| 1115 | lexenv = Fcons (Fcons (var, tem), lexenv); | 1140 | lexenv = Fcons (Fcons (var, tem), lexenv); |
| 1116 | else | 1141 | else |
| @@ -2302,25 +2327,17 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0, | |||
| 2302 | 2327 | ||
| 2303 | if (SYMBOLP (form)) | 2328 | if (SYMBOLP (form)) |
| 2304 | { | 2329 | { |
| 2305 | /* If there's an active lexical environment, and the variable | 2330 | /* Look up its binding in the lexical environment. |
| 2306 | isn't declared special, look up its binding in the lexical | 2331 | We do not pay attention to the declared_special flag here, since we |
| 2307 | environment. */ | 2332 | already did that when let-binding the variable. */ |
| 2308 | if (!NILP (Vinternal_interpreter_environment) | 2333 | Lisp_Object lex_binding |
| 2309 | && !XSYMBOL (form)->declared_special) | 2334 | = !NILP (Vinternal_interpreter_environment) /* Mere optimization! */ |
| 2310 | { | 2335 | ? Fassq (form, Vinternal_interpreter_environment) |
| 2311 | Lisp_Object lex_binding | 2336 | : Qnil; |
| 2312 | = Fassq (form, Vinternal_interpreter_environment); | 2337 | if (CONSP (lex_binding)) |
| 2313 | 2338 | return XCDR (lex_binding); | |
| 2314 | /* If we found a lexical binding for FORM, return the value. | 2339 | else |
| 2315 | Otherwise, we just drop through and look for a dynamic | 2340 | return Fsymbol_value (form); |
| 2316 | binding -- the variable isn't declared special, but there's | ||
| 2317 | not much else we can do, and Fsymbol_value will take care | ||
| 2318 | of signaling an error if there is no binding at all. */ | ||
| 2319 | if (CONSP (lex_binding)) | ||
| 2320 | return XCDR (lex_binding); | ||
| 2321 | } | ||
| 2322 | |||
| 2323 | return Fsymbol_value (form); | ||
| 2324 | } | 2341 | } |
| 2325 | 2342 | ||
| 2326 | if (!CONSP (form)) | 2343 | if (!CONSP (form)) |
| @@ -2485,7 +2502,7 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0, | |||
| 2485 | } | 2502 | } |
| 2486 | } | 2503 | } |
| 2487 | if (FUNVECP (fun)) | 2504 | if (FUNVECP (fun)) |
| 2488 | val = apply_lambda (fun, original_args, 1, Qnil); | 2505 | val = apply_lambda (fun, original_args, Qnil); |
| 2489 | else | 2506 | else |
| 2490 | { | 2507 | { |
| 2491 | if (EQ (fun, Qunbound)) | 2508 | if (EQ (fun, Qunbound)) |
| @@ -2503,7 +2520,7 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0, | |||
| 2503 | if (EQ (funcar, Qmacro)) | 2520 | if (EQ (funcar, Qmacro)) |
| 2504 | val = Feval (apply1 (Fcdr (fun), original_args)); | 2521 | val = Feval (apply1 (Fcdr (fun), original_args)); |
| 2505 | else if (EQ (funcar, Qlambda)) | 2522 | else if (EQ (funcar, Qlambda)) |
| 2506 | val = apply_lambda (fun, original_args, 1, | 2523 | val = apply_lambda (fun, original_args, |
| 2507 | /* Only pass down the current lexical environment | 2524 | /* Only pass down the current lexical environment |
| 2508 | if FUN is lexically embedded in FORM. */ | 2525 | if FUN is lexically embedded in FORM. */ |
| 2509 | (CONSP (original_fun) | 2526 | (CONSP (original_fun) |
| @@ -2513,7 +2530,7 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0, | |||
| 2513 | && CONSP (XCDR (fun)) | 2530 | && CONSP (XCDR (fun)) |
| 2514 | && CONSP (XCDR (XCDR (fun))) | 2531 | && CONSP (XCDR (XCDR (fun))) |
| 2515 | && EQ (XCAR (XCDR (XCDR (fun))), Qlambda)) | 2532 | && EQ (XCAR (XCDR (XCDR (fun))), Qlambda)) |
| 2516 | val = apply_lambda (XCDR (XCDR (fun)), original_args, 1, | 2533 | val = apply_lambda (XCDR (XCDR (fun)), original_args, |
| 2517 | XCAR (XCDR (fun))); | 2534 | XCAR (XCDR (fun))); |
| 2518 | else | 2535 | else |
| 2519 | xsignal1 (Qinvalid_function, original_fun); | 2536 | xsignal1 (Qinvalid_function, original_fun); |
| @@ -3208,9 +3225,8 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */) | |||
| 3208 | return val; | 3225 | return val; |
| 3209 | } | 3226 | } |
| 3210 | 3227 | ||
| 3211 | Lisp_Object | 3228 | static Lisp_Object |
| 3212 | apply_lambda (Lisp_Object fun, Lisp_Object args, int eval_flag, | 3229 | apply_lambda (Lisp_Object fun, Lisp_Object args, Lisp_Object lexenv) |
| 3213 | Lisp_Object lexenv) | ||
| 3214 | { | 3230 | { |
| 3215 | Lisp_Object args_left; | 3231 | Lisp_Object args_left; |
| 3216 | Lisp_Object numargs; | 3232 | Lisp_Object numargs; |
| @@ -3230,18 +3246,15 @@ apply_lambda (Lisp_Object fun, Lisp_Object args, int eval_flag, | |||
| 3230 | for (i = 0; i < XINT (numargs);) | 3246 | for (i = 0; i < XINT (numargs);) |
| 3231 | { | 3247 | { |
| 3232 | tem = Fcar (args_left), args_left = Fcdr (args_left); | 3248 | tem = Fcar (args_left), args_left = Fcdr (args_left); |
| 3233 | if (eval_flag) tem = Feval (tem); | 3249 | tem = Feval (tem); |
| 3234 | arg_vector[i++] = tem; | 3250 | arg_vector[i++] = tem; |
| 3235 | gcpro1.nvars = i; | 3251 | gcpro1.nvars = i; |
| 3236 | } | 3252 | } |
| 3237 | 3253 | ||
| 3238 | UNGCPRO; | 3254 | UNGCPRO; |
| 3239 | 3255 | ||
| 3240 | if (eval_flag) | 3256 | backtrace_list->args = arg_vector; |
| 3241 | { | 3257 | backtrace_list->nargs = i; |
| 3242 | backtrace_list->args = arg_vector; | ||
| 3243 | backtrace_list->nargs = i; | ||
| 3244 | } | ||
| 3245 | backtrace_list->evalargs = 0; | 3258 | backtrace_list->evalargs = 0; |
| 3246 | tem = funcall_lambda (fun, XINT (numargs), arg_vector, lexenv); | 3259 | tem = funcall_lambda (fun, XINT (numargs), arg_vector, lexenv); |
| 3247 | 3260 | ||
| @@ -3387,8 +3400,11 @@ funcall_lambda (Lisp_Object fun, int nargs, | |||
| 3387 | val = Qnil; | 3400 | val = Qnil; |
| 3388 | 3401 | ||
| 3389 | /* Bind the argument. */ | 3402 | /* Bind the argument. */ |
| 3390 | if (!NILP (lexenv) | 3403 | if (!NILP (lexenv) && SYMBOLP (next) |
| 3391 | && SYMBOLP (next) && !XSYMBOL (next)->declared_special) | 3404 | /* FIXME: there's no good reason to allow dynamic-scoping |
| 3405 | on function arguments, other than consistency with let. */ | ||
| 3406 | && !XSYMBOL (next)->declared_special | ||
| 3407 | && NILP (Fmemq (next, Vinternal_interpreter_environment))) | ||
| 3392 | /* Lexically bind NEXT by adding it to the lexenv alist. */ | 3408 | /* Lexically bind NEXT by adding it to the lexenv alist. */ |
| 3393 | lexenv = Fcons (Fcons (next, val), lexenv); | 3409 | lexenv = Fcons (Fcons (next, val), lexenv); |
| 3394 | else | 3410 | else |