caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: "blue storm" <bluestorm.dylc@gmail.com>
To: caml-list@yquem.inria.fr
Subject: small Camlp4 code : get a free name
Date: Wed, 23 Jan 2008 20:59:59 +0100	[thread overview]
Message-ID: <527cf6bc0801231159o7c001a73lddd74e5b3cb30061@mail.gmail.com> (raw)

>> 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.


             reply	other threads:[~2008-01-23 20:00 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-23 19:59 blue storm [this message]
2008-01-23 20:30 ` [Caml-list] " Martin Jambon
2008-01-23 21:35   ` Edgar Friendly
2008-02-09 19:01     ` Nicolas Pouillard
2008-02-09 19:13 ` Nicolas Pouillard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=527cf6bc0801231159o7c001a73lddd74e5b3cb30061@mail.gmail.com \
    --to=bluestorm.dylc@gmail.com \
    --cc=caml-list@yquem.inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).