Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
* [Caml-list] Camlp4 type constructor transformation
@ 2011-03-14 19:32 eagriffis
  2011-03-23  8:57 ` Hendrik Tews
  0 siblings, 1 reply; 2+ messages in thread
From: eagriffis @ 2011-03-14 19:32 UTC (permalink / raw)
  To: caml-list

Hello,

I am having trouble getting Camlp4 to detect and transform type constructors
that take parameters. I believe the problem is with my grammar. Here is a base
case (call it base.ml):


open Camlp4.PreCast
open Syntax

let is_interesting = function
  | ("Foo", 2) -> true
  | _ -> false
    
let rec name = function
  | Ast.ExApp (_, e, _) -> name e
  | Ast.ExId (_, Ast.IdUid (_, n)) -> n
  | _ -> raise Not_found
;;

let arity e =
  (* print_string "ZZZ\t";
  let _loc = Loc.ghost in
  Printers.OCaml.print_implem <:str_item< $exp:e$ >>; *)
  let rec loop a = function
    | Ast.ExApp (_, f, _) -> loop (a + 1) f
    | Ast.ExId (_, Ast.IdUid _) -> a
    | _ -> raise Not_found
  in
  loop 0 e

let apply _loc e1 e2 =
  try
    (* Printf.printf "XXX\t%s %d\n" (name e1) (arity e1); *)
    if is_interesting (name e1, arity e1) then
      <:expr< transform ($e1$ $e2$) >>
    else
      <:expr< $e1$ $e2$ >>
  with Not_found -> <:expr< $e1$ $e2$ >>

DELETE_RULE Gram expr: SELF; SELF END;

EXTEND Gram
  GLOBAL: expr;

  expr: LEVEL "apply"
    [ LEFTA
	[ e1 = SELF; e2 = SELF -> apply _loc e1 e2 ] ];
  
END;;


I compile with this command (ocaml 3.12.0):

ocamlc -I +camlp4 -pp camlp4of dynlink.cma camlp4fulllib.cma base.ml


Here is a test case (call it test.ml):

type t = Foo of int * int | Bar of int | Baz
    
let f = function
  | 1 -> Foo (1, 1)
  | 2 -> Bar 2
  | _ -> Baz


I process the test case with this command:

camlp4of base.cmo test.ml


... and get the following output:

type t = | Foo of int * int | Bar of int | Baz

let f = function | 1 -> Foo ((1, 1)) | 2 -> Bar 2 | _ -> Baz


... but what I want is this:

type t = | Foo of int * int | Bar of int | Baz

let f = function | 1 -> transform (Foo (1, 1)) | 2 -> Bar 2 | _ -> Baz


If I uncomment the print statements in base.ml, I see this before the output:

ZZZ	let _ = Foo;;
XXX	Foo 0
ZZZ	let _ = Foo;;
ZZZ	let _ = Bar;;
XXX	Bar 0
ZZZ	let _ = Bar;;


So it seems my grammar extension only ever considers the inner-most expression
application. Perhaps further explanation is necessary. I examine the structure
of the expression application with the following experiment (call it exp.ml):

let p = <:str_item<
type t = Foo of int * int | Bar of int | Baz
    
let f = function
  | 1 -> Foo (1, 1)
  | 2 -> Bar 2
  | _ -> Baz
>>


I run the following command:

camlp4of exp.ml


It expands the quotation to a crazy big tree, the interesting bit being this:

		      (Ast.ExApp (_loc,
			 (Ast.ExApp (_loc,
			    (Ast.ExId (_loc, (Ast.IdUid (_loc, "Foo")))),
			    (Ast.ExInt (_loc, "1")))),
			 (Ast.ExInt (_loc, "1")))))),

It seems that my constructor of arity 2 can be located as an uppercase
identifier nested twice deep in ExApps. So either I do not understand how to
modify the grammar rule to catch this, or the problem is not in the rule?

Any help would be most appreciated. I've gotten this far by reading whatever
tutorials I could find and trying to follow along in the Camlp4 source code,
but I am now completely stumped. Thank you!

Eric Griffis
eagriffis@gmail.com

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2011-03-23  8:57 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-14 19:32 [Caml-list] Camlp4 type constructor transformation eagriffis
2011-03-23  8:57 ` Hendrik Tews

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox