/
sharedvars.arc
112 lines (109 loc) · 3.4 KB
/
sharedvars.arc
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
; sharedvars.arc
; by AmkG
; Shared variables transformation:
;
; (fn (x)
; (list
; (fn () x)
; (fn (v) (set x v))))
;
; =>
;
; (fn (x)
; ((fn (shared)
; (list
; (fn () (%sharedvar-read shared))
; (fn (v) (%sharedvar-write shared v))))
; (%sharedvar x)))
;
; Based on an idea by stefano
(def sharedvars-convert (ast)
(with (sc [map sharedvars-convert _]
; flip the arguments to make-lam
make-fn (fn (x y) (make-lam y x))
transform nil
transform-shared nil)
; creates a function whose shared variables
; have been transformed to explicit objects
(= transform
(fn (params subx shared)
(with (lookup (table))
(each v shared
(= lookup.v (new-var 'shared)))
; fn ,params
(make-fn params
; apply
(list:make-app
(cons
; fn shared
(make-fn (map [lookup _] shared)
; ,@body
(transform-shared subx lookup))
; (map [%sharedvar _] shared)
(map
[make-prim (list:make-ref () _) '%sharedvar]
shared) ))))))
; transform references to shared variables
(= transform-shared
(fn (subx lookup)
(mapeach ast subx
(if
((orf alit aquote) ast)
ast
(aref ast)
(aif (lookup ast!var)
(make-prim
(list:make-ref () it)
'%sharedvar-read)
ast)
(aset ast)
(aif (lookup ast!var)
(make-prim
(cons (make-ref () it)
; we depend on 'xe to ensure that
; 'set only has a singleton list in
; its subx
(transform-shared ast!subx lookup))
'%sharedvar-write)
(make-set (transform-shared ast!subx lookup) ast!var))
(aquote ast)
ast
; else
(do
(= ast!subx (transform-shared ast!subx lookup))
ast)))))
(if
((orf alit aref aquote) ast)
ast
(aset ast)
(make-set (sc ast!subx) ast!var)
(acnd ast)
(make-cnd (sc ast!subx))
(aprim ast)
(make-prim (sc ast!subx) ast!op)
(anapp ast)
(make-app (sc ast!subx))
(alam ast)
(with (params ast!params
; TODO: shared should only have local variables that are:
; 1. assigned anywhere, and
; 2. are used in more than one sub-lambda
; Note however that we then have to handle assignments
; to locals in the codegen
shared (lv-set ast)
proper-params)
(= proper-params (properify params))
(if (some [some _ proper-params] shared)
(transform params
(sc ast!subx)
(keep [some _ proper-params] shared))
(make-lam (sc ast!subx) params)))
(aseq ast)
(make-seq (sc ast!subx)))))
(def sharedvars-convert-assert (ast)
(let rv (sharedvars-convert ast)
(awhen (lv-set rv)
(ppr-sexp:source rv)
(err:tostring:pr
"sharedvar-convert assertion failed: local variables set - " it))
rv))