diff options
| author | Tom Tromey | 2013-08-19 21:53:07 -0600 |
|---|---|---|
| committer | Tom Tromey | 2013-08-19 21:53:07 -0600 |
| commit | 6d75555c5cc3d2a629646cee7629e67530fa7a36 (patch) | |
| tree | 3852804dd234ad613ea8691332e10b92c027e87d /src/eval.c | |
| parent | cc231cbe45d27a1906d268fb72d3b4105a2e9c65 (diff) | |
| parent | 8c2f38aaab7a7a2f0605416fc2ee38701e41ab61 (diff) | |
| download | emacs-6d75555c5cc3d2a629646cee7629e67530fa7a36.tar.gz emacs-6d75555c5cc3d2a629646cee7629e67530fa7a36.zip | |
merge from trunk
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 163 |
1 files changed, 104 insertions, 59 deletions
diff --git a/src/eval.c b/src/eval.c index e93c3473ae8..d36defc8fe4 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -678,6 +678,51 @@ The return value is BASE-VARIABLE. */) | |||
| 678 | return base_variable; | 678 | return base_variable; |
| 679 | } | 679 | } |
| 680 | 680 | ||
| 681 | static union specbinding * | ||
| 682 | default_toplevel_binding (Lisp_Object symbol) | ||
| 683 | { | ||
| 684 | union specbinding *binding = NULL; | ||
| 685 | union specbinding *pdl = specpdl_ptr; | ||
| 686 | while (pdl > specpdl) | ||
| 687 | { | ||
| 688 | switch ((--pdl)->kind) | ||
| 689 | { | ||
| 690 | case SPECPDL_LET_DEFAULT: | ||
| 691 | case SPECPDL_LET: | ||
| 692 | if (EQ (specpdl_symbol (pdl), symbol)) | ||
| 693 | binding = pdl; | ||
| 694 | break; | ||
| 695 | } | ||
| 696 | } | ||
| 697 | return binding; | ||
| 698 | } | ||
| 699 | |||
| 700 | DEFUN ("default-toplevel-value", Fdefault_toplevel_value, Sdefault_toplevel_value, 1, 1, 0, | ||
| 701 | doc: /* Return SYMBOL's toplevel default value. | ||
| 702 | "Toplevel" means outside of any let binding. */) | ||
| 703 | (Lisp_Object symbol) | ||
| 704 | { | ||
| 705 | union specbinding *binding = default_toplevel_binding (symbol); | ||
| 706 | Lisp_Object value | ||
| 707 | = binding ? specpdl_old_value (binding) : Fdefault_value (symbol); | ||
| 708 | if (!EQ (value, Qunbound)) | ||
| 709 | return value; | ||
| 710 | xsignal1 (Qvoid_variable, symbol); | ||
| 711 | } | ||
| 712 | |||
| 713 | DEFUN ("set-default-toplevel-value", Fset_default_toplevel_value, | ||
| 714 | Sset_default_toplevel_value, 2, 2, 0, | ||
| 715 | doc: /* Set SYMBOL's toplevel default value to VALUE. | ||
| 716 | "Toplevel" means outside of any let binding. */) | ||
| 717 | (Lisp_Object symbol, Lisp_Object value) | ||
| 718 | { | ||
| 719 | union specbinding *binding = default_toplevel_binding (symbol); | ||
| 720 | if (binding) | ||
| 721 | set_specpdl_old_value (binding, value); | ||
| 722 | else | ||
| 723 | Fset_default (symbol, value); | ||
| 724 | return Qnil; | ||
| 725 | } | ||
| 681 | 726 | ||
| 682 | DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0, | 727 | DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0, |
| 683 | doc: /* Define SYMBOL as a variable, and return SYMBOL. | 728 | doc: /* Define SYMBOL as a variable, and return SYMBOL. |
| @@ -726,18 +771,10 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */) | |||
| 726 | else | 771 | else |
| 727 | { /* Check if there is really a global binding rather than just a let | 772 | { /* Check if there is really a global binding rather than just a let |
| 728 | binding that shadows the global unboundness of the var. */ | 773 | binding that shadows the global unboundness of the var. */ |
| 729 | union specbinding *pdl = specpdl_ptr; | 774 | union specbinding *binding = default_toplevel_binding (sym); |
| 730 | while (pdl > specpdl) | 775 | if (binding && EQ (specpdl_old_value (binding), Qunbound)) |
| 731 | { | 776 | { |
| 732 | if ((--pdl)->kind >= SPECPDL_LET | 777 | set_specpdl_old_value (binding, eval_sub (XCAR (tail))); |
| 733 | && EQ (specpdl_symbol (pdl), sym) | ||
| 734 | && EQ (specpdl_old_value (pdl), Qunbound)) | ||
| 735 | { | ||
| 736 | message_with_string | ||
| 737 | ("Warning: defvar ignored because %s is let-bound", | ||
| 738 | SYMBOL_NAME (sym), 1); | ||
| 739 | break; | ||
| 740 | } | ||
| 741 | } | 778 | } |
| 742 | } | 779 | } |
| 743 | tail = XCDR (tail); | 780 | tail = XCDR (tail); |
| @@ -3325,53 +3362,50 @@ do_one_unbind (union specbinding *this_binding, int unwinding) | |||
| 3325 | switch (this_binding->kind) | 3362 | switch (this_binding->kind) |
| 3326 | { | 3363 | { |
| 3327 | case SPECPDL_UNWIND: | 3364 | case SPECPDL_UNWIND: |
| 3328 | specpdl_ptr->unwind.func (specpdl_ptr->unwind.arg); | 3365 | this_binding->unwind.func (this_binding->unwind.arg); |
| 3329 | break; | 3366 | break; |
| 3330 | case SPECPDL_UNWIND_PTR: | 3367 | case SPECPDL_UNWIND_PTR: |
| 3331 | specpdl_ptr->unwind_ptr.func (specpdl_ptr->unwind_ptr.arg); | 3368 | this_binding->unwind_ptr.func (this_binding->unwind_ptr.arg); |
| 3332 | break; | 3369 | break; |
| 3333 | case SPECPDL_UNWIND_INT: | 3370 | case SPECPDL_UNWIND_INT: |
| 3334 | specpdl_ptr->unwind_int.func (specpdl_ptr->unwind_int.arg); | 3371 | this_binding->unwind_int.func (this_binding->unwind_int.arg); |
| 3335 | break; | 3372 | break; |
| 3336 | case SPECPDL_UNWIND_VOID: | 3373 | case SPECPDL_UNWIND_VOID: |
| 3337 | specpdl_ptr->unwind_void.func (); | 3374 | this_binding->unwind_void.func (); |
| 3338 | break; | 3375 | break; |
| 3339 | case SPECPDL_BACKTRACE: | 3376 | case SPECPDL_BACKTRACE: |
| 3340 | break; | 3377 | break; |
| 3341 | case SPECPDL_LET: | 3378 | case SPECPDL_LET: |
| 3342 | /* If variable has a trivial value (no forwarding), we can | 3379 | { /* If variable has a trivial value (no forwarding), we can |
| 3343 | just set it. No need to check for constant symbols here, | 3380 | just set it. No need to check for constant symbols here, |
| 3344 | since that was already done by specbind. */ | 3381 | since that was already done by specbind. */ |
| 3345 | if (XSYMBOL (specpdl_symbol (this_binding))->redirect | 3382 | struct Lisp_Symbol *sym = XSYMBOL (specpdl_symbol (this_binding)); |
| 3346 | == SYMBOL_PLAINVAL) | 3383 | if (sym->redirect == SYMBOL_PLAINVAL) |
| 3347 | SET_SYMBOL_VAL (XSYMBOL (specpdl_symbol (this_binding)), | 3384 | { |
| 3348 | specpdl_old_value (this_binding)); | 3385 | SET_SYMBOL_VAL (sym, specpdl_old_value (this_binding)); |
| 3349 | else | 3386 | break; |
| 3350 | /* NOTE: we only ever come here if make_local_foo was used for | 3387 | } |
| 3351 | the first time on this var within this let. */ | 3388 | else |
| 3352 | Fset_default (specpdl_symbol (this_binding), | 3389 | { /* FALLTHROUGH!! |
| 3353 | specpdl_old_value (this_binding)); | 3390 | NOTE: we only ever come here if make_local_foo was used for |
| 3391 | the first time on this var within this let. */ | ||
| 3392 | } | ||
| 3393 | } | ||
| 3394 | case SPECPDL_LET_DEFAULT: | ||
| 3395 | Fset_default (specpdl_symbol (this_binding), | ||
| 3396 | specpdl_old_value (this_binding)); | ||
| 3354 | break; | 3397 | break; |
| 3355 | case SPECPDL_LET_LOCAL: | 3398 | case SPECPDL_LET_LOCAL: |
| 3356 | case SPECPDL_LET_DEFAULT: | 3399 | { |
| 3357 | { /* If the symbol is a list, it is really (SYMBOL WHERE | ||
| 3358 | . CURRENT-BUFFER) where WHERE is either nil, a buffer, or a | ||
| 3359 | frame. If WHERE is a buffer or frame, this indicates we | ||
| 3360 | bound a variable that had a buffer-local or frame-local | ||
| 3361 | binding. WHERE nil means that the variable had the default | ||
| 3362 | value when it was bound. CURRENT-BUFFER is the buffer that | ||
| 3363 | was current when the variable was bound. */ | ||
| 3364 | Lisp_Object symbol = specpdl_symbol (this_binding); | 3400 | Lisp_Object symbol = specpdl_symbol (this_binding); |
| 3365 | Lisp_Object where = specpdl_where (this_binding); | 3401 | Lisp_Object where = specpdl_where (this_binding); |
| 3402 | Lisp_Object old_value = specpdl_old_value (this_binding); | ||
| 3366 | eassert (BUFFERP (where)); | 3403 | eassert (BUFFERP (where)); |
| 3367 | 3404 | ||
| 3368 | if (this_binding->kind == SPECPDL_LET_DEFAULT) | ||
| 3369 | Fset_default (symbol, specpdl_old_value (this_binding)); | ||
| 3370 | /* If this was a local binding, reset the value in the appropriate | 3405 | /* If this was a local binding, reset the value in the appropriate |
| 3371 | buffer, but only if that buffer's binding still exists. */ | 3406 | buffer, but only if that buffer's binding still exists. */ |
| 3372 | else if (!NILP (Flocal_variable_p (symbol, where))) | 3407 | if (!NILP (Flocal_variable_p (symbol, where))) |
| 3373 | set_internal (symbol, specpdl_old_value (this_binding), | 3408 | set_internal (symbol, old_value, where, 1); |
| 3374 | where, 1); | ||
| 3375 | } | 3409 | } |
| 3376 | break; | 3410 | break; |
| 3377 | } | 3411 | } |
| @@ -3406,6 +3440,16 @@ clear_unwind_protect (ptrdiff_t count) | |||
| 3406 | previous value without invoking it. */ | 3440 | previous value without invoking it. */ |
| 3407 | 3441 | ||
| 3408 | void | 3442 | void |
| 3443 | set_unwind_protect (ptrdiff_t count, void (*func) (Lisp_Object), | ||
| 3444 | Lisp_Object arg) | ||
| 3445 | { | ||
| 3446 | union specbinding *p = specpdl + count; | ||
| 3447 | p->unwind.kind = SPECPDL_UNWIND; | ||
| 3448 | p->unwind.func = func; | ||
| 3449 | p->unwind.arg = arg; | ||
| 3450 | } | ||
| 3451 | |||
| 3452 | void | ||
| 3409 | set_unwind_protect_ptr (ptrdiff_t count, void (*func) (void *), void *arg) | 3453 | set_unwind_protect_ptr (ptrdiff_t count, void (*func) (void *), void *arg) |
| 3410 | { | 3454 | { |
| 3411 | union specbinding *p = specpdl + count; | 3455 | union specbinding *p = specpdl + count; |
| @@ -3592,7 +3636,7 @@ nearest activation frame. */) | |||
| 3592 | directly in the pre-existing specpdl elements (i.e. we swap the current | 3636 | directly in the pre-existing specpdl elements (i.e. we swap the current |
| 3593 | value and the old value stored in the specpdl), kind of like the inplace | 3637 | value and the old value stored in the specpdl), kind of like the inplace |
| 3594 | pointer-reversal trick. As it turns out, the rewind does the same as the | 3638 | pointer-reversal trick. As it turns out, the rewind does the same as the |
| 3595 | unwind, except it starts from the other end of the spepdl stack, so we use | 3639 | unwind, except it starts from the other end of the specpdl stack, so we use |
| 3596 | the same function for both unwind and rewind. */ | 3640 | the same function for both unwind and rewind. */ |
| 3597 | static void | 3641 | static void |
| 3598 | backtrace_eval_unrewind (int distance) | 3642 | backtrace_eval_unrewind (int distance) |
| @@ -3622,24 +3666,23 @@ backtrace_eval_unrewind (int distance) | |||
| 3622 | case SPECPDL_BACKTRACE: | 3666 | case SPECPDL_BACKTRACE: |
| 3623 | break; | 3667 | break; |
| 3624 | case SPECPDL_LET: | 3668 | case SPECPDL_LET: |
| 3625 | /* If variable has a trivial value (no forwarding), we can | 3669 | { /* If variable has a trivial value (no forwarding), we can |
| 3626 | just set it. No need to check for constant symbols here, | 3670 | just set it. No need to check for constant symbols here, |
| 3627 | since that was already done by specbind. */ | 3671 | since that was already done by specbind. */ |
| 3628 | if (XSYMBOL (specpdl_symbol (tmp))->redirect | 3672 | struct Lisp_Symbol *sym = XSYMBOL (specpdl_symbol (tmp)); |
| 3629 | == SYMBOL_PLAINVAL) | 3673 | if (sym->redirect == SYMBOL_PLAINVAL) |
| 3630 | { | 3674 | { |
| 3631 | struct Lisp_Symbol *sym = XSYMBOL (specpdl_symbol (tmp)); | 3675 | Lisp_Object old_value = specpdl_old_value (tmp); |
| 3632 | Lisp_Object old_value = specpdl_old_value (tmp); | 3676 | set_specpdl_old_value (tmp, SYMBOL_VAL (sym)); |
| 3633 | set_specpdl_old_value (tmp, SYMBOL_VAL (sym)); | 3677 | SET_SYMBOL_VAL (sym, old_value); |
| 3634 | SET_SYMBOL_VAL (sym, old_value); | 3678 | break; |
| 3635 | break; | 3679 | } |
| 3636 | } | 3680 | else |
| 3637 | else | 3681 | { /* FALLTHROUGH!! |
| 3638 | { | 3682 | NOTE: we only ever come here if make_local_foo was used for |
| 3639 | /* FALLTHROUGH! | 3683 | the first time on this var within this let. */ |
| 3640 | NOTE: we only ever come here if make_local_foo was used for | 3684 | } |
| 3641 | the first time on this var within this let. */ | 3685 | } |
| 3642 | } | ||
| 3643 | case SPECPDL_LET_DEFAULT: | 3686 | case SPECPDL_LET_DEFAULT: |
| 3644 | { | 3687 | { |
| 3645 | Lisp_Object sym = specpdl_symbol (tmp); | 3688 | Lisp_Object sym = specpdl_symbol (tmp); |
| @@ -3908,6 +3951,8 @@ alist of active lexical bindings. */); | |||
| 3908 | defsubr (&Ssetq); | 3951 | defsubr (&Ssetq); |
| 3909 | defsubr (&Squote); | 3952 | defsubr (&Squote); |
| 3910 | defsubr (&Sfunction); | 3953 | defsubr (&Sfunction); |
| 3954 | defsubr (&Sdefault_toplevel_value); | ||
| 3955 | defsubr (&Sset_default_toplevel_value); | ||
| 3911 | defsubr (&Sdefvar); | 3956 | defsubr (&Sdefvar); |
| 3912 | defsubr (&Sdefvaralias); | 3957 | defsubr (&Sdefvaralias); |
| 3913 | defsubr (&Sdefconst); | 3958 | defsubr (&Sdefconst); |