Source file jib_visitor.ml
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
open Jib
include Visitor
class type common_visitor = object
method vid : Ast.id -> Ast.id option
method vname : name -> name option
method vctyp : ctyp -> ctyp visit_action
end
class type jib_visitor = object
inherit common_visitor
method vcval : cval -> cval visit_action
method vclexp : clexp -> clexp visit_action
method vinstrs : instr list -> instr list visit_action
method vinstr : instr -> instr visit_action
method vcdef : cdef -> cdef visit_action
end
let visit_id vis id = Option.value ~default:id (vis#vid id)
let visit_name vis name = Option.value ~default:name (vis#vname name)
let rec visit_ctyp vis outer_ctyp =
let aux vis no_change =
match no_change with
| CT_lint | CT_fint _ | CT_constant _ | CT_lbits | CT_sbits _ | CT_fbits _ | CT_unit | CT_bool | CT_bit | CT_string
| CT_real | CT_float _ | CT_rounding_mode | CT_memory_writes | CT_poly _ | CT_json | CT_json_key ->
no_change
| CT_tup ctyps ->
let ctyps' = visit_ctyps vis ctyps in
if ctyps == ctyps' then no_change else CT_tup ctyps'
| CT_enum id ->
let id' = visit_id vis id in
if id == id' then no_change else CT_enum id'
| CT_struct (id, ctyps) ->
let id' = visit_id vis id in
let ctyps' = visit_ctyps vis ctyps in
if id == id' && ctyps == ctyps' then no_change else CT_struct (id', ctyps')
| CT_variant (id, ctyps) ->
let id' = visit_id vis id in
let ctyps' = visit_ctyps vis ctyps in
if id == id' && ctyps == ctyps' then no_change else CT_variant (id', ctyps')
| CT_fvector (n, ctyp) ->
let ctyp' = visit_ctyp vis ctyp in
if ctyp == ctyp' then no_change else CT_fvector (n, ctyp')
| CT_vector ctyp ->
let ctyp' = visit_ctyp vis ctyp in
if ctyp == ctyp' then no_change else CT_vector ctyp'
| CT_list ctyp ->
let ctyp' = visit_ctyp vis ctyp in
if ctyp == ctyp' then no_change else CT_list ctyp'
| CT_ref ctyp ->
let ctyp' = visit_ctyp vis ctyp in
if ctyp == ctyp' then no_change else CT_ref ctyp'
in
do_visit vis (vis#vctyp outer_ctyp) aux outer_ctyp
and visit_ctyps vis ctyps = map_no_copy (visit_ctyp vis) ctyps
and visit_binding vis ((id, ctyp) as binding) =
let id' = visit_id vis id in
let ctyp' = visit_ctyp vis ctyp in
if id == id' && ctyp == ctyp' then binding else (id', ctyp')
let rec visit_clexp vis outer_clexp =
let aux vis no_change =
match no_change with
| CL_id (name, ctyp) ->
let name' = visit_name vis name in
let ctyp' = visit_ctyp vis ctyp in
if name == name' && ctyp == ctyp' then no_change else CL_id (name', ctyp')
| CL_rmw (name1, name2, ctyp) ->
let name1' = visit_name vis name1 in
let name2' = visit_name vis name2 in
let ctyp' = visit_ctyp vis ctyp in
if name1 == name1' && name2 == name2' && ctyp == ctyp' then no_change else CL_rmw (name1', name2', ctyp')
| CL_field (clexp, id, ctyp) ->
let clexp' = visit_clexp vis clexp in
let id' = visit_id vis id in
let ctyp' = visit_ctyp vis ctyp in
if clexp == clexp' && id == id' && ctyp == ctyp' then no_change else CL_field (clexp', id', ctyp')
| CL_addr clexp ->
let clexp' = visit_clexp vis clexp in
if clexp == clexp' then no_change else CL_addr clexp'
| CL_tuple (clexp, n) ->
let clexp' = visit_clexp vis clexp in
if clexp == clexp' then no_change else CL_tuple (clexp', n)
| CL_void ctyp ->
let ctyp' = visit_ctyp vis ctyp in
if ctyp == ctyp' then no_change else CL_void ctyp'
in
do_visit vis (vis#vclexp outer_clexp) aux outer_clexp
let visit_creturn vis no_change =
match no_change with
| CR_one clexp ->
let clexp' = visit_clexp vis clexp in
if clexp == clexp' then no_change else CR_one clexp'
| CR_multi clexps ->
let clexps' = map_no_copy (visit_clexp vis) clexps in
if clexps == clexps' then no_change else CR_multi clexps'
let rec visit_cval vis outer_cval =
let aux vis no_change =
match no_change with
| V_id (name, ctyp) ->
let name' = visit_name vis name in
let ctyp' = visit_ctyp vis ctyp in
if name == name' && ctyp == ctyp' then no_change else V_id (name', ctyp')
| V_member (id, ctyp) ->
let ctyp' = visit_ctyp vis ctyp in
if ctyp == ctyp' then no_change else V_member (id, ctyp')
| V_lit (value, ctyp) ->
let ctyp' = visit_ctyp vis ctyp in
if ctyp == ctyp' then no_change else V_lit (value, ctyp')
| V_tuple cvals ->
let cvals' = visit_cvals vis cvals in
if cvals == cvals' then no_change else V_tuple cvals'
| V_struct (fields, ctyp) ->
let fields' = map_no_copy (visit_field vis) fields in
let ctyp' = visit_ctyp vis ctyp in
if fields == fields' && ctyp == ctyp' then no_change else V_struct (fields', ctyp')
| V_ctor_kind (cval, (id, ctyps)) ->
let cval' = visit_cval vis cval in
let id' = visit_id vis id in
let ctyps' = visit_ctyps vis ctyps in
if cval == cval' && id == id' && ctyps == ctyps' then no_change else V_ctor_kind (cval', (id', ctyps'))
| V_ctor_unwrap (cval, (id, ctyps), ctyp) ->
let cval' = visit_cval vis cval in
let id' = visit_id vis id in
let ctyps' = visit_ctyps vis ctyps in
let ctyp' = visit_ctyp vis ctyp in
if cval == cval' && id == id' && ctyps == ctyps' && ctyp == ctyp' then no_change
else V_ctor_unwrap (cval', (id', ctyps'), ctyp')
| V_tuple_member (cval, n, m) ->
let cval' = visit_cval vis cval in
if cval == cval' then no_change else V_tuple_member (cval', n, m)
| V_call (op, cvals) ->
let cvals' = visit_cvals vis cvals in
if cvals == cvals' then no_change else V_call (op, cvals')
| V_field (cval, id, ctyp) ->
let cval' = visit_cval vis cval in
let id' = visit_id vis id in
let ctyp' = visit_ctyp vis ctyp in
if cval == cval' && id == id' && ctyp == ctyp' then no_change else V_field (cval', id', ctyp')
in
do_visit vis (vis#vcval outer_cval) aux outer_cval
and visit_field vis ((id, cval) as field) =
let id' = visit_id vis id in
let cval' = visit_cval vis cval in
if id == id' && cval == cval' then field else (id', cval')
and visit_cvals vis cvals = map_no_copy (visit_cval vis) cvals
let visit_init vis no_change =
match no_change with
| Init_cval cval ->
let cval' = visit_cval vis cval in
if cval == cval' then no_change else Init_cval cval'
| Init_static _ | Init_json_key _ -> no_change
let rec visit_instr vis outer_instr =
let aux vis no_change =
match no_change with
| I_aux (I_decl (ctyp, name), aux) ->
let ctyp' = visit_ctyp vis ctyp in
let name' = visit_name vis name in
if ctyp == ctyp' && name == name' then no_change else I_aux (I_decl (ctyp', name'), aux)
| I_aux (I_init (ctyp, name, init), aux) ->
let ctyp' = visit_ctyp vis ctyp in
let name' = visit_name vis name in
let init' = visit_init vis init in
if ctyp == ctyp' && name == name' && init == init' then no_change else I_aux (I_init (ctyp', name', init'), aux)
| I_aux (I_jump (cval, label), aux) ->
let cval' = visit_cval vis cval in
if cval == cval' then no_change else I_aux (I_jump (cval', label), aux)
| I_aux (I_goto _, _) -> no_change
| I_aux (I_label _, _) -> no_change
| I_aux (I_funcall (creturn, extern, (id, ctyps), cvals), aux) ->
let creturn' = visit_creturn vis creturn in
let extern' =
match extern with
| Call -> extern
| Extern ret_ctyp ->
let ret_ctyp' = visit_ctyp vis ret_ctyp in
if ret_ctyp == ret_ctyp' then extern else Extern ret_ctyp'
in
let id' = visit_id vis id in
let ctyps' = visit_ctyps vis ctyps in
let cvals' = visit_cvals vis cvals in
if creturn == creturn' && extern == extern' && id == id' && ctyps == ctyps' && cvals == cvals' then no_change
else I_aux (I_funcall (creturn', extern', (id', ctyps'), cvals'), aux)
| I_aux (I_copy (clexp, cval), aux) ->
let clexp' = visit_clexp vis clexp in
let cval' = visit_cval vis cval in
if clexp == clexp' && cval == cval' then no_change else I_aux (I_copy (clexp', cval'), aux)
| I_aux (I_clear (ctyp, name), aux) ->
let ctyp' = visit_ctyp vis ctyp in
let name' = visit_name vis name in
if ctyp == ctyp' && name == name' then no_change else I_aux (I_clear (ctyp', name'), aux)
| I_aux (I_undefined ctyp, aux) ->
let ctyp' = visit_ctyp vis ctyp in
if ctyp == ctyp' then no_change else I_aux (I_undefined ctyp', aux)
| I_aux (I_exit _, _) -> no_change
| I_aux (I_end name, aux) ->
let name' = visit_name vis name in
if name == name' then no_change else I_aux (I_end name', aux)
| I_aux (I_comment _, _) -> no_change
| I_aux (I_raw _, _) -> no_change
| I_aux (I_return cval, aux) ->
let cval' = visit_cval vis cval in
if cval == cval' then no_change else I_aux (I_return cval', aux)
| I_aux (I_if (cval, then_instrs, else_instrs), aux) ->
let cval' = visit_cval vis cval in
let then_instrs' = visit_instrs vis then_instrs in
let else_instrs' = visit_instrs vis else_instrs in
if cval == cval' && then_instrs == then_instrs' && else_instrs == else_instrs' then no_change
else I_aux (I_if (cval', then_instrs', else_instrs'), aux)
| I_aux (I_block instrs, aux) ->
let instrs' = visit_instrs vis instrs in
if instrs == instrs' then no_change else I_aux (I_block instrs', aux)
| I_aux (I_try_block instrs, aux) ->
let instrs' = visit_instrs vis instrs in
if instrs == instrs' then no_change else I_aux (I_try_block instrs', aux)
| I_aux (I_throw cval, aux) ->
let cval' = visit_cval vis cval in
if cval == cval' then no_change else I_aux (I_throw cval', aux)
| I_aux (I_reset (ctyp, name), aux) ->
let ctyp' = visit_ctyp vis ctyp in
let name' = visit_name vis name in
if ctyp == ctyp' && name == name' then no_change else I_aux (I_reset (ctyp', name'), aux)
| I_aux (I_reinit (ctyp, name, cval), aux) ->
let ctyp' = visit_ctyp vis ctyp in
let name' = visit_name vis name in
let cval' = visit_cval vis cval in
if ctyp == ctyp' && name == name' && cval == cval' then no_change
else I_aux (I_reinit (ctyp', name', cval'), aux)
in
do_visit vis (vis#vinstr outer_instr) aux outer_instr
and visit_instrs vis outer_instrs =
let aux vis no_change =
match no_change with
| instr :: instrs ->
let instr' = visit_instr vis instr in
let instrs' = visit_instrs vis instrs in
if instr == instr' && instrs == instrs' then no_change else instr' :: instrs'
| [] -> []
in
do_visit vis (vis#vinstrs outer_instrs) aux outer_instrs
and visit_ctype_def vis no_change =
match no_change with
| CTD_enum (id, members) ->
let id' = visit_id vis id in
let members' = map_no_copy (visit_id vis) members in
if id == id' && members == members' then no_change else CTD_enum (id', members')
| CTD_struct (id, tyvars, fields) ->
let id' = visit_id vis id in
let fields' = map_no_copy (visit_binding vis) fields in
if id == id' && fields == fields' then no_change else CTD_struct (id', tyvars, fields')
| CTD_variant (id, tyvars, ctors) ->
let id' = visit_id vis id in
let ctors' = map_no_copy (visit_binding vis) ctors in
if id == id' && ctors == ctors' then no_change else CTD_variant (id', tyvars, ctors')
| CTD_abbrev (id, ctyp) ->
let id' = visit_id vis id in
let ctyp' = visit_ctyp vis ctyp in
if id == id' && ctyp == ctyp' then no_change else CTD_abbrev (id', ctyp')
| CTD_abstract (id, ctyp, init) ->
let id' = visit_id vis id in
let ctyp' = visit_ctyp vis ctyp in
let init' =
match init with
| CTDI_none -> init
| CTDI_instrs instrs ->
let instrs' = map_no_copy (visit_instr vis) instrs in
if instrs == instrs' then init else CTDI_instrs instrs'
in
if id == id' && ctyp == ctyp' && init == init' then no_change else CTD_abstract (id', ctyp', init')
let visit_cdef vis outer_cdef =
let aux vis (CDEF_aux (aux, def_annot) as no_change) =
match aux with
| CDEF_register (id, ctyp, instrs) ->
let id' = visit_name vis id in
let ctyp' = visit_ctyp vis ctyp in
let instrs' = visit_instrs vis instrs in
if id == id' && ctyp == ctyp' && instrs == instrs' then no_change
else CDEF_aux (CDEF_register (id', ctyp', instrs'), def_annot)
| CDEF_type ctd ->
let ctd' = visit_ctype_def vis ctd in
if ctd == ctd' then no_change else CDEF_aux (CDEF_type ctd', def_annot)
| CDEF_let (n, bindings, instrs) ->
let bindings' = map_no_copy (visit_binding vis) bindings in
let instrs' = visit_instrs vis instrs in
if bindings == bindings' && instrs == instrs' then no_change
else CDEF_aux (CDEF_let (n, bindings', instrs'), def_annot)
| CDEF_val (id, tyvars, ctyps, ctyp, extern) ->
let id' = visit_id vis id in
let ctyps' = visit_ctyps vis ctyps in
let ctyp' = visit_ctyp vis ctyp in
if id == id' && ctyps == ctyps' && ctyp == ctyp' then no_change
else CDEF_aux (CDEF_val (id', tyvars, ctyps', ctyp', extern), def_annot)
| CDEF_fundef (id, ret_id, params, instrs) ->
let id' = visit_id vis id in
let ret_id' =
match ret_id with
| Return_via name ->
let name' = visit_name vis name in
if name == name' then ret_id else Return_via name'
| Return_plain -> ret_id
in
let params' = map_no_copy (visit_name vis) params in
let instrs' = visit_instrs vis instrs in
if id == id' && ret_id == ret_id' && params == params' && instrs == instrs' then no_change
else CDEF_aux (CDEF_fundef (id', ret_id', params', instrs'), def_annot)
| CDEF_startup (id, instrs) ->
let id' = visit_id vis id in
let instrs' = visit_instrs vis instrs in
if id == id' && instrs == instrs' then no_change else CDEF_aux (CDEF_startup (id', instrs'), def_annot)
| CDEF_finish (id, instrs) ->
let id' = visit_id vis id in
let instrs' = visit_instrs vis instrs in
if id == id' && instrs == instrs' then no_change else CDEF_aux (CDEF_finish (id', instrs'), def_annot)
| CDEF_pragma (_, _) -> no_change
in
do_visit vis (vis#vcdef outer_cdef) aux outer_cdef
let visit_cdefs vis cdefs = map_no_copy (visit_cdef vis) cdefs
class empty_jib_visitor : jib_visitor =
object
method vid _ = None
method vname _ = None
method vctyp _ = DoChildren
method vcval _ = DoChildren
method vclexp _ = DoChildren
method vinstrs _ = DoChildren
method vinstr _ = DoChildren
method vcdef _ = DoChildren
end