-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdemod-model.rkt
345 lines (310 loc) · 16 KB
/
demod-model.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
#lang racket
(require redex)
(provide (all-defined-out))
(define-language
compiled
[program (mod ...)]
[mod (module id (req ...) (code ...))]
[code (phase (expr ...))]
[req (require id @ phase)]
[expr var
val
(+ expr expr)
(set! var expr)]
[val number
(quote id @ phase)]
[var (id id)]
[id variable-not-otherwise-mentioned]
[phase number])
(define-extended-language
compiled/eval compiled
[E hole
(+ E expr)
(+ val E)
(set! var E)]
[σ ([var val] ...)]
[state (program / (inst ...) / (inst ...))]
[inst (id phase)]
[st (σ / state)])
(define -->/ce
(reduction-relation
compiled/eval
#:domain st
[--> (σ / ((mod_0 ... (module id_0 ((require id_new @ phase_new) req ...) (code ...)) mod_n ...) / ((id_0 phase_0) inst_n ...) / (inst_d ...)))
(σ / ((mod_0 ... (module id_0 (req ...) (code ...)) mod_n ...) / ((id_new ,(+ (term phase_new) (term phase_0))) (id_0 phase_0) inst_n ...) / (inst_d ...)))
"module require"]
[--> (σ / (in-hole ((mod_0 ... (module id_0 () (code_0 ... (phase (E expr ...)) code_n ...)) mod_n ...) / ((id_0 phase_0) inst_n ...) / (inst_d ...)) var))
(σ / (in-hole ((mod_0 ... (module id_0 () (code_0 ... (phase (E expr ...)) code_n ...)) mod_n ...) / ((id_0 phase_0) inst_n ...) / (inst_d ...)) val))
(side-condition (zero? (+ (term phase) (term phase_0))))
(where val (lookup σ var))
"var ref"]
[--> (σ / (in-hole ((mod_0 ... (module id_0 () (code_0 ... (phase (E expr ...)) code_n ...)) mod_n ...) / ((id_0 phase_0) inst_n ...) / (inst_d ...)) (+ number_0 number_1)))
(σ / (in-hole ((mod_0 ... (module id_0 () (code_0 ... (phase (E expr ...)) code_n ...)) mod_n ...) / ((id_0 phase_0) inst_n ...) / (inst_d ...)) ,(+ (term number_0) (term number_1))))
(side-condition (zero? (+ (term phase) (term phase_0))))
"add"]
[--> (σ_0 / (in-hole ((mod_0 ... (module id_0 () (code_0 ... (phase (E expr ...)) code_n ...)) mod_n ...) / ((id_0 phase_0) inst_n ...) / (inst_d ...)) (set! var val)))
(σ_1 / (in-hole ((mod_0 ... (module id_0 () (code_0 ... (phase (E expr ...)) code_n ...)) mod_n ...) / ((id_0 phase_0) inst_n ...) / (inst_d ...)) val))
(side-condition (zero? (+ (term phase) (term phase_0))))
(where σ_1 (assign σ_0 var val))
"set!"]
[--> (σ / ((mod_0 ... (module id_0 () (code_0 ... (phase (val expr ...)) code_n ...)) mod_n ...) / ((id_0 phase_0) inst_n ...) / (inst_d ...)))
(σ / ((mod_0 ... (module id_0 () (code_0 ... (phase (expr ...)) code_n ...)) mod_n ...) / ((id_0 phase_0) inst_n ...) / (inst_d ...)))
(side-condition (zero? (+ (term phase) (term phase_0))))
"expression done"]
[--> (σ / ((mod_0 ... (module id_0 () (code_0 ... (phase ()) code_n ...)) mod_n ...) / ((id_0 phase_0) inst_n ...) / (inst_d ...)))
(σ / ((mod_0 ... mod_n ...) / (inst_n ...) / ((id_0 phase_0) inst_d ...)))
(side-condition (zero? (+ (term phase) (term phase_0))))
"module done"]
[--> (σ / ((mod ...) / (inst_0 inst_n ...) / (inst_d0 ... inst_0 inst_dn ...)))
(σ / ((mod ...) / (inst_n ...) / (inst_d0 ... inst_0 inst_dn ...)))
"module done already"]))
(define-metafunction compiled/eval
lookup : σ var -> val
[(lookup ([var_0 val_0] ... [var val] [var_n val_n] ...) var)
val]
[(lookup σ var)
,(error 'lookup "unbound variable reference: ~a" (term var))])
(define-metafunction compiled/eval
assign : σ var val -> σ
[(assign ([var_0 val_0] ... [var val_old] [var_n val_n] ...) var val_new)
([var_0 val_0] ... [var val_new] [var_n val_n] ...)]
[(assign ([var val] ...) var_new val_new)
([var val] ... [var_new val_new])])
;; run : compiled id -> [var -> val]
;; many modules to one mapping as modules are instantiated and run
(define (run prog main)
#;(traces -->/ce (term (() / (,prog / ((,main 0)) / ()))))
(match (apply-reduction-relation* -->/ce (term (() / (,prog / ((,main 0)) / ()))))
[(list (list σ '/ (list prog* '/ (list) '/ done)))
σ]
[(and (list one two ...) ans)
(error 'run "nondeterministic: ~a" ans)]
[else
(error 'run "leftover modules")]))
(define (compile/run prog main)
(run (term (compile ,prog)) main))
(define-extended-language
expanded-core compiled
[mod (module id (req ...) (def ...) (expr ...))]
[def (define id @ phase as expr)]
[var id])
(define-extended-language
expanded expanded-core
[var ....
(id id)])
(define (re-balance small big)
(for/list ([id_m (in-list small)]
[id_ds (in-list big)])
(map (λ _ id_m) id_ds)))
;; compile : expanded -> compiled
;; Many modules to many modules with resolved refs
(define-metafunction expanded
compile : program -> any
[(compile (name modules ((module id_m (req ...) ((define id_d @ phase_d as expr_d) ...) (expr_m ...)) ...)))
((module id_m (req ...) (compile-code id_m
(id_d ...)
(phase_d ...)
((resolve-ref id_md phase_d modules expr_d) ...)
((resolve-ref id_mm 0 modules expr_m) ...)))
...)
(where ((id_md ...) ...)
,(re-balance (term (id_m ...)) (term ((id_d ...) ...))))
(where ((id_mm ...) ...)
,(re-balance (term (id_m ...)) (term ((expr_m ...) ...))))])
(define-metafunction expanded
compile-code : id (id ...) (phase ...) (expr ...) (expr ...) -> any
[(compile-code id_m (id_d ...) (phase_d ...) (expr_d ...) (expr_m ...))
,(compile-code* (term id_m) (term (id_d ...)) (term (phase_d ...)) (term (expr_d ...)) (term (expr_m ...)))])
(define (compile-code* m-id def-ids def-phases def-exprs m-exprs)
(define (snoc l v)
(append l (list v)))
(define phase->exprs
(for/fold ([h (hasheq)])
([id (in-list def-ids)]
[phase (in-list def-phases)]
[expr (in-list def-exprs)])
(hash-update h phase (λ (exprs) (snoc exprs (term (set! (,m-id ,id) ,expr)))) (λ () empty))))
(define phase->exprs*
(hash-update phase->exprs 0 (λ (exprs) (append exprs m-exprs)) (λ () empty)))
(sort (for/list ([(phase exprs) (in-hash phase->exprs*)])
(list phase exprs))
<
#:key car))
(module+ test
(test-equal (term (compile ((module foo () () ()))))
(term ((module foo () ((0 ()))))))
(test-equal (term (compile ((module foo () ((define x @ 0 as 5)) ()))))
(term ((module foo () ((0 ((set! (foo x) 5))))))))
(test-equal (term (compile ((module foo () ((define x @ 0 as 5)) ((set! x 4))))))
(term ((module foo () ((0 ((set! (foo x) 5) (set! (foo x) 4))))))))
(test-equal (term (compile ((module foo ((require bar @ 1)) ((define x @ 1 as (+ y 8))) ((set! x 3)))
(module bar () ((define x @ -1 as 9) (define y @ 0 as 4)) ()))))
(term ((module foo ((require bar @ 1)) ((0 ((set! (bar x) 3))) (1 ((set! (foo x) (+ (bar y) 8))))))
(module bar () ((-1 ((set! (bar x) 9))) (0 ((set! (bar y) 4)))))))))
(define-metafunction expanded
resolve-ref : id phase (mod ...) expr -> expr
;; defined in current module
[(resolve-ref id phase (mod ...) (+ expr_0 expr_1))
(+ (resolve-ref id phase (mod ...) expr_0) (resolve-ref id phase (mod ...) expr_1))]
[(resolve-ref id phase (mod ...) val)
val]
[(resolve-ref id phase (mod ...) (id_m id_d))
(id_m id_d)]
[(resolve-ref id_m phase (mod_0 ... (module id_m (req ...) (def_0 ... (define id_d @ phase as expr_d) def_n ...) (expr_m ...)) mod_n ...) id_d)
(id_m id_d)]
[(resolve-ref id_m phase (mod_0 ... (module id_m (req ...) (def_0 ... (define id_d @ phase as expr_d) def_n ...) (expr_m ...)) mod_n ...) (set! id_d expr))
(set! (id_m id_d) expr)]
;; defined in required module
[(resolve-ref id_m phase (mod_0 ...
(module id_m (req_0 ... (require id_r @ phase_r) req_n ...) (def_m ...) (expr_m ...))
mod_i ...
(module id_r (req_r ...) (def_r ...) (expr_r ...))
mod_n ...) expr)
(resolve-ref id_r ,(- (term phase) (term phase_r)) (mod_0 ... mod_i ... (module id_r (req_r ...) (def_r ...) (expr_r ...)) mod_n ...) expr)]
[(resolve-ref id_m phase (mod_0 ...
(module id_r (req_r ...) (def_r ...) (expr_r ...))
mod_i ...
(module id_m (req_0 ... (require id_r @ phase_r) req_n ...) (def_m ...) (expr_m ...))
mod_n ...) expr)
(resolve-ref id_r ,(- (term phase) (term phase_r)) (mod_0 ... (module id_r (req_r ...) (def_r ...) (expr_r ...)) mod_i ... mod_n ...) expr)]
[(resolve-ref id phase (mod ...) expr)
,(error 'resolve-ref "cannot resolve reference ~a" (term expr))])
(module+ test
(test-equal (term (resolve-ref foo 0 ((module foo () ((define x @ 0 as 5)) ())) x))
(term (foo x)))
(test-equal (term (resolve-ref foo 0 ((module foo () ((define x @ 0 as 5)) ())) (set! x 6)))
(term (set! (foo x) 6)))
(test-equal (term (resolve-ref foo 0 ((module foo ((require bar @ 0)) () ())
(module bar () ((define y @ 0 as 4)) ())) y))
(term (bar y)))
(test-equal (term (resolve-ref foo 0 ((module bar () ((define y @ 0 as 4)) ())
(module foo ((require bar @ 0)) () ())) y))
(term (bar y)))
(test-equal (term (resolve-ref foo 0 ((module foo ((require bar @ 1)) () ())
(module bar () ((define y @ -1 as 4)) ())) y))
(term (bar y)))
(test-equal (term (resolve-ref foo 0 ((module foo ((require bar @ 1)) () ())
(module bar ((require baz @ 1)) () ())
(module baz () ((define z @ -2 as 3)) ())) z))
(term (baz z)))
(test-equal (term (resolve-ref foo 0 ((module foo () ((define x @ 0 as 1)) ())) (+ x x)))
(term (+ (foo x) (foo x)))))
;; demod : expanded id -> compiled
;; many modules to one module with resolve refs
(module+ test
;; module with no requires and only phase 0 code
(test-equal (term (demod foo () ((module foo () ((0 ((set! (foo x) 5))))))))
(term ((module foo () ((0 ((set! (foo x) 5))))))))
;; module with no requires and multiple phases
(test-equal (term (demod foo () ((module foo () ((-1 ((set! (foo y) 6))) (0 ((set! (foo x) 3))))))))
(term ((module foo () ((0 ((set! (foo x) 3))))))))
;; mulitple modules, but main has no requires
(test-equal (term (demod foo () ((module foo () ((0 ((set! (foo x) 5)))))
(module bar () ((0 ((set! (bar y) 3))))))))
(term ((module foo () ((0 ((set! (foo x) 5))))))))
;; module with phase 0 require
(test-equal (term (demod foo () ((module foo ((require bar @ 0)) ((0 ((set! (foo x) 5)))))
(module bar () ((0 ((set! (bar y) 4) (set! (bar y) 2))))))))
(term ((module foo () ((0 ((set! (bar y) 4) (set! (bar y) 2) (set! (foo x) 5))))))))
;; module with phase 1 require and phase -1 def
(test-equal (term (demod foo () ((module foo ((require bar @ 1)) ((0 ((set! (foo x) 5) (set! (bar z) 3)))))
(module bar () ((-1 ((set! (bar z) 8))) (0 ((set! (bar y) 3) (set! (bar y) 6))))))))
(term ((module foo () ((0 ((set! (bar z) 8) (set! (foo x) 5) (set! (bar z) 3))))))))
;; required module without code
(test-equal (term (demod foo () ((module foo ((require bar @ 1)) ((0 ((set! (foo x) 5)))))
(module bar () ((0 ((set! (bar y) 4))))))))
(term ((module foo () ((0 ((set! (foo x) 5))))))))
;; multiple
)
;; todo: use plus for the phase and zero? to mirror eval
(define-metafunction compiled
demod : id ((id phase) ...) program -> program
;; no requires left, return phase 0 code only
[(demod id () (mod_0 ... (module id () (code_0 ... (0 (expr ...)) code_n ...)) mod_n ...))
((module id () ((0 (expr ...)))))]
;; require with code
[(demod id () ((module id ((require id_r @ phase_r) req_m ...) (code_m0 ... (0 (expr_m ...)) code_mn ...))
(module id_r (req_r ...) (code_r0 ... (phase_nr (expr_r ...)) code_rn ...))
mod_n ...))
(demod id ((id_r ,(- (term phase_r))))
((module id (req_m ...) (code_m0 ... (0 (expr_r ... expr_m ...)) code_mn ...))
(module id_r (req_r ...) (code_r0 ... (phase_nr (expr_r ...)) code_rn ...))
mod_n ...))
(where phase_nr ,(- (term phase_r)))]
;; require without code
[(demod id () ((module id ((require id_r @ phase_r) req_m ...) (code_m ...))
(module id_r (req_r ...) (code_r ...))
mod_n ...))
(demod id ((id_r ,(- (term phase_r))))
((module id (req_m ...) (code_m ...))
(module id_r (req_r ...) (code_r ...))
mod_n ...))]
;; require of require with code
[(demod id ((id_c phase_c) (id_n phase_n) ...)
((module id (req_m ...) (code_m0 ... (0 (expr_m ...)) code_mn ...))
(module id_c ((require id_r @ phase_r) req_c ...) (code_c ...))
(module id_r (req_r ...) (code_r0 ... (phase_c (expr_r ...)) code_rn ...))
mod_n ...))
(demod id ((id_r ,(- (term phase_c) (term phase_r))) (id_c phase_c) (id_n phase_n) ...)
((module id (req_m ...) (code_m0 ... (0 (expr_r ... expr_m ...)) code_mn ...))
(module id_c (req_c ...) (code_c ...))
(module id_r (req_r ...) (code_r0 ... (phase_c (expr_r ...)) code_rn ...))
mod_n ...))]
;; require of require without code
[(demod id ((id_c phase_c) (id_n phase_n) ...)
((module id (req_m ...) (code_m ...))
(module id_c ((require id_r @ phase_r) req_c ...) (code_c ...))
(module id_r (req_r ...) (code_r ...))
mod_n ...))
(demod id ((id_r ,(- (term phase_c) (term phase_r))) (id_c phase_c) (id_n phase_n) ...)
((module id (req_m ...) (code_m ...))
(module id_c (req_c ...) (code_c ...))
(module id_r (req_r ...) (code_r ...))
mod_n ...))]
;; no more require of requires
[(demod id ((id_c phase_c) (id_n phase_n) ...)
((module id (req_m ...) (code_m ...))
(module id_c () (code_c ...))
mod_n ...))
(demod id ((id_n phase_n) ...)
((module id (req_m ...) (code_m ...))
(module id_c () (code_c ...))
mod_n ...))]
;; rearrange stuff
[(demod id () (mod_0 ... (module id (req ...) (code ...)) mod_n ...))
(demod id () ((module id (req ...) (code ...)) mod_0 ... mod_n ...))]
[(demod id () ((module id ((require id_r @ phase_r) req_m ...) (code_m ...)) mod_i ... (module id_r (req_r ...) (code_r ...)) mod_n ...))
(demod id () ((module id ((require id_r @ phase_r) req_m ...) (code_m ...)) (module id_r (req_r ...) (code_r ...)) mod_i ... mod_n ...))]
[(demod id ((id_c phase_c) (id_n phase_n) ...)
((module id (req_m ...) (code_m ...))
mod_i ...
(module id_c (req_c ...) (code_c ...))
mod_n ...))
(demod id ((id_c phase_c) (id_n phase_n) ...)
((module id (req_m ...) (code_m ...))
(module id_c (req_c ...) (code_c ...))
mod_i ...
mod_n ...))]
[(demod id ((id_c phase_c) (id_n phase_n) ...)
((module id (req_m ...) (code_m ...))
(module id_c ((require id_r @ phase_r) req_c ...) (code_c ...))
mod_i ...
(module id_r (req_r ...) (code_r ...))
mod_n ...))
(demod id ((id_c phase_c) (id_n phase_n) ...)
((module id (req_m ...) (code_m ...))
(module id_c ((require id_r @ phase_r) req_c ...) (code_c ...))
(module id_r (req_r ...) (code_r ...))
mod_i ...
mod_n ...))])
;; todo: change (id id) to locations
(module+ test
(test-results))
(define-extended-language
source expanded-core
[var ....
(ref id @ phase)])
#|
forall e:expanded, id:id,
run(compile(e),id) = run(demod(e,id),id)
|#