blob: 840479ea31d21993baa59836199c4f63a61e438b [file] [edit]
open Util.Source
open Il.Ast
open Il.Free
include Xl.Gen_free
let det_list = free_list
let det_list_dep = free_list_dep
(* Iterations *)
let rec det_iter iter =
match iter with
| Opt | List | List1 -> empty
| ListN (e, _xo) -> det_exp e
(* Types *)
and det_typ t =
Il.Debug.(log_at "il.det_typ" t.at
(fun _ -> fmt "%s" (il_typ t))
(fun s -> String.concat ", " (Set.elements s.varid))
) @@ fun _ ->
match t.it with
| VarT (_x, as_) -> det_list det_arg as_
| BoolT | NumT _ | TextT -> empty
| TupT xts -> det_list_dep det_typbind bound_typbind xts
| IterT (t1, iter) -> det_typ t1 ++ det_iter iter
and det_typbind (_x, t) = det_typ t
and bound_typbind (x, _t) = bound_varid x
(* Expressions *)
and det_exp e =
Il.Debug.(log_at "il.det_exp" e.at
(fun _ -> fmt "%s" (il_exp e))
(fun s -> String.concat ", " (Set.elements s.varid))
) @@ fun _ ->
match e.it with
| VarE x -> bound_varid x
| BoolE _ | NumE _ | TextE _ -> empty
(* We consider arithmetic expressions determinate,
* since we sometimes need to use invertible formulas. *)
| CvtE (e1, _, _) | UnE (#Xl.Num.unop, _, e1) | TheE e1 | LiftE e1
| SubE (e1, _, _) -> det_exp e1
| BinE (#Xl.Num.binop, _, e1, e2) | CatE (e1, e2) -> det_exp e1 ++ det_exp e2
| OptE eo -> free_opt det_exp eo
| ListE es | TupE es -> det_list det_exp es
| CaseE (_, e1) | UncaseE (e1, _) -> det_exp e1
| StrE efs -> det_list det_expfield efs
| IterE (e1, ite) -> det_iterexp (det_exp e1) ite
(* As a special hack to work with bijective functions,
* we treat last position of a call as a pattern, too. *)
| CallE (_, []) -> empty
| CallE (_, as_) -> det_list det_idx_arg as_ ++ det_arg (Util.Lib.List.last as_)
| UnE _ | BinE _ | CmpE _
| IdxE _ | SliceE _ | UpdE _ | ExtE _ | CompE _ | MemE _
| ProjE _ | DotE _ | LenE _ -> det_idx_exp e
and det_expfield (_, e) = det_exp e
and det_iterexp s1 (it, xes) =
s1 -- bound_iter it -- free_list bound_varid (List.map fst xes) ++
det_iter it ++
det_list det_exp (List.filter_map
(fun (x, e) -> if Set.mem x.it s1.varid then Some e else None) xes)
and det_cond_exp e =
Il.Debug.(log_at "il.det_cond_exp" e.at
(fun _ -> fmt "%s" (il_exp e))
(fun s -> String.concat ", " (Set.elements s.varid))
) @@ fun _ ->
match e.it with
| UnE (#Xl.Bool.unop, _, e1) -> det_cond_exp e1
| BinE (#Xl.Bool.binop, _, e1, e2) -> det_cond_exp e1 ++ det_cond_exp e2
| CmpE (`EqOp, _, e1, e2) -> det_exp e1 ++ det_exp e2
| MemE (e1, e2) -> det_exp e1 ++ det_quant_exp e2
| _ -> det_quant_exp e
and det_idx_exp e =
Il.Debug.(log_at "il.det_idx_exp" e.at
(fun _ -> fmt "%s" (il_exp e))
(fun s -> String.concat ", " (Set.elements s.varid))
) @@ fun _ ->
match e.it with
| VarE _ -> empty
| LiftE e1 | SubE (e1, _, _) | CaseE (_, e1) -> det_idx_exp e1
| OptE eo -> free_opt det_idx_exp eo
| ListE es | TupE es -> det_list det_idx_exp es
| StrE efs -> det_list det_idx_expfield efs
| IterE (e1, ite) -> det_idx_iterexp (det_idx_exp e1) ite
| CallE (_, as_) -> det_list det_idx_arg as_
| IdxE (e1, e2) -> det_quant_exp e1 ++ det_exp e2
| _ -> det_quant_exp e
and det_idx_expfield (_, e) =
det_idx_exp e
and det_idx_iter iter =
match iter with
| Opt | List | List1 -> empty
| ListN (e, x_opt) -> det_idx_exp e ++ free_opt bound_varid x_opt
and det_idx_iterexp s1 (it, xes) =
s1 -- free_list bound_varid (List.map fst xes) ++
det_idx_iter it ++
det_list det_exp (List.filter_map
(fun (x, e) -> if Set.mem x.it s1.varid then Some e else None) xes)
and det_quant_exp e =
Il.Debug.(log_at "il.det_quant_exp" e.at
(fun _ -> fmt "%s" (il_exp e))
(fun s -> String.concat ", " (Set.elements s.varid))
) @@ fun _ ->
match e.it with
| VarE x -> bound_varid x
| BoolE _ | NumE _ | TextE _ -> empty
| UnE (_, _, e1) | ProjE (e1, _) | TheE e1 | LiftE e1 | LenE e1
| CvtE (e1, _, _) | SubE (e1, _, _) ->
det_quant_exp e1
| BinE (_, _, e1, e2) | CmpE (_, _, e1, e2)
| IdxE (e1, e2) | MemE (e1, e2) | CatE (e1, e2) | CompE (e1, e2) ->
det_quant_exp e1 ++ det_quant_exp e2
| SliceE (e1, e2, e3) ->
det_quant_exp e1 ++ det_quant_exp e2 ++ det_quant_exp e3
| UpdE (e1, p, e2) | ExtE (e1, p, e2) ->
det_quant_exp e1 ++ det_quant_path p ++ det_quant_exp e2
| DotE (e1, _) | CaseE (_, e1) | UncaseE (e1, _) -> det_quant_exp e1
| OptE eo -> free_opt det_quant_exp eo
| ListE es | TupE es -> det_list det_quant_exp es
| StrE efs -> det_list det_quant_expfield efs
| IterE (e1, ite) -> det_quant_iterexp (det_quant_exp e1) ite
| CallE (_, as_) -> det_list det_quant_arg as_
and det_quant_expfield (_, e) =
det_quant_exp e
and det_quant_iterexp s1 (it, xes) =
s1 -- bound_iter it -- free_list bound_varid (List.map fst xes) ++
det_quant_iter it ++
det_list det_exp (List.filter_map
(fun (x, e) -> if Set.mem x.it s1.varid then Some e else None) xes)
and det_quant_path p =
match p.it with
| RootP -> empty
| IdxP (p1, e) -> det_quant_path p1 ++ det_quant_exp e
| SliceP (p1, e1, e2) ->
det_quant_path p1 ++ det_quant_exp e1 ++ det_quant_exp e2
| DotP (p1, _) -> det_quant_path p1
and det_quant_iter iter =
match iter with
| Opt | List | List1 -> empty
| ListN (e, _x_opt) -> det_quant_exp e
(* Grammars *)
and det_sym g =
Il.Debug.(log_at "il.det_sym" g.at
(fun _ -> fmt "%s" (il_sym g))
(fun s -> String.concat ", " (Set.elements s.varid))
) @@ fun _ ->
match g.it with
| VarG (_x, as_) -> det_list det_arg as_
| NumG _ | TextG _ | EpsG -> empty
| SeqG gs | AltG gs -> det_list det_sym gs
| RangeG (g1, g2) -> det_sym g1 ++ det_sym g2
| IterG (g1, ite) -> det_iterexp (det_sym g1) ite
| AttrG (e, g1) -> det_exp e ++ det_sym g1
(* Premises *)
and det_prem pr =
Il.Debug.(log_at "il.det_prem" pr.at
(fun _ -> fmt "%s" (il_prem pr))
(fun s -> String.concat ", " (Set.elements s.varid))
) @@ fun _ ->
match pr.it with
| RulePr (_x, _as, _mixop, e) -> det_exp e
| IfPr e -> det_cond_exp e
| LetPr (e1, _e2, _xs) -> det_exp e1
| ElsePr -> empty
| IterPr (pr1, ite) -> det_iterexp (det_prem pr1) ite
(* Definitions *)
and det_arg a =
match a.it with
| ExpA e -> det_exp e
| TypA t -> free_typ t (* must be an id *)
| GramA g -> free_sym g (* must be an id *)
| DefA x -> bound_defid x
and det_idx_arg a =
match a.it with
| ExpA e -> det_idx_exp e
| TypA _ -> empty
| GramA _ -> empty
| DefA _ -> empty
and det_quant_arg a =
match a.it with
| ExpA e -> det_quant_exp e
| TypA _ -> empty
| GramA _ -> empty
| DefA _ -> empty