Skip to content
Snippets Groups Projects
Commit 0f54289a authored by Erwan Jahier's avatar Erwan Jahier
Browse files

Fix a bug in the fresh var names generation.

cf test/should_work/NONREG/fresh_name.lus

where the local variable _n1e1_1 was defined twice !

The fix contist the following idea : prefix fresh var name by "_",
   except if at least one user ident begins by "_". In that case, we
   try to prefix them by "_1", and then "_2", and so on. We take the
   first possible one.

   nb : this won't work if the user defined idents from "_1" to
   "_1073741823" (on 32-bits machine), but I bet that this compiler
   would die before anyway...
parent 0f5b381b
No related branches found
No related tags found
No related merge requests found
(** Time-stamp: <modified the 19/01/2010 (at 15:49) by Erwan Jahier> *)
(** Time-stamp: <modified the 22/01/2010 (at 17:43) by Erwan Jahier> *)
(** Here follows a description of the different modules used by this lus2lic compiler.
......@@ -191,12 +191,12 @@ and
)
(* Retourne un parse_tree *)
let lus_load lexbuf = (
SolveIdent.recognize_predef_op
(Parser.sxLusFile Lexer.lexer lexbuf)
)
(* Retourne un SyntaxTree.t *)
let lus_load lexbuf =
let tree = Parser.sxLusFile Lexer.lexer lexbuf in
Name.update_fresh_var_prefix ();
SolveIdent.recognize_predef_op tree
(*
Lance le parser et renvoie la liste name-spaces d'entre.
......
(** Time-stamp: <modified the 20/01/2010 (at 11:24) by Erwan Jahier> *)
(** Time-stamp: <modified the 22/01/2010 (at 18:15) by Erwan Jahier> *)
(* maps node_key to a string that won't clash *)
......@@ -42,7 +42,6 @@ let (node_key: Eff.node_key -> string -> string) =
fresh_name
(********************************************************************************)
(* Dealing with fresh local (to the node) variable idents *)
let local_var_tbl = Hashtbl.create 0
......@@ -52,18 +51,100 @@ let (reset_local_var_prefix : string -> unit) =
fun str ->
Hashtbl.remove local_var_tbl str
(********************************************************************************)
(* The idea is to prefix fresh var name by "_", except if at least
one user ident begins by "_". In that case, we try to prefix them
by "_0", and then "_1", and so on so forth. We take the first
possible one.
nb : this won't work if the user defined idents from "_1" to
"_1073741823" (on 32-bits machine), but I bet that this compiler
would die before anyway...
nb : We stored in ParserUtils.name_table the set of idents that begins by "_".
*)
let fresh_var_prefix = ref "_"
let char_is_int = function
|'0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' -> true
| _ -> false
(* Returns None if str.[1] is not an int, and Some i otherwhise,
where i is the biggest possible int in str after the "_" (e.g.,
"_23toto" returns "Some 23" *)
let (get_int : string -> int option) =
fun str ->
let _ = assert (str<>"" && str.[0]='_') in
let s = String.length str in
if s>1 && char_is_int str.[1] then
let j = ref 2 in
while !j<s && char_is_int str.[!j] do incr j done;
Some (int_of_string (String.sub str 1 (!j-1)))
else
None
let _ = (* A few unit tests *)
assert (get_int "_" = None);
assert (get_int "_toto" = None);
assert (get_int "_1" = Some 1);
assert (get_int "_1234" = Some 1234);
assert (get_int "_1234toto" = Some 1234)
module IntSet =
Set.Make(struct
type t = int
let compare = compare
end)
(* exported *)
let (update_fresh_var_prefix : unit -> unit) =
fun _ ->
let used_ints = (* the set of ints apprearing after a "_" in program idents *)
Hashtbl.fold
(fun name _ acc ->
match get_int name with
None -> IntSet.add (-1) acc
| Some i -> IntSet.add i acc
)
ParserUtils.name_table
IntSet.empty
in
let used_ints = IntSet.elements used_ints in
let rec find_int l =
match l with
| [] -> -1
| [i] -> if i > 0 then 0 else i+1
| i::j::tail -> if j=i+1 then find_int (j::tail) else i+1
in
let index = find_int used_ints in
if index = (-1) then
()
(* no var begins by "_", so "_" is a good prefix.*)
else (
let new_prefix = ("_" ^ (string_of_int index)) in
fresh_var_prefix := new_prefix ;
if (Verbose.get_level()>1) then (
print_string ("I use " ^ new_prefix ^ " as prefix for fresh var names.\n");
flush stdout
)
)
(********************************************************************************)
(* exported *)
let (new_local_var : string -> string) =
fun prefix ->
try
let cpt = Hashtbl.find local_var_tbl prefix in
Hashtbl.replace local_var_tbl prefix (cpt+1);
"_" ^ prefix ^"_"^ (string_of_int cpt)
!fresh_var_prefix ^ prefix ^"_"^ (string_of_int cpt)
with
Not_found ->
Hashtbl.add local_var_tbl prefix 2;
"_" ^ prefix ^ "_1"
!fresh_var_prefix ^ prefix ^ "_1"
(********************************************************************************)
let (array_type : Eff.type_ -> string -> string) =
......
(** Time-stamp: <modified the 26/01/2009 (at 14:28) by Erwan Jahier> *)
(** Time-stamp: <modified the 22/01/2010 (at 18:08) by Erwan Jahier> *)
(** All new identifier names ougth to be created via this module.
To avoid name clashes when inventing new identifiers, all user
program idents have been prefixed by "_". Hence, the new idents
generated here never begins with "_" and no clash is possible.
*)
(** All new identifier names ougth to be created via this module. *)
(** [node_key nk name] returns a node ident that won't clash, using [name] or not.
......@@ -30,3 +25,7 @@ val reset_local_var_prefix : string -> unit
(** *)
val array_type : Eff.type_ -> string -> string
(** To be called just after the parsing (to make sure that fresh var names won't clash with
user idents. ) *)
val update_fresh_var_prefix : unit -> unit
(** Time-stamp: <modified the 15/09/2008 (at 15:35) by Erwan Jahier> *)
(** Time-stamp: <modified the 22/01/2010 (at 17:25) by Erwan Jahier> *)
......@@ -145,11 +145,20 @@ open Ident
(**********************************************************************************)
(* Interface avec SyntaxTree *)
(* we store ident names in a table to be able to generated fresh var
name that won't clash afterwards *)
let (name_table : (string, unit) Hashtbl.t) =
Hashtbl.create 0
let idref_of_lxm lxm =
try Lxm.flagit (Ident.idref_of_string (Lxm.str lxm)) lxm
with _ ->
print_string ("Parser.idref_of_lxm" ^(Lxm.str lxm));
assert false
let name = (Lxm.str lxm) in
if name.[0] = '_' then (
Hashtbl.add name_table name ());
try Lxm.flagit (Ident.idref_of_string name) lxm
with _ ->
print_string ("Parser.idref_of_lxm" ^(Lxm.str lxm));
assert false
(**********************************************************************************)
......
(** Time-stamp: <modified the 23/10/2008 (at 10:51) by Erwan Jahier> *)
(** Time-stamp: <modified the 22/01/2010 (at 14:30) by Erwan Jahier> *)
(** (Raw) Abstract syntax tree of source programs.
This syntax tree represented by Hash tables.
This is a syntax tree represented by Hash tables.
*)
open Printf
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment