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