-
Notifications
You must be signed in to change notification settings - Fork 0
/
type-check-Lvar.rkt
79 lines (63 loc) · 2.65 KB
/
type-check-Lvar.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#lang racket
(require "utilities.rkt")
(provide type-check-Lvar type-check-Lvar-class type-check-var-mixin)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Integers and Variables ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; type-check-var-mixin (the parts reusable for Lvar and Cvar)
(define (type-check-var-mixin super-class)
(class super-class
(super-new)
(define/public (operator-types)
'((+ . ((Integer Integer) . Integer))
(- . ((Integer Integer) . Integer))
(read . (() . Integer))))
(define/public (type-equal? t1 t2) (equal? t1 t2))
(define/public (check-type-equal? t1 t2 e)
(unless (type-equal? t1 t2)
(error 'type-check "~a != ~a\nin ~v" t1 t2 e)))
(define/public (type-check-op op arg-types e)
(match (dict-ref (operator-types) op)
[`(,param-types . ,return-type)
(for ([at arg-types] [pt param-types])
(check-type-equal? at pt e))
return-type]
[else (error 'type-check-op "unrecognized ~a" op)]))
(define/public (type-check-exp env)
(lambda (e)
(debug 'type-check-exp "Lvar ~a" e)
(match e
[(Var x) (values (Var x) (dict-ref env x))]
[(Int n) (values (Int n) 'Integer)]
[(Prim op es)
(define-values (new-es ts)
(for/lists (exprs types) ([e es]) ((type-check-exp env) e)))
(values (Prim op new-es) (type-check-op op ts e))]
[else (error 'type-check-exp "couldn't match ~a" e)])))
))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; type-check-Lvar
(define type-check-Lvar-class
(class (type-check-var-mixin object%)
(super-new)
(inherit check-type-equal?)
(define/override (type-check-exp env)
(lambda (e)
(debug 'type-check-exp "Lvar ~a" e)
(match e
[(Let x e body)
(define-values (e^ Te) ((type-check-exp env) e))
(define-values (b Tb) ((type-check-exp (dict-set env x Te)) body))
(values (Let x e^ b) Tb)]
[else ((super type-check-exp env) e)])))
(define/public (type-check-program e)
(match e
[(Program info body)
(define-values (body^ Tb) ((type-check-exp '()) body))
(check-type-equal? Tb 'Integer body)
(Program info body^)]
[else (error 'type-check-Lvar "couldn't match ~a" e)]))
))
(define (type-check-Lvar p)
(send (new type-check-Lvar-class) type-check-program p))