www

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

commit 35c7900463b28c093b06c9ec73a1193c31c1242a
parent 3c769179eb62be822ff55c1a1475736803d7727e
Author: AlexKnauth <alexander@knauth.org>
Date:   Mon, 20 Jun 2016 15:25:13 -0400

implement sysf and fsub with typed-lang-builder

Diffstat:
Mtapl/tests/fsub-tests.rkt | 2+-
Mtapl/tests/sysf-tests.rkt | 4++--
Atapl/typed-lang-builder/fsub.rkt | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atapl/typed-lang-builder/sysf.rkt | 32++++++++++++++++++++++++++++++++
4 files changed, 127 insertions(+), 3 deletions(-)

diff --git a/tapl/tests/fsub-tests.rkt b/tapl/tests/fsub-tests.rkt @@ -1,4 +1,4 @@ -#lang s-exp "../fsub.rkt" +#lang s-exp "../typed-lang-builder/fsub.rkt" (require "rackunit-typechecking.rkt") ;; examples from tapl ch26, bounded quantification diff --git a/tapl/tests/sysf-tests.rkt b/tapl/tests/sysf-tests.rkt @@ -1,4 +1,4 @@ -#lang s-exp "../sysf.rkt" +#lang s-exp "../typed-lang-builder/sysf.rkt" (require "rackunit-typechecking.rkt") (check-type (Λ (X) (λ ([x : X]) x)) : (∀ (X) (→ X X))) @@ -27,7 +27,7 @@ (typecheck-fail (inst 1 Int) #:with-msg - "Expected expression 1 to have ∀ type, got: Int") + "Expected ∀ type, got: Int") ;; polymorphic arguments (check-type (Λ (t) (λ ([x : t]) x)) : (∀ (t) (→ t t))) diff --git a/tapl/typed-lang-builder/fsub.rkt b/tapl/typed-lang-builder/fsub.rkt @@ -0,0 +1,92 @@ +#lang macrotypes/tapl/typed-lang-builder +(extends "stlc+reco+sub.rkt" #:except +) +(require (rename-in (only-in "sysf.rkt" ∀? ∀ ~∀) [~∀ ~sysf:∀] [∀ sysf:∀])) + +;; System F<: +;; Types: +;; - types from sysf.rkt and stlc+reco+sub +;; - extend ∀ with bounds +;; Terms: +;; - terms from sysf.rkt and stlc+reco+sub +;; - extend Λ and inst +;; - redefine + with Nat +;; Other +;; - current-promote, expose +;; - extend current-sub? to call current-promote + +(define-primop + : (→ Nat Nat Nat)) + +; can't just call expose in type-eval, +; otherwise typevars will have bound as type, rather than instantiated type +; only need expose during +; 1) subtype checking +; 2) pattern matching -- including base types +(begin-for-syntax + (define (expose t) + (cond [(identifier? t) + (define sub (typeof t #:tag '<:)) + (if sub (expose sub) t)] + [else t])) + (current-promote expose) + (define stlc:sub? (current-sub?)) + (define (sub? t1 t2) + (stlc:sub? ((current-promote) t1) t2)) + (current-sub? sub?) + (current-typecheck-relation (current-sub?))) + +; quasi-kind, but must be type constructor because its arguments are types +(define-type-constructor <: #:arity >= 0) +(begin-for-syntax + (current-type? (λ (t) (or (type? t) (<:? (typeof t)))))) + +;; Type annotations used in two places: +;; 1) typechecking the body of +;; 2) instantiation of ∀ +;; Problem: need type annotations, even in expanded form +;; Solution: store type annotations in a (quasi) kind <: +(define-typed-syntax ∀ #:datum-literals (<:) + [(∀ ([tv:id <: τ:type] ...) τ_body) ▶ + -------- + ; eval first to overwrite the old #%type + [⊢ [[_ ≫ #,((current-type-eval) #'(sysf:∀ (tv ...) τ_body))] ⇒ (: (<: τ.norm ...))]]]) +(begin-for-syntax + (define-syntax ~∀ + (pattern-expander + (syntax-parser #:datum-literals (<:) #:literals (...) + [(_ ([tv:id <: τ_sub] ooo:...) τ) + #'(~and ∀τ + (~parse (~sysf:∀ (tv ooo) τ) #'∀τ) + (~parse (~<: τ_sub ooo) (typeof #'∀τ)))] + [(_ . args) + #'(~and ∀τ + (~parse (~sysf:∀ (tv (... ...)) τ) #'∀τ) + (~parse (~<: τ_sub (... ...)) (typeof #'∀τ)) + (~parse args #'(([tv τ_sub] (... ...)) τ)))]))) + (define-syntax ~∀* + (pattern-expander + (syntax-parser #:datum-literals (<:) + [(_ . args) + #'(~or + (~∀ . args) + (~and any (~do + (type-error + #:src #'any + #:msg "Expected ∀ type, got: ~a" #'any))))])))) + +(define-typed-syntax Λ #:datum-literals (<:) + [(Λ ([tv:id <: τsub:type] ...) e) ▶ + ;; NOTE: store the subtyping relation of tv and τsub in the + ;; environment with a syntax property using another tag: '<: + ;; The "expose" function looks for this tag to enforce the bound, + ;; as in TaPL (fig 28-1) + [([tv : #%type <: τsub ≫ tv-] ...) () ⊢ [[e ≫ e-] ⇒ (: τ_e)]] + -------- + [⊢ [[_ ≫ e-] ⇒ (: (∀ ([tv- <: τsub] ...) τ_e))]]]) +(define-typed-syntax inst + [(inst e τ:type ...) ▶ + [⊢ [[e ≫ e-] ⇒ (: (~∀ ([tv <: τ_sub] ...) τ_body))]] + [τ.norm τ⊑ τ_sub] ... + [#:with τ_inst (substs #'(τ.norm ...) #'(tv ...) #'τ_body)] + -------- + [⊢ [[_ ≫ e-] ⇒ (: τ_inst)]]]) + diff --git a/tapl/typed-lang-builder/sysf.rkt b/tapl/typed-lang-builder/sysf.rkt @@ -0,0 +1,32 @@ +#lang macrotypes/tapl/typed-lang-builder +(extends "stlc+lit.rkt") +(reuse #:from "stlc+rec-iso.rkt") ; want this type=? + +;; System F +;; Type relation: +;; - extend type=? with ∀ +;; Types: +;; - types from stlc+lit.rkt +;; - ∀ +;; Terms: +;; - terms from stlc+lit.rkt +;; - Λ and inst + +(define-type-constructor ∀ #:bvs >= 0) + +(define-typed-syntax Λ + [(Λ (tv:id ...) e) ▶ + [([tv : #%type ≫ tv-] ...) () ⊢ [[e ≫ e-] ⇒ (: τ)]] + -------- + [⊢ [[_ ≫ e-] ⇒ (: (∀ (tv- ...) τ))]]]) + +(define-typed-syntax inst + [(inst e τ:type ...) ▶ + [⊢ [[e ≫ e-] ⇒ (: (~∀ tvs τ_body))]] + [#:with τ_inst (substs #'(τ.norm ...) #'tvs #'τ_body)] + -------- + [⊢ [[_ ≫ e-] ⇒ (: τ_inst)]]] + [(inst e) ▶ + -------- + [_ ≻ e]]) +