* modules.h, modules.c: Moved around a lot of code so that
[bpt/guile.git] / libguile / modules.c
1 /* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
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. */
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
45 \f
46
47 #include <stdarg.h>
48
49 #include "libguile/_scm.h"
50
51 #include "libguile/eval.h"
52 #include "libguile/smob.h"
53 #include "libguile/procprop.h"
54 #include "libguile/vectors.h"
55 #include "libguile/hashtab.h"
56 #include "libguile/struct.h"
57 #include "libguile/variable.h"
58 #include "libguile/fluids.h"
59 #include "libguile/deprecation.h"
60
61 #include "libguile/modules.h"
62
63 int scm_module_system_booted_p = 0;
64
65 SCM scm_module_tag;
66
67 static SCM the_module;
68
69 SCM_DEFINE (scm_current_module, "current-module", 0, 0, 0,
70 (),
71 "Return the current module.")
72 #define FUNC_NAME s_scm_current_module
73 {
74 return scm_fluid_ref (the_module);
75 }
76 #undef FUNC_NAME
77
78 static void scm_post_boot_init_modules (void);
79
80 SCM_DEFINE (scm_set_current_module, "set-current-module", 1, 0, 0,
81 (SCM module),
82 "Set the current module to @var{module} and return"
83 "the previous current module.")
84 #define FUNC_NAME s_scm_set_current_module
85 {
86 SCM old;
87
88 if (!scm_module_system_booted_p)
89 scm_post_boot_init_modules ();
90
91 SCM_VALIDATE_MODULE (SCM_ARG1, module);
92
93 old = scm_current_module ();
94 scm_fluid_set_x (the_module, module);
95
96 #if SCM_DEBUG_DEPRECATED == 0
97 scm_fluid_set_x (SCM_VARIABLE_REF (scm_top_level_lookup_closure_var),
98 scm_current_module_lookup_closure ());
99 scm_fluid_set_x (SCM_VARIABLE_REF (scm_system_transformer),
100 scm_current_module_transformer ());
101 #endif
102
103 return old;
104 }
105 #undef FUNC_NAME
106
107 SCM_DEFINE (scm_interaction_environment, "interaction-environment", 0, 0, 0,
108 (),
109 "Return a specifier for the environment that contains\n"
110 "implementation--defined bindings, typically a superset of those\n"
111 "listed in the report. The intent is that this procedure will\n"
112 "return the environment in which the implementation would\n"
113 "evaluate expressions dynamically typed by the user.")
114 #define FUNC_NAME s_scm_interaction_environment
115 {
116 return scm_current_module ();
117 }
118 #undef FUNC_NAME
119
120 SCM
121 scm_c_call_with_current_module (SCM module,
122 SCM (*func)(void *), void *data)
123 {
124 return scm_c_with_fluid (the_module, module, func, data);
125 }
126
127 static SCM
128 convert_module_name (const char *name)
129 {
130 SCM list = SCM_EOL;
131 SCM *tail = &list;
132
133 const char *ptr;
134 while (*name)
135 {
136 while (*name == ' ')
137 name++;
138 ptr = name;
139 while (*ptr && *ptr != ' ')
140 ptr++;
141 if (ptr > name)
142 {
143 *tail = scm_cons (scm_mem2symbol (name, ptr-name), SCM_EOL);
144 tail = SCM_CDRLOC (*tail);
145 }
146 name = ptr;
147 }
148
149 return list;
150 }
151
152 static SCM process_define_module_var;
153 static SCM process_use_modules_var;
154 static SCM resolve_module_var;
155
156 SCM
157 scm_c_resolve_module (const char *name)
158 {
159 return scm_resolve_module (convert_module_name (name));
160 }
161
162 SCM
163 scm_resolve_module (SCM name)
164 {
165 return scm_apply (SCM_VARIABLE_REF (resolve_module_var),
166 SCM_LIST1 (name), SCM_EOL);
167 }
168
169 SCM
170 scm_c_define_module (const char *name,
171 void (*init)(void *), void *data)
172 {
173 SCM module = scm_apply (SCM_VARIABLE_REF (process_define_module_var),
174 SCM_LIST1 (SCM_LIST1 (convert_module_name (name))),
175 SCM_EOL);
176 if (init)
177 scm_c_call_with_current_module (module, (SCM (*)(void*))init, data);
178 return module;
179 }
180
181 void
182 scm_c_use_module (const char *name)
183 {
184 scm_apply (SCM_VARIABLE_REF (process_use_modules_var),
185 SCM_LIST1 (SCM_LIST1 (convert_module_name (name))),
186 SCM_EOL);
187 }
188
189 static SCM module_export_x_var;
190
191 void
192 scm_c_export (const char *name, ...)
193 {
194 va_list ap;
195 SCM names = scm_cons (scm_str2symbol (name), SCM_EOL);
196 SCM *tail = SCM_CDRLOC (names);
197 va_start (ap, name);
198 while (1)
199 {
200 const char *n = va_arg (ap, const char *);
201 if (n == NULL)
202 break;
203 *tail = scm_cons (scm_str2symbol (n), SCM_EOL);
204 tail = SCM_CDRLOC (*tail);
205 }
206 scm_apply (SCM_VARIABLE_REF (module_export_x_var),
207 SCM_LIST2 (scm_current_module (),
208 names),
209 SCM_EOL);
210 }
211
212 /* Environments */
213
214 SCM
215 scm_top_level_env (SCM thunk)
216 {
217 if (SCM_IMP (thunk))
218 return SCM_EOL;
219 else
220 return scm_cons (thunk, SCM_EOL);
221 }
222
223 SCM
224 scm_env_top_level (SCM env)
225 {
226 while (SCM_NIMP (env))
227 {
228 if (!SCM_CONSP (SCM_CAR (env))
229 && SCM_NFALSEP (scm_procedure_p (SCM_CAR (env))))
230 return SCM_CAR (env);
231 env = SCM_CDR (env);
232 }
233 return SCM_BOOL_F;
234 }
235
236 SCM_SYMBOL (sym_module, "module");
237
238 static SCM the_root_module_var;
239
240 static SCM
241 the_root_module ()
242 {
243 if (scm_module_system_booted_p)
244 return SCM_VARIABLE_REF (the_root_module_var);
245 else
246 return SCM_BOOL_F;
247 }
248
249 SCM
250 scm_lookup_closure_module (SCM proc)
251 {
252 if (SCM_FALSEP (proc))
253 return the_root_module ();
254 else if (SCM_EVAL_CLOSURE_P (proc))
255 return SCM_PACK (SCM_SMOB_DATA (proc));
256 else
257 {
258 SCM mod = scm_procedure_property (proc, sym_module);
259 if (mod == SCM_BOOL_F)
260 mod = the_root_module ();
261 return mod;
262 }
263 }
264
265 SCM
266 scm_env_module (SCM env)
267 {
268 return scm_lookup_closure_module (scm_env_top_level (env));
269 }
270
271 /*
272 * C level implementation of the standard eval closure
273 *
274 * This increases loading speed substantially.
275 * The code will be replaced by the low-level environments in next release.
276 */
277
278 static SCM module_make_local_var_x_var;
279
280 static SCM
281 module_variable (SCM module, SCM sym)
282 {
283 /* 1. Check module obarray */
284 SCM b = scm_hashq_ref (SCM_MODULE_OBARRAY (module), sym, SCM_UNDEFINED);
285 if (SCM_VARIABLEP (b))
286 return b;
287 {
288 SCM binder = SCM_MODULE_BINDER (module);
289 if (SCM_NFALSEP (binder))
290 /* 2. Custom binder */
291 {
292 b = scm_apply (binder,
293 SCM_LIST3 (module, sym, SCM_BOOL_F),
294 SCM_EOL);
295 if (SCM_NFALSEP (b))
296 return b;
297 }
298 }
299 {
300 /* 3. Search the use list */
301 SCM uses = SCM_MODULE_USES (module);
302 while (SCM_CONSP (uses))
303 {
304 b = module_variable (SCM_CAR (uses), sym);
305 if (SCM_NFALSEP (b))
306 return b;
307 uses = SCM_CDR (uses);
308 }
309 return SCM_BOOL_F;
310 }
311 }
312
313 scm_bits_t scm_tc16_eval_closure;
314
315 #define SCM_F_EVAL_CLOSURE_INTERFACE (1<<16)
316 #define SCM_EVAL_CLOSURE_INTERFACE_P(e) \
317 (SCM_CELL_WORD_0 (e) & SCM_F_EVAL_CLOSURE_INTERFACE)
318
319 /* NOTE: This function may be called by a smob application
320 or from another C function directly. */
321 SCM
322 scm_eval_closure_lookup (SCM eclo, SCM sym, SCM definep)
323 {
324 SCM module = SCM_PACK (SCM_SMOB_DATA (eclo));
325 if (SCM_NFALSEP (definep))
326 {
327 if (SCM_EVAL_CLOSURE_INTERFACE_P (eclo))
328 return SCM_BOOL_F;
329 return scm_apply (SCM_VARIABLE_REF (module_make_local_var_x_var),
330 SCM_LIST2 (module, sym),
331 SCM_EOL);
332 }
333 else
334 return module_variable (module, sym);
335 }
336
337 SCM_DEFINE (scm_standard_eval_closure, "standard-eval-closure", 1, 0, 0,
338 (SCM module),
339 "Return an eval closure for the module @var{module}.")
340 #define FUNC_NAME s_scm_standard_eval_closure
341 {
342 SCM_RETURN_NEWSMOB (scm_tc16_eval_closure, SCM_UNPACK (module));
343 }
344 #undef FUNC_NAME
345
346 SCM_DEFINE (scm_standard_interface_eval_closure,
347 "standard-interface-eval-closure", 1, 0, 0,
348 (SCM module),
349 "Return a interface eval closure for the module @var{module}. "
350 "Such a closure does not allow new bindings to be added.")
351 #define FUNC_NAME s_scm_standard_interface_eval_closure
352 {
353 SCM_RETURN_NEWSMOB (scm_tc16_eval_closure | SCM_F_EVAL_CLOSURE_INTERFACE,
354 SCM_UNPACK (module));
355 }
356 #undef FUNC_NAME
357
358 SCM
359 scm_module_lookup_closure (SCM module)
360 {
361 if (module == SCM_BOOL_F)
362 return SCM_BOOL_F;
363 else
364 return SCM_MODULE_EVAL_CLOSURE (module);
365 }
366
367 SCM
368 scm_current_module_lookup_closure ()
369 {
370 if (scm_module_system_booted_p)
371 return scm_module_lookup_closure (scm_current_module ());
372 else
373 return SCM_BOOL_F;
374 }
375
376 SCM
377 scm_module_transformer (SCM module)
378 {
379 if (module == SCM_BOOL_F)
380 return SCM_BOOL_F;
381 else
382 return SCM_MODULE_TRANSFORMER (module);
383 }
384
385 SCM
386 scm_current_module_transformer ()
387 {
388 if (scm_module_system_booted_p)
389 return scm_module_transformer (scm_current_module ());
390 else
391 return SCM_BOOL_F;
392 }
393
394 /* scm_sym2var
395 *
396 * looks up the variable bound to SYM according to PROC. PROC should be
397 * a `eval closure' of some module.
398 *
399 * When no binding exists, and DEFINEP is true, create a new binding
400 * with a initial value of SCM_UNDEFINED. Return `#f' when DEFINEP as
401 * false and no binding exists.
402 *
403 * When PROC is `#f', it is ignored and the binding is searched for in
404 * the scm_pre_modules_obarray (a `eq' hash table).
405 */
406
407 SCM scm_pre_modules_obarray;
408
409 SCM
410 scm_sym2var (SCM sym, SCM proc, SCM definep)
411 #define FUNC_NAME "scm_sym2var"
412 {
413 SCM var;
414
415 if (SCM_NIMP (proc))
416 {
417 if (SCM_EVAL_CLOSURE_P (proc))
418 {
419 /* Bypass evaluator in the standard case. */
420 var = scm_eval_closure_lookup (proc, sym, definep);
421 }
422 else
423 var = scm_apply (proc, sym, scm_cons (definep, scm_listofnull));
424 }
425 else
426 {
427 SCM handle;
428
429 if (definep == SCM_BOOL_F)
430 var = scm_hashq_ref (scm_pre_modules_obarray, sym, SCM_BOOL_F);
431 else
432 {
433 handle = scm_hashq_create_handle_x (scm_pre_modules_obarray,
434 sym, SCM_BOOL_F);
435 var = SCM_CDR (handle);
436 if (var == SCM_BOOL_F)
437 {
438 var = scm_make_variable (SCM_UNDEFINED);
439 #if SCM_ENABLE_VCELLS
440 scm_variable_set_name_hint (var, sym);
441 #endif
442 SCM_SETCDR (handle, var);
443 }
444 }
445 }
446
447 if (var != SCM_BOOL_F && !SCM_VARIABLEP (var))
448 SCM_MISC_ERROR ("~S is not bound to a variable", SCM_LIST1 (sym));
449
450 return var;
451 }
452 #undef FUNC_NAME
453
454 SCM
455 scm_c_module_lookup (SCM module, const char *name)
456 {
457 return scm_module_lookup (module, scm_str2symbol (name));
458 }
459
460 SCM
461 scm_module_lookup (SCM module, SCM sym)
462 #define FUNC_NAME "module-lookup"
463 {
464 SCM var;
465 SCM_VALIDATE_MODULE (1, module);
466
467 var = scm_sym2var (sym, scm_module_lookup_closure (module), SCM_BOOL_F);
468 if (SCM_FALSEP (var))
469 SCM_MISC_ERROR ("unbound variable: ~S", SCM_LIST1 (sym));
470 return var;
471 }
472 #undef FUNC_NAME
473
474 SCM
475 scm_c_lookup (const char *name)
476 {
477 return scm_lookup (scm_str2symbol (name));
478 }
479
480 SCM
481 scm_lookup (SCM sym)
482 {
483 SCM var =
484 scm_sym2var (sym, scm_current_module_lookup_closure (), SCM_BOOL_F);
485 if (SCM_FALSEP (var))
486 scm_misc_error ("scm_lookup", "unbound variable: ~S", SCM_LIST1 (sym));
487 return var;
488 }
489
490 SCM
491 scm_c_module_define (SCM module, const char *name, SCM value)
492 {
493 return scm_module_define (module, scm_str2symbol (name), value);
494 }
495
496 SCM
497 scm_module_define (SCM module, SCM sym, SCM value)
498 #define FUNC_NAME "module-define"
499 {
500 SCM var;
501 SCM_VALIDATE_MODULE (1, module);
502
503 var = scm_sym2var (sym, scm_module_lookup_closure (module), SCM_BOOL_T);
504 SCM_VARIABLE_SET (var, value);
505 return var;
506 }
507 #undef FUNC_NAME
508
509 SCM
510 scm_c_define (const char *name, SCM value)
511 {
512 return scm_define (scm_str2symbol (name), value);
513 }
514
515 SCM
516 scm_define (SCM sym, SCM value)
517 {
518 SCM var =
519 scm_sym2var (sym, scm_current_module_lookup_closure (), SCM_BOOL_T);
520 SCM_VARIABLE_SET (var, value);
521 return var;
522 }
523
524 SCM
525 scm_module_reverse_lookup (SCM module, SCM variable)
526 #define FUNC_NAME "module-reverse-lookup"
527 {
528 SCM obarray;
529 int i, n;
530
531 if (module == SCM_BOOL_F)
532 obarray = scm_pre_modules_obarray;
533 else
534 {
535 SCM_VALIDATE_MODULE (1, module);
536 obarray = SCM_MODULE_OBARRAY (module);
537 }
538
539 /* XXX - We do not use scm_hash_fold here to avoid searching the
540 whole obarray. We should have a scm_hash_find procedure. */
541
542 n = SCM_VECTOR_LENGTH (obarray);
543 for (i = 0; i < n; ++i)
544 {
545 SCM ls = SCM_VELTS (obarray)[i], handle;
546 while (!SCM_NULLP (ls))
547 {
548 handle = SCM_CAR (ls);
549 if (SCM_CDR (handle) == variable)
550 return SCM_CAR (handle);
551 ls = SCM_CDR (ls);
552 }
553 }
554
555 /* Try the `uses' list.
556 */
557 {
558 SCM uses = SCM_MODULE_USES (module);
559 while (SCM_CONSP (uses))
560 {
561 SCM sym = scm_module_reverse_lookup (SCM_CAR (uses), variable);
562 if (sym != SCM_BOOL_F)
563 return sym;
564 uses = SCM_CDR (uses);
565 }
566 }
567
568 return SCM_BOOL_F;
569 }
570 #undef FUNC_NAME
571
572 SCM_DEFINE (scm_get_pre_modules_obarray, "%get-pre-modules-obarray", 0, 0, 0,
573 (),
574 "Return the obarray that is used for all new bindings before "
575 "the module system is booted. The first call to "
576 "@code{set-current-module} will boot the module system.")
577 #define FUNC_NAME s_scm_get_pre_modules_obarray
578 {
579 return scm_pre_modules_obarray;
580 }
581 #undef FUNC_NAME
582
583 #if SCM_DEBUG_DEPRECATED == 0
584
585 static SCM root_module_lookup_closure;
586 SCM_SYMBOL (scm_sym_app, "app");
587 SCM_SYMBOL (scm_sym_modules, "modules");
588 static SCM module_prefix;
589 static SCM make_modules_in_var;
590 static SCM beautify_user_module_x_var;
591 static SCM try_module_autoload_var;
592
593 #endif
594
595 SCM_SYMBOL (scm_sym_system_module, "system-module");
596
597 SCM
598 scm_system_module_env_p (SCM env)
599 {
600 SCM proc = scm_env_top_level (env);
601 if (SCM_FALSEP (proc))
602 return SCM_BOOL_T;
603 return ((SCM_NFALSEP (scm_procedure_property (proc,
604 scm_sym_system_module)))
605 ? SCM_BOOL_T
606 : SCM_BOOL_F);
607 }
608
609 void
610 scm_modules_prehistory ()
611 {
612 scm_pre_modules_obarray
613 = scm_permanent_object (scm_c_make_hash_table (2001));
614 }
615
616 void
617 scm_init_modules ()
618 {
619 #ifndef SCM_MAGIC_SNARFER
620 #include "libguile/modules.x"
621 #endif
622 module_make_local_var_x_var = scm_c_define ("module-make-local-var!",
623 SCM_UNDEFINED);
624 scm_tc16_eval_closure = scm_make_smob_type ("eval-closure", 0);
625 scm_set_smob_mark (scm_tc16_eval_closure, scm_markcdr);
626 scm_set_smob_apply (scm_tc16_eval_closure, scm_eval_closure_lookup, 2, 0, 0);
627
628 the_module = scm_permanent_object (scm_make_fluid ());
629 }
630
631 static void
632 scm_post_boot_init_modules ()
633 {
634 #define PERM(x) scm_permanent_object(x)
635
636 SCM module_type = SCM_VARIABLE_REF (scm_c_lookup ("module-type"));
637 scm_module_tag = (SCM_CELL_WORD_1 (module_type) + scm_tc3_cons_gloc);
638
639 resolve_module_var = PERM (scm_c_lookup ("resolve-module"));
640 process_define_module_var = PERM (scm_c_lookup ("process-define-module"));
641 process_use_modules_var = PERM (scm_c_lookup ("process-use-modules"));
642 module_export_x_var = PERM (scm_c_lookup ("module-export!"));
643 the_root_module_var = PERM (scm_c_lookup ("the-root-module"));
644
645 #if SCM_DEBUG_DEPRECATED == 0
646
647 module_prefix = PERM (SCM_LIST2 (scm_sym_app, scm_sym_modules));
648 make_modules_in_var = PERM (scm_c_lookup ("make-modules-in"));
649 root_module_lookup_closure =
650 PERM (scm_module_lookup_closure (SCM_VARIABLE_REF (the_root_module_var)));
651 beautify_user_module_x_var = PERM (scm_c_lookup ("beautify-user-module!"));
652 try_module_autoload_var = PERM (scm_c_lookup ("try-module-autoload"));
653
654 #endif
655
656 scm_module_system_booted_p = 1;
657 }
658
659 #if SCM_DEBUG_DEPRECATED == 0
660
661 SCM
662 scm_the_root_module ()
663 {
664 scm_c_issue_deprecation_warning ("`scm_the_root_module' is deprecated. "
665 "Use `scm_c_resolve_module (\"guile\") "
666 "instead.");
667
668 return the_root_module ();
669 }
670
671 static SCM
672 scm_module_full_name (SCM name)
673 {
674 if (SCM_EQ_P (SCM_CAR (name), scm_sym_app))
675 return name;
676 else
677 return scm_append (SCM_LIST2 (module_prefix, name));
678 }
679
680 SCM
681 scm_make_module (SCM name)
682 {
683 scm_c_issue_deprecation_warning ("`scm_make_module' is deprecated. "
684 "Use `scm_c_define_module instead.");
685
686 return scm_apply (SCM_VARIABLE_REF (make_modules_in_var),
687 SCM_LIST2 (scm_the_root_module (),
688 scm_module_full_name (name)),
689 SCM_EOL);
690 }
691
692 SCM
693 scm_ensure_user_module (SCM module)
694 {
695 scm_c_issue_deprecation_warning ("`scm_ensure_user_module' is deprecated. "
696 "Use `scm_c_define_module instead.");
697
698 scm_apply (SCM_VARIABLE_REF (beautify_user_module_x_var),
699 SCM_LIST1 (module), SCM_EOL);
700 return SCM_UNSPECIFIED;
701 }
702
703 SCM
704 scm_load_scheme_module (SCM name)
705 {
706 scm_c_issue_deprecation_warning ("`scm_load_scheme_module' is deprecated. "
707 "Use `scm_c_resolve_module instead.");
708
709 return scm_apply (SCM_VARIABLE_REF (try_module_autoload_var),
710 SCM_LIST1 (name), SCM_EOL);
711 }
712
713 #endif
714
715 /*
716 Local Variables:
717 c-file-style: "gnu"
718 End:
719 */