aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
authorStefan Monnier2013-08-02 17:16:33 -0400
committerStefan Monnier2013-08-02 17:16:33 -0400
commita104f656c8217b027866d32e8d7bf024a671e3cc (patch)
treeb62ddfb915099ba3398b2f0b1f9ddc0ed6203102 /src/eval.c
parent185e3b5a2f3dc2b5163eb1fe97499c6af1edaa9c (diff)
downloademacs-a104f656c8217b027866d32e8d7bf024a671e3cc.tar.gz
emacs-a104f656c8217b027866d32e8d7bf024a671e3cc.zip
Make defvar affect the default binding outside of any let.
* src/eval.c (default_toplevel_binding): New function. (Fdefvar): Use it. (unbind_to, backtrace_eval_unrewind): Do a bit of CSE simplification. (Fdefault_toplevel_value, Fset_default_toplevel_value): New subrs. (syms_of_eval): Export them. * src/data.c (Fdefault_value): Micro cleanup. * src/term.c (init_tty): Use "false". * lisp/custom.el (custom-initialize-default, custom-initialize-set) (custom-initialize-reset, custom-initialize-changed): Affect the toplevel-default-value (bug#6275, bug#14586). * lisp/emacs-lisp/advice.el (ad-compile-function): Undo previous workaround for bug#6275. * test/automated/core-elisp-tests.el: New file.
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c124
1 files changed, 82 insertions, 42 deletions
diff --git a/src/eval.c b/src/eval.c
index cb716690e3c..8ee259110f4 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -658,6 +658,51 @@ The return value is BASE-VARIABLE. */)
658 return base_variable; 658 return base_variable;
659} 659}
660 660
661static union specbinding *
662default_toplevel_binding (Lisp_Object symbol)
663{
664 union specbinding *binding = NULL;
665 union specbinding *pdl = specpdl_ptr;
666 while (pdl > specpdl)
667 {
668 switch ((--pdl)->kind)
669 {
670 case SPECPDL_LET_DEFAULT:
671 case SPECPDL_LET:
672 if (EQ (specpdl_symbol (pdl), symbol))
673 binding = pdl;
674 break;
675 }
676 }
677 return binding;
678}
679
680DEFUN ("default-toplevel-value", Fdefault_toplevel_value, Sdefault_toplevel_value, 1, 1, 0,
681 doc: /* Return SYMBOL's toplevel default value.
682"Toplevel" means outside of any let binding. */)
683 (Lisp_Object symbol)
684{
685 union specbinding *binding = default_toplevel_binding (symbol);
686 Lisp_Object value
687 = binding ? specpdl_old_value (binding) : Fdefault_value (symbol);
688 if (!EQ (value, Qunbound))
689 return value;
690 xsignal1 (Qvoid_variable, symbol);
691}
692
693DEFUN ("set-default-toplevel-value", Fset_default_toplevel_value,
694 Sset_default_toplevel_value, 2, 2, 0,
695 doc: /* Set SYMBOL's toplevel default value to VALUE.
696"Toplevel" means outside of any let binding. */)
697 (Lisp_Object symbol, Lisp_Object value)
698{
699 union specbinding *binding = default_toplevel_binding (symbol);
700 if (binding)
701 set_specpdl_old_value (binding, value);
702 else
703 Fset_default (symbol, value);
704 return Qnil;
705}
661 706
662DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0, 707DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0,
663 doc: /* Define SYMBOL as a variable, and return SYMBOL. 708 doc: /* Define SYMBOL as a variable, and return SYMBOL.
@@ -706,18 +751,10 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */)
706 else 751 else
707 { /* Check if there is really a global binding rather than just a let 752 { /* Check if there is really a global binding rather than just a let
708 binding that shadows the global unboundness of the var. */ 753 binding that shadows the global unboundness of the var. */
709 union specbinding *pdl = specpdl_ptr; 754 union specbinding *binding = default_toplevel_binding (sym);
710 while (pdl > specpdl) 755 if (binding && EQ (specpdl_old_value (binding), Qunbound))
711 { 756 {
712 if ((--pdl)->kind >= SPECPDL_LET 757 set_specpdl_old_value (binding, eval_sub (XCAR (tail)));
713 && EQ (specpdl_symbol (pdl), sym)
714 && EQ (specpdl_old_value (pdl), Qunbound))
715 {
716 message_with_string
717 ("Warning: defvar ignored because %s is let-bound",
718 SYMBOL_NAME (sym), 1);
719 break;
720 }
721 } 758 }
722 } 759 }
723 tail = XCDR (tail); 760 tail = XCDR (tail);
@@ -3311,19 +3348,21 @@ unbind_to (ptrdiff_t count, Lisp_Object value)
3311 case SPECPDL_BACKTRACE: 3348 case SPECPDL_BACKTRACE:
3312 break; 3349 break;
3313 case SPECPDL_LET: 3350 case SPECPDL_LET:
3314 /* If variable has a trivial value (no forwarding), we can 3351 { /* If variable has a trivial value (no forwarding), we can
3315 just set it. No need to check for constant symbols here, 3352 just set it. No need to check for constant symbols here,
3316 since that was already done by specbind. */ 3353 since that was already done by specbind. */
3317 if (XSYMBOL (specpdl_symbol (specpdl_ptr))->redirect 3354 struct Lisp_Symbol *sym = XSYMBOL (specpdl_symbol (specpdl_ptr));
3318 == SYMBOL_PLAINVAL) 3355 if (sym->redirect == SYMBOL_PLAINVAL)
3319 SET_SYMBOL_VAL (XSYMBOL (specpdl_symbol (specpdl_ptr)), 3356 {
3320 specpdl_old_value (specpdl_ptr)); 3357 SET_SYMBOL_VAL (sym, specpdl_old_value (specpdl_ptr));
3321 else 3358 break;
3322 /* NOTE: we only ever come here if make_local_foo was used for 3359 }
3323 the first time on this var within this let. */ 3360 else
3324 Fset_default (specpdl_symbol (specpdl_ptr), 3361 { /* FALLTHROUGH!!
3325 specpdl_old_value (specpdl_ptr)); 3362 NOTE: we only ever come here if make_local_foo was used for
3326 break; 3363 the first time on this var within this let. */
3364 }
3365 }
3327 case SPECPDL_LET_DEFAULT: 3366 case SPECPDL_LET_DEFAULT:
3328 Fset_default (specpdl_symbol (specpdl_ptr), 3367 Fset_default (specpdl_symbol (specpdl_ptr),
3329 specpdl_old_value (specpdl_ptr)); 3368 specpdl_old_value (specpdl_ptr));
@@ -3511,24 +3550,23 @@ backtrace_eval_unrewind (int distance)
3511 case SPECPDL_BACKTRACE: 3550 case SPECPDL_BACKTRACE:
3512 break; 3551 break;
3513 case SPECPDL_LET: 3552 case SPECPDL_LET:
3514 /* If variable has a trivial value (no forwarding), we can 3553 { /* If variable has a trivial value (no forwarding), we can
3515 just set it. No need to check for constant symbols here, 3554 just set it. No need to check for constant symbols here,
3516 since that was already done by specbind. */ 3555 since that was already done by specbind. */
3517 if (XSYMBOL (specpdl_symbol (tmp))->redirect 3556 struct Lisp_Symbol *sym = XSYMBOL (specpdl_symbol (tmp));
3518 == SYMBOL_PLAINVAL) 3557 if (sym->redirect == SYMBOL_PLAINVAL)
3519 { 3558 {
3520 struct Lisp_Symbol *sym = XSYMBOL (specpdl_symbol (tmp)); 3559 Lisp_Object old_value = specpdl_old_value (tmp);
3521 Lisp_Object old_value = specpdl_old_value (tmp); 3560 set_specpdl_old_value (tmp, SYMBOL_VAL (sym));
3522 set_specpdl_old_value (tmp, SYMBOL_VAL (sym)); 3561 SET_SYMBOL_VAL (sym, old_value);
3523 SET_SYMBOL_VAL (sym, old_value); 3562 break;
3524 break; 3563 }
3525 } 3564 else
3526 else 3565 { /* FALLTHROUGH!!
3527 { 3566 NOTE: we only ever come here if make_local_foo was used for
3528 /* FALLTHROUGH! 3567 the first time on this var within this let. */
3529 NOTE: we only ever come here if make_local_foo was used for 3568 }
3530 the first time on this var within this let. */ 3569 }
3531 }
3532 case SPECPDL_LET_DEFAULT: 3570 case SPECPDL_LET_DEFAULT:
3533 { 3571 {
3534 Lisp_Object sym = specpdl_symbol (tmp); 3572 Lisp_Object sym = specpdl_symbol (tmp);
@@ -3796,6 +3834,8 @@ alist of active lexical bindings. */);
3796 defsubr (&Ssetq); 3834 defsubr (&Ssetq);
3797 defsubr (&Squote); 3835 defsubr (&Squote);
3798 defsubr (&Sfunction); 3836 defsubr (&Sfunction);
3837 defsubr (&Sdefault_toplevel_value);
3838 defsubr (&Sset_default_toplevel_value);
3799 defsubr (&Sdefvar); 3839 defsubr (&Sdefvar);
3800 defsubr (&Sdefvaralias); 3840 defsubr (&Sdefvaralias);
3801 defsubr (&Sdefconst); 3841 defsubr (&Sdefconst);