Abstraction of the boxes used for unit imports/exports to allow for adding

contracts in an already created unit.

svn: r13331
This commit is contained in:
Stevie Strickland 2009-01-31 01:39:23 +00:00
parent ab5a01da76
commit f6493e1c32
2 changed files with 369 additions and 66 deletions

View File

@ -472,12 +472,12 @@
(define-for-syntax (make-import-unboxing var loc ctc)
(if ctc
(quasisyntax/loc (error-syntax)
(quote-syntax (let ([v/c (unbox #,loc)])
(quote-syntax (let ([v/c ((car #,loc))])
(contract #,ctc (car v/c) (cdr v/c)
(current-contract-region)
#,(id->contract-src-info var)))))
(quasisyntax/loc (error-syntax)
(quote-syntax (unbox #,loc)))))
(quote-syntax ((car #,loc))))))
;; build-unit : syntax-object ->
;; (values syntax-object (listof identifier) (listof identifier))
@ -557,7 +557,10 @@
(list (cons 'dept depr) ...)
(syntax-parameterize ([current-contract-region (lambda (stx) #'(quote (unit name)))])
(lambda ()
(let ([eloc (box undefined)] ... ...)
(let ([eloc (let ([loc (box undefined)])
(cons
(λ () (unbox loc))
(λ (v) (set-box! loc v))))] ... ...)
(values
(lambda (import-table)
(let-values ([(iloc ...)
@ -731,12 +734,12 @@
(current-contract-region)
'cant-happen
#,(id->contract-src-info id))
(set-box! #,export-loc
(let ([#,id #,tmp])
(cons #,id (current-contract-region))))))
((cdr #,export-loc)
(let ([#,id #,tmp])
(cons #,id (current-contract-region))))))
(quasisyntax/loc defn-or-expr
(set-box! #,export-loc
(let ([#,id #,tmp]) #,id))))
((cdr #,export-loc)
(let ([#,id #,tmp]) #,id))))
(quasisyntax/loc defn-or-expr
(define-syntax #,id
(make-id-mapper (quote-syntax #,tmp)))))))]
@ -776,12 +779,6 @@
(lambda (target-sig)
(map
(lambda (target-int/ext-name target-ctc)
(when target-ctc
(raise-stx-err
(format (if import?
"identifier ~a is contracted in old imports"
"identifier ~a is contracted in new exports")
(syntax-e (car target-int/ext-name)))))
(let ([vref/ctc
(bound-identifier-mapping-get
def-table
@ -792,13 +789,26 @@
"identifier ~a is not present in new imports"
"identifier ~a is not present in old exports")
(syntax-e (car target-int/ext-name))))))])
(when (cdr vref/ctc)
(raise-stx-err
(format (if import?
"identifier ~a is contracted in new imports"
"identifier ~a is contracted in old exports")
(syntax-e (car target-int/ext-name)))))
(car vref/ctc)))
(let ([old-cl (car vref/ctc)])
#`(cons
(λ ()
(let ([old-v #,(if (cdr vref/ctc)
#`(let ([old-v/c ((car #,old-cl))])
(contract #,(cdr vref/ctc) (car old-v/c)
(cdr old-v/c) (current-contract-region)
#,(id->contract-src-info (car target-int/ext-name))))
#`((car #,old-cl)))])
#,(if target-ctc
#'(cons old-v (current-contract-region))
#'old-v)))
(λ (v) (let ([new-v #,(if (cdr vref/ctc)
#`(contract #,(cdr vref/ctc) (car v)
(current-contract-region) (cdr v)
#,(id->contract-src-info (car target-int/ext-name)))
#'v)])
#,(if target-ctc
#`((cdr #,old-cl) (cons new-v (current-contract-region)))
#`((cdr #,old-cl) new-v))))))))
(car target-sig)
(cadddr target-sig)))
target-import-sigs))
@ -902,19 +912,20 @@
(vector-immutable (cons 'export-name
(vector-immutable export-key ...)) ...)
(list (cons 'dept depr) ...)
(lambda ()
(let-values ([(unit-fn export-table) ((unit-go unit-tmp))])
(values (lambda (import-table)
(unit-fn #,(redirect-imports #'import-table
import-tagged-infos
import-sigs
orig-import-tagged-infos
orig-import-sigs)))
#,(redirect-exports #'export-table
orig-export-tagged-infos
orig-export-sigs
export-tagged-infos
export-sigs)))))))
(syntax-parameterize ([current-contract-region (lambda (stx) #'(quote (unit name)))])
(lambda ()
(let-values ([(unit-fn export-table) ((unit-go unit-tmp))])
(values (lambda (import-table)
(unit-fn #,(redirect-imports #'import-table
import-tagged-infos
import-sigs
orig-import-tagged-infos
orig-import-sigs)))
#,(redirect-exports #'export-table
orig-export-tagged-infos
orig-export-sigs
export-tagged-infos
export-sigs))))))))
import-tagged-sigids
export-tagged-sigids
dep-tagged-sigids)))))))
@ -1238,11 +1249,11 @@
(map
(lambda (i v c)
(if c
#`(let ([v/c (unbox (vector-ref #,ov #,i))])
#`(let ([v/c ((car (vector-ref #,ov #,i)))])
(contract #,c (car v/c) (cdr v/c)
(current-contract-region)
#,(id->contract-src-info v)))
#`(unbox (vector-ref #,ov #,i))))
#`((car (vector-ref #,ov #,i)))))
(iota (length (car os)))
(map car (car os))
(cadddr os)))

View File

@ -196,46 +196,338 @@
(test-runtime-error exn:fail:contract? "top-level misuses f"
(f #t)))
;; eventually we can hopefully fix this so these are allowed, but for right
;; now, test that they fail during unit/new-import-export
;; unit/new-import-export tests
(define-signature sig7 (x))
(define-signature sig8 ((contracted [x number?])))
(define-signature sig7 (f))
(define-signature sig8 ((contracted [f (-> number? number?)])))
(define-signature sig9 ((contracted [f (-> number? number?)])))
;; All units that play nicely
(define-unit unit12
(import sig7)
(export)
x)
(f 3))
(define-unit unit13
(import sig8)
(export)
x)
(f 3))
(define-unit unit14
(import)
(export sig8)
(define x 3))
(export sig7)
(define f (λ (n) 3)))
(define-unit unit15
(import)
(export sig7)
(define x 3))
(export sig8)
(define f (λ (n) 3)))
(test-syntax-error "not contracted in old import -> contracted in new"
(unit/new-import-export
(import sig8)
(export)
(() unit12 sig7)))
(test-syntax-error "contracted in old import -> not contracted in new"
(unit/new-import-export
(import sig7)
(export)
(() unit13 sig8)))
(test-syntax-error "not contracted in old export -> contracted in new"
(unit/new-import-export
(import)
(export sig8)
((sig7) unit14)))
(test-syntax-error "contracted in old export -> not contracted in new"
(unit/new-import-export
(import)
(export sig7)
((sig8) unit15)))
;; All units that don't play nicely (or won't after converted)
(define-unit unit16
(import sig7)
(export)
(f #t))
(define-unit unit17
(import sig8)
(export)
(f #t))
(define-unit unit18
(import)
(export sig7)
(define f (λ (n) #t)))
(define-unit unit19
(import)
(export sig8)
(define f (λ (n) #t)))
;; Converting units without internal contract violations
;; uncontracted import -> contracted import
(define-unit/new-import-export unit20
(import sig8)
(export)
(() unit12 sig7))
(let ()
(define-compound-unit unit21
(import)
(export)
(link [((S : sig8)) unit15]
[() unit20 S]))
(invoke-unit unit21))
(let ()
(define-compound-unit unit22
(import)
(export)
(link [((S : sig8)) unit19]
[() unit20 S]))
(test-runtime-error exn:fail:contract? "unit19 provides bad f"
(invoke-unit unit22)))
;; contracted import -> uncontracted import
(define-unit/new-import-export unit23
(import sig7)
(export)
(() unit13 sig8))
(let ()
(define-compound-unit unit24
(import)
(export)
(link [((S : sig7)) unit14]
[() unit23 S]))
(invoke-unit unit24))
(let ()
(define-compound-unit unit25
(import)
(export)
(link [((S : sig7)) unit18]
[() unit23 S]))
(test-runtime-error exn:fail:contract? "unit23 provides f with no protection into a bad context"
(invoke-unit unit25)))
;; contracted import -> contracted import
(define-unit/new-import-export unit26
(import sig9)
(export)
(() unit13 sig8))
(let ()
(define-unit unit27-1
(import)
(export sig9)
(define (f n) 3))
(define-compound-unit unit27-2
(import)
(export)
(link [((S : sig9)) unit27-1]
[() unit26 S]))
(invoke-unit unit27-2))
(let ()
(define-unit unit28-1
(import)
(export sig9)
(define (f n) #f))
(define-compound-unit unit28-2
(import)
(export)
(link [((S : sig9)) unit28-1]
[() unit26 S]))
(test-runtime-error exn:fail:contract? "unit28-1 broke contract on f"
(invoke-unit unit28-2)))
;; uncontracted export -> contracted export
(define-unit/new-import-export unit29
(import)
(export sig8)
((sig7) unit14))
(let ()
(define-compound-unit unit30
(import)
(export)
(link [((S : sig8)) unit29]
[() unit13 S]))
(invoke-unit unit30))
(let ()
(define-compound-unit unit31
(import)
(export)
(link [((S : sig8)) unit29]
[() unit17 S]))
(test-runtime-error exn:fail:contract? "unit17 misuses f"
(invoke-unit unit31)))
;; contracted export -> uncontracted export
(define-unit/new-import-export unit32
(import)
(export sig7)
((sig8) unit15))
(let ()
(define-compound-unit unit33
(import)
(export)
(link [((S : sig7)) unit32]
[() unit14 S]))
(invoke-unit unit33))
(let ()
(define-compound-unit unit34
(import)
(export)
(link [((S : sig7)) unit32]
[() unit16 S]))
(test-runtime-error exn:fail:contract? "unit32 provides f with no protection into bad context"
(invoke-unit unit34)))
;; contracted export -> contracted export
(define-unit/new-import-export unit35
(import)
(export sig9)
((sig8) unit15))
(let ()
(define-unit unit36-1
(import sig9)
(export)
(f 3))
(define-compound-unit unit36-2
(import)
(export)
(link [((S : sig9)) unit35]
[() unit36-1 S]))
(invoke-unit unit36-2))
(let ()
(define-unit unit37-1
(import sig9)
(export)
(f #f))
(define-compound-unit unit37-2
(import)
(export)
(link [((S : sig9)) unit35]
[() unit37-1 S]))
(test-runtime-error exn:fail:contract? "unit37-1 broke contract on f"
(invoke-unit unit37-2)))
;; Converting units with internal contract violations
;; uncontracted import -> contracted import
(define-unit/new-import-export unit38
(import sig8)
(export)
(() unit16 sig7))
(let ()
(define-compound-unit unit39
(import)
(export)
(link [((S : sig8)) unit15]
[() unit38 S]))
(test-runtime-error exn:fail:contract? "unit38 allowed f to flow into uncontracted bad context"
(invoke-unit unit39)))
(let ()
(define-compound-unit unit40
(import)
(export)
(link [((S : sig8)) unit19]
[() unit38 S]))
(test-runtime-error exn:fail:contract? "unit38 allowed f to flow into uncontracted bad context"
(invoke-unit unit40)))
;; contracted import -> uncontracted import
(define-unit/new-import-export unit41
(import sig7)
(export)
(() unit17 sig8))
(let ()
(define-compound-unit unit42
(import)
(export)
(link [((S : sig7)) unit14]
[() unit41 S]))
(test-runtime-error exn:fail:contract? "unit17 misuses f"
(invoke-unit unit42)))
(let ()
(define-compound-unit unit43
(import)
(export)
(link [((S : sig7)) unit18]
[() unit41 S]))
(test-runtime-error exn:fail:contract? "unit17 misuses f"
(invoke-unit unit43)))
;; contracted import -> contracted import
(define-unit/new-import-export unit44
(import sig9)
(export)
(() unit17 sig8))
(let ()
(define-unit unit45-1
(import)
(export sig9)
(define (f n) 3))
(define-compound-unit unit45-2
(import)
(export)
(link [((S : sig9)) unit45-1]
[() unit44 S]))
(test-runtime-error exn:fail:contract? "unit17 misuses f"
(invoke-unit unit45-2)))
(let ()
(define-unit unit46-1
(import)
(export sig9)
(define (f n) #t))
(define-compound-unit unit46-2
(import)
(export)
(link [((S : sig9)) unit46-1]
[() unit44 S]))
(test-runtime-error exn:fail:contract? "unit17 misuses f"
(invoke-unit unit46-2)))
;; uncontracted export -> contracted export
(define-unit/new-import-export unit47
(import)
(export sig8)
((sig7) unit18))
(let ()
(define-compound-unit unit48
(import)
(export)
(link [((S : sig8)) unit47]
[() unit13 S]))
(test-runtime-error exn:fail:contract? "unit47 provided bad f"
(invoke-unit unit48)))
(let ()
(define-compound-unit unit49
(import)
(export)
(link [((S : sig8)) unit47]
[() unit17 S]))
(test-runtime-error exn:fail:contract? "unit17 misuses f"
(invoke-unit unit49)))
;; contracted import -> uncontracted import
(define-unit/new-import-export unit50
(import)
(export sig7)
((sig8) unit19))
(let ()
(define-compound-unit unit51
(import)
(export)
(link [((S : sig7)) unit50]
[() unit12 S]))
(test-runtime-error exn:fail:contract? "unit19 provides bad f"
(invoke-unit unit51)))
(let ()
(define-compound-unit unit52
(import)
(export)
(link [((S : sig7)) unit50]
[() unit16 S]))
(test-runtime-error exn:fail:contract? "unit50 provides unprotected f into bad context"
(invoke-unit unit52)))
;; contracted export -> contracted export
(define-unit/new-import-export unit53
(import)
(export sig9)
((sig8) unit19))
(let ()
(define-unit unit54-1
(import sig9)
(export)
(f 3))
(define-compound-unit unit54-2
(import)
(export)
(link [((S : sig9)) unit53]
[() unit54-1 S]))
(test-runtime-error exn:fail:contract? "unit19 provides bad f"
(invoke-unit unit54-2)))
(let ()
(define-unit unit55-1
(import sig9)
(export)
(f #t))
(define-compound-unit unit55-2
(import)
(export)
(link [((S : sig9)) unit53]
[() unit55-1 S]))
(test-runtime-error exn:fail:contract? "unit55-1 misuses f"
(invoke-unit unit55-2)))