blob: bce500e9c69cf2083224c4080c9cfc2d92f111b4 [file] [edit]
open Util.Source
open Ast
(* Data Structure *)
module Set = Env.Set
type sets =
{typid : Set.t; relid : Set.t; varid : Set.t; defid : Set.t; gramid : Set.t}
let empty =
{ typid = Set.empty;
relid = Set.empty;
varid = Set.empty;
defid = Set.empty;
gramid = Set.empty
}
let union sets1 sets2 =
{ typid = Set.union sets1.typid sets2.typid;
relid = Set.union sets1.relid sets2.relid;
varid = Set.union sets1.varid sets2.varid;
defid = Set.union sets1.defid sets2.defid;
gramid = Set.union sets1.gramid sets2.gramid;
}
let diff sets1 sets2 =
{ typid = Set.diff sets1.typid sets2.typid;
relid = Set.diff sets1.relid sets2.relid;
varid = Set.diff sets1.varid sets2.varid;
defid = Set.diff sets1.defid sets2.defid;
gramid = Set.diff sets1.gramid sets2.gramid;
}
let (+) = union
let (-) = diff
let subset sets1 sets2 =
Set.subset sets1.typid sets2.typid &&
Set.subset sets1.relid sets2.relid &&
Set.subset sets1.varid sets2.varid &&
Set.subset sets1.defid sets2.defid &&
Set.subset sets1.gramid sets2.gramid
let disjoint sets1 sets2 =
Set.disjoint sets1.typid sets2.typid &&
Set.disjoint sets1.relid sets2.relid &&
Set.disjoint sets1.varid sets2.varid &&
Set.disjoint sets1.defid sets2.defid &&
Set.disjoint sets1.gramid sets2.gramid
let free_opt free_x xo = Option.(value (map free_x xo) ~default:empty)
let free_list free_x xs = List.(fold_left (+) empty (map free_x xs))
let free_pair free_x free_y (x, y) = free_x x + free_y y
let bound_list = free_list
let rec free_list_dep free_x bound_x = function
| [] -> empty
| x::xs -> free_x x + (free_list_dep free_x bound_x xs - bound_x x)
(* Identifiers *)
let free_typid id = {empty with typid = Set.singleton id.it}
let free_relid id = {empty with relid = Set.singleton id.it}
let free_varid id = {empty with varid = Set.singleton id.it}
let free_defid id = {empty with defid = Set.singleton id.it}
let free_gramid id = {empty with gramid = Set.singleton id.it}
let bound_typid id = if id.it = "_" then empty else free_typid id
let bound_relid id = if id.it = "_" then empty else free_relid id
let bound_varid id = if id.it = "_" then empty else free_varid id
let bound_defid id = if id.it = "_" then empty else free_defid id
let bound_gramid id = if id.it = "_" then empty else free_gramid id
(* Iterations *)
let rec free_iter iter =
match iter with
| Opt | List | List1 -> empty
| ListN (e, _) -> free_exp e
and bound_iter iter =
match iter with
| Opt | List | List1 -> empty
| ListN (_, id_opt) -> free_opt bound_varid id_opt
(* Types *)
and free_typ t =
match t.it with
| VarT (id, as_) -> free_typid id + free_args as_
| BoolT | NumT _ | TextT -> empty
| TupT ets -> free_typbinds ets
| IterT (t1, iter) -> free_typ t1 + free_iter iter
and bound_typ t =
match t.it with
| VarT _ | BoolT | NumT _ | TextT -> empty
| TupT ets -> bound_list bound_typbind ets
| IterT (t1, _iter) -> bound_typ t1
and free_typbind (_e, t) = free_typ t
and bound_typbind (e, _t) = free_exp e
and free_typbinds xts = free_list_dep free_typbind bound_typbind xts
and free_deftyp dt =
match dt.it with
| AliasT t -> free_typ t
| StructT tfs -> free_list free_typfield tfs
| VariantT tcs -> free_list free_typcase tcs
and free_typfield (_, (bs, t, prems), _) =
free_binds bs + (free_typ t + (free_prems prems - bound_typ t) - bound_binds bs)
and free_typcase (_, (bs, t, prems), _) =
free_binds bs + (free_typ t + (free_prems prems - bound_typ t) - bound_binds bs)
(* Expressions *)
and free_exp e =
match e.it with
| VarE id -> free_varid id
| BoolE _ | NumE _ | TextE _ -> empty
| UnE (_, _, e1) | LiftE e1 | LenE e1 | ProjE (e1, _) | TheE e1 | DotE (e1, _) -> free_exp e1
| BinE (_, _, e1, e2) | CmpE (_, _, e1, e2)
| IdxE (e1, e2) | CompE (e1, e2) | MemE (e1, e2) | CatE (e1, e2) -> free_exp e1 + free_exp e2
| SliceE (e1, e2, e3) -> free_list free_exp [e1; e2; e3]
| OptE eo -> free_opt free_exp eo
| TupE es | ListE es -> free_list free_exp es
| UpdE (e1, p, e2) | ExtE (e1, p, e2) -> free_exp e1 + free_path p + free_exp e2
| StrE efs -> free_list free_expfield efs
| CaseE (_, e1) | UncaseE (e1, _) -> free_exp e1
| CallE (id, as1) -> free_defid id + free_args as1
| IterE (e1, iter) -> (free_exp e1 - bound_iterexp iter) + free_iterexp iter
| CvtE (e1, _nt1, _nt2) -> free_exp e1
| SubE (e1, t1, t2) -> free_exp e1 + free_typ t1 + free_typ t2
and free_expfield (_, e) = free_exp e
and free_path p =
match p.it with
| RootP -> empty
| IdxP (p1, e) -> free_path p1 + free_exp e
| SliceP (p1, e1, e2) -> free_path p1 + free_exp e1 + free_exp e2
| DotP (p1, _atom) -> free_path p1
and free_iterexp (iter, xes) =
free_iter iter + free_list (free_pair free_varid free_exp) xes
and bound_iterexp (iter, xes) =
bound_iter iter + free_list bound_varid (List.map fst xes)
(* Grammars *)
and free_sym g =
match g.it with
| VarG (id, as_) -> free_gramid id + free_args as_
| NumG _ | TextG _ | EpsG -> empty
| SeqG gs | AltG gs -> free_list free_sym gs
| RangeG (g1, g2) -> free_sym g1 + free_sym g2
| IterG (g1, iter) -> (free_sym g1 - bound_iterexp iter) + free_iterexp iter
| AttrG (e, g1) -> free_exp e + free_sym g1
(* Premises *)
and free_prem prem =
match prem.it with
| RulePr (id, _op, e) -> free_relid id + free_exp e
| IfPr e -> free_exp e
| LetPr (e1, e2, _) -> free_exp e1 + free_exp e2
| ElsePr -> empty
| IterPr (prem1, iter) -> (free_prem prem1 - bound_iterexp iter) + free_iterexp iter
and free_prems prems = free_list free_prem prems
(* Definitions *)
and free_arg a =
match a.it with
| ExpA e -> free_exp e
| TypA t -> free_typ t
| DefA id -> free_defid id
| GramA g -> free_sym g
and free_bind b =
match b.it with
| ExpB (_, t) -> free_typ t
| TypB _ -> empty
| DefB (_, ps, t) -> free_params ps + (free_typ t - bound_params ps)
| GramB (_, ps, t) -> free_params ps + (free_typ t - bound_params ps)
and free_param p =
match p.it with
| ExpP (_, t) -> free_typ t
| TypP _ -> empty
| DefP (_, ps, t) -> free_params ps + (free_typ t - bound_params ps)
| GramP (_, t) -> free_typ t
and bound_bind b =
match b.it with
| ExpB (id, _) -> bound_varid id
| TypB id -> bound_typid id
| DefB (id, _, _) -> bound_defid id
| GramB (id, _, _) -> bound_gramid id
and bound_param p =
match p.it with
| ExpP (id, _) -> bound_varid id
| TypP id -> bound_typid id
| DefP (id, _, _) -> bound_defid id
| GramP (id, _) -> bound_gramid id
and free_args as_ = free_list free_arg as_
and free_binds bs = free_list_dep free_bind bound_bind bs
and free_params ps = free_list_dep free_param bound_param ps
and bound_binds bs = free_list bound_bind bs
and bound_params ps = free_list bound_param ps
let free_inst inst =
match inst.it with
| InstD (bs, as_, dt) ->
free_binds bs + (free_args as_ + free_deftyp dt - bound_binds bs)
let free_rule rule =
match rule.it with
| RuleD (_id, bs, _op, e, prems) ->
free_binds bs + (free_exp e + free_prems prems - bound_binds bs)
let free_clause clause =
match clause.it with
| DefD (bs, as_, e, prems) ->
free_binds bs + (free_args as_ + free_exp e + free_prems prems - bound_binds bs)
let free_prod prod =
match prod.it with
| ProdD (bs, g, e, prems) ->
free_binds bs + (free_sym g + free_exp e + free_prems prems - bound_binds bs)
let free_hintdef hd =
match hd.it with
| TypH (id, _) -> free_typid id
| RelH (id, _) -> free_relid id
| DecH (id, _) -> free_defid id
| GramH (id, _) -> free_gramid id
let rec free_def d =
match d.it with
| TypD (_id, ps, insts) -> free_params ps + free_list free_inst insts
| RelD (_id, _mixop, t, rules) -> free_typ t + free_list free_rule rules
| DecD (_id, ps, t, clauses) ->
free_params ps + (free_typ t - bound_params ps)
+ free_list free_clause clauses
| GramD (_id, ps, t, prods) ->
free_params ps + (free_typ t + free_list free_prod prods - bound_params ps)
| RecD ds -> free_list free_def ds
| HintD hd -> free_hintdef hd
let rec bound_def d =
match d.it with
| TypD (id, _, _) -> bound_typid id
| RelD (id, _, _, _) -> bound_relid id
| DecD (id, _, _, _) -> bound_defid id
| GramD (id, _, _, _) -> bound_gramid id
| RecD ds -> free_list bound_def ds
| HintD _ -> empty