(scm_modulo_expt): Renamed from
[bpt/guile.git] / libguile / modules.c
index f304df3..7d578dc 100644 (file)
@@ -1,43 +1,19 @@
-/* Copyright (C) 1998,2000,2001 Free Software Foundation, Inc.
+/* Copyright (C) 1998,2000,2001,2002, 2003 Free Software Foundation, Inc.
  * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA
- *
- * As a special exception, the Free Software Foundation gives permission
- * for additional uses of the text contained in its release of GUILE.
- *
- * The exception is that, if you link the GUILE library with other files
- * to produce an executable, this does not by itself cause the
- * resulting executable to be covered by the GNU General Public License.
- * Your use of that executable is in no way restricted on account of
- * linking the GUILE library code into it.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
  *
- * This exception does not however invalidate any other reasons why
- * the executable file might be covered by the GNU General Public License.
- *
- * This exception applies only to the code released by the
- * Free Software Foundation under the name GUILE.  If you copy
- * code from other Free Software Foundation releases into a copy of
- * GUILE, as the General Public License permits, the exception does
- * not apply to the code that you add in this way.  To avoid misleading
- * anyone as to the status of such modified files, you must delete
- * this exception notice from them.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
  *
- * If you write modifications of your own for GUILE, it is your choice
- * whether to permit this exception to apply to your modifications.
- * If you do not wish that, delete this exception notice.  */
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
 
 
 \f
@@ -115,6 +91,10 @@ scm_c_call_with_current_module (SCM module,
   return scm_c_with_fluid (the_module, module, func, data);
 }
 
+
+/*
+  convert "A B C" to scheme list (A B C)
+ */
 static SCM
 convert_module_name (const char *name)
 {
@@ -171,30 +151,57 @@ void
 scm_c_use_module (const char *name)
 {
   scm_call_1 (SCM_VARIABLE_REF (process_use_modules_var),
-             scm_list_1 (convert_module_name (name)));
+             scm_list_1 (scm_list_1 (convert_module_name (name))));
 }
 
 static SCM module_export_x_var;
 
+
+/*
+  TODO: should export this function? --hwn.
+ */
+static SCM
+scm_export (SCM module, SCM namelist)
+{
+  return scm_call_2 (SCM_VARIABLE_REF (module_export_x_var),
+                    module, namelist);
+}
+
+
+/*
+  @code{scm_c_export}(@var{name-list})
+
+  @code{scm_c_export} exports the named bindings from the current
+  module, making them visible to users of the module. This function
+  takes a list of string arguments, terminated by NULL, e.g.
+
+  @example
+    scm_c_export ("add-double-record", "bamboozle-money", NULL);
+  @end example
+*/
 void
 scm_c_export (const char *name, ...)
 {
-  va_list ap;
-  SCM names = scm_cons (scm_str2symbol (name), SCM_EOL);
-  SCM *tail = SCM_CDRLOC (names);
-  va_start (ap, name);
-  while (1)
+  if (name)
     {
-      const char *n = va_arg (ap, const char *);
-      if (n == NULL)
-       break;
-      *tail = scm_cons (scm_str2symbol (n), SCM_EOL);
-      tail = SCM_CDRLOC (*tail);
+      va_list ap;
+      SCM names = scm_cons (scm_str2symbol (name), SCM_EOL);
+      SCM *tail = SCM_CDRLOC (names);
+      va_start (ap, name);
+      while (1)
+       {
+         const char *n = va_arg (ap, const char *);
+         if (n == NULL)
+           break;
+         *tail = scm_cons (scm_str2symbol (n), SCM_EOL);
+         tail = SCM_CDRLOC (*tail);
+       }
+      va_end (ap);
+      scm_export (scm_current_module(), names);
     }
-  scm_call_2 (SCM_VARIABLE_REF (module_export_x_var),
-             scm_current_module (), names);
 }
 
+
 /* Environments */
 
 SCM
@@ -209,11 +216,11 @@ scm_top_level_env (SCM thunk)
 SCM
 scm_env_top_level (SCM env)
 {
-  while (SCM_NIMP (env))
+  while (SCM_CONSP (env))
     {
-      if (!SCM_CONSP (SCM_CAR (env))
-         && SCM_NFALSEP (scm_procedure_p (SCM_CAR (env))))
-       return SCM_CAR (env);
+      SCM car_env = SCM_CAR (env);
+      if (!SCM_CONSP (car_env) && !SCM_FALSEP (scm_procedure_p (car_env)))
+       return car_env;
       env = SCM_CDR (env);
     }
   return SCM_BOOL_F;
@@ -242,7 +249,7 @@ scm_lookup_closure_module (SCM proc)
   else
     {
       SCM mod = scm_procedure_property (proc, sym_module);
-      if (mod == SCM_BOOL_F)
+      if (SCM_FALSEP (mod))
        mod = the_root_module ();
       return mod;
     }
@@ -270,8 +277,7 @@ static SCM
 module_variable (SCM module, SCM sym)
 {
 #define SCM_BOUND_THING_P(b) \
-  (SCM_NFALSEP(b) && \
-   (!SCM_VARIABLEP(b) || !SCM_UNBNDP (SCM_VARIABLE_REF (b))))
+  (SCM_VARIABLEP (b) && !SCM_UNBNDP (SCM_VARIABLE_REF (b)))
 
   /* 1. Check module obarray */
   SCM b = scm_hashq_ref (SCM_MODULE_OBARRAY (module), sym, SCM_UNDEFINED);
@@ -279,7 +285,7 @@ module_variable (SCM module, SCM sym)
     return b;
   {
     SCM binder = SCM_MODULE_BINDER (module);
-    if (SCM_NFALSEP (binder))
+    if (!SCM_FALSEP (binder))
       /* 2. Custom binder */
       {
        b = scm_call_3 (binder, module, sym, SCM_BOOL_F);
@@ -314,7 +320,7 @@ SCM
 scm_eval_closure_lookup (SCM eclo, SCM sym, SCM definep)
 {
   SCM module = SCM_PACK (SCM_SMOB_DATA (eclo));
-  if (SCM_NFALSEP (definep))
+  if (!SCM_FALSEP (definep))
     {
       if (SCM_EVAL_CLOSURE_INTERFACE_P (eclo))
        return SCM_BOOL_F;
@@ -349,7 +355,7 @@ SCM_DEFINE (scm_standard_interface_eval_closure,
 SCM
 scm_module_lookup_closure (SCM module)
 {
-  if (module == SCM_BOOL_F)
+  if (SCM_FALSEP (module))
     return SCM_BOOL_F;
   else
     return SCM_MODULE_EVAL_CLOSURE (module);
@@ -367,7 +373,7 @@ scm_current_module_lookup_closure ()
 SCM
 scm_module_transformer (SCM module)
 {
-  if (module == SCM_BOOL_F)
+  if (SCM_FALSEP (module))
     return SCM_BOOL_F;
   else
     return SCM_MODULE_TRANSFORMER (module);
@@ -382,6 +388,43 @@ scm_current_module_transformer ()
     return SCM_BOOL_F;
 }
 
+SCM_DEFINE (scm_module_import_interface, "module-import-interface", 2, 0, 0,
+           (SCM module, SCM sym),
+           "")
+#define FUNC_NAME s_scm_module_import_interface
+{
+#define SCM_BOUND_THING_P(b) (!SCM_FALSEP (b))
+  SCM uses;
+  SCM_VALIDATE_MODULE (SCM_ARG1, module);
+  /* Search the use list */
+  uses = SCM_MODULE_USES (module);
+  while (SCM_CONSP (uses))
+    {
+      SCM _interface = SCM_CAR (uses);
+      /* 1. Check module obarray */
+      SCM b = scm_hashq_ref (SCM_MODULE_OBARRAY (_interface), sym, SCM_BOOL_F);
+      if (SCM_BOUND_THING_P (b))
+       return _interface;
+      {
+       SCM binder = SCM_MODULE_BINDER (_interface);
+       if (!SCM_FALSEP (binder))
+         /* 2. Custom binder */
+         {
+           b = scm_call_3 (binder, _interface, sym, SCM_BOOL_F);
+           if (SCM_BOUND_THING_P (b))
+             return _interface;
+         }
+      }
+      /* 3. Search use list recursively. */
+      _interface = scm_module_import_interface (_interface, sym);
+      if (!SCM_FALSEP (_interface))
+       return _interface;
+      uses = SCM_CDR (uses);
+    }
+  return SCM_BOOL_F;
+}
+#undef FUNC_NAME
+
 /* scm_sym2var
  *
  * looks up the variable bound to SYM according to PROC.  PROC should be
@@ -417,14 +460,14 @@ scm_sym2var (SCM sym, SCM proc, SCM definep)
     {
       SCM handle;
 
-      if (definep == SCM_BOOL_F)
+      if (SCM_FALSEP (definep))
        var = scm_hashq_ref (scm_pre_modules_obarray, sym, SCM_BOOL_F);
       else
        {
          handle = scm_hashq_create_handle_x (scm_pre_modules_obarray,
                                              sym, SCM_BOOL_F);
          var = SCM_CDR (handle);
-         if (var == SCM_BOOL_F)
+         if (SCM_FALSEP (var))
            {
              var = scm_make_variable (SCM_UNDEFINED);
              SCM_SETCDR (handle, var);
@@ -432,7 +475,7 @@ scm_sym2var (SCM sym, SCM proc, SCM definep)
        }
     }
 
-  if (var != SCM_BOOL_F && !SCM_VARIABLEP (var))
+  if (!SCM_FALSEP (var) && !SCM_VARIABLEP (var))
     SCM_MISC_ERROR ("~S is not bound to a variable", scm_list_1 (sym));
 
   return var;
@@ -516,7 +559,7 @@ scm_module_reverse_lookup (SCM module, SCM variable)
   SCM obarray;
   long i, n;
 
-  if (module == SCM_BOOL_F)
+  if (SCM_FALSEP (module))
     obarray = scm_pre_modules_obarray;
   else
     {
@@ -524,13 +567,16 @@ scm_module_reverse_lookup (SCM module, SCM variable)
       obarray = SCM_MODULE_OBARRAY (module);
     }
 
+  if (!SCM_HASHTABLE_P (obarray))
+      return SCM_BOOL_F;
+
   /* XXX - We do not use scm_hash_fold here to avoid searching the
      whole obarray.  We should have a scm_hash_find procedure. */
 
-  n = SCM_VECTOR_LENGTH (obarray);
+  n = SCM_HASHTABLE_N_BUCKETS (obarray);
   for (i = 0; i < n; ++i)
     {
-      SCM ls = SCM_VELTS (obarray)[i], handle;
+      SCM ls = SCM_HASHTABLE_BUCKETS (obarray)[i], handle;
       while (!SCM_NULLP (ls))
        {
          handle = SCM_CAR (ls);
@@ -547,7 +593,7 @@ scm_module_reverse_lookup (SCM module, SCM variable)
     while (SCM_CONSP (uses))
       {
        SCM sym = scm_module_reverse_lookup (SCM_CAR (uses), variable);
-       if (sym != SCM_BOOL_F)
+       if (!SCM_FALSEP (sym))
          return sym;
        uses = SCM_CDR (uses);
       }
@@ -576,7 +622,7 @@ scm_system_module_env_p (SCM env)
   SCM proc = scm_env_top_level (env);
   if (SCM_FALSEP (proc))
     return SCM_BOOL_T;
-  return ((SCM_NFALSEP (scm_procedure_property (proc,
+  return ((!SCM_FALSEP (scm_procedure_property (proc,
                                                scm_sym_system_module)))
          ? SCM_BOOL_T
          : SCM_BOOL_F);
@@ -586,15 +632,13 @@ void
 scm_modules_prehistory ()
 {
   scm_pre_modules_obarray 
-    = scm_permanent_object (scm_c_make_hash_table (2001));
+    = scm_permanent_object (scm_c_make_hash_table (1533));
 }
 
 void
 scm_init_modules ()
 {
-#ifndef SCM_MAGIC_SNARFER
 #include "libguile/modules.x"
-#endif
   module_make_local_var_x_var = scm_c_define ("module-make-local-var!",
                                            SCM_UNDEFINED);
   scm_tc16_eval_closure = scm_make_smob_type ("eval-closure", 0);