1 /* Copyright (C) 1999,2000,2001, 2003, 2006, 2008 Free Software Foundation, Inc.
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "libguile/_scm.h"
24 #include "libguile/alist.h"
25 #include "libguile/eval.h"
26 #include "libguile/gh.h"
27 #include "libguile/hash.h"
28 #include "libguile/list.h"
29 #include "libguile/ports.h"
30 #include "libguile/smob.h"
31 #include "libguile/symbols.h"
32 #include "libguile/vectors.h"
33 #include "libguile/weaks.h"
35 #include "libguile/environments.h"
39 scm_t_bits scm_tc16_environment;
40 scm_t_bits scm_tc16_observer;
41 #define DEFAULT_OBARRAY_SIZE 31
43 SCM scm_system_environment;
47 /* error conditions */
50 * Throw an error if symbol is not bound in environment func
53 scm_error_environment_unbound (const char *func, SCM env, SCM symbol)
55 /* Dirk:FIXME:: Should throw an environment:unbound type error */
56 char error[] = "Symbol `~A' not bound in environment `~A'.";
57 SCM arguments = scm_cons2 (symbol, env, SCM_EOL);
58 scm_misc_error (func, error, arguments);
63 * Throw an error if func tried to create (define) or remove
64 * (undefine) a new binding for symbol in env
67 scm_error_environment_immutable_binding (const char *func, SCM env, SCM symbol)
69 /* Dirk:FIXME:: Should throw an environment:immutable-binding type error */
70 char error[] = "Immutable binding in environment ~A (symbol: `~A').";
71 SCM arguments = scm_cons2 (env, symbol, SCM_EOL);
72 scm_misc_error (func, error, arguments);
77 * Throw an error if func tried to change an immutable location.
80 scm_error_environment_immutable_location (const char *func, SCM env, SCM symbol)
82 /* Dirk:FIXME:: Should throw an environment:immutable-location type error */
83 char error[] = "Immutable location in environment `~A' (symbol: `~A').";
84 SCM arguments = scm_cons2 (env, symbol, SCM_EOL);
85 scm_misc_error (func, error, arguments);
90 /* generic environments */
93 /* Create an environment for the given type. Dereferencing type twice must
94 * deliver the initialized set of environment functions. Thus, type will
95 * also determine the signature of the underlying environment implementation.
96 * Dereferencing type once will typically deliver the data fields used by the
97 * underlying environment implementation.
100 scm_make_environment (void *type)
102 return scm_cell (scm_tc16_environment, (scm_t_bits) type);
106 SCM_DEFINE (scm_environment_p, "environment?", 1, 0, 0,
108 "Return @code{#t} if @var{obj} is an environment, or @code{#f}\n"
110 #define FUNC_NAME s_scm_environment_p
112 return scm_from_bool (SCM_ENVIRONMENT_P (obj));
117 SCM_DEFINE (scm_environment_bound_p, "environment-bound?", 2, 0, 0,
119 "Return @code{#t} if @var{sym} is bound in @var{env}, or\n"
120 "@code{#f} otherwise.")
121 #define FUNC_NAME s_scm_environment_bound_p
123 SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
124 SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, FUNC_NAME);
126 return scm_from_bool (SCM_ENVIRONMENT_BOUND_P (env, sym));
131 SCM_DEFINE (scm_environment_ref, "environment-ref", 2, 0, 0,
133 "Return the value of the location bound to @var{sym} in\n"
134 "@var{env}. If @var{sym} is unbound in @var{env}, signal an\n"
135 "@code{environment:unbound} error.")
136 #define FUNC_NAME s_scm_environment_ref
140 SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
141 SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, FUNC_NAME);
143 val = SCM_ENVIRONMENT_REF (env, sym);
145 if (!SCM_UNBNDP (val))
148 scm_error_environment_unbound (FUNC_NAME, env, sym);
153 /* This C function is identical to environment-ref, except that if symbol is
154 * unbound in env, it returns the value SCM_UNDEFINED, instead of signalling
158 scm_c_environment_ref (SCM env, SCM sym)
160 SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, "scm_c_environment_ref");
161 SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, "scm_c_environment_ref");
162 return SCM_ENVIRONMENT_REF (env, sym);
167 environment_default_folder (SCM proc, SCM symbol, SCM value, SCM tail)
169 return scm_call_3 (proc, symbol, value, tail);
173 SCM_DEFINE (scm_environment_fold, "environment-fold", 3, 0, 0,
174 (SCM env, SCM proc, SCM init),
175 "Iterate over all the bindings in @var{env}, accumulating some\n"
177 "For each binding in @var{env}, apply @var{proc} to the symbol\n"
178 "bound, its value, and the result from the previous application\n"
180 "Use @var{init} as @var{proc}'s third argument the first time\n"
181 "@var{proc} is applied.\n"
182 "If @var{env} contains no bindings, this function simply returns\n"
184 "If @var{env} binds the symbol sym1 to the value val1, sym2 to\n"
185 "val2, and so on, then this procedure computes:\n"
193 "Each binding in @var{env} will be processed exactly once.\n"
194 "@code{environment-fold} makes no guarantees about the order in\n"
195 "which the bindings are processed.\n"
196 "Here is a function which, given an environment, constructs an\n"
197 "association list representing that environment's bindings,\n"
198 "using environment-fold:\n"
200 " (define (environment->alist env)\n"
201 " (environment-fold env\n"
202 " (lambda (sym val tail)\n"
203 " (cons (cons sym val) tail))\n"
206 #define FUNC_NAME s_scm_environment_fold
208 SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
209 SCM_ASSERT (scm_is_true (scm_procedure_p (proc)),
210 proc, SCM_ARG2, FUNC_NAME);
212 return SCM_ENVIRONMENT_FOLD (env, environment_default_folder, proc, init);
217 /* This is the C-level analog of environment-fold. For each binding in ENV,
219 * (*proc) (data, symbol, value, previous)
220 * where previous is the value returned from the last call to *PROC, or INIT
221 * for the first call. If ENV contains no bindings, return INIT.
224 scm_c_environment_fold (SCM env, scm_environment_folder proc, SCM data, SCM init)
226 SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, "scm_c_environment_fold");
228 return SCM_ENVIRONMENT_FOLD (env, proc, data, init);
232 SCM_DEFINE (scm_environment_define, "environment-define", 3, 0, 0,
233 (SCM env, SCM sym, SCM val),
234 "Bind @var{sym} to a new location containing @var{val} in\n"
235 "@var{env}. If @var{sym} is already bound to another location\n"
236 "in @var{env} and the binding is mutable, that binding is\n"
237 "replaced. The new binding and location are both mutable. The\n"
238 "return value is unspecified.\n"
239 "If @var{sym} is already bound in @var{env}, and the binding is\n"
240 "immutable, signal an @code{environment:immutable-binding} error.")
241 #define FUNC_NAME s_scm_environment_define
245 SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
246 SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, FUNC_NAME);
248 status = SCM_ENVIRONMENT_DEFINE (env, sym, val);
250 if (scm_is_eq (status, SCM_ENVIRONMENT_SUCCESS))
251 return SCM_UNSPECIFIED;
252 else if (scm_is_eq (status, SCM_ENVIRONMENT_BINDING_IMMUTABLE))
253 scm_error_environment_immutable_binding (FUNC_NAME, env, sym);
260 SCM_DEFINE (scm_environment_undefine, "environment-undefine", 2, 0, 0,
262 "Remove any binding for @var{sym} from @var{env}. If @var{sym}\n"
263 "is unbound in @var{env}, do nothing. The return value is\n"
265 "If @var{sym} is already bound in @var{env}, and the binding is\n"
266 "immutable, signal an @code{environment:immutable-binding} error.")
267 #define FUNC_NAME s_scm_environment_undefine
271 SCM_ASSERT(SCM_ENVIRONMENT_P(env), env, SCM_ARG1, FUNC_NAME);
272 SCM_ASSERT(scm_is_symbol(sym), sym, SCM_ARG2, FUNC_NAME);
274 status = SCM_ENVIRONMENT_UNDEFINE (env, sym);
276 if (scm_is_eq (status, SCM_ENVIRONMENT_SUCCESS))
277 return SCM_UNSPECIFIED;
278 else if (scm_is_eq (status, SCM_ENVIRONMENT_BINDING_IMMUTABLE))
279 scm_error_environment_immutable_binding (FUNC_NAME, env, sym);
286 SCM_DEFINE (scm_environment_set_x, "environment-set!", 3, 0, 0,
287 (SCM env, SCM sym, SCM val),
288 "If @var{env} binds @var{sym} to some location, change that\n"
289 "location's value to @var{val}. The return value is\n"
291 "If @var{sym} is not bound in @var{env}, signal an\n"
292 "@code{environment:unbound} error. If @var{env} binds @var{sym}\n"
293 "to an immutable location, signal an\n"
294 "@code{environment:immutable-location} error.")
295 #define FUNC_NAME s_scm_environment_set_x
299 SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
300 SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, FUNC_NAME);
302 status = SCM_ENVIRONMENT_SET (env, sym, val);
304 if (scm_is_eq (status, SCM_ENVIRONMENT_SUCCESS))
305 return SCM_UNSPECIFIED;
306 else if (SCM_UNBNDP (status))
307 scm_error_environment_unbound (FUNC_NAME, env, sym);
308 else if (scm_is_eq (status, SCM_ENVIRONMENT_LOCATION_IMMUTABLE))
309 scm_error_environment_immutable_binding (FUNC_NAME, env, sym);
316 SCM_DEFINE (scm_environment_cell, "environment-cell", 3, 0, 0,
317 (SCM env, SCM sym, SCM for_write),
318 "Return the value cell which @var{env} binds to @var{sym}, or\n"
319 "@code{#f} if the binding does not live in a value cell.\n"
320 "The argument @var{for-write} indicates whether the caller\n"
321 "intends to modify the variable's value by mutating the value\n"
322 "cell. If the variable is immutable, then\n"
323 "@code{environment-cell} signals an\n"
324 "@code{environment:immutable-location} error.\n"
325 "If @var{sym} is unbound in @var{env}, signal an\n"
326 "@code{environment:unbound} error.\n"
327 "If you use this function, you should consider using\n"
328 "@code{environment-observe}, to be notified when @var{sym} gets\n"
329 "re-bound to a new value cell, or becomes undefined.")
330 #define FUNC_NAME s_scm_environment_cell
334 SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
335 SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, FUNC_NAME);
336 SCM_ASSERT (scm_is_bool (for_write), for_write, SCM_ARG3, FUNC_NAME);
338 location = SCM_ENVIRONMENT_CELL (env, sym, scm_is_true (for_write));
339 if (!SCM_IMP (location))
341 else if (SCM_UNBNDP (location))
342 scm_error_environment_unbound (FUNC_NAME, env, sym);
343 else if (scm_is_eq (location, SCM_ENVIRONMENT_LOCATION_IMMUTABLE))
344 scm_error_environment_immutable_location (FUNC_NAME, env, sym);
351 /* This C function is identical to environment-cell, with the following
352 * exceptions: If symbol is unbound in env, it returns the value
353 * SCM_UNDEFINED, instead of signalling an error. If symbol is bound to an
354 * immutable location but the cell is requested for write, the value
355 * SCM_ENVIRONMENT_LOCATION_IMMUTABLE is returned.
358 scm_c_environment_cell(SCM env, SCM sym, int for_write)
360 SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, "scm_c_environment_cell");
361 SCM_ASSERT (scm_is_symbol (sym), sym, SCM_ARG2, "scm_c_environment_cell");
363 return SCM_ENVIRONMENT_CELL (env, sym, for_write);
368 environment_default_observer (SCM env, SCM proc)
370 scm_call_1 (proc, env);
374 SCM_DEFINE (scm_environment_observe, "environment-observe", 2, 0, 0,
376 "Whenever @var{env}'s bindings change, apply @var{proc} to\n"
378 "This function returns an object, token, which you can pass to\n"
379 "@code{environment-unobserve} to remove @var{proc} from the set\n"
380 "of procedures observing @var{env}. The type and value of\n"
381 "token is unspecified.")
382 #define FUNC_NAME s_scm_environment_observe
384 SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
386 return SCM_ENVIRONMENT_OBSERVE (env, environment_default_observer, proc, 0);
391 SCM_DEFINE (scm_environment_observe_weak, "environment-observe-weak", 2, 0, 0,
393 "This function is the same as environment-observe, except that\n"
394 "the reference @var{env} retains to @var{proc} is a weak\n"
395 "reference. This means that, if there are no other live,\n"
396 "non-weak references to @var{proc}, it will be\n"
397 "garbage-collected, and dropped from @var{env}'s\n"
398 "list of observing procedures.")
399 #define FUNC_NAME s_scm_environment_observe_weak
401 SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
403 return SCM_ENVIRONMENT_OBSERVE (env, environment_default_observer, proc, 1);
408 /* This is the C-level analog of the Scheme functions environment-observe and
409 * environment-observe-weak. Whenever env's bindings change, call the
410 * function proc, passing it env and data. If weak_p is non-zero, env will
411 * retain only a weak reference to data, and if data is garbage collected, the
412 * entire observation will be dropped. This function returns a token, with
413 * the same meaning as those returned by environment-observe and
414 * environment-observe-weak.
417 scm_c_environment_observe (SCM env, scm_environment_observer proc, SCM data, int weak_p)
418 #define FUNC_NAME "scm_c_environment_observe"
420 SCM_ASSERT (SCM_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
422 return SCM_ENVIRONMENT_OBSERVE (env, proc, data, weak_p);
427 SCM_DEFINE (scm_environment_unobserve, "environment-unobserve", 1, 0, 0,
429 "Cancel the observation request which returned the value\n"
430 "@var{token}. The return value is unspecified.\n"
431 "If a call @code{(environment-observe env proc)} returns\n"
432 "@var{token}, then the call @code{(environment-unobserve token)}\n"
433 "will cause @var{proc} to no longer be called when @var{env}'s\n"
435 #define FUNC_NAME s_scm_environment_unobserve
439 SCM_ASSERT (SCM_OBSERVER_P (token), token, SCM_ARG1, FUNC_NAME);
441 env = SCM_OBSERVER_ENVIRONMENT (token);
442 SCM_ENVIRONMENT_UNOBSERVE (env, token);
444 return SCM_UNSPECIFIED;
450 environment_mark (SCM env)
452 return (*(SCM_ENVIRONMENT_FUNCS (env)->mark)) (env);
457 environment_free (SCM env)
459 (*(SCM_ENVIRONMENT_FUNCS (env)->free)) (env);
465 environment_print (SCM env, SCM port, scm_print_state *pstate)
467 return (*(SCM_ENVIRONMENT_FUNCS (env)->print)) (env, port, pstate);
475 observer_mark (SCM observer)
477 scm_gc_mark (SCM_OBSERVER_ENVIRONMENT (observer));
478 scm_gc_mark (SCM_OBSERVER_DATA (observer));
484 observer_print (SCM type, SCM port, scm_print_state *pstate SCM_UNUSED)
486 SCM address = scm_from_size_t (SCM_UNPACK (type));
487 SCM base16 = scm_number_to_string (address, scm_from_int (16));
489 scm_puts ("#<observer ", port);
490 scm_display (base16, port);
491 scm_puts (">", port);
500 * Obarrays form the basic lookup tables used to implement most of guile's
501 * built-in environment types. An obarray is implemented as a hash table with
502 * symbols as keys. The content of the data depends on the environment type.
507 * Enter symbol into obarray. The symbol must not already exist in obarray.
508 * The freshly generated (symbol . data) cell is returned.
511 obarray_enter (SCM obarray, SCM symbol, SCM data)
513 size_t hash = scm_i_symbol_hash (symbol) % SCM_HASHTABLE_N_BUCKETS (obarray);
514 SCM entry = scm_cons (symbol, data);
515 SCM slot = scm_cons (entry, SCM_HASHTABLE_BUCKET (obarray, hash));
516 SCM_SET_HASHTABLE_BUCKET (obarray, hash, slot);
517 SCM_HASHTABLE_INCREMENT (obarray);
518 if (SCM_HASHTABLE_N_ITEMS (obarray) > SCM_HASHTABLE_UPPER (obarray))
519 scm_i_rehash (obarray, scm_i_hash_symbol, 0, "obarray_enter");
526 * Enter symbol into obarray. An existing entry for symbol is replaced. If
527 * an entry existed, the old (symbol . data) cell is returned, #f otherwise.
530 obarray_replace (SCM obarray, SCM symbol, SCM data)
532 size_t hash = scm_i_symbol_hash (symbol) % SCM_HASHTABLE_N_BUCKETS (obarray);
533 SCM new_entry = scm_cons (symbol, data);
537 for (lsym = SCM_HASHTABLE_BUCKET (obarray, hash);
539 lsym = SCM_CDR (lsym))
541 SCM old_entry = SCM_CAR (lsym);
542 if (scm_is_eq (SCM_CAR (old_entry), symbol))
544 SCM_SETCAR (lsym, new_entry);
549 slot = scm_cons (new_entry, SCM_HASHTABLE_BUCKET (obarray, hash));
550 SCM_SET_HASHTABLE_BUCKET (obarray, hash, slot);
551 SCM_HASHTABLE_INCREMENT (obarray);
552 if (SCM_HASHTABLE_N_ITEMS (obarray) > SCM_HASHTABLE_UPPER (obarray))
553 scm_i_rehash (obarray, scm_i_hash_symbol, 0, "obarray_replace");
560 * Look up symbol in obarray
563 obarray_retrieve (SCM obarray, SCM sym)
565 size_t hash = scm_i_symbol_hash (sym) % SCM_HASHTABLE_N_BUCKETS (obarray);
568 for (lsym = SCM_HASHTABLE_BUCKET (obarray, hash);
570 lsym = SCM_CDR (lsym))
572 SCM entry = SCM_CAR (lsym);
573 if (scm_is_eq (SCM_CAR (entry), sym))
577 return SCM_UNDEFINED;
582 * Remove entry from obarray. If the symbol was found and removed, the old
583 * (symbol . data) cell is returned, #f otherwise.
586 obarray_remove (SCM obarray, SCM sym)
588 size_t hash = scm_i_symbol_hash (sym) % SCM_HASHTABLE_N_BUCKETS (obarray);
589 SCM table_entry = SCM_HASHTABLE_BUCKET (obarray, hash);
590 SCM handle = scm_sloppy_assq (sym, table_entry);
592 if (scm_is_pair (handle))
594 SCM new_table_entry = scm_delq1_x (handle, table_entry);
595 SCM_SET_HASHTABLE_BUCKET (obarray, hash, new_table_entry);
596 SCM_HASHTABLE_DECREMENT (obarray);
604 obarray_remove_all (SCM obarray)
606 size_t size = SCM_HASHTABLE_N_BUCKETS (obarray);
609 for (i = 0; i < size; i++)
611 SCM_SET_HASHTABLE_BUCKET (obarray, i, SCM_EOL);
613 SCM_SET_HASHTABLE_N_ITEMS (obarray, 0);
618 /* core environments base
620 * This struct and the corresponding functions form a base class for guile's
621 * built-in environment types.
625 struct core_environments_base {
626 struct scm_environment_funcs *funcs;
633 #define CORE_ENVIRONMENTS_BASE(env) \
634 ((struct core_environments_base *) SCM_CELL_WORD_1 (env))
635 #define CORE_ENVIRONMENT_OBSERVERS(env) \
636 (CORE_ENVIRONMENTS_BASE (env)->observers)
637 #define SCM_SET_CORE_ENVIRONMENT_OBSERVERS(env, v) \
638 (CORE_ENVIRONMENT_OBSERVERS (env) = (v))
639 #define CORE_ENVIRONMENT_WEAK_OBSERVER_VECTOR(env) \
640 (CORE_ENVIRONMENTS_BASE (env)->weak_observers)
641 #define CORE_ENVIRONMENT_WEAK_OBSERVERS(env) \
642 (scm_c_vector_ref (CORE_ENVIRONMENT_WEAK_OBSERVER_VECTOR (env), 0))
643 #define SCM_SET_CORE_ENVIRONMENT_WEAK_OBSERVERS(env, v) \
644 (scm_c_vector_set_x (CORE_ENVIRONMENT_WEAK_OBSERVER_VECTOR (env), 0, (v)))
649 core_environments_observe (SCM env, scm_environment_observer proc, SCM data, int weak_p)
651 SCM observer = scm_double_cell (scm_tc16_observer,
658 SCM observers = CORE_ENVIRONMENT_OBSERVERS (env);
659 SCM new_observers = scm_cons (observer, observers);
660 SCM_SET_CORE_ENVIRONMENT_OBSERVERS (env, new_observers);
664 SCM observers = CORE_ENVIRONMENT_WEAK_OBSERVERS (env);
665 SCM new_observers = scm_acons (SCM_BOOL_F, observer, observers);
666 SCM_SET_CORE_ENVIRONMENT_WEAK_OBSERVERS (env, new_observers);
674 core_environments_unobserve (SCM env, SCM observer)
676 unsigned int handling_weaks;
677 for (handling_weaks = 0; handling_weaks <= 1; ++handling_weaks)
679 SCM l = handling_weaks
680 ? CORE_ENVIRONMENT_WEAK_OBSERVERS (env)
681 : CORE_ENVIRONMENT_OBSERVERS (env);
683 if (!scm_is_null (l))
685 SCM rest = SCM_CDR (l);
686 SCM first = handling_weaks
690 if (scm_is_eq (first, observer))
692 /* Remove the first observer */
694 SCM_SET_CORE_ENVIRONMENT_WEAK_OBSERVERS (env, rest);
696 SCM_SET_CORE_ENVIRONMENT_OBSERVERS (env, rest);
701 SCM rest = SCM_CDR (l);
703 if (!scm_is_null (rest))
705 SCM next = handling_weaks
709 if (scm_is_eq (next, observer))
711 SCM_SETCDR (l, SCM_CDR (rest));
717 } while (!scm_is_null (l));
721 /* Dirk:FIXME:: What to do now, since the observer is not found? */
726 core_environments_mark (SCM env)
728 scm_gc_mark (CORE_ENVIRONMENT_OBSERVERS (env));
729 return CORE_ENVIRONMENT_WEAK_OBSERVER_VECTOR (env);
734 core_environments_finalize (SCM env SCM_UNUSED)
740 core_environments_preinit (struct core_environments_base *body)
743 body->observers = SCM_BOOL_F;
744 body->weak_observers = SCM_BOOL_F;
749 core_environments_init (struct core_environments_base *body,
750 struct scm_environment_funcs *funcs)
753 body->observers = SCM_EOL;
754 body->weak_observers = scm_make_weak_value_alist_vector (scm_from_int (1));
758 /* Tell all observers to clear their caches.
760 * Environments have to be informed about changes in the following cases:
761 * - The observed env has a new binding. This must be always reported.
762 * - The observed env has dropped a binding. This must be always reported.
763 * - A binding in the observed environment has changed. This must only be
764 * reported, if there is a chance that the binding is being cached outside.
765 * However, this potential optimization is not performed currently.
767 * Errors that occur while the observers are called are accumulated and
768 * signalled as one single error message to the caller.
779 update_catch_body (void *ptr)
781 struct update_data *data = (struct update_data *) ptr;
782 SCM observer = data->observer;
784 (*SCM_OBSERVER_PROC (observer))
785 (data->environment, SCM_OBSERVER_DATA (observer));
787 return SCM_UNDEFINED;
792 update_catch_handler (void *ptr, SCM tag, SCM args)
794 struct update_data *data = (struct update_data *) ptr;
795 SCM observer = data->observer;
797 scm_from_locale_string ("Observer `~A' signals `~A' error: ~S");
799 return scm_cons (message, scm_list_3 (observer, tag, args));
804 core_environments_broadcast (SCM env)
805 #define FUNC_NAME "core_environments_broadcast"
807 unsigned int handling_weaks;
808 SCM errors = SCM_EOL;
810 for (handling_weaks = 0; handling_weaks <= 1; ++handling_weaks)
812 SCM observers = handling_weaks
813 ? CORE_ENVIRONMENT_WEAK_OBSERVERS (env)
814 : CORE_ENVIRONMENT_OBSERVERS (env);
816 for (; !scm_is_null (observers); observers = SCM_CDR (observers))
818 struct update_data data;
819 SCM observer = handling_weaks
820 ? SCM_CDAR (observers)
821 : SCM_CAR (observers);
824 data.observer = observer;
825 data.environment = env;
827 error = scm_internal_catch (SCM_BOOL_T,
828 update_catch_body, &data,
829 update_catch_handler, &data);
831 if (!SCM_UNBNDP (error))
832 errors = scm_cons (error, errors);
836 if (!scm_is_null (errors))
838 /* Dirk:FIXME:: As soon as scm_misc_error is fixed to handle the name
839 * parameter correctly it should not be necessary any more to also pass
840 * namestr in order to get the desired information from the error
843 SCM ordered_errors = scm_reverse (errors);
846 "Observers of `~A' have signalled the following errors: ~S",
847 scm_cons2 (env, ordered_errors, SCM_EOL));
856 * A leaf environment is simply a mutable set of definitions. A leaf
857 * environment supports no operations beyond the common set.
859 * Implementation: The obarray of the leaf environment holds (symbol . value)
860 * pairs. No further information is necessary, since all bindings and
861 * locations in a leaf environment are mutable.
865 struct leaf_environment {
866 struct core_environments_base base;
872 #define LEAF_ENVIRONMENT(env) \
873 ((struct leaf_environment *) SCM_CELL_WORD_1 (env))
878 leaf_environment_ref (SCM env, SCM sym)
880 SCM obarray = LEAF_ENVIRONMENT (env)->obarray;
881 SCM binding = obarray_retrieve (obarray, sym);
882 return SCM_UNBNDP (binding) ? binding : SCM_CDR (binding);
887 leaf_environment_fold (SCM env, scm_environment_folder proc, SCM data, SCM init)
891 SCM obarray = LEAF_ENVIRONMENT (env)->obarray;
893 for (i = 0; i < SCM_HASHTABLE_N_BUCKETS (obarray); i++)
896 for (l = SCM_HASHTABLE_BUCKET (obarray, i);
900 SCM binding = SCM_CAR (l);
901 SCM symbol = SCM_CAR (binding);
902 SCM value = SCM_CDR (binding);
903 result = (*proc) (data, symbol, value, result);
911 leaf_environment_define (SCM env, SCM sym, SCM val)
912 #define FUNC_NAME "leaf_environment_define"
914 SCM obarray = LEAF_ENVIRONMENT (env)->obarray;
916 obarray_replace (obarray, sym, val);
917 core_environments_broadcast (env);
919 return SCM_ENVIRONMENT_SUCCESS;
925 leaf_environment_undefine (SCM env, SCM sym)
926 #define FUNC_NAME "leaf_environment_undefine"
928 SCM obarray = LEAF_ENVIRONMENT (env)->obarray;
929 SCM removed = obarray_remove (obarray, sym);
931 if (scm_is_true (removed))
932 core_environments_broadcast (env);
934 return SCM_ENVIRONMENT_SUCCESS;
940 leaf_environment_set_x (SCM env, SCM sym, SCM val)
941 #define FUNC_NAME "leaf_environment_set_x"
943 SCM obarray = LEAF_ENVIRONMENT (env)->obarray;
944 SCM binding = obarray_retrieve (obarray, sym);
946 if (!SCM_UNBNDP (binding))
948 SCM_SETCDR (binding, val);
949 return SCM_ENVIRONMENT_SUCCESS;
953 return SCM_UNDEFINED;
960 leaf_environment_cell (SCM env, SCM sym, int for_write SCM_UNUSED)
962 SCM obarray = LEAF_ENVIRONMENT (env)->obarray;
963 SCM binding = obarray_retrieve (obarray, sym);
969 leaf_environment_mark (SCM env)
971 scm_gc_mark (LEAF_ENVIRONMENT (env)->obarray);
972 return core_environments_mark (env);
977 leaf_environment_free (SCM env)
979 core_environments_finalize (env);
980 scm_gc_free (LEAF_ENVIRONMENT (env), sizeof (struct leaf_environment),
986 leaf_environment_print (SCM type, SCM port, scm_print_state *pstate SCM_UNUSED)
988 SCM address = scm_from_size_t (SCM_UNPACK (type));
989 SCM base16 = scm_number_to_string (address, scm_from_int (16));
991 scm_puts ("#<leaf environment ", port);
992 scm_display (base16, port);
993 scm_puts (">", port);
999 static struct scm_environment_funcs leaf_environment_funcs = {
1000 leaf_environment_ref,
1001 leaf_environment_fold,
1002 leaf_environment_define,
1003 leaf_environment_undefine,
1004 leaf_environment_set_x,
1005 leaf_environment_cell,
1006 core_environments_observe,
1007 core_environments_unobserve,
1008 leaf_environment_mark,
1009 leaf_environment_free,
1010 leaf_environment_print
1014 void *scm_type_leaf_environment = &leaf_environment_funcs;
1017 SCM_DEFINE (scm_make_leaf_environment, "make-leaf-environment", 0, 0, 0,
1019 "Create a new leaf environment, containing no bindings.\n"
1020 "All bindings and locations created in the new environment\n"
1022 #define FUNC_NAME s_scm_make_leaf_environment
1024 size_t size = sizeof (struct leaf_environment);
1025 struct leaf_environment *body = scm_gc_malloc (size, "leaf environment");
1028 core_environments_preinit (&body->base);
1029 body->obarray = SCM_BOOL_F;
1031 env = scm_make_environment (body);
1033 core_environments_init (&body->base, &leaf_environment_funcs);
1034 body->obarray = scm_c_make_hash_table (DEFAULT_OBARRAY_SIZE);
1041 SCM_DEFINE (scm_leaf_environment_p, "leaf-environment?", 1, 0, 0,
1043 "Return @code{#t} if object is a leaf environment, or @code{#f}\n"
1045 #define FUNC_NAME s_scm_leaf_environment_p
1047 return scm_from_bool (SCM_LEAF_ENVIRONMENT_P (object));
1053 /* eval environments
1055 * A module's source code refers to definitions imported from other modules,
1056 * and definitions made within itself. An eval environment combines two
1057 * environments -- a local environment and an imported environment -- to
1058 * produce a new environment in which both sorts of references can be
1061 * Implementation: The obarray of the eval environment is used to cache
1062 * entries from the local and imported environments such that in most of the
1063 * cases only a single lookup is necessary. Since for neither the local nor
1064 * the imported environment it is known, what kind of environment they form,
1065 * the most general case is assumed. Therefore, entries in the obarray take
1066 * one of the following forms:
1068 * 1) (<symbol> location mutability . source-env), where mutability indicates
1069 * one of the following states: IMMUTABLE if the location is known to be
1070 * immutable, MUTABLE if the location is known to be mutable, UNKNOWN if
1071 * the location has only been requested for non modifying accesses.
1073 * 2) (symbol . source-env) if the symbol has a binding in the source-env, but
1074 * if the source-env can't provide a cell for the binding. Thus, for every
1075 * access, the source-env has to be contacted directly.
1079 struct eval_environment {
1080 struct core_environments_base base;
1085 SCM imported_observer;
1091 #define EVAL_ENVIRONMENT(env) \
1092 ((struct eval_environment *) SCM_CELL_WORD_1 (env))
1094 #define IMMUTABLE SCM_I_MAKINUM (0)
1095 #define MUTABLE SCM_I_MAKINUM (1)
1096 #define UNKNOWN SCM_I_MAKINUM (2)
1098 #define CACHED_LOCATION(x) SCM_CAR (x)
1099 #define CACHED_MUTABILITY(x) SCM_CADR (x)
1100 #define SET_CACHED_MUTABILITY(x, v) SCM_SETCAR (SCM_CDR (x), (v))
1101 #define CACHED_SOURCE_ENVIRONMENT(x) SCM_CDDR (x)
1105 /* eval_environment_lookup will report one of the following distinct results:
1106 * a) (<object> . value) if a cell could be obtained.
1107 * b) <environment> if the environment has to be contacted directly.
1108 * c) IMMUTABLE if an immutable cell was requested for write.
1109 * d) SCM_UNDEFINED if there is no binding for the symbol.
1112 eval_environment_lookup (SCM env, SCM sym, int for_write)
1114 SCM obarray = EVAL_ENVIRONMENT (env)->obarray;
1115 SCM binding = obarray_retrieve (obarray, sym);
1117 if (!SCM_UNBNDP (binding))
1119 /* The obarray holds an entry for the symbol. */
1121 SCM entry = SCM_CDR (binding);
1123 if (scm_is_pair (entry))
1125 /* The entry in the obarray is a cached location. */
1127 SCM location = CACHED_LOCATION (entry);
1133 mutability = CACHED_MUTABILITY (entry);
1134 if (scm_is_eq (mutability, MUTABLE))
1137 if (scm_is_eq (mutability, UNKNOWN))
1139 SCM source_env = CACHED_SOURCE_ENVIRONMENT (entry);
1140 SCM location = SCM_ENVIRONMENT_CELL (source_env, sym, 1);
1142 if (scm_is_pair (location))
1144 SET_CACHED_MUTABILITY (entry, MUTABLE);
1147 else /* IMMUTABLE */
1149 SET_CACHED_MUTABILITY (entry, IMMUTABLE);
1158 /* The obarray entry is an environment */
1165 /* There is no entry for the symbol in the obarray. This can either
1166 * mean that there has not been a request for the symbol yet, or that
1167 * the symbol is really undefined. We are looking for the symbol in
1168 * both the local and the imported environment. If we find a binding, a
1169 * cached entry is created.
1172 struct eval_environment *body = EVAL_ENVIRONMENT (env);
1173 unsigned int handling_import;
1175 for (handling_import = 0; handling_import <= 1; ++handling_import)
1177 SCM source_env = handling_import ? body->imported : body->local;
1178 SCM location = SCM_ENVIRONMENT_CELL (source_env, sym, for_write);
1180 if (!SCM_UNBNDP (location))
1182 if (scm_is_pair (location))
1184 SCM mutability = for_write ? MUTABLE : UNKNOWN;
1185 SCM entry = scm_cons2 (location, mutability, source_env);
1186 obarray_enter (obarray, sym, entry);
1189 else if (scm_is_eq (location, SCM_ENVIRONMENT_LOCATION_NO_CELL))
1191 obarray_enter (obarray, sym, source_env);
1201 return SCM_UNDEFINED;
1207 eval_environment_ref (SCM env, SCM sym)
1208 #define FUNC_NAME "eval_environment_ref"
1210 SCM location = eval_environment_lookup (env, sym, 0);
1212 if (scm_is_pair (location))
1213 return SCM_CDR (location);
1214 else if (!SCM_UNBNDP (location))
1215 return SCM_ENVIRONMENT_REF (location, sym);
1217 return SCM_UNDEFINED;
1223 eval_environment_folder (SCM extended_data, SCM symbol, SCM value, SCM tail)
1225 SCM local = SCM_CAR (extended_data);
1227 if (!SCM_ENVIRONMENT_BOUND_P (local, symbol))
1229 SCM proc_as_nr = SCM_CADR (extended_data);
1230 unsigned long int proc_as_ul = scm_to_ulong (proc_as_nr);
1231 scm_environment_folder proc = (scm_environment_folder) proc_as_ul;
1232 SCM data = SCM_CDDR (extended_data);
1234 return (*proc) (data, symbol, value, tail);
1244 eval_environment_fold (SCM env, scm_environment_folder proc, SCM data, SCM init)
1246 SCM local = EVAL_ENVIRONMENT (env)->local;
1247 SCM imported = EVAL_ENVIRONMENT (env)->imported;
1248 SCM proc_as_nr = scm_from_ulong ((unsigned long) proc);
1249 SCM extended_data = scm_cons2 (local, proc_as_nr, data);
1250 SCM tmp_result = scm_c_environment_fold (imported, eval_environment_folder, extended_data, init);
1252 return scm_c_environment_fold (local, proc, data, tmp_result);
1257 eval_environment_define (SCM env, SCM sym, SCM val)
1258 #define FUNC_NAME "eval_environment_define"
1260 SCM local = EVAL_ENVIRONMENT (env)->local;
1261 return SCM_ENVIRONMENT_DEFINE (local, sym, val);
1267 eval_environment_undefine (SCM env, SCM sym)
1268 #define FUNC_NAME "eval_environment_undefine"
1270 SCM local = EVAL_ENVIRONMENT (env)->local;
1271 return SCM_ENVIRONMENT_UNDEFINE (local, sym);
1277 eval_environment_set_x (SCM env, SCM sym, SCM val)
1278 #define FUNC_NAME "eval_environment_set_x"
1280 SCM location = eval_environment_lookup (env, sym, 1);
1282 if (scm_is_pair (location))
1284 SCM_SETCDR (location, val);
1285 return SCM_ENVIRONMENT_SUCCESS;
1287 else if (SCM_ENVIRONMENT_P (location))
1289 return SCM_ENVIRONMENT_SET (location, sym, val);
1291 else if (scm_is_eq (location, IMMUTABLE))
1293 return SCM_ENVIRONMENT_LOCATION_IMMUTABLE;
1297 return SCM_UNDEFINED;
1304 eval_environment_cell (SCM env, SCM sym, int for_write)
1305 #define FUNC_NAME "eval_environment_cell"
1307 SCM location = eval_environment_lookup (env, sym, for_write);
1309 if (scm_is_pair (location))
1311 else if (SCM_ENVIRONMENT_P (location))
1312 return SCM_ENVIRONMENT_LOCATION_NO_CELL;
1313 else if (scm_is_eq (location, IMMUTABLE))
1314 return SCM_ENVIRONMENT_LOCATION_IMMUTABLE;
1316 return SCM_UNDEFINED;
1322 eval_environment_mark (SCM env)
1324 struct eval_environment *body = EVAL_ENVIRONMENT (env);
1326 scm_gc_mark (body->obarray);
1327 scm_gc_mark (body->imported);
1328 scm_gc_mark (body->imported_observer);
1329 scm_gc_mark (body->local);
1330 scm_gc_mark (body->local_observer);
1332 return core_environments_mark (env);
1337 eval_environment_free (SCM env)
1339 core_environments_finalize (env);
1340 scm_gc_free (EVAL_ENVIRONMENT (env), sizeof (struct eval_environment),
1341 "eval environment");
1346 eval_environment_print (SCM type, SCM port, scm_print_state *pstate SCM_UNUSED)
1348 SCM address = scm_from_size_t (SCM_UNPACK (type));
1349 SCM base16 = scm_number_to_string (address, scm_from_int (16));
1351 scm_puts ("#<eval environment ", port);
1352 scm_display (base16, port);
1353 scm_puts (">", port);
1359 static struct scm_environment_funcs eval_environment_funcs = {
1360 eval_environment_ref,
1361 eval_environment_fold,
1362 eval_environment_define,
1363 eval_environment_undefine,
1364 eval_environment_set_x,
1365 eval_environment_cell,
1366 core_environments_observe,
1367 core_environments_unobserve,
1368 eval_environment_mark,
1369 eval_environment_free,
1370 eval_environment_print
1374 void *scm_type_eval_environment = &eval_environment_funcs;
1378 eval_environment_observer (SCM caller SCM_UNUSED, SCM eval_env)
1380 SCM obarray = EVAL_ENVIRONMENT (eval_env)->obarray;
1382 obarray_remove_all (obarray);
1383 core_environments_broadcast (eval_env);
1387 SCM_DEFINE (scm_make_eval_environment, "make-eval-environment", 2, 0, 0,
1388 (SCM local, SCM imported),
1389 "Return a new environment object eval whose bindings are the\n"
1390 "union of the bindings in the environments @var{local} and\n"
1391 "@var{imported}, with bindings from @var{local} taking\n"
1392 "precedence. Definitions made in eval are placed in @var{local}.\n"
1393 "Applying @code{environment-define} or\n"
1394 "@code{environment-undefine} to eval has the same effect as\n"
1395 "applying the procedure to @var{local}.\n"
1396 "Note that eval incorporates @var{local} and @var{imported} by\n"
1398 "If, after creating eval, the program changes the bindings of\n"
1399 "@var{local} or @var{imported}, those changes will be visible\n"
1401 "Since most Scheme evaluation takes place in eval environments,\n"
1402 "they transparently cache the bindings received from @var{local}\n"
1403 "and @var{imported}. Thus, the first time the program looks up\n"
1404 "a symbol in eval, eval may make calls to @var{local} or\n"
1405 "@var{imported} to find their bindings, but subsequent\n"
1406 "references to that symbol will be as fast as references to\n"
1407 "bindings in finite environments.\n"
1408 "In typical use, @var{local} will be a finite environment, and\n"
1409 "@var{imported} will be an import environment")
1410 #define FUNC_NAME s_scm_make_eval_environment
1413 struct eval_environment *body;
1415 SCM_ASSERT (SCM_ENVIRONMENT_P (local), local, SCM_ARG1, FUNC_NAME);
1416 SCM_ASSERT (SCM_ENVIRONMENT_P (imported), imported, SCM_ARG2, FUNC_NAME);
1418 body = scm_gc_malloc (sizeof (struct eval_environment), "eval environment");
1420 core_environments_preinit (&body->base);
1421 body->obarray = SCM_BOOL_F;
1422 body->imported = SCM_BOOL_F;
1423 body->imported_observer = SCM_BOOL_F;
1424 body->local = SCM_BOOL_F;
1425 body->local_observer = SCM_BOOL_F;
1427 env = scm_make_environment (body);
1429 core_environments_init (&body->base, &eval_environment_funcs);
1430 body->obarray = scm_c_make_hash_table (DEFAULT_OBARRAY_SIZE);
1431 body->imported = imported;
1432 body->imported_observer
1433 = SCM_ENVIRONMENT_OBSERVE (imported, eval_environment_observer, env, 1);
1434 body->local = local;
1435 body->local_observer
1436 = SCM_ENVIRONMENT_OBSERVE (local, eval_environment_observer, env, 1);
1443 SCM_DEFINE (scm_eval_environment_p, "eval-environment?", 1, 0, 0,
1445 "Return @code{#t} if object is an eval environment, or @code{#f}\n"
1447 #define FUNC_NAME s_scm_eval_environment_p
1449 return scm_from_bool (SCM_EVAL_ENVIRONMENT_P (object));
1454 SCM_DEFINE (scm_eval_environment_local, "eval-environment-local", 1, 0, 0,
1456 "Return the local environment of eval environment @var{env}.")
1457 #define FUNC_NAME s_scm_eval_environment_local
1459 SCM_ASSERT (SCM_EVAL_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
1461 return EVAL_ENVIRONMENT (env)->local;
1466 SCM_DEFINE (scm_eval_environment_set_local_x, "eval-environment-set-local!", 2, 0, 0,
1467 (SCM env, SCM local),
1468 "Change @var{env}'s local environment to @var{local}.")
1469 #define FUNC_NAME s_scm_eval_environment_set_local_x
1471 struct eval_environment *body;
1473 SCM_ASSERT (SCM_EVAL_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
1474 SCM_ASSERT (SCM_ENVIRONMENT_P (local), local, SCM_ARG2, FUNC_NAME);
1476 body = EVAL_ENVIRONMENT (env);
1478 obarray_remove_all (body->obarray);
1479 SCM_ENVIRONMENT_UNOBSERVE (body->local, body->local_observer);
1481 body->local = local;
1482 body->local_observer
1483 = SCM_ENVIRONMENT_OBSERVE (local, eval_environment_observer, env, 1);
1485 core_environments_broadcast (env);
1487 return SCM_UNSPECIFIED;
1492 SCM_DEFINE (scm_eval_environment_imported, "eval-environment-imported", 1, 0, 0,
1494 "Return the imported environment of eval environment @var{env}.")
1495 #define FUNC_NAME s_scm_eval_environment_imported
1497 SCM_ASSERT (SCM_EVAL_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
1499 return EVAL_ENVIRONMENT (env)->imported;
1504 SCM_DEFINE (scm_eval_environment_set_imported_x, "eval-environment-set-imported!", 2, 0, 0,
1505 (SCM env, SCM imported),
1506 "Change @var{env}'s imported environment to @var{imported}.")
1507 #define FUNC_NAME s_scm_eval_environment_set_imported_x
1509 struct eval_environment *body;
1511 SCM_ASSERT (SCM_EVAL_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
1512 SCM_ASSERT (SCM_ENVIRONMENT_P (imported), imported, SCM_ARG2, FUNC_NAME);
1514 body = EVAL_ENVIRONMENT (env);
1516 obarray_remove_all (body->obarray);
1517 SCM_ENVIRONMENT_UNOBSERVE (body->imported, body->imported_observer);
1519 body->imported = imported;
1520 body->imported_observer
1521 = SCM_ENVIRONMENT_OBSERVE (imported, eval_environment_observer, env, 1);
1523 core_environments_broadcast (env);
1525 return SCM_UNSPECIFIED;
1531 /* import environments
1533 * An import environment combines the bindings of a set of argument
1534 * environments, and checks for naming clashes.
1536 * Implementation: The import environment does no caching at all. For every
1537 * access, the list of imported environments is scanned.
1541 struct import_environment {
1542 struct core_environments_base base;
1545 SCM import_observers;
1551 #define IMPORT_ENVIRONMENT(env) \
1552 ((struct import_environment *) SCM_CELL_WORD_1 (env))
1556 /* Lookup will report one of the following distinct results:
1557 * a) <environment> if only environment binds the symbol.
1558 * b) (env-1 env-2 ...) for conflicting bindings in env-1, ...
1559 * c) SCM_UNDEFINED if there is no binding for the symbol.
1562 import_environment_lookup (SCM env, SCM sym)
1564 SCM imports = IMPORT_ENVIRONMENT (env)->imports;
1565 SCM result = SCM_UNDEFINED;
1568 for (l = imports; !scm_is_null (l); l = SCM_CDR (l))
1570 SCM imported = SCM_CAR (l);
1572 if (SCM_ENVIRONMENT_BOUND_P (imported, sym))
1574 if (SCM_UNBNDP (result))
1576 else if (scm_is_pair (result))
1577 result = scm_cons (imported, result);
1579 result = scm_cons2 (imported, result, SCM_EOL);
1583 if (scm_is_pair (result))
1584 return scm_reverse (result);
1591 import_environment_conflict (SCM env, SCM sym, SCM imports)
1593 SCM conflict_proc = IMPORT_ENVIRONMENT (env)->conflict_proc;
1594 SCM args = scm_cons2 (env, sym, scm_cons (imports, SCM_EOL));
1596 return scm_apply_0 (conflict_proc, args);
1601 import_environment_ref (SCM env, SCM sym)
1602 #define FUNC_NAME "import_environment_ref"
1604 SCM owner = import_environment_lookup (env, sym);
1606 if (SCM_UNBNDP (owner))
1608 return SCM_UNDEFINED;
1610 else if (scm_is_pair (owner))
1612 SCM resolve = import_environment_conflict (env, sym, owner);
1614 if (SCM_ENVIRONMENT_P (resolve))
1615 return SCM_ENVIRONMENT_REF (resolve, sym);
1617 return SCM_UNSPECIFIED;
1621 return SCM_ENVIRONMENT_REF (owner, sym);
1628 import_environment_folder (SCM extended_data, SCM symbol, SCM value, SCM tail)
1629 #define FUNC_NAME "import_environment_fold"
1631 SCM import_env = SCM_CAR (extended_data);
1632 SCM imported_env = SCM_CADR (extended_data);
1633 SCM owner = import_environment_lookup (import_env, symbol);
1634 SCM proc_as_nr = SCM_CADDR (extended_data);
1635 unsigned long int proc_as_ul = scm_to_ulong (proc_as_nr);
1636 scm_environment_folder proc = (scm_environment_folder) proc_as_ul;
1637 SCM data = SCM_CDDDR (extended_data);
1639 if (scm_is_pair (owner) && scm_is_eq (SCM_CAR (owner), imported_env))
1640 owner = import_environment_conflict (import_env, symbol, owner);
1642 if (SCM_ENVIRONMENT_P (owner))
1643 return (*proc) (data, symbol, value, tail);
1644 else /* unresolved conflict */
1645 return (*proc) (data, symbol, SCM_UNSPECIFIED, tail);
1651 import_environment_fold (SCM env, scm_environment_folder proc, SCM data, SCM init)
1653 SCM proc_as_nr = scm_from_ulong ((unsigned long) proc);
1657 for (l = IMPORT_ENVIRONMENT (env)->imports; !scm_is_null (l); l = SCM_CDR (l))
1659 SCM imported_env = SCM_CAR (l);
1660 SCM extended_data = scm_cons (env, scm_cons2 (imported_env, proc_as_nr, data));
1662 result = scm_c_environment_fold (imported_env, import_environment_folder, extended_data, result);
1670 import_environment_define (SCM env SCM_UNUSED,
1673 #define FUNC_NAME "import_environment_define"
1675 return SCM_ENVIRONMENT_BINDING_IMMUTABLE;
1681 import_environment_undefine (SCM env SCM_UNUSED,
1683 #define FUNC_NAME "import_environment_undefine"
1685 return SCM_ENVIRONMENT_BINDING_IMMUTABLE;
1691 import_environment_set_x (SCM env, SCM sym, SCM val)
1692 #define FUNC_NAME "import_environment_set_x"
1694 SCM owner = import_environment_lookup (env, sym);
1696 if (SCM_UNBNDP (owner))
1698 return SCM_UNDEFINED;
1700 else if (scm_is_pair (owner))
1702 SCM resolve = import_environment_conflict (env, sym, owner);
1704 if (SCM_ENVIRONMENT_P (resolve))
1705 return SCM_ENVIRONMENT_SET (resolve, sym, val);
1707 return SCM_ENVIRONMENT_LOCATION_IMMUTABLE;
1711 return SCM_ENVIRONMENT_SET (owner, sym, val);
1718 import_environment_cell (SCM env, SCM sym, int for_write)
1719 #define FUNC_NAME "import_environment_cell"
1721 SCM owner = import_environment_lookup (env, sym);
1723 if (SCM_UNBNDP (owner))
1725 return SCM_UNDEFINED;
1727 else if (scm_is_pair (owner))
1729 SCM resolve = import_environment_conflict (env, sym, owner);
1731 if (SCM_ENVIRONMENT_P (resolve))
1732 return SCM_ENVIRONMENT_CELL (resolve, sym, for_write);
1734 return SCM_ENVIRONMENT_LOCATION_NO_CELL;
1738 return SCM_ENVIRONMENT_CELL (owner, sym, for_write);
1745 import_environment_mark (SCM env)
1747 scm_gc_mark (IMPORT_ENVIRONMENT (env)->imports);
1748 scm_gc_mark (IMPORT_ENVIRONMENT (env)->import_observers);
1749 scm_gc_mark (IMPORT_ENVIRONMENT (env)->conflict_proc);
1750 return core_environments_mark (env);
1755 import_environment_free (SCM env)
1757 core_environments_finalize (env);
1758 scm_gc_free (IMPORT_ENVIRONMENT (env), sizeof (struct import_environment),
1759 "import environment");
1764 import_environment_print (SCM type, SCM port,
1765 scm_print_state *pstate SCM_UNUSED)
1767 SCM address = scm_from_size_t (SCM_UNPACK (type));
1768 SCM base16 = scm_number_to_string (address, scm_from_int (16));
1770 scm_puts ("#<import environment ", port);
1771 scm_display (base16, port);
1772 scm_puts (">", port);
1778 static struct scm_environment_funcs import_environment_funcs = {
1779 import_environment_ref,
1780 import_environment_fold,
1781 import_environment_define,
1782 import_environment_undefine,
1783 import_environment_set_x,
1784 import_environment_cell,
1785 core_environments_observe,
1786 core_environments_unobserve,
1787 import_environment_mark,
1788 import_environment_free,
1789 import_environment_print
1793 void *scm_type_import_environment = &import_environment_funcs;
1797 import_environment_observer (SCM caller SCM_UNUSED, SCM import_env)
1799 core_environments_broadcast (import_env);
1803 SCM_DEFINE (scm_make_import_environment, "make-import-environment", 2, 0, 0,
1804 (SCM imports, SCM conflict_proc),
1805 "Return a new environment @var{imp} whose bindings are the union\n"
1806 "of the bindings from the environments in @var{imports};\n"
1807 "@var{imports} must be a list of environments. That is,\n"
1808 "@var{imp} binds a symbol to a location when some element of\n"
1809 "@var{imports} does.\n"
1810 "If two different elements of @var{imports} have a binding for\n"
1811 "the same symbol, the @var{conflict-proc} is called with the\n"
1812 "following parameters: the import environment, the symbol and\n"
1813 "the list of the imported environments that bind the symbol.\n"
1814 "If the @var{conflict-proc} returns an environment @var{env},\n"
1815 "the conflict is considered as resolved and the binding from\n"
1816 "@var{env} is used. If the @var{conflict-proc} returns some\n"
1817 "non-environment object, the conflict is considered unresolved\n"
1818 "and the symbol is treated as unspecified in the import\n"
1820 "The checking for conflicts may be performed lazily, i. e. at\n"
1821 "the moment when a value or binding for a certain symbol is\n"
1822 "requested instead of the moment when the environment is\n"
1823 "created or the bindings of the imports change.\n"
1824 "All bindings in @var{imp} are immutable. If you apply\n"
1825 "@code{environment-define} or @code{environment-undefine} to\n"
1826 "@var{imp}, Guile will signal an\n"
1827 " @code{environment:immutable-binding} error. However,\n"
1828 "notice that the set of bindings in @var{imp} may still change,\n"
1829 "if one of its imported environments changes.")
1830 #define FUNC_NAME s_scm_make_import_environment
1832 size_t size = sizeof (struct import_environment);
1833 struct import_environment *body = scm_gc_malloc (size, "import environment");
1836 core_environments_preinit (&body->base);
1837 body->imports = SCM_BOOL_F;
1838 body->import_observers = SCM_BOOL_F;
1839 body->conflict_proc = SCM_BOOL_F;
1841 env = scm_make_environment (body);
1843 core_environments_init (&body->base, &import_environment_funcs);
1844 body->imports = SCM_EOL;
1845 body->import_observers = SCM_EOL;
1846 body->conflict_proc = conflict_proc;
1848 scm_import_environment_set_imports_x (env, imports);
1855 SCM_DEFINE (scm_import_environment_p, "import-environment?", 1, 0, 0,
1857 "Return @code{#t} if object is an import environment, or\n"
1858 "@code{#f} otherwise.")
1859 #define FUNC_NAME s_scm_import_environment_p
1861 return scm_from_bool (SCM_IMPORT_ENVIRONMENT_P (object));
1866 SCM_DEFINE (scm_import_environment_imports, "import-environment-imports", 1, 0, 0,
1868 "Return the list of environments imported by the import\n"
1869 "environment @var{env}.")
1870 #define FUNC_NAME s_scm_import_environment_imports
1872 SCM_ASSERT (SCM_IMPORT_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
1874 return IMPORT_ENVIRONMENT (env)->imports;
1879 SCM_DEFINE (scm_import_environment_set_imports_x, "import-environment-set-imports!", 2, 0, 0,
1880 (SCM env, SCM imports),
1881 "Change @var{env}'s list of imported environments to\n"
1882 "@var{imports}, and check for conflicts.")
1883 #define FUNC_NAME s_scm_import_environment_set_imports_x
1885 struct import_environment *body = IMPORT_ENVIRONMENT (env);
1886 SCM import_observers = SCM_EOL;
1889 SCM_ASSERT (SCM_IMPORT_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
1890 for (l = imports; scm_is_pair (l); l = SCM_CDR (l))
1892 SCM obj = SCM_CAR (l);
1893 SCM_ASSERT (SCM_ENVIRONMENT_P (obj), imports, SCM_ARG2, FUNC_NAME);
1895 SCM_ASSERT (scm_is_null (l), imports, SCM_ARG2, FUNC_NAME);
1897 for (l = body->import_observers; !scm_is_null (l); l = SCM_CDR (l))
1899 SCM obs = SCM_CAR (l);
1900 SCM_ENVIRONMENT_UNOBSERVE (env, obs);
1903 for (l = imports; !scm_is_null (l); l = SCM_CDR (l))
1905 SCM imp = SCM_CAR (l);
1906 SCM obs = SCM_ENVIRONMENT_OBSERVE (imp, import_environment_observer, env, 1);
1907 import_observers = scm_cons (obs, import_observers);
1910 body->imports = imports;
1911 body->import_observers = import_observers;
1913 return SCM_UNSPECIFIED;
1919 /* export environments
1921 * An export environment restricts an environment to a specified set of
1924 * Implementation: The export environment does no caching at all. For every
1925 * access, the signature is scanned. The signature that is stored internally
1926 * is an alist of pairs (symbol . (mutability)).
1930 struct export_environment {
1931 struct core_environments_base base;
1934 SCM private_observer;
1940 #define EXPORT_ENVIRONMENT(env) \
1941 ((struct export_environment *) SCM_CELL_WORD_1 (env))
1944 SCM_SYMBOL (symbol_immutable_location, "immutable-location");
1945 SCM_SYMBOL (symbol_mutable_location, "mutable-location");
1950 export_environment_ref (SCM env, SCM sym)
1951 #define FUNC_NAME "export_environment_ref"
1953 struct export_environment *body = EXPORT_ENVIRONMENT (env);
1954 SCM entry = scm_assq (sym, body->signature);
1956 if (scm_is_false (entry))
1957 return SCM_UNDEFINED;
1959 return SCM_ENVIRONMENT_REF (body->private, sym);
1965 export_environment_fold (SCM env, scm_environment_folder proc, SCM data, SCM init)
1967 struct export_environment *body = EXPORT_ENVIRONMENT (env);
1971 for (l = body->signature; !scm_is_null (l); l = SCM_CDR (l))
1973 SCM symbol = SCM_CAR (l);
1974 SCM value = SCM_ENVIRONMENT_REF (body->private, symbol);
1975 if (!SCM_UNBNDP (value))
1976 result = (*proc) (data, symbol, value, result);
1983 export_environment_define (SCM env SCM_UNUSED,
1986 #define FUNC_NAME "export_environment_define"
1988 return SCM_ENVIRONMENT_BINDING_IMMUTABLE;
1994 export_environment_undefine (SCM env SCM_UNUSED, SCM sym SCM_UNUSED)
1995 #define FUNC_NAME "export_environment_undefine"
1997 return SCM_ENVIRONMENT_BINDING_IMMUTABLE;
2003 export_environment_set_x (SCM env, SCM sym, SCM val)
2004 #define FUNC_NAME "export_environment_set_x"
2006 struct export_environment *body = EXPORT_ENVIRONMENT (env);
2007 SCM entry = scm_assq (sym, body->signature);
2009 if (scm_is_false (entry))
2011 return SCM_UNDEFINED;
2015 if (scm_is_eq (SCM_CADR (entry), symbol_mutable_location))
2016 return SCM_ENVIRONMENT_SET (body->private, sym, val);
2018 return SCM_ENVIRONMENT_LOCATION_IMMUTABLE;
2025 export_environment_cell (SCM env, SCM sym, int for_write)
2026 #define FUNC_NAME "export_environment_cell"
2028 struct export_environment *body = EXPORT_ENVIRONMENT (env);
2029 SCM entry = scm_assq (sym, body->signature);
2031 if (scm_is_false (entry))
2033 return SCM_UNDEFINED;
2037 if (!for_write || scm_is_eq (SCM_CADR (entry), symbol_mutable_location))
2038 return SCM_ENVIRONMENT_CELL (body->private, sym, for_write);
2040 return SCM_ENVIRONMENT_LOCATION_IMMUTABLE;
2047 export_environment_mark (SCM env)
2049 struct export_environment *body = EXPORT_ENVIRONMENT (env);
2051 scm_gc_mark (body->private);
2052 scm_gc_mark (body->private_observer);
2053 scm_gc_mark (body->signature);
2055 return core_environments_mark (env);
2060 export_environment_free (SCM env)
2062 core_environments_finalize (env);
2063 scm_gc_free (EXPORT_ENVIRONMENT (env), sizeof (struct export_environment),
2064 "export environment");
2069 export_environment_print (SCM type, SCM port,
2070 scm_print_state *pstate SCM_UNUSED)
2072 SCM address = scm_from_size_t (SCM_UNPACK (type));
2073 SCM base16 = scm_number_to_string (address, scm_from_int (16));
2075 scm_puts ("#<export environment ", port);
2076 scm_display (base16, port);
2077 scm_puts (">", port);
2083 static struct scm_environment_funcs export_environment_funcs = {
2084 export_environment_ref,
2085 export_environment_fold,
2086 export_environment_define,
2087 export_environment_undefine,
2088 export_environment_set_x,
2089 export_environment_cell,
2090 core_environments_observe,
2091 core_environments_unobserve,
2092 export_environment_mark,
2093 export_environment_free,
2094 export_environment_print
2098 void *scm_type_export_environment = &export_environment_funcs;
2102 export_environment_observer (SCM caller SCM_UNUSED, SCM export_env)
2104 core_environments_broadcast (export_env);
2108 SCM_DEFINE (scm_make_export_environment, "make-export-environment", 2, 0, 0,
2109 (SCM private, SCM signature),
2110 "Return a new environment @var{exp} containing only those\n"
2111 "bindings in private whose symbols are present in\n"
2112 "@var{signature}. The @var{private} argument must be an\n"
2114 "The environment @var{exp} binds symbol to location when\n"
2115 "@var{env} does, and symbol is exported by @var{signature}.\n\n"
2116 "@var{signature} is a list specifying which of the bindings in\n"
2117 "@var{private} should be visible in @var{exp}. Each element of\n"
2118 "@var{signature} should be a list of the form:\n"
2119 " (symbol attribute ...)\n"
2120 "where each attribute is one of the following:\n"
2122 "@item the symbol @code{mutable-location}\n"
2123 " @var{exp} should treat the\n"
2124 " location bound to symbol as mutable. That is, @var{exp}\n"
2125 " will pass calls to @code{environment-set!} or\n"
2126 " @code{environment-cell} directly through to private.\n"
2127 "@item the symbol @code{immutable-location}\n"
2128 " @var{exp} should treat\n"
2129 " the location bound to symbol as immutable. If the program\n"
2130 " applies @code{environment-set!} to @var{exp} and symbol, or\n"
2131 " calls @code{environment-cell} to obtain a writable value\n"
2132 " cell, @code{environment-set!} will signal an\n"
2133 " @code{environment:immutable-location} error. Note that, even\n"
2134 " if an export environment treats a location as immutable, the\n"
2135 " underlying environment may treat it as mutable, so its\n"
2136 " value may change.\n"
2138 "It is an error for an element of signature to specify both\n"
2139 "@code{mutable-location} and @code{immutable-location}. If\n"
2140 "neither is specified, @code{immutable-location} is assumed.\n\n"
2141 "As a special case, if an element of signature is a lone\n"
2142 "symbol @var{sym}, it is equivalent to an element of the form\n"
2144 "All bindings in @var{exp} are immutable. If you apply\n"
2145 "@code{environment-define} or @code{environment-undefine} to\n"
2146 "@var{exp}, Guile will signal an\n"
2147 "@code{environment:immutable-binding} error. However,\n"
2148 "notice that the set of bindings in @var{exp} may still change,\n"
2149 "if the bindings in private change.")
2150 #define FUNC_NAME s_scm_make_export_environment
2153 struct export_environment *body;
2156 SCM_ASSERT (SCM_ENVIRONMENT_P (private), private, SCM_ARG1, FUNC_NAME);
2158 size = sizeof (struct export_environment);
2159 body = scm_gc_malloc (size, "export environment");
2161 core_environments_preinit (&body->base);
2162 body->private = SCM_BOOL_F;
2163 body->private_observer = SCM_BOOL_F;
2164 body->signature = SCM_BOOL_F;
2166 env = scm_make_environment (body);
2168 core_environments_init (&body->base, &export_environment_funcs);
2169 body->private = private;
2170 body->private_observer
2171 = SCM_ENVIRONMENT_OBSERVE (private, export_environment_observer, env, 1);
2172 body->signature = SCM_EOL;
2174 scm_export_environment_set_signature_x (env, signature);
2181 SCM_DEFINE (scm_export_environment_p, "export-environment?", 1, 0, 0,
2183 "Return @code{#t} if object is an export environment, or\n"
2184 "@code{#f} otherwise.")
2185 #define FUNC_NAME s_scm_export_environment_p
2187 return scm_from_bool (SCM_EXPORT_ENVIRONMENT_P (object));
2192 SCM_DEFINE (scm_export_environment_private, "export-environment-private", 1, 0, 0,
2194 "Return the private environment of export environment @var{env}.")
2195 #define FUNC_NAME s_scm_export_environment_private
2197 SCM_ASSERT (SCM_EXPORT_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
2199 return EXPORT_ENVIRONMENT (env)->private;
2204 SCM_DEFINE (scm_export_environment_set_private_x, "export-environment-set-private!", 2, 0, 0,
2205 (SCM env, SCM private),
2206 "Change the private environment of export environment @var{env}.")
2207 #define FUNC_NAME s_scm_export_environment_set_private_x
2209 struct export_environment *body;
2211 SCM_ASSERT (SCM_EXPORT_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
2212 SCM_ASSERT (SCM_ENVIRONMENT_P (private), private, SCM_ARG2, FUNC_NAME);
2214 body = EXPORT_ENVIRONMENT (env);
2215 SCM_ENVIRONMENT_UNOBSERVE (private, body->private_observer);
2217 body->private = private;
2218 body->private_observer
2219 = SCM_ENVIRONMENT_OBSERVE (private, export_environment_observer, env, 1);
2221 return SCM_UNSPECIFIED;
2226 SCM_DEFINE (scm_export_environment_signature, "export-environment-signature", 1, 0, 0,
2228 "Return the signature of export environment @var{env}.")
2229 #define FUNC_NAME s_scm_export_environment_signature
2231 SCM_ASSERT (SCM_EXPORT_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
2233 return EXPORT_ENVIRONMENT (env)->signature;
2239 export_environment_parse_signature (SCM signature, const char* caller)
2241 SCM result = SCM_EOL;
2244 for (l = signature; scm_is_pair (l); l = SCM_CDR (l))
2246 SCM entry = SCM_CAR (l);
2248 if (scm_is_symbol (entry))
2250 SCM new_entry = scm_cons2 (entry, symbol_immutable_location, SCM_EOL);
2251 result = scm_cons (new_entry, result);
2262 SCM_ASSERT (scm_is_pair (entry), entry, SCM_ARGn, caller);
2263 SCM_ASSERT (scm_is_symbol (SCM_CAR (entry)), entry, SCM_ARGn, caller);
2265 sym = SCM_CAR (entry);
2267 for (l2 = SCM_CDR (entry); scm_is_pair (l2); l2 = SCM_CDR (l2))
2269 SCM attribute = SCM_CAR (l2);
2270 if (scm_is_eq (attribute, symbol_immutable_location))
2272 else if (scm_is_eq (attribute, symbol_mutable_location))
2275 SCM_ASSERT (0, entry, SCM_ARGn, caller);
2277 SCM_ASSERT (scm_is_null (l2), entry, SCM_ARGn, caller);
2278 SCM_ASSERT (!mutable || !immutable, entry, SCM_ARGn, caller);
2280 if (!mutable && !immutable)
2283 mutability = mutable ? symbol_mutable_location : symbol_immutable_location;
2284 new_entry = scm_cons2 (sym, mutability, SCM_EOL);
2285 result = scm_cons (new_entry, result);
2288 SCM_ASSERT (scm_is_null (l), signature, SCM_ARGn, caller);
2290 /* Dirk:FIXME:: Now we know that signature is syntactically correct. There
2291 * are, however, no checks for symbols entered twice with contradicting
2292 * mutabilities. It would be nice, to implement this test, to be able to
2293 * call the sort functions conveniently from C.
2296 return scm_reverse (result);
2300 SCM_DEFINE (scm_export_environment_set_signature_x, "export-environment-set-signature!", 2, 0, 0,
2301 (SCM env, SCM signature),
2302 "Change the signature of export environment @var{env}.")
2303 #define FUNC_NAME s_scm_export_environment_set_signature_x
2307 SCM_ASSERT (SCM_EXPORT_ENVIRONMENT_P (env), env, SCM_ARG1, FUNC_NAME);
2308 parsed_sig = export_environment_parse_signature (signature, FUNC_NAME);
2310 EXPORT_ENVIRONMENT (env)->signature = parsed_sig;
2312 return SCM_UNSPECIFIED;
2319 scm_environments_prehistory ()
2321 /* create environment smob */
2322 scm_tc16_environment = scm_make_smob_type ("environment", 0);
2323 scm_set_smob_mark (scm_tc16_environment, environment_mark);
2324 scm_set_smob_free (scm_tc16_environment, environment_free);
2325 scm_set_smob_print (scm_tc16_environment, environment_print);
2327 /* create observer smob */
2328 scm_tc16_observer = scm_make_smob_type ("observer", 0);
2329 scm_set_smob_mark (scm_tc16_observer, observer_mark);
2330 scm_set_smob_print (scm_tc16_observer, observer_print);
2332 /* create system environment */
2333 scm_system_environment = scm_make_leaf_environment ();
2334 scm_permanent_object (scm_system_environment);
2339 scm_init_environments ()
2341 #include "libguile/environments.x"