package libsail

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

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