remove @apply memoizer
authorAndy Wingo <wingo@pobox.com>
Thu, 27 Jun 2013 09:25:34 +0000 (11:25 +0200)
committerAndy Wingo <wingo@pobox.com>
Thu, 27 Jun 2013 20:02:35 +0000 (22:02 +0200)
* libguile/memoize.c (memoize): Recognize a primcall to 'apply as
  SCM_M_APPLY.
  (@apply): Remove @apply memoizer.
  (unmemoize): Unmemoize using "apply", not "@apply".

* libguile/memoize.h:
* libguile/expand.c (scm_sym_atapply): Remove.

* module/ice-9/boot-9.scm (apply): Re-implement using apply primcall.
  Use case-lambda, so as to give an appropriate minimum arity.

* module/language/tree-il/compile-glil.scm (flatten-lambda-case):
  Compile a primcall of "apply" specially, not "@apply".

* module/language/tree-il/peval.scm (peval): Match primcalls to "apply",
  not "@apply".  Residualize "apply" primcalls.

* module/language/tree-il/primitives.scm (*interesting-primitive-names*):
  (*multiply-valued-primitives*): Remove @apply, and apply primitive
  expander.

* test-suite/tests/peval.test:
* test-suite/tests/tree-il.test: Update tests to expect residualized
  "apply".

* test-suite/tests/procprop.test ("procedure-arity"): Update test for
  better apply arity.

* test-suite/tests/strings.test ("string"): Update expected error.

libguile/expand.c
libguile/memoize.c
libguile/memoize.h
module/ice-9/boot-9.scm
module/language/tree-il/compile-glil.scm
module/language/tree-il/peval.scm
module/language/tree-il/primitives.scm
test-suite/tests/peval.test
test-suite/tests/procprop.test
test-suite/tests/strings.test
test-suite/tests/tree-il.test

index 396df3b..28636a4 100644 (file)
@@ -181,7 +181,6 @@ SCM_GLOBAL_SYMBOL (scm_sym_arrow, "=>");
 SCM_GLOBAL_SYMBOL (scm_sym_at, "@");
 SCM_GLOBAL_SYMBOL (scm_sym_atat, "@@");
 SCM_GLOBAL_SYMBOL (scm_sym_at_call_with_values, "@call-with-values");
-SCM_GLOBAL_SYMBOL (scm_sym_atapply, "@apply");
 SCM_GLOBAL_SYMBOL (scm_sym_atcall_cc, "@call-with-current-continuation");
 SCM_GLOBAL_SYMBOL (scm_sym_begin, "begin");
 SCM_GLOBAL_SYMBOL (scm_sym_case, "case");
index f4a4c9e..12e670a 100644 (file)
@@ -279,6 +279,9 @@ memoize (SCM exp, SCM env)
           return MAKMEMO_CALL_WITH_PROMPT (CAR (args),
                                            CADR (args),
                                            CADDR (args));
+        else if (nargs == 2
+                 && scm_is_eq (name, scm_from_latin1_symbol ("apply")))
+          return MAKMEMO_APPLY (CAR (args), CADR (args));
         else if (scm_is_eq (scm_current_module (), scm_the_root_module ()))
           return MAKMEMO_CALL (MAKMEMO_TOP_REF (name), nargs, args);
         else
@@ -524,18 +527,10 @@ SCM_DEFINE (scm_memoize_expression, "memoize-expression", 1, 0, 0,
 #define SCM_DEFINE_MEMOIZER(STR, MEMOIZER, N)                           \
 SCM_SNARF_INIT(scm_c_define (STR, SCM_MAKE_MEMOIZER (STR, MEMOIZER, N)))
 
-#define SCM_MAKE_REST_MEMOIZER(STR, MEMOIZER, N)                        \
-  (scm_cell (scm_tc16_memoizer,                                         \
-             SCM_UNPACK ((scm_c_make_gsubr (STR, N, 0, 1, MEMOIZER)))))
-#define SCM_DEFINE_REST_MEMOIZER(STR, MEMOIZER, N)                      \
-SCM_SNARF_INIT(scm_c_define (STR, SCM_MAKE_REST_MEMOIZER (STR, MEMOIZER, N)))
-
-static SCM m_apply (SCM proc, SCM arg, SCM rest);
 static SCM m_call_cc (SCM proc);
 static SCM m_call_values (SCM prod, SCM cons);
 static SCM m_dynamic_wind (SCM pre, SCM exp, SCM post);
 
-SCM_DEFINE_REST_MEMOIZER ("@apply", m_apply, 2);
 SCM_DEFINE_MEMOIZER ("@call-with-current-continuation", m_call_cc, 1);
 SCM_DEFINE_MEMOIZER ("@call-with-values", m_call_values, 2);
 SCM_DEFINE_MEMOIZER ("@dynamic-wind", m_dynamic_wind, 3);
@@ -543,41 +538,6 @@ SCM_DEFINE_MEMOIZER ("@dynamic-wind", m_dynamic_wind, 3);
 
 \f
 
-static SCM m_apply (SCM proc, SCM arg, SCM rest)
-#define FUNC_NAME "@apply"
-{
-  long len;
-  
-  SCM_VALIDATE_MEMOIZED (1, proc);
-  SCM_VALIDATE_MEMOIZED (2, arg);
-  len = scm_ilength (rest);
-  if (len < 0)
-    abort ();
-  else if (len == 0)
-    return MAKMEMO_APPLY (proc, arg);
-  else
-    {
-      SCM tail;
-
-      rest = scm_reverse (rest);
-      tail = scm_car (rest);
-      rest = scm_cdr (rest);
-      len--;
-      
-      while (scm_is_pair (rest))
-        {
-          tail = MAKMEMO_CALL (MAKMEMO_MOD_REF (scm_list_1 (scm_from_latin1_symbol ("guile")),
-                                                scm_from_latin1_symbol ("cons"),
-                                                SCM_BOOL_F),
-                               2,
-                               scm_list_2 (scm_car (rest), tail));
-          rest = scm_cdr (rest);
-        }
-      return MAKMEMO_APPLY (proc, tail);
-    }
-}
-#undef FUNC_NAME
-
 static SCM m_call_cc (SCM proc)
 #define FUNC_NAME "@call-with-current-continuation"
 {
@@ -666,7 +626,8 @@ unmemoize (const SCM expr)
   switch (SCM_MEMOIZED_TAG (expr))
     {
     case SCM_M_APPLY:
-      return scm_cons (scm_sym_atapply, unmemoize_exprs (args));
+      return scm_cons (scm_from_latin1_symbol ("apply"),
+                       unmemoize_exprs (args));
     case SCM_M_SEQ:
       return scm_list_3 (scm_sym_begin, unmemoize (CAR (args)),
                          unmemoize (CDR (args)));
index 764aa42..3bd37eb 100644 (file)
@@ -3,7 +3,7 @@
 #ifndef SCM_MEMOIZE_H
 #define SCM_MEMOIZE_H
 
-/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002,2004,2008,2009,2010,2011
+/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002,2004,2008,2009,2010,2011,2013
  * Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
@@ -48,7 +48,6 @@ SCM_API SCM scm_sym_with_fluids;
 
 SCM_API SCM scm_sym_at;
 SCM_API SCM scm_sym_atat;
-SCM_API SCM scm_sym_atapply;
 SCM_API SCM scm_sym_atcall_cc;
 SCM_API SCM scm_sym_at_call_with_values;
 SCM_API SCM scm_sym_delay;
index 4a884d8..7760a2c 100644 (file)
@@ -192,7 +192,7 @@ If there is no handler at all, Guile prints an error and then exits."
 ;;;
 
 ;; These are are the procedural wrappers around the primitives of
-;; Guile's language: @apply, @call-with-current-continuation, etc.
+;; Guile's language: apply, call-with-current-continuation, etc.
 ;;
 ;; Usually, a call to a primitive is compiled specially.  The compiler
 ;; knows about all these kinds of expressions.  But the primitives may
@@ -200,8 +200,18 @@ If there is no handler at all, Guile prints an error and then exits."
 ;; stub procedures are the "values" of apply, dynamic-wind, and other
 ;; such primitives.
 ;;
-(define (apply fun . args)
-  (@apply fun (apply:nconc2last args)))
+(define apply
+  (case-lambda
+    ((fun args)
+     ((@@ primitive apply) fun args))
+    ((fun arg1 . args)
+     (letrec ((append* (lambda (tail)
+                         (let ((tail (car tail))
+                               (tail* (cdr tail)))
+                           (if (null? tail*)
+                               tail
+                               (cons tail (append* tail*)))))))
+       (apply fun (cons arg1 (append* args)))))))
 (define (call-with-current-continuation proc)
   (@call-with-current-continuation proc))
 (define (call-with-values producer consumer)
index c06a1f6..c211f37 100644 (file)
 
       ((<primcall> src name args)
        (pmatch (cons name args)
-         ((@apply ,proc . ,args)
+         ((apply ,proc . ,args)
           (cond
            ((and (primitive-ref? proc) (eq? (primitive-ref-name proc) 'values)
                  (not (eq? context 'push)) (not (eq? context 'vals)))
                (emit-code src (make-glil-call 'apply (1+ (length args))))
                (maybe-emit-return))
               (else
-               (comp-tail (make-primcall src 'apply (cons proc args))))))))
+               (comp-tail (make-call src (make-primitive-ref #f 'apply)
+                                     (cons proc args))))))))
 
          ((values . _)
           ;; tail: (lambda () (values '(1 2)))
index 27da460..a7504fd 100644 (file)
@@ -861,7 +861,7 @@ top-level bindings from ENV and return the resulting expression."
           (names ... rest)
           (gensyms ... rest-sym)
           (vals ... ($ <primcall> _ 'list rest-args))
-          ($ <primcall> asrc (or 'apply '@apply)
+          ($ <primcall> asrc 'apply
              (proc args ...
                    ($ <lexical-ref> _
                       (? (cut eq? <> rest))
@@ -1192,7 +1192,7 @@ top-level bindings from ENV and return the resulting expression."
                (for-tail (list->seq src (append (cdr vals) (list (car vals)))))
                (make-primcall src 'values vals))))))
 
-      (($ <primcall> src (or 'apply '@apply) (proc args ... tail))
+      (($ <primcall> src 'apply (proc args ... tail))
        (let lp ((tail* (find-definition tail 1)) (speculative? #t))
          (define (copyable? x)
            ;; Inlining a result from find-definition effectively copies it,
@@ -1205,7 +1205,7 @@ top-level bindings from ENV and return the resulting expression."
               (for-tail (make-call src proc (append args args*)))))
            (($ <primcall> _ 'cons
                ((and head (? copyable?)) (and tail (? copyable?))))
-            (for-tail (make-primcall src '@apply
+            (for-tail (make-primcall src 'apply
                                      (cons proc
                                            (append args (list head tail))))))
            (($ <primcall> _ 'list
@@ -1215,7 +1215,7 @@ top-level bindings from ENV and return the resulting expression."
             (if speculative?
                 (lp (for-value tail) #f)
                 (let ((args (append (map for-value args) (list tail*))))
-                  (make-primcall src '@apply
+                  (make-primcall src 'apply
                                  (cons (for-value proc) args))))))))
 
       (($ <primcall> src (? constructor-primitive? name) args)
@@ -1461,7 +1461,7 @@ top-level bindings from ENV and return the resulting expression."
        (define (lift-applied-lambda body gensyms)
          (and (not opt) rest (not kw)
               (match body
-                (($ <primcall> _ '@apply
+                (($ <primcall> _ 'apply
                     (($ <lambda> _ _ (and lcase ($ <lambda-case>)))
                      ($ <lexical-ref> _ _ sym)
                      ...))
index fb30082..db80d8a 100644 (file)
@@ -36,7 +36,7 @@
 ;; When adding to this, be sure to update *multiply-valued-primitives*
 ;; if appropriate.
 (define *interesting-primitive-names* 
-  '(apply @apply
+  '(apply
     call-with-values @call-with-values
     call-with-current-continuation @call-with-current-continuation
     call/cc
 
 ;; Primitives that don't always return one value.
 (define *multiply-valued-primitives* 
-  '(apply @apply
+  '(apply
     call-with-values @call-with-values
     call-with-current-continuation @call-with-current-continuation
     call/cc
 (define-primitive-expander acons (x y z)
   (cons (cons x y) z))
 
-(define-primitive-expander apply (f a0 . args)
-  (@apply f a0 . args))
-
 (define-primitive-expander call-with-values (producer consumer)
   (@call-with-values producer consumer))
 
index 7322d61..0beeb75 100644 (file)
     (let (args) (_) ((primcall list (const 2) (const 3)))
          (seq
           (call (toplevel foo!) (lexical args _))
-          (primcall @apply
+          (primcall apply
                     (lambda ()
                       (lambda-case
                        (((x y z w) #f #f #f () (_ _ _ _))
                 bv
                 (+ offset 4))))
         (let ((args (list x y)))
-          (@apply
+          (apply
            (lambda (bv offset x y)
              (bytevector-ieee-single-native-set!
               bv
     ;; Here we ensure that non-constant expressions are not copied.
     (lambda ()
       (let ((args (list (foo!))))
-        (@apply
+        (apply
          (lambda (z x)
            (list z x))
          ;; This toplevel ref might raise an unbound variable exception.
     (lambda ()
       (let ((args (list 'foo)))
         (set-car! args 'bar)
-        (@apply
+        (apply
          (lambda (z x)
            (list z x))
          z
              ((primcall list (const foo)))
              (seq
               (primcall set-car! (lexical args _) (const bar))
-              (primcall @apply
+              (primcall apply
                         (lambda . _)
                         (toplevel z)
                         (lexical args _))))))))
           (lambda-case
            ((() #f vals #f () (_))
             (seq (toplevel baz)
-                 (primcall @apply (primitive values) (lexical vals _))))))))
+                 (primcall apply (primitive values) (lexical vals _))))))))
   
   (pass-if-peval
    ;; Prompt is removed if tag is unreferenced
                 (const 1)
                 (lambda-case
                  ((() #f args #f () (_))
-                  (primcall @apply
+                  (primcall apply
                             (lexical handler _)
                             (lexical args _)))))))
 
index 9407791..eee54e6 100644 (file)
@@ -1,7 +1,7 @@
 ;;;; procprop.test --- Procedure properties -*- mode: scheme; coding: utf-8; -*-
 ;;;; Ludovic Courtès <ludo@gnu.org>
 ;;;;
-;;;;   Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+;;;;   Copyright (C) 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -49,7 +49,7 @@
 
   (pass-if "apply"
     (equal? (procedure-minimum-arity apply)
-            '(1 0 #t)))
+            '(2 0 #t)))
 
   (pass-if "cons*"
     (equal? (procedure-minimum-arity cons*)
index 679e173..56c898c 100644 (file)
@@ -2,7 +2,7 @@
 ;;;; Jim Blandy <jimb@red-bean.com> --- August 1999
 ;;;;
 ;;;; Copyright (C) 1999, 2001, 2004, 2005, 2006, 2008, 2009, 2010,
-;;;;   2011 Free Software Foundation, Inc.
+;;;;   2011, 2013 Free Software Foundation, Inc.
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
 (with-test-prefix "string"
 
   (pass-if-exception "convert circular list to string"
-     exception:wrong-type-arg
-     (let ((foo (list #\a #\b #\c)))
-       (set-cdr! (cddr foo) (cdr foo))
-       (apply string foo))))
+    '(wrong-type-arg . "Apply to non-list")
+    (let ((foo (list #\a #\b #\c)))
+      (set-cdr! (cddr foo) (cdr foo))
+      (apply string foo))))
  
 (with-test-prefix "string-split"
 
index 50847fd..059cb82 100644 (file)
 
 (with-test-prefix "apply"
   (assert-tree-il->glil
-   (primcall @apply (toplevel foo) (toplevel bar))
+   (primcall apply (toplevel foo) (toplevel bar))
    (program () (std-prelude 0 0 #f) (label _) (toplevel ref foo) (toplevel ref bar) (call tail-apply 2)))
   (assert-tree-il->glil
-   (begin (primcall @apply (toplevel foo) (toplevel bar)) (void))
+   (begin (primcall apply (toplevel foo) (toplevel bar)) (void))
    (program () (std-prelude 0 0 #f) (label _)
             (call new-frame 0) (toplevel ref apply) (toplevel ref foo) (toplevel ref bar) (mv-call 2 ,l1)
             (call drop 1) (branch br ,l2) (label ,l3) (mv-bind 0 #f)
             (void) (call return 1))
    (and (eq? l1 l3) (eq? l2 l4)))
   (assert-tree-il->glil
-   (call (toplevel foo) (call (toplevel @apply) (toplevel bar) (toplevel baz)))
+   (call (toplevel foo) (call (toplevel apply) (toplevel bar) (toplevel baz)))
    (program () (std-prelude 0 0 #f) (label _)
             (toplevel ref foo)
             (call new-frame 0) (toplevel ref bar) (toplevel ref baz) (call apply 2)