2010-06-15 14:05:26 +02:00
|
|
|
(**************************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* Heptagon *)
|
|
|
|
(* *)
|
|
|
|
(* Author : Marc Pouzet *)
|
|
|
|
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
|
|
|
(* *)
|
|
|
|
(**************************************************************************)
|
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
(* naming and local environment *)
|
|
|
|
|
2010-12-14 18:29:55 +01:00
|
|
|
(* TODO AG : preprocessing pour avoir un release efficace :
|
|
|
|
IFDEF RELEASE type iden = int
|
|
|
|
ELSE *)
|
|
|
|
|
|
|
|
|
2010-06-15 14:05:26 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
type ident = {
|
|
|
|
num : int; (* a unique index *)
|
|
|
|
source : string; (* the original name in the source *)
|
|
|
|
is_generated : bool;
|
2011-05-23 20:42:04 +02:00
|
|
|
is_reset : bool;
|
2010-06-15 10:49:03 +02:00
|
|
|
}
|
|
|
|
|
2011-05-23 20:42:04 +02:00
|
|
|
let is_reset id = id.is_reset
|
|
|
|
|
2010-07-07 15:11:32 +02:00
|
|
|
type var_ident = ident
|
|
|
|
|
2010-09-13 14:09:05 +02:00
|
|
|
let num = ref 0
|
|
|
|
|
2010-09-30 19:13:43 +02:00
|
|
|
let ident_compare id1 id2 = compare id1.num id2.num
|
2010-12-14 18:29:55 +01:00
|
|
|
|
|
|
|
(* used only for debuging *)
|
2010-06-26 16:53:25 +02:00
|
|
|
let name id =
|
2010-06-15 10:49:03 +02:00
|
|
|
if id.is_generated then
|
|
|
|
id.source ^ "_" ^ (string_of_int id.num)
|
|
|
|
else
|
|
|
|
id.source
|
|
|
|
|
2010-12-14 18:29:55 +01:00
|
|
|
(* used only for debuging *)
|
2011-05-10 20:29:01 +02:00
|
|
|
let print_ident ff id = Format.fprintf ff "%s" (name id)
|
2010-06-15 10:49:03 +02:00
|
|
|
|
|
|
|
module M = struct
|
|
|
|
type t = ident
|
2010-09-30 19:13:43 +02:00
|
|
|
let compare = ident_compare
|
2011-05-10 20:29:01 +02:00
|
|
|
let print_t = print_ident
|
2010-06-15 10:49:03 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
module Env =
|
|
|
|
struct
|
|
|
|
include (Map.Make(M))
|
|
|
|
|
|
|
|
let append env0 env =
|
|
|
|
fold (fun key v env -> add key v env) env0 env
|
|
|
|
|
|
|
|
(* Environments union *)
|
|
|
|
let union env1 env2 =
|
|
|
|
fold (fun name elt env -> add name elt env) env2 env1
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
(* Environments difference : env1 - env2 *)
|
|
|
|
let diff env1 env2 =
|
|
|
|
fold (fun name _ env -> remove name env) env2 env1
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
(* Environments partition *)
|
|
|
|
let partition p env =
|
|
|
|
fold
|
|
|
|
(fun key elt (env1,env2) ->
|
2010-06-26 16:53:25 +02:00
|
|
|
if p(key)
|
|
|
|
then ((add key elt env1),env2)
|
|
|
|
else (env1,(add key elt env2)))
|
2010-06-15 10:49:03 +02:00
|
|
|
env
|
|
|
|
(empty, empty)
|
2011-05-10 20:29:01 +02:00
|
|
|
|
|
|
|
(* Print Env *)
|
|
|
|
let print_t print_value ff m =
|
|
|
|
Format.fprintf ff "@[<hov>{@ ";
|
|
|
|
iter (fun k v -> Format.fprintf ff "%a => %a,@ " M.print_t k print_value v) m;
|
|
|
|
Format.fprintf ff "}@]";
|
2010-06-15 10:49:03 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
module IdentSet = struct
|
|
|
|
include (Set.Make(M))
|
|
|
|
|
2011-05-10 20:29:01 +02:00
|
|
|
let print_t ff s =
|
2010-06-15 10:49:03 +02:00
|
|
|
Format.fprintf ff "@[<hov>{@ ";
|
2011-05-10 20:29:01 +02:00
|
|
|
iter (fun e -> Format.fprintf ff "%a,@ " M.print_t e) s;
|
2010-06-15 10:49:03 +02:00
|
|
|
Format.fprintf ff "}@]";
|
|
|
|
end
|
|
|
|
|
2010-09-13 10:18:52 +02:00
|
|
|
module S = Set.Make (struct type t = string
|
|
|
|
let compare = Pervasives.compare end)
|
|
|
|
|
2010-12-14 18:29:55 +01:00
|
|
|
|
|
|
|
(** Module used to generate unique string (inside a node) per ident.
|
|
|
|
/!\ Any pass generating a name must call [enter_node] and use gen_fresh *)
|
2010-09-13 14:09:05 +02:00
|
|
|
module UniqueNames =
|
|
|
|
struct
|
2010-12-14 18:29:55 +01:00
|
|
|
open Names
|
2011-05-12 00:54:02 +02:00
|
|
|
let used_names = ref (ref NamesSet.empty) (** Used strings in the current node *)
|
2010-12-14 18:29:55 +01:00
|
|
|
let env = ref Env.empty (** Map idents to their string *)
|
2011-05-12 00:54:02 +02:00
|
|
|
let (node_env : NamesSet.t ref QualEnv.t ref) = ref QualEnv.empty
|
2012-03-07 17:44:10 +01:00
|
|
|
let name_counters = Hashtbl.create 500
|
2010-09-13 14:09:05 +02:00
|
|
|
|
2010-12-14 18:29:55 +01:00
|
|
|
(** This function should be called every time we enter a node *)
|
|
|
|
let enter_node n =
|
|
|
|
(if not (QualEnv.mem n !node_env)
|
2011-05-12 00:54:02 +02:00
|
|
|
then node_env := QualEnv.add n (ref NamesSet.empty) !node_env);
|
2010-12-14 18:29:55 +01:00
|
|
|
used_names := QualEnv.find n !node_env
|
2010-09-13 14:09:05 +02:00
|
|
|
|
|
|
|
(** @return a unique string for each identifier. Idents corresponding
|
|
|
|
to variables defined in the source file have the same name unless
|
|
|
|
there is a collision. *)
|
|
|
|
let assign_name n =
|
2012-03-07 17:44:10 +01:00
|
|
|
|
|
|
|
let find_and_increment_counter s =
|
|
|
|
let num = try Hashtbl.find name_counters s with Not_found -> 1 in
|
|
|
|
Hashtbl.add name_counters s (num + 1);
|
|
|
|
num
|
|
|
|
in
|
|
|
|
|
|
|
|
let rec fresh_string s =
|
|
|
|
let num = find_and_increment_counter s in
|
|
|
|
let new_name = s ^ "_" ^ string_of_int num in
|
|
|
|
if NamesSet.mem new_name !(!used_names) then fresh_string s else new_name
|
|
|
|
in
|
|
|
|
|
2010-12-14 18:29:55 +01:00
|
|
|
if not (Env.mem n !env) then
|
|
|
|
(let s = n.source in
|
2011-05-12 00:54:02 +02:00
|
|
|
let s = if NamesSet.mem s !(!used_names) then fresh_string s else s in
|
|
|
|
!used_names := NamesSet.add s !(!used_names);
|
2010-12-14 18:29:55 +01:00
|
|
|
env := Env.add n s !env)
|
2010-09-13 14:09:05 +02:00
|
|
|
|
|
|
|
let name id =
|
|
|
|
Env.find id !env
|
|
|
|
end
|
|
|
|
|
2011-05-23 20:42:04 +02:00
|
|
|
let gen_fresh pass_name kind_to_string ?(reset=false) kind =
|
2010-12-14 19:34:09 +01:00
|
|
|
let s = kind_to_string kind in
|
|
|
|
let s = if !Compiler_options.full_name then "__"^pass_name ^ "_" ^ s else s in
|
2010-09-13 14:09:05 +02:00
|
|
|
num := !num + 1;
|
2011-05-23 20:42:04 +02:00
|
|
|
let id = { num = !num; source = s; is_generated = true; is_reset = reset } in
|
2010-09-13 14:09:05 +02:00
|
|
|
UniqueNames.assign_name id; id
|
|
|
|
|
2011-05-23 20:42:04 +02:00
|
|
|
let gen_var pass_name ?(reset=false) name =
|
|
|
|
gen_fresh pass_name (fun () -> name) ~reset:reset ()
|
2010-12-14 18:29:55 +01:00
|
|
|
|
2011-05-23 20:42:04 +02:00
|
|
|
let ident_of_name ?(reset=false) s =
|
2010-09-13 14:09:05 +02:00
|
|
|
num := !num + 1;
|
2011-05-23 20:42:04 +02:00
|
|
|
let id = { num = !num; source = s; is_generated = false; is_reset = reset } in
|
2010-09-13 14:09:05 +02:00
|
|
|
UniqueNames.assign_name id; id
|
|
|
|
|
2011-05-09 19:32:12 +02:00
|
|
|
let source_name id = id.source
|
2010-09-13 14:09:05 +02:00
|
|
|
let name id = UniqueNames.name id
|
2010-12-14 18:29:55 +01:00
|
|
|
let enter_node n = UniqueNames.enter_node n
|
2010-06-16 19:31:51 +02:00
|
|
|
|
2010-06-17 09:22:26 +02:00
|
|
|
let print_ident ff id = Format.fprintf ff "%s" (name id)
|