~ chicken-core (chicken-5) 77e53c7e8648a6ec9a3a605fa131626fd7a31be9


commit 77e53c7e8648a6ec9a3a605fa131626fd7a31be9
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Mon Aug 22 01:13:06 2011 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Mon Aug 22 01:13:06 2011 +0200

    if it goes on like this, I'll go mad

diff --git a/compiler-namespace.scm b/compiler-namespace.scm
index 766c21d4..b1929b17 100644
--- a/compiler-namespace.scm
+++ b/compiler-namespace.scm
@@ -182,6 +182,7 @@
  inline-table-used
  inlining
  insert-timer-checks
+ install-specializations
  installation-home
  internal-bindings
  intrinsic?
diff --git a/compiler.scm b/compiler.scm
index 0edf2b3c..b0e04381 100644
--- a/compiler.scm
+++ b/compiler.scm
@@ -1516,8 +1516,8 @@
 			  (when pred
 			    (mark-variable name '##compiler#predicate pred))
 			  (when (pair? (cddr spec))
-			    (mark-variable
-			     name '##compiler#specializations
+			    (install-specializations 
+			     name 
 			     (##sys#strip-syntax (cddr spec)))))
 			 (else
 			  (warning 
diff --git a/scrutinizer.scm b/scrutinizer.scm
index 5d997ef7..2978cc00 100755
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -297,7 +297,7 @@
 		    ""))
 	      "")
 	  (fragment (first (node-subexpressions node)))))
-      (d "  call-result: ~a " args)
+      (d "  call: ~a " args)
       (let* ((ptype (car args))
 	     (pptype? (procedure-type? ptype))
 	     (nargs (length (cdr args)))
@@ -382,21 +382,21 @@
 				       (let* ((spec (car specs))
 					      (stype (first spec))
 					      (tenv2 (append (append-map type-typeenv stype) typeenv)))
-					   (cond ((match-argument-types
-						   stype (cdr args) tenv2
-						   #t)
-						  (set! op (cons pn (car spec)))
-						  (set! typeenv tenv2)
-						  (let* ((r2 (and (pair? (cddr spec))
-								  (second spec)))
-							 (rewrite (if r2
-								      (third spec)
-								      (second spec))))
-						    (specialize-node! node rewrite)
-						    (when r2 (set! r r2))))
-						 (else
-						  (trail-restore trail0 tenv2)
-						  (loop (cdr specs))))))))))
+					 (cond ((match-argument-types
+						 stype (cdr args) tenv2
+						 #t)
+						(set! op (cons pn (car spec)))
+						(set! typeenv tenv2)
+						(let* ((r2 (and (pair? (cddr spec))
+								(second spec)))
+						       (rewrite (if r2
+								    (third spec)
+								    (second spec))))
+						  (specialize-node! node rewrite)
+						  (when r2 (set! r r2))))
+					       (else
+						(trail-restore trail0 tenv2)
+						(loop (cdr specs))))))))))
 		       (when op
 			 (d "  specialized: `~s' for ~a" (car op) (cdr op))
 			 (cond ((assoc op specialization-statistics) =>
@@ -845,9 +845,8 @@
 (define (match-types t1 t2 typeenv #!optional exact all)
 
   (define (match-args args1 args2)
-    (d "match-args: ~s <-> ~s" args1 args2)
+    (d "match args: ~s <-> ~s" args1 args2)
     (let loop ((args1 args1) (args2 args2) (opt1 #f) (opt2 #f))
-      (dd "  args ~a ~a ~a ~a" args1 args2 opt1 opt2)
       (cond ((null? args1) 
 	     (or opt2
 		 (null? args2)
@@ -1199,7 +1198,7 @@
 	  ((memq t1 '(vector list)) (type<=? `(,t1 *) t2))
 	  ((and (eq? 'null t1)
 		(pair? t2) 
-		(memq (car t2) '(pair list))))
+		(eq? (car t2) 'list)))
 	  ((and (pair? t1) (eq? 'forall (car t1)))
 	   (set! typeenv (append (map (cut cons <> #f) (second t1)) typeenv))
 	   (type<=? (third t1) t2))
@@ -1520,8 +1519,7 @@
 		  name new old)))
 	     (mark-variable name '##compiler#type t)
 	     (when specs
-	       ;;XXX validate types in specs
-	       (mark-variable name '##compiler#specializations specs)))))
+	       (install-specializations name specs)))))
        (read-file dbfile))
       #t)))
 
@@ -1636,6 +1634,9 @@
 		    (set! usedvars (cons t usedvars))
 		    t)
 		   (else #f)))
+	    ((eq? 'not (car t))
+	     (and (= 2 (length t))
+		  `(not ,(validate (second t)))))
 	    ((eq? 'forall (car t))
 	     (and (= 3 (length t))
 		  (list? (second t))
@@ -1714,6 +1715,51 @@
 	       (values type (and ptype (eq? (car ptype) type) (cdr ptype))))))
 	  (else (values #f #f)))))
 
+(define (install-specializations name specs)
+  (define (fail spec)
+    (error "invalid specialization format" spec name))
+  (mark-variable 
+   name '##compiler#specializations
+   ;;XXX it would be great if result types could refer to typevars
+   ;;    bound in the argument types, like this:
+   ;;
+   ;; (: with-input-from-file ((-> . *) -> . *)
+   ;;    (((forall (a) (-> a))) (a) ...code that does it single-valued-ly...))
+   ;;
+   ;; This would make it possible to propagate the (single) result type from
+   ;; the thunk to the enclosing expression. Unfortunately the simplification in
+   ;; the first validation renames typevars, so the second validation will have
+   ;; non-matching names.
+   (map (lambda (spec)
+	  (if (and (list? spec) (list? (first spec)))
+	      (let* ((args
+		      (map (lambda (t) 
+			     (let-values (((t2 _) (validate-type t #f)))
+			       (or t2
+				   (error "invalid argument type in specialization" 
+					  t spec name))))
+			   (first spec)))
+		     (typevars (unzip1 (append-map type-typeenv args))))
+		(cons
+		 args
+		 (case (length spec)
+		   ((2) (cdr spec))
+		   ((3) 
+		    (cond ((list? (second spec))
+			   (cons
+			    (map (lambda (t)
+				   (let-values (((t2 _) (validate-type t #f)))
+				     (or t2
+					 (error "invalid result type in specialization" 
+						t spec name))))
+				 (second spec))
+			    (cddr spec)))
+			  ((eq? '* (second spec)) (cdr spec))
+			  (else (fail spec))))
+		   (else (fail spec)))))
+	      (fail spec)))
+	specs)))
+
 
 ;;; hardcoded result types for certain primitives
 
diff --git a/tests/runtests.sh b/tests/runtests.sh
index 2e15b2f4..31bdf6d5 100644
--- a/tests/runtests.sh
+++ b/tests/runtests.sh
@@ -4,6 +4,7 @@
 # - Note: this needs a proper shell, so it will not work with plain mingw
 #   (just the compiler and the Windows shell, without MSYS)
 
+
 set -e
 TEST_DIR=`pwd`
 OS_NAME=`uname -s`
@@ -13,22 +14,6 @@ export LIBRARY_PATH=${TEST_DIR}/..:${LIBRARY_PATH}
 
 mkdir -p test-repository
 
-# copy files into test-repository (by hand to avoid calling `chicken-install'):
-
-for x in setup-api.so setup-api.import.so setup-download.so \
-      setup-download.import.so chicken.import.so lolevel.import.so \
-      srfi-1.import.so srfi-4.import.so data-structures.import.so \
-      ports.import.so files.import.so posix.import.so \
-      srfi-13.import.so srfi-69.import.so extras.import.so \
-      irregex.import.so srfi-14.import.so tcp.import.so \
-      foreign.import.so scheme.import.so srfi-18.import.so \
-      utils.import.so csi.import.so irregex.import.so types.db; do
-  cp ../$x test-repository
-done
-
-#XXX
-cp ../types.db.new test-repository
-
 CHICKEN_REPOSITORY=${TEST_DIR}/test-repository
 CHICKEN=../chicken
 CHICKEN_INSTALL=${TEST_DIR}/../chicken-install
@@ -38,6 +23,11 @@ FAST_OPTIONS="-O5 -d0 -b -disable-interrupts"
 
 $CHICKEN_INSTALL -init ${TEST_DIR}/test-repository
 
+#TYPESDB=../types.db
+#XXX
+TYPESDB=../types.db.new
+cp $TYPESDB test-repository/types.db
+
 if test -n "$MSYSTEM"; then
     CHICKEN="..\\chicken.exe"
     ASMFLAGS=-Wa,-w
@@ -67,7 +57,7 @@ $compile inlining-tests.scm -optimize-level 3
 echo "======================================== scrutiny tests ..."
 $compile typematch-tests.scm -specialize -w
 ./a.out
-$compile scrutiny-tests.scm -scrutinize -ignore-repository -types ../types.db 2>scrutiny.out -verbose
+$compile scrutiny-tests.scm -scrutinize -ignore-repository -types $TYPESDB 2>scrutiny.out -verbose
 
 if test -n "$MSYSTEM"; then
     dos2unix scrutiny.out
@@ -80,7 +70,7 @@ fi
 
 diff -bu scrutiny.expected scrutiny.out
 
-$compile scrutiny-tests-2.scm -scrutinize -analyze-only -ignore-repository -types ../types.db 2>scrutiny-2.out -verbose
+$compile scrutiny-tests-2.scm -scrutinize -analyze-only -ignore-repository -types $TYPESDB 2>scrutiny-2.out -verbose
 
 if test -n "$MSYSTEM"; then
     dos2unix scrutiny.out
diff --git a/tests/scrutiny.expected b/tests/scrutiny.expected
index 23691128..f60ccdbe 100644
--- a/tests/scrutiny.expected
+++ b/tests/scrutiny.expected
@@ -6,7 +6,7 @@ Note: in local procedure `c',
   in local procedure `b',
   in toplevel procedure `a':
   expected value of type boolean in conditional but were given a value of type
-   `number' which is always true:
+  `number' which is always true:
 
 (if x3 '1 '2)
 
@@ -37,7 +37,7 @@ Warning: at toplevel:
   scrutiny-tests.scm:28: in procedure call to `+', expected argument #2 of type `number', but was given an argument of type `symbol'
 
 Warning: at toplevel:
-  assignment of value of type `fixnum' to toplevel variable `car' does not match declared type `(procedure car (pair) *)'
+  assignment of value of type `fixnum' to toplevel variable `car' does not match declared type `(forall (a99) (procedure car ((pair a99 *)) a99))'
 
 Warning: at toplevel:
   expected in `let' binding of `g8' a single result, but were given 2 results
diff --git a/tests/typematch-tests.scm b/tests/typematch-tests.scm
index 43915a11..1b5ce750 100644
--- a/tests/typematch-tests.scm
+++ b/tests/typematch-tests.scm
@@ -89,7 +89,7 @@
 	     (((not ,type)) 'ok-too))
 	  (define (,fname x) 'bomb)
 	  (assert (eq? 'ok (,fname ,val)) "did not specialize" ',val ',type)
-	  (assert (eq? 'ok-too (,fname ,nval)) "did specialize" ',val ',type)
+	  (assert (eq? 'ok-too (,fname ,nval)) "did specialize" ',nval ',type)
 	  (: ,fname2 (* -> *)
 	     (((not ,type)) 'bomb))
 	  (define (,fname2 x) 'ok)
diff --git a/types.db.new b/types.db.new
index ee6f5eeb..2870bfe7 100644
--- a/types.db.new
+++ b/types.db.new
@@ -57,7 +57,7 @@
 
 (equal? (procedure equal? (* *) boolean)
 	(((or fixnum symbol char eof null undefined) *) (eq? #(1) #(2)))
-	((* (or fixnum symbol char eof null undefined) (eq? #(1) #(2)))))
+	((* (or fixnum symbol char eof null undefined)) (eq? #(1) #(2))))
 
 (pair? (procedure? pair pair? (*) boolean))
 
@@ -227,6 +227,7 @@
      ((float float) (##core#inline "C_i_flonum_min" #(1) #(2))))
 
 (+ (procedure! + (#!rest number) number)
+   (() (fixnum) '0)
    ((fixnum) (fixnum) #(1))
    ((float) (float) #(1))
    ((number) #(1))
@@ -263,6 +264,7 @@
     (##core#inline_allocate ("C_a_i_flonum_negate" 4) #(1))))
 
 (* (procedure! * (#!rest number) number)
+   (() (fixnum) '1)
    ((fixnum) (fixnum) #(1))
    ((float) (float) #(1))
    ((number) (number) #(1))
@@ -534,7 +536,7 @@
 (##sys#apply (procedure! ##sys#apply (procedure #!rest) . *))
 
 (force (procedure force (*) *)
-       ((not (struct promise)) #(1)))
+       (((not (struct promise))) #(1)))
 
 (call-with-current-continuation
  (procedure! call-with-current-continuation ((procedure (procedure) . *)) . *))
@@ -607,10 +609,10 @@
 (char-ready? (procedure! char-ready? (#!optional port) boolean))
 
 (imag-part (procedure! imag-part (number) number)
-	   ((or fixnum float number) (let ((#(tmp) #(1))) '0)))
+	   (((or fixnum float number)) (let ((#(tmp) #(1))) '0)))
 
 (real-part (procedure! real-part (number) number)
-	   ((or fixnum float number) #(1)))
+	   (((or fixnum float number)) #(1)))
 
 (magnitude (procedure! magnitude (number) number)
 	   ((fixnum) (fixnum)
@@ -722,7 +724,7 @@
 
 (equal=? (procedure equal=? (* *) boolean)
 	 (((or fixnum symbol char eof null undefined) *) (eq? #(1) #(2)))
-	 ((* (or fixnum symbol char eof null undefined) (eq? #(1) #(2))))
+	 ((* (or fixnum symbol char eof null undefined)) (eq? #(1) #(2)))
 	 (((or float number) (or float number)) (= #(1) #(2))))
 
 (er-macro-transformer
@@ -1028,7 +1030,7 @@
 		  (((or null pair list) *) (let ((#(tmp) #(1))) '#t)))
 (##sys#check-string (procedure! ##sys#check-string (string #!optional *) *)
 		    ((string) (let ((#(tmp) #(1))) '#t))
-		    ((string) *  (let ((#(tmp) #(1))) '#t)))
+		    ((string) * (let ((#(tmp) #(1))) '#t)))
 (##sys#check-number (procedure! ##sys#check-number (number #!optional *) *)
 		    ((number) (let ((#(tmp) #(1))) '#t))
 		    ((number *) (let ((#(tmp) #(1))) '#t)))
@@ -1738,7 +1740,13 @@
 (fold (procedure! fold ((procedure (* #!rest) *) * #!rest list) *)) ;XXX
 (fold-right (procedure! fold-right ((procedure (* #!rest) *) * #!rest list) *)) ;XXX
 
-(fourth (forall (a) (procedure! fourth ((pair * (pair * (pair * (pair a *))))) a)))
+(fourth (forall (a) (procedure! fourth ((pair * (pair * (pair * (pair a *))))) a))
+	(((pair * (pair * (pair * (pair * *)))))
+	 (##core#inline "C_u_i_car" 
+			(##core#inline "C_u_i_cdr"
+				       (##core#inline "C_u_i_cdr"
+						      (##core#inline "C_u_i_cdr" #(1)))))))
+
 (iota (procedure! iota (fixnum #!optional fixnum fixnum) (list number)))
 (last (procedure! last (pair) *))
 (last-pair (procedure! last-pair (pair) *))
Trap