mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-15 10:30:25 -08:00
Obey lexical-binding in interactive evaluation commands.
* lisp/emacs-lisp/edebug.el (edebug-eval-defun, edebug-eval): * lisp/emacs-lisp/lisp-mode.el (eval-last-sexp-1, eval-defun-1): * lisp/ielm.el (ielm-eval-input): * lisp/simple.el (eval-expression): Use new eval arg to obey lexical-binding. * src/eval.c (Feval): Add `lexical' argument. Adjust callers. (Ffuncall, eval_sub): Avoid goto.
This commit is contained in:
parent
defb141157
commit
a0ee6f2751
13 changed files with 179 additions and 164 deletions
|
|
@ -1,3 +1,10 @@
|
|||
2010-12-15 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* emacs-lisp/edebug.el (edebug-eval-defun, edebug-eval):
|
||||
* emacs-lisp/lisp-mode.el (eval-last-sexp-1, eval-defun-1):
|
||||
* ielm.el (ielm-eval-input):
|
||||
* simple.el (eval-expression): Use new eval arg to obey lexical-binding.
|
||||
|
||||
2010-12-14 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* emacs-lisp/bytecomp.el (byte-compile-condition-case): Use push.
|
||||
|
|
|
|||
|
|
@ -521,7 +521,7 @@ the minibuffer."
|
|||
((and (eq (car form) 'defcustom)
|
||||
(default-boundp (nth 1 form)))
|
||||
;; Force variable to be bound.
|
||||
(set-default (nth 1 form) (eval (nth 2 form))))
|
||||
(set-default (nth 1 form) (eval (nth 2 form) lexical-binding)))
|
||||
((eq (car form) 'defface)
|
||||
;; Reset the face.
|
||||
(setq face-new-frame-defaults
|
||||
|
|
@ -534,7 +534,7 @@ the minibuffer."
|
|||
(put ',(nth 1 form) 'customized-face
|
||||
,(nth 2 form)))
|
||||
(put (nth 1 form) 'saved-face nil)))))
|
||||
(setq edebug-result (eval form))
|
||||
(setq edebug-result (eval form lexical-binding))
|
||||
(if (not edebugging)
|
||||
(princ edebug-result)
|
||||
edebug-result)))
|
||||
|
|
@ -2466,6 +2466,7 @@ MSG is printed after `::::} '."
|
|||
(if edebug-global-break-condition
|
||||
(condition-case nil
|
||||
(setq edebug-global-break-result
|
||||
;; FIXME: lexbind.
|
||||
(eval edebug-global-break-condition))
|
||||
(error nil))))
|
||||
(edebug-break))
|
||||
|
|
@ -2477,6 +2478,7 @@ MSG is printed after `::::} '."
|
|||
(and edebug-break-data
|
||||
(or (not edebug-break-condition)
|
||||
(setq edebug-break-result
|
||||
;; FIXME: lexbind.
|
||||
(eval edebug-break-condition))))))
|
||||
(if (and edebug-break
|
||||
(nth 2 edebug-break-data)) ; is it temporary?
|
||||
|
|
@ -3637,9 +3639,10 @@ Return the result of the last expression."
|
|||
|
||||
(defun edebug-eval (edebug-expr)
|
||||
;; Are there cl lexical variables active?
|
||||
(if (bound-and-true-p cl-debug-env)
|
||||
(eval (cl-macroexpand-all edebug-expr cl-debug-env))
|
||||
(eval edebug-expr)))
|
||||
(eval (if (bound-and-true-p cl-debug-env)
|
||||
(cl-macroexpand-all edebug-expr cl-debug-env)
|
||||
edebug-expr)
|
||||
lexical-binding)) ;; FIXME: lexbind.
|
||||
|
||||
(defun edebug-safe-eval (edebug-expr)
|
||||
;; Evaluate EXPR safely.
|
||||
|
|
@ -4241,8 +4244,8 @@ It is removed when you hit any char."
|
|||
;;; Menus
|
||||
|
||||
(defun edebug-toggle (variable)
|
||||
(set variable (not (eval variable)))
|
||||
(message "%s: %s" variable (eval variable)))
|
||||
(set variable (not (symbol-value variable)))
|
||||
(message "%s: %s" variable (symbol-value variable)))
|
||||
|
||||
;; We have to require easymenu (even for Emacs 18) just so
|
||||
;; the easy-menu-define macro call is compiled correctly.
|
||||
|
|
|
|||
|
|
@ -699,16 +699,9 @@ If CHAR is not a character, return nil."
|
|||
(defun eval-last-sexp-1 (eval-last-sexp-arg-internal)
|
||||
"Evaluate sexp before point; print value in minibuffer.
|
||||
With argument, print output into current buffer."
|
||||
(let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t))
|
||||
;; preserve the current lexical environment
|
||||
(internal-interpreter-environment internal-interpreter-environment))
|
||||
(let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t)))
|
||||
;; Setup the lexical environment if lexical-binding is enabled.
|
||||
;; Note that `internal-interpreter-environment' _can't_ be both
|
||||
;; assigned and let-bound above -- it's treated specially (and
|
||||
;; oddly) by the interpreter!
|
||||
(when lexical-binding
|
||||
(setq internal-interpreter-environment '(t)))
|
||||
(eval-last-sexp-print-value (eval (preceding-sexp)))))
|
||||
(eval-last-sexp-print-value (eval (preceding-sexp) lexical-binding))))
|
||||
|
||||
|
||||
(defun eval-last-sexp-print-value (value)
|
||||
|
|
@ -772,16 +765,18 @@ Reinitialize the face according to the `defface' specification."
|
|||
;; `defcustom' is now macroexpanded to
|
||||
;; `custom-declare-variable' with a quoted value arg.
|
||||
((and (eq (car form) 'custom-declare-variable)
|
||||
(default-boundp (eval (nth 1 form))))
|
||||
(default-boundp (eval (nth 1 form) lexical-binding)))
|
||||
;; Force variable to be bound.
|
||||
(set-default (eval (nth 1 form)) (eval (nth 1 (nth 2 form))))
|
||||
(set-default (eval (nth 1 form) lexical-binding)
|
||||
(eval (nth 1 (nth 2 form)) lexical-binding))
|
||||
form)
|
||||
;; `defface' is macroexpanded to `custom-declare-face'.
|
||||
((eq (car form) 'custom-declare-face)
|
||||
;; Reset the face.
|
||||
(setq face-new-frame-defaults
|
||||
(assq-delete-all (eval (nth 1 form)) face-new-frame-defaults))
|
||||
(put (eval (nth 1 form)) 'face-defface-spec nil)
|
||||
(assq-delete-all (eval (nth 1 form) lexical-binding)
|
||||
face-new-frame-defaults))
|
||||
(put (eval (nth 1 form) lexical-binding) 'face-defface-spec nil)
|
||||
;; Setting `customized-face' to the new spec after calling
|
||||
;; the form, but preserving the old saved spec in `saved-face',
|
||||
;; imitates the situation when the new face spec is set
|
||||
|
|
@ -792,10 +787,11 @@ Reinitialize the face according to the `defface' specification."
|
|||
;; `defface' change the spec, regardless of a saved spec.
|
||||
(prog1 `(prog1 ,form
|
||||
(put ,(nth 1 form) 'saved-face
|
||||
',(get (eval (nth 1 form)) 'saved-face))
|
||||
',(get (eval (nth 1 form) lexical-binding)
|
||||
'saved-face))
|
||||
(put ,(nth 1 form) 'customized-face
|
||||
,(nth 2 form)))
|
||||
(put (eval (nth 1 form)) 'saved-face nil)))
|
||||
(put (eval (nth 1 form) lexical-binding) 'saved-face nil)))
|
||||
((eq (car form) 'progn)
|
||||
(cons 'progn (mapcar 'eval-defun-1 (cdr form))))
|
||||
(t form)))
|
||||
|
|
|
|||
|
|
@ -372,7 +372,8 @@ simply inserts a newline."
|
|||
(*** *3))
|
||||
(kill-buffer (current-buffer))
|
||||
(set-buffer ielm-wbuf)
|
||||
(setq ielm-result (eval ielm-form))
|
||||
(setq ielm-result
|
||||
(eval ielm-form lexical-binding))
|
||||
(setq ielm-wbuf (current-buffer))
|
||||
(setq
|
||||
ielm-temp-buffer
|
||||
|
|
|
|||
|
|
@ -1212,12 +1212,12 @@ this command arranges for all errors to enter the debugger."
|
|||
current-prefix-arg))
|
||||
|
||||
(if (null eval-expression-debug-on-error)
|
||||
(setq values (cons (eval eval-expression-arg) values))
|
||||
(push (eval eval-expression-arg lexical-binding) values)
|
||||
(let ((old-value (make-symbol "t")) new-value)
|
||||
;; Bind debug-on-error to something unique so that we can
|
||||
;; detect when evaled code changes it.
|
||||
(let ((debug-on-error old-value))
|
||||
(setq values (cons (eval eval-expression-arg) values))
|
||||
(push (eval eval-expression-arg lexical-binding) values)
|
||||
(setq new-value debug-on-error))
|
||||
;; If evaled code has changed the value of debug-on-error,
|
||||
;; propagate that change to the global binding.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
2010-12-15 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* eval.c (Feval): Add `lexical' argument. Adjust callers.
|
||||
(Ffuncall, eval_sub): Avoid goto.
|
||||
|
||||
2010-12-14 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
Try and be more careful about propagation of lexical environment.
|
||||
|
|
|
|||
|
|
@ -915,7 +915,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
|
|||
Lisp_Object v1;
|
||||
BEFORE_POTENTIAL_GC ();
|
||||
v1 = POP;
|
||||
TOP = internal_catch (TOP, Feval, v1); /* FIXME: lexbind */
|
||||
TOP = internal_catch (TOP, eval_sub, v1); /* FIXME: lexbind */
|
||||
AFTER_POTENTIAL_GC ();
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ invoke it. If KEYS is omitted or nil, the return value of
|
|||
input = specs;
|
||||
/* Compute the arg values using the user's expression. */
|
||||
GCPRO2 (input, filter_specs);
|
||||
specs = Feval (specs); /* FIXME: lexbind */
|
||||
specs = Feval (specs, Qnil); /* FIXME: lexbind */
|
||||
UNGCPRO;
|
||||
if (i != num_input_events || !NILP (record_flag))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -490,7 +490,7 @@ aren't strings. */)
|
|||
}
|
||||
else if (!STRINGP (tem))
|
||||
/* Feval protects its argument. */
|
||||
tem = Feval (tem);
|
||||
tem = Feval (tem, Qnil);
|
||||
|
||||
if (NILP (raw) && STRINGP (tem))
|
||||
tem = Fsubstitute_command_keys (tem);
|
||||
|
|
|
|||
71
src/eval.c
71
src/eval.c
|
|
@ -2311,12 +2311,14 @@ do_autoload (Lisp_Object fundef, Lisp_Object funname)
|
|||
}
|
||||
|
||||
|
||||
DEFUN ("eval", Feval, Seval, 1, 1, 0,
|
||||
doc: /* Evaluate FORM and return its value. */)
|
||||
(Lisp_Object form)
|
||||
DEFUN ("eval", Feval, Seval, 1, 2, 0,
|
||||
doc: /* Evaluate FORM and return its value.
|
||||
If LEXICAL is t, evaluate using lexical scoping. */)
|
||||
(Lisp_Object form, Lisp_Object lexical)
|
||||
{
|
||||
int count = SPECPDL_INDEX ();
|
||||
specbind (Qinternal_interpreter_environment, Qnil);
|
||||
specbind (Qinternal_interpreter_environment,
|
||||
NILP (lexical) ? Qnil : Fcons (Qt, Qnil));
|
||||
return unbind_to (count, eval_sub (form));
|
||||
}
|
||||
|
||||
|
|
@ -2414,10 +2416,8 @@ eval_sub (Lisp_Object form)
|
|||
{
|
||||
backtrace.evalargs = 0;
|
||||
val = (XSUBR (fun)->function.aUNEVALLED) (args_left);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (XSUBR (fun)->max_args == MANY)
|
||||
else if (XSUBR (fun)->max_args == MANY)
|
||||
{
|
||||
/* Pass a vector of evaluated arguments */
|
||||
Lisp_Object *vals;
|
||||
|
|
@ -2443,9 +2443,9 @@ eval_sub (Lisp_Object form)
|
|||
val = (XSUBR (fun)->function.aMANY) (XINT (numargs), vals);
|
||||
UNGCPRO;
|
||||
SAFE_FREE ();
|
||||
goto done;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
GCPRO3 (args_left, fun, fun);
|
||||
gcpro3.var = argvals;
|
||||
gcpro3.nvars = 0;
|
||||
|
|
@ -2466,41 +2466,41 @@ eval_sub (Lisp_Object form)
|
|||
{
|
||||
case 0:
|
||||
val = (XSUBR (fun)->function.a0) ();
|
||||
goto done;
|
||||
break;
|
||||
case 1:
|
||||
val = (XSUBR (fun)->function.a1) (argvals[0]);
|
||||
goto done;
|
||||
break;
|
||||
case 2:
|
||||
val = (XSUBR (fun)->function.a2) (argvals[0], argvals[1]);
|
||||
goto done;
|
||||
break;
|
||||
case 3:
|
||||
val = (XSUBR (fun)->function.a3) (argvals[0], argvals[1],
|
||||
argvals[2]);
|
||||
goto done;
|
||||
break;
|
||||
case 4:
|
||||
val = (XSUBR (fun)->function.a4) (argvals[0], argvals[1],
|
||||
argvals[2], argvals[3]);
|
||||
goto done;
|
||||
break;
|
||||
case 5:
|
||||
val = (XSUBR (fun)->function.a5) (argvals[0], argvals[1], argvals[2],
|
||||
argvals[3], argvals[4]);
|
||||
goto done;
|
||||
break;
|
||||
case 6:
|
||||
val = (XSUBR (fun)->function.a6) (argvals[0], argvals[1], argvals[2],
|
||||
argvals[3], argvals[4], argvals[5]);
|
||||
goto done;
|
||||
break;
|
||||
case 7:
|
||||
val = (XSUBR (fun)->function.a7) (argvals[0], argvals[1], argvals[2],
|
||||
argvals[3], argvals[4], argvals[5],
|
||||
argvals[6]);
|
||||
goto done;
|
||||
|
||||
break;
|
||||
case 8:
|
||||
val = (XSUBR (fun)->function.a8) (argvals[0], argvals[1], argvals[2],
|
||||
argvals[3], argvals[4], argvals[5],
|
||||
argvals[6], argvals[7]);
|
||||
goto done;
|
||||
|
||||
break;
|
||||
default:
|
||||
/* Someone has created a subr that takes more arguments than
|
||||
is supported by this code. We need to either rewrite the
|
||||
|
|
@ -2509,7 +2509,8 @@ eval_sub (Lisp_Object form)
|
|||
abort ();
|
||||
}
|
||||
}
|
||||
if (FUNVECP (fun))
|
||||
}
|
||||
else if (FUNVECP (fun))
|
||||
val = apply_lambda (fun, original_args);
|
||||
else
|
||||
{
|
||||
|
|
@ -2533,7 +2534,6 @@ eval_sub (Lisp_Object form)
|
|||
else
|
||||
xsignal1 (Qinvalid_function, original_fun);
|
||||
}
|
||||
done:
|
||||
CHECK_CONS_LIST ();
|
||||
|
||||
lisp_eval_depth--;
|
||||
|
|
@ -3119,12 +3119,10 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
|
|||
if (XSUBR (fun)->max_args == UNEVALLED)
|
||||
xsignal1 (Qinvalid_function, original_fun);
|
||||
|
||||
if (XSUBR (fun)->max_args == MANY)
|
||||
{
|
||||
else if (XSUBR (fun)->max_args == MANY)
|
||||
val = (XSUBR (fun)->function.aMANY) (numargs, args + 1);
|
||||
goto done;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (XSUBR (fun)->max_args > numargs)
|
||||
{
|
||||
internal_args = (Lisp_Object *) alloca (XSUBR (fun)->max_args * sizeof (Lisp_Object));
|
||||
|
|
@ -3138,44 +3136,44 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
|
|||
{
|
||||
case 0:
|
||||
val = (XSUBR (fun)->function.a0) ();
|
||||
goto done;
|
||||
break;
|
||||
case 1:
|
||||
val = (XSUBR (fun)->function.a1) (internal_args[0]);
|
||||
goto done;
|
||||
break;
|
||||
case 2:
|
||||
val = (XSUBR (fun)->function.a2) (internal_args[0], internal_args[1]);
|
||||
goto done;
|
||||
break;
|
||||
case 3:
|
||||
val = (XSUBR (fun)->function.a3) (internal_args[0], internal_args[1],
|
||||
internal_args[2]);
|
||||
goto done;
|
||||
break;
|
||||
case 4:
|
||||
val = (XSUBR (fun)->function.a4) (internal_args[0], internal_args[1],
|
||||
internal_args[2], internal_args[3]);
|
||||
goto done;
|
||||
break;
|
||||
case 5:
|
||||
val = (XSUBR (fun)->function.a5) (internal_args[0], internal_args[1],
|
||||
internal_args[2], internal_args[3],
|
||||
internal_args[4]);
|
||||
goto done;
|
||||
break;
|
||||
case 6:
|
||||
val = (XSUBR (fun)->function.a6) (internal_args[0], internal_args[1],
|
||||
internal_args[2], internal_args[3],
|
||||
internal_args[4], internal_args[5]);
|
||||
goto done;
|
||||
break;
|
||||
case 7:
|
||||
val = (XSUBR (fun)->function.a7) (internal_args[0], internal_args[1],
|
||||
internal_args[2], internal_args[3],
|
||||
internal_args[4], internal_args[5],
|
||||
internal_args[6]);
|
||||
goto done;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
val = (XSUBR (fun)->function.a8) (internal_args[0], internal_args[1],
|
||||
internal_args[2], internal_args[3],
|
||||
internal_args[4], internal_args[5],
|
||||
internal_args[6], internal_args[7]);
|
||||
goto done;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
|
|
@ -3185,8 +3183,8 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
|
|||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
if (FUNVECP (fun))
|
||||
}
|
||||
else if (FUNVECP (fun))
|
||||
val = funcall_lambda (fun, numargs, args + 1);
|
||||
else
|
||||
{
|
||||
|
|
@ -3209,7 +3207,6 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
|
|||
else
|
||||
xsignal1 (Qinvalid_function, original_fun);
|
||||
}
|
||||
done:
|
||||
CHECK_CONS_LIST ();
|
||||
lisp_eval_depth--;
|
||||
if (backtrace.debug_on_exit)
|
||||
|
|
|
|||
|
|
@ -1327,7 +1327,7 @@ command_loop_2 (Lisp_Object ignore)
|
|||
Lisp_Object
|
||||
top_level_2 (void)
|
||||
{
|
||||
return Feval (Vtop_level);
|
||||
return Feval (Vtop_level, Qnil);
|
||||
}
|
||||
|
||||
Lisp_Object
|
||||
|
|
@ -3255,7 +3255,7 @@ read_char (int commandflag, int nmaps, Lisp_Object *maps, Lisp_Object prev_event
|
|||
help_form_saved_window_configs);
|
||||
record_unwind_protect (read_char_help_form_unwind, Qnil);
|
||||
|
||||
tem0 = Feval (Vhelp_form);
|
||||
tem0 = Feval (Vhelp_form, Qnil);
|
||||
if (STRINGP (tem0))
|
||||
internal_with_output_to_temp_buffer ("*Help*", print_help, tem0);
|
||||
|
||||
|
|
@ -7696,6 +7696,12 @@ menu_item_eval_property_1 (Lisp_Object arg)
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
eval_dyn (Lisp_Object form)
|
||||
{
|
||||
return Feval (form, Qnil);
|
||||
}
|
||||
|
||||
/* Evaluate an expression and return the result (or nil if something
|
||||
went wrong). Used to evaluate dynamic parts of menu items. */
|
||||
Lisp_Object
|
||||
|
|
@ -7704,7 +7710,7 @@ menu_item_eval_property (Lisp_Object sexpr)
|
|||
int count = SPECPDL_INDEX ();
|
||||
Lisp_Object val;
|
||||
specbind (Qinhibit_redisplay, Qt);
|
||||
val = internal_condition_case_1 (Feval, sexpr, Qerror,
|
||||
val = internal_condition_case_1 (eval_dyn, sexpr, Qerror,
|
||||
menu_item_eval_property_1);
|
||||
return unbind_to (count, val);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2971,7 +2971,7 @@ extern void xsignal3 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object) NO_RET
|
|||
extern void signal_error (const char *, Lisp_Object) NO_RETURN;
|
||||
EXFUN (Fautoload, 5);
|
||||
EXFUN (Fcommandp, 2);
|
||||
EXFUN (Feval, 1);
|
||||
EXFUN (Feval, 2);
|
||||
extern Lisp_Object eval_sub (Lisp_Object form);
|
||||
EXFUN (Fapply, MANY);
|
||||
EXFUN (Ffuncall, MANY);
|
||||
|
|
|
|||
|
|
@ -1026,10 +1026,10 @@ is a string to insert in the minibuffer before reading.
|
|||
Such arguments are used as in `read-from-minibuffer'.) */)
|
||||
(Lisp_Object prompt, Lisp_Object initial_contents)
|
||||
{
|
||||
/* FIXME: lexbind. */
|
||||
return Feval (read_minibuf (Vread_expression_map, initial_contents,
|
||||
prompt, Qnil, 1, Qread_expression_history,
|
||||
make_number (0), Qnil, 0, 0));
|
||||
make_number (0), Qnil, 0, 0),
|
||||
Qnil);
|
||||
}
|
||||
|
||||
/* Functions that use the minibuffer to read various things. */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue