(scm_internal_with_fluids): Deprecated.
[bpt/guile.git] / libguile / modules.c
CommitLineData
152abe96 1/* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
1ffa265b
MD
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program 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
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
6e8d25a6
GB
41
42/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
1ffa265b
MD
45\f
46
a0599745 47#include "libguile/_scm.h"
1ffa265b 48
a0599745 49#include "libguile/eval.h"
fb43bf74 50#include "libguile/smob.h"
a0599745 51#include "libguile/procprop.h"
152abe96
MD
52#include "libguile/vectors.h"
53#include "libguile/hashtab.h"
54#include "libguile/struct.h"
55#include "libguile/variable.h"
7f763132 56#include "libguile/fluids.h"
1ffa265b 57
a0599745 58#include "libguile/modules.h"
1ffa265b 59
86d31dfe 60int scm_module_system_booted_p = 0;
e3365c07
MD
61
62SCM scm_module_tag;
63
86d31dfe 64static SCM the_root_module_var;
c15c33ee 65static SCM root_module_lookup_closure;
281004cc
MD
66
67SCM
68scm_the_root_module ()
69{
86d31dfe
MV
70 if (scm_module_system_booted_p)
71 return SCM_VARIABLE_REF (the_root_module_var);
72 else
73 return SCM_BOOL_F;
281004cc
MD
74}
75
1ffa265b
MD
76static SCM the_module;
77
55000e5f
MV
78SCM_DEFINE (scm_current_module, "current-module", 0, 0, 0,
79 (),
80 "Return the current module.")
81#define FUNC_NAME s_scm_current_module
1ffa265b 82{
55000e5f 83 return scm_fluid_ref (the_module);
1ffa265b 84}
55000e5f 85#undef FUNC_NAME
1ffa265b 86
86d31dfe 87static void scm_post_boot_init_modules (void);
1ffa265b 88
55000e5f
MV
89SCM_DEFINE (scm_set_current_module, "set-current-module", 1, 0, 0,
90 (SCM module),
91 "Set the current module to @var{module} and return"
92 "the previous current module.")
93#define FUNC_NAME s_scm_set_current_module
1ffa265b 94{
55000e5f
MV
95 SCM old;
96
86d31dfe
MV
97 if (!scm_module_system_booted_p)
98 scm_post_boot_init_modules ();
99
100 SCM_VALIDATE_MODULE (SCM_ARG1, module);
55000e5f
MV
101
102 old = scm_current_module ();
103 scm_fluid_set_x (the_module, module);
104
105#if SCM_DEBUG_DEPRECATED == 0
86d31dfe 106 scm_fluid_set_x (SCM_VARIABLE_REF (scm_top_level_lookup_closure_var),
55000e5f 107 scm_current_module_lookup_closure ());
86d31dfe 108 scm_fluid_set_x (SCM_VARIABLE_REF (scm_system_transformer),
55000e5f
MV
109 scm_current_module_transformer ());
110#endif
111
1ffa265b
MD
112 return old;
113}
55000e5f 114#undef FUNC_NAME
1ffa265b 115
e3365c07
MD
116SCM_DEFINE (scm_interaction_environment, "interaction-environment", 0, 0, 0,
117 (),
1e6808ea
MG
118 "Return a specifier for the environment that contains\n"
119 "implementation--defined bindings, typically a superset of those\n"
120 "listed in the report. The intent is that this procedure will\n"
121 "return the environment in which the implementation would\n"
122 "evaluate expressions dynamically typed by the user.")
e3365c07
MD
123#define FUNC_NAME s_scm_interaction_environment
124{
aa767bc5 125 return scm_current_module ();
e3365c07
MD
126}
127#undef FUNC_NAME
128
1ffa265b
MD
129SCM_SYMBOL (scm_sym_app, "app");
130SCM_SYMBOL (scm_sym_modules, "modules");
131static SCM module_prefix;
132
133static SCM
134scm_module_full_name (SCM name)
135{
54778cd3 136 if (SCM_EQ_P (SCM_CAR (name), scm_sym_app))
1ffa265b
MD
137 return name;
138 else
139 return scm_append (SCM_LIST2 (module_prefix, name));
140}
141
86d31dfe
MV
142static SCM make_modules_in_var;
143static SCM beautify_user_module_x_var;
1ffa265b
MD
144
145SCM
146scm_make_module (SCM name)
147{
86d31dfe 148 return scm_apply (SCM_VARIABLE_REF (make_modules_in_var),
281004cc 149 SCM_LIST2 (scm_the_root_module (),
1ffa265b
MD
150 scm_module_full_name (name)),
151 SCM_EOL);
152}
153
281004cc
MD
154SCM
155scm_ensure_user_module (SCM module)
156{
86d31dfe
MV
157 scm_apply (SCM_VARIABLE_REF (beautify_user_module_x_var),
158 SCM_LIST1 (module), SCM_EOL);
281004cc
MD
159 return SCM_UNSPECIFIED;
160}
161
1ffa265b
MD
162SCM
163scm_module_lookup_closure (SCM module)
164{
86d31dfe
MV
165 if (module == SCM_BOOL_F)
166 return SCM_BOOL_F;
167 else
168 return SCM_MODULE_EVAL_CLOSURE (module);
1ffa265b
MD
169}
170
9e57344b
MV
171SCM
172scm_current_module_lookup_closure ()
173{
174 if (scm_module_system_booted_p)
175 return scm_module_lookup_closure (scm_current_module ());
176 else
177 return SCM_BOOL_F;
178}
179
55000e5f
MV
180SCM
181scm_module_transformer (SCM module)
182{
86d31dfe
MV
183 if (module == SCM_BOOL_F)
184 return SCM_BOOL_F;
185 else
186 return SCM_MODULE_TRANSFORMER (module);
55000e5f
MV
187}
188
189SCM
190scm_current_module_transformer ()
191{
192 if (scm_module_system_booted_p)
193 return scm_module_transformer (scm_current_module ());
194 else
195 return SCM_BOOL_F;
196}
197
86d31dfe 198static SCM resolve_module_var;
90184345
MD
199
200SCM
201scm_resolve_module (SCM name)
202{
86d31dfe
MV
203 return scm_apply (SCM_VARIABLE_REF (resolve_module_var),
204 SCM_LIST1 (name), SCM_EOL);
90184345
MD
205}
206
86d31dfe 207static SCM try_module_autoload_var;
281004cc
MD
208
209SCM
210scm_load_scheme_module (SCM name)
211{
86d31dfe
MV
212 return scm_apply (SCM_VARIABLE_REF (try_module_autoload_var),
213 SCM_LIST1 (name), SCM_EOL);
281004cc
MD
214}
215
e3365c07 216/* Environments */
d164a5af
MD
217
218SCM
6e8d25a6 219scm_top_level_env (SCM thunk)
d164a5af
MD
220{
221 if (SCM_IMP (thunk))
222 return SCM_EOL;
223 else
224 return scm_cons (thunk, SCM_EOL);
225}
226
227SCM
228scm_env_top_level (SCM env)
229{
230 while (SCM_NIMP (env))
231 {
232 if (!SCM_CONSP (SCM_CAR (env))
233 && SCM_NFALSEP (scm_procedure_p (SCM_CAR (env))))
c15c33ee 234 return SCM_CAR (env);
d164a5af
MD
235 env = SCM_CDR (env);
236 }
237 return SCM_BOOL_F;
238}
239
86d31dfe
MV
240SCM_SYMBOL (sym_module, "module");
241
242SCM
243scm_lookup_closure_module (SCM proc)
244{
245 if (SCM_FALSEP (proc))
246 return scm_the_root_module ();
247 else if (SCM_EVAL_CLOSURE_P (proc))
248 return SCM_PACK (SCM_SMOB_DATA (proc));
249 else
250 {
251 SCM mod = scm_procedure_property (proc, sym_module);
252 if (mod == SCM_BOOL_F)
253 mod = scm_the_root_module ();
254 return mod;
255 }
256}
257
258SCM
259scm_env_module (SCM env)
260{
261 return scm_lookup_closure_module (scm_env_top_level (env));
262}
263
d164a5af
MD
264
265SCM_SYMBOL (scm_sym_system_module, "system-module");
266
267SCM
268scm_system_module_env_p (SCM env)
269{
270 SCM proc = scm_env_top_level (env);
271 if (SCM_FALSEP (proc))
c15c33ee 272 proc = root_module_lookup_closure;
d164a5af
MD
273 return ((SCM_NFALSEP (scm_procedure_property (proc,
274 scm_sym_system_module)))
275 ? SCM_BOOL_T
276 : SCM_BOOL_F);
277}
278
152abe96
MD
279/*
280 * C level implementation of the standard eval closure
281 *
282 * This increases loading speed substantially.
283 * The code will be replaced by the low-level environments in next release.
284 */
285
86d31dfe 286static SCM module_make_local_var_x_var;
152abe96
MD
287
288static SCM
289module_variable (SCM module, SCM sym)
290{
291 /* 1. Check module obarray */
e3365c07 292 SCM b = scm_hashq_ref (SCM_MODULE_OBARRAY (module), sym, SCM_UNDEFINED);
152abe96
MD
293 if (SCM_VARIABLEP (b))
294 return b;
295 {
e3365c07 296 SCM binder = SCM_MODULE_BINDER (module);
152abe96
MD
297 if (SCM_NFALSEP (binder))
298 /* 2. Custom binder */
299 {
300 b = scm_apply (binder,
301 SCM_LIST3 (module, sym, SCM_BOOL_F),
302 SCM_EOL);
303 if (SCM_NFALSEP (b))
304 return b;
305 }
306 }
307 {
308 /* 3. Search the use list */
e3365c07 309 SCM uses = SCM_MODULE_USES (module);
152abe96
MD
310 while (SCM_CONSP (uses))
311 {
312 b = module_variable (SCM_CAR (uses), sym);
313 if (SCM_NFALSEP (b))
314 return b;
315 uses = SCM_CDR (uses);
316 }
317 return SCM_BOOL_F;
318 }
319}
320
e841c3e0 321scm_bits_t scm_tc16_eval_closure;
152abe96 322
86d31dfe
MV
323#define SCM_F_EVAL_CLOSURE_INTERFACE (1<<16)
324#define SCM_EVAL_CLOSURE_INTERFACE_P(e) \
325 (SCM_CELL_WORD_0 (e) & SCM_F_EVAL_CLOSURE_INTERFACE)
326
fb43bf74
KN
327/* NOTE: This function may be called by a smob application
328 or from another C function directly. */
329SCM
330scm_eval_closure_lookup (SCM eclo, SCM sym, SCM definep)
152abe96 331{
fb43bf74 332 SCM module = SCM_PACK (SCM_SMOB_DATA (eclo));
152abe96 333 if (SCM_NFALSEP (definep))
86d31dfe
MV
334 {
335 if (SCM_EVAL_CLOSURE_INTERFACE_P (eclo))
336 return SCM_BOOL_F;
337 return scm_apply (SCM_VARIABLE_REF (module_make_local_var_x_var),
338 SCM_LIST2 (module, sym),
339 SCM_EOL);
340 }
152abe96
MD
341 else
342 return module_variable (module, sym);
343}
344
345SCM_DEFINE (scm_standard_eval_closure, "standard-eval-closure", 1, 0, 0,
346 (SCM module),
84526793 347 "Return an eval closure for the module @var{module}.")
152abe96
MD
348#define FUNC_NAME s_scm_standard_eval_closure
349{
e841c3e0 350 SCM_RETURN_NEWSMOB (scm_tc16_eval_closure, SCM_UNPACK (module));
152abe96
MD
351}
352#undef FUNC_NAME
353
86d31dfe
MV
354SCM_DEFINE (scm_standard_interface_eval_closure,
355 "standard-interface-eval-closure", 1, 0, 0,
356 (SCM module),
357 "Return a interface eval closure for the module @var{module}. "
358 "Such a closure does not allow new bindings to be added.")
359#define FUNC_NAME s_scm_standard_interface_eval_closure
360{
361 SCM_RETURN_NEWSMOB (scm_tc16_eval_closure | SCM_F_EVAL_CLOSURE_INTERFACE,
362 SCM_UNPACK (module));
363}
364#undef FUNC_NAME
365
366/* scm_sym2var
367 *
368 * looks up the variable bound to SYM according to PROC. PROC should be
369 * a `eval closure' of some module.
370 *
371 * When no binding exists, and DEFINEP is true, create a new binding
372 * with a initial value of SCM_UNDEFINED. Return `#f' when DEFINEP as
373 * false and no binding exists.
374 *
375 * When PROC is `#f', it is ignored and the binding is searched for in
376 * the scm_pre_modules_obarray (a `eq' hash table).
377 */
378
379SCM scm_pre_modules_obarray;
380
381SCM
382scm_sym2var (SCM sym, SCM proc, SCM definep)
383#define FUNC_NAME "scm_sym2var"
384{
385 SCM var;
386
387 if (SCM_NIMP (proc))
388 {
389 if (SCM_EVAL_CLOSURE_P (proc))
390 {
391 /* Bypass evaluator in the standard case. */
392 var = scm_eval_closure_lookup (proc, sym, definep);
393 }
394 else
395 var = scm_apply (proc, sym, scm_cons (definep, scm_listofnull));
396 }
397 else
398 {
399 SCM handle;
400
401 if (definep == SCM_BOOL_F)
402 var = scm_hashq_ref (scm_pre_modules_obarray, sym, SCM_BOOL_F);
403 else
404 {
405 handle = scm_hashq_create_handle_x (scm_pre_modules_obarray,
406 sym, SCM_BOOL_F);
407 var = SCM_CDR (handle);
408 if (var == SCM_BOOL_F)
409 {
410 var = scm_make_variable (SCM_UNDEFINED);
411#if SCM_ENABLE_VCELLS
412 scm_variable_set_name_hint (var, sym);
413#endif
414 SCM_SETCDR (handle, var);
415 }
416 }
417 }
418
419 if (var != SCM_BOOL_F && !SCM_VARIABLEP (var))
420 SCM_MISC_ERROR ("~S is not bound to a variable", SCM_LIST1 (sym));
421
422 return var;
423}
424#undef FUNC_NAME
425
426SCM
427scm_c_module_lookup (SCM module, const char *name)
428{
429 return scm_module_lookup (module, scm_str2symbol (name));
430}
431
432SCM
433scm_module_lookup (SCM module, SCM sym)
434#define FUNC_NAME "module-lookup"
435{
436 SCM var;
437 SCM_VALIDATE_MODULE (1, module);
438
439 var = scm_sym2var (sym, scm_module_lookup_closure (module), SCM_BOOL_F);
440 if (SCM_FALSEP (var))
441 SCM_MISC_ERROR ("unbound variable: ~S", SCM_LIST1 (sym));
442 return var;
443}
444#undef FUNC_NAME
445
446SCM
447scm_c_lookup (const char *name)
448{
449 return scm_lookup (scm_str2symbol (name));
450}
451
452SCM
453scm_lookup (SCM sym)
454{
455 SCM var =
456 scm_sym2var (sym, scm_current_module_lookup_closure (), SCM_BOOL_F);
457 if (SCM_FALSEP (var))
458 scm_misc_error ("scm_lookup", "unbound variable: ~S", SCM_LIST1 (sym));
459 return var;
460}
461
462SCM
463scm_c_module_define (SCM module, const char *name, SCM value)
464{
465 return scm_module_define (module, scm_str2symbol (name), value);
466}
467
468SCM
469scm_module_define (SCM module, SCM sym, SCM value)
470#define FUNC_NAME "module-define"
471{
472 SCM var;
473 SCM_VALIDATE_MODULE (1, module);
474
475 var = scm_sym2var (sym, scm_module_lookup_closure (module), SCM_BOOL_T);
476 SCM_VARIABLE_SET (var, value);
477 return var;
478}
479#undef FUNC_NAME
480
481SCM
482scm_c_define (const char *name, SCM value)
483{
484 return scm_define (scm_str2symbol (name), value);
485}
486
487SCM
488scm_define (SCM sym, SCM value)
489{
490 SCM var =
491 scm_sym2var (sym, scm_current_module_lookup_closure (), SCM_BOOL_T);
492 SCM_VARIABLE_SET (var, value);
493 return var;
494}
495
496SCM
497scm_module_reverse_lookup (SCM module, SCM variable)
498#define FUNC_NAME "module-reverse-lookup"
499{
500 SCM obarray;
501 int i, n;
502
503 if (module == SCM_BOOL_F)
504 obarray = scm_pre_modules_obarray;
505 else
506 {
507 SCM_VALIDATE_MODULE (1, module);
508 obarray = SCM_MODULE_OBARRAY (module);
509 }
510
511 /* XXX - We do not use scm_hash_fold here to avoid searching the
512 whole obarray. We should have a scm_hash_find procedure. */
513
514 n = SCM_VECTOR_LENGTH (obarray);
515 for (i = 0; i < n; ++i)
516 {
517 SCM ls = SCM_VELTS (obarray)[i], handle;
518 while (!SCM_NULLP (ls))
519 {
520 handle = SCM_CAR (ls);
521 if (SCM_CDR (handle) == variable)
522 return SCM_CAR (handle);
523 ls = SCM_CDR (ls);
524 }
525 }
526
527 /* Try the `uses' list.
528 */
529 {
530 SCM uses = SCM_MODULE_USES (module);
531 while (SCM_CONSP (uses))
532 {
533 SCM sym = scm_module_reverse_lookup (SCM_CAR (uses), variable);
534 if (sym != SCM_BOOL_F)
535 return sym;
536 uses = SCM_CDR (uses);
537 }
538 }
539
540 return SCM_BOOL_F;
541}
542#undef FUNC_NAME
543
544SCM_DEFINE (scm_get_pre_modules_obarray, "%get-pre-modules-obarray", 0, 0, 0,
545 (),
546 "Return the obarray that is used for all new bindings before "
547 "the module system is booted. The first call to "
548 "@code{set-current-module} will boot the module system.")
549#define FUNC_NAME s_scm_get_pre_modules_obarray
550{
551 return scm_pre_modules_obarray;
552}
553#undef FUNC_NAME
554
555void
556scm_modules_prehistory ()
557{
558 scm_pre_modules_obarray
559 = scm_permanent_object (scm_c_make_hash_table (2001));
560}
561
1ffa265b
MD
562void
563scm_init_modules ()
564{
8dc9439f 565#ifndef SCM_MAGIC_SNARFER
a0599745 566#include "libguile/modules.x"
8dc9439f 567#endif
86d31dfe
MV
568 module_make_local_var_x_var = scm_c_define ("module-make-local-var!",
569 SCM_UNDEFINED);
e841c3e0
KN
570 scm_tc16_eval_closure = scm_make_smob_type ("eval-closure", 0);
571 scm_set_smob_mark (scm_tc16_eval_closure, scm_markcdr);
572 scm_set_smob_apply (scm_tc16_eval_closure, scm_eval_closure_lookup, 2, 0, 0);
55000e5f
MV
573
574 the_module = scm_permanent_object (scm_make_fluid ());
1ffa265b
MD
575}
576
86d31dfe 577static void
1ffa265b
MD
578scm_post_boot_init_modules ()
579{
86d31dfe
MV
580#define PERM(x) scm_permanent_object(x)
581
582 SCM module_type = SCM_VARIABLE_REF (scm_c_lookup ("module-type"));
583 scm_module_tag = (SCM_CELL_WORD_1 (module_type) + scm_tc3_cons_gloc);
584 module_prefix = PERM (SCM_LIST2 (scm_sym_app, scm_sym_modules));
585 make_modules_in_var = PERM (scm_c_lookup ("make-modules-in"));
586 beautify_user_module_x_var = PERM (scm_c_lookup ("beautify-user-module!"));
587 the_root_module_var = PERM (scm_c_lookup ("the-root-module"));
588 root_module_lookup_closure =
589 PERM (scm_module_lookup_closure (SCM_VARIABLE_REF (the_root_module_var)));
590 resolve_module_var = PERM (scm_c_lookup ("resolve-module"));
591 try_module_autoload_var = PERM (scm_c_lookup ("try-module-autoload"));
e3365c07 592 scm_module_system_booted_p = 1;
1ffa265b 593}
89e00824
ML
594
595/*
596 Local Variables:
597 c-file-style: "gnu"
598 End:
599*/