allow `apply' on %nil-terminated lists
authorAndy Wingo <wingo@pobox.com>
Sun, 4 Jan 2009 13:06:52 +0000 (14:06 +0100)
committerAndy Wingo <wingo@pobox.com>
Sun, 4 Jan 2009 13:06:52 +0000 (14:06 +0100)
* libguile/vm-engine.h (PUSH_LIST): Add a parameter to check that the
  list was proper.

* libguile/vm-i-system.c: Adapt PUSH_LIST callsites to pass SCM_NULLP or
  SCM_NULL_OR_NIL_P, as appropriate. Add a check to return/values*.

* libguile/vm.c: Add lang.h header for SCM_NULL_OR_NIL_P.

* test-suite/tests/elisp.test: Fix XFAIL for elisp + apply.

libguile/vm-engine.h
libguile/vm-i-system.c
libguile/vm.c
test-suite/tests/elisp.test

index 217ad2e..d0ceaf4 100644 (file)
@@ -299,12 +299,12 @@ do                                                \
 } while (0)
 
 /* The opposite: push all of the elements in L onto the list. */
-#define PUSH_LIST(l)                           \
+#define PUSH_LIST(l, NILP)                     \
 do                                             \
 {                                              \
   for (; scm_is_pair (l); l = SCM_CDR (l))      \
     PUSH (SCM_CAR (l));                         \
-  if (SCM_UNLIKELY (!SCM_NULLP (l))) {          \
+  if (SCM_UNLIKELY (!NILP (l))) {               \
     err_args = scm_list_1 (l);                  \
     goto vm_error_improper_list;                \
   }                                             \
index 831819d..60182c7 100644 (file)
@@ -214,7 +214,7 @@ VM_DEFINE_INSTRUCTION (list_break, "list-break", 0, 0, 0)
 {
   SCM l;
   POP (l);
-  PUSH_LIST (l);
+  PUSH_LIST (l, SCM_NULLP);
   NEXT;
 }
 
@@ -784,7 +784,7 @@ VM_DEFINE_INSTRUCTION (goto_args, "goto/args", 1, -1, 1)
           POP (values);
           values = scm_struct_ref (values, SCM_INUM0);
           nvalues = scm_ilength (values);
-          PUSH_LIST (values);
+          PUSH_LIST (values, SCM_NULLP);
           goto vm_return_values;
         }
       goto vm_return;
@@ -861,7 +861,7 @@ VM_DEFINE_INSTRUCTION (mv_call, "mv-call", 3, -1, 1)
           POP (values);
           values = scm_struct_ref (values, SCM_INUM0);
           len = scm_length (values);
-          PUSH_LIST (values);
+          PUSH_LIST (values, SCM_NULLP);
           PUSH (len);
           ip += offset;
         }
@@ -893,7 +893,7 @@ VM_DEFINE_INSTRUCTION (apply, "apply", 1, -1, 1)
   if (len < 0)
     goto vm_error_wrong_type_arg;
 
-  PUSH_LIST (ls);
+  PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
 
   nargs += len - 2;
   goto vm_call;
@@ -912,7 +912,7 @@ VM_DEFINE_INSTRUCTION (goto_apply, "goto/apply", 1, -1, 1)
   if (len < 0)
     goto vm_error_wrong_type_arg;
 
-  PUSH_LIST (ls);
+  PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
 
   nargs += len - 2;
   goto vm_goto_args;
@@ -974,7 +974,7 @@ VM_DEFINE_INSTRUCTION (goto_cc, "goto/cc", 0, 1, 1)
       SCM values;
       values = scm_struct_ref (cont, SCM_INUM0);
       nvalues = scm_ilength (values);
-      PUSH_LIST (values);
+      PUSH_LIST (values, SCM_NULLP);
       goto vm_return_values;
     }
   else
@@ -1097,6 +1097,10 @@ VM_DEFINE_INSTRUCTION (return_values_star, "return/values*", 1, -1, -1)
       l = SCM_CDR (l);
       nvalues++;
     }
+  if (SCM_UNLIKELY (!SCM_NULL_OR_NIL_P (l))) {
+    err_args = scm_list_1 (l);
+    goto vm_error_improper_list;
+  }
 
   goto vm_return_values;
 }
index 32fde61..ed69bd9 100644 (file)
@@ -49,6 +49,7 @@
 #include "instructions.h"
 #include "objcodes.h"
 #include "programs.h"
+#include "lang.h" /* NULL_OR_NIL_P */
 #include "vm.h"
 
 /* I sometimes use this for debugging. */
index 06378f8..eaf6dbb 100644 (file)
       (elisp-pass-if '(function (lambda (x y &optional o &rest r) (list x y o r))) "(lambda (x y &optional o &rest r) (list x y o r))")
       (elisp-pass-if '(funcall (lambda (x y &optional o &rest r) (list x y o r)) 1 2 3 4) "(1 2 3 (4))")
 
-      ;; If r4rs.scm is compiled, `apply' will only unroll true scheme
-      ;; lists.
-      (elisp-pass-if/maybe-error
-       'vm-error
-       '(apply (lambda (x y &optional o &rest r) (list x y o r)) 1 2 3 nil)
-       "(1 2 3 #nil)")
+      (elisp-pass-if '(apply (lambda (x y &optional o &rest r) (list x y o r)) 1 2 3 nil)
+                     "(1 2 3 #nil)")
       
       (elisp-pass-if '(setq x 3) "3")
       (elisp-pass-if '(defvar x 4) "x")