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