www

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

commit 3c769179eb62be822ff55c1a1475736803d7727e
parent a71ee3e46a55bb98c2ea76c88e2617ee38d1dfc6
Author: AlexKnauth <alexander@knauth.org>
Date:   Mon, 20 Jun 2016 15:21:29 -0400

implement sub and reco+sub with typed-lang-builder

Diffstat:
Mtapl/tests/stlc+reco+sub-tests.rkt | 2+-
Mtapl/tests/stlc+sub-tests.rkt | 2+-
Atapl/typed-lang-builder/stlc+reco+sub.rkt | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Atapl/typed-lang-builder/stlc+sub.rkt | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 161 insertions(+), 2 deletions(-)

diff --git a/tapl/tests/stlc+reco+sub-tests.rkt b/tapl/tests/stlc+reco+sub-tests.rkt @@ -1,4 +1,4 @@ -#lang s-exp "../stlc+reco+sub.rkt" +#lang s-exp "../typed-lang-builder/stlc+reco+sub.rkt" (require "rackunit-typechecking.rkt") ;; record subtyping tests diff --git a/tapl/tests/stlc+sub-tests.rkt b/tapl/tests/stlc+sub-tests.rkt @@ -1,4 +1,4 @@ -#lang s-exp "../stlc+sub.rkt" +#lang s-exp "../typed-lang-builder/stlc+sub.rkt" (require "rackunit-typechecking.rkt") ;; subtyping tests diff --git a/tapl/typed-lang-builder/stlc+reco+sub.rkt b/tapl/typed-lang-builder/stlc+reco+sub.rkt @@ -0,0 +1,52 @@ +#lang macrotypes/tapl/typed-lang-builder +(extends "stlc+sub.rkt" #:except #%app #%datum) +(extends "stlc+reco+var.rkt" #:except #%datum +) +;;use type=? and eval-type from stlc+reco+var.rkt, not stlc+sub.rkt +;; but extend sub? from stlc+sub.rkt + +;; Simply-Typed Lambda Calculus, plus subtyping, plus records +;; Types: +;; - types from stlc+sub.rkt +;; Type relations: +;; - sub? extended to records +;; Terms: +;; - terms from stlc+sub.rkt +;; - records and variants from stlc+reco+var + +(define-typed-syntax #%datum + [(#%datum . n:number) ▶ + -------- + [_ ≻ (stlc+sub:#%datum . n)]] + [(#%datum . x) ▶ + -------- + [_ ≻ (stlc+reco+var:#%datum . x)]]) + +(begin-for-syntax + (define old-sub? (current-sub?)) + (define (sub? τ1 τ2) +; (printf "t1 = ~a\n" (syntax->datum τ1)) +; (printf "t2 = ~a\n" (syntax->datum τ2)) + (or + (old-sub? τ1 τ2) + (syntax-parse (list τ1 τ2) + [((~× [k : τk] ...) (~× [l : τl] ...)) + #:when (subset? (stx-map syntax-e (syntax->list #'(l ...))) + (stx-map syntax-e (syntax->list #'(k ...)))) + (stx-andmap + (syntax-parser + [(label τlabel) + #:with (k_match τk_match) (stx-assoc #'label #'([k τk] ...)) + ((current-sub?) #'τk_match #'τlabel)]) + #'([l τl] ...))] + [((~∨ [k : τk] ...) (~∨ [l : τl] ...)) + #:when (subset? (stx-map syntax-e (syntax->list #'(l ...))) + (stx-map syntax-e (syntax->list #'(k ...)))) + (stx-andmap + (syntax-parser + [(label τlabel) + #:with (k_match τk_match) (stx-assoc #'label #'([k τk] ...)) + ((current-sub?) #'τk_match #'τlabel)]) + #'([l τl] ...))] + [_ #f]))) + (current-sub? sub?) + (current-typecheck-relation (current-sub?))) diff --git a/tapl/typed-lang-builder/stlc+sub.rkt b/tapl/typed-lang-builder/stlc+sub.rkt @@ -0,0 +1,107 @@ +#lang macrotypes/tapl/typed-lang-builder +(extends "stlc+lit.rkt" #:except #%datum +) +(reuse Bool String add1 #:from "ext-stlc.rkt") +(require (prefix-in ext: (only-in "ext-stlc.rkt" #%datum)) + (only-in "ext-stlc.rkt" current-join)) +(provide (for-syntax subs? current-sub?)) + +;; Simply-Typed Lambda Calculus, plus subtyping +;; Types: +;; - types from and stlc+lit.rkt +;; - Top, Num, Nat +;; Type relations: +;; - sub? +;; - Any <: Top +;; - Nat <: Int +;; - Int <: Num +;; - → +;; Terms: +;; - terms from stlc+lit.rkt, except redefined: datum and + +;; - also * +;; Other: sub? current-sub? + +(define-base-type Top) +(define-base-type Num) +(define-base-type Nat) + +(define-primop + : (→ Num Num Num)) +(define-primop * : (→ Num Num Num)) + +(define-typed-syntax #%datum + [(#%datum . n:nat) ▶ + -------- + [⊢ [[_ ≫ (#%datum- . n)] ⇒ (: Nat)]]] + [(#%datum . n:integer) ▶ + -------- + [⊢ [[_ ≫ (#%datum- . n)] ⇒ (: Int)]]] + [(#%datum . n:number) ▶ + -------- + [⊢ [[_ ≫ (#%datum- . n)] ⇒ (: Num)]]] + [(#%datum . x) ▶ + -------- + [_ ≻ (ext:#%datum . x)]]) + +(begin-for-syntax + (define (sub? t1 t2) + ; need this because recursive calls made with unexpanded types + (define τ1 ((current-type-eval) t1)) + (define τ2 ((current-type-eval) t2)) +; (printf "t1 = ~a\n" (syntax->datum τ1)) +; (printf "t2 = ~a\n" (syntax->datum τ2)) + (or ((current-type=?) τ1 τ2) + (Top? τ2))) + (define current-sub? (make-parameter sub?)) + (current-typecheck-relation sub?) + (define (subs? τs1 τs2) + (and (stx-length=? τs1 τs2) + (stx-andmap (current-sub?) τs1 τs2))) + + (define-syntax (define-sub-relation stx) + (syntax-parse stx #:datum-literals (<: =>) + [(_ τ1:id <: τ2:id) + #:with τ1-expander (format-id #'τ1 "~~~a" #'τ1) + #:with τ2-expander (format-id #'τ2 "~~~a" #'τ2) + #:with fn (generate-temporary) + #:with old-sub? (generate-temporary) + #'(begin + (define old-sub? (current-sub?)) + (define (fn t1 t2) + (define τ1 ((current-type-eval) t1)) + (define τ2 ((current-type-eval) t2)) + (syntax-parse (list τ1 τ2) + [(τ1-expander τ) ((current-sub?) #'τ2 #'τ)] + [(τ τ2-expander) ((current-sub?) #'τ #'τ1)] + [_ #f])) + (current-sub? (λ (t1 t2) (or (old-sub? t1 t2) (fn t1 t2)))) + (current-typecheck-relation (current-sub?)))] + [(_ (~seq τ1:id <: τ2:id (~and (~literal ...) ddd)) + (~seq τ3:id <: τ4:id) + => + (tycon1 . rst1) <: (tycon2 . rst2)) + #:with tycon1-expander (format-id #'tycon1 "~~~a" #'tycon1) + #:with tycon2-expander (format-id #'tycon2 "~~~a" #'tycon2) + #:with fn (generate-temporary) + #:with old-sub? (generate-temporary) + #'(begin + (define old-sub? (current-sub?)) + (define (fn t1 t2) + (define τ1 ((current-type-eval) t1)) + (define τ2 ((current-type-eval) t2)) + (syntax-parse (list τ1 τ2) + [((tycon1-expander . rst1) (tycon2-expander . rst2)) + (and (subs? #'(τ1 ddd) #'(τ2 ddd)) + ((current-sub?) #'τ3 #'τ4))] + [_ #f])) + (current-sub? (λ (t1 t2) (or (old-sub? t1 t2) (fn t1 t2)))) + (current-typecheck-relation (current-sub?)))])) + + (define-sub-relation Nat <: Int) + (define-sub-relation Int <: Num) + (define-sub-relation t1 <: s1 ... s2 <: t2 => (→ s1 ... s2) <: (→ t1 ... t2)) + + (define (join t1 t2) + (cond + [((current-sub?) t1 t2) t2] + [((current-sub?) t2 t1) t1] + [else #'Top])) + (current-join join))