Browse thread
small Camlp4 code : get a free name
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
| Date: | -- (:) |
| From: | blue storm <bluestorm.dylc@g...> |
| Subject: | small Camlp4 code : get a free name |
>> I deduce that there is no standard way of introducing
>> `fresh' (w.r.t. the abstract syntax tree) variables
>> within a camlp4 syntax extension? Wouldn't that be nice? =)
>> Has anybody every implemented a solution to that problem?
> That would be nice, but doing it cleanly would require a large amount of work
> and user visible changes.
I'm not sure it's a "clean" way of doing it, but i think this may works :
you can fold the AST to get every bound variable names, and then look
for conflicts.
I tried to do that. See my camlp4 code at the end of the message.
The folder is very simple : it collects every identifier name, even
not-really-bounded ones (eg. in patterns). I don't think it's a
problem : the important thing is to get no false positive.
Is there a problem with this method ?
Do you have any comment or advice ?
------------------
open Camlp4;
module Make (Syntax : Sig.Camlp4Syntax) = struct
open Syntax;
value get_bound_vars =
let folder = object (self)
inherit Ast.fold as super;
value binds = [];
method binds = binds;
method ident = fun
[ <:ident< $lid:id$ >> | <:ident< $uid:id$ >> ->
{< binds = [id::binds] >}
| other -> super#ident other ];
end in
fun expr -> (folder#expr expr)#binds;
value get_free_var suffix binds =
let rec generate var =
if List.mem var binds
then generate ("_" ^ var ^ "_")
else var
in generate suffix;
end;
------------------
You can test it with this example code (for example) :
------------------
open Camlp4
open PreCast
module FV = Freevars.Make(Syntax)
let _loc = Loc.ghost
let expr = <:expr< match foo with bar -> foo2 | _ -> 1 + 2 >>
let binds = FV.get_bound_vars expr
let fv = FV.get_free_var "foo" binds
(* fv is "_foo_" *)
------------------
Thanks for your comments.