Version française
Home     About     Download     Resources     Contact us    
Browse thread
AST transformation and scrapping boilerplate code
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Nicolas Pouillard <nicolas.pouillard@g...>
Subject: Re: [Caml-list] AST transformation and scrapping boilerplate code
On 4/29/07, Joel Reymont <joelr1@gmail.com> wrote:
> Folks,
>
> I have a large AST [2] that I would like to strip of token locations.
> Using the "Scrap your boilerplate" approach [1] the Haskell code
> looks like this:
>
> strip :: (Data a) => a -> a
> strip = everywhere (mkT f)
>      where f (TokenPos a _) = a
>            f x = x
>
> Is there a way to accomplish a similar feat in OCaml without writing
> out heaps of code that recursively invokes strip for various
> constructors to get to expr and strip it of TokenPos?
>

The new Camlp4 can generate extensible map and fold traversals for a
given data structure. alphaCaml [1] also generetates some similar code
(and a lot more since its goal is to treat bindings).

However these to generators don't handle polymorphic variants.

Here is an example using camlp4, but without polymorphic variants:

-------------------8<----------------------------------------------------------------------------------
type statement =
  | InputDecls of input_decl list
  | VarDecls of var_decl list

and subscript = expr list

and input_decl =
    | InputDecl of id * ty * expr
    | FunArgDecl of id * ty * subscript

and expr =
    | Num of int
    | Mul of expr * expr
    | PrintExpr of expr * expr * expr
    | TokenPos of expr * pos list

and id = string
and ty = Int
and var_decl = Var_decl
and pos = int
;;

class map = Camlp4Filters.GenerateMap.generated;;
class fold = Camlp4Filters.GenerateFold.generated;;

let strip_postions = object inherit map as super
  method expr e =
    match super#expr e with
    | TokenPos(a, _) -> a
    | e -> e
end

let x =
  InputDecls
    [InputDecl("foo", Int,
      TokenPos(
        Mul(TokenPos(Num 3,[12]), Num 4),
        [15]))]
;;

let y = strip_postions#statement x
--------------------------------------8<---------------------------------------------------------------------

$ ocamlc -pp "camlp4o -filter map -filter fold" /tmp/test.ml

Hope this helps,

[1]: http://cristal.inria.fr/~fpottier/alphaCaml/

-- 
Nicolas Pouillard