ocamlcamlp4

How to compile using Camlp4?


I am testing out quotations in Camlp4. My tester.ml program is as follows:

open Camlp4.PreCast;;
let x = <:Cstm< x = 1 + 2 >>;;
let y = <:expr< let y = 1 + 2 >>;;
print_string "done";;

I have tried compiling this in various ways, eg.

ocamlc -pp "camlp4of pa_extend.cmo -loc" -I +camlp4 tester.ml

however the executable produced doesn't print out "done" as expected. How should I compile this file?


Solution

  • camlp4 --help says:

    -loc <name>      Name of the location variable (default: _loc).
    

    You forget the argument for -loc. You can check the consequence of this by ocamlc's -verbose option. (-verbose is really handy to find out what are exactly happening in the compilation):

    $ ocamlc -verbose -pp "camlp4of pa_extend.cmo -loc" -I +camlp4 tester.ml
    + camlp4of pa_extend.cmo -loc "tester.ml" > /blahblah//ocamlpp2f0635
    

    The input file name tester.ml is not treated as a file name but is considered as the name of location variables. With the empty input camlp4of outputs an empty program and it is compiled by ocamlc. That's why the final executable does nothing.

    You code contains a strange quotation name Cstrm, and let y = 1 + 2 is not an expression but a structure item. The following is one of the nearest codes which compile:

    (* compilable by ocamlc -pp "camlp4of pa_extend.cmo" -I +camlp4 tester.ml *)
    open Camlp4.PreCast;;
    let x _loc = <:expr< x = 1 + 2 >>;;
    let y _loc = <:str_item< let y = 1 + 2 >>;;
    print_string "done";;
    

    You can check the output of CamlP4 in a human readable form with -printer Camlp4OCamlPrinter option. This is another important technique to work with CamlP4:

    $ camlp4of pa_extend.cmo -printer Camlp4OCamlPrinter tester.ml
    open Camlp4.PreCast
    
    let x _loc =
      Ast.ExApp (_loc,
        (Ast.ExApp (_loc, (Ast.ExId (_loc, (Ast.IdLid (_loc, "=")))),
           (Ast.ExId (_loc, (Ast.IdLid (_loc, "x")))))),
        (Ast.ExApp (_loc,
           (Ast.ExApp (_loc, (Ast.ExId (_loc, (Ast.IdLid (_loc, "+")))),
              (Ast.ExInt (_loc, "1")))),
           (Ast.ExInt (_loc, "2")))))
    
    let y _loc =
      Ast.StVal (_loc, Ast.ReNil,
        (Ast.BiEq (_loc, (Ast.PaId (_loc, (Ast.IdLid (_loc, "y")))),
           (Ast.ExApp (_loc,
              (Ast.ExApp (_loc, (Ast.ExId (_loc, (Ast.IdLid (_loc, "+")))),
                 (Ast.ExInt (_loc, "1")))),
              (Ast.ExInt (_loc, "2")))))))
    
    let _ = print_string "done"