add stlc+tup

This commit is contained in:
Stephen Chang 2015-05-20 19:27:19 -04:00
parent c4813ebd95
commit bb7ed03f3c
8 changed files with 267 additions and 6 deletions

View File

@ -21,11 +21,12 @@
;; Terms:
;; - terms from stlc+lit.rkt
;; - literals: bool, string
;; - prims: and, or, not, zero?
;; - boolean prims, numeric prims
;; - if
;; - prim void : (→ Unit)
;; - begin
;; - ascription (ann)
;; - let
;; - let, let*, letrec
(define-base-type Bool)
(define-base-type String)

29
tapl/stlc+tup.rkt Normal file
View File

@ -0,0 +1,29 @@
#lang racket/base
(require
(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 λ))
(provide (rename-out [stlc:#%app #%app] [stlc:λ λ])
tup proj)
(provide (all-from-out "ext-stlc.rkt"))
;; Simply-Typed Lambda Calculus, plus tuples
;; Types:
;; - types from ext-stlc.rkt
;; Terms:
;; - terms from ext-stlc.rkt
(define-syntax (tup stx)
(syntax-parse stx
[(_ e ...)
#:with ((e- τ) ...) (infers+erase #'(e ...))
( #'(list e- ...) #'(τ ...))]))
(define-syntax (proj stx)
(syntax-parse stx
[(_ tup n:integer)
#:with (tup- τ_tup) (infer+erase #'tup)
#:fail-unless (not (identifier? #'τ_tup)) "not tuple type"
#:fail-unless (< (syntax->datum #'n) (stx-length #'τ_tup)) "proj index too large"
( #'(list-ref tup n) (stx-list-ref #'τ_tup (syntax->datum #'n)))]))

19
tapl/stlc+var.rkt Normal file
View File

@ -0,0 +1,19 @@
#lang racket/base
(require
(for-syntax racket/base syntax/parse syntax/stx racket/string "stx-utils.rkt")
"typecheck.rkt")
(require (prefix-in stlc: (only-in "stlc+tup.rkt" #%app λ))
(except-in "stlc+tup.rkt" #%app λ))
(provide (rename-out [stlc:#%app #%app] [stlc:λ λ])
tup proj)
(provide (all-from-out "stlc+tup.rkt"))
;; Simply-Typed Lambda Calculus, plus variants
;; Types:
;; - types from stlc+tup.rkt
;; Terms:
;; - terms from stlc+tup.rkt
(provide Tmp Tmp2)
(define-syntax Tmp (make-rename-transformer #'Int))
(define-syntax Tmp2 (λ (stx) (syntax-parse stx [x:id #'(Int Int Int)])))

View File

@ -19,4 +19,7 @@
(define (stx-length stx) (length (syntax->list stx)))
(define (stx-last stx) (last (syntax->list stx)))
(define (stx-last stx) (last (syntax->list stx)))
(define (stx-list-ref stx i)
(list-ref (syntax->list stx) i))

View File

@ -64,7 +64,8 @@
(is-even? (sub1 n))))])
(is-odd? 11)) : Bool #t)
;; tests from stlc+lit-tests.rkt - most should still pass --------------------------
;; tests from stlc+lit-tests.rkt --------------------------
; most should pass, some failing may now pass due to added types/forms
(check-type 1 : Int)
;(check-not-type 1 : (Int → Int))
;(typecheck-fail "one") ; literal now supported

View File

@ -0,0 +1,103 @@
#lang s-exp "../stlc+tup.rkt"
(require "rackunit-typechecking.rkt")
;; tests for tuples
(check-type (tup 1 2 3) : (Int Int Int))
(check-type (tup 1 "1" #f +) : (Int String Bool (Int Int Int)))
(check-not-type (tup 1 "1" #f +) : (Unit String Bool (Int Int Int)))
(check-not-type (tup 1 "1" #f +) : (Int Unit Bool (Int Int Int)))
(check-not-type (tup 1 "1" #f +) : (Int String Unit (Int Int Int)))
(check-not-type (tup 1 "1" #f +) : (Int String Bool (Int Int Unit)))
(check-type (proj (tup 1 "2" #f) 0) : Int 1)
(check-type (proj (tup 1 "2" #f) 1) : String "2")
(check-type (proj (tup 1 "2" #f) 2) : Bool #f)
(typecheck-fail (proj (tup 1 "2" #f) 3)) ; index too large
(typecheck-fail (proj 1 2)) ; not tuple
;; ext-stlc.rkt tests ---------------------------------------------------------
;; should still pass
;; new literals and base types
(check-type "one" : String) ; literal now supported
(check-type #f : Bool) ; literal now supported
(check-type (λ ([x : Bool]) x) : (Bool Bool)) ; Bool is now valid type
;; Unit
(check-type (void) : Unit)
(check-type void : ( Unit))
(typecheck-fail ((λ ([x : Unit]) x) 2))
(typecheck-fail ((λ ([x : Unit])) void))
(check-type ((λ ([x : Unit]) x) (void)) : Unit)
;; begin
(typecheck-fail (begin))
(check-type (begin 1) : Int)
(typecheck-fail (begin 1 2 3))
(check-type (begin (void) 1) : Int 1)
;;ascription
(typecheck-fail (ann 1 : Bool))
(check-type (ann 1 : Int) : Int 1)
(check-type ((λ ([x : Int]) (ann x : Int)) 10) : Int 10)
; let
(check-type (let () (+ 1 1)) : Int 2)
(check-type (let ([x 10]) (+ 1 2)) : Int)
(typecheck-fail (let ([x #f]) (+ x 1)))
(check-type (let ([x 10] [y 20]) ((λ ([z : Int] [a : Int]) (+ a z)) x y)) : Int 30)
(typecheck-fail (let ([x 10] [y (+ x 1)]) (+ x y))) ; unbound identifier
(check-type (let* ([x 10] [y (+ x 1)]) (+ x y)) : Int 21)
(typecheck-fail (let* ([x #t] [y (+ x 1)]) 1))
; letrec
(typecheck-fail (letrec ([(x : Int) #f] [(y : Int) 1]) y))
(typecheck-fail (letrec ([(y : Int) 1] [(x : Int) #f]) x))
(check-type (letrec ([(x : Int) 1] [(y : Int) (+ x 1)]) (+ x y)) : Int 3)
;; recursive
(check-type
(letrec ([(countdown : (Int String))
(λ ([i : Int])
(if (= i 0)
"liftoff"
(countdown (- i 1))))])
(countdown 10)) : String "liftoff")
;; mutually recursive
(check-type
(letrec ([(is-even? : (Int Bool))
(λ ([n : Int])
(or (zero? n)
(is-odd? (sub1 n))))]
[(is-odd? : (Int Bool))
(λ ([n : Int])
(and (not (zero? n))
(is-even? (sub1 n))))])
(is-odd? 11)) : Bool #t)
;; tests from stlc+lit-tests.rkt --------------------------
; most should pass, some failing may now pass due to added types/forms
(check-type 1 : Int)
;(check-not-type 1 : (Int → Int))
;(typecheck-fail "one") ; literal now supported
;(typecheck-fail #f) ; literal now supported
(check-type (λ ([x : Int] [y : Int]) x) : (Int Int Int))
(check-not-type (λ ([x : Int]) x) : Int)
(check-type (λ ([x : Int]) x) : (Int Int))
(check-type (λ ([f : (Int Int)]) 1) : ((Int Int) Int))
(check-type ((λ ([x : Int]) x) 1) : Int 1)
(typecheck-fail ((λ ([x : Bool]) x) 1)) ; Bool now valid type, but arg has wrong type
;(typecheck-fail (λ ([x : Bool]) x)) ; Bool is now valid type
(typecheck-fail (λ ([f : Int]) (f 1 2))) ; applying f with non-fn type
(check-type (λ ([f : (Int Int Int)] [x : Int] [y : Int]) (f x y))
: ((Int Int Int) Int Int Int))
(check-type ((λ ([f : (Int Int Int)] [x : Int] [y : Int]) (f x y)) + 1 2) : Int 3)
(typecheck-fail (+ 1 (λ ([x : Int]) x))) ; adding non-Int
(typecheck-fail (λ ([x : (Int Int)]) (+ x x))) ; x should be Int
(typecheck-fail ((λ ([x : Int] [y : Int]) y) 1)) ; wrong number of args
(check-type ((λ ([x : Int]) (+ x x)) 10) : Int 20)

View File

@ -0,0 +1,105 @@
#lang s-exp "../stlc+var.rkt"
(require "rackunit-typechecking.rkt")
(check-type ((λ ([x : Tmp]) (+ x 2)) 3) : Tmp)
;; tests for tuples -----------------------------------------------------------
(check-type (tup 1 2 3) : (Int Int Int))
(check-type (tup 1 "1" #f +) : (Int String Bool (Int Int Int)))
(check-not-type (tup 1 "1" #f +) : (Unit String Bool (Int Int Int)))
(check-not-type (tup 1 "1" #f +) : (Int Unit Bool (Int Int Int)))
(check-not-type (tup 1 "1" #f +) : (Int String Unit (Int Int Int)))
(check-not-type (tup 1 "1" #f +) : (Int String Bool (Int Int Unit)))
(check-type (proj (tup 1 "2" #f) 0) : Int 1)
(check-type (proj (tup 1 "2" #f) 1) : String "2")
(check-type (proj (tup 1 "2" #f) 2) : Bool #f)
(typecheck-fail (proj (tup 1 "2" #f) 3)) ; index too large
(typecheck-fail (proj 1 2)) ; not tuple
;; ext-stlc.rkt tests ---------------------------------------------------------
;; should still pass
;; new literals and base types
(check-type "one" : String) ; literal now supported
(check-type #f : Bool) ; literal now supported
(check-type (λ ([x : Bool]) x) : (Bool Bool)) ; Bool is now valid type
;; Unit
(check-type (void) : Unit)
(check-type void : ( Unit))
(typecheck-fail ((λ ([x : Unit]) x) 2))
(typecheck-fail ((λ ([x : Unit])) void))
(check-type ((λ ([x : Unit]) x) (void)) : Unit)
;; begin
(typecheck-fail (begin))
(check-type (begin 1) : Int)
(typecheck-fail (begin 1 2 3))
(check-type (begin (void) 1) : Int 1)
;;ascription
(typecheck-fail (ann 1 : Bool))
(check-type (ann 1 : Int) : Int 1)
(check-type ((λ ([x : Int]) (ann x : Int)) 10) : Int 10)
; let
(check-type (let () (+ 1 1)) : Int 2)
(check-type (let ([x 10]) (+ 1 2)) : Int)
(typecheck-fail (let ([x #f]) (+ x 1)))
(check-type (let ([x 10] [y 20]) ((λ ([z : Int] [a : Int]) (+ a z)) x y)) : Int 30)
(typecheck-fail (let ([x 10] [y (+ x 1)]) (+ x y))) ; unbound identifier
(check-type (let* ([x 10] [y (+ x 1)]) (+ x y)) : Int 21)
(typecheck-fail (let* ([x #t] [y (+ x 1)]) 1))
; letrec
(typecheck-fail (letrec ([(x : Int) #f] [(y : Int) 1]) y))
(typecheck-fail (letrec ([(y : Int) 1] [(x : Int) #f]) x))
(check-type (letrec ([(x : Int) 1] [(y : Int) (+ x 1)]) (+ x y)) : Int 3)
;; recursive
(check-type
(letrec ([(countdown : (Int String))
(λ ([i : Int])
(if (= i 0)
"liftoff"
(countdown (- i 1))))])
(countdown 10)) : String "liftoff")
;; mutually recursive
(check-type
(letrec ([(is-even? : (Int Bool))
(λ ([n : Int])
(or (zero? n)
(is-odd? (sub1 n))))]
[(is-odd? : (Int Bool))
(λ ([n : Int])
(and (not (zero? n))
(is-even? (sub1 n))))])
(is-odd? 11)) : Bool #t)
;; tests from stlc+lit-tests.rkt --------------------------
; most should pass, some failing may now pass due to added types/forms
(check-type 1 : Int)
;(check-not-type 1 : (Int → Int))
;(typecheck-fail "one") ; literal now supported
;(typecheck-fail #f) ; literal now supported
(check-type (λ ([x : Int] [y : Int]) x) : (Int Int Int))
(check-not-type (λ ([x : Int]) x) : Int)
(check-type (λ ([x : Int]) x) : (Int Int))
(check-type (λ ([f : (Int Int)]) 1) : ((Int Int) Int))
(check-type ((λ ([x : Int]) x) 1) : Int 1)
(typecheck-fail ((λ ([x : Bool]) x) 1)) ; Bool now valid type, but arg has wrong type
;(typecheck-fail (λ ([x : Bool]) x)) ; Bool is now valid type
(typecheck-fail (λ ([f : Int]) (f 1 2))) ; applying f with non-fn type
(check-type (λ ([f : (Int Int Int)] [x : Int] [y : Int]) (f x y))
: ((Int Int Int) Int Int Int))
(check-type ((λ ([f : (Int Int Int)] [x : Int] [y : Int]) (f x y)) + 1 2) : Int 3)
(typecheck-fail (+ 1 (λ ([x : Int]) x))) ; adding non-Int
(typecheck-fail (λ ([x : (Int Int)]) (+ x x))) ; x should be Int
(typecheck-fail ((λ ([x : Int] [y : Int]) y) 1)) ; wrong number of args
(check-type ((λ ([x : Int]) (+ x x)) 10) : Int 20)

View File

@ -25,7 +25,7 @@
[(_ τ:id)
#:with τ? (format-id #'τ "~a?" #'τ)
#'(begin
(provide τ)
(provide τ (for-syntax τ?))
(define-syntax (τ stx)
(syntax-parse stx
[_ (error 'Int "Cannot use type at run time.")]))
@ -37,7 +37,7 @@
[(_ τ:id)
#:with τ? (format-id #'τ "~a?" #'τ)
#'(begin
(provide τ)
(provide τ (for-syntax τ?))
(define-syntax (τ stx)
(syntax-parse stx
[_ (error 'Int "Cannot use type at run time.")]))