Add br-if-logtest opcode
[bpt/guile.git] / libguile / eval.c
index 43a182a..2488ee2 100644 (file)
@@ -1,5 +1,5 @@
 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,
- *   2005,2006,2007,2008,2009,2010,2011,2012,2013
+ *   2005,2006,2007,2008,2009,2010,2011,2012,2013,2014
  * Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
@@ -245,18 +245,6 @@ truncate_values (SCM x)
 }
 #define EVAL1(x, env) (truncate_values (eval ((x), (env))))
 
-/* the environment:
-   (VAL ... . MOD)
-   If MOD is #f, it means the environment was captured before modules were
-   booted.
-   If MOD is the literal value '(), we are evaluating at the top level, and so
-   should track changes to the current module. You have to be careful in this
-   case, because further lexical contours should capture the current module.
-*/
-#define CAPTURE_ENV(env)                                        \
-  (scm_is_null (env) ? scm_current_module () :                  \
-   (scm_is_false (env) ? scm_the_root_module () : env))
-
 static SCM
 eval (SCM x, SCM env)
 {
@@ -288,8 +276,7 @@ eval (SCM x, SCM env)
         SCM new_env;
         int i;
 
-        new_env = make_env (VECTOR_LENGTH (inits), SCM_UNDEFINED,
-                            CAPTURE_ENV (env));
+        new_env = make_env (VECTOR_LENGTH (inits), SCM_UNDEFINED, env);
         for (i = 0; i < VECTOR_LENGTH (inits); i++)
           env_set (new_env, 0, i, EVAL1 (VECTOR_REF (inits, i), env));
         env = new_env;
@@ -298,7 +285,7 @@ eval (SCM x, SCM env)
       }
           
     case SCM_M_LAMBDA:
-      RETURN_BOOT_CLOSURE (mx, CAPTURE_ENV (env));
+      RETURN_BOOT_CLOSURE (mx, env);
 
     case SCM_M_QUOTE:
       return mx;
@@ -307,6 +294,9 @@ eval (SCM x, SCM env)
       scm_define (CAR (mx), EVAL1 (CDR (mx), env));
       return SCM_UNSPECIFIED;
 
+    case SCM_M_CAPTURE_MODULE:
+      return eval (mx, scm_current_module ());
+
     case SCM_M_APPLY:
       /* Evaluate the procedure to be applied.  */
       proc = EVAL1 (CAR (mx), env);
@@ -322,7 +312,7 @@ eval (SCM x, SCM env)
           goto loop;
         }
       else
-        return scm_call_with_vm (scm_the_vm (), proc, args);
+        return scm_apply_0 (proc, args);
 
     case SCM_M_CALL:
       /* Evaluate the procedure to be applied.  */
@@ -344,7 +334,7 @@ eval (SCM x, SCM env)
          for (i = 0; i < argc; i++, mx = CDR (mx))
            argv[i] = EVAL1 (CAR (mx), env);
 
-         return scm_c_vm_run (scm_the_vm (), proc, argv, argc);
+         return scm_call_n (proc, argv, argc);
         }
 
     case SCM_M_CONT:
@@ -358,7 +348,7 @@ eval (SCM x, SCM env)
         producer = EVAL1 (CAR (mx), env);
         /* `proc' is the consumer.  */
         proc = EVAL1 (CDR (mx), env);
-        v = scm_call_with_vm (scm_the_vm (), producer, SCM_EOL);
+        v = scm_call_0 (producer);
         if (SCM_VALUESP (v))
           args = scm_struct_ref (v, SCM_INUM0);
         else
@@ -405,8 +395,7 @@ eval (SCM x, SCM env)
       else
         {
           env = env_tail (env);
-          return SCM_VARIABLE_REF
-            (scm_memoize_variable_access_x (x, CAPTURE_ENV (env)));
+          return SCM_VARIABLE_REF (scm_memoize_variable_access_x (x, env));
         }
 
     case SCM_M_TOPLEVEL_SET:
@@ -421,9 +410,7 @@ eval (SCM x, SCM env)
         else
           {
             env = env_tail (env);
-            SCM_VARIABLE_SET
-              (scm_memoize_variable_access_x (x, CAPTURE_ENV (env)),
-               val);
+            SCM_VARIABLE_SET (scm_memoize_variable_access_x (x, env), val);
             return SCM_UNSPECIFIED;
           }
       }
@@ -451,7 +438,8 @@ eval (SCM x, SCM env)
 
     case SCM_M_CALL_WITH_PROMPT:
       {
-        SCM vm, k, res;
+        struct scm_vm *vp;
+        SCM k, res;
         scm_i_jmp_buf registers;
         /* We need the handler after nonlocal return to the setjmp, so
            make sure it is volatile.  */
@@ -459,23 +447,25 @@ eval (SCM x, SCM env)
 
         k = EVAL1 (CAR (mx), env);
         handler = EVAL1 (CDDR (mx), env);
-        vm = scm_the_vm ();
+        vp = scm_the_vm ();
 
         /* Push the prompt onto the dynamic stack. */
         scm_dynstack_push_prompt (&SCM_I_CURRENT_THREAD->dynstack,
                                   SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY
                                   | SCM_F_DYNSTACK_PROMPT_PUSH_NARGS,
                                   k,
-                                  SCM_VM_DATA (vm)->fp,
-                                  SCM_VM_DATA (vm)->sp,
-                                  SCM_VM_DATA (vm)->ip,
+                                  vp->fp - vp->stack_base,
+                                  vp->sp - vp->stack_base,
+                                  vp->ip,
                                   &registers);
 
         if (SCM_I_SETJMP (registers))
           {
             /* The prompt exited nonlocally. */
+            scm_gc_after_nonlocal_exit ();
             proc = handler;
-            args = scm_i_prompt_pop_abort_args_x (scm_the_vm ());
+            vp = scm_the_vm ();
+            args = scm_i_prompt_pop_abort_args_x (vp);
             goto apply_proc;
           }
         
@@ -497,41 +487,41 @@ eval (SCM x, SCM env)
 SCM
 scm_call_0 (SCM proc)
 {
-  return scm_c_vm_run (scm_the_vm (), proc, NULL, 0);
+  return scm_call_n (proc, NULL, 0);
 }
 
 SCM
 scm_call_1 (SCM proc, SCM arg1)
 {
-  return scm_c_vm_run (scm_the_vm (), proc, &arg1, 1);
+  return scm_call_n (proc, &arg1, 1);
 }
 
 SCM
 scm_call_2 (SCM proc, SCM arg1, SCM arg2)
 {
   SCM args[] = { arg1, arg2 };
-  return scm_c_vm_run (scm_the_vm (), proc, args, 2);
+  return scm_call_n (proc, args, 2);
 }
 
 SCM
 scm_call_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3)
 {
   SCM args[] = { arg1, arg2, arg3 };
-  return scm_c_vm_run (scm_the_vm (), proc, args, 3);
+  return scm_call_n (proc, args, 3);
 }
 
 SCM
 scm_call_4 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4)
 {
   SCM args[] = { arg1, arg2, arg3, arg4 };
-  return scm_c_vm_run (scm_the_vm (), proc, args, 4);
+  return scm_call_n (proc, args, 4);
 }
 
 SCM
 scm_call_5 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5)
 {
   SCM args[] = { arg1, arg2, arg3, arg4, arg5 };
-  return scm_c_vm_run (scm_the_vm (), proc, args, 5);
+  return scm_call_n (proc, args, 5);
 }
 
 SCM
@@ -539,7 +529,7 @@ scm_call_6 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
             SCM arg6)
 {
   SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6 };
-  return scm_c_vm_run (scm_the_vm (), proc, args, 6);
+  return scm_call_n (proc, args, 6);
 }
 
 SCM
@@ -547,7 +537,7 @@ scm_call_7 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
             SCM arg6, SCM arg7)
 {
   SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7 };
-  return scm_c_vm_run (scm_the_vm (), proc, args, 7);
+  return scm_call_n (proc, args, 7);
 }
 
 SCM
@@ -555,7 +545,7 @@ scm_call_8 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
             SCM arg6, SCM arg7, SCM arg8)
 {
   SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 };
-  return scm_c_vm_run (scm_the_vm (), proc, args, 8);
+  return scm_call_n (proc, args, 8);
 }
 
 SCM
@@ -563,14 +553,10 @@ scm_call_9 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
             SCM arg6, SCM arg7, SCM arg8, SCM arg9)
 {
   SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 };
-  return scm_c_vm_run (scm_the_vm (), proc, args, 9);
+  return scm_call_n (proc, args, 9);
 }
 
-SCM
-scm_call_n (SCM proc, SCM *argv, size_t nargs)
-{
-  return scm_c_vm_run (scm_the_vm (), proc, argv, nargs);
-}
+/* scm_call_n defined in vm.c */
 
 SCM
 scm_call (SCM proc, ...)
@@ -590,7 +576,7 @@ scm_call (SCM proc, ...)
     argv[i] = va_arg (argp, SCM);
   va_end (argp);
 
-  return scm_c_vm_run (scm_the_vm (), proc, argv, nargs);
+  return scm_call_n (proc, argv, nargs);
 }
 
 /* Simple procedure applies
@@ -599,53 +585,74 @@ scm_call (SCM proc, ...)
 SCM
 scm_apply_0 (SCM proc, SCM args)
 {
-  return scm_apply (proc, args, SCM_EOL);
+  SCM *argv;
+  int i, nargs;
+
+  nargs = scm_ilength (args);
+  if (SCM_UNLIKELY (nargs < 0))
+    scm_wrong_type_arg_msg ("apply", 2, args, "list");
+  
+  /* FIXME: Use vm_builtin_apply instead of alloca.  */
+  argv = alloca (nargs * sizeof(SCM));
+  for (i = 0; i < nargs; i++)
+    {
+      argv[i] = SCM_CAR (args);
+      args = SCM_CDR (args);
+    }
+
+  return scm_call_n (proc, argv, nargs);
 }
 
 SCM
 scm_apply_1 (SCM proc, SCM arg1, SCM args)
 {
-  return scm_apply (proc, scm_cons (arg1, args), SCM_EOL);
+  return scm_apply_0 (proc, scm_cons (arg1, args));
 }
 
 SCM
 scm_apply_2 (SCM proc, SCM arg1, SCM arg2, SCM args)
 {
-  return scm_apply (proc, scm_cons2 (arg1, arg2, args), SCM_EOL);
+  return scm_apply_0 (proc, scm_cons2 (arg1, arg2, args));
 }
 
 SCM
 scm_apply_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM args)
 {
-  return scm_apply (proc, scm_cons (arg1, scm_cons2 (arg2, arg3, args)),
-                   SCM_EOL);
+  return scm_apply_0 (proc, scm_cons (arg1, scm_cons2 (arg2, arg3, args)));
 }
 
+static SCM map_var, for_each_var;
+
+static void init_map_var (void)
+{
+  map_var = scm_private_variable (scm_the_root_module (),
+                                  scm_from_latin1_symbol ("map"));
+}
+
+static void init_for_each_var (void)
+{
+  for_each_var = scm_private_variable (scm_the_root_module (),
+                                       scm_from_latin1_symbol ("for-each"));
+}
 
 SCM 
 scm_map (SCM proc, SCM arg1, SCM args)
 {
-  static SCM var = SCM_BOOL_F;
+  static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
+  scm_i_pthread_once (&once, init_map_var);
 
-  if (scm_is_false (var))
-    var = scm_private_variable (scm_the_root_module (),
-                                scm_from_latin1_symbol ("map"));
-
-  return scm_apply (scm_variable_ref (var),
-                    scm_cons (proc, scm_cons (arg1, args)), SCM_EOL);
+  return scm_apply_0 (scm_variable_ref (map_var),
+                      scm_cons (proc, scm_cons (arg1, args)));
 }
 
 SCM 
 scm_for_each (SCM proc, SCM arg1, SCM args)
 {
-  static SCM var = SCM_BOOL_F;
-
-  if (scm_is_false (var))
-    var = scm_private_variable (scm_the_root_module (),
-                                scm_from_latin1_symbol ("for-each"));
+  static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
+  scm_i_pthread_once (&once, init_for_each_var);
 
-  return scm_apply (scm_variable_ref (var),
-                    scm_cons (proc, scm_cons (arg1, args)), SCM_EOL);
+  return scm_apply_0 (scm_variable_ref (for_each_var),
+                      scm_cons (proc, scm_cons (arg1, args)));
 }
 
 
@@ -654,15 +661,15 @@ scm_c_primitive_eval (SCM exp)
 {
   if (!SCM_EXPANDED_P (exp))
     exp = scm_call_1 (scm_current_module_transformer (), exp);
-  return eval (scm_memoize_expression (exp), SCM_EOL);
+  return eval (scm_memoize_expression (exp), SCM_BOOL_F);
 }
 
 static SCM var_primitive_eval;
 SCM
 scm_primitive_eval (SCM exp)
 {
-  return scm_c_vm_run (scm_the_vm (), scm_variable_ref (var_primitive_eval),
-                       &exp, 1);
+  return scm_call_n (scm_variable_ref (var_primitive_eval),
+                     &exp, 1);
 }
 
 
@@ -707,24 +714,18 @@ static SCM f_apply;
 
 /* Apply a function to a list of arguments.
 
-   This function is exported to the Scheme level as taking two
-   required arguments and a tail argument, as if it were:
+   This function's interface is a bit wonly.  It takes two required
+   arguments and a tail argument, as if it were:
+
        (lambda (proc arg1 . args) ...)
-   Thus, if you just have a list of arguments to pass to a procedure,
-   pass the list as ARG1, and '() for ARGS.  If you have some fixed
-   args, pass the first as ARG1, then cons any remaining fixed args
-   onto the front of your argument list, and pass that as ARGS.  */
+
+   Usually you want to use scm_apply_0 or one of its cousins.  */
 
 SCM 
 scm_apply (SCM proc, SCM arg1, SCM args)
 {
-  /* Fix things up so that args contains all args. */
-  if (scm_is_null (args))
-    args = arg1;
-  else
-    args = scm_cons_star (arg1, args);
-
-  return scm_call_with_vm (scm_the_vm (), proc, args);
+  return scm_apply_0 (proc,
+                      scm_is_null (args) ? arg1 : scm_cons_star (arg1, args));
 }
 
 static void