(* camlp4r *)
(****************************************************************************)
(* *)
(* OCaml *)
(* *)
(* INRIA Rocquencourt *)
(* *)
(* Copyright 2006 Institut National de Recherche en Informatique et *)
(* en Automatique. All rights reserved. This file is distributed under *)
(* the terms of the GNU Library General Public License, with the special *)
(* exception on linking described in LICENSE at the top of the Camlp4 *)
(* source tree. *)
(* *)
(****************************************************************************)
#default_quotation "expr";
open Camlp4.PreCast;
open Format;
module FV = Camlp4.Struct.FreeVars.Make Ast;
module S = FV.S;
value _loc = Loc.ghost;
value pervasives =
let list =
[ "+"; "-"; "/"; "*" (* ... *) ]
in List.fold_right S.add list S.empty;
value collect_free_vars_sets =
object (self)
inherit FV.fold_free_vars [S.t] S.add ~env_init:pervasives S.empty as super;
value free_sets = [];
method set_free free = {< free = free >};
method expr =
fun
[ << close_expr $e$ >> -> (self#expr e)#add_current_free#set_free free
| e -> super#expr e ];
method add_current_free = {< free_sets = [ free :: free_sets ] >};
method free_sets = free_sets;
end;
value apply_close_expr next_free_set =
object (self)
inherit Ast.map as super;
method expr =
fun
[ << close_expr $e$ >> ->
let e = self#expr e in
let fv = next_free_set () in
S.fold (fun x acc -> << fun ~ $x$ -> $acc$ >>) fv e
| e -> super#expr e ];
end;
value f st =
let fv_sets = ref (collect_free_vars_sets#str_item st)#free_sets in
let next_free_set () =
match fv_sets.val with
[ [] -> assert False
| [x::xs] -> let () = fv_sets.val := xs in x ]
in (apply_close_expr next_free_set)#str_item st;
AstFilters.register_str_item_filter f;