aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
authorStefan Monnier2010-04-19 21:50:52 -0400
committerStefan Monnier2010-04-19 21:50:52 -0400
commitce5b453a449e4e7729abb5128114e2687f08360d (patch)
tree55a132b01782b9667ff6f754949d55d5e52e76a4 /src/eval.c
parent56d365a93da3c6b439998c251e9f01c73791f4b2 (diff)
downloademacs-ce5b453a449e4e7729abb5128114e2687f08360d.tar.gz
emacs-ce5b453a449e4e7729abb5128114e2687f08360d.zip
Make variable forwarding explicit rather the using special values.
Basically, this makes the structure of buffer-local values and object forwarding explicit in the type of Lisp_Symbols rather than use special Lisp_Objects for that. This tends to lead to slightly more verbose code, but is more C-like, simpler, and makes it easier to make sure we handled all cases, among other things by letting the compiler help us check it. * lisp.h (enum Lisp_Misc_Type, union Lisp_Misc): Removing forwarding objects. (enum Lisp_Fwd_Type, enum symbol_redirect, union Lisp_Fwd): New types. (struct Lisp_Symbol): Make the various forms of variable-forwarding explicit rather than hiding them inside Lisp_Object "values". (XFWDTYPE): New macro. (XINTFWD, XBOOLFWD, XOBJFWD, XKBOARD_OBJFWD): Redefine. (XBUFFER_LOCAL_VALUE): Remove. (SYMBOL_VAL, SYMBOL_ALIAS, SYMBOL_BLV, SYMBOL_FWD, SET_SYMBOL_VAL) (SET_SYMBOL_ALIAS, SET_SYMBOL_BLV, SET_SYMBOL_FWD): New macros. (SYMBOL_VALUE, SET_SYMBOL_VALUE): Remove. (struct Lisp_Intfwd, struct Lisp_Boolfwd, struct Lisp_Objfwd) (struct Lisp_Buffer_Objfwd, struct Lisp_Kboard_Objfwd): Remove the Lisp_Misc_* header. (struct Lisp_Buffer_Local_Value): Redefine. (BLV_FOUND, SET_BLV_FOUND, BLV_VALUE, SET_BLV_VALUE): New macros. (struct Lisp_Misc_Any): Add filler to get the right size. (struct Lisp_Free): Use struct Lisp_Misc_Any rather than struct Lisp_Intfwd. (DEFVAR_LISP, DEFVAR_LISP_NOPRO, DEFVAR_BOOL, DEFVAR_INT) (DEFVAR_KBOARD): Allocate a forwarding object. * data.c (do_blv_forwarding, store_blv_forwarding): New macros. (let_shadows_global_binding_p): New function. (union Lisp_Val_Fwd): New type. (make_blv): New function. (swap_in_symval_forwarding, indirect_variable, do_symval_forwarding) (store_symval_forwarding, swap_in_global_binding, Fboundp) (swap_in_symval_forwarding, find_symbol_value, Fset) (let_shadows_buffer_binding_p, set_internal, default_value) (Fset_default, Fmake_variable_buffer_local, Fmake_local_variable) (Fkill_local_variable, Fmake_variable_frame_local) (Flocal_variable_p, Flocal_variable_if_set_p) (Fvariable_binding_locus): * xdisp.c (select_frame_for_redisplay): * lread.c (Fintern, Funintern, init_obarray, defvar_int) (defvar_bool, defvar_lisp_nopro, defvar_lisp, defvar_kboard): * frame.c (store_frame_param): * eval.c (Fdefvaralias, Fuser_variable_p, specbind, unbind_to): * bytecode.c (Fbyte_code) <varref, varset>: Adapt to the new symbol value structure. * buffer.c (PER_BUFFER_SYMBOL): Move from buffer.h. (clone_per_buffer_values): Only adjust markers into the current buffer. (reset_buffer_local_variables): PER_BUFFER_IDX is never -2. (Fbuffer_local_value, set_buffer_internal_1) (swap_out_buffer_local_variables): Adapt to the new symbol value structure. (DEFVAR_PER_BUFFER): Allocate a Lisp_Buffer_Objfwd object. (defvar_per_buffer): Take a new arg for the fwd object. (buffer_lisp_local_variables): Return a proper alist (different fix for bug#4138). * alloc.c (Fmake_symbol): Use SET_SYMBOL_VAL. (Fgarbage_collect): Don't handle buffer_defaults specially. (mark_object): Handle new symbol value structure rather than the old special Lisp_Misc_* objects. (gc_sweep) <symbols>: Free also the buffer-local-value objects. * term.c (set_tty_color_mode): * bidi.c (bidi_initialize): Don't access the ->value field directly. * buffer.h (PER_BUFFER_VAR_OFFSET): Don't bother with a buffer_local_flags. * print.c (print_object): Get rid of impossible forwarding objects.
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c214
1 files changed, 129 insertions, 85 deletions
diff --git a/src/eval.c b/src/eval.c
index 6609d3b5c8a..cb1d435cb8b 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -767,24 +767,46 @@ The return value is BASE-VARIABLE. */)
767 CHECK_SYMBOL (new_alias); 767 CHECK_SYMBOL (new_alias);
768 CHECK_SYMBOL (base_variable); 768 CHECK_SYMBOL (base_variable);
769 769
770 if (SYMBOL_CONSTANT_P (new_alias))
771 error ("Cannot make a constant an alias");
772
773 sym = XSYMBOL (new_alias); 770 sym = XSYMBOL (new_alias);
771
772 if (sym->constant)
773 if (sym->redirect == SYMBOL_VARALIAS)
774 sym->constant = 0; /* Reset. */
775 else
776 /* Not sure why. */
777 error ("Cannot make a constant an alias");
778
779 switch (sym->redirect)
780 {
781 case SYMBOL_FORWARDED:
782 error ("Cannot make an internal variable an alias");
783 case SYMBOL_LOCALIZED:
784 error ("Don't know how to make a localized variable an alias");
785 }
786
774 /* http://lists.gnu.org/archive/html/emacs-devel/2008-04/msg00834.html 787 /* http://lists.gnu.org/archive/html/emacs-devel/2008-04/msg00834.html
775 If n_a is bound, but b_v is not, set the value of b_v to n_a. 788 If n_a is bound, but b_v is not, set the value of b_v to n_a,
776 This is for the sake of define-obsolete-variable-alias and user 789 so that old-code that affects n_a before the aliasing is setup
777 customizations. */ 790 still works. */
778 if (NILP (Fboundp (base_variable)) && !NILP (Fboundp (new_alias))) 791 if (NILP (Fboundp (base_variable)))
779 XSYMBOL(base_variable)->value = sym->value; 792 set_internal (base_variable, find_symbol_value (new_alias), NULL, 1);
780 sym->indirect_variable = 1; 793
781 sym->value = base_variable; 794 {
795 struct specbinding *p;
796
797 for (p = specpdl_ptr - 1; p >= specpdl; p--)
798 if (p->func == NULL
799 && (EQ (new_alias,
800 CONSP (p->symbol) ? XCAR (p->symbol) : p->symbol)))
801 error ("Don't know how to make a let-bound variable an alias");
802 }
803
804 sym->redirect = SYMBOL_VARALIAS;
805 SET_SYMBOL_ALIAS (sym, XSYMBOL (base_variable));
782 sym->constant = SYMBOL_CONSTANT_P (base_variable); 806 sym->constant = SYMBOL_CONSTANT_P (base_variable);
783 LOADHIST_ATTACH (new_alias); 807 LOADHIST_ATTACH (new_alias);
784 if (!NILP (docstring)) 808 /* Even if docstring is nil: remove old docstring. */
785 Fput (new_alias, Qvariable_documentation, docstring); 809 Fput (new_alias, Qvariable_documentation, docstring);
786 else
787 Fput (new_alias, Qvariable_documentation, Qnil);
788 810
789 return base_variable; 811 return base_variable;
790} 812}
@@ -944,7 +966,7 @@ chain of symbols. */)
944 return Qnil; 966 return Qnil;
945 967
946 /* If indirect and there's an alias loop, don't check anything else. */ 968 /* If indirect and there's an alias loop, don't check anything else. */
947 if (XSYMBOL (variable)->indirect_variable 969 if (XSYMBOL (variable)->redirect == SYMBOL_VARALIAS
948 && NILP (internal_condition_case_1 (lisp_indirect_variable, variable, 970 && NILP (internal_condition_case_1 (lisp_indirect_variable, variable,
949 Qt, user_variable_p_eh))) 971 Qt, user_variable_p_eh)))
950 return Qnil; 972 return Qnil;
@@ -968,11 +990,11 @@ chain of symbols. */)
968 || (!NILP (Fget (variable, intern ("custom-autoload"))))) 990 || (!NILP (Fget (variable, intern ("custom-autoload")))))
969 return Qt; 991 return Qt;
970 992
971 if (!XSYMBOL (variable)->indirect_variable) 993 if (!(XSYMBOL (variable)->redirect == SYMBOL_VARALIAS))
972 return Qnil; 994 return Qnil;
973 995
974 /* An indirect variable? Let's follow the chain. */ 996 /* An indirect variable? Let's follow the chain. */
975 variable = XSYMBOL (variable)->value; 997 XSETSYMBOL (variable, SYMBOL_ALIAS (XSYMBOL (variable)));
976 } 998 }
977} 999}
978 1000
@@ -3263,78 +3285,94 @@ void
3263specbind (symbol, value) 3285specbind (symbol, value)
3264 Lisp_Object symbol, value; 3286 Lisp_Object symbol, value;
3265{ 3287{
3266 Lisp_Object valcontents; 3288 struct Lisp_Symbol *sym;
3289
3290 eassert (!handling_signal);
3267 3291
3268 CHECK_SYMBOL (symbol); 3292 CHECK_SYMBOL (symbol);
3293 sym = XSYMBOL (symbol);
3269 if (specpdl_ptr == specpdl + specpdl_size) 3294 if (specpdl_ptr == specpdl + specpdl_size)
3270 grow_specpdl (); 3295 grow_specpdl ();
3271 3296
3272 /* The most common case is that of a non-constant symbol with a 3297 start:
3273 trivial value. Make that as fast as we can. */ 3298 switch (sym->redirect)
3274 valcontents = SYMBOL_VALUE (symbol); 3299 {
3275 if (!MISCP (valcontents) && !SYMBOL_CONSTANT_P (symbol)) 3300 case SYMBOL_VARALIAS:
3276 { 3301 sym = indirect_variable (sym); XSETSYMBOL (symbol, sym); goto start;
3277 specpdl_ptr->symbol = symbol; 3302 case SYMBOL_PLAINVAL:
3278 specpdl_ptr->old_value = valcontents; 3303 { /* The most common case is that of a non-constant symbol with a
3279 specpdl_ptr->func = NULL; 3304 trivial value. Make that as fast as we can. */
3280 ++specpdl_ptr; 3305 specpdl_ptr->symbol = symbol;
3281 SET_SYMBOL_VALUE (symbol, value); 3306 specpdl_ptr->old_value = SYMBOL_VAL (sym);
3282 } 3307 specpdl_ptr->func = NULL;
3283 else 3308 ++specpdl_ptr;
3284 { 3309 if (!sym->constant)
3285 Lisp_Object ovalue = find_symbol_value (symbol); 3310 SET_SYMBOL_VAL (sym, value);
3286 specpdl_ptr->func = 0;
3287 specpdl_ptr->old_value = ovalue;
3288
3289 valcontents = XSYMBOL (symbol)->value;
3290
3291 if (BUFFER_LOCAL_VALUEP (valcontents)
3292 || BUFFER_OBJFWDP (valcontents))
3293 {
3294 Lisp_Object where, current_buffer;
3295
3296 current_buffer = Fcurrent_buffer ();
3297
3298 /* For a local variable, record both the symbol and which
3299 buffer's or frame's value we are saving. */
3300 if (!NILP (Flocal_variable_p (symbol, Qnil)))
3301 where = current_buffer;
3302 else if (BUFFER_LOCAL_VALUEP (valcontents)
3303 && XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame)
3304 where = XBUFFER_LOCAL_VALUE (valcontents)->frame;
3305 else 3311 else
3306 where = Qnil; 3312 set_internal (symbol, value, 0, 1);
3307 3313 break;
3308 /* We're not using the `unused' slot in the specbinding
3309 structure because this would mean we have to do more
3310 work for simple variables. */
3311 specpdl_ptr->symbol = Fcons (symbol, Fcons (where, current_buffer));
3312
3313 /* If SYMBOL is a per-buffer variable which doesn't have a
3314 buffer-local value here, make the `let' change the global
3315 value by changing the value of SYMBOL in all buffers not
3316 having their own value. This is consistent with what
3317 happens with other buffer-local variables. */
3318 if (NILP (where)
3319 && BUFFER_OBJFWDP (valcontents))
3320 {
3321 ++specpdl_ptr;
3322 Fset_default (symbol, value);
3323 return;
3324 }
3325 } 3314 }
3326 else 3315 case SYMBOL_LOCALIZED: case SYMBOL_FORWARDED:
3327 specpdl_ptr->symbol = symbol; 3316 {
3328 3317 Lisp_Object ovalue = find_symbol_value (symbol);
3329 specpdl_ptr++; 3318 specpdl_ptr->func = 0;
3330 /* We used to do 3319 specpdl_ptr->old_value = ovalue;
3331 if (BUFFER_OBJFWDP (ovalue) || KBOARD_OBJFWDP (ovalue)) 3320
3332 store_symval_forwarding (symbol, ovalue, value, NULL); 3321 eassert (sym->redirect != SYMBOL_LOCALIZED
3333 else 3322 || (EQ (SYMBOL_BLV (sym)->where,
3334 but ovalue comes from find_symbol_value which should never return 3323 SYMBOL_BLV (sym)->frame_local ?
3335 such an internal value. */ 3324 Fselected_frame () : Fcurrent_buffer ())));
3336 eassert (!(BUFFER_OBJFWDP (ovalue) || KBOARD_OBJFWDP (ovalue))); 3325
3337 set_internal (symbol, value, 0, 1); 3326 if (sym->redirect == SYMBOL_LOCALIZED
3327 || BUFFER_OBJFWDP (SYMBOL_FWD (sym)))
3328 {
3329 Lisp_Object where, cur_buf = Fcurrent_buffer ();
3330
3331 /* For a local variable, record both the symbol and which
3332 buffer's or frame's value we are saving. */
3333 if (!NILP (Flocal_variable_p (symbol, Qnil)))
3334 {
3335 eassert (sym->redirect != SYMBOL_LOCALIZED
3336 || (BLV_FOUND (SYMBOL_BLV (sym))
3337 && EQ (cur_buf, SYMBOL_BLV (sym)->where)));
3338 where = cur_buf;
3339 }
3340 else if (sym->redirect == SYMBOL_LOCALIZED
3341 && BLV_FOUND (SYMBOL_BLV (sym)))
3342 where = SYMBOL_BLV (sym)->where;
3343 else
3344 where = Qnil;
3345
3346 /* We're not using the `unused' slot in the specbinding
3347 structure because this would mean we have to do more
3348 work for simple variables. */
3349 /* FIXME: The third value `current_buffer' is only used in
3350 let_shadows_buffer_binding_p which is itself only used
3351 in set_internal for local_if_set. */
3352 specpdl_ptr->symbol = Fcons (symbol, Fcons (where, cur_buf));
3353
3354 /* If SYMBOL is a per-buffer variable which doesn't have a
3355 buffer-local value here, make the `let' change the global
3356 value by changing the value of SYMBOL in all buffers not
3357 having their own value. This is consistent with what
3358 happens with other buffer-local variables. */
3359 if (NILP (where)
3360 && sym->redirect == SYMBOL_FORWARDED)
3361 {
3362 eassert (BUFFER_OBJFWDP (SYMBOL_FWD (sym)));
3363 ++specpdl_ptr;
3364 Fset_default (symbol, value);
3365 return;
3366 }
3367 }
3368 else
3369 specpdl_ptr->symbol = symbol;
3370
3371 specpdl_ptr++;
3372 set_internal (symbol, value, 0, 1);
3373 break;
3374 }
3375 default: abort ();
3338 } 3376 }
3339} 3377}
3340 3378
@@ -3394,7 +3432,12 @@ unbind_to (count, value)
3394 if (NILP (where)) 3432 if (NILP (where))
3395 Fset_default (symbol, this_binding.old_value); 3433 Fset_default (symbol, this_binding.old_value);
3396 else if (BUFFERP (where)) 3434 else if (BUFFERP (where))
3397 set_internal (symbol, this_binding.old_value, XBUFFER (where), 1); 3435 if (!NILP (Flocal_variable_p (symbol, where)))
3436 set_internal (symbol, this_binding.old_value, XBUFFER (where), 1);
3437 /* else if (!NILP (Fbuffer_live_p (where)))
3438 error ("Unbinding local %s to global!", symbol); */
3439 else
3440 ;
3398 else 3441 else
3399 set_internal (symbol, this_binding.old_value, NULL, 1); 3442 set_internal (symbol, this_binding.old_value, NULL, 1);
3400 } 3443 }
@@ -3403,8 +3446,9 @@ unbind_to (count, value)
3403 /* If variable has a trivial value (no forwarding), we can 3446 /* If variable has a trivial value (no forwarding), we can
3404 just set it. No need to check for constant symbols here, 3447 just set it. No need to check for constant symbols here,
3405 since that was already done by specbind. */ 3448 since that was already done by specbind. */
3406 if (!MISCP (SYMBOL_VALUE (this_binding.symbol))) 3449 if (XSYMBOL (this_binding.symbol)->redirect == SYMBOL_PLAINVAL)
3407 SET_SYMBOL_VALUE (this_binding.symbol, this_binding.old_value); 3450 SET_SYMBOL_VAL (XSYMBOL (this_binding.symbol),
3451 this_binding.old_value);
3408 else 3452 else
3409 set_internal (this_binding.symbol, this_binding.old_value, 0, 1); 3453 set_internal (this_binding.symbol, this_binding.old_value, 0, 1);
3410 } 3454 }