-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdomain.rkt
108 lines (92 loc) · 3.21 KB
/
domain.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#lang racket
;; TODO: Add false value
;; TODO: Abstract procedure values (w/ arity?)
(provide T T?
ℕ ℕ?
⊥ ⊥?
in-domain?
(struct-out closure)
closure-label
<=?
lub)
(require "environment.rkt"
"free-vars.rkt")
(define T (unquoted-printing-string "T"))
(define ℕ (unquoted-printing-string "ℕ"))
(define (T? v) (eq? v T))
(define (ℕ? v) (eq? v ℕ))
(struct ⊥ (message)
#:constructor-name make-⊥
#:transparent
#:omit-define-syntaxes)
(define/match (⊥ arg . rest-args)
[((? string? message-str) '())
(make-⊥ message-str)]
[((? symbol? who-sym) (list* (? string? format-str) rest-args))
(make-⊥ (format "~a: ~a" who-sym (apply format format-str rest-args)))])
(struct closure (source-syntax environment)
#:constructor-name make-closure)
(define closure-label closure-source-syntax)
(define (in-domain? v)
(or (T? v) (⊥? v) (ℕ? v) (natural? v) (false? v) (procedure? v) (closure? v)))
(define (<=? d1 d2)
(define ht (make-hashalw))
(let loop ([d1 d1] [d2 d2])
(or (hash-ref ht (cons d1 d2) #f)
(begin
(hash-set! ht (cons d1 d2) #t)
(<=?/recur d1 d2 loop)))))
(define (<=?/recur d1 d2 recur-proc)
(let loop ([d1 d1] [d2 d2])
(cond
[(eqv? d1 d2) #t]
[(T? d2) #t]
[(⊥? d1) #t]
[(and (natural? d1) (ℕ? d2)) #t]
[(and (closure? d1) (closure? d2))
(and (eq? (closure-label d1) (closure-label d2))
(closure-environment<=?/recur d1 d2 recur-proc))]
[else #f])))
(define (closure-environment<=?/recur c1 c2 recur-proc)
(define ρ1 (closure-environment c1))
(define ρ2 (closure-environment c2))
(for/and ([id (in-list (free-vars (closure-source-syntax c1)))])
(let/ec break
(define v1 (ρ-ref ρ1 id))
(define v2 (ρ-ref ρ2 id (lambda () (break #f))))
(<=?/recur (force v1) (force v2) recur-proc))))
(define (lub d d′)
(define ht
(make-custom-hash
(lambda (p p′)
(or (and (eqv? (car p) (car p′))
(eqv? (cdr p) (cdr p′)))
(and (eqv? (car p) (cdr p′))
(eqv? (cdr p) (car p′)))))))
(let loop ([d d] [d′ d′])
(or (dict-ref ht (cons d d′) #f)
(let ()
(define d″ (delay (lub/recur d d′ loop)))
(dict-set! ht (cons d d′) d″)
(force d″)))))
(define (lub/recur d d′ recur-proc)
(cond
[(eqv? d d′) d]
[(or (T? d) (T? d′)) T]
[(and (⊥? d) (⊥? d′))
(⊥ "something went wrong")]
[(⊥? d ) d′]
[(⊥? d′) d ]
[(and (<=? d ℕ) (<=? d′ ℕ)) ℕ]
[(and (closure? d) (closure? d′) (eq? (closure-label d) (closure-label d′)))
(make-closure (closure-source-syntax d) (closure-environment-lub/recur d d′ recur-proc))]
[else T]))
(define (closure-environment-lub/recur c c′ recur-proc)
(define ρ (closure-environment c ))
(define ρ′ (closure-environment c′))
(for/fold ([ρ″ (make-ρ)])
([id (in-list (free-vars (closure-source-syntax c)))])
(define d (force (ρ-ref ρ id)))
(define d′ (force (ρ-ref ρ′ id (⊥ "unbound identifier"))))
(define d″ (recur-proc d d′))
(ρ-set ρ″ id d″)))