GOOPS cosmetics
[bpt/guile.git] / test-suite / tests / compiler.test
dissimilarity index 67%
index d83167f..02f2a54 100644 (file)
-;;;; compiler.test --- tests for the compiler      -*- scheme -*-
-;;;; Copyright (C) 1991, 1992, 1993, 1994, 1995, 1999, 2001, 2006 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
-;;;; License as published by the Free Software Foundation; either
-;;;; version 2.1 of the License, or (at your option) any later version.
-;;;; 
-;;;; 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.
-;;;; 
-;;;; 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-(define-module (test-suite tests compiler)
-  :use-module (test-suite lib)
-  :use-module (test-suite guile-test)
-  :use-module (system vm program))
-  
-
-(with-test-prefix "environments"
-
-  (pass-if "compile-time-environment in evaluator"
-    (eq? (primitive-eval '(compile-time-environment)) #f))
-
-  (pass-if "compile-time-environment in compiler"
-    (equal? (compile '(compile-time-environment))
-            (cons (current-module)
-                  (cons '() '()))))
-
-  (let ((env (compile
-              '(let ((x 0)) (set! x 1) (compile-time-environment)))))
-    (pass-if "compile-time-environment in compiler, heap-allocated var"
-             (equal? env
-                     (cons (current-module)
-                           (cons '((x . 0)) '(1)))))
-
-    ;; fixme: compiling with #t or module
-    (pass-if "recompiling with environment"
-             (equal? ((compile '(lambda () x) #:env env))
-                     1))
-
-    (pass-if "recompiling with environment/2"
-             (equal? ((compile '(lambda () (set! x (1+ x)) x) #:env env))
-                     2))
-
-    (pass-if "recompiling with environment/3"
-             (equal? ((compile '(lambda () x) #:env env))
-                     2))
-    )
-
-  (pass-if "compile environment is #f"
-           (equal? ((compile '(lambda () 10)))
-                   10))
-
-  (pass-if "compile environment is a module"
-           (equal? ((compile '(lambda () 10) #:env (current-module)))
-                   10))
-  )
\ No newline at end of file
+;;;; compiler.test --- tests for the compiler      -*- scheme -*-
+;;;; Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 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
+;;;; License as published by the Free Software Foundation; either
+;;;; version 3 of the License, or (at your option) any later version.
+;;;; 
+;;;; 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.
+;;;; 
+;;;; 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+(define-module (tests compiler)
+  #:use-module (test-suite lib)
+  #:use-module (test-suite guile-test)
+  #:use-module (system base compile)
+  #:use-module ((system vm loader) #:select (load-thunk-from-memory))
+  #:use-module ((system vm program) #:select (program-sources source:addr)))
+
+(define read-and-compile
+  (@@ (system base compile) read-and-compile))
+
+
+\f
+(with-test-prefix "basic"
+
+  (pass-if "compile to value"
+    (equal? (compile 1) 1)))
+
+\f
+(with-test-prefix "psyntax"
+
+  (pass-if "compile uses a fresh module by default"
+    (begin
+      (compile '(define + -))
+      (eq? (compile '+) +)))
+
+  (pass-if "compile-time definitions are isolated"
+    (begin
+      (compile '(define foo-bar #t))
+      (not (module-variable (current-module) 'foo-bar))))
+
+  (pass-if "compile in current module"
+    (let ((o (begin
+               (compile '(define-macro (foo) 'bar)
+                        #:env (current-module))
+               (compile '(let ((bar 'ok)) (foo))
+                        #:env (current-module)))))
+      (and (macro? (module-ref (current-module) 'foo))
+           (eq? o 'ok))))
+
+  (pass-if "compile in fresh module"
+    (let* ((m  (let ((m (make-module)))
+                 (beautify-user-module! m)
+                 m))
+           (o  (begin
+                 (compile '(define-macro (foo) 'bar) #:env m)
+                 (compile '(let ((bar 'ok)) (foo)) #:env m))))
+      (and (module-ref m 'foo)
+           (eq? o 'ok))))
+
+  (pass-if "redefinition"
+    ;; In this case the locally-bound `round' must have the same value as the
+    ;; imported `round'.  See the same test in `syntax.test' for details.
+    (let ((m (make-module)))
+      (beautify-user-module! m)
+      (compile '(define round round) #:env m)
+      (eq? round (module-ref m 'round)))))
+
+\f
+(with-test-prefix "current-reader"
+
+  (pass-if "default compile-time current-reader differs"
+    (not (eq? (compile 'current-reader)
+              current-reader)))
+
+  (pass-if "compile-time changes are honored and isolated"
+    ;; Make sure changing `current-reader' as the side-effect of a defmacro
+    ;; actually works.
+    (let ((r     (fluid-ref current-reader))
+          (input (open-input-string
+                  "(define-macro (install-reader!)
+                     ;;(format #t \"current-reader = ~A~%\" current-reader)
+                     (fluid-set! current-reader
+                                 (let ((first? #t))
+                                   (lambda args
+                                     (if first?
+                                         (begin
+                                           (set! first? #f)
+                                           ''ok)
+                                         (read (open-input-string \"\"))))))
+                     #f)
+                   (install-reader!)
+                   this-should-be-ignored")))
+      (and (eq? ((load-thunk-from-memory (read-and-compile input)))
+                'ok)
+           (eq? r (fluid-ref current-reader)))))
+
+  (pass-if "with eval-when"
+    (let ((r (fluid-ref current-reader)))
+      (compile '(eval-when (compile eval)
+                  (fluid-set! current-reader (lambda args 'chbouib))))
+      (eq? (fluid-ref current-reader) r))))
+
+\f
+(with-test-prefix "procedure-name"
+
+  (pass-if "program"
+    (let ((m  (make-module)))
+      (beautify-user-module! m)
+      (compile '(define (foo x) x) #:env m)
+      (eq? (procedure-name (module-ref m 'foo)) 'foo)))
+
+  (pass-if "program with lambda"
+    (let ((m  (make-module)))
+      (beautify-user-module! m)
+      (compile '(define foo (lambda (x) x)) #:env m)
+      (eq? (procedure-name (module-ref m 'foo)) 'foo)))
+
+  (pass-if "subr"
+    (eq? (procedure-name waitpid) 'waitpid)))
+
+\f
+(with-test-prefix "program-sources"
+
+  (with-test-prefix "source info associated with IP 0"
+
+    ;; Tools like `(system vm coverage)' like it when source info is associated
+    ;; with IP 0 of a VM program, which corresponds to the entry point.  See
+    ;; also <http://savannah.gnu.org/bugs/?29817> for details.
+
+    (pass-if "lambda"
+      (let ((s (program-sources (compile '(lambda (x) x)))))
+        (not (not (memv 0 (map source:addr s))))))
+
+    (pass-if "lambda*"
+      (let ((s (program-sources
+                (compile '(lambda* (x #:optional y) x)))))
+        (not (not (memv 0 (map source:addr s))))))
+
+    (pass-if "case-lambda"
+      (let ((s (program-sources
+                (compile '(case-lambda (()    #t)
+                                       ((y)   y)
+                                       ((y z) (list y z)))))))
+        (not (not (memv 0 (map source:addr s))))))))
+
+(with-test-prefix "case-lambda"
+  (pass-if "self recursion to different clause"
+    (equal? (with-output-to-string
+              (lambda ()
+                (let ()
+                  (define t
+                    (case-lambda
+                      ((x)
+                       (t x 'y))
+                      ((x y)
+                       (display (list x y))
+                       (list x y))))
+                  (display (t 'x)))))
+            "(x y)(x y)")))
+
+(with-test-prefix "limits"
+  (define (arg n)
+    (string->symbol (format #f "arg~a" n)))
+
+  ;; Cons and vector-set! take uint8 arguments, so this triggers the
+  ;; shuffling case.  Also there is the case where more than 252
+  ;; arguments causes shuffling.
+
+  (pass-if "300 arguments"
+    (equal? (apply (compile `(lambda ,(map arg (iota 300))
+                               'foo))
+                   (iota 300))
+            'foo))
+
+  (pass-if "300 arguments with list"
+    (equal? (apply (compile `(lambda ,(map arg (iota 300))
+                               (list ,@(reverse (map arg (iota 300))))))
+                   (iota 300))
+            (reverse (iota 300))))
+
+  (pass-if "300 arguments with vector"
+    (equal? (apply (compile `(lambda ,(map arg (iota 300))
+                               (vector ,@(reverse (map arg (iota 300))))))
+                   (iota 300))
+            (list->vector (reverse (iota 300)))))
+
+  (pass-if "0 arguments with list of 300 elements"
+    (equal? ((compile `(lambda ()
+                         (list ,@(map (lambda (n) `(identity ,n))
+                                      (iota 300))))))
+            (iota 300)))
+
+  (pass-if "0 arguments with vector of 300 elements"
+    (equal? ((compile `(lambda ()
+                         (vector ,@(map (lambda (n) `(identity ,n))
+                                        (iota 300))))))
+            (list->vector (iota 300)))))