aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
authorNoam Postavsky2015-11-19 19:50:06 -0500
committerNoam Postavsky2016-12-02 20:25:14 -0500
commit227213164e06363f0a4fb2beeeb647c99749299e (patch)
tree8fda48112af0631ce9b6c595e33101a9b5961909 /src/eval.c
parent0fc4761ca88175c30da7209c9ab1cde788b66a76 (diff)
downloademacs-227213164e06363f0a4fb2beeeb647c99749299e.tar.gz
emacs-227213164e06363f0a4fb2beeeb647c99749299e.zip
Add lisp watchpoints
This allows calling a function whenever a symbol-value is changed. * src/lisp.h (lisp_h_SYMBOL_TRAPPED_WRITE_P): (SYMBOL_TRAPPED_WRITE_P): New function/macro. (lisp_h_SYMBOL_CONSTANT_P): Check for SYMBOL_NOWRITE specifically. (enum symbol_trapped_write): New enumeration. (struct Lisp_Symbol): Rename field constant to trapped_write. (make_symbol_constant): New function. * src/data.c (Fadd_variable_watcher, Fremove_variable_watcher): (set_symbol_trapped_write, restore_symbol_trapped_write): (harmonize_variable_watchers, notify_variable_watchers): New functions. * src/data.c (Fset_default): Call `notify_variable_watchers' for trapped symbols. (set_internal): Change bool argument BIND to 3-value enum and call `notify_variable_watchers' for trapped symbols. * src/data.c (syms_of_data): * src/data.c (syms_of_data): * src/font.c (syms_of_font): * src/lread.c (intern_sym, init_obarray): * src/buffer.c (syms_of_buffer): Use make_symbol_constant. * src/alloc.c (init_symbol): * src/bytecode.c (exec_byte_code): Use SYMBOL_TRAPPED_WRITE_P. * src/data.c (Fmake_variable_buffer_local, Fmake_local_variable): (Fmake_variable_frame_local): * src/eval.c (Fdefvaralias, specbind): Refer to Lisp_Symbol's trapped_write instead of constant. (Ffuncall): Move subr calling code into separate function. (funcall_subr): New function.
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c206
1 files changed, 107 insertions, 99 deletions
diff --git a/src/eval.c b/src/eval.c
index bbc1518be54..724f0018a58 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -593,12 +593,12 @@ The return value is BASE-VARIABLE. */)
593 CHECK_SYMBOL (new_alias); 593 CHECK_SYMBOL (new_alias);
594 CHECK_SYMBOL (base_variable); 594 CHECK_SYMBOL (base_variable);
595 595
596 sym = XSYMBOL (new_alias); 596 if (SYMBOL_CONSTANT_P (new_alias))
597 597 /* Making it an alias effectively changes its value. */
598 if (sym->constant)
599 /* Not sure why, but why not? */
600 error ("Cannot make a constant an alias"); 598 error ("Cannot make a constant an alias");
601 599
600 sym = XSYMBOL (new_alias);
601
602 switch (sym->redirect) 602 switch (sym->redirect)
603 { 603 {
604 case SYMBOL_FORWARDED: 604 case SYMBOL_FORWARDED:
@@ -617,8 +617,8 @@ The return value is BASE-VARIABLE. */)
617 so that old-code that affects n_a before the aliasing is setup 617 so that old-code that affects n_a before the aliasing is setup
618 still works. */ 618 still works. */
619 if (NILP (Fboundp (base_variable))) 619 if (NILP (Fboundp (base_variable)))
620 set_internal (base_variable, find_symbol_value (new_alias), Qnil, 1); 620 set_internal (base_variable, find_symbol_value (new_alias),
621 621 Qnil, SET_INTERNAL_BIND);
622 { 622 {
623 union specbinding *p; 623 union specbinding *p;
624 624
@@ -628,11 +628,14 @@ The return value is BASE-VARIABLE. */)
628 error ("Don't know how to make a let-bound variable an alias"); 628 error ("Don't know how to make a let-bound variable an alias");
629 } 629 }
630 630
631 if (sym->trapped_write == SYMBOL_TRAPPED_WRITE)
632 notify_variable_watchers (new_alias, base_variable, Qdefvaralias, Qnil);
633
631 sym->declared_special = 1; 634 sym->declared_special = 1;
632 XSYMBOL (base_variable)->declared_special = 1; 635 XSYMBOL (base_variable)->declared_special = 1;
633 sym->redirect = SYMBOL_VARALIAS; 636 sym->redirect = SYMBOL_VARALIAS;
634 SET_SYMBOL_ALIAS (sym, XSYMBOL (base_variable)); 637 SET_SYMBOL_ALIAS (sym, XSYMBOL (base_variable));
635 sym->constant = SYMBOL_CONSTANT_P (base_variable); 638 sym->trapped_write = XSYMBOL (base_variable)->trapped_write;
636 LOADHIST_ATTACH (new_alias); 639 LOADHIST_ATTACH (new_alias);
637 /* Even if docstring is nil: remove old docstring. */ 640 /* Even if docstring is nil: remove old docstring. */
638 Fput (new_alias, Qvariable_documentation, docstring); 641 Fput (new_alias, Qvariable_documentation, docstring);
@@ -2645,9 +2648,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
2645 Lisp_Object fun, original_fun; 2648 Lisp_Object fun, original_fun;
2646 Lisp_Object funcar; 2649 Lisp_Object funcar;
2647 ptrdiff_t numargs = nargs - 1; 2650 ptrdiff_t numargs = nargs - 1;
2648 Lisp_Object lisp_numargs;
2649 Lisp_Object val; 2651 Lisp_Object val;
2650 Lisp_Object *internal_args;
2651 ptrdiff_t count; 2652 ptrdiff_t count;
2652 2653
2653 QUIT; 2654 QUIT;
@@ -2680,86 +2681,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
2680 fun = indirect_function (fun); 2681 fun = indirect_function (fun);
2681 2682
2682 if (SUBRP (fun)) 2683 if (SUBRP (fun))
2683 { 2684 val = funcall_subr (XSUBR (fun), numargs, args + 1);
2684 if (numargs < XSUBR (fun)->min_args
2685 || (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < numargs))
2686 {
2687 XSETFASTINT (lisp_numargs, numargs);
2688 xsignal2 (Qwrong_number_of_arguments, original_fun, lisp_numargs);
2689 }
2690
2691 else if (XSUBR (fun)->max_args == UNEVALLED)
2692 xsignal1 (Qinvalid_function, original_fun);
2693
2694 else if (XSUBR (fun)->max_args == MANY)
2695 val = (XSUBR (fun)->function.aMANY) (numargs, args + 1);
2696 else
2697 {
2698 Lisp_Object internal_argbuf[8];
2699 if (XSUBR (fun)->max_args > numargs)
2700 {
2701 eassert (XSUBR (fun)->max_args <= ARRAYELTS (internal_argbuf));
2702 internal_args = internal_argbuf;
2703 memcpy (internal_args, args + 1, numargs * word_size);
2704 memclear (internal_args + numargs,
2705 (XSUBR (fun)->max_args - numargs) * word_size);
2706 }
2707 else
2708 internal_args = args + 1;
2709 switch (XSUBR (fun)->max_args)
2710 {
2711 case 0:
2712 val = (XSUBR (fun)->function.a0 ());
2713 break;
2714 case 1:
2715 val = (XSUBR (fun)->function.a1 (internal_args[0]));
2716 break;
2717 case 2:
2718 val = (XSUBR (fun)->function.a2
2719 (internal_args[0], internal_args[1]));
2720 break;
2721 case 3:
2722 val = (XSUBR (fun)->function.a3
2723 (internal_args[0], internal_args[1], internal_args[2]));
2724 break;
2725 case 4:
2726 val = (XSUBR (fun)->function.a4
2727 (internal_args[0], internal_args[1], internal_args[2],
2728 internal_args[3]));
2729 break;
2730 case 5:
2731 val = (XSUBR (fun)->function.a5
2732 (internal_args[0], internal_args[1], internal_args[2],
2733 internal_args[3], internal_args[4]));
2734 break;
2735 case 6:
2736 val = (XSUBR (fun)->function.a6
2737 (internal_args[0], internal_args[1], internal_args[2],
2738 internal_args[3], internal_args[4], internal_args[5]));
2739 break;
2740 case 7:
2741 val = (XSUBR (fun)->function.a7
2742 (internal_args[0], internal_args[1], internal_args[2],
2743 internal_args[3], internal_args[4], internal_args[5],
2744 internal_args[6]));
2745 break;
2746
2747 case 8:
2748 val = (XSUBR (fun)->function.a8
2749 (internal_args[0], internal_args[1], internal_args[2],
2750 internal_args[3], internal_args[4], internal_args[5],
2751 internal_args[6], internal_args[7]));
2752 break;
2753
2754 default:
2755
2756 /* If a subr takes more than 8 arguments without using MANY
2757 or UNEVALLED, we need to extend this function to support it.
2758 Until this is done, there is no way to call the function. */
2759 emacs_abort ();
2760 }
2761 }
2762 }
2763 else if (COMPILEDP (fun)) 2685 else if (COMPILEDP (fun))
2764 val = funcall_lambda (fun, numargs, args + 1); 2686 val = funcall_lambda (fun, numargs, args + 1);
2765 else 2687 else
@@ -2791,6 +2713,89 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
2791 return val; 2713 return val;
2792} 2714}
2793 2715
2716
2717/* Apply a C subroutine SUBR to the NUMARGS evaluated arguments in ARG_VECTOR
2718 and return the result of evaluation. */
2719
2720Lisp_Object
2721funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *args)
2722{
2723 if (numargs < subr->min_args
2724 || (subr->max_args >= 0 && subr->max_args < numargs))
2725 {
2726 Lisp_Object fun;
2727 XSETSUBR (fun, subr);
2728 xsignal2 (Qwrong_number_of_arguments, fun, make_number (numargs));
2729 }
2730
2731 else if (subr->max_args == UNEVALLED)
2732 {
2733 Lisp_Object fun;
2734 XSETSUBR (fun, subr);
2735 xsignal1 (Qinvalid_function, fun);
2736 }
2737
2738 else if (subr->max_args == MANY)
2739 return (subr->function.aMANY) (numargs, args);
2740 else
2741 {
2742 Lisp_Object internal_argbuf[8];
2743 Lisp_Object *internal_args;
2744 if (subr->max_args > numargs)
2745 {
2746 eassert (subr->max_args <= ARRAYELTS (internal_argbuf));
2747 internal_args = internal_argbuf;
2748 memcpy (internal_args, args, numargs * word_size);
2749 memclear (internal_args + numargs,
2750 (subr->max_args - numargs) * word_size);
2751 }
2752 else
2753 internal_args = args;
2754 switch (subr->max_args)
2755 {
2756 case 0:
2757 return (subr->function.a0 ());
2758 case 1:
2759 return (subr->function.a1 (internal_args[0]));
2760 case 2:
2761 return (subr->function.a2
2762 (internal_args[0], internal_args[1]));
2763 case 3:
2764 return (subr->function.a3
2765 (internal_args[0], internal_args[1], internal_args[2]));
2766 case 4:
2767 return (subr->function.a4
2768 (internal_args[0], internal_args[1], internal_args[2],
2769 internal_args[3]));
2770 case 5:
2771 return (subr->function.a5
2772 (internal_args[0], internal_args[1], internal_args[2],
2773 internal_args[3], internal_args[4]));
2774 case 6:
2775 return (subr->function.a6
2776 (internal_args[0], internal_args[1], internal_args[2],
2777 internal_args[3], internal_args[4], internal_args[5]));
2778 case 7:
2779 return (subr->function.a7
2780 (internal_args[0], internal_args[1], internal_args[2],
2781 internal_args[3], internal_args[4], internal_args[5],
2782 internal_args[6]));
2783 case 8:
2784 return (subr->function.a8
2785 (internal_args[0], internal_args[1], internal_args[2],
2786 internal_args[3], internal_args[4], internal_args[5],
2787 internal_args[6], internal_args[7]));
2788
2789 default:
2790
2791 /* If a subr takes more than 8 arguments without using MANY
2792 or UNEVALLED, we need to extend this function to support it.
2793 Until this is done, there is no way to call the function. */
2794 emacs_abort ();
2795 }
2796 }
2797}
2798
2794static Lisp_Object 2799static Lisp_Object
2795apply_lambda (Lisp_Object fun, Lisp_Object args, ptrdiff_t count) 2800apply_lambda (Lisp_Object fun, Lisp_Object args, ptrdiff_t count)
2796{ 2801{
@@ -3171,10 +3176,10 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3171 specpdl_ptr->let.symbol = symbol; 3176 specpdl_ptr->let.symbol = symbol;
3172 specpdl_ptr->let.old_value = SYMBOL_VAL (sym); 3177 specpdl_ptr->let.old_value = SYMBOL_VAL (sym);
3173 grow_specpdl (); 3178 grow_specpdl ();
3174 if (!sym->constant) 3179 if (!sym->trapped_write)
3175 SET_SYMBOL_VAL (sym, value); 3180 SET_SYMBOL_VAL (sym, value);
3176 else 3181 else
3177 set_internal (symbol, value, Qnil, 1); 3182 set_internal (symbol, value, Qnil, SET_INTERNAL_BIND);
3178 break; 3183 break;
3179 case SYMBOL_LOCALIZED: 3184 case SYMBOL_LOCALIZED:
3180 if (SYMBOL_BLV (sym)->frame_local) 3185 if (SYMBOL_BLV (sym)->frame_local)
@@ -3214,7 +3219,7 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3214 specpdl_ptr->let.kind = SPECPDL_LET; 3219 specpdl_ptr->let.kind = SPECPDL_LET;
3215 3220
3216 grow_specpdl (); 3221 grow_specpdl ();
3217 set_internal (symbol, value, Qnil, 1); 3222 set_internal (symbol, value, Qnil, SET_INTERNAL_BIND);
3218 break; 3223 break;
3219 } 3224 }
3220 default: emacs_abort (); 3225 default: emacs_abort ();
@@ -3341,14 +3346,16 @@ unbind_to (ptrdiff_t count, Lisp_Object value)
3341 case SPECPDL_BACKTRACE: 3346 case SPECPDL_BACKTRACE:
3342 break; 3347 break;
3343 case SPECPDL_LET: 3348 case SPECPDL_LET:
3344 { /* If variable has a trivial value (no forwarding), we can 3349 { /* If variable has a trivial value (no forwarding), and
3345 just set it. No need to check for constant symbols here, 3350 isn't trapped, we can just set it. */
3346 since that was already done by specbind. */
3347 Lisp_Object sym = specpdl_symbol (specpdl_ptr); 3351 Lisp_Object sym = specpdl_symbol (specpdl_ptr);
3348 if (SYMBOLP (sym) && XSYMBOL (sym)->redirect == SYMBOL_PLAINVAL) 3352 if (SYMBOLP (sym) && XSYMBOL (sym)->redirect == SYMBOL_PLAINVAL)
3349 { 3353 {
3350 SET_SYMBOL_VAL (XSYMBOL (sym), 3354 if (XSYMBOL (sym)->trapped_write == SYMBOL_UNTRAPPED_WRITE)
3351 specpdl_old_value (specpdl_ptr)); 3355 SET_SYMBOL_VAL (XSYMBOL (sym), specpdl_old_value (specpdl_ptr));
3356 else
3357 set_internal (sym, specpdl_old_value (specpdl_ptr),
3358 Qnil, SET_INTERNAL_UNBIND);
3352 break; 3359 break;
3353 } 3360 }
3354 else 3361 else
@@ -3371,7 +3378,7 @@ unbind_to (ptrdiff_t count, Lisp_Object value)
3371 /* If this was a local binding, reset the value in the appropriate 3378 /* If this was a local binding, reset the value in the appropriate
3372 buffer, but only if that buffer's binding still exists. */ 3379 buffer, but only if that buffer's binding still exists. */
3373 if (!NILP (Flocal_variable_p (symbol, where))) 3380 if (!NILP (Flocal_variable_p (symbol, where)))
3374 set_internal (symbol, old_value, where, 1); 3381 set_internal (symbol, old_value, where, SET_INTERNAL_UNBIND);
3375 } 3382 }
3376 break; 3383 break;
3377 } 3384 }
@@ -3596,7 +3603,7 @@ backtrace_eval_unrewind (int distance)
3596 { 3603 {
3597 set_specpdl_old_value 3604 set_specpdl_old_value
3598 (tmp, Fbuffer_local_value (symbol, where)); 3605 (tmp, Fbuffer_local_value (symbol, where));
3599 set_internal (symbol, old_value, where, 1); 3606 set_internal (symbol, old_value, where, SET_INTERNAL_UNBIND);
3600 } 3607 }
3601 } 3608 }
3602 break; 3609 break;
@@ -3940,6 +3947,7 @@ alist of active lexical bindings. */);
3940 defsubr (&Sset_default_toplevel_value); 3947 defsubr (&Sset_default_toplevel_value);
3941 defsubr (&Sdefvar); 3948 defsubr (&Sdefvar);
3942 defsubr (&Sdefvaralias); 3949 defsubr (&Sdefvaralias);
3950 DEFSYM (Qdefvaralias, "defvaralias");
3943 defsubr (&Sdefconst); 3951 defsubr (&Sdefconst);
3944 defsubr (&Smake_var_non_special); 3952 defsubr (&Smake_var_non_special);
3945 defsubr (&Slet); 3953 defsubr (&Slet);