don't propagate pure primcalls that might not type-check
authorAndy Wingo <wingo@pobox.com>
Tue, 27 Sep 2011 21:20:49 +0000 (23:20 +0200)
committerAndy Wingo <wingo@pobox.com>
Tue, 27 Sep 2011 22:13:56 +0000 (00:13 +0200)
* module/language/tree-il/optimize.scm (types-check?): New helper, to
  determine if a primcall will apply without throwing an exception.
  (peval): constant-expression? returns #f for expressions that don't
  types-check?.  Effect-free primitives that type-check are void.

module/language/tree-il/optimize.scm
test-suite/tests/tree-il.test

index e9317ef..369c2e4 100644 (file)
@@ -296,6 +296,16 @@ references to the new symbols."
     (transfer! current c effort-limit size-limit)
     c))
 
+(define (types-check? primitive-name args)
+  (case primitive-name
+    ((values) #t)
+    ((not pair? null? list? symbol? vector? struct?)
+     (= (length args) 1))
+    ((eq? eqv? equal?)
+     (= (length args) 2))
+    ;; FIXME: add more cases?
+    (else #f)))
+
 (define* (peval exp #:optional (cenv (current-module)) (env vlist-null)
                 #:key
                 (operator-size-limit 40)
@@ -472,6 +482,7 @@ it does not handle <fix> and <let-values>, it should be called before
         (($ <application> _ ($ <primitive-ref> _ name) args)
          (and (effect-free-primitive? name)
               (not (constructor-primitive? name))
+              (types-check? name args)
               (every loop args)))
         (($ <application> _ ($ <lambda> _ _ body) args)
          (and (loop body) (every loop args)))
@@ -818,7 +829,11 @@ it does not handle <fix> and <let-values>, it should be called before
                            (make-values src (map (cut make-const src <>)
                                                  values))))
                         (make-application src proc args)))
-                  (make-application src proc args))))
+                  (cond
+                   ((and (eq? ctx 'effect) (types-check? name args))
+                    (make-void #f))
+                   (else
+                    (make-application src proc args))))))
            (($ <lambda> _ _
                ($ <lambda-case> _ req opt #f #f inits gensyms body #f))
             ;; Simple case: no rest, no keyword arguments.
index cd33143..d98700a 100644 (file)
     (let (x) (_) ((if (apply (primitive >) (toplevel p) (toplevel q))
                       (apply (toplevel frob!))
                       (apply (toplevel display) (const chbouib))))
-         (apply (primitive +) (lexical x _) (lexical x _)
-                (apply (primitive *) (lexical x _) (const 2)))))
+         (let (y) (_) ((apply (primitive *) (lexical x _) (const 2)))
+              (apply (primitive +)
+                     (lexical x _) (lexical x _) (lexical y _)))))
 
   (pass-if-peval
     ;; Non-constant arguments not propagated to lambdas.