aboutsummaryrefslogtreecommitdiff
path: root/stlc-imp.rkt
diff options
context:
space:
mode:
Diffstat (limited to 'stlc-imp.rkt')
-rw-r--r--stlc-imp.rkt57
1 files changed, 14 insertions, 43 deletions
diff --git a/stlc-imp.rkt b/stlc-imp.rkt
index fc34115..0c3c3c7 100644
--- a/stlc-imp.rkt
+++ b/stlc-imp.rkt
@@ -32,37 +32,19 @@
(check-core (desugar expr) with #hash()))
(define (check-core expr with Γ)
(match with
- ['sole (equal? 'Unit with)]
- [n #:when (natural? n) (equal? 'Nat with)]
- [x #:when (dict-has-key? Γ x)
- (equal? (dict-ref Γ x) with)]
-
[`(new ,e)
(match with
[`(Ref ,t) (check-core e t Γ)]
[_ #f])]
- [`(! ,e) (check-core e `(Ref ,with) Γ)]
- [`(set ,e1 ,e2)
- (match (infer-core e1 Γ)
- [`(Ref ,t)
- (and (equal? 'Unit with)
- (check-core e2 t Γ))]
- [_ #f])]
[`(λ (,x : ,t) ,e)
(match with
[`(,t1 → ,k ,t2)
(and (equal? t t1) (check-core e t2 (dict-set Γ x t))
- (> k (max-level e t1 t2 (dict-set Γ x t1))))] ; KNOB
- [_ #f])]
- [`(,e1 ,e2)
- (match (infer-core e1 Γ)
- [`(,t1 → ,k ,t2)
- (and (equal? t2 with)
- (equal? t1 (infer-core e2 Γ)))]
+ (> k (level-body e (dict-set Γ x t1))))] ; KNOB
[_ #f])]
- [_ #f]))
+ [_ (equal? (infer-core expr Γ) with)]))
;; (infer Expr Table[Sym, Type]): Type
(define (infer expr)
@@ -71,8 +53,7 @@
(match expr
['sole 'Unit]
[n #:when (natural? n) 'Nat]
- [x #:when (dict-has-key? Γ x)
- (dict-ref Γ x)]
+ [x #:when (dict-has-key? Γ x) (dict-ref Γ x)]
[`(new ,e) `(Ref ,(infer-core e Γ))]
[`(! ,e)
@@ -88,35 +69,28 @@
[t (err (format "attempting to update non-reference ~a: ~a" e1 t))])]
[`(λ (,x : ,t1) ,e)
- (let ([t2 (infer-core e (dict-set Γ x t1))])
- (let ([k (+ 1 (max-level e (dict-set Γ x t1) t1 t2))]) ; KNOB
- `(,t1 → ,k ,t2)))]
+ (let* ([t2 (infer-core e (dict-set Γ x t1))]
+ [k (+ 1 (level-body e (dict-set Γ x t1)))]) ; KNOB
+ `(,t1 → ,k ,t2))]
[`(,e1 ,e2)
(match (infer-core e1 Γ)
[`(,t1 → ,k ,t2)
(if (check-core e2 t1 Γ) t2
- (err (format "inferred argument type ~a does not match arg ~a of type ~a" t1 e2 (infer-core e2 Γ))))]
+ (err (format "inferred argument type ~a does not match arg ~a of type ~a"
+ t1 e2 (infer-core e2 Γ))))]
[t (err (format "expected → type on application body, got ~a" t))])]
[e (err (format "attempting to infer an unknown expression ~a" e))]))
-;; (max-level Table[Sym, Type] Expr Type Type): Natural
-(define (max-level e Γ t1 t2)
- (max
- (level-type t1)
- (level-type t2)
- (level-body e Γ)))
-
;; (level-type Type): Natural
(define (level-type t)
(match t
['Unit 0]
['Nat 0]
[`(,t1 → ,k ,t2)
- (if (or (< k (level-type t1)) (< k (level-type t2)))
+ (if (and (>= k (level-type t1)) (>= k (level-type t2))) k
(err (format "annotated level ~a is less than inferred levels of ~a and ~a!"
- k t1 t2))
- k)]
+ k t1 t2)))]
[`(Ref ,t)
(let ([k (level-type t)])
(if (zero? k) 0 (+ 1 k)))] ; KNOB
@@ -127,10 +101,7 @@
(match e
['sole 0]
[n #:when (natural? n) 0]
- [x #:when (dict-has-key? Γ x)
- (level-type (dict-ref Γ x))]
- [`(new ,e) (level-body e Γ)]
- [`(! ,e) (level-body e Γ)]
- [`(set ,e1 ,e2) (max (level-body e1 Γ) (level-body e2 Γ))]
- [`(λ (,x : ,t) ,e) (level-body e (dict-set Γ x t))] ; todo: should be 0?
- [`(,e1 ,e2) (max (level-body e1 Γ) (level-body e2 Γ))]))
+ [x #:when (dict-has-key? Γ x) (level-type (dict-ref Γ x))]
+ [(or `(new ,e) `(! ,e) `(λ (,_ : ,_) ,e)) (level-body e Γ)]
+ [(or `(set ,e1 ,e2) `(,e1 ,e2)) (max (level-body e1 Γ) (level-body e2 Γ))]
+ [x #:when (symbol? x) 0])) ; local variables, not in Γ