Hello
Here is the latest Caml Weekly News, for the week of March 27 to April 03, 2007.
Posted in the hope to save somebody's time before the new camlp4 documentation gets out. First a word on side effects: I mean those side effects that newly loaded modules perform inside camlp4 to register their functions in the camlp4 engine. In the good old times one simply used assignments for that, for instance Pcaml.print_implem := f has always been used to install f as printer for a .ml file. In the new camlp4 (some of) these side effects are performed not by the user but by camlp4 itself. The user only supplies the structure. It works the following way: The user defines a functor Make that maps some structure to a structure that defines the entities that camlp4 should use: module Make (some arg) = struct let important_fun ... end The user then uses Make in a functor application with a higher-order, registering functor from camlp4: module IgnoreResult = Camlp4.Register.Purpose(Make) where Purpose is one of the functors that Camlp4.Register provides. On invocation Purpose applies the user supplied Make to the right arguments, obtains a structure with important_fun and, finally, performs the side effect to register important_fun in the right hook. Actually the story is a bit more complicated, because the side effects are delayed: First Make is registered as a loaded module inside camlp4 together with a function that will perform the necessary side effects some time later. See for example functor Printer in camlp4/Camlp4/Register.ml line 73. In order to install a new camlp4 printer we only have to find the right registering functor and apply it to our arguments, put everything into some file and compile it into a .cmo. To install a new printer I chose Register.Printer, which takes two arguments: an identification module and a Make functor with my new printer functions inside. Here is the complete code: (* identification module *) module Id = struct (* name is printed with the -loaded-modules switch *) let name = "Printer HOWTO" (* cvs id's seem to be the preferred version string *) let version = "$Id: howto verion 1 $" end (* the real thing containing the real functions *) module Make (Syntax : Camlp4.Sig.Syntax) : Camlp4.Sig.Printer with module Ast = Syntax.Ast = struct module Ast = Syntax.Ast let opt_string = function | None -> "<None>" | Some s -> s let info ?input_file ?output_file name = Printf.eprintf "printer on %s\n input : %s\n output : %s\n" name (opt_string input_file) (opt_string output_file) (* print_interf shall be called on .mli files *) let print_interf ?input_file ?output_file ast = info ?input_file ?output_file "signature" (* print_implem shall be called on .ml files *) let print_implem ?input_file ?output_file ast = info ?input_file ?output_file "structure" end (* apply everything to register the new printer *) module M = Camlp4.Register.Printer(Id)(Make) (* end of source *) Put the source into a file printer.ml and compile with ocamlc -c -I `camlp4 -where` printer.ml Use examples: gromit otags 7> camlp4o printer.cmo printer.ml printer on structure input : printer.ml output : <None> gromit otags 8> camlp4o -o output_file printer.cmo printer.ml printer on structure input : printer.ml output : output_file gromit otags 9> ocamlc -pp 'camlp4o printer.cmo' printer.ml printer on structure input : printer.ml output : <None> Happy printing, HendrikNicolas Pouillard added:
I'm making a little change. [...] > (* the real thing containing the real functions *) > module Make (Syntax : Camlp4.Sig.Syntax) : > Camlp4.Sig.Printer with module Ast = Syntax.Ast = Will be Camlp4.Sig.Printer(Syntax.Ast).S = [...] Since 3.10 is not officially out the sooner is the better.
> Has anyone succeeded in wrapping OCaml code in a dynamic library for > use in C? > I can build a static OCaml library without any problems but when I > try to package that and some other C code in a dynamic library I get > errors like this on Mac OSX: > > /usr/bin/ld: ./libfib.a(fibcaml.o) has local relocation entries in > non-writable section (__TEXT,__text) i recently make a dynamic library including c++ wrappers to an ocaml module, to be loaded as a SCA component by apache tuscany. The first problem was that i have a 64b architecture, and in order to link against libcamlrun in shared mode, a recompilation of the runtime with -fPIC flag was necessary. I called the resulting library libcamlrun_shared, to not confuse it with the original one. Also you have to initialize the ocaml runtime from whiting you library.., and for my best knowledge it is necessary to pass the path to you .so to the caml_main function, like: #define LIB_DIR "/home/pablo/ocaml/tproject/deploy/TuscanyCalculator" static char *argv[] = { LIB_DIR "/libTuscanyCalculatorImpl.so", LIB_DIR "/libTuscanyCalculatorImpl.so", NULL }; caml_main (argv); The way that work for my is to compile the c code with -c -fPIC flags, compile the ocaml modules also with -c , and then link all the object codes together with ocamlc -linkall -custom -cclib "-fPIC -shared .. and include the libraries you need ( -lcamlrun_shared -ltermcap in my system) I think the best is to look at the makefile of the ocaml module for the aol server http://www.crystalballinc.com/vlad/software/ or the apache mod_ocaml http://merjis.com/developers/mod_caml , a lite more complex makefile. also, look at these previous post in this area: http://caml.inria.fr/pub/ml-archives/caml-list/2002/09/0d8daa135bd30302f1ebf30daf9a0ed9.en.html http://caml.inria.fr/pub/ml-archives/caml-list/2002/01/44d30c5454106646098bf00977c66796.en.html http://caml.inria.fr/pub/ml-archives/caml-list/2001/12/e9e89dadd773729481bf8446f1b73b64.en.html and also the manual pages http://caml.inria.fr/pub/docs/manual-ocaml/manual032.html
> It appears that Parsing uses global state, e.g. > let rhs_loc n = (Parsing.rhs_start_pos n, Parsing.rhs_end_pos n) > I'm building an "app server" to provide translation services to Ruby/ > Rails . How would you suggest I work around the global state issue? > Would I need to switch to Menhir? Yes Menhir is reentrant.
> Also, what XML package for OCaml is the easiest for publishing RSS > and parsing XHTML? COCANWIKI (very recent versions) use OCamlRSS and xml-light.
I'm pleased to announce that we've selected a list of winning projects for the OCaml Summer Project. The project has gone well beyond our expectations. Our initial expectation was to fund 5-10 students, but the quality of the submissions we saw was so high that we decided to fund 12 projects for a total of 15 students (three of the projects had two participants.) We're really excited about this summer, and we hope to see some great software come out of it. For a list of the accepted titles, take a look at the project website: http://osp2007.janestcapital.com
> Here is your rosetta stone :) > I translated pa_json_static.ml. Thanks a lot. I backported it to camlp4 3.10.0+beta. Compiling the extension and using it to preprocess a sample file now work fine (but I haven't tested the correctness of the generated code). The few things that didn't want to work with 3.10.0+beta were commented out and replaced by workarounds. People interested in upgrading their syntax extensions can read the side-by-side diffs: http://martin.jambon.free.fr/examples/pa_json_static_3100beta.html
Here is a quick trick to help you read this CWN if you are viewing it using vim (version 6 or greater).
:set foldmethod=expr
:set foldexpr=getline(v:lnum)=~'^=\\{78}$'?'<1':1
zM
If you know of a better way, please let me know.
If you happen to miss a CWN, you can send me a message and I'll mail it to you, or go take a look at the archive or the RSS feed of the archives.
If you also wish to receive it every week by mail, you may subscribe online.