2019-11-02 16:56:05 -05:00
|
|
|
open Mini_c
|
|
|
|
open Trace
|
|
|
|
|
2019-11-13 13:43:03 -06:00
|
|
|
(* Overly conservative purity test: ok to treat pure things as impure,
|
2019-11-02 16:56:05 -05:00
|
|
|
must not treat impure things as pure. *)
|
2019-11-13 13:43:03 -06:00
|
|
|
|
|
|
|
(* true if the name names a pure constant -- i.e. if uses will be pure
|
|
|
|
assuming arguments are pure *)
|
|
|
|
let is_pure_constant : string -> bool =
|
|
|
|
function
|
|
|
|
| "CAR"
|
|
|
|
| "CDR"
|
|
|
|
| "PAIR"
|
|
|
|
-> true
|
|
|
|
(* TODO... *)
|
2019-11-02 16:56:05 -05:00
|
|
|
| _ -> false
|
|
|
|
|
2019-11-13 13:43:03 -06:00
|
|
|
let rec is_pure : expression -> bool = fun e ->
|
|
|
|
match e.content with
|
|
|
|
| E_literal _
|
|
|
|
| E_closure _
|
|
|
|
| E_skip
|
|
|
|
| E_variable _
|
|
|
|
| E_make_empty_map _
|
2019-11-04 17:01:39 -06:00
|
|
|
| E_make_empty_big_map _
|
2019-11-13 13:43:03 -06:00
|
|
|
| E_make_empty_list _
|
|
|
|
| E_make_empty_set _
|
|
|
|
| E_make_none _
|
|
|
|
-> true
|
|
|
|
|
|
|
|
| E_if_bool (cond, bt, bf)
|
|
|
|
| E_if_none (cond, bt, (_, bf))
|
|
|
|
| E_if_cons (cond, bt, (_, bf))
|
|
|
|
| E_if_left (cond, (_, bt), (_, bf))
|
|
|
|
-> List.for_all is_pure [ cond ; bt ; bf ]
|
|
|
|
|
|
|
|
| E_let_in (_, e1, e2)
|
|
|
|
| E_sequence (e1, e2)
|
|
|
|
-> List.for_all is_pure [ e1 ; e2 ]
|
|
|
|
|
|
|
|
| E_constant (c, args)
|
|
|
|
-> is_pure_constant c && List.for_all is_pure args
|
|
|
|
|
|
|
|
(* I'm not sure about these. Maybe can be tested better? *)
|
|
|
|
| E_application _
|
|
|
|
| E_iterator _
|
|
|
|
| E_fold _
|
|
|
|
-> false
|
|
|
|
|
|
|
|
(* Could be pure, but, divergence is an effect, so halting problem
|
|
|
|
is near... *)
|
|
|
|
| E_while _ -> false
|
|
|
|
|
|
|
|
(* definitely not pure *)
|
|
|
|
| E_assignment _ -> false
|
|
|
|
|
|
|
|
|
|
|
|
(* Eliminate dead `let` with pure rhs *)
|
|
|
|
|
|
|
|
let rec elim_dead_code : expression -> expression result = fun e ->
|
2019-11-02 16:56:05 -05:00
|
|
|
let changed = ref false in (* ugh *)
|
|
|
|
let mapper : Helpers.mapper = fun e ->
|
|
|
|
match e.content with
|
|
|
|
| E_let_in ((x, _), e1, e2) when is_pure e1 ->
|
|
|
|
let fvs = Free_variables.expression [] e2 in
|
|
|
|
if Free_variables.mem x fvs
|
|
|
|
then ok e
|
|
|
|
else
|
|
|
|
(* pure e1 is not used, eliminate! *)
|
|
|
|
(changed := true ; ok e2)
|
|
|
|
| _ -> ok e in
|
|
|
|
let%bind e = Helpers.map_expression mapper e in
|
|
|
|
if !changed
|
2019-11-13 13:43:03 -06:00
|
|
|
then elim_dead_code e
|
2019-11-02 16:56:05 -05:00
|
|
|
else ok e
|
|
|
|
|
|
|
|
let all_expression : expression -> expression result =
|
2019-11-13 13:43:03 -06:00
|
|
|
elim_dead_code
|