~ chicken-core (chicken-5) 73ee51ffa0467d8b7116fb478f293dc5867bd66d


commit 73ee51ffa0467d8b7116fb478f293dc5867bd66d
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Mon Aug 29 04:28:04 2011 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Mon Aug 29 04:28:04 2011 +0200

    repaired define-specialization; various bugfixes; will this ever end?

diff --git a/chicken-syntax.scm b/chicken-syntax.scm
index 9cb1f655..c9ba3428 100644
--- a/chicken-syntax.scm
+++ b/chicken-syntax.scm
@@ -1103,29 +1103,6 @@
     (##core#let-compiler-syntax (binding ...) body ...))))
 
 
-;;; type-declaration syntax
-
-(##sys#extend-macro-environment
- ': '()
- (##sys#er-transformer
-  (lambda (x r c)
-    (##sys#check-syntax ': x '(_ symbol _ . _))
-    (if (memq #:csi ##sys#features) 
-	'(##core#undefined)
-	(let* ((type1 (##sys#strip-syntax (caddr x)))
-	       (name1 (cadr x)))
-	  (let-values (((type pred pure)
-			(##compiler#validate-type type1 (##sys#strip-syntax name1))))
-	    (cond ((not type)
-		   (syntax-error ': "invalid type syntax" name1 type1))
-		  (else
-		   `(##core#declare 
-		     (type (,name1 ,type ,@(cdddr x)))
-		     ,@(if pure `((pure ,name1)) '())
-		     (enforce-argument-types ,name1)
-		     ,@(if pred `((predicate (,name1 ,pred))) '()))))))))))
-
-
 ;;; interface definition
 
 (##sys#extend-macro-environment
@@ -1180,7 +1157,27 @@
 	(begin-for-syntax ,registration))))))
 
 
-;;; inline type declaration
+;;; type-related syntax
+
+(##sys#extend-macro-environment
+ ': '()
+ (##sys#er-transformer
+  (lambda (x r c)
+    (##sys#check-syntax ': x '(_ symbol _ . _))
+    (if (memq #:csi ##sys#features) 
+	'(##core#undefined)
+	(let* ((type1 (##sys#strip-syntax (caddr x)))
+	       (name1 (cadr x)))
+	  (let-values (((type pred pure)
+			(##compiler#validate-type type1 (##sys#strip-syntax name1))))
+	    (cond ((not type)
+		   (syntax-error ': "invalid type syntax" name1 type1))
+		  (else
+		   `(##core#declare 
+		     (type (,name1 ,type1 ,@(cdddr x)))
+		     ,@(if pure `((pure ,name1)) '())
+		     (enforce-argument-types ,name1)
+		     ,@(if pred `((predicate (,name1 ,pred))) '()))))))))))
 
 (##sys#extend-macro-environment
  'the '()
@@ -1202,14 +1199,14 @@
   (lambda (x r c)
     (cond ((memq #:csi ##sys#features) '(##core#undefined))
 	  (else
-	   (##sys#check-syntax 'define-specialization x '(_ (symbol . #(_ 0)) _ . #(_ 0 1)))
+	   (##sys#check-syntax 'define-specialization x '(_ (variable . #(_ 0)) _ . #(_ 0 1)))
 	   (let* ((head (cadr x))
 		  (name (car head))
 		  (gname (##sys#globalize name '())) ;XXX correct?
 		  (args (cdr head))
 		  (alias (gensym name))
 		  (galias (##sys#globalize alias '())) ;XXX and this?
-		  (rtypes (and (pair? (cdddr x)) (caddr x)))
+		  (rtypes (and (pair? (cdddr x)) (##sys#strip-syntax (caddr x))))
 		  (%define (r 'define))
 		  (body (if rtypes (cadddr x) (caddr x))))
 	     (let loop ((args args) (anames '()) (atypes '()))
@@ -1256,7 +1253,9 @@
 			       (loop (cdr args) (cons arg anames) (cons '* atypes)))
 			      ((and (list? arg) (fx= 2 (length arg)) (symbol? (car arg)))
 			       (let-values (((t pred pure)
-					     (##compiler#validate-type (cadr arg) #f)))
+					     (##compiler#validate-type
+					      (##sys#strip-syntax (cadr arg))
+					      #f)))
 				 (if t
 				     (loop
 				      (cdr args)
diff --git a/scrutinizer.scm b/scrutinizer.scm
index 027fecbf..eabd2b4d 100755
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -315,16 +315,16 @@
 		  (resolve ptype typeenv)))
 	       (values '* #f))
 	      (else
-	       (let-values (((atypes values-rest)
+	       (let-values (((atypes values-rest ok alen)
 			     (procedure-argument-types ptype nargs typeenv)))
-		 (unless (= (length atypes) nargs)
-		   (let ((alen (length atypes)))
-		     (report 
-		      loc
-		      (sprintf
-			  "~aexpected ~a argument~a, but was given ~a argument~a"
-			(pname) alen (multiples alen)
-			nargs (multiples nargs)))))
+		 (unless ok
+		   (report 
+		    loc
+		    (sprintf
+			"~aexpected ~a argument~a, but was given ~a argument~a"
+		      (pname)
+		      alen (multiples alen)
+		      nargs (multiples nargs))))
 		 (do ((args (cdr args) (cdr args))
 		      (atypes atypes (cdr atypes))
 		      (i 1 (add1 i)))
@@ -661,6 +661,8 @@
 			  (smash-component-types! e "env")
 			  (smash-component-types! blist "blist")))
 		      (cond (specialized?
+			     ;;XXX this will walk the arguments again, resulting in
+			     ;;    duplicate warnings
 			     (walk n e loc dest tail flow ctags)
 			     (smash)
 			     ;; keep type, as the specialization may contain icky stuff
@@ -1386,17 +1388,22 @@
 	 (else (bomb "procedure-results: not a procedure type" t)))))
 
 (define (procedure-argument-types t n typeenv #!optional norest)
-  (let loop1 ((t t) (done '())
+  (let loop1 ((t t) (done '()))
     (cond ((and (pair? t)
 		(eq? 'procedure (car t)))
 	   (let* ((vf #f)
+		  (ok #t)
+		  (alen 0)
 		  (llist
+		   ;; quite a mess
 		   (let loop ((at (if (or (string? (second t)) (symbol? (second t)))
 				      (third t)
 				      (second t)))
 			      (m n)
 			      (opt #f))
-		     (cond ((null? at) '())
+		     (cond ((null? at)
+			    (set! ok (or opt (zero? m)))
+			    '())
 			   ((eq? '#!optional (car at))
 			    (if norest
 				'()
@@ -1407,18 +1414,20 @@
 				   (set! vf (and (pair? (cdr at)) (eq? 'values (cadr at))))
 				   (make-list m (rest-type (cdr at))))))
 			   ((and opt (<= m 0)) '())
-			   (else (cons (car at) (loop (cdr at) (sub1 m) opt)))))))
-	     (values llist vf)))
-	  ((and (pair? t) 
-		(eq? 'forall (car t)))
+			   (else
+			    (set! ok (positive? m))
+			    (set! alen (add1 alen))
+			    (cons (car at) (loop (cdr at) (sub1 m) opt)))))))
+	     (values llist vf ok alen)))
+	  ((and (pair? t) (eq? 'forall (car t)))
 	   (loop1 (third t) done)) ; assumes typeenv has already been extracted
 	  ((assq t typeenv) =>
 	   (lambda (e)
 	     (let ((t2 (cdr e)))
 	       (if (memq t2 done)
 		   (loop1 '* done)		; circularity
-		   (loop1 t2 (cons t done)))))))))))
-	  (else (values (make-list n '*) #f)))))
+		   (loop1 t2 (cons t done))))))
+	  (else (values (make-list n '*) #f #t n)))))
 
 (define (procedure-result-types t values-rest? args typeenv)
   (define (loop1 t)
@@ -1690,6 +1699,7 @@
   ;; - returns converted type or #f
   ;; - also converts "(... -> ...)" types
   ;; - converts some typenames to struct types (u32vector, etc.)
+  ;; - handles some type aliases
   ;; - drops "#!key ..." args by converting to #!rest
   ;; - handles "(T1 -> T2 : T3)" (predicate) 
   ;; - handles "(T1 --> T2 [: T3])" (clean)
@@ -1735,6 +1745,8 @@
 	     `(struct ,t))
 	    ((eq? t 'immediate)
 	     '(or eof null fixnum char boolean))
+	    ((eq? t 'any) '*)
+	    ((eq? t 'void) 'undefined)
 	    ((not (pair? t)) 
 	     (cond ((memq t typevars)
 		    (set! usedvars (cons t usedvars))
@@ -1773,8 +1785,8 @@
 				`(procedure ,(upto t p) ,@(cdr p))
 				rec)))
 			 ((and (= 5 (length t))
-			       (eq? p (cdr t))
-			       (eq? cp (cdddr t)))
+			       (eq? p (cdr t)) ; one argument?
+			       (eq? cp (cdddr t))) ; 4th item is ":"?
 			  (set! t (validate `(procedure (,(first t)) ,(third t)) rec))
 			  ;; we do it this way to distinguish the "outermost" predicate
 			  ;; procedure type
@@ -1821,9 +1833,9 @@
 			    (lambda (v) (and (memq v usedvars) v))
 			    (delete-duplicates typevars eq?))
 			  ,type)))
-	     (let ((type (simplify-type type)))
+	     (let ((type2 (simplify-type type)))
 	       (values 
-		type 
+		type2
 		(and ptype (eq? (car ptype) type) (cdr ptype))
 		clean))))
 	  (else (values #f #f #f)))))
diff --git a/tests/scrutiny.expected b/tests/scrutiny.expected
index f60ccdbe..d3d2bbd9 100644
--- a/tests/scrutiny.expected
+++ b/tests/scrutiny.expected
@@ -60,6 +60,9 @@ Warning: in toplevel procedure `foo5':
 Warning: in toplevel procedure `foo6':
   scrutiny-tests.scm:82: in procedure call to `+', expected argument #1 of type `number', but was given an argument of type `string'
 
+Warning: at toplevel:
+  scrutiny-tests.scm:89: in procedure call to `+', expected argument #1 of type `number', but was given an argument of type `string'
+
 Warning: in toplevel procedure `foo9':
   scrutiny-tests.scm:97: in procedure call to `+', expected argument #1 of type `number', but was given an argument of type `string'
 
diff --git a/tests/specialization-test-1.scm b/tests/specialization-test-1.scm
index 5faaf120..9d380fcc 100644
--- a/tests/specialization-test-1.scm
+++ b/tests/specialization-test-1.scm
@@ -24,9 +24,16 @@ return n;}
   (print "bar: " i)
   0)
 
-(handle-exceptions ex #f (foo 1.0))	; failed type-check
 (assert (zero? (foo 1)))
 (assert (zero? (bar 1.0)))
 (assert (= 1 (bar 1)))
 
+(: spec (* -> *))
+(define (spec x) x)
+
+(define-specialization (spec (x fixnum)) fixnum
+  (+ x 1))
+
+(assert (= 2 (spec 1)))
+
 )
diff --git a/types.db b/types.db
index 426fc319..eec0045a 100644
--- a/types.db
+++ b/types.db
@@ -1135,7 +1135,12 @@
 (rassoc (#(procedure #:clean #:enforce) rassoc (* (list pair) #!optional (procedure (* *) *)) *))
 (reverse-string-append (#(procedure #:clean #:enforce) reverse-string-append ((list string)) string))
 (shuffle deprecated)
+
+;; really should be
+;;   (: sort (forall (e (s (or (vector e) (list e)))) (s (e e -> *) -> s)))
+;; if we had contraints for "forall"
 (sort (#(procedure #:enforce) sort ((or list vector) (procedure (* *) *)) (or list vector)))
+
 (sort! (#(procedure #:enforce) sort! ((or list vector) (procedure (* *) *)) (or list vector)))
 (sorted? (#(procedure #:enforce) sorted? ((or list vector) (procedure (* *) *)) boolean))
 (topological-sort (#(procedure #:enforce) topological-sort ((list list) (procedure (* *) *)) list))
Trap