~ chicken-core (chicken-5) b4d056ac344b69dee65a173e4d305276910819ef


commit b4d056ac344b69dee65a173e4d305276910819ef
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Mon Apr 18 00:13:44 2011 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Mon Apr 18 00:13:44 2011 +0200

    - added type-check routines for booleans and locatives
    - changed all node-constructions in compiler to not use constant parameter lists
      (or side-effecting one would create a shared side-effect - not sure if this can be
      the case, but who knows...)
    - -O5 enables -strict-types
    - declared types generate type-checks at procedure entry, unless unsafe or strict-types
    - specialization: assigned variables retain computed type if strict-types;
      no blist-invalidation anymore; using declared procedure-argument types as initial
      type-env entries for formal parameters; incompatible assignment to declared global
      removes type marks; blist-entries for assigned vars only if strict-types; no
      occurrance typing for assigned vars

diff --git a/c-platform.scm b/c-platform.scm
index 9946b65e..241e010d 100644
--- a/c-platform.scm
+++ b/c-platform.scm
@@ -169,7 +169,7 @@
   '(##sys#slot ##sys#setslot ##sys#block-ref ##sys#block-set!
     ##sys#call-with-current-continuation ##sys#size ##sys#byte ##sys#setbyte
     ##sys#pointer? ##sys#generic-structure? ##sys#structure? ##sys#check-structure
-    ##sys#check-exact ##sys#check-number ##sys#check-list ##sys#check-pair ##sys#check-string ##sys#check-symbol 
+    ##sys#check-exact ##sys#check-number ##sys#check-list ##sys#check-pair ##sys#check-string ##sys#check-symbol ##sys#check-boolean
     ##sys#check-char ##sys#check-vector ##sys#check-byte-vector ##sys#list ##sys#cons
     ##sys#call-with-values ##sys#fits-in-int? ##sys#fits-in-unsigned-int? ##sys#flonum-in-fixnum-range? 
     ##sys#fudge ##sys#immediate? ##sys#direct-return ##sys#context-switch
@@ -256,12 +256,12 @@
 	     (and (eq? 'quote (node-class x))
 		  (eq? 1 (first (node-parameters x))) ) ) 
 	   callargs) ] )
-     (cond [(null? callargs) (make-node '##core#call '(#t) (list cont (qnode 0)))]
+     (cond [(null? callargs) (make-node '##core#call (list #t) (list cont (qnode 0)))]
 	   [(null? (cdr callargs))
-	    (make-node '##core#call '(#t) (list cont (first callargs))) ]
+	    (make-node '##core#call (list #t) (list cont (first callargs))) ]
 	   [(eq? number-type 'fixnum)
 	    (make-node 
-	     '##core#call '(#t)
+	     '##core#call (list #t)
 	     (list
 	      cont
 	      (fold-inner
@@ -284,7 +284,7 @@
    (cond [(null? callargs) #f]
 	 [(and (null? (cdr callargs)) (eq? number-type 'fixnum))
 	  (make-node
-	   '##core#call '(#t)
+	   '##core#call (list #t)
 	   (list cont
 		 (make-node '##core#inline
 			    (if unsafe '("C_u_fixnum_negate") '("C_fixnum_negate"))
@@ -300,7 +300,7 @@
 	    (and (eq? number-type 'fixnum)
 		 (>= (length callargs) 2)
 		 (make-node
-		  '##core#call '(#t)
+		  '##core#call (list #t)
 		  (list 
 		   cont
 		   (fold-inner
@@ -327,7 +327,7 @@
 	  (and (eq? number-type 'fixnum)
 	       (>= (length callargs) 2)
 	       (make-node
-		'##core#call '(#t)
+		'##core#call (list #t)
 		(list
 		 cont
 		 (fold-inner
@@ -346,7 +346,7 @@
    (and (= (length callargs) 2)
 	(if (eq? 'fixnum number-type)
 	    (make-node
-	     '##core#call '(#t)
+	     '##core#call (list #t)
 	     (let ([arg2 (second callargs)])
 	       (list cont 
 		     (if (and (eq? 'quote (node-class arg2)) 
@@ -356,7 +356,7 @@
 			  (list (first callargs) (qnode 1)) )
 			 (make-node '##core#inline '("C_fixnum_divide") callargs) ) ) ) )
 	    (make-node
-	     '##core#call '(#t)
+	     '##core#call (list #t)
 	     (cons* (make-node '##core#proc '("C_quotient" #t) '()) cont callargs) ) ) ) ) )
 
 (let ()
@@ -369,7 +369,7 @@
   (define ((op1 fiop ufiop aiop) db classargs cont callargs)
     (and (= (length callargs) 1)
 	 (make-node
-	  '##core#call '(#t)
+	  '##core#call (list #t)
 	  (list 
 	   cont
 	   (if (eq? 'fixnum number-type)
@@ -390,13 +390,13 @@
 	   (or (and (eq? '##core#variable (node-class arg1))
 		    (eq? '##core#variable (node-class arg2))
 		    (equal? (node-parameters arg1) (node-parameters arg2))
-		    (make-node '##core#call '(#t) (list cont (qnode #t))) )
+		    (make-node '##core#call (list #t) (list cont (qnode #t))) )
 	       (and (or (and (eq? 'quote (node-class arg1))
 			     (not (flonum? (first (node-parameters arg1)))) )
 			(and (eq? 'quote (node-class arg2))
 			     (not (flonum? (first (node-parameters arg2)))) ) )
 		    (make-node
-		     '##core#call '(#t) 
+		     '##core#call (list #t) 
 		     (list cont (make-node '##core#inline '("C_eqp") callargs)) ) ) ) ) ) )
   (rewrite 'eqv? 8 eqv?-id)
   (rewrite '##sys#eqv? 8 eqv?-id))
@@ -413,7 +413,7 @@
 	  (or (and (eq? '##core#variable (node-class arg1))
 		   (eq? '##core#variable (node-class arg2))
 		   (equal? (node-parameters arg1) (node-parameters arg2))
-		   (make-node '##core#call '(#t) (list cont (qnode #t))) )
+		   (make-node '##core#call (list #t) (list cont (qnode #t))) )
 	      (and (or (and (eq? 'quote (node-class arg1))
 			    (let ([f (first (node-parameters arg1))])
 			      (or (immediate? f) (symbol? f)) ) )
@@ -421,10 +421,10 @@
 			    (let ([f (first (node-parameters arg2))])
 			      (or (immediate? f) (symbol? f)) ) ) )
 		   (make-node
-		    '##core#call '(#t) 
+		    '##core#call (list #t) 
 		    (list cont (make-node '##core#inline '("C_eqp") callargs)) ) )
 	      (make-node
-	       '##core#call '(#t) 
+	       '##core#call (list #t) 
 	       (list cont (make-node '##core#inline '("C_i_equalp") callargs)) ) ) ) ) ) )
 
 (let ()
@@ -438,7 +438,7 @@
 	       [proc (car callargs)] )
 	   (if (eq? 'quote (node-class lastarg))
 	       (make-node
-		'##core#call '(#f)
+		'##core#call (list #f)
 		(cons* (first callargs)
 		       cont 
 		       (append (cdr (butlast callargs)) (map qnode (first (node-parameters lastarg)))) ) )
@@ -448,12 +448,12 @@
 			  (and (memq name '(values ##sys#values))
 			       (intrinsic? name)
 			       (make-node
-				'##core#call '(#t)
+				'##core#call (list #t)
 				(list (make-node '##core#proc '("C_apply_values" #t) '())
 				      cont
 				      (cadr callargs) ) ) ) ) ) 
 		   (make-node
-		    '##core#call '(#t)
+		    '##core#call (list #t)
 		    (cons* (make-node '##core#proc '("C_apply" #t) '())
 			   cont callargs) ) ) ) ) ) )
   (rewrite 'apply 8 rewrite-apply)
@@ -472,7 +472,7 @@
 	     (lambda (return)
 	       (let ([arg (first callargs)])
 		 (make-node
-		  '##core#call '(#t)
+		  '##core#call (list #t)
 		  (list
 		   cont
 		   (cond [(and (eq? '##core#variable (node-class arg))
@@ -502,7 +502,7 @@
        (lambda (db classargs cont callargs)
 	 ;; (values <x>) -> <x>
 	 (and (= (length callargs) 1)
-	      (make-node '##core#call '(#t) (cons cont callargs) ) ) ) ] )
+	      (make-node '##core#call (list #t) (cons cont callargs) ) ) ) ] )
   (rewrite 'values 8 rvalues)
   (rewrite '##sys#values 8 rvalues) )
 
@@ -530,10 +530,10 @@
 				       '##core#lambda
 				       (list (gensym 'f_) #f (list tmpk) 0)
 				       (list (make-node
-					      '##core#call '(#t)
+					      '##core#call (list #t)
 					      (list arg2 cont (varnode tmpk)) ) ) ) 
 				      (make-node
-				       '##core#call '(#t)
+				       '##core#call (list #t)
 				       (list arg1 (varnode tmp)) ) ) ) ) ) ) ) ) ) ) ) )
   (rewrite 'call-with-values 8 rewrite-c-w-v)
   (rewrite '##sys#call-with-values 8 rewrite-c-w-v) )
@@ -738,6 +738,8 @@
 (rewrite '##sys#check-number 2 1 "C_i_check_number" #t)
 (rewrite '##sys#check-list 2 1 "C_i_check_list" #t)
 (rewrite '##sys#check-pair 2 1 "C_i_check_pair" #t)
+(rewrite '##sys#check-boolean 2 1 "C_i_check_boolean" #t)
+(rewrite '##sys#check-locative 2 1 "C_i_check_locative" #t)
 (rewrite '##sys#check-symbol 2 1 "C_i_check_symbol" #t)
 (rewrite '##sys#check-string 2 1 "C_i_check_string" #t)
 (rewrite '##sys#check-byte-vector 2 1 "C_i_check_bytevector" #t)
@@ -748,6 +750,8 @@
 (rewrite '##sys#check-number 2 2 "C_i_check_number_2" #t)
 (rewrite '##sys#check-list 2 2 "C_i_check_list_2" #t)
 (rewrite '##sys#check-pair 2 2 "C_i_check_pair_2" #t)
+(rewrite '##sys#check-boolean 2 2 "C_i_check_boolean_2" #t)
+(rewrite '##sys#check-locative 2 2 "C_i_check_locative_2" #t)
 (rewrite '##sys#check-symbol 2 2 "C_i_check_symbol_2" #t)
 (rewrite '##sys#check-string 2 2 "C_i_check_string_2" #t)
 (rewrite '##sys#check-byte-vector 2 2 "C_i_check_bytevector_2" #t)
@@ -855,7 +859,7 @@
    ;; (string->number X Y) -> (##core#inline_allocate ("C_a_i_string_to_number" 4) X Y)
    (define (build x y)
      (make-node
-      '##core#call '(#t)
+      '##core#call (list #t)
       (list cont
 	    (make-node
 	     '##core#inline_allocate 
@@ -903,7 +907,7 @@
    ;; (##sys#setslot <x> <y> <z>) -> (##core#inline "C_i_setslot" <x> <y> <z>)
    (and (= (length callargs) 3)
 	(make-node 
-	 '##core#call '(#t)
+	 '##core#call (list #t)
 	 (list cont
 	       (make-node
 		'##core#inline
@@ -935,7 +939,7 @@
    (and (= 2 (length callargs))
 	(let ([val (second callargs)])
 	  (make-node
-	   '##core#call '(#t)
+	   '##core#call (list #t)
 	   (list cont
 		 (or (and-let* ([(eq? 'quote (node-class val))]
 				[(eq? number-type 'fixnum)]
@@ -1049,7 +1053,7 @@
 			    (list tmp)
 			    (list val
 				  (make-node
-				   '##core#call '(#t)
+				   '##core#call (list #t)
 				   (list cont
 					 (make-node
 					  '##core#inline_allocate 
@@ -1079,7 +1083,7 @@
 				   (not (get db var 'assigned)) 
 				   (not (get db var 'inline-transient))
 				   (make-node
-				    '##core#call '(#t)
+				    '##core#call (list #t)
 				    (list val cont (qnode #f)) ) ) ) ) ) ) ) ) ) ) ) )
   (rewrite 'call-with-current-continuation 8 rewrite-call/cc)
   (rewrite 'call/cc 8 rewrite-call/cc) )
@@ -1123,7 +1127,7 @@
 		 (and (intrinsic? sym)
 		      (and-let* ((a (assq sym setter-map)))
 			(make-node
-			 '##core#call '(#t)
+			 '##core#call (list #t)
 			 (list cont (varnode (cdr a))) ) ) ) ) ) ) ) ) )
 			       
 (rewrite 'void 3 '##sys#undefined-value 0)
@@ -1139,7 +1143,7 @@
    (and (= 1 (length callargs))
 	(let ((arg (car callargs)))
 	  (make-node
-	   '##core#call '(#t) 
+	   '##core#call (list #t) 
 	   (list cont
 		 (if (and (eq? '##core#variable (node-class arg))
 			  (not (get db (car (node-parameters arg)) 'global)) )
@@ -1153,7 +1157,7 @@
  (lambda (db classargs cont callargs)
    (and (= 2 (length callargs))
 	(make-node
-	 '##core#call '(#t)
+	 '##core#call (list #t)
 	 (list cont
 	       (make-node
 		'##core#inline 
@@ -1176,7 +1180,7 @@
  (lambda (db classargs cont callargs)
    (and (= 3 (length callargs))
 	(make-node
-	 '##core#call '(#t)
+	 '##core#call (list #t)
 	 (list cont
 	       (make-node
 		'##core#inline_allocate
@@ -1197,7 +1201,7 @@
 	   (list
 	    (first callargs)
 	    (make-node
-	     '##core#call '(#t)
+	     '##core#call (list #t)
 	     (list cont
 		   (make-node
 		    '##core#inline_allocate
diff --git a/chicken.h b/chicken.h
index 00033d14..84bee82f 100644
--- a/chicken.h
+++ b/chicken.h
@@ -552,6 +552,8 @@ void *alloca ();
 #define C_BAD_ARGUMENT_TYPE_NO_CLOSURE_ERROR          34
 #define C_BAD_ARGUMENT_TYPE_BAD_BASE_ERROR            35
 #define C_CIRCULAR_DATA_ERROR                         36
+#define C_BAD_ARGUMENT_TYPE_NO_BOOLEAN_ERROR          37
+#define C_BAD_ARGUMENT_TYPE_NO_LOCATIVE_ERROR         38
 
 
 /* Platform information */
@@ -1249,6 +1251,8 @@ extern double trunc(double);
 #define C_i_check_symbol(x)             C_i_check_symbol_2(x, C_SCHEME_FALSE)
 #define C_i_check_list(x)               C_i_check_list_2(x, C_SCHEME_FALSE)
 #define C_i_check_pair(x)               C_i_check_pair_2(x, C_SCHEME_FALSE)
+#define C_i_check_locative(x)           C_i_check_locative_2(x, C_SCHEME_FALSE)
+#define C_i_check_boolean(x)            C_i_check_boolean_2(x, C_SCHEME_FALSE)
 #define C_i_check_vector(x)             C_i_check_vector_2(x, C_SCHEME_FALSE)
 #define C_i_check_structure(x, st)      C_i_check_structure_2(x, (st), C_SCHEME_FALSE)
 #define C_i_check_char(x)               C_i_check_char_2(x, C_SCHEME_FALSE)
@@ -1745,6 +1749,8 @@ C_fctexport C_word C_fcall C_i_check_bytevector_2(C_word x, C_word loc) C_regpar
 C_fctexport C_word C_fcall C_i_check_symbol_2(C_word x, C_word loc) C_regparm;
 C_fctexport C_word C_fcall C_i_check_list_2(C_word x, C_word loc) C_regparm;
 C_fctexport C_word C_fcall C_i_check_pair_2(C_word x, C_word loc) C_regparm;
+C_fctexport C_word C_fcall C_i_check_boolean_2(C_word x, C_word loc) C_regparm;
+C_fctexport C_word C_fcall C_i_check_locative_2(C_word x, C_word loc) C_regparm;
 C_fctexport C_word C_fcall C_i_check_vector_2(C_word x, C_word loc) C_regparm;
 C_fctexport C_word C_fcall C_i_check_structure_2(C_word x, C_word st, C_word loc) C_regparm;
 C_fctexport C_word C_fcall C_i_check_char_2(C_word x, C_word loc) C_regparm;
diff --git a/chicken.scm b/chicken.scm
index 8c0147f0..27e3739b 100644
--- a/chicken.scm
+++ b/chicken.scm
@@ -121,6 +121,7 @@
 			       'inline
 			       'inline-global
 			       'unboxing
+			       'strict-types
 			       options) ) ) ) )
 		 (loop (cdr rest)) ) )
 	      ((eq? 'debug-level o)
diff --git a/compiler.scm b/compiler.scm
index 065b58ba..07c50747 100644
--- a/compiler.scm
+++ b/compiler.scm
@@ -1631,7 +1631,7 @@
 	  '##core#lambda (list id #t (cons t1 llist) 0)
 	  (list (walk (car subs)
 		      (lambda (r) 
-			(make-node '##core#call '(#t) (list (varnode t1) r)) ) ) ) ) ) ) )
+			(make-node '##core#call (list #t) (list (varnode t1) r)) ) ) ) ) ) ) )
   
   (define (walk n k)
     (let ((subs (node-subexpressions n))
@@ -1641,7 +1641,7 @@
 	((##core#variable quote ##core#undefined ##core#primitive ##core#global-ref) (k n))
 	((if) (let* ((t1 (gensym 'k))
 		     (t2 (gensym 'r))
-		     (k1 (lambda (r) (make-node '##core#call '(#t) (list (varnode t1) r)))) )
+		     (k1 (lambda (r) (make-node '##core#call (list #t) (list (varnode t1) r)))) )
 		(make-node 
 		 'let
 		 (list t1)
diff --git a/library.scm b/library.scm
index c764583c..48503eb0 100644
--- a/library.scm
+++ b/library.scm
@@ -304,6 +304,16 @@ EOF
       (##core#inline "C_i_check_char_2" x (car loc))
       (##core#inline "C_i_check_char" x) ) )
 
+(define (##sys#check-boolean x . loc)
+  (If (pair? loc)
+      (##core#inline "C_i_check_boolean_2" x (car loc))
+      (##core#inline "C_i_check_boolean" x) ) )
+
+(define (##sys#check-locative x . loc)
+  (If (pair? loc)
+      (##core#inline "C_i_check_locative_2" x (car loc))
+      (##core#inline "C_i_check_locative" x) ) )
+
 (define (##sys#check-integer x . loc)
   (unless (##core#inline "C_i_integerp" x) 
     (##sys#error-hook (foreign-value "C_BAD_ARGUMENT_TYPE_NO_INTEGER_ERROR" int)
@@ -4041,6 +4051,8 @@ EOF
 	((34) (apply ##sys#signal-hook #:type-error loc "bad argument type - not a procedure" args))
 	((35) (apply ##sys#signal-hook #:type-error loc "bad argument type - invalid base" args))
 	((36) (apply ##sys#signal-hook #:limit-error loc "recursion too deep or circular data encountered" args))
+	((37) (apply ##sys#signal-hook #:type-error loc "bad argument type - not a boolean" args))
+	((38) (apply ##sys#signal-hook #:type-error loc "bad argument type - not a locative" args))
 	(else (apply ##sys#signal-hook #:runtime-error loc "unknown internal error" args)) ) ) ) )
 
 
diff --git a/manual/Using the compiler b/manual/Using the compiler
index 8009358f..b9c0db45 100644
--- a/manual/Using the compiler	
+++ b/manual/Using the compiler	
@@ -128,7 +128,7 @@ the source text should be read from standard input.
      -optimize-level 2          is equivalent to -optimize-leaf-routines -inline -unboxing
      -optimize-level 3          is equivalent to -optimize-leaf-routines -local -inline -inline-global -unboxing -specialize
      -optimize-level 4          is equivalent to -optimize-leaf-routines -local -inline -inline-global -unboxing -specialize -unsafe
-     -optimize-level 5          is equivalent to -optimize-leaf-routines -block -inline -inline-global -unboxing -specialize -unsafe -disable-interrupts -no-trace -no-lambda-info
+     -optimize-level 5          is equivalent to -optimize-leaf-routines -block -inline -inline-global -unboxing -specialize -unsafe -disable-interrupts -no-trace -no-lambda-info -strict-types
 
 ; -output-file FILENAME : Specifies the pathname of the generated C file. Default is {{FILENAME.c}}.
 
@@ -157,7 +157,7 @@ the source text should be read from standard input.
 
 ; -static-extension NAME : similar to {{-require-extension NAME}}, but links extension statically (also applies for an explicit {{(require-extension NAME)}}).
 
-; -strict-types : Assume that the type of variables does not change during their lifetime. This gives more type-information during specialization, but violating this assumption will result in unsafe and incorrectly behaving code.
+; -strict-types : Assume that the type of variables does not change because of assignments. This gives more type-information during specialization, but violating this assumption will result in unsafe and incorrectly behaving code.
 
 ; -types FILENAME : load additional type database from {{FILENAME}}. Type-definitions in {{FILENAME}} will override previous type-definitions.
 
diff --git a/optimizer.scm b/optimizer.scm
index dfb50d10..920d4e34 100644
--- a/optimizer.scm
+++ b/optimizer.scm
@@ -199,7 +199,7 @@
 				    (let ((n2 (qnode result)))
 				      (make-node
 				       '##core#call
-				       '(#t)
+				       (list #t)
 				       (list (cadr subs) n2) ) ) ) )))
 			  n1) )
 		    n1) )
@@ -313,7 +313,7 @@
 				    "removed call to pure procedure with unused result"
 				    (or (source-info->string info) var)))
 				 (make-node
-				  '##core#call '(#t)
+				  '##core#call (list #t)
 				  (list k (make-node '##core#undefined '() '())) ) ) 
 			       (walk-generic n class params subs fids)) ) )
 			((and lval
@@ -857,10 +857,10 @@
 		     (and (eq? '##core#variable (node-class arg1))
 			  (eq? '##core#variable (node-class arg2))
 			  (equal? (node-parameters arg1) (node-parameters arg2))
-			  (make-node '##core#call '(#t) (list cont (qnode #t))) ) ) )
+			  (make-node '##core#call (list #t) (list cont (qnode #t))) ) ) )
 	      (and inline-substitutions-enabled
 		   (make-node
-		    '##core#call '(#t) 
+		    '##core#call (list #t) 
 		    (list cont (make-node '##core#inline (list (second classargs)) callargs)) ) ) ) ) )
 
     ;; (<op> ...) -> (##core#inline <iop> ...)
@@ -872,7 +872,7 @@
 	  (or (third classargs) unsafe)
 	  (let ((arg1 (first callargs)))
 	    (make-node
-	     '##core#call '(#t)
+	     '##core#call (list #t)
 	     (list 
 	      cont
 	      (make-node '##core#inline (list (second classargs)) callargs) ) ) ) ) )
@@ -886,7 +886,7 @@
 	  (fold-right
 	   (lambda (val body)
 	     (make-node 'let (list (gensym)) (list val body)) )
-	   (make-node '##core#call '(#t) (list cont (varnode (first classargs))))
+	   (make-node '##core#call (list #t) (list cont (varnode (first classargs))))
 	   callargs)))
 
     ;; (<op> a b) -> (<primitiveop> a (quote <i>) b)
@@ -910,7 +910,7 @@
 	  (= 1 (length callargs))
 	  (let ((ntype (third classargs)))
 	    (or (not ntype) (eq? ntype number-type)) )
-	  (make-node '##core#call '(#t)
+	  (make-node '##core#call (list #t)
 		     (list cont
 			   (make-node '##core#inline (list (first classargs))
 				      (list (first callargs)
@@ -922,7 +922,7 @@
 	   inline-substitutions-enabled
 	   (= 1 (length callargs))
 	   (intrinsic? name)
-	   (make-node '##core#call '(#t)
+	   (make-node '##core#call (list #t)
 		      (list cont
 			    (make-node '##core#inline (list (first classargs))
 				       (list (make-node '##core#inline (list (second classargs))
@@ -934,7 +934,7 @@
 	  inline-substitutions-enabled
 	  (= (length callargs) (first classargs))
 	  (intrinsic? name)
-	  (make-node '##core#call '(#t)
+	  (make-node '##core#call (list #t)
 		     (list cont
 			   (make-node '##core#inline (list (second classargs))
 				      (append callargs
@@ -952,7 +952,7 @@
      (and inline-substitutions-enabled
 	  (intrinsic? name)
 	  (if (< (length callargs) 2)
-	      (make-node '##core#call '(#t) (list cont (qnode #t)))
+	      (make-node '##core#call (list #t) (list cont (qnode #t)))
 	      (and (or (and unsafe (not (eq? number-type 'generic)))
 		       (and (eq? number-type 'fixnum) (third classargs))
 		       (and (eq? number-type 'flonum) (fourth classargs)) )
@@ -961,7 +961,7 @@
 		     (fold-right
 		      (lambda (x n y) (make-node 'let (list n) (list x y)))
 		      (make-node
-		       '##core#call '(#t)
+		       '##core#call (list #t)
 		       (list 
 			cont
 			(let ([op (list
@@ -1012,7 +1012,7 @@
 	  (let ((n (length callargs)))
 	    (and (<= n (third classargs))
 		 (case n
-		   ((1) (make-node '##core#call '(#t) (cons cont callargs)))
+		   ((1) (make-node '##core#call (list #t) (cons cont callargs)))
 		   (else (make-node '##core#call (list #t (first classargs))
 				    (cons* (varnode (first classargs))
 					   cont callargs) ) ) ) ) ) ) )
@@ -1035,7 +1035,7 @@
 	  (eq? number-type (first classargs))
 	  (or (fourth classargs) unsafe)
 	  (make-node
-	   '##core#call '(#t)
+	   '##core#call (list #t)
 	   (list cont
 		 (make-node
 		  '##core#inline
@@ -1053,7 +1053,7 @@
 		 (make-node '##core#call (list #t (third classargs))
 			    (cons* (varnode (third classargs)) cont callargs) ) )
 		((eq? number-type (second classargs))
-		 (make-node '##core#call '(#t) (cons cont callargs)) )
+		 (make-node '##core#call (list #t) (cons cont callargs)) )
 		(else #f) ) ) )
 
     ;; (<alloc-op> ...) -> (##core#inline_allocate (<aiop> <words>) ...)
@@ -1080,7 +1080,7 @@
 		    unchecked-specialized-arithmetic
 		    safe))
 	    (make-node
-	     '##core#call '(#t)
+	     '##core#call (list #t)
 	     (list cont 
 		   (make-node
 		    '##core#inline_allocate
@@ -1098,7 +1098,7 @@
 	  (= (length callargs) (first classargs))
 	  (intrinsic? name)
 	  (make-node
-	   '##core#call '(#t)
+	   '##core#call (list #t)
 	   (list cont
 		 (make-node '##core#inline
 			    (list (if (and unsafe (pair? (cddr classargs)))
@@ -1111,7 +1111,7 @@
      (and inline-substitutions-enabled
 	  (null? callargs)
 	  (intrinsic? name)
-	  (make-node '##core#call '(#t) (list cont (qnode (first classargs))) ) ) )
+	  (make-node '##core#call (list #t) (list cont (qnode (first classargs))) ) ) )
 
     ;; (<op>) -> <id>
     ;; (<op> <x>) -> <x>
@@ -1129,12 +1129,12 @@
 		     (and (eq? 'quote (node-class x))
 			  (eq? id (first (node-parameters x))) ) ) 
 		   callargs) ] )
-	    (cond [(null? callargs) (make-node '##core#call '(#t) (list cont (qnode id)))]
+	    (cond [(null? callargs) (make-node '##core#call (list #t) (list cont (qnode id)))]
 		  [(null? (cdr callargs))
-		   (make-node '##core#call '(#t) (list cont (first callargs))) ]
+		   (make-node '##core#call (list #t) (list cont (first callargs))) ]
 		  [(or (fourth classargs) (eq? number-type 'fixnum))
 		   (make-node
-		    '##core#call '(#t)
+		    '##core#call (list #t)
 		    (list
 		     cont
 		     (fold-inner
@@ -1151,7 +1151,7 @@
 	    (= n (first classargs))
 	    (intrinsic? name)
 	    (make-node
-	     '##core#call '(#t)
+	     '##core#call (list #t)
 	     (list cont
 		   (make-node 
 		    '##core#inline (list (second classargs))
@@ -1178,12 +1178,12 @@
 		     (and (eq? 'quote (node-class x))
 			  (eq? id (first (node-parameters x))) ) ) 
 		   callargs) ] )
-	    (cond [(null? callargs) (make-node '##core#call '(#t) (list cont (qnode id)))]
+	    (cond [(null? callargs) (make-node '##core#call (list #t) (list cont (qnode id)))]
 		  [(null? (cdr callargs))
-		   (make-node '##core#call '(#t) (list cont (first callargs))) ]
+		   (make-node '##core#call (list #t) (list cont (first callargs))) ]
 		  [else
 		   (make-node
-		    '##core#call '(#t)
+		    '##core#call (list #t)
 		    (list
 		     cont
 		     (fold-inner
@@ -1204,7 +1204,7 @@
 	    (intrinsic? name)
 	    (or (third classargs) unsafe)
 	    (make-node
-	     '##core#call '(#t)
+	     '##core#call (list #t)
 	     (list cont 
 		   (if (eq? number-type 'fixnum)
 		       (make-node
diff --git a/runtime.c b/runtime.c
index 880eda19..9ebac8ed 100644
--- a/runtime.c
+++ b/runtime.c
@@ -1515,6 +1515,16 @@ void barf(int code, char *loc, ...)
     c = 1;
     break;
 
+  case C_BAD_ARGUMENT_TYPE_NO_BOOLEAN_ERROR:
+    msg = C_text("bad argument type - not a boolean");
+    c = 1;
+    break;
+
+  case C_BAD_ARGUMENT_TYPE_NO_LOCATIVE_ERROR:
+    msg = C_text("bad argument type - not a locative");
+    c = 1;
+    break;
+
   case C_BAD_ARGUMENT_TYPE_NO_LIST_ERROR:
     msg = C_text("bad argument type - not a list");
     c = 1;
@@ -5541,6 +5551,28 @@ C_regparm C_word C_fcall C_i_check_pair_2(C_word x, C_word loc)
 }
 
 
+C_regparm C_word C_fcall C_i_check_boolean_2(C_word x, C_word loc)
+{
+  if((x & C_IMMEDIATE_TYPE_BITS) != C_BOOLEAN_BITS) {
+    error_location = loc;
+    barf(C_BAD_ARGUMENT_TYPE_NO_BOOLEAN_ERROR, NULL, x);
+  }
+
+  return C_SCHEME_UNDEFINED;
+}
+
+
+C_regparm C_word C_fcall C_i_check_locative_2(C_word x, C_word loc)
+{
+  if(C_immediatep(x) || C_block_header(x) != C_LOCATIVE_TAG) {
+    error_location = loc;
+    barf(C_BAD_ARGUMENT_TYPE_NO_LOCATIVE_ERROR, NULL, x);
+  }
+
+  return C_SCHEME_UNDEFINED;
+}
+
+
 C_regparm C_word C_fcall C_i_check_symbol_2(C_word x, C_word loc)
 {
   if(C_immediatep(x) || C_block_header(x) != C_SYMBOL_TAG) {
diff --git a/scrutinizer.scm b/scrutinizer.scm
index 12d38aa7..9a42840d 100755
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -28,8 +28,8 @@
   (unit scrutinizer)
   (hide match-specialization specialize-node! specialization-statistics
 	procedure-type? named? procedure-result-types procedure-argument-types
-	noreturn-type? rest-type procedure-name d-depth
-	compatible-types? type<=?))
+	noreturn-type? rest-type procedure-name d-depth generate-type-checks!
+	compatible-types? type<=? initial-argument-types))
 
 
 (include "compiler-namespace")
@@ -82,9 +82,6 @@
 ;            | INTEGER | SYMBOL | STRING
 ;            | (quote CONSTANT)
 ;            | (TEMPLATE . TEMPLATE)
-;
-;   - (not number) succeeds for fixnum and flonum
-;   - (not list) succeeds for pair and null
 
 
 (define-constant +fragment-max-length+ 5)
@@ -154,7 +151,8 @@
 
     (define (variable-result id e loc flow)
       (cond ((blist-type id flow) => list)
-	    ((and (get db id 'assigned) 
+	    ((and (not strict-variable-types)
+		  (get db id 'assigned) 
 		  (not (variable-mark id '##compiler#declared-type)))
 	     '(*))
 	    ((assq id e) =>
@@ -564,18 +562,6 @@
 	  (set! n (add1 n))
 	  n)))
 
-    (define (invalidate-blist)
-      (for-each
-       (lambda (b)
-	 (let ((var (caar b)))
-	   (when (and (get db var 'assigned)
-		      ;; if it has a known value, then it only assigned once
-		      (or (get db var 'unknown)
-			  (not (get db var 'value))))
-	     (dd "invalidating: ~a" b)
-	     (set-cdr! b '*))))
-       blist))
-
     (define (walk n e loc dest tail flow ctags) ; returns result specifier
       (let ((subs (node-subexpressions n))
 	    (params (node-parameters n)) 
@@ -625,17 +611,26 @@
 		   (first params)
 		   (lambda (vars argc rest)
 		     (let* ((namelst (if dest (list dest) '()))
-			    (args (append (make-list argc '*) (if rest '(#!rest) '()))) 
-			    (e2 (append (map (lambda (v) (cons v '*)) 
-					     (if rest (butlast vars) vars))
+			    (inits (initial-argument-types dest vars argc))
+			    (args (append inits (if rest '(#!rest) '())))
+			    (e2 (append (map (lambda (v i) (cons v i))
+					     (if rest (butlast vars) vars)
+					     inits)
 					e)))
+		       (when dest 
+			 (d "~a: initial-argument types: ~a" dest inits))
 		       (fluid-let ((blist '()))
 			 (let* ((initial-tag (tag))
 				(r (walk (first subs)
 					 (if rest (alist-cons rest 'list e2) e2)
 					 (add-loc dest loc)
 					 #f #t (list initial-tag) #f)))
-			   (list 
+			   (when (and specialize
+				      dest
+				      (not strict-variable-types) 
+				      (not unsafe))
+			     (generate-type-checks! n dest vars inits))
+			   (list
 			    (append
 			     '(procedure) 
 			     namelst
@@ -643,7 +638,7 @@
 			      (let loop ((argc argc) (vars vars) (args args))
 				(cond ((zero? argc) args)
 				      ((and (not (get db (car vars) 'assigned))
-					   (assoc (cons (car vars) initial-tag) blist))
+					    (assoc (cons (car vars) initial-tag) blist))
 				      =>
 				      (lambda (a)
 					(cons
@@ -674,7 +669,8 @@
 		       (sprintf 
 			   "assignment of value of type `~a' to toplevel variable `~a' does not match declared type `~a'"
 			 rt var type)
-		       #t))
+		       #t)
+		      (mark-variable var '##compiler#type #f))
 		    (when (and (not type)
 			       (not b)
 			       (not (eq? '* rt))
@@ -697,7 +693,8 @@
 				      "variable `~a' of type `~a' was modified to a value of type `~a'"
 				    var ot rt)
 				  #t)))))
-		      (set! blist (alist-cons (cons var (car flow)) rt blist)))
+		      (when strict-variable-types
+			(set! blist (alist-cons (cons var (car flow)) rt blist))))
 		    '(undefined)))
 		 ((##core#primitive ##core#inline_ref) '*)
 		 ((##core#call)
@@ -719,15 +716,13 @@
 			 (enforces (and pn (variable-mark pn '##compiler#enforce-argument-types)))
 			 (pt (and pn (variable-mark pn '##compiler#predicate))))
 		    (let ((r (call-result n args e loc params)))
-		      (unless strict-variable-types
-			(invalidate-blist))
 		      (for-each
 		       (lambda (arg argr)
 			 (when (eq? '##core#variable (node-class arg))
 			   (let* ((var (first (node-parameters arg)))
 				  (a (assq var e))
 				  (oparg? (eq? arg (first subs)))
-				  (pred (and pt ctags (not oparg?))))
+				  (pred (and pt ctags (not (get db var 'assigned)) (not oparg?))))
 			     (cond (pred
 				    (d "  predicate `~a' indicates `~a' is ~a in flow ~a" pn var pt
 				       (car ctags))
@@ -762,7 +757,7 @@
 					 (dd "  hardcoded special case: ~a" var)
 					 (set! r (srt n r))))))))
 		       subs
-		       (cons fn (procedure-argument-types fn (sub1 len))))
+		       (cons fn (nth-value 0 (procedure-argument-types fn (sub1 len)))))
 		      r)))
 		 ((##core#switch ##core#cond)
 		  (bomb "unexpected node class: ~a" class))
@@ -845,7 +840,7 @@
 	       ((symbol? n) n)
 	       (else #f)))))
 
-(define (procedure-argument-types t n)
+(define (procedure-argument-types t n #!optional norest)
   (cond ((or (memq t '(* procedure)) 
 	     (not-pair? t)
 	     (eq? 'deprecated (car t)))
@@ -859,11 +854,15 @@
 			    (m n)
 			    (opt #f))
 		   (cond ((null? at) '())
-			 ((eq? '#!optional (car at)) 
-			  (loop (cdr at) m #t) )
+			 ((eq? '#!optional (car at))
+			  (if norest
+			      '()
+			      (loop (cdr at) m #t) ))
 			 ((eq? '#!rest (car at))
-			  (set! vf (and (pair? (cdr at)) (eq? 'values (cadr at))))
-			  (make-list m (rest-type (cdr at))))
+			  (cond (norest '())
+				(else
+				 (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)))
@@ -925,7 +924,7 @@
 		(when (and old (not (equal? old new)))
 		  (##sys#notice
 		   (sprintf
-		       "type-definition `~a' for toplevel binding `~a' conflicts with previously loaded type `~a'"
+		       "type-deifnition `~a' for toplevel binding `~a' conflicts with previously loaded type `~a'"
 		     name new old)))
 		(mark-variable name '##compiler#type new)
 		(when specs
@@ -1067,14 +1066,79 @@
 	  (else #f)))
   (validate type))
 
+(define (initial-argument-types dest vars argc)
+  (if (and dest (variable-mark dest '##compiler#declared-type))
+      (let ((ptype (variable-mark dest '##compiler#type)))
+	(if (procedure-type? ptype)
+	    (nth-value 0 (procedure-argument-types ptype argc #t))
+	    (make-list argc '*)))
+      (make-list argc '*)))
+
+
+;;; generate type-checks for formal variables
+
+(define (generate-type-checks! node loc vars inits)
+  (let ((body (first (node-subexpressions node))))
+    (let loop ((vars (reverse vars)) (inits (reverse inits)) (b body))
+      (cond ((null? inits)
+	     (if (eq? b body)
+		 body
+		 (copy-node!
+		  (make-node 
+		   (node-class node)	; lambda
+		   (node-parameters node)
+		   (list b))
+		  node)))
+	    ((eq? '* (car inits))
+	     (loop (cdr vars) (cdr inits) b))
+	    (else
+	     (loop
+	      (cdr vars)
+	      (cdr inits)
+	      (make-node
+	       'let (list (gensym))
+	       (list
+		(build-node-graph
+		 (let ((t (car inits))
+		       (v (car vars)))
+		   (case t
+		     ((null) `(if (not (null? ,v))
+				  (##core#app ##sys#error ',loc "bad argument type - not null" v)))
+		     ((eof) `(if (not (eof-object? ,v))
+				 (##core#app ##sys#error ',loc "bad argument type - not eof" v)))
+		     ((string) `(##core#app ##sys#check-string ,v ',loc))
+		     ((fixnum) `(##core#app ##sys#check-exact ,v ',loc))
+		     ((float) `(##core#app ##sys#check-inexact ,v ',loc))
+		     ((char) `(##core#app ##sys#check-char ,v ',loc))
+		     ((number) `(##core#app ##sys#check-number ,v ',loc))
+		     ((list) `(##core#app ##sys#check-list ,v ',loc))
+		     ((symbol) `(##core#app ##sys#check-symbol ,v ',loc))
+		     ((pair) `(##core#app ##sys#check-pair ,v ',loc))
+		     ((boolean) `(##core#app ##sys#check-boolean ,v ',loc))
+		     ((procedure) `(##core#app ##sys#check-closure ,v ',loc))
+		     ((vector) `(##core#app ##sys#check-vector ,v ',loc))
+		     ((pointer) `(##core#app ##sys#check-pointer ,v ',loc))
+		     ((blob) `(##core#app ##sys#check-blob ,v ',loc))
+		     ((locative) `(##core#app ##sys#check-locative ,v ',loc))
+		     ((port) `(##core#app ##sys#check-port ,v ',loc))
+		     ((pointer-vector) `(##core#app ##sys#check-structure ,v 'pointer-vector ',loc))
+		     (else
+		      (if (pair? t)
+			  (case (car t)
+			    ((procedure) `(##core#app ##sys#check-closure ,v ',loc))
+			    ((struct) `(##core#app ##sys#check-structure ,v ',(cadr t) ',loc))
+			    (else (bomb "can not generate type-check for `~a'" t)))
+			  (bomb "can not generate type-check for `~a'" t))))))
+		b))))))))
+
+
+;;; hardcoded result types for certain primitives
+
 (define-syntax define-special-case
   (syntax-rules ()
     ((_ name handler)
      (##sys#put! 'name '##compiler#special-result-type handler))))
 
-
-;;; hardcoded result types for certain primitives
-
 (define-special-case ##sys#make-structure
   (lambda (node rtypes)
     (or (let ((subs (node-subexpressions node)))
diff --git a/support.scm b/support.scm
index 0d8c01a9..c04e0e6f 100644
--- a/support.scm
+++ b/support.scm
@@ -528,7 +528,7 @@
 					##core#inline_loc_ref ##core#inline_loc_update)
 		(make-node (first x) (second x) (map walk (cddr x))) )
 	       ((##core#app)
-		(make-node '##core#call '(#t) (map walk (cdr x))) )
+		(make-node '##core#call (list #t) (map walk (cdr x))) )
 	       (else
 		(receive (name ln) (get-line-2 x)
 		  (make-node
@@ -543,7 +543,7 @@
 				     (or rn (##sys#symbol->qualified-string name))) )
 			     (##sys#symbol->qualified-string name) ) )
 		   (map walk x) ) ) ) ) )
-	    (else (make-node '##core#call '(#f) (map walk x))) ) )
+	    (else (make-node '##core#call (list #f) (map walk x))) ) )
     (let ([exp2 (walk exp)])
       (when (positive? count)
 	(debugging 'o "eliminated procedure checks" count))
Trap