change remaining %nil -> #nil
[bpt/guile.git] / test-suite / tests / elisp-compiler.test
index 5e9094a..61f0acd 100644 (file)
@@ -1,6 +1,6 @@
-;;;; elisp-compiler.test --- Test the compiler for Elisp.
+;;;; elisp-compiler.test --- Test the compiler for Elisp.  -*- scheme -*-
 ;;;;
-;;;; Copyright (C) 2009 Free Software Foundation, Inc.
+;;;; Copyright (C) 2009, 2010 Free Software Foundation, Inc.
 ;;;; Daniel Kraft
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
            (and (= a 0) (= b 0) (= c 0)
                 (= (unwind-protect 42 1 2 3) 42)))))
 
+(with-test-prefix/compile "Eval"
+
+  (pass-if-equal "basic eval" 3
+    (progn (setq code '(+ 1 2))
+           (eval code)))
+
+  (pass-if "real dynamic code"
+    (and (setq a 1 b 1 c 1)
+         (defun set-code (var val)
+           (list 'setq var val))
+         (= a 1) (= b 1) (= c 1)
+         (eval (set-code 'a '(+ 2 3)))
+         (eval (set-code 'c 42))
+         (= a 5) (= b 1) (= c 42)))
+
+  ; Build code that recursively again and again calls eval.  What we want is
+  ; something like:
+  ; (eval '(1+ (eval '(1+ (eval 1)))))
+  (pass-if "recursive eval"
+    (progn (setq depth 10 i depth)
+           (setq code '(eval 0))
+           (while (not (zerop i))
+             (setq code (\` (eval (quote (1+ (\, code))))))
+             (setq i (1- i)))
+           (= (eval code) depth))))
+
 
 ; Test handling of variables.
 ; ===========================
   (pass-if-equal "setq and reference" 6
     (progn (setq a 1 b 2 c 3)
            (+ a b c)))
+  (pass-if-equal "setq evaluation order" 1
+    (progn (setq a 0 b 0)
+           (setq a 1 b a)))
   (pass-if-equal "setq value" 2
     (progn (setq a 1 b 2)))
 
     #:opts '(#:disable-void-check all))
   (pass-if "disabled void check (symbol list)"
     (progn (makunbound 'a) a t)
-    #:opts '(#:disable-void-check (x y a b))))
+    #:opts '(#:disable-void-check (x y a b)))
+  (pass-if "without-void-checks"
+    (progn (makunbound 'a)
+           (= (without-void-checks (a) a 5) 5))))
 
 (with-test-prefix/compile "Let and Let*"
 
            (and (= a 0)
                 (= b 1)))))
 
+(with-test-prefix/compile "Lexical Scoping"
+
+  (pass-if "basic let semantics"
+    (and (setq a 1)
+         (lexical-let ((a 2) (b a))
+           (and (= a 2) (= b 1)))
+         (lexical-let* ((a 2) (b a))
+           (and (= a 2) (= b 2) (setq a 42) (= a 42)))
+         (= a 1)))
+
+  (pass-if "lexical scope with lexical-let's"
+    (and (setq a 1)
+         (defun dyna () a)
+         (lexical-let (a)
+           (setq a 2)
+           (and (= a 2) (= (dyna) 1)))
+         (= a 1)
+         (lexical-let* (a)
+           (setq a 2)
+           (and (= a 2) (= (dyna) 1)))
+         (= a 1)))
+
+  (pass-if "lexical scoping vs. symbol-value / set"
+    (and (setq a 1)
+         (lexical-let ((a 2))
+           (and (= a 2)
+                (= (symbol-value 'a) 1)
+                (set 'a 3)
+                (= a 2)
+                (= (symbol-value 'a) 3)))
+         (= a 3)))
+
+  (pass-if "let inside lexical-let"
+    (and (setq a 1 b 1)
+         (defun dynvals () (cons a b))
+         (lexical-let ((a 2))
+           (and (= a 2) (equal (dynvals) '(1 . 1))
+                (let ((a 3) (b a))
+                  (and (= a 3) (= b 2)
+                       (equal (dynvals) '(1 . 2))))
+                (let* ((a 4) (b a))
+                  (and (= a 4) (= b 4)
+                       (equal (dynvals) '(1 . 4))))
+                (= a 2)))
+         (= a 1)))
+
+  (pass-if "lambda args inside lexical-let"
+    (and (setq a 1)
+         (defun dyna () a)
+         (lexical-let ((a 2) (b 42))
+           (and (= a 2) (= (dyna) 1)
+                ((lambda (a) (and (= a 3) (= b 42) (= (dyna) 3))) 3)
+                ((lambda () (let ((a 3))
+                              (and (= a 3) (= (dyna) 1)))))
+                (= a 2) (= (dyna) 1)))
+         (= a 1)))
+
+  (pass-if "closures"
+    (and (defun make-counter ()
+           (lexical-let ((cnt 0))
+             (lambda ()
+               (setq cnt (1+ cnt)))))
+         (setq c1 (make-counter) c2 (make-counter))
+         (= (funcall c1) 1)
+         (= (funcall c1) 2)
+         (= (funcall c1) 3)
+         (= (funcall c2) 1)
+         (= (funcall c2) 2)
+         (= (funcall c1) 4)
+         (= (funcall c2) 3)))
+
+  (pass-if "always lexical option (all)"
+    (progn (setq a 0)
+           (defun dyna () a)
+           (let ((a 1))
+             (and (= a 1) (= (dyna) 0))))
+    #:opts '(#:always-lexical all))
+  (pass-if "always lexical option (list)"
+    (progn (setq a 0 b 0)
+           (defun dyna () a)
+           (defun dynb () b)
+           (let ((a 1)
+                 (b 1))
+             (and (= a 1) (= (dyna) 0)
+                  (= b 1) (= (dynb) 1))))
+    #:opts '(#:always-lexical (a)))
+  (pass-if "with-always-lexical"
+    (progn (setq a 0)
+           (defun dyna () a)
+           (with-always-lexical (a)
+             (let ((a 1))
+               (and (= a 1) (= (dyna) 0))))))
+
+  (pass-if "lexical lambda args"
+    (progn (setq a 1 b 1)
+           (defun dyna () a)
+           (defun dynb () b)
+           (with-always-lexical (a c)
+             ((lambda (a b &optional c)
+                (and (= a 3) (= (dyna) 1)
+                     (= b 2) (= (dynb) 2)
+                     (= c 1)))
+              3 2 1))))
+
+  ; Check if a lambda without dynamically bound arguments
+  ; is tail-optimized by doing a deep recursion that would otherwise overflow
+  ; the stack.
+  (pass-if "lexical lambda tail-recursion"
+    (with-always-lexical (i)
+      (setq to 1000000)
+      (defun iteration-1 (i)
+        (if (< i to)
+          (iteration-1 (1+ i))))
+      (iteration-1 0)
+      (setq x 0)
+      (defun iteration-2 ()
+        (if (< x to)
+          (setq x (1+ x))
+          (iteration-2)))
+      (iteration-2)
+      t)))
+
+
 (with-test-prefix/compile "defconst and defvar"
 
   (pass-if-equal "defconst without docstring" 3.141
            (defun bar (a)
              (foo))
            (and (= 43 (bar 42))
-                (zerop a)))))
+                (zerop a))))
+
+  (pass-if "funcall and apply argument handling"
+    (and (defun allid (&rest args) args)
+         (setq allid-var (symbol-function 'allid))
+         (equal (funcall allid-var 1 2 3) '(1 2 3))
+         (equal (funcall allid-var) nil)
+         (equal (funcall allid-var 1 2 '(3 4)) '(1 2 (3 4)))
+         (equal (funcall allid-var '()) '(()))
+         (equal (apply allid-var 1 2 '(3 4)) '(1 2 3 4))
+         (equal (apply allid-var '(1 2)) '(1 2))
+         (equal (apply allid-var '()) nil)))
+
+  (pass-if "raw functions with funcall"
+    (and (= (funcall '+ 1 2) 3)
+         (= (funcall (lambda (a b) (+ a b)) 1 2) 3)
+         (= (funcall '(lambda (a b) (+ a b)) 1 2) 3))))
 
 
 ; Quoting and Backquotation.
          (equal (nthcdr 1 '(1 2 3)) '(2 3))
          (equal (nthcdr 2 '(1 2 3)) '(3))))
 
+  (pass-if "length"
+    (and (= (length '()) 0)
+         (= (length '(1 2 3 4 5)) 5)
+         (= (length '(1 2 (3 4 (5)) 6)) 4)))
+
   (pass-if "cons, list and make-list"
     (and (equal (cons 1 2) '(1 . 2)) (equal (cons 1 '(2 3)) '(1 2 3))
          (equal (cons 1 '()) '(1))