Source file optimizations.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
open Catala_utils
open Shared_ast
open Ast
module D = Dcalc.Ast
let visitor_map (t : 'm expr -> 'm expr boxed) (e : 'm expr) : 'm expr boxed =
Expr.map ~f:t e
let rec iota_expr (e : 'm expr) : 'm expr boxed =
let m = Marked.get_mark e in
match Marked.unmark e with
| EMatch { e = EInj { e = e'; cons; name = n' }, _; cases; name = n }
when EnumName.equal n n' ->
let e1 = visitor_map iota_expr e' in
let case = visitor_map iota_expr (EnumConstructor.Map.find cons cases) in
Expr.eapp case [e1] m
| EMatch { e = e'; cases; name = n }
when cases
|> EnumConstructor.Map.mapi (fun i case ->
match Marked.unmark case with
| EInj { cons = i'; name = n'; _ } ->
EnumConstructor.equal i i' && EnumName.equal n n'
| _ -> false)
|> EnumConstructor.Map.for_all (fun _ b -> b) ->
visitor_map iota_expr e'
| _ -> visitor_map iota_expr e
let rec beta_expr (e : 'm expr) : 'm expr boxed =
let m = Marked.get_mark e in
match Marked.unmark e with
| EApp { f = e1; args } ->
Expr.Box.app1n (beta_expr e1) (List.map beta_expr args)
(fun e1 args ->
match Marked.unmark e1 with
| EAbs { binder; _ } -> Marked.unmark (Expr.subst binder args)
| _ -> EApp { f = e1; args })
m
| _ -> visitor_map beta_expr e
let iota_optimizations (p : 'm program) : 'm program =
let new_code_items =
Scope.map_exprs ~f:iota_expr ~varf:(fun v -> v) p.code_items
in
{ p with code_items = Bindlib.unbox new_code_items }
let _beta_optimizations (p : 'm program) : 'm program =
let new_code_items =
Scope.map_exprs ~f:beta_expr ~varf:(fun v -> v) p.code_items
in
{ p with code_items = Bindlib.unbox new_code_items }
let rec peephole_expr (e : 'm expr) : 'm expr boxed =
let m = Marked.get_mark e in
match Marked.unmark e with
| EIfThenElse { cond; etrue; efalse } ->
Expr.Box.app3 (peephole_expr cond) (peephole_expr etrue)
(peephole_expr efalse)
(fun cond etrue efalse ->
match Marked.unmark cond with
| ELit (LBool true)
| EApp { f = EOp { op = Log _; _ }, _; args = [(ELit (LBool true), _)] }
->
Marked.unmark etrue
| ELit (LBool false)
| EApp
{ f = EOp { op = Log _; _ }, _; args = [(ELit (LBool false), _)] }
->
Marked.unmark efalse
| _ -> EIfThenElse { cond; etrue; efalse })
m
| ECatch { body; exn; handler } ->
Expr.Box.app2 (peephole_expr body) (peephole_expr handler)
(fun body handler ->
match Marked.unmark body, Marked.unmark handler with
| ERaise exn', ERaise exn'' when exn' = exn && exn = exn'' -> ERaise exn
| ERaise exn', _ when exn' = exn -> Marked.unmark handler
| _, ERaise exn' when exn' = exn -> Marked.unmark body
| _ -> ECatch { body; exn; handler })
m
| _ -> visitor_map peephole_expr e
let peephole_optimizations (p : 'm program) : 'm program =
let new_code_items =
Scope.map_exprs ~f:peephole_expr ~varf:(fun v -> v) p.code_items
in
{ p with code_items = Bindlib.unbox new_code_items }
let optimize_program (p : 'm program) : untyped program =
p |> iota_optimizations |> peephole_optimizations |> Program.untype