Source file shape_reduce.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
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
open Shape
module MB = Misc.Maybe_bounded
type result =
| Resolved of Uid.t
| Resolved_alias of Uid.t * result
| Unresolved of t
| Approximated of Uid.t option
| Internal_error_missing_uid
let rec print_result fmt result =
match result with
| Resolved uid ->
Format.fprintf fmt "@[Resolved: %a@]@;" Uid.print uid
| Resolved_alias (uid, r) ->
Format.fprintf fmt "@[Alias: %a -> %a@]@;"
Uid.print uid print_result r
| Unresolved shape ->
Format.fprintf fmt "@[Unresolved: %a@]@;" print shape
| Approximated (Some uid) ->
Format.fprintf fmt "@[Approximated: %a@]@;" Uid.print uid
| Approximated None ->
Format.fprintf fmt "@[Approximated: No uid@]@;"
| Internal_error_missing_uid ->
Format.fprintf fmt "@[Missing uid@]@;"
module Diagnostics = struct
type diagnostics =
{ mutable reduction_steps : int;
mutable computation_unit_lookups : int;
mutable cms_files_loaded : int;
mutable cms_files_cached : int;
mutable cms_files_missing : string list;
mutable cms_files_unreadable : string list
}
type t = diagnostics option
let no_diagnostics = None
let create_diagnostics () =
Some
{ reduction_steps = 0;
computation_unit_lookups = 0;
cms_files_loaded = 0;
cms_files_cached = 0;
cms_files_missing = [];
cms_files_unreadable = []
}
let count_reduction_step d =
match d with
| None -> ()
| Some d -> d.reduction_steps <- d.reduction_steps + 1
let count_computation_unit_lookup d =
match d with
| None -> ()
| Some d -> d.computation_unit_lookups <- d.computation_unit_lookups + 1
let reduction_steps d = match d with None -> 0 | Some d -> d.reduction_steps
let computation_unit_lookups d =
match d with None -> 0 | Some d -> d.computation_unit_lookups
let count_cms_file_loaded d =
match d with
| None -> ()
| Some d -> d.cms_files_loaded <- d.cms_files_loaded + 1
let cms_files_loaded d =
match d with None -> 0 | Some d -> d.cms_files_loaded
let count_cms_file_cached d =
match d with
| None -> ()
| Some d -> d.cms_files_cached <- d.cms_files_cached + 1
let cms_files_cached d =
match d with None -> 0 | Some d -> d.cms_files_cached
let add_cms_file_missing d filename =
match d with
| None -> ()
| Some d -> d.cms_files_missing <- filename :: d.cms_files_missing
let cms_files_missing d =
match d with None -> [] | Some d -> List.rev d.cms_files_missing
let add_cms_file_unreadable d filename =
match d with
| None -> ()
| Some d -> d.cms_files_unreadable <- filename :: d.cms_files_unreadable
let cms_files_unreadable d =
match d with None -> [] | Some d -> List.rev d.cms_files_unreadable
end
let find_shape env id =
let namespace = Shape.Sig_component_kind.Module in
Env.shape_of_path ~namespace env (Pident id)
module Make(Params : sig
val fuel : unit -> MB.t
val projection_rules_for_merlin_enabled : bool
val fuel_for_compilation_units : unit -> MB.t
val max_shape_reduce_steps_per_variable : unit -> MB.t
val max_compilation_unit_depth : unit -> MB.t
val read_unit_shape :
diagnostics:Diagnostics.t -> unit_name:string -> t option
end) = struct
type nf = { uid: Uid.t option; desc: nf_desc; approximated: bool }
and nf_desc =
| NVar of var
| NApp of nf * nf
| NAbs of local_env * var * t * delayed_nf
| NStruct of delayed_nf Item.Map.t
| NAlias of delayed_nf
| NProj of nf * Item.t
| NLeaf
| NComp_unit of string
| NError of string
| NMu of nf
| NRec_var of Shape.DeBruijn_index.t
| NMutrec of nf Ident.Map.t
| NProj_decl of nf * Ident.t
| NConstr of Ident.t * nf list
| NTuple of nf list
| NUnboxed_tuple of nf list
| NPredef of Predef.t * nf list
| NArrow
| NPoly_variant of nf poly_variant_constructors
| NVariant of (delayed_nf * Layout.t) complex_constructors
| NVariant_unboxed of
{ name : string;
variant_uid : Uid.t option;
arg_name : string option;
arg_uid : Uid.t option;
arg_shape : delayed_nf;
arg_layout : Layout.t
}
| NRecord of
{ fields : (string * Uid.t option * delayed_nf * Layout.t) list;
kind : record_kind
}
| NUnknown_type
| NAt_layout of nf * Layout.t
and delayed_nf = Thunk of local_env * t
and local_env =
{ subst: delayed_nf option Ident.Map.t;
depth: int }
let approx_nf nf = { nf with approximated = true }
let rec equal_local_env t1 t2 =
t1.depth = t2.depth &&
Ident.Map.equal (Option.equal equal_delayed_nf) t1.subst t2.subst
and equal_delayed_nf t1 t2 =
match t1, t2 with
| Thunk (l1, t1), Thunk (l2, t2) ->
if equal t1 t2 then equal_local_env l1 l2
else false
and equal_nf_desc d1 d2 =
match d1, d2 with
| NVar v1, NVar v2 -> Ident.equal v1 v2
| NAbs (l1, v1, t1, nf1), NAbs (l2, v2, t2, nf2) ->
if not (Ident.equal v1 v2) then false
else if not (equal t1 t2) then false
else if not (equal_delayed_nf nf1 nf2) then false
else equal_local_env l1 l2
| NApp (v1, t1), NApp (v2, t2) ->
if equal_nf v1 v2 then equal_nf t1 t2
else false
| NLeaf, NLeaf -> true
| NStruct t1, NStruct t2 ->
Item.Map.equal equal_delayed_nf t1 t2
| NProj (t1, i1), NProj (t2, i2) ->
if Item.compare i1 i2 <> 0 then false
else equal_nf t1 t2
| NComp_unit c1, NComp_unit c2 -> String.equal c1 c2
| NAlias a1, NAlias a2 -> equal_delayed_nf a1 a2
| NError e1, NError e2 -> String.equal e1 e2
| NMu (nf1), NMu (nf2) -> equal_nf nf1 nf2
| NRec_var i1, NRec_var i2 -> DeBruijn_index.equal i1 i2
| NMutrec defs1, NMutrec defs2 ->
Ident.Map.equal equal_nf defs1 defs2
| NProj_decl (nf1, id1), NProj_decl (nf2, id2) ->
Ident.equal id1 id2 && equal_nf nf1 nf2
| NConstr (id1, args1), NConstr (id2, args2) ->
Ident.equal id1 id2 && List.equal equal_nf args1 args2
| NTuple args1, NTuple args2 ->
List.equal equal_nf args1 args2
| NUnboxed_tuple args1, NUnboxed_tuple args2 ->
List.equal equal_nf args1 args2
| NPredef (p1, args1), NPredef (p2, args2) ->
Predef.equal p1 p2 && List.equal equal_nf args1 args2
| NArrow, NArrow -> true
| NPoly_variant constrs1, NPoly_variant constrs2 ->
let equal_pv_constructor c1 c2 =
String.equal c1.pv_constr_name c2.pv_constr_name &&
List.equal equal_nf c1.pv_constr_args c2.pv_constr_args
in
List.equal equal_pv_constructor constrs1 constrs2
| NVariant cc1, NVariant cc2 ->
List.equal
(Shape.equal_complex_constructor
(fun (dnf1, ly1) (dnf2, ly2) ->
Layout.equal ly1 ly2 && equal_delayed_nf dnf1 dnf2))
cc1 cc2
| NVariant_unboxed { name = n1; variant_uid = vu1; arg_name = an1;
arg_uid = au1; arg_shape = as1; arg_layout = al1 },
NVariant_unboxed { name = n2; variant_uid = vu2; arg_name = an2;
arg_uid = au2; arg_shape = as2; arg_layout = al2 } ->
String.equal n1 n2 &&
Option.equal Uid.equal vu1 vu2 &&
Option.equal String.equal an1 an2 &&
Option.equal Uid.equal au1 au2 &&
Layout.equal al1 al2 &&
equal_delayed_nf as1 as2
| NRecord { fields = f1; kind = k1 }, NRecord { fields = f2; kind = k2 } ->
Shape.equal_record_kind k1 k2 &&
List.equal
(fun (name1, uid1, dnf1, ly1) (name2, uid2, dnf2, ly2) ->
String.equal name1 name2 &&
Option.equal Shape.Uid.equal uid1 uid2 &&
Layout.equal ly1 ly2 &&
equal_delayed_nf dnf1 dnf2)
f1 f2
| NUnknown_type, NUnknown_type -> true
| NAt_layout (nf1, layout1), NAt_layout (nf2, layout2) ->
equal_nf nf1 nf2 && Layout.equal layout1 layout2
| ( ( NVar _ | NLeaf | NApp _ | NAbs _ | NStruct _ | NProj _ | NComp_unit _
| NAlias _ | NError _ | NConstr _ | NTuple _ | NUnboxed_tuple _
| NPredef _ | NArrow | NPoly_variant _ | NVariant _
| NVariant_unboxed _ | NRecord _ | NMutrec _ | NProj_decl _ | NMu _
| NRec_var _ | NUnknown_type | NAt_layout _ ), _ ) -> false
and equal_nf t1 t2 =
if not (Option.equal Uid.equal t1.uid t2.uid) then false
else equal_nf_desc t1.desc t2.desc
module ReduceMemoTable = Hashtbl.Make(struct
type nonrec t = local_env * t
let hash t = Hashtbl.hash t
let equal (env1, t1) (env2, t2) =
if equal t1 t2 then equal_local_env env1 env2
else false
end)
module ReadBackMemoTable = Hashtbl.Make(struct
type nonrec t = nf
let hash t = Hashtbl.hash t
let equal a b = equal_nf a b
end)
let in_reduce_memo_table memo_table memo_key f arg =
match ReduceMemoTable.find memo_table memo_key with
| res -> res
| exception Not_found ->
let res = f arg in
ReduceMemoTable.replace memo_table memo_key res;
res
let in_read_back_memo_table memo_table memo_key f arg =
match ReadBackMemoTable.find memo_table memo_key with
| res -> res
| exception Not_found ->
let res = f arg in
ReadBackMemoTable.replace memo_table memo_key res;
res
type env = {
fuel: MB.t;
fuel_for_compilation_units: MB.t;
max_steps_per_variable: MB.t;
diagnostics: Diagnostics.t;
global_env: Env.t;
local_env: local_env;
reduce_memo_table: nf ReduceMemoTable.t;
read_back_memo_table: t ReadBackMemoTable.t;
}
let bind env var shape =
let subst = Ident.Map.add var shape env.local_env.subst in
{ env with local_env = { env.local_env with subst } }
let rec reduce_ env t =
Diagnostics.count_reduction_step env.diagnostics;
let local_env = env.local_env in
let memo_key = (local_env, t) in
in_reduce_memo_table env.reduce_memo_table memo_key (reduce__ env) t
and force env (Thunk (local_env, t)) =
reduce_ { env with local_env } t
and reduce__
({fuel; fuel_for_compilation_units; max_steps_per_variable;
global_env; local_env; _} as env) (t : t) =
let reduce env t = reduce_ env t in
let reduce_with_increased_depth env t =
let local_env = { env.local_env with depth = env.local_env.depth + 1 } in
reduce_ { env with local_env } t
in
let delay_reduce env t = Thunk (env.local_env, t) in
let return desc = { uid = t.uid; desc; approximated = t.approximated } in
let rec force_aliases nf = match nf.desc with
| NAlias delayed_nf ->
let nf = force env delayed_nf in
force_aliases nf
| _ -> nf
in
let reset_uid_if_new_binding t' =
match t.uid with
| None -> t'
| Some _ as uid -> { t' with uid }
in
let set_uid_if_none uid t =
match t.uid with
| None -> { t with uid = uid }
| Some _ -> t
in
let delayed_nf_set_uid (Thunk (l, t) as dnf) uid =
match uid with
| None -> dnf
| Some uid -> Thunk (l, Shape.set_uid_if_none t uid)
in
if MB.is_depleted fuel
then approx_nf (return (NError "NoFuelLeft"))
else if MB.is_depleted max_steps_per_variable
then return NUnknown_type
else (
MB.decr max_steps_per_variable;
match t.desc with
| Comp_unit unit_name ->
let reduce_max_depth = Params.max_compilation_unit_depth () in
if MB.is_depleted fuel_for_compilation_units
|| MB.is_out_of_bounds env.local_env.depth reduce_max_depth
then
return (NComp_unit unit_name)
else (
MB.decr fuel_for_compilation_units;
Diagnostics.count_computation_unit_lookup env.diagnostics;
begin match
Params.read_unit_shape ~diagnostics:env.diagnostics ~unit_name
with
| Some t ->
reduce_with_increased_depth env t
| None -> return (NComp_unit unit_name)
end)
| App(f, arg) ->
let f = reduce env f |> force_aliases in
begin match f.desc with
| NAbs(clos_env, var, body, _body_nf) ->
let arg = delay_reduce env arg in
let env = bind { env with local_env = clos_env } var (Some arg) in
reduce env body |> reset_uid_if_new_binding
| _ ->
let arg = reduce env arg in
return (NApp(f, arg))
end
| Proj(str, item) ->
let str = reduce env str |> force_aliases in
let nored () = return (NProj(str, item)) in
begin match str.desc with
| NStruct (items) ->
begin match Item.Map.find item items with
| exception Not_found -> nored ()
| nf -> force env nf |> reset_uid_if_new_binding
end
| NVariant constrs when Params.projection_rules_for_merlin_enabled &&
Shape.Item.is_constructor item ->
let name = Shape.Item.name item in
(match List.find_opt (fun c -> String.equal c.name name)
constrs with
| Some { name = _; constr_uid; kind = _; args } ->
let has_unnamed_field =
List.exists (fun { field_name; _ } ->
Option.is_none field_name) args in
if has_unnamed_field then
let tuple_args = List.map (fun { field_name = _; field_uid;
field_value = sh, _ } ->
let sh = delayed_nf_set_uid sh field_uid in
force env sh
) args in
{ desc = NTuple tuple_args; uid = constr_uid;
approximated = false }
else
let fields = List.map (fun { field_name; field_uid;
field_value = sh, layout } ->
let name = Option.get field_name in
let sh = delayed_nf_set_uid sh field_uid in
(name, field_uid, sh, layout)
) args in
{ desc = NRecord { fields; kind = Record_boxed };
uid = constr_uid; approximated = false }
| None -> nored())
| NVariant_unboxed { name; variant_uid; arg_name; arg_uid;
arg_shape; arg_layout }
when Params.projection_rules_for_merlin_enabled &&
Shape.Item.is_constructor item ->
let item_name = Shape.Item.name item in
if String.equal name item_name then
match arg_name with
| Some arg_name ->
let sh = delayed_nf_set_uid arg_shape arg_uid in
let fields = [(arg_name, arg_uid, sh, arg_layout)] in
{ desc = NRecord { fields; kind = Record_boxed };
uid = variant_uid; approximated = false }
| None ->
let sh = delayed_nf_set_uid arg_shape arg_uid in
let sh = force env sh in
{ desc = NUnboxed_tuple [sh]; uid = variant_uid;
approximated = false }
else nored()
| NRecord { fields; kind = _ }
when Params.projection_rules_for_merlin_enabled &&
(Shape.Item.is_label item || Shape.Item.is_unboxed_label item) ->
let field_name = Shape.Item.name item in
(match List.find_opt (fun (name, _, _, _) ->
String.equal name field_name) fields with
| Some (_, field_uid, field_shape, _) ->
force env field_shape |> set_uid_if_none field_uid
| None -> nored())
| _ ->
nored ()
end
| Abs(var, body) ->
let body_nf = delay_reduce (bind env var None) body in
return (NAbs(local_env, var, body, body_nf))
| Var id ->
begin match Ident.Map.find id local_env.subst with
| None -> return (NVar id)
| Some def ->
begin match force env def with
| { uid = Some _; _ } as nf -> nf
| { uid = None; _ } as nf -> { nf with uid = t.uid }
end
| exception Not_found ->
match find_shape global_env id with
| exception Not_found -> return (NVar id)
| res when res = t -> return (NVar id)
| res ->
MB.decr fuel;
reduce env res
end
| Leaf -> return NLeaf
| Mu t_body -> return (NMu (reduce env t_body))
| Rec_var n -> return (NRec_var n)
| Struct m ->
let mnf = Item.Map.map (delay_reduce env) m in
return (NStruct mnf)
| Alias t -> return (NAlias (delay_reduce env t))
| Error s -> approx_nf (return (NError s))
| Mutrec defs ->
let dnfs = Ident.Map.map (reduce env) defs in
return (NMutrec dnfs)
| Proj_decl (t, id) ->
let nf = reduce env t in
return (NProj_decl (nf, id))
| Constr (id, args) ->
let nfs = List.map (reduce env) args in
return (NConstr (id, nfs))
| Tuple args ->
let nfs = List.map (reduce env) args in
return (NTuple nfs)
| Unboxed_tuple args ->
let nfs = List.map (reduce env) args in
return (NUnboxed_tuple nfs)
| Predef (p, args) ->
let nfs = List.map (reduce env) args in
return (NPredef (p, nfs))
| Arrow ->
return NArrow
| Poly_variant constrs ->
let dnf_constrs =
poly_variant_constructors_map (reduce env) constrs
in
return (NPoly_variant dnf_constrs)
| Variant constructors ->
let dnf_constructors =
complex_constructors_map (fun (t, ly) ->
(delay_reduce env t, ly)) constructors
in
return (NVariant dnf_constructors)
| Variant_unboxed { name; variant_uid; arg_name; arg_uid; arg_shape;
arg_layout } ->
let dnf_arg_shape = delay_reduce env arg_shape in
return (NVariant_unboxed { name; variant_uid; arg_name; arg_uid;
arg_shape = dnf_arg_shape; arg_layout })
| Record { fields; kind } ->
let dnf_fields =
List.map (fun (name, uid_opt, t, ly) ->
(name, uid_opt, delay_reduce env t, ly)) fields
in
return (NRecord { fields = dnf_fields; kind })
| Unknown_type ->
return NUnknown_type
| At_layout (shape, layout) ->
let nf = reduce env shape in
return (NAt_layout (nf, layout))
)
and read_back env (nf : nf) : t =
in_read_back_memo_table env.read_back_memo_table nf (read_back_ env) nf
and read_back_ env (nf : nf) : t =
read_back_desc ~uid:nf.uid env nf.desc
and read_back_desc ~uid env desc =
let read_back nf = read_back env nf in
let read_back_force dnf = read_back (force env dnf) in
match desc with
| NVar v ->
var' uid v
| NApp (nft, nfu) ->
let f = read_back nft in
let arg = read_back nfu in
app ?uid f ~arg
| NAbs (_env, x, _t, nf) ->
let body = read_back_force nf in
abs ?uid x body
| NStruct nstr ->
let map = Item.Map.map read_back_force nstr in
str ?uid map
| NProj (nf, item) ->
let t = read_back nf in
proj ?uid t item
| NLeaf -> leaf' uid
| NComp_unit s -> comp_unit ?uid s
| NAlias nf -> alias ?uid (read_back_force nf)
| NError t -> error ?uid t
| NMu (t_body) ->
mu ?uid (read_back t_body)
| NRec_var n ->
rec_var ?uid n
| NMutrec defs ->
let t_defs = Ident.Map.map read_back defs in
mutrec ?uid t_defs
| NProj_decl (nf, id) ->
let t = read_back nf in
proj_decl ?uid t id
| NConstr (id, args) ->
let t_args = List.map read_back args in
constr ?uid id t_args
| NTuple args ->
let t_args = List.map read_back args in
tuple ?uid t_args
| NUnboxed_tuple args ->
let t_args = List.map read_back args in
unboxed_tuple ?uid t_args
| NPredef (p, args) ->
let t_args = List.map read_back args in
predef ?uid p t_args
| NArrow ->
arrow ?uid ()
| NPoly_variant constrs ->
let t_constrs = poly_variant_constructors_map read_back constrs in
poly_variant ?uid t_constrs
| NVariant constructors ->
let t_constructors =
complex_constructors_map
(fun (dnf, ly) -> (read_back_force dnf, ly))
constructors
in
variant ?uid t_constructors
| NVariant_unboxed { name; variant_uid; arg_name; arg_uid;
arg_shape; arg_layout } ->
let t_arg_shape = read_back_force arg_shape in
variant_unboxed ?uid ~variant_uid ~arg_uid name arg_name
t_arg_shape arg_layout
| NRecord { fields; kind } ->
let t_fields = List.map (fun (name, uid_opt, dnf, ly) ->
(name, uid_opt, read_back_force dnf, ly)) fields
in
record ?uid kind t_fields
| NUnknown_type ->
unknown_type ?uid ()
| NAt_layout (nf, layout) ->
let shape = read_back nf in
at_layout ?uid shape layout
let reduce_memo_table = ReduceMemoTable.create 42
let read_back_memo_table = ReadBackMemoTable.create 42
let reduce ?(diagnostics = Diagnostics.no_diagnostics) global_env t =
let fuel = Params.fuel () in
MB.incr fuel;
let fuel_for_compilation_units =
Params.fuel_for_compilation_units ()
in
let max_steps_per_variable =
Params.max_shape_reduce_steps_per_variable ()
in
let local_env = { subst = Ident.Map.empty; depth = 0 } in
let env = {
fuel;
fuel_for_compilation_units;
max_steps_per_variable;
global_env;
diagnostics;
reduce_memo_table = reduce_memo_table;
read_back_memo_table = read_back_memo_table;
local_env;
} in
reduce_ env t |> read_back env
let rec is_stuck_on_comp_unit (nf : nf) =
match nf.desc with
| NVar _ ->
false
| NApp (nf, _) | NProj (nf, _) -> is_stuck_on_comp_unit nf
| NStruct _ | NAbs _ -> false
| NAlias _ -> false
| NComp_unit _ -> true
| NError _ -> false
| NLeaf -> false
| NMu _ -> false
| NRec_var _ -> false
| NMutrec _ | NProj_decl _ | NConstr _ | NTuple _ | NUnboxed_tuple _
| NPredef _ | NArrow | NPoly_variant _ | NVariant _ | NVariant_unboxed _
| NRecord _ | NUnknown_type | NAt_layout _ -> false
let rec reduce_aliases_for_uid env (nf : nf) =
match nf with
| { uid = Some uid; desc = NAlias dnf; approximated = false; _ } ->
let result = reduce_aliases_for_uid env (force env dnf) in
Resolved_alias (uid, result)
| { uid = Some uid; approximated = false; _ } -> Resolved uid
| { uid; approximated = true } -> Approximated uid
| { uid = None; approximated = false; _ } ->
Internal_error_missing_uid
let reduce_for_uid global_env t =
let fuel = Params.fuel () in
MB.incr fuel;
let local_env = { subst = Ident.Map.empty; depth = 0 } in
let env = {
fuel;
fuel_for_compilation_units = Params.fuel_for_compilation_units ();
max_steps_per_variable = Params.max_shape_reduce_steps_per_variable ();
global_env;
diagnostics = Diagnostics.no_diagnostics;
reduce_memo_table = reduce_memo_table;
read_back_memo_table = read_back_memo_table;
local_env;
} in
let nf = reduce_ env t in
if is_stuck_on_comp_unit nf then
Unresolved (read_back env nf)
else
reduce_aliases_for_uid env nf
end
module Local_reduce =
Make(struct
let fuel () = MB.of_int 10
let fuel_for_compilation_units () = MB.Unbounded
let max_shape_reduce_steps_per_variable () = MB.Unbounded
let max_compilation_unit_depth () = MB.Unbounded
let projection_rules_for_merlin_enabled = true
let read_unit_shape ~diagnostics:_ ~unit_name:_ = None
end)
let local_reduce = Local_reduce.reduce
let local_reduce_for_uid = Local_reduce.reduce_for_uid