commit ea5d0d1a0289ba8b604565303f67af117b87d18b
parent dc3409fe208b386827cb47f725e4c42d51d1291e
Author: Stephen Chang <stchang@ccs.neu.edu>
Date: Wed, 27 Aug 2014 14:50:27 -0400
stlc: use define-primop; rename stlc-test stlc-tests.rkt
Diffstat:
5 files changed, 14 insertions(+), 170 deletions(-)
diff --git a/racket-extended-for-implementing-typed-langs.rkt b/racket-extended-for-implementing-typed-langs.rkt
@@ -125,7 +125,7 @@
...
[(_ . x)
#:when (type-error #:src stx #:msg "Don't know the type for literal: ~a" #'x)
- stx]))
+ (syntax/loc stx (#%datum . x))]))
(template
(#%module-begin
(provide (rename-out [my-datum #%datum]))
diff --git a/stlc-test.rkt b/stlc-test.rkt
@@ -1,5 +0,0 @@
-#lang s-exp "stlc-via-racket-extended.rkt"
-((λ ([f : (Int → Int)] [x : Int]) (f x))
- (λ ([x : Int]) (+ x x 2))
- 10)
-((λ ([x : Int]) (+ x 1 3)) 100)
-\ No newline at end of file
diff --git a/stlc-tests.rkt b/stlc-tests.rkt
@@ -1,151 +1,5 @@
-#lang s-exp "stlc+define+cons.rkt"
-
-(check-type-error ((λ ([x : Int]) (+ x 1)) "10"))
-(check-type ((λ ([x : Int]) (+ x 1)) 10) : Int)
-(check-equal? ((λ ([x : Int]) (+ x 1)) 10) 11) ; identifier used out of context
-(check-type-and-result ((λ ([x : Int]) (+ x 1)) 10) : Int => 11)
-
-; check fns with literal or id bodies
-(check-type (λ ([x : Int]) x) : (Int → Int))
-(check-type (λ ([x : Unit] [y : Int]) x y) : (Unit Int → Int))
-
-;; check fns with multi-expr body
-(check-type (λ ([x : Int]) (void) x) : (Int → Int))
-(check-type-error (λ ([x : Int]) 1 x))
-(check-type (λ ([x : Int]) (void) (void) x) : (Int → Int))
-
-; HO fn
-(check-type-and-result ((λ ([f : (Int → Int)]) (f 10)) (λ ([x : Int]) (+ x 1))) : Int => 11)
-(check-type (λ ([f : (Int → Int)]) (f 10)) : ((Int → Int) → Int))
-(check-type (λ ([f : (Int → Int)]) (λ ([x : Int]) (f (f x)))) : ((Int → Int) → (Int → Int)))
-(check-type-error (λ (f : (Int → Int)) (λ (x : String) (f (f x)))))
-
-;; shadowed var
-(check-type-error ((λ ([x : Int]) ((λ ([x : String]) x) x)) 10))
-(check-type-and-result ((λ ([x : String]) ((λ ([x : Int]) (+ x 1)) 10)) "ten") : Int => 11)
-
-;; let
-(check-type-and-result (let ([x 1] [y 2]) (+ x y)) : Int => 3)
-(check-type-error (let ([x 1] [y "two"]) (+ x y)))
-(check-type-and-result (let ([x "one"]) (let ([x 2]) (+ x x))) : Int => 4)
-
-;; lists
-(check-type-and-result (first {Int} (cons {Int} 1 (null {Int}))) : Int => 1)
-(check-type-and-result (rest {Int} (cons {Int} 1 (null {Int}))) : (Listof Int) => (null {Int}))
-(check-type-error (cons {Int} 1 (null {String})))
-(check-type-error (cons {Int} "one" (null {Int})))
-(check-type-error (cons {String} 1 (null {Int})))
-(check-type-error (cons {String} 1 (null {Int})))
-(check-type-error (cons {String} "one" (cons {Int} "two" (null {String}))))
-(check-type-and-result (first {String} (cons {String} "one" (cons {String} "two" (null {String}))))
- : String => "one")
-(check-type-and-result (null? {String} (null {String})) : Bool => #t)
-(check-type-and-result (null? {String} (cons {String} "one" (null {String}))) : Bool => #f)
-(check-type-error (null? {String} (null {Int})))
-(check-type-error (null? {Int} (null {String})))
-(check-type-error (null? {Int} 1))
-(check-type-error (null? {Int} "one"))
-(check-type-error (null? {Int} (cons {String} "one" (null {String}))))
-
-; begin and void
-(check-type (void) : Unit)
-(check-type-and-result (begin (void) 1) : Int => 1)
-(check-type-and-result (begin (void) (void) 1) : Int => 1)
-(check-type-and-result (begin (void) (void) (void)) : Unit => (void))
-(check-type-and-result (begin (+ 1 2)) : Int => 3)
-(check-type-error (begin 1 2))
-
-(check-type (λ ([x : Int]) (void) (+ x 1)) : (Int → Int))
-(check-type-error (λ ([x : Int]) 1 1))
-(check-type (λ ([x : Int] [y : Int]) (+ x y)) : (Int Int → Int))
-(check-type-and-result ((λ ([a : Int] [b : Int] [c : Int]) (void) (void) (+ a (+ b c))) 1 2 3)
- : Int => 6)
-
-; define
-(define (g [y : Int]) : Int
- (+ (f y) 1))
-(define (f [x : Int]) : Int
- (+ x 1))
-(check-type-and-result (f 10) : Int => 11)
-(check-type-and-result (g 100) : Int => 102)
-(check-not-type (f 10) : String)
-(check-not-type (g 100) : String)
-
-;; if
-(check-type-and-result (if (null? {Int} (null {Int})) 1 2) : Int => 1)
-(check-type-and-result (if (null? {Int} (cons {Int} 1 (null {Int}))) 1 2) : Int => 2)
-(check-type-error (if (null? {Int} (null {Int})) 1 "one"))
-(check-type-error (if (null? {Int} (null {Int})) "one" 1))
-(check-type-error (if 1 2 3))
-
-;;; recursive fn
-(define (add1 [x : Int]) : Int
- (+ x 1))
-(define (map [f : (Int → Int)] [lst : (Listof Int)]) : (Listof Int)
- (if (null? {Int} lst)
- (null {Int})
- (cons {Int} (f (first {Int} lst)) (map f (rest {Int} lst)))))
-(check-type-and-result (map add1 (cons {Int} 1 (cons {Int} 2 (null {Int}))))
- : (Listof Int)
- => (cons {Int} 2 (cons {Int} 3 (null {Int}))))
-(check-not-type (map add1 (cons {Int} 1 (cons {Int} 2 (null {Int}))))
- : (Listof String))
-
-;; recursive types
-(define (a [x : Int]) : Int (b x))
-(define (b [x : Int]) : Int (a x))
-(define (ff [x : Int]) : Int (ff x))
-
-;; define-type (non parametric)
-(define-type MaybeInt (variant (None) (Just Int)))
-(check-type (None) : MaybeInt)
-(check-type (Just 10) : MaybeInt)
-(check-type-error (Just "ten"))
-(check-type-error (Just (None)))
-(define (maybeint->bool [maybint : MaybeInt]) : Bool
- (cases maybint
- [None () #f]
- [Just (x) #t]))
-(check-type-and-result (maybeint->bool (None)) : Bool => #f)
-(check-type-and-result (maybeint->bool (Just 25)) : Bool => #t)
-(check-type-error (maybeint->bool 25))
-(check-type-error (define (maybeint->wrong [maybint : MaybeInt])
- (cases maybint
- [None () #f]
- [Just (x) x])))
-
-(define-type IntList (variant (Null) (Cons Int IntList)))
-(check-type-and-result (Null) : IntList => (Null))
-(check-type-and-result (Cons 1 (Null)) : IntList => (Cons 1 (Null)))
-(check-type-error (Cons "one" (Null)))
-(check-type-error (Cons 1 2))
-(define (map/IntList [f : (Int → Int)] [lst : IntList]) : IntList
- (cases lst
- [Null () (Null)]
- [Cons (x xs) (Cons (f x) (map/IntList f xs))]))
-(check-type-and-result (map/IntList add1 (Null)) : IntList => (Null))
-(check-type-and-result (map/IntList add1 (Cons 1 (Null))) : IntList => (Cons 2 (Null)))
-(check-type-and-result (map/IntList add1 (Cons 2 (Cons 1 (Null))))
- : IntList => (Cons 3 (Cons 2 (Null))))
-(check-type-error (map/IntList (λ ([n : Int]) #f) (Null)))
-(define-type BoolList (variant (BoolNull) (BoolCons Bool BoolList)))
-(define (map/BoolList [f : (Bool → Int)] [lst : BoolList]) : IntList
- (cases lst
- [BoolNull () (Null)]
- [BoolCons (x xs) (Cons (f x) (map/BoolList f xs))]))
-(check-type (map/BoolList (λ ([b : Bool]) (if b 0 1)) (BoolNull)) : IntList)
-(check-type-and-result
- (map/BoolList (λ ([b : Bool]) (if b 0 1)) (BoolCons #f (BoolNull)))
- : IntList => (Cons 1 (Null)))
-(check-not-type (map/BoolList (λ ([b : Bool]) (if b 0 1)) (BoolNull)) : BoolList)
-;; check typename is available
-(check-type (λ ([lst : IntList])
- (cases lst
- [Null () (None)]
- [Cons (x xs) (Just x)]))
- : (IntList → MaybeInt))
-(check-type ((λ ([lst : IntList])
- (cases lst
- [Null () (None)]
- [Cons (x xs) (Just x)]))
- (Null)) : MaybeInt)
-\ No newline at end of file
+#lang s-exp "stlc.rkt";"stlc-via-racket-extended.rkt"
+((λ ([f : (Int → Int)] [x : Int]) (f x))
+ (λ ([x : Int]) (+ x x 1))
+ 10)
+((λ ([x : Int]) (+ x 1 3)) 100)
+\ No newline at end of file
diff --git a/stlc-via-racket-extended.rkt b/stlc-via-racket-extended.rkt
@@ -5,7 +5,7 @@
;; Simply-Typed Lambda Calculus
;; - implemented with racket-extended language
-;; - lam, app, and var only
+;; - lam, app, var, +, and int literals only
(declare-built-in-types → Int)
diff --git a/stlc.rkt b/stlc.rkt
@@ -4,14 +4,15 @@
syntax/stx racket/syntax
"stx-utils.rkt")
"typecheck.rkt")
-(provide (rename-out [λ/tc λ] [app/tc #%app] [datum/tc #%datum] [+/tc +]))
+(provide (rename-out [λ/tc λ] [app/tc #%app] [datum/tc #%datum]))
(provide #%module-begin #%top-interaction)
;; Simply-Typed Lambda Calculus
-;; - lam, app, and var only
+;; - lam, app, var, +, and int literals only
;; - implemented in racket
(define-and-provide-builtin-types → Int)
+(provide (for-syntax assert-Int-type))
(define-for-syntax (assert-Int-type e) (assert-type e #'Int))
;; typed forms ----------------------------------------------------------------
@@ -20,17 +21,12 @@
(define-syntax (datum/tc stx)
(syntax-parse stx
[(_ . n:integer) (⊢ (syntax/loc stx (#%datum . n)) #'Int)]
- [(_ x)
- #:when (type-error #:src #'x #:msg "~a has unknown type" #'x)
+ [(_ . x)
+ #:when (type-error #:src #'x #:msg "Literal ~a has unknown type." #'x)
(syntax/loc stx (#%datum . x))]))
;; op
-(define-syntax (+/tc stx)
- (syntax-parse stx
- [(_ e ...)
- #:with es+ (stx-map expand/df #'(e ...))
- #:when (stx-andmap assert-Int-type #'es+)
- (⊢ (syntax/loc stx (+ . es+)) #'Int)]))
+(define-primop + : (Int ... → Int))
;; lambda
(define-syntax (λ/tc stx)