racket/collects/tests/units/test-unit.rktl
2010-05-01 09:58:16 -06:00

1789 lines
64 KiB
Racket

(require (for-syntax mzlib/private/unit-compiletime
mzlib/private/unit-syntax))
(require "test-harness.ss"
;unit
scheme/unit)
(define-syntax (lookup-sig-mac stx)
(parameterize ((error-syntax stx))
(syntax-case stx ()
((_ id)
#`#'#,(let ((s (lookup-signature #'id)))
(list (map syntax-local-introduce (signature-vars s))
(map (lambda (def)
(cons (map syntax-local-introduce (car def))
(syntax-local-introduce (cdr def))))
(signature-val-defs s))
(map (lambda (def)
(cons (map syntax-local-introduce (car def))
(syntax-local-introduce (cdr def))))
(signature-stx-defs s))))))))
(define-signature x-sig (x))
(define-signature x-sig2 (x))
(define-signature y-sig (y))
(define-signature z-sig (z))
(define-signature yz-sig (y z))
(define-signature xy-sig (x y))
(define-signature empty-sig ())
(define-signature b-sig (b))
(define-signature empty-sub extends empty-sig ())
(define-signature x-sub extends x-sig (xx))
(define-signature y-sub extends y-sig (yy))
(define-signature x-sub2 extends x-sig (x2))
;; Keyword errors
(test-syntax-error "misuse of import"
import)
(test-syntax-error "misuse of export"
export)
(test-syntax-error "misuse of init-depend"
init-depend)
(test-syntax-error "misuse of link"
link)
(test-syntax-error "misuse of only"
only)
(test-syntax-error "misuse of except"
except)
(test-syntax-error "misuse of prefix"
prefix)
(test-syntax-error "misuse of rename"
rename)
(test-syntax-error "misuse of tag"
tag)
;; define-signature-forms syntax errors
(test-syntax-error "define-signature-form: missing arguments"
(define-signature-form))
(test-syntax-error "define-signature-form: missing arguments"
(define-signature-form (a b)))
(test-syntax-error "define-signature-form: too many arguments"
(define-signature-form (a b c) 1 2))
(test-syntax-error "define-signature-form: dot"
(define-signature-form (a b) . c))
(test-syntax-error "define-signature-form: set!"
(let ()
(define-signature-form (a b) b)
(set! a 1)))
(test-syntax-error "define-signature-form: bad params"
(define-signature-form 1 2))
(test-syntax-error "define-signature-form: bad params"
(define-signature-form a 2))
(test-syntax-error "define-signature-form: name not id"
(define-signature-form (1 a) 1))
(test-syntax-error "define-signature-form: param not id"
(define-signature-form (a 1) 1))
(test-syntax-error "define-signature-form: param dot"
(define-signature-form (a . b) 1))
;; define-signature syntax-errors
(test-syntax-error "define-signature: missing name"
(define-signature))
(test-syntax-error "define-signature: missing sig"
(define-signature x))
(test-syntax-error "define-signature: too many args"
(define-signature x (a b) 1))
(test-syntax-error "define-signature: bad name"
(define-signature 1 (a b)))
(test-syntax-error "define-signature: bad name"
(define-signature x extends 1 (a b)))
(test-syntax-error "define-signature: not a signature"
(define-signature x extends y12 (a b)))
(test-syntax-error "define-signature: not a signature"
(let () (define-signature x extends x (a b))))
(test-syntax-error "define-signature: bad name"
(define-signature (a . b) (a b)))
(test-syntax-error "define-signature: dot"
(define-signature b . (a b)))
(test-syntax-error "define-signature: dot"
(define-signature b (a b) . 2))
(test-syntax-error "define-signature: set!"
(let ()
(define-signature a (a))
(set! a 1)))
(test-syntax-error "define-signature: bad sig"
(define-signature x y))
(test-syntax-error "define-signature: bad sig"
(define-signature x (1)))
(test-syntax-error "define-signature: bad sig"
(define-signature x (a . b)))
(test-syntax-error "define-signature: bad signature form"
(define-signature x ((a))))
(test-syntax-error "define-signature: bad signature form"
(define-signature x ((define-signature))))
(test-syntax-error "define-values: malformed (in define-signature)"
(define-signature x ((define-values 1 2))))
(test-syntax-error "define-signature: bad form (does not return list)"
(let ()
(define-signature-form (a b) 1)
(define-signature x ((a 1)))))
(test-syntax-error "define-signature: unknown form"
(let ()
(define-signature-form (a b) (list #'(c d)))
(define-signature x ((a 1)))
1))
(test-syntax-error "define-signature: duplicate name"
(define-signature x (a a)))
(test-syntax-error "define-signature: duplicate values"
(define-signature x (a (define-values (a) 1))))
(test-syntax-error "define-signature: duplicate values"
(define-signature x (a (define-values (b b) 1))))
(test-syntax-error "define-signature: duplicate values"
(define-signature x (a (define-values (b) 1) (define-syntaxes (b) 1))))
(test-syntax-error "define-signature: duplicate values"
(let ()
(define-signature test (y))
(define-signature x extends test ((define-values (y) 1)))))
;; define-signature
(test stx-bound-id=? #'((a b) () ())
(let ()
(define-signature x (a b))
(lookup-sig-mac x)))
(let ()
(define s7 (void))
(define h (void))
(define-signature super (s1 (define-values (s2 s3) s4) (define-syntaxes (s5 s6) (values #'s7 #'s7))))
(test stx-bound-id=? #'((s1 a b f) (((s2 s3) . s4) ((c d) . e) ((i) . j)) (((s5 s6) . (values #'s7 #'s7)) ((g) . #'h)))
(let ()
(define-signature x extends super (a b (define-values (c d) e) f
(define-syntaxes (g) #'h)
(define-values (i) j)))
(lookup-sig-mac x))))
(let ()
(define s7 (void))
(define h (void))
(define-signature super (s1 (define-values (s2 s3) s4) (define-syntaxes (s5 s6) (values #'s7 #'s7))))
(let ((a 1) (g 2) (j 3) (s1 4) (s2 5))
(test stx-bound-id=? #'(((#f . s1) a b f) ((((#f . s2) s3) . s4) ((c d) . e) ((i) . j)) (((s5 s6) . (values #'s7 #'s7)) ((g) . #'h)))
(let ()
(define-signature x extends super (a b (define-values (c d) e) f
(define-syntaxes (g) #'h)
(define-values (i) j)))
(lookup-sig-mac x)))))
(let ()
(define s7 (void))
(define h (void))
(define-signature super (s1 (define-values (s2 s3) s4) (define-syntaxes (s5 s6) (values #'s7 #'s7))))
(test stx-bound-id=? #'((s1 a b f) (((s2 s3) . s4) ((c d) . e) ((i) . j)) (((s5 s6) . (values #'s7 #'s7)) ((g) . #'h)))
(let ()
(define-signature x extends super (a b (define-values (c d) e) f
(define-syntaxes (g) #'h)
(define-values (i) j)))
(let ((a 1) (g 2) (j 3))
(lookup-sig-mac x)))))
(test stx-bound-id=? #'(((#f . a) b f) (((c d) . e) ((i) . (#f . j))) ((((#f . g)) . #'h)))
(let ((a 1) (g 2) (j 3))
(define-signature x (a b (define-values (c d) e) f
(define-syntaxes (g) #'h)
(define-values (i) j)))
(lookup-sig-mac x)))
(let ()
(define-signature-form (x y)
(list (cdr (syntax-e y))))
(test stx-bound-id=? #'((a)
()
())
(let ()
(define-signature z ((x . a)))
(lookup-sig-mac z))))
;; unit syntax errors (without sub-signatures)
(test-syntax-error "unit: bad sig import"
(unit (import 1) (export)))
(test-syntax-error "unit: bad sig export"
(unit (import) (export 1)))
(test-syntax-error "unit: unknown sig import"
(unit (import a) (export)))
(test-syntax-error "unit: unknown sig export"
(unit (import) (export a)))
(test-syntax-error "unit: bad tag (not identifier)"
(unit (import (tag 1 empty-sig)) (export)))
(test-syntax-error "unit: bad tag (not identifier)"
(unit (import) (export (tag 'a empty-sig))))
(test-syntax-error "define-values: bad syntax (in unit)"
(unit (import) (export) (define-values)))
(test-syntax-error "unit: multiple definition"
(unit (import) (export) (define-values (x x) (values 1 2))))
(test-syntax-error "unit: multiple definition"
(unit (import) (export) (define-syntaxes (x x) (values 1 2))))
(test-syntax-error "unit: multiple definition"
(unit (import) (export) (define x 1) (define x 2)))
(test-syntax-error "unit: multiple definition"
(unit (import) (export) (define-syntax x 1) (define-syntax x 2)))
(test-syntax-error "unit: multiple definition"
(unit (import) (export) (define x 1) (define-syntax x 2)))
(test-syntax-error "unit: re-export"
(unit (import x-sig) (export x-sig) (define x 1)))
(test-syntax-error "unit: redefine import"
(unit (import x-sig) (export) (define x 1)))
(test-syntax-error "unit: set! import"
(unit (import x-sig) (export) (set! x 1)))
(test-syntax-error "unit: set! export"
(unit (import) (export x-sig) (define x 1) (set! x 1)))
(test-syntax-error "unit: undefined export"
(unit (import) (export x-sig)))
(test-syntax-error "unit: undefined export"
(unit (import) (export (prefix x: x-sig)) (define x 1)))
(test-syntax-error "unit: syntax export"
(unit (import) (export x-sig) (define-syntax x 1)))
(test-syntax-error "unit: duplicate import"
(unit (import x-sig x-sig2) (export)))
(test-syntax-error "unit: duplicate export"
(unit (import) (export x-sig x-sig2) (define x 12)))
(test-syntax-error "unit: duplicate import signature"
(unit (import x-sig (prefix a x-sig)) (export)))
(test-syntax-error "unit: duplicate export signature"
(unit (import) (export x-sig (prefix a x-sig))
(define x 1) (define ax 2)))
(test-syntax-error "unit: duplicate import signature"
(unit (import (tag t x-sig) (tag t (prefix a x-sig))) (export)))
(test-syntax-error "unit: duplicate export signature"
(unit (import) (export (tag t x-sig) (tag t (prefix a x-sig)))
(define x 1) (define ax 2)))
(test-syntax-error "unit: duplicate export signature"
(unit (import) (export x-sig x-sig)
(define x 1)))
;; compound-unit syntax errors (without sub-signatures)
(test-syntax-error "compound-unit: bad import clause"
(compound-unit (import (a empty-sig)) (export) (link)))
(test-syntax-error "compound-unit: import clause bad link id"
(compound-unit (import (1 : empty-sig)) (export) (link)))
(test-syntax-error "compound-unit: import clause unknown sig"
(compound-unit (import (a : empty-si)) (export) (link)))
(test-syntax-error "compound-unit: export bad link id"
(compound-unit (import) (export a 1 b) (link)))
(test-syntax-error "compound-unit: link line bad link id"
(compound-unit (import) (export) (link (((a : empty-sig)) b 1))))
(test-syntax-error "compound-unit: import clause bad sig id"
(compound-unit (import (a : ())) (export) (link)))
(test-syntax-error "compound-unit: link line clause bad sig id"
(compound-unit (import) (export) (link (((a : "")) b))))
(test-syntax-error "compound-unit: link line clause bad"
(compound-unit (import) (export) (link (((a empty-sig)) b))))
(test-syntax-error "compound-unit: link line clause unknown"
(compound-unit (import) (export) (link (((a : b)) b))))
(test-syntax-error "compound-unit: duplicate link ids"
(compound-unit (import (x : x-sig) (x : y-sig)) (export) (link)))
(test-syntax-error "compound-unit: duplicate link ids"
(compound-unit (import) (export) (link (((x : x-sig) (x : y-sig)) u))))
(test-syntax-error "compound-unit: duplicate link ids"
(compound-unit (import (x : x-sig)) (export) (link (((x : x-sig)) u))))
(test-syntax-error "export: unbound link id"
(compound-unit (import) (export a) (link)))
(test-syntax-error "link link: unbound link id"
(compound-unit (import) (export) (link (() u a))))
(test-syntax-error "compound-unit: re-export"
(compound-unit (import (S : x-sig)) (export S) (link)))
(test-syntax-error "compound-unit: re-export"
(compound-unit (import (tag s (S : x-sig))) (export (tag t S)) (link)))
(test-syntax-error "compound-unit: duplicate export signature"
(compound-unit (import) (export X1 X2)
(link (((X1 : x-sig)) (unit (import) (export x-sig) (define x 1)))
(((X2 : x-sig)) (unit (import) (export x-sig) (define x 1))))))
(test-syntax-error "compound-unit: duplicate export signature"
(compound-unit (import) (export (tag t X1) (tag t X2))
(link (((X1 : x-sig)) (unit (import) (export x-sig) (define x 1)))
(((X2 : x-sig)) (unit (import) (export x-sig) (define x 1))))))
;; define-values/invoke-unit syntax errors
(test-syntax-error "define-values/invoke-unit: no unit"
(define-values/invoke-unit))
(test-syntax-error "define-values/invoke-unit: dot"
(define-values/invoke-unit x y . x))
(test-syntax-error "define-values/invoke-unit: bad sig"
(define-values/invoke-unit 1 1))
(test-syntax-error "define-values/invoke-unit: duplicate exports"
(define-values/invoke-unit (unit (import) (export (prefix x: x-sig) x-sig2)
(define x 1)
(define x:x 2))
x-sig x-sig2))
;; simple units, compound-units, and invoke-units (no subtypes, no tags, no prefix/rename/etc, no fancy signatures)
(test 12
(invoke-unit (unit (import) (export) 12)))
(test 3
(invoke-unit
(compound-unit (import) (export)
(link (((X : x-sig) (Y : y-sig)) (unit (import empty-sig z-sig)
(export y-sig x-sig)
(define x 1)
(define y 2))
Z E)
(((Z : z-sig) (E : empty-sig)) (unit (import x-sig y-sig)
(export empty-sig z-sig)
(define z 3)
3) X Y)))))
;; Test compound export with signatures containing overlapping names
(test (list 10 11 12)
(let ((un (compound-unit (import) (export S U)
(link (((S : x-sig)) (unit (import) (export x-sig) (define x 10)))
(((U : xy-sig)) (unit (import) (export xy-sig) (define x 11) (define y 12)))))))
(invoke-unit
(compound-unit (import) (export)
(link (((S : x-sig) (U : xy-sig)) un)
(((B : b-sig)) (unit (import x-sig) (export b-sig) (define b x)) S)
(() (unit (import b-sig xy-sig) (export) (list b x y)) B U))))))
(define-signature even-sig (even))
(define-signature odd-sig (odd))
(define even-unit
(unit (import odd-sig)
(export even-sig)
(define (even x)
(or (= 0 x) (odd (sub1 x))))))
(define odd-unit
(unit (import even-sig)
(export odd-sig)
(define (odd x)
(and (> x 0) (even (sub1 x))))
(define x (odd 11))
x))
(define run-unit
(compound-unit (import)
(export)
(link (((EVEN : even-sig)) even-unit ODD)
(((ODD : odd-sig)) odd-unit EVEN))))
(test #t (invoke-unit run-unit))
(define-signature is-3x-sig (is-3x))
(define-signature is-3x+1-sig (is-3x+1))
(define-signature is-3x+2-sig (is-3x+2))
(define is-3x-unit
(unit (import is-3x+2-sig)
(export is-3x-sig)
(define (is-3x x)
(or (= 0 x) (is-3x+2 (sub1 x))))))
(define is-3x+2-unit
(unit (import is-3x+1-sig)
(export is-3x+2-sig)
(define (is-3x+2 x)
(and (> x 0) (is-3x+1 (sub1 x))))))
(define is-3x+1-unit
(unit (import is-3x-sig)
(export is-3x+1-sig)
(define (is-3x+1 x)
(and (> x 0) (is-3x (sub1 x))))))
(define 3x-compound1
(compound-unit (import (IS-3X : is-3x-sig))
(export IS-3X+1 IS-3X+2)
(link (((IS-3X+1 : is-3x+1-sig)) is-3x+1-unit IS-3X)
(((IS-3X+2 : is-3x+2-sig)) is-3x+2-unit IS-3X+1))))
(define 3x-compound2
(compound-unit (import)
(export IS-3X)
(link (((IS-3X : is-3x-sig)) is-3x-unit IS-3X+2)
(((IS-3X+1 : is-3x+1-sig)
(IS-3X+2 : is-3x+2-sig)) 3x-compound1 IS-3X))))
(define 3x-run-unit
(unit (import is-3x-sig is-3x+1-sig is-3x+2-sig)
(export)
(list (is-3x 1)
(is-3x 3)
(is-3x+1 5)
(is-3x+1 7)
(is-3x+2 4)
(is-3x+2 8))))
(define 3x-compound3
(compound-unit (import)
(export IS-3X IS-3X+1 IS-3X+2)
(link (((IS-3X : is-3x-sig)) 3x-compound2)
(((IS-3X+1 : is-3x+1-sig)
(IS-3X+2 : is-3x+2-sig)) 3x-compound1 IS-3X)
(() 3x-run-unit IS-3X IS-3X+1 IS-3X+2))))
(test (list #f #t #f #t #f #t)
(invoke-unit 3x-compound3))
(test (list #t #t #t)
(let ()
(define-values/invoke-unit 3x-compound3 (import) (export is-3x-sig is-3x+1-sig is-3x+2-sig))
(list (is-3x+2 8)
(is-3x+1 7)
(is-3x 6))))
(test (list #t #t #t)
(let ()
(define-values/invoke-unit 3x-compound3 (import) (export (only is-3x-sig is-3x) (except is-3x+1-sig) (prefix x: is-3x+2-sig)))
(list (x:is-3x+2 8)
(is-3x+1 7)
(is-3x 6))))
(test (list #t #t #t)
(let ()
(define-values/invoke-unit 3x-compound3 (import) (export is-3x-sig is-3x+1-sig (rename is-3x+2-sig (y is-3x+2))))
(list (y 8)
(is-3x+1 7)
(is-3x 6))))
;; Tags
(let ()
(define u
(unit (import x-sig (tag t (prefix t: x-sig)) (tag u (prefix u: x-sig)))
(export)
(list x t:x u:x)))
(define v
(unit (import)
(export x-sig (tag t (prefix t: x-sig)) (tag u (prefix u: x-sig)))
(define x 1)
(define t:x 2)
(define u:x 3)))
(test '(3 1 2)
(invoke-unit
(compound-unit (import) (export)
(link (((X1 : x-sig) (X2 : (tag u x-sig)) (X3 : (tag t x-sig))) v)
(() u (tag t X1) X2 (tag u X3))))))
(test '(3 1 2)
(invoke-unit
(compound-unit (import) (export)
(link (((L1 : (tag a x-sig)) (L2 : (tag b x-sig)) (L3 : (tag c x-sig)))
(compound-unit (import) (export (tag a X1) (tag b X2) (tag c X3))
(link (((X1 : x-sig) (X2 : (tag u x-sig)) (X3 : (tag t x-sig))) v))))
(()
(compound-unit (import (X1 : x-sig) (X2 : (tag u x-sig)) (X3 : (tag t x-sig))) (export)
(link (() u (tag t X1) X2 (tag u X3))))
L1 (tag u L2) (tag t L3)))))))
(let ()
(define-values/invoke-unit (unit (import) (export (tag t x-sig)) (define x 1)) (import) (export (tag t x-sig)))
(test 1 x))
;; simple runtime errors (no subtyping, no deps)
(test-runtime-error exn:fail:contract? "compound-unit: not a unit"
(compound-unit (import) (export) (link (() 1))))
(test-runtime-error exn:fail:contract? "compound-unit: missing import"
(compound-unit (import) (export)
(link (() (unit (import x-sig) (export))))))
(test-runtime-error exn:fail:contract? "compound-unit: missing import"
(compound-unit (import (X : x-sig)) (export)
(link (() (unit (import x-sig) (export))
(tag u X)))))
(test-runtime-error exn:fail:contract? "compound-unit: missing import"
(compound-unit (import (X : x-sig)) (export)
(link (() (unit (import (tag u x-sig)) (export))
X))))
(test-runtime-error exn:fail:contract? "compound-unit: missing export"
(compound-unit (import) (export)
(link (((X : x-sig)) (unit (import) (export))))))
(test-runtime-error exn:fail:contract? "compound-unit: missing export"
(compound-unit (import) (export)
(link (((X : (tag u x-sig))) (unit (import) (export x-sig) (define x 1))))))
(test-runtime-error exn:fail:contract? "compound-unit: missing export"
(compound-unit (import) (export)
(link (((X : x-sig)) (unit (import (tag u x-sig)) (export))))))
(test-runtime-error exn:fail:contract? "invoke-unit: not a unit"
(invoke-unit 1))
(test-runtime-error exn:fail:contract? "invoke-unit: unit has imports"
(invoke-unit (unit (import x-sig) (export) x)))
(test-runtime-error exn:fail:contract? "define-values/invoke-unit: not a unit"
(define-values/invoke-unit 1 (import) (export)))
(test-runtime-error exn:fail:contract? "define-values/invoke-unit: has imports"
(define-values/invoke-unit (unit (import x-sig) (export) x) (import) (export)))
(test-runtime-error exn:fail:contract? "define-values/invoke-unit: signature mismatch"
(define-values/invoke-unit (unit (import) (export)) (import) (export x-sig)))
;; unit creation w/o signatures (including macros and prefixes/renames).
;; free vars
(let ((y 1)
(z 10))
(define u (unit (import) (export yz-sig)
(define y 2)
(define z 3)))
(define u1 (unit (import) (export)
y))
(define u2 (unit (import (only yz-sig z)) (export)
y))
(define u3 (unit (import (except yz-sig y)) (export)
y))
(define u4 (unit (import (prefix s: yz-sig)) (export)
y))
(define u5 (unit (import (rename yz-sig (r y))) (export)
y))
(define u6 (unit (import yz-sig) (export)
y))
(define (l x)
(invoke-unit
(compound-unit (import) (export)
(link (((YZ : yz-sig)) u)
(() x YZ)))))
(test 1 (invoke-unit u1))
(test 1 (l u2))
(test 1 (l u3))
(test 1 (l u4))
(test 1 (l u5))
(test 2 (l u6))
(test (letrec ((x x)) x)
(let ()
(define-values/invoke-unit (unit-from-context yz-sig) (import) (export yz-sig))
y))
(test 1
(let ()
(let ((u (unit-from-context yz-sig)))
(define-values/invoke-unit u (import) (export (prefix x: yz-sig)))
x:y)))
;; Exporting and prefix don't work right because the shadower doesn't see the shadowed
;; bindings, I think.
#;(test 1
(let ((x:y 12)
(x:z 10))
(let ((u (unit-from-context (prefix x: yz-sig))))
(define-values/invoke-unit u yz-sig)
y)))
#;(test 1
(let ((x:y 12)
(x:z 10))
(define-signature t (y z))
(let ((u (unit-from-context (prefix x: t))))
(define-values/invoke-unit u t)
y)))
(test 12
(let ((x:y 12)
(x:z 10))
(define-values/invoke-unit (unit-from-context (rename yz-sig (x:y y) (x:z z)))
(import) (export yz-sig))
y))
(test 12
(let ((x:y 12)
(x:z 10))
(define-signature t (y z))
(let ()
(define-values/invoke-unit (unit-from-context (rename t (x:y y) (x:z z))) (import) (export t))
y))))
;; Test that a define-values can define both internal and exported vars
(test '(1 2)
(invoke-unit
(compound-unit (import) (export)
(link (((T : yz-sig)) (unit (import x-sig) (export yz-sig)
(define-values (y a) (values 1 2))
(define-values (b z) (values y a)))
S)
(((S : x-sig)) (unit (import yz-sig) (export x-sig) (define x 3) (list y z)) T)))))
;; Test that internal macros can define exports
(test 1
(invoke-unit
(unit (import) (export x-sig)
(define-syntax (y stx)
(syntax-case stx ()
((_ x) #'(define x 1))))
(y x)
x)))
(define-signature fact-sig (fact n))
;; Test renaming, self-recursion, only, and except
(test 24
(invoke-unit
(compound-unit (import) (export)
(link (((F : fact-sig)) (unit (import (except (rename fact-sig (f-in fact)) n))
(export (rename fact-sig (f-out fact)))
(define n 1)
(define (f-out x) (if (= 0 x)
1
(* x (f-in (sub1 x))))))
F)
(() (unit (import (only fact-sig fact)) (export)
(define n 2)
(fact 4))
F)))))
;; Test import prefix
(test 1
(invoke-unit
(compound-unit (import) (export)
(link (((S : x-sig)) (unit (import) (export x-sig) (define x 1)))
(() (unit (import (prefix s: x-sig)) (export) s:x) S)))))
(define-signature sx (x))
(define-signature sy (y))
(define-signature sz (z))
;; Test separate signatures with overlapping bindings, and export renaming and prefix
(test '(1 2 3)
(invoke-unit
(compound-unit (import) (export)
(link (((S : x-sig) (T : yz-sig) (U : xy-sig)) (unit (import) (export (rename x-sig (s:x x))
(rename yz-sig (t:y y) (t:z z))
(prefix u: xy-sig))
(define x 1) (define y 2) (define z 3)
(define s:x x) (define t:y y) (define t:z z) (define u:x x) (define u:y y)))
(((SX : sx)) (unit (import (prefix s: x-sig)) (export sx) (define x s:x)) S)
(((SY : sy)) (unit (import (prefix u: xy-sig)) (export sy) (define y u:y)) U)
(((SZ : sz)) (unit (import (prefix t: yz-sig)) (export sz) (define z t:z)) T)
(() (unit (import sx sy sz) (export) (list x y z)) SX SY SZ)))))
;; Test units importing and exporting b, where lexical definition of b shadows
;; the b identifier in the signature
(test 2
(let ((b 1))
(define u1 (unit (import) (export b-sig) (define b 2)))
(define u2 (unit (import b-sig) (export) b))
(invoke-unit (compound-unit (import) (export)
(link (((B : b-sig)) u1)
(() u2 B))))))
(test 1
(let ((b 1))
(define u1 (unit-from-context b-sig))
(let ((b 2))
(define-values/invoke-unit u1 (import) (export b-sig))
b)))
(let ((x 1)
(v 2))
(let-syntax ((s (syntax-rules () ((_) (list x v)))))
(define-signature t (x (define-syntaxes (s)
(syntax-rules ()
((_) (list x v))))
(define-values (v) (add1 x))))
(define-signature t2 (x (define-syntaxes (s)
(syntax-rules ()
((_) (list x v))))
(define-values (v) (add1 x))))
(define u3 (unit (import) (export t)
(define x 3)))
(define u4 (unit (import) (export t2)
(define x 4)))
(define (i u)
(invoke-unit
(compound-unit (import) (export)
(link (((T3 : t)) u3)
(((T4 : t2)) u4)
(() u T3 T4)))))
;; prefix
(let ((x 5)
(v 6))
(let-syntax ((s (syntax-rules () ((_) (list x v)))))
(test '(7 8 (7 8) 3 4 (3 4) 4 5 (4 5))
(i (unit (import (prefix p: t) (prefix q: t2)) (export)
(define x 7)
(define v 8)
(define-syntax s (syntax-rules () ((_) (list x v))))
(list x v (s) p:x p:v (p:s) q:x q:v (q:s)))))
(test '(5 6 (5 6) 3 4 (3 4) 4 5 (4 5))
(i (unit (import (prefix p: t) (prefix q: t2)) (export)
(list x v (s) p:x p:v (p:s) q:x q:v (q:s)))))))
(test '(7 8 (7 8) 3 4 (3 4) 4 5 (4 5))
(i (unit (import (prefix p: t) (prefix q: t2)) (export)
(define x 7)
(define v 8)
(define-syntax s (syntax-rules () ((_) (list x v))))
(list x v (s) p:x p:v (p:s) q:x q:v (q:s)))))
(test '(1 2 (1 2) 3 4 (3 4) 4 5 (4 5))
(i (unit (import (prefix p: t) (prefix q: t2)) (export)
(list x v (s) p:x p:v (p:s) q:x q:v (q:s)))))
;; only
(let ((x 5)
(v 6))
(let-syntax ((s (syntax-rules () ((_) (list x v)))))
(test '(7 8 (7 8) (3 4) (4 5))
(i (unit (import (prefix p: (only t s)) (only (prefix q: t2) q:s)) (export)
(define x 7)
(define v 8)
(define-syntax s (syntax-rules () ((_) (list x v))))
(list x v (s) (p:s) (q:s)))))
(test '(5 6 (5 6) (3 4) (4 5))
(i (unit (import (prefix p: (only t s)) (prefix q: (only t2 s))) (export)
(list x v (s) (p:s) (q:s)))))))
(test '(7 8 (7 8) (3 4) (4 5))
(i (unit (import (only (prefix p: t) p:s) (only (prefix q: t2) q:s)) (export)
(define x 7)
(define v 8)
(define-syntax s (syntax-rules () ((_) (list x v))))
(list x v (s) (p:s) (q:s)))))
(test '(1 2 (1 2) (3 4) (4 5))
(i (unit (import (prefix p: (only t s)) (prefix q: (only t2 s))) (export)
(list x v (s) (p:s) (q:s)))))
;;rename
(let ((x 5)
(v 6))
(let-syntax ((s (syntax-rules () ((_) (list x v)))))
(test '(7 8 (7 8) 3 4 (3 4) 4 5 (4 5))
(i (unit (import (rename t (p:x x) (p:v v) (p:s s))
(rename t2 (q:x x) (q:v v) (q:s s)))
(export)
(define x 7)
(define v 8)
(define-syntax s (syntax-rules () ((_) (list x v))))
(list x v (s) p:x p:v (p:s) q:x q:v (q:s)))))
(test '(5 6 (5 6) 3 4 (3 4) 4 5 (4 5))
(i (unit (import (rename t (p:x x) (p:v v) (p:s s))
(rename t2 (q:x x) (q:v v) (q:s s)))
(export)
(list x v (s) p:x p:v (p:s) q:x q:v (q:s)))))))
(test '(7 8 (7 8) 3 4 (3 4) 4 5 (4 5))
(i (unit (import (rename t (p:x x) (p:v v) (p:s s))
(rename t2 (q:x x) (q:v v) (q:s s)))
(export)
(define x 7)
(define v 8)
(define-syntax s (syntax-rules () ((_) (list x v))))
(list x v (s) p:x p:v (p:s) q:x q:v (q:s)))))
(test '(1 2 (1 2) 3 4 (3 4) 4 5 (4 5))
(i (unit (import (rename t (p:x x) (p:v v) (p:s s))
(rename t2 (q:x x) (q:v v) (q:s s)))
(export)
(list x v (s) p:x p:v (p:s) q:x q:v (q:s))))))
)
(let ()
(define-signature x ((define-syntaxes (m)
(syntax-rules ()
((_ x) (define-syntax x
(syntax-rules ()
((_ y) y))))))
(define-values (v)
(let ()
(m a)
(a 1)))))
(test 1
(invoke-unit
(compound-unit (import) (export)
(link (((X : x)) (unit (import) (export x)))
(() (unit (import x) (export) v) X))))))
(let ()
(define-signature x ((define-syntaxes (m)
(syntax-rules ()
((_ x) (define-syntax x #'1))))
(define-syntaxes (m2)
(lambda (stx)
(syntax-case stx ()
((_ x) (syntax-local-value #'x)))))
(define-values (v)
(let ()
(m a)
(m2 a)))))
(test 1
(invoke-unit
(compound-unit (import) (export)
(link (((X : x)) (unit (import) (export x)))
(() (unit (import x) (export) v) X))))))
(let ()
(define-signature x ((define-syntaxes (m) #'1)
(define-syntaxes (m2)
(lambda (stx)
(syntax-case stx ()
((_ x) (syntax-local-value #'x)))))
(define-values (v)
(let ()
(m2 m)))))
(test 1
(invoke-unit
(compound-unit (import) (export)
(link (((X : x)) (unit (import) (export x)))
(() (unit (import x) (export) v) X))))))
(let ()
(define-signature s1 (a (define-values (x y) (values 1 2))))
(define-signature s2 extends s1 ((define-values (z) (list a x))))
(define u1 (unit (import s2) (export) (cons y z)))
(define u2 (unit (import) (export s2) (define a 123)))
(test (list 2 123 1) (invoke-unit (compound-unit (import) (export)
(link (((a : s2)) u2)
(() u1 a))))))
(let ()
(define-signature s1 (a (define-values (x y) (values 1 2))))
(let ((x 12))
(define-signature s2 extends s1 ((define-values (z) (list a x))))
(define u1 (unit (import s2) (export) (cons y z)))
(define u2 (unit (import) (export s2) (define a 123)))
(test (list 2 123 12) (invoke-unit (compound-unit (import) (export)
(link (((a : s2)) u2)
(() u1 a)))))))
(let ()
(define-signature s1 (a (define-values (x y) (values c 2))))
(define-signature s2 extends s1 (c (define-values (z) (list a x))))
(define u1 (unit (import s2) (export) (cons y z)))
(define u2 (unit (import) (export s2) (define a 123) (define c 43)))
(test (list 2 123 43) (invoke-unit (compound-unit (import) (export)
(link (((a : s2)) u2)
(() u1 a))))))
;; Test define-syntaxes and define-values, without except, only, prefix and rename
;; Check the scoping
(let ((a 'abad)
(b 'bbad)
(c 'cbad)
(v1 'v1bad)
(v2 'v2bad)
(s1 's1bad)
(s2 's2bad)
(strange-fact 'sfbad)
(z 'zbad))
(define z 1)
(define a 'abad2)
(define c 'cbad2)
(define strange-fact 'sfbad4)
(define-signature macro (a b c
(define-values (v1) (list a b c z 2))
(define-values (v2) (s2 a b c))
(define-values (strange-fact)
(lambda (x)
(if (= x 0) (list z a b c) (cons x (strange-fact (sub1 x))))))
(define-syntaxes (s1 s2)
(values
(syntax-rules ()
((_ a1 b1 c1) (list a b c v1 a1 b1 c1 z)))
(syntax-rules ()
((_ a1 b1 c1) (s1 a1 b1 c1)))))))
(let ((b 'bbad2)
(c 'cbad3))
(define z 3)
(define u1
(unit (import macro) (export)
(define z 4)
(list a b c v1 v2 (strange-fact 5) (s1 6 7 8) (s2 9 10 11))))
(define u2
(unit (import) (export macro)
(define a 12)
(define b 13)
(define c 14)))
(test '(12 13 14
(12 13 14 1 2)
(12 13 14 (12 13 14 1 2) 12 13 14 1)
(5 4 3 2 1 1 12 13 14)
(12 13 14 (12 13 14 1 2) 6 7 8 1)
(12 13 14 (12 13 14 1 2) 9 10 11 1))
(invoke-unit
(compound-unit (import) (export)
(link (((U2 : macro)) u2)
(() u1 U2)))))))
;; We can re-define imported values
(let ()
(define-signature s ((define-values (y) 1)))
(define-signature t (z))
(test 3
(invoke-unit
(compound-unit (import) (export)
(link (((T : t)) (unit (import s) (export t) (define y 3) (define z y)) S)
(((S : s)) (unit (import) (export s) (define y 1)))
(() (unit (import t) (export) z) T))))))
;; Can't use imports as pattern variables
#;(let ()
(define-signature s (y (define-syntaxes (m) (syntax-rules (y) ((_ y) 1)))))
(unit (import s) (export)
(m y)))
(test '(2 3)
(let ()
(define-signature sig (y (define-values (v) (add1 y))))
(let ()
(define-values/invoke-unit
(unit (import) (export sig) (define y 2))
(import)
(export sig))
(list y v))))
;; I'm not sure that this should work.
#;(test '(2 3)
(let ()
(define-signature sig (y (define-values (v) (add1 y))))
(define-values/invoke-unit
(unit (import) (export sig) (define y 2))
sig)
(list y v)))
;; subtyping
(let ()
(define u1 (unit (import x-sig) (export y-sub) (define y (add1 x)) (define yy 2) (list x y yy)))
(define u2 (unit (import y-sig) (export x-sub) (define x 3) (define xx 44)))
(define u3 (compound-unit (import (S1 : x-sig)) (export S4)
(link (((S4 : y-sub)) u1 S1))))
(define u4 (compound-unit (import (S3 : y-sig)) (export S2)
(link (((S2 : x-sub)) u2 S3))))
(define u5 (compound-unit (import (S2 : y-sub)) (export S1)
(link (((S1 : x-sig)) u2 S2))))
(test '(3 4 2)
(invoke-unit
(compound-unit (import) (export)
(link (((S1 : x-sig)) u2 S2)
(((S2 : y-sig)) u1 S1)))))
(test '(3 4 2)
(invoke-unit
(compound-unit (import) (export)
(link (((S1 : x-sub)) u2 S2)
(((S2 : y-sub)) u1 S1)))))
(test '(3 4 2)
(invoke-unit
(compound-unit (import) (export)
(link (((S1 : x-sub)) u4 S4)
(((S4 : y-sub)) u3 S1)))))
(test '(3 4 2)
(invoke-unit
(compound-unit (import) (export)
(link (((S1 : x-sig)) u4 S4)
(((S4 : y-sig)) u3 S1)))))
(test '(3 4 2)
(invoke-unit
(compound-unit (import) (export)
(link (((S1 : x-sig)) u5 S2)
(((S2 : y-sub)) u1 S1))))))
(let ()
(define u1 (unit (import) (export x-sig) (define x 1)))
(define u2 (unit (import x-sub) (export)))
(test-runtime-error exn:fail:contract? "compound-unit: not a subtype"
(compound-unit (import) (export)
(link (((S : x-sub)) u1))))
(test-runtime-error exn:fail:contract? "compound-unit: not a subtype"
(compound-unit (import) (export)
(link (((S : x-sig)) u1)
(() u2 S))))
(test-runtime-error exn:fail:contract? "compound-unit: not a subtype"
(compound-unit (import (S : x-sig)) (export)
(link (() u2 S)))))
(let ()
(define u1 (unit (import) (export x-sub y-sub) (define x 1) (define xx 2) (define y 3) (define yy 4)))
(define-values/invoke-unit u1 (import) (export x-sig))
(test 1 x)
(test-runtime-error exn? "unbound identifier" xx)
(test-runtime-error exn? "unbound identifier" y)
(test-runtime-error exn? "unbound identifier" yy))
(let ()
(define u1 (unit (import) (export x-sig) (define x 1)))
(test-runtime-error exn:fail:contract? "define-values/invoke-unit: not a subtype"
(define-values/invoke-unit u1 (import) (export x-sub))))
;; export-subtyping
(test-syntax-error "duplicate exports (subtypes)"
(unit (import) (export x-sig x-sub)
(define x 1)
(define xx 1)))
(test-syntax-error "duplicate exports (subtypes)"
(unit (import) (export x-sub x-sig)
(define x 1)
(define xx 1)))
(let ()
(define u (unit (import) (export x-sub) (define x 1) (define xx 1)))
(test-syntax-error "duplicate exports (subtypes)"
(compound-unit (import) (export l1 l2)
(link (((l1 : s1)) u)
(((l2 : s2)) u)))))
(let ()
(define u (unit (import) (export x-sub (prefix x: x-sub2))
(define x 1)
(define xx 2)
(define x:x 3)
(define x:x2 4)))
(define u2 (unit (import x-sig) (export)))
(define v (unit (import x-sub) (export)
(+ x xx)))
(define w (unit (import x-sub2) (export)
(+ x x2)))
(define u3 (unit (import x-sub (prefix m: x-sub2)) (export)
(+ x xx m:x m:x2)))
(test 3
(invoke-unit
(compound-unit (import) (export)
(link (((S2 : x-sub)) u)
(() v S2)))))
(test 7
(invoke-unit
(compound-unit (import) (export)
(link (((S3 : x-sub2)) u)
(() w S3)))))
(test 10
(invoke-unit
(compound-unit (import) (export)
(link (((S3 : x-sub2) (S2 : x-sub)) u)
(() u3 S3 S2)))))
(test-runtime-error exn:fail:contract? "ambiguous export"
(compound-unit (import) (export)
(link (((S1 : x-sig)) u)))))
(test-runtime-error exn:fail:contract? "ambiguous import"
(compound-unit (import (S1 : x-sub) (S2 : x-sub2)) (export)
(link (() u2 S1 S2))))
(test-syntax-error "duplicate links (subtype)"
(compound-unit (import) (export)
(link (((S1 : x-sig)) u3)
(() u1 S2 S1)
(((S2 : x-sig)) u3))))
;; tags
(let ()
(define-signature s1 (a))
(define-signature s2 extends s1 (b))
(define-signature s3 extends s2 ())
(define-signature s4 extends s3 ())
(define u1
(unit (import (prefix s1: s1)
(tag t (prefix s2: s2))
(prefix bs1: s2)
(prefix bs2: s3))
(export)
(list s1:a s2:a s2:b bs1:a bs2:b)))
(define u2
(unit (import) (export s3)
(define a 1) (define b 2)))
(define u3
(unit (import) (export s2)
(define a 3) (define b 4)))
(test '(1 3 4 1 2)
(invoke-unit
(compound-unit (import) (export)
(link (((S2a : s3)) u2)
(((S2b : s2)) u3)
(() u1 S2a (tag t S2b))))))
(test-runtime-error exn:fail:contract? "compound-unit: signature mismatch"
(invoke-unit
(compound-unit (import) (export)
(link (((S1 : s1)) u2)
(((S2 : s2)) u3)
(() u1 (tag t S1) S2))))))
(let ()
(define u1
(unit (import) (export (prefix a: x-sig) (tag t (prefix c: x-sig)))
(define a:x 1)
(define c:x 4)))
(define u2
(unit (import x-sig) (export)
x))
(define u3
(unit (import x-sub) (export)
(list x xx)))
(test 4
(invoke-unit
(compound-unit (import) (export)
(link (((S1 : (tag t x-sig)) (S2 : x-sig)) u1)
(() u2 S1)))))
(test-runtime-error exn:fail:contract? "compound-unit: signature mismatch"
(invoke-unit
(compound-unit (import) (export)
(link (((S1 : (tag t x-sub)) (S2 : x-sub)) u1)
(() u2 S1)))))
)
(let ()
(define u1 (unit (import) (export (tag t1 x-sig) (prefix : x-sig))
(define x 10)
(define :x 11)))
(define-values/invoke-unit u1 (import) (export x-sig (tag t1 (prefix m x-sig))))
(test '(11 10)
(list x mx)))
(define-signature s1 (x))
(define-signature s2 (a x z))
(test-syntax-error "unit-from-context: no sigs"
(unit-from-context))
(test-syntax-error "unit-from-context: too many sigs"
(unit-from-context s1 s2))
(test-syntax-error "unit-from-context: too many sigs"
(unit-from-context s1 . s2))
(test-syntax-error "unit-from-context: bad sig"
(unit-from-context 1))
(test-syntax-error "unit-from-context: no name"
(define-unit-from-context))
(test-syntax-error "unit-from-context: no sigs"
(define-unit-from-context s1))
(test-syntax-error "unit-from-context: no sigs"
(define-unit-from-context n))
(test-syntax-error "unit-from-context: too many sigs"
(define-unit-from-context n s1 s2))
(test-syntax-error "unit-from-context: too many sigs"
(define-unit-from-context n s1 . s2))
(test-syntax-error "unit-from-context: bad sig"
(define-unit-from-context n 1))
;; Test the struct form
(test-syntax-error "struct: missing name and fields"
(define-signature x ((struct))))
(test-syntax-error "struct: missing name"
(define-signature x ((struct n))))
(test-syntax-error "struct: bad name"
(define-signature x ((struct 1 ()))))
(test-syntax-error "struct: bad fields (dot)"
(define-signature x ((struct n (x . y)))))
(test-syntax-error "struct: bad fields"
(define-signature x ((struct n 1))))
(test-syntax-error "struct: bad omission"
(define-signature x ((struct n () t))))
(test-syntax-error "struct: bad omission (dot)"
(define-signature x ((struct n () . -selectors))))
(test-syntax-error "struct: bad omission"
(define-signature x ((struct n () x))))
(let ()
(define-signature sig ((struct s (x y))))
(test 3
(invoke-unit
(compound-unit (import) (export)
(link (((S : sig)) (unit (import) (export sig)
(define-struct s (x y))))
(() (unit (import sig) (export)
(match (make-s 1 2)
((struct s (a b)) (+ a b))))
S)))))
(let ()
(define-values/invoke-unit (unit (import) (export sig) (define-struct s (x y)))
(import)
(export sig))
(test 3
(match (make-s 1 2)
((struct s (a b)) (+ a b)))))
(let ()
(define u
(unit (import) (export (rename sig (make-s/defaults make-s)))
(define-struct s (x y))
(define (make-s/defaults x)
(make-s x 'default))))
(define-values/invoke-unit u (import) (export sig))
(test #t (s? (make-s 1))))
(let ((set-s-x! 1))
(define-signature sig ((struct s (x y))))
(test 1
(invoke-unit
(compound-unit (import) (export)
(link (((S : sig)) (unit (import) (export sig) (define-struct s (x y))))
(() (unit (import sig) (export)
set-s-x!) S))))))
(let ((make-s 1))
(define-signature sig ((struct s (x y) #:omit-constructor)))
(test 1
(invoke-unit
(compound-unit (import) (export)
(link (((S : sig)) (unit (import) (export sig) (define-struct s (x y))))
(() (unit (import sig) (export)
make-s) S)))))))
;; Dependencies
(define-signature s1 (a))
(define-signature s2 extends s1 ())
(define u1 (unit (import s1) (export) (init-depend s1)
a))
(define u2 (unit (import) (export s1)
(define a 12)))
(define u3 (unit (import (tag t s1)) (export) (init-depend (tag t s1))
a))
(define u4 (compound-unit (import (L : s2)) (export)
(link (() u1 L))))
(define u5 (unit (import) (export s2)
(define a 12)))
(test-syntax-error "unit: bad dependency"
(unit (import (tag t s1)) (export) (init-depend s1)))
(test-syntax-error "unit: bad dependency"
(unit (import s1) (export) (init-depend (tag t s1))))
(test 12 (invoke-unit (compound-unit (import) (export)
(link (((S1 : s1)) u2)
(() u1 S1)))))
(test-runtime-error exn:fail:contract? "Dependency violation"
(compound-unit (import) (export)
(link (() u1 S1)
(((S1 : s1)) u2))))
(test-runtime-error exn:fail:contract? "Dependency violation"
(compound-unit (import) (export)
(link (() u3 (tag t S1))
(((S1 : s1)) u2))))
(test-runtime-error exn:fail:contract? "Dependency violation"
(compound-unit (import) (export)
(link (() u4 S2)
(((S2 : s2)) u5))))
;; Inference
(define u (unit (import x-sig) (export y-sig) (define y 0) x))
(define v (unit (import) (export x-sig y-sig) (define x 9) (define y 10)))
(test 9
(let ()
(define-unit-binding u2 u (import x-sig y-sig) (export))
(invoke-unit
(compound-unit (import) (export)
(link (((A : x-sig) (B : y-sig)) v)
(() u A B))))))
(test-runtime-error exn:fail:contract? "not subunit"
(let () (define-unit-binding u2 u (import x-sig) (export x-sig)) 1))
(test-runtime-error exn:fail:contract? "not subunit"
(let () (define-unit-binding u2 u (import) (export)) 1))
(test-runtime-error exn:fail:contract? "not a unit"
(let () (define-unit-binding u2 1 (import) (export)) 1))
(test-syntax-error "define-unit-binding: duplicate import"
(define-unit-binding u 1 (import x-sig x-sig) (export)))
(test-syntax-error "define-unit-binding: export subtypes"
(define-unit-binding u 1 (import) (export x-sig x-sub)))
(test-syntax-error "define-unit-binding: export subtypes"
(define-unit-binding u 1 (import) (export x-sub x-sig)))
(test-syntax-error "define-unit-binding: bad dependency"
(define-unit-binding u 1 (import x-sig) (export) (init-depend x-sub)))
(test-syntax-error "define-unit-binding: bad dependency"
(define-unit-binding u 1 (import x-sub) (export) (init-depend x-sig)))
(test-syntax-error "define-unit: missing name, import, export"
(define-unit))
(test-syntax-error "define-unit: missing import, export"
(define-unit a))
(test-syntax-error "define-unit: missing export"
(define-unit a (import)))
(test-syntax-error "define-unit: missing name"
(define-unit (import) (export)))
(test-syntax-error "define-unit: bad name"
(define-unit "x" (import) (export)))
(test-syntax-error "define-unit: bad syntax"
(define-unit x (unit (import) (export))))
(test-runtime-error exn:fail:contract? "define-unit: bad set!"
(let ()
(define-signature s ())
(define-unit x (import) (export) 1)
(set! x (unit (import s) (export) 1))))
(test-runtime-error exn:fail:contract? "define-unit: bad set!"
(let ()
(define-signature s ())
(define-unit x (import) (export s) 1)
(set! x (unit (import) (export) 1))))
(test-syntax-error "define-compound-unit: missing import"
(define-compound-unit x))
(test-syntax-error "define-compound-unit: missing name"
(define-compound-unit))
(test-syntax-error "define-compound-unit: missing name"
(define-compound-unit (import) (link) (export)))
(test-syntax-error "define-compound-unit: bad name"
(define-compound-unit 1 (import) (link) (export)))
(test-syntax-error "invoke-unit/infer : no unit"
(invoke-unit/infer))
(test-syntax-error "invoke-unit/infer : not a unit"
(invoke-unit/infer 1))
(test-syntax-error "invoke-unit/infer : not a unit"
(let ([x 1]) (invoke-unit/infer x)))
(test-syntax-error "invoke-unit/infer : not a unit"
(let-syntax ([x 1]) (invoke-unit/infer x)))
(test-syntax-error "invoke-unit/infer: too much"
(invoke-unit/infer x y))
(define-unit u (import x-sig) (export))
(define-unit v (import) (export x-sig) (define x 3))
(test-syntax-error "invoke-unit/infer : no unit"
(invoke-unit/infer (link)))
(test-syntax-error "invoke-unit/infer : not a unit"
(invoke-unit/infer (link 1 u)))
(test-syntax-error "invoke-unit/infer : not a unit"
(let ([x 1]) (invoke-unit/infer (link u x))))
(test-syntax-error "invoke-unit/infer : not a unit"
(let-syntax ([x 1]) (invoke-unit/infer (link x u))))
(invoke-unit/infer (link u v))
(test-syntax-error "define-values/invoke-unit/infer: no unit"
(define-values/invoke-unit/infer))
(test-syntax-error "define-values/invoke-unit/infer: not a unit"
(define-values/invoke-unit/infer 1))
(test-syntax-error "define-values/invoke-unit/infer: not a unit"
(let ((x 1))
(define-values/invoke-unit/infer x)))
(test-syntax-error "define-values/invoke-unit/infer: not a unit"
(let-syntax ((x 1))
(define-values/invoke-unit/infer x)))
(test-syntax-error "define-values/invoke-unit/infer: too much"
(define-values/invoke-unit/infer x y))
(define-unit u (import x-sig) (export) x)
(define-unit v (import) (export x-sig) (define x 3))
(test-syntax-error "define-values/invoke-unit/infer: no unit"
(define-values/invoke-unit/infer (link)))
(test-syntax-error "define-values/invoke-unit/infer: not a unit"
(define-values/invoke-unit/infer (link 1 u)))
(test-syntax-error "define-values/invoke-unit/infer: not a unit"
(let ([x 1])
(define-values/invoke-unit/infer (link u x))))
(test-syntax-error "define-values/invoke-unit/infer: not a unit"
(let-syntax ([x 1])
(define-values/invoke-unit/infer (link u x))))
(let ()
(define-values/invoke-unit/infer (link u v))
x)
(let ()
(define-values/invoke-unit/infer (export x-sig) (link u v))
x)
(let ()
(define-values/invoke-unit/infer (export x-sig) v)
x)
(test-syntax-error "define-values/invoke-unit/infer: doesn't export y"
(define-values/invoke-unit/infer (export y-sig) (link u v)))
(test-runtime-error exn? "define-values/invoke-unit/infer: unbound variable: x"
(let ()
(define-values/invoke-unit/infer (export) (link u v))
x))
(test-syntax-error "define-values/invoke-unit/infer: doesn't export y"
(define-values/invoke-unit/infer (export y-sig) v))
(test-runtime-error exn? "define-values/invoke-unit/infer: unbound variable: x"
(let ()
(define-values/invoke-unit/infer (export) v)
x))
(let ()
(define-signature s^ (a))
(define-signature t^ (b))
(define-unit u@
(import s^)
(export t^)
(init-depend s^)
(define b a))
(define-unit v@
(import)
(export s^)
(define a 2))
(define-values/invoke-unit/infer (export) (link v@ u@))
(test-runtime-error exn? "define-values/invoke-unit/infer: init-depend broken"
(define-values/invoke-unit/infer (export) (link u@ v@))))
(define-unit u (import x-sig) (export) x)
(test-syntax-error "define-values/invoke-unit/infer: bad imports"
(define-values/invoke-unit/infer u))
(define-unit u (import x-sig y-sig) (export))
(test-syntax-error "define-values/invoke-unit/infer: bad imports"
(define-values/invoke-unit/infer u))
(define-unit u (import) (export x-sig y-sig)
(define x 10)
(define y 20))
(test 30
(let ()
(define-values/invoke-unit/infer u)
(+ y x)))
(test 1
(let ()
(define-unit x (import) (export) 1)
(invoke-unit x)))
(test 1
(let ()
(define-unit x (import) (export) 1)
(let ((u 1))
(invoke-unit x))))
(test 2
(let ()
(define-unit x (import) (export) 1)
(set! x (unit (import) (export) 2))
(invoke-unit x)))
(let ()
(define-signature s1 (a))
(define-signature s2 extends s1 (b))
(define-signature s3 (c))
(define-signature s4 extends s3 (d))
(define-unit u (import s2) (export s3) (define c (+ a b)))
(define-unit v (import) (export s2) (define a 1) (define b 3))
(set! u (unit (import s1) (export s4) (define c (add1 a)) (define d 12)))
(let ()
(define-values/invoke-unit (compound-unit/infer (import) (export s2 s3) (link v u))
(import) (export s2 s3))
(test '(1 3 2) (list a b c))))
(test-syntax-error "compound-unit/infer: missing export"
(compound-unit/infer (link) (import)))
(test-syntax-error "compound-unit/infer: bad unit"
(compound-unit/infer (import) (export) (link 1)))
(test-syntax-error "compound-unit/infer: bad import"
(compound-unit/infer (import (a : b)) (export) (link)))
(test-syntax-error "compound-unit/infer: bad link"
(compound-unit/infer (import) (export) (link (((A : b)) c))))
(test-syntax-error "compound-unit/infer: unknown sig"
(compound-unit/infer (import ??) (export) (link)))
(test-syntax-error "compound-unit/infer: unknown sig"
(compound-unit/infer (import) (export ??) (link)))
(test-syntax-error "compound-unit/infer: unknown sig"
(compound-unit/infer (import) (export) (link (() u ??))))
(define-unit x
(import x-sig)
(export y-sig)
(define y x)
y)
(define-unit y
(import y-sig)
(export (rename x-sig (x x)))
(define x y)
x)
(define-unit z
(import (prefix : x-sig) y-sig)
(export)
(+ :x y))
(define-unit a
(import)
(export x-sig y-sig z-sig)
(define x 1)
(define y 2)
(define z 3))
(define-unit b
(import x-sig y-sig z-sig)
(export)
(+ x y z))
(test-syntax-error "compound-unit/infer: re-export"
(compound-unit/infer (import (l : x-sig)) (export x-sig) (link)))
(test-syntax-error "compound-unit/infer: duplicate def and import"
(compound-unit/infer (import y-sig x-sig) (export) (link x y)))
(test-syntax-error "compound-unit/infer: unprovided sig"
(compound-unit/infer (import) (export) (link x)))
(test-syntax-error "compound-unit/infer: unprovided sig"
(compound-unit/infer (import) (export x-sig) (link)))
(test (letrec ((x x)) x)
(invoke-unit
(compound-unit/infer (import) (export)
(link x y))))
(test 3
(let ()
(define-signature s (x y))
(let ((x 1)
(y 2))
(define-unit-from-context u1 s)
(define-unit u2 (import (prefix : s)) (export)
(+ :x :y))
(invoke-unit
(compound-unit/infer (import) (export)
(link u1 u2))))))
(test 6
(invoke-unit
(compound-unit/infer (import) (export)
(link (((L1 : y-sig)) a)
x
(() b L1)))))
(let ()
(define-unit u1 (import (tag t x-sig)) (export)
(add1 x))
(define-unit u2 (import) (export x-sig)
(define x 2))
(test 3
(invoke-unit
(compound-unit/infer (import) (export)
(link u2 u1)))))
(let ()
(define-unit u1 (import x-sig) (export)
(add1 x))
(define-unit u2 (import) (export (tag u x-sig))
(define x 2))
(test 3
(invoke-unit
(compound-unit/infer (import) (export)
(link u2 u1)))))
(let ()
(define-unit x2 (import) (export x-sig) (define x 44))
(define-unit x3 (import) (export x-sig) (define x 4400))
(define-unit z (import x-sig) (export z-sig) (define z (+ 100 x)))
(define-compound-unit/infer u (import (L : x-sig)) (export L2 y-sig)
(link x3 (((L2 : z-sig)) z L) (() a L)))
(test 190
(invoke-unit
(compound-unit/infer (import) (export)
(link x2 u b)))))
(let ()
(define-unit u (import x-sig) (export))
(define-unit v (import) (export x-sub) (define x 12) (define xx 13))
(define-compound-unit/infer c (import) (export x-sig) (link v u))
(define-values/invoke-unit/infer c)
(test 12 x))
(let ()
(define-unit u (import) (export x-sig)
(define x 12))
(define-unit u2 (import) (export x-sig)
(define x 13))
(define-unit v (import) (export y-sig)
(define y 11))
(define-unit v2 (import) (export y-sig)
(define y 1))
(define-unit u3 (import y-sig x-sig) (export)
(+ y x))
(test 24
(invoke-unit
(compound-unit/infer (import) (export)
(link (((l : x-sig)) u)
(((l2 : x-sig)) u2)
(((l3 : y-sig)) v)
(((l4 : y-sig)) v2)
(() u3 l2 l3))))))
;; unit/new-import-export
(test-runtime-error exn:fail:contract? "unit/new-import-export: not a unit"
(unit/new-import-export (import) (export)
(() 1)))
(test-runtime-error exn:fail:contract? "unit/new-import-export: not a subtype"
(unit/new-import-export (import) (export)
((x-sig) (unit (import) (export)))))
(test-runtime-error exn:fail:contract? "unit/new-import-export: not a subtype"
(unit/new-import-export (import) (export)
(() (unit (import x-sig) (export)))))
(define-unit u (import x-sig) (export y-sig)
(define y x))
(test-syntax-error "unit/new-import-export: not enough imports"
(unit/new-import-export (import) (export x-sig)
((y-sig) u x-sig)))
(test-syntax-error "unit/new-import-export: too many exports"
(unit/new-import-export (import x-sig) (export y-sig z-sig)
((y-sig) u x-sig)))
(let ()
(define-unit u
(import xy-sig) (export z-sig)
(define z (+ x y)))
(define-unit v
(import) (export x-sig y-sig)
(define x 4)
(define y 8))
(define-unit w (import z-sig) (export)
z)
(define-unit/new-import-export u2 (import x-sig y-sig) (export z-sig)
((z-sig) u xy-sig))
(test 12
(invoke-unit (compound-unit/infer (import) (export)
(link v u2 w)))))
(let ()
(define-unit u
(import x-sig y-sig) (export z-sig)
(define z (+ x y)))
(define-unit v
(import) (export xy-sig)
(define x 4)
(define y 8))
(define-unit w (import z-sig) (export)
z)
(define-unit/new-import-export u2 (import xy-sig) (export z-sig)
((z-sig) u y-sig x-sig))
(test 12
(invoke-unit (compound-unit/infer (import) (export)
(link v u2 w)))))
(let ()
(define-unit u
(import xy-sig) (export z-sig)
(define z (+ x y)))
(define-unit v
(import) (export x-sig y-sig)
(define x 4)
(define y 8))
(define-unit w (import z-sig) (export)
z)
(define-unit/new-import-export v2 (import) (export xy-sig)
((x-sig y-sig) v))
(test 12
(invoke-unit (compound-unit/infer (import) (export)
(link v2 u w)))))
(let ()
(define-unit u
(import x-sig y-sig) (export z-sig)
(define z (+ x y)))
(define-unit v
(import) (export xy-sig)
(define x 4)
(define y 8))
(define-unit w (import z-sig) (export)
z)
(define-unit/new-import-export v2 (import) (export y-sig x-sig)
((xy-sig) v))
(test 12
(invoke-unit (compound-unit/infer (import) (export)
(link v2 u w)))))
;; open
(let ()
(define-signature xzy
((open x-sig) (open y-sig) (open z-sig)))
(define-unit u (import xzy) (export)
(+ x z y))
(define-unit v (import) (export xzy)
(define x 10)
(define y 20)
(define z 30))
(test 60
(invoke-unit (compound-unit/infer (import) (export) (link v u)))))
(let ([x 1]
[y 2]
[z 3])
(define-signature xzy
((open x-sig) (open y-sig) (open z-sig)))
(define-unit u (import xzy) (export)
(+ x z y))
(define-unit v (import) (export xzy)
(define x 10)
(define y 20)
(define z 30))
(test 60
(invoke-unit (compound-unit/infer (import) (export) (link v u)))))
(define-signature s
(x (define-values (y) (add1 x))))
(let ([x 1]
[y 10]
[s:x 100]
[s:y 1000])
(define-signature s2
((open (prefix s: s)) x (define-values (y) (sub1 x))))
(define-unit u1 (import s2) (export)
(list s:x s:y x y))
(define-unit u2 (import) (export s2)
(define s:x 3)
(define x 19))
(test '(3 4 19 18)
(invoke-unit (compound-unit/infer (import) (export) (link u2 u1)))))
(define-signature sig^ (u-a))
(define-unit unit@
(import)
(export sig^)
(define u-a 'zero))
(test 'zero
(let ([q:u-a 5])
(define-values/invoke-unit unit@ (import) (export (prefix q: sig^)))
q:u-a))
(define-syntax (use-unit stx)
(syntax-case stx ()
[(_)
#'(let ()
(define-values/invoke-unit unit@ (import) (export sig^))
u-a)]))
(define-syntax (use-unit2 stx)
(syntax-case stx ()
[(_)
#'(let ()
(define-values/invoke-unit/infer unit@)
u-a)]))
(define-syntax (use-unit-badly1 stx)
(syntax-case stx ()
[(_ u-a)
#'(let ()
(define-values/invoke-unit unit@ (import) (export sig^))
u-a)]))
(define-syntax (use-unit-badly2 stx)
(syntax-case stx ()
[(_ sig^)
#'(let ()
(define-values/invoke-unit unit@ (import) (export sig^))
u-a)]))
(test 'zero (use-unit))
(test 'zero (use-unit2))
(test-runtime-error exn:fail:contract:variable? "context mismatch; no u-a"
(use-unit-badly1 u-a))
(test-runtime-error exn:fail:contract:variable? "context mismatch; no u-a"
(use-unit-badly2 sig^))
(test 12
(let ()
(define-signature s^ (x))
(define-unit u@
(import)
(export s^)
(define x 12))
(define-values/invoke-unit u@ (import) (export s^))
x))