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