From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by yquem.inria.fr (Postfix) with ESMTP id 92479BB83 for ; Fri, 21 Jul 2006 14:01:23 +0200 (CEST) Received: from pauillac.inria.fr (pauillac.inria.fr [128.93.11.35]) by concorde.inria.fr (8.13.6/8.13.6) with ESMTP id k6LC1MGm013048 for ; Fri, 21 Jul 2006 14:01:22 +0200 Received: from nez-perce.inria.fr (nez-perce.inria.fr [192.93.2.78]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id OAA19344 for ; Fri, 21 Jul 2006 14:01:22 +0200 (MET DST) Received: from ug-out-1314.google.com (ug-out-1314.google.com [66.249.92.172]) by nez-perce.inria.fr (8.13.6/8.13.6) with ESMTP id k6LC1L5O022080 for ; Fri, 21 Jul 2006 14:01:22 +0200 Received: by ug-out-1314.google.com with SMTP id c2so1273639ugf for ; Fri, 21 Jul 2006 05:01:21 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=gmail.com; h=received:message-id:date:from:sender:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references:x-google-sender-auth; b=ZgHjEKRtLbk1DUpqwQ9yymMpmBiV0/Z7IVsEZFuNQY50sgC84AjzuOhL0XHX7UHpC1wc1KsID9FSV7ROSb7f9LHqG23zP9sEnm/+mjfsIUhWCNcWJ75mWoGkPCFtU+bHBWelr/Bp5lcdepO9MmXOwRWX97+6qelqxh0G6gtmIYA= Received: by 10.78.117.10 with SMTP id p10mr315772huc; Fri, 21 Jul 2006 05:01:21 -0700 (PDT) Received: by 10.78.13.17 with HTTP; Fri, 21 Jul 2006 05:01:21 -0700 (PDT) Message-ID: Date: Fri, 21 Jul 2006 14:01:21 +0200 From: "Nicolas Pouillard" Sender: nicolas.pouillard@gmail.com To: "Christophe TROESTLER" Subject: Re: [Caml-list] camlp4 & free variables Cc: caml-list In-Reply-To: <20060720.163930.91910937.Christophe.Troestler@umh.ac.be> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline References: <20060720.012706.109316902.Christophe.Troestler@umh.ac.be> <20060720.163930.91910937.Christophe.Troestler@umh.ac.be> X-Google-Sender-Auth: c638228652d95eb5 X-Miltered: at concorde with ID 44C0C212.001 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Miltered: at nez-perce with ID 44C0C211.001 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Spam: no; 0.00; camlp:01 christophe:01 troestler:01 christophe:01 troestler:01 umh:01 umh:01 camlp:01 syntax:01 vars:01 pervasives:01 expr:01 expr:01 struct:01 pervasives:01 X-Spam-Checker-Version: SpamAssassin 3.0.3 (2005-04-27) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_BY_IP autolearn=disabled version=3.0.3 On 7/20/06, Christophe TROESTLER wrote: > On Thu, 20 Jul 2006, "Nicolas Pouillard" wrote: > > > > On 7/20/06, Christophe TROESTLER wrote: > > > Hi, > > > > > > Is it possible to write a camlp4 syntax extension that "extract" the > > > free variables of an expression? > > You are quite lucky, the camlp4 version has one module to do that! > > Thank you very much for your help! Is there an updated manual for > camlp4 (if possible written more from a user perspective :)? > Alas not now. > If I understand well your code (I really ought to learn camlp4!) > FV.free_vars first argument is a set of names which should net be > considered as free variables. Is it possible to do it contextually, > e.g. in > > open_out("X" ^ x) > > only "x" is returned as free because "open_out" and "^" are known from > Pervasives? Or in > > let z = 1 > ... > FUNCTION(x + z) > > only "x" is returned as free because "z" is known from the context? > In my previous program, I provide a function f that takes an AST: f <> Here the AST is given using a quotation but there is no relation between the code outside and inside the quotation so: let x = 42 in f <> This code does not bind x inside the quotation. Now if you want to use FUNCTION(...) as a sort of macro function there is a camlp4 filter for that. Let's call close_expr the this macro function (instead of FUNCTION) $ cat expression_closure_filter.ml (* camlp4r *) #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; $ ocamlc -c -pp camlp4rf expression_closure_filter.ml $ cat test_expression_closure_filter.ml (* x and y are free *) close_expr(x y);; (* bind x *) let x = 42;; (* y is free *) close_expr(x y);; (* bind y locally so the expr is closed *) close_expr(let y = x in x y);; (* bind y locally but outside, z is free *) let y = x in close_expr(x z y);; $ camlp4o ./expression_closure_filter.cmo test_expression_closure_filter.ml (* x and y are free *) let _ = fun ~y ~x -> x y (* bind x *) let x = 42 (* y is free *) let _ = fun ~y -> x y (* bind y locally so the expr is closed *) let _ = let y = x in x y (* bind y locally but outside, z is free *) let _ = let y = x in fun ~z -> x z y > Thanks again -- the new camlp4 version seem to really shine > w.r.t. the previous one ! Thanks, I'm glad to see camlp4 receive appreciations :) Cheers, -- Nicolas Pouillard