www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 50540efaa52407a2828704f5c961e814bec4108d
parent bec3be8b22bfe3982a64a1c19f68c847f9b6ccb1
Author: Stephen Chang <stchang@ccs.neu.edu>
Date:   Thu,  4 Jun 2015 15:22:39 -0400

add current-typecheck-relation - generalizes equality and subtype

Diffstat:
Mtapl/ext-stlc.rkt | 6+++---
Mtapl/stlc+box.rkt | 8++++----
Mtapl/stlc+cons.rkt | 8++++----
Mtapl/stlc+lit.rkt | 2+-
Mtapl/stlc+rec+sub.rkt | 12+++++++-----
Mtapl/stlc+sub.rkt | 15++++++++-------
Mtapl/stlc+tup.rkt | 2+-
Mtapl/stlc+var.rkt | 9+++++----
Mtapl/stlc.rkt | 9+++++----
Mtapl/sysf.rkt | 3++-
Mtapl/tests/rackunit-typechecking.rkt | 10+++++-----
Mtapl/typecheck.rkt | 17+++++++++++------
12 files changed, 56 insertions(+), 45 deletions(-)

diff --git a/tapl/ext-stlc.rkt b/tapl/ext-stlc.rkt @@ -1,6 +1,6 @@ #lang racket/base (require - (for-syntax racket/base syntax/parse syntax/stx racket/string "stx-utils.rkt") + #;(for-syntax racket/base syntax/parse syntax/stx racket/string "stx-utils.rkt") "typecheck.rkt") (require (prefix-in stlc: (only-in "stlc+lit.rkt" #%app #%datum)) (except-in "stlc+lit.rkt" #%app #%datum)) @@ -94,7 +94,7 @@ (syntax-parse stx #:datum-literals (:) [(_ e : ascribed-τ) #:with (e- τ) (infer+erase #'e) - #:fail-unless ((current-type=?) #'τ #'ascribed-τ) + #:fail-unless (typecheck? #'τ #'ascribed-τ) (format "~a does not have type ~a\n" (syntax->datum #'e) (syntax->datum #'ascribed-τ)) (⊢ #'e- #'ascribed-τ)])) @@ -117,7 +117,7 @@ [(_ ([b:typed-binding e] ...) e_body) #:with ((x- ...) (e- ... e_body-) (τ ... τ_body)) (infers/type-ctxt+erase #'(b ...) #'(e ... e_body)) - #:fail-unless (types=? #'(b.τ ...) #'(τ ...)) + #:fail-unless (typechecks? #'(b.τ ...) #'(τ ...)) (string-append "letrec: type check fail, args have wrong type:\n" (string-join diff --git a/tapl/stlc+box.rkt b/tapl/stlc+box.rkt @@ -1,13 +1,13 @@ #lang racket/base (require - (for-syntax racket/base syntax/parse syntax/stx racket/syntax racket/string + #;(for-syntax racket/base syntax/parse syntax/stx racket/syntax racket/string "stx-utils.rkt" "typecheck.rkt") - (for-meta 2 racket/base syntax/parse racket/syntax) + #;(for-meta 2 racket/base syntax/parse racket/syntax) "typecheck.rkt") (require (prefix-in stlc: (only-in "stlc+cons.rkt" #%app λ)) (except-in "stlc+cons.rkt" #%app λ)) (provide (rename-out [stlc:#%app #%app] [stlc:λ λ])) -(provide (all-from-out "stlc+cons.rkt")) +(provide (except-out (all-from-out "stlc+cons.rkt") stlc:#%app stlc:λ)) (provide ref deref :=) ;; Simply-Typed Lambda Calculus, plus mutable references @@ -34,5 +34,5 @@ [(_ e_ref e) #:with (e_ref- ((~literal Ref) τ1)) (infer+erase #'e_ref) #:with (e- τ2) (infer+erase #'e) - #:when (type=? #'τ1 #'τ2) + #:when (typecheck? #'τ1 #'τ2) (⊢ #'(set-box! e_ref- e-) #'Unit)])) \ No newline at end of file diff --git a/tapl/stlc+cons.rkt b/tapl/stlc+cons.rkt @@ -1,14 +1,14 @@ #lang racket/base (require - (for-syntax racket/base syntax/parse syntax/stx racket/syntax racket/string + #;(for-syntax racket/base syntax/parse syntax/stx racket/syntax racket/string "stx-utils.rkt" "typecheck.rkt") - (for-meta 2 racket/base syntax/parse racket/syntax) + #;(for-meta 2 racket/base syntax/parse racket/syntax) "typecheck.rkt") (require (prefix-in stlc: (only-in "stlc+var.rkt" #%app λ let begin)) (except-in "stlc+var.rkt" #%app λ let begin)) (provide (rename-out [stlc:#%app #%app] [stlc:λ λ] [stlc:let let] [stlc:begin begin] [cons/tc cons] [define/tc define])) -(provide (all-from-out "stlc+var.rkt")) +(provide (except-out (all-from-out "stlc+var.rkt") stlc:#%app stlc:λ stlc:let stlc:begin)) (provide nil isnil head tail) ;; Simply-Typed Lambda Calculus, plus cons @@ -45,7 +45,7 @@ [(_ e1 e2) #:with (e1- τ1) (infer+erase #'e1) #:with (e2- ((~literal List) τ2)) (infer+erase #'e2) - #:when ((current-type=?) #'τ1 #'τ2) + #:when (typecheck? #'τ1 #'τ2) (⊢ #'(cons e1- e2-) #'(List τ1))])) (define-syntax (isnil stx) (syntax-parse stx diff --git a/tapl/stlc+lit.rkt b/tapl/stlc+lit.rkt @@ -1,6 +1,6 @@ #lang racket/base (require - (for-syntax racket/base syntax/parse) + #;(for-syntax racket/base syntax/parse) "typecheck.rkt") (require "stlc.rkt") (provide (all-from-out "stlc.rkt")) diff --git a/tapl/stlc+rec+sub.rkt b/tapl/stlc+rec+sub.rkt @@ -1,16 +1,17 @@ #lang racket/base (require - (for-syntax racket/base syntax/parse racket/string syntax/stx racket/set "stx-utils.rkt") + #;(for-syntax racket/base syntax/parse racket/string syntax/stx racket/set "stx-utils.rkt") "typecheck.rkt") +;; want to use type=? from stlc+var.rkt (require (except-in "stlc+sub.rkt" #%app #%datum sub? type=?) (prefix-in stlc: (only-in "stlc+sub.rkt" #%app #%datum sub?)) (except-in "stlc+var.rkt" #%app #%datum +) - (prefix-in var: (only-in "stlc+var.rkt" #%datum type=?))) + (prefix-in var: (only-in "stlc+var.rkt" #%datum))) (provide (rename-out [stlc:#%app #%app] [datum/tc #%datum])) (provide (except-out (all-from-out "stlc+sub.rkt") stlc:#%app stlc:#%datum (for-syntax stlc:sub?)) - (except-out (all-from-out "stlc+var.rkt") var:#%datum (for-syntax var:type=?))) + (except-out (all-from-out "stlc+var.rkt") var:#%datum)) (provide (for-syntax sub?)) ;; Simply-Typed Lambda Calculus, plus subtyping, plus records @@ -49,4 +50,5 @@ #'([l τl] ...))] [_ #f]) (stlc:sub? τ1 τ2))) - (current-sub? sub?)) -\ No newline at end of file + (current-sub? sub?) + (current-typecheck-relation (current-sub?))) +\ No newline at end of file diff --git a/tapl/stlc+sub.rkt b/tapl/stlc+sub.rkt @@ -1,12 +1,12 @@ #lang racket/base (require - (for-syntax racket/base syntax/parse racket/string "stx-utils.rkt") + #;(for-syntax racket/base syntax/parse racket/string "stx-utils.rkt") "typecheck.rkt") (require (except-in "stlc+lit.rkt" #%datum + #%app) - (prefix-in stlc: (only-in "stlc+lit.rkt" #%datum))) -(provide (rename-out [app/tc #%app] [datum/tc #%datum])) -(provide (except-out (all-from-out "stlc+lit.rkt") stlc:#%datum)) -(provide (for-syntax sub? subs?)) + (prefix-in stlc: (only-in "stlc+lit.rkt" #%app #%datum))) +(provide (rename-out #;[app/tc #%app] [stlc:#%app #%app] [datum/tc #%datum])) +(provide (except-out (all-from-out "stlc+lit.rkt") stlc:#%app stlc:#%datum)) +(provide (for-syntax sub? subs? current-sub?)) ;; Simply-Typed Lambda Calculus, plus subtyping ;; Types: @@ -53,7 +53,8 @@ (and (subs? #'(t1 ...) #'(s1 ...)) ((current-sub?) #'s2 #'t2))] [_ #f]))) - (current-sub? sub?) + (define current-sub? (make-parameter sub?)) + (current-typecheck-relation (current-sub?)) (define (subs? τs1 τs2) (stx-andmap (current-sub?) τs1 τs2))) #;(define-syntax (app/tc stx) @@ -64,7 +65,7 @@ (local-expand #'(stlc:#%app x ...) 'expression null)) #'res])) -(define-syntax (app/tc stx) +#;(define-syntax (app/tc stx) (syntax-parse stx #:literals (→) [(_ e_fn e_arg ...) #:with (e_fn- τ_fn) (infer+erase #'e_fn) diff --git a/tapl/stlc+tup.rkt b/tapl/stlc+tup.rkt @@ -1,6 +1,6 @@ #lang racket/base (require - (for-syntax racket/base syntax/parse syntax/stx racket/string "stx-utils.rkt") + #;(for-syntax racket/base syntax/parse syntax/stx racket/string "stx-utils.rkt") "typecheck.rkt") (require (prefix-in stlc: (only-in "ext-stlc.rkt" #%app)) (except-in "ext-stlc.rkt" #%app)) diff --git a/tapl/stlc+var.rkt b/tapl/stlc+var.rkt @@ -1,8 +1,8 @@ #lang racket/base (require - (for-syntax racket/base syntax/parse syntax/stx racket/syntax racket/string + #;(for-syntax racket/base syntax/parse syntax/stx racket/syntax racket/string "stx-utils.rkt" "typecheck.rkt") - (for-meta 2 racket/base syntax/parse racket/syntax) + #;(for-meta 2 racket/base syntax/parse racket/syntax) "typecheck.rkt") (require (prefix-in stlc: (only-in "stlc+tup.rkt" #%app λ tup proj let type=?)) (except-in "stlc+tup.rkt" #%app λ tup proj let type=?)) @@ -41,6 +41,7 @@ #;[_ #f])) (current-type=? type=?) + (current-typecheck-relation (current-type=?)) ;; redefine these to use the new type=? ;; type equality = structurally recursive identifier equality @@ -97,7 +98,7 @@ #:with (∨ (l_τ τ_l) ...) #'τ+ #:with (l_match τ_match) (str-stx-assoc #'l #'((l_τ τ_l) ...)) #:with (e- τ_e) (infer+erase #'e) - #:when ((current-type=?) #'τ_match #'τ_e) + #:when (typecheck? #'τ_match #'τ_e) (⊢ #'(list l e) #'τ+)])) (define-syntax (case stx) (syntax-parse stx #:datum-literals (of =>) @@ -108,7 +109,7 @@ #:fail-when (null? (syntax->list #'(l ...))) "no clauses" #:fail-unless (= (stx-length #'(l ...)) (stx-length #'(l_x ...))) "wrong number of case clauses" ; #:fail-unless (stx-andmap stx-str=? #'(l ...) #'(l_x ...)) "case clauses not exhaustive" - #:fail-unless (types=? #'(l ...) #'(l_x ...)) "case clauses not exhaustive" + #:fail-unless (typechecks? #'(l ...) #'(l_x ...)) "case clauses not exhaustive" #:with (((x-) e_l- τ_el) ...) (stx-map (λ (bs e) (infer/type-ctxt+erase bs e)) #'(([x : τ_x]) ...) #'(e_l ...)) #:fail-unless (same-types? #'(τ_el ...)) "branches have different types" diff --git a/tapl/stlc.rkt b/tapl/stlc.rkt @@ -1,9 +1,9 @@ #lang racket/base (require - (for-syntax racket/base syntax/parse syntax/stx racket/string "stx-utils.rkt") + #;(for-syntax racket/base syntax/parse syntax/stx racket/string "stx-utils.rkt") "typecheck.rkt") (provide (rename-out [λ/tc λ] [app/tc #%app])) -(provide (for-syntax type=? types=? same-types?)) +(provide (for-syntax type=? types=? same-types? current-type=?)) (provide #%module-begin #%top-interaction #%top require) ; from racket ;; Simply-Typed Lambda Calculus @@ -28,7 +28,8 @@ [((τa ...) (τb ...)) (types=? #'(τa ...) #'(τb ...))] [_ #f])) - (current-type=? type=?) + (define current-type=? (make-parameter type=?)) + (current-typecheck-relation (current-type=?)) ;; type equality = structurally recursive identifier equality ;; uses the type=? in the context of τs1 instead of here @@ -57,7 +58,7 @@ #:with (→ τ ... τ_res) #'τ_fn #:with ((e_arg- τ_arg) ...) (infers+erase #'(e_arg ...)) ; #:fail-unless ((eval-syntax (datum->syntax #'e_fn 'types=?)) #'(τ ...) #'(τ_arg ...)) - #:fail-unless (types=? #'(τ_arg ...) #'(τ ...)) + #:fail-unless (typechecks? #'(τ_arg ...) #'(τ ...)) (string-append (format "Wrong number of args given to function ~a, or args have wrong type:\ngiven: " diff --git a/tapl/sysf.rkt b/tapl/sysf.rkt @@ -1,6 +1,6 @@ #lang racket/base (require - (for-syntax racket/base syntax/parse "stx-utils.rkt") + #;(for-syntax racket/base syntax/parse "stx-utils.rkt") "typecheck.rkt") (require (except-in "stlc+lit.rkt" #%app type=?) (prefix-in stlc: (only-in "stlc+lit.rkt" #%app type=?))) @@ -36,6 +36,7 @@ (substs #'(z ...) #'(y ...) #'t2))] [_ (stlc:type=? τ1 τ2)])) (current-type=? type=?) + (current-typecheck-relation (current-type=?)) ; [(s1:str s2:str) (string=? (syntax-e #'s1) (syntax-e #'s2))] ; [(x:id y:id) (free-identifier=? τ1 τ2)] ; [((τa ...) (τb ...)) (types=? #'(τa ...) #'(τb ...))] diff --git a/tapl/tests/rackunit-typechecking.rkt b/tapl/tests/rackunit-typechecking.rkt @@ -1,10 +1,10 @@ #lang racket/base -(require (for-syntax racket/base syntax/parse syntax/srcloc rackunit) - rackunit +(require #;(for-syntax racket/base syntax/parse syntax/srcloc rackunit) + (for-syntax rackunit) rackunit "../typecheck.rkt") (provide (all-defined-out)) -(define-for-syntax (type=? t1 t2) +#;(define-for-syntax (type=? t1 t2) (if (current-sub?) ((current-sub?) t1 t2) ((current-type=?) t1 t2))) @@ -19,7 +19,7 @@ ;; use subtyping if it's bound in the context of #'e #;(with-handlers ([exn:fail? (λ _ ((eval-syntax (datum->syntax #'e 'type=?)) #'τ #'τ-expected+))]) ((eval-syntax (datum->syntax #'e 'sub?)) #'τ #'τ-expected+)) - (type=? #'τ #'τ-expected+) + (typecheck? #'τ #'τ-expected+) (format "Expression ~a [loc ~a:~a] has type ~a, expected ~a" (syntax->datum #'e) (syntax-line #'e) (syntax-column #'e) @@ -34,7 +34,7 @@ #:fail-when #;(with-handlers ([exn:fail? (λ _ ((eval-syntax (datum->syntax #'e 'type=?)) #'τ #'not-τ+))]) ((eval-syntax (datum->syntax #'e 'sub?)) #'τ #'not-τ+)) - (type=? #'τ #'not-τ+) + (typecheck? #'τ #'not-τ+) (format "(~a:~a) Expression ~a should not have type ~a" (syntax-line stx) (syntax-column stx) diff --git a/tapl/typecheck.rkt b/tapl/typecheck.rkt @@ -1,10 +1,11 @@ #lang racket/base (require - (for-syntax racket/base syntax/parse racket/list racket/syntax syntax/stx "stx-utils.rkt") - (for-meta 2 racket/base syntax/parse racket/list syntax/stx "stx-utils.rkt")) + (for-syntax racket syntax/parse racket/syntax syntax/stx "stx-utils.rkt") + #;(for-meta 2 racket/base syntax/parse racket/list syntax/stx "stx-utils.rkt")) (provide (for-syntax (all-defined-out)) - (all-defined-out)) + (all-defined-out) + (for-syntax (all-from-out racket syntax/parse racket/syntax syntax/stx "stx-utils.rkt"))) ;; type checking functions/forms @@ -29,7 +30,7 @@ #'(begin (provide τ (for-syntax τ?)) (define τ (void)) - (define-for-syntax (τ? τ1) (free-identifier=? #'τ τ1)))])) + (define-for-syntax (τ? τ1) (typecheck? τ1 #'τ)))])) (define-syntax (define-type-constructor stx) (syntax-parse stx @@ -108,8 +109,12 @@ (syntax-parse (expand/df #`(λ #,tvs (#%expression #,e))) #:literals (#%expression) [(lam tvs+ (#%expression e+)) (list #'tvs+ #'e+ (typeof #'e+))])) - (define current-type=? (make-parameter #f)) - (define current-sub? (make-parameter #f)) + (define current-typecheck-relation (make-parameter #f)) + (define (typecheck? t1 t2) ((current-typecheck-relation) t1 t2)) + (define (typechecks? τs1 τs2) + (stx-andmap (current-typecheck-relation) τs1 τs2)) + ; (define current-type=? (make-parameter #f)) + ; (define current-sub? (make-parameter #f)) ; ;; type equality = structurally recursive identifier equality ; (define (types=? τs1 τs2)