diff options
| author | Stefan Monnier | 2013-08-02 17:16:33 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2013-08-02 17:16:33 -0400 |
| commit | a104f656c8217b027866d32e8d7bf024a671e3cc (patch) | |
| tree | b62ddfb915099ba3398b2f0b1f9ddc0ed6203102 /src/eval.c | |
| parent | 185e3b5a2f3dc2b5163eb1fe97499c6af1edaa9c (diff) | |
| download | emacs-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.c | 124 |
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 | ||
| 661 | static union specbinding * | ||
| 662 | default_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 | |||
| 680 | DEFUN ("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 | |||
| 693 | DEFUN ("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 | ||
| 662 | DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0, | 707 | DEFUN ("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); |