~ chicken-core (chicken-5) e231be6676389285f60399cc71cad6f390e03e24


commit e231be6676389285f60399cc71cad6f390e03e24
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Wed Apr 6 08:57:32 2011 -0400
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Wed Apr 6 08:57:32 2011 -0400

    -strict-types

diff --git a/batch-driver.scm b/batch-driver.scm
index dbd0e9e5..37f70793 100644
--- a/batch-driver.scm
+++ b/batch-driver.scm
@@ -259,6 +259,7 @@
       (parentheses-synonyms #f)
       (symbol-escape #f) )
     (set! verbose-mode verbose)
+    (set! strict-variable-types (memq 'strict-types options))
     (set! ##sys#read-error-with-line-number #t)
     (set! ##sys#include-pathnames
       (append (map chop-separator (collect-options 'include-path))
@@ -530,7 +531,7 @@
 			(load-inline-file ilf) )
 		      ifs)))
 
-		 (when (or do-scrutinize do-specialize)
+		 (when (or strict-variable-types do-scrutinize do-specialize)
 		   ;;XXX hardcoded database file name
 		   (unless (memq 'ignore-repository options)
 		     (load-type-database "types.db"))
diff --git a/c-platform.scm b/c-platform.scm
index 5b7d2b63..b5fcdb6c 100644
--- a/c-platform.scm
+++ b/c-platform.scm
@@ -91,6 +91,7 @@
     no-procedure-checks-for-toplevel-bindings module
     no-bound-checks no-procedure-checks-for-usual-bindings no-compiler-syntax
     no-parentheses-synonyms no-symbol-escape r5rs-syntax emit-all-import-libraries
+    strict-types
     lambda-lift				; OBSOLETE
     setup-mode unboxing no-module-registration) )
 
diff --git a/compiler-namespace.scm b/compiler-namespace.scm
index de3869ad..c5fc3ecd 100644
--- a/compiler-namespace.scm
+++ b/compiler-namespace.scm
@@ -268,6 +268,7 @@
  source-info->line
  specialize-node!
  standalone-executable
+ strict-variable-types
  string->c-identifier
  string->expr
  stringify
diff --git a/compiler.scm b/compiler.scm
index 4d958fa6..e9123eda 100644
--- a/compiler.scm
+++ b/compiler.scm
@@ -334,6 +334,7 @@
 (define compiler-syntax-enabled #t)
 (define unchecked-specialized-arithmetic #f)
 (define bootstrap-mode #f)
+(define struct-variable-types #f)
 
 
 ;;; These are here so that the backend can access them:
diff --git a/csc.scm b/csc.scm
index 16643dd2..fd91fa98 100644
--- a/csc.scm
+++ b/csc.scm
@@ -139,7 +139,7 @@
     -no-argc-checks -no-bound-checks -no-procedure-checks -no-compiler-syntax
     -emit-all-import-libraries -setup-mode -unboxing -no-elevation -no-module-registration
     -no-procedure-checks-for-usual-bindings -module
-    -specialize
+    -specialize -strict-types
     -lambda-lift			; OBSOLETE
     -no-procedure-checks-for-toplevel-bindings))
 
@@ -353,6 +353,7 @@ Usage: #{csc} FILENAME | OPTION ...
                                     file
     -S  -scrutinize                perform local flow analysis
     -types FILENAME                load additional type database
+    -strict-types                  assume variable do not change their type
 
   Optimization options:
 
diff --git a/scrutinizer.scm b/scrutinizer.scm
index 005d3419..f918d174 100755
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -87,6 +87,7 @@
 
 (define specialization-statistics '())
 
+
 (define (scrutinize node db complain specialize)
   (let ((blist '())
 	(safe-calls 0))
@@ -375,6 +376,9 @@
 	    ((match (car results1) (car results2)) 
 	     (match-results (cdr results1) (cdr results2)))
 	    (else #f)))
+    (define (compatible-types? t1 t2)
+      (or (type<=? t1 t2)
+	  (type<=? t2 t1)))
     (define (type<=? t1 t2)
       (or (eq? t1 t2)
 	  (memq t2 '(* undefined))
@@ -715,11 +719,19 @@
 			   "assignment of value of type `~a' to toplevel variable `~a' does not match declared type `~a'"
 			 rt var type)
 		       #t))
-		    (when (and b (eq? 'undefined (cdr b)))
-		      (set-cdr! b rt))
 		    ;;XXX we could set the ##compiler#type property here for hidden
 		    ;;    globals that are only assigned once
 		    (when b
+		      (cond ((eq? 'undefined (cdr b)) (set-cdr! b rt))
+			    (strict-variable-types
+			     (let ((ot (or (blist-type var flow) (cdr b))))
+			       (unless (compatible-types? ot rt)
+				 (report
+				  loc
+				  (sprintf 
+				      "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)))
 		    '(undefined)))
 		 ((##core#primitive ##core#inline_ref) '*)
@@ -742,7 +754,8 @@
 			 (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)))
-		      (invalidate-blist)
+		      (unless strict-variable-types
+			(invalidate-blist))
 		      (for-each
 		       (lambda (arg argr)
 			 (when (eq? '##core#variable (node-class arg))
diff --git a/support.scm b/support.scm
index ab0295b7..e9d20e86 100644
--- a/support.scm
+++ b/support.scm
@@ -1535,6 +1535,7 @@ Usage: chicken FILENAME OPTION ...
     -no-lambda-info              omit additional procedure-information
     -scrutinize                  perform local flow analysis for static checks
     -types FILENAME              load additional type database
+    -strict-types                assume variable do not change their type
     -emit-type-file FILENAME     write type-declaration information into file
 
   Optimization options:
Trap