Previous week Up Next week

Hello

Here is the latest Caml Weekly News, for the week of November 20 to 27, 2007.

  1. Camlp5 release 5.03
  2. Coq Tutorial at POPL 2008: Using Proof Assistants for Programming Language Research
  3. labltk : mini-tutorial
  4. ocaml-based magnetism simulation package
  5. XmlRpc-Light 0.6
  6. Ocaml(opt) & llvm
  7. LLVM: A native-code compiler for MiniML in ~100LOC
  8. Native-code Smoke demos now for Mac OS X on Intel

Camlp5 release 5.03

Archive: http://groups.google.com/group/fa.caml/browse_frm/thread/2260d2c1f91dc3c1#99b988e98f8d4d6a

Daniel de Rauglaudre announced:
New release of Camlp5: 5.03 

Main changes: 
  * Added commands mkcamlp5 and mkcamlp5.opt to build camlp5 executables. 
  * Some small improvements and bug fixes. 

For changes of all versions, see file CHANGES in Camlp5 site. 

Download the sources and the documentation at: 
   http://pauillac.inria.fr/~ddr/camlp5/ 
			
David Teller asked and Daniel de Rauglaudre answered:
> By quickly browsing the documentation, I haven't been able to understand 
> the core of the difference between camlp4 and camlp5. I mean, there's a 
> Pcaml module which seems to have disappared from camlp4 in 3.10, but I 
> assume that's not where it ends. Could you tell us a bit more about it ? 

Camlp5 is the continuation of the classical Camlp4. 

At OCaml 3.10, Camlp4 was changed, with some incompatible features, 
sometimes implying many changes in user programs. A solution is to 
use Camlp5. Some softwares, e.g. "Coq", adopted this solution.
			
Richard Jones also answered:
Camlp4 was extensively changed for the 3.10 release, in many ways not 
for the better (it's much bigger now for a start, and not backwards 
compatible, and has almost no documentation, and I have problems with 
it and findlib). 

Camlp5 is the camlp4 from 3.09.3 (before the changes / fork), and with 
some ongoing maintenance. 

     3.09         3.10 
-------+----/\/----+---------> "new" camlp4 (distributed with OCaml) 
       | 
        \ 
         --------------------> camlp5 (now distributed separately) 

If you had a package which depends on camlp4 in 3.09.3, you need to 
modify it so it compiles with OCaml 3.10.  An alternative which 
doesn't involve modifying your package is to install camlp5.  You can 
install both in parallel no problem. 

Debian ships both.  Fedora will soon as well.
			

Coq Tutorial at POPL 2008: Using Proof Assistants for Programming Language Research

Archive: http://groups.google.com/group/fa.caml/browse_frm/thread/f85425f2099921d3#dc2694c20eafb6b0

Stephanie Weirich announced:
               Tutorial Announcement and Call for Participation 

           Using Proof Assistants for Programming Language Research 
                                     Or: 
                   How to Write Your Next POPL Paper in Coq 

                        San Francisco, CA, 8 Jan 2008 
                          Co-located with POPL 2008 
                           Sponsored by ACM SIGPLAN 

                     http://plclub.org/popl08-tutorial/ 

======================================================================= 

The University of Pennsylvania PLClub invites you to participate in a 
tutorial on using the Coq proof assistant to formalize programming   
language 
metatheory. 

This tutorial will be tailored to people who are familiar with syntactic 
proofs of programming language metatheory (type soundness, etc.), but   
have 
never used a proof assistant. At the end of the day, participants   
will have 
a reading knowledge of Coq and a running start on using Coq in their own 
work. 

This tutorial will be hands-on, with breaks for exercises;   
participants are 
strongly encouraged to bring a laptop running Coq 8.1 (or a later   
release) 
and either Proof General or CoqIDE. 

Tutorial topics 

   - Defining language semantics in Coq 
      - Abstract syntax 
      - Inductively-defined relations 
      - Derivations 
   - Proving simple results 
      - Fundamental tactics 
      - Automation 
      - Forward and backward reasoning 
   - Scaling up to POPLmark 
      - Semantic functions and conversion 
      - Sets and environments 
   - Representing binding 
      - Locally nameless representation 
      - Freshness through cofinite quantification 
      - Syntactic type soundness 

Registration will be through the POPL 2008 registration site: 
         http://www.regmaster.com/conf/popl2008.html 

The tutorial is organized and presented by members of the University of 
Pennsylvania PLClub: Brian Aydemir, Aaron Bohannon, Benjamin Pierce,   
Jeffrey 
Vaughan, Dimitrios Vytiniotis, Stephanie Weirich, and Steve Zdancewic. 

Questions can be sent to Stephanie Weirich (sweirich@cis.upenn.edu).
			

labltk : mini-tutorial

Archive: http://groups.google.com/group/fa.caml/browse_frm/thread/fbfe88f193572aa8#3ac9d5e0e18ab0c9

François Thomasset announced:
As I could not find easily informations on the use of labltk, I took a PerlTk 
tutorial with nice pedagogic qualities, and adapted it to labltk: 
http://www-rocq.inria.fr/~thomasse/Labltk/Tutoriel_FT/ 
I know this is still far from being a complete tutorial: a number of features 
are not described, explanations are a bit terse. I may try to improve it some 
day. Meanwhile I hope this batch of examples can be useful to other people than 
myself. Please warn me about any mistakes or imprecision.
			

ocaml-based magnetism simulation package

Archive: http://groups.google.com/group/fa.caml/browse_frm/thread/5293f5244e787a94#70cfd4be024478bd

Thomas Fischbacher announced:
I thought I should mention this to keep people informed about 
large projects done in OCaml. 

Micromagnetism is a rather hot topic these days. There are 
a number of packages around that allow one to do physical 
simulations of sub-micron scale magnetic systems, but there 
is one around (ours) which is written mostly in ocaml. 
(The user interface is python, though.) 

The rationale for using ocaml was that we needed both speed 
and enough flexibility to do symbolic manipulations. 
Actually, this micromagnetism package is just a library on 
top of a much more generic multiphysics simulation system 
that was designed to deal with a very broad class of 
generalized reaction-diffusion systems, whose ultimate goal 
is to automatically compile an abstract problem specification 
(containing differential operators and equations of motion 
in symbolic form) down to some numerical finite element code. 

The first beta-release (still a bit wobbly) is at: 

http://nmag.soton.ac.uk
			
Andrej Bauer asked and Thomas Fischbacher answered:
> I have suspected for a while that writing the computational part in 
> ocaml and the user interface in python is a good combination. What is 
> your experience? Are there any drawbacks? Would you do it again? 

We use a modified variant of Art (arty) Yerkes' old "pycaml" module. 

Essentially, I had to re-write quite a bit of it, as both reference 
counting on the Python side and Gc management on the OCaml side were 
broken. One impotant issue is that the pycaml module (which also is 
part of Debian) does not recognize properly that python library 
primitives often differ in their behaviour concerning whether they 
increase the reference count of a return value or not. 

Also, we added a lot of extra stuff and goodies which allows us to 
interface ML to python quite smoothly. When I call a ML-function from 
python, dynamic type-checking of all the arguments is automatic and 
generates appropriate python exceptions. Here is an example for a 
python-wrapped ML function that uses our extended pycaml module: 

let _py_raw_cvode_advance = 
   python_pre_interfaced_function 
     [|CamlpillType; (* the cvode *) 
       CamlpillType; (* the result vector *) 
       FloatType;    (* target time *) 
       IntType;      (* max nr_steps, -1 for "no limit" *) 
     |] 
     (fun args -> 
        let cvode = cvode_from_ocamlpill args.(0) in 
        let FEM_field (_,_,v_result) = field_from_ocamlpill args.(1) in 
        let target_time = pyfloat_asdouble args.(2) in 
        let max_steps = pyint_asint args.(3) in 
        let result_time = 
         Sundials.cvode_advance cvode target_time v_result max_steps 
         in 
         pyfloat_fromdouble result_time) 
;; 

It is nice to be able to implement other high-level python/caml 
interface abstractions through functional tricks -- such as a caml 
function constructing and accessing a higher-rank nested-list python 
tensor. 

How does it feel? If I had a need for some specific fast low-level 
extension to python, I would prefer using python+ocaml a thousand 
times over python+C. It is just so much nicer not having to worry 
about reference counting issues. Even if you feel you can do it 
right, there is always a bit of doubt. Doubly so if you are not 
the sole developer. I would not let our PhD students write C 
extensions to python, but I have no problems whatsoever letting 
them extend python via ocaml functions. 

One sort-of limitation is that we use our own python interpreter. 
(I.e. the main program is written in OCaml and eventually provides 
a python prompt or runs a python script.) 

This is necessary in our situation as we also want to support running 
in parallel under MPI control, and the MPI libraries do some nasty 
arg-passing things that upset an unmodified python interpreter. So, we 
do not load some object-code module containing all the ML runtime 
environment system into a standard python interpreter; technically, that 
should be possible as well on many platforms, but it is not relevant in 
our particular case here. 

On the other hand, of course, if one can completely avoid such 
inter-language interfaces, the better. In principle, both Python 
and OCaml are widely loved because of flexibility they both derive 
from LISP. So, some situations, one may be better off using e.g. the 
Gambit Scheme Compiler instead (which has, by the way, a terrific 
C interface!) 

It depends a lot on your constraints. If you want to build something 
that can be easily integrated with lots of data processing libraries 
that are readily available and accessible to casual programmers 
(engineers, physicists, etc.), providing python support seems to be a 
very good choice to me. It is rather popular among engineers these 
days, which I consider mostly a good thing. 

Also, if you want your PhD students to be productive at writing code 
that has to run fast, and if they are spoilt enough from previous 
exposure to imperative languages that you cannot really teach them 
Lisp/Scheme within a short amount of time ;-), then ocaml certainly 
is a very good choice. (In terms of what we teach our students about 
caml, this is not much more than the core ML language plus a bit 
about the C interface. They usually pick that up in less than 3 months. 
With C++, they never could be productive after such a short amount 
of time.) 

So, I would say: in an ideal computing world, we would all be expert 
Scheme hackers, but in the real world, python+ocaml can be an extremely 
productive and powerful combination. I have used and combined many 
systems in the past, but I would have difficulty naming anything 
else I played with that appeared even remotely as powerful. 

I know that in the longer run, we certainly should split nmag and 
ship our new and improved pycaml module separately (after brushing 
it up a bit) -- and a few other modules as well. But for now, 
we are busy dealing with other issues. (We are, after all, 
physicists studying real physical systems, so all this symbolic 
mumbo-jumbo in nmag/nsim is just a tool to us.)
			

XmlRpc-Light 0.6

Archive: http://groups.google.com/group/fa.caml/browse_frm/thread/9fbd8b6b789533cb#52277cf02782bc2c

Dave Benjamin announced:
I have released XmlRpc-Light 0.6. XmlRpc-Light is an XmlRpc client and 
server library written in OCaml. It requires Xml-Light and Ocamlnet 2. 

http://code.google.com/p/xmlrpc-light/ 

This release introduces a new module, XmlRpcDateTime, which provides a 
date time type (still a tuple of integers), time-zone-aware equality and 
comparison, XmlRpc-flavored iso-8601 parsing and generation, time zone 
adjustment, and conversion functions to- and from- Unix float and 
Unix.tm for both local and UTC times. There is also a handy "now()" 
function to build a time stamp for the current time. The Unix conversion 
functions follow the same naming convention as Julien Signoles' calendar 
library to ease integration with that package. 

I have written a suite of unit tests, based on Maas-Maarten Zeeman's 
oUnit framework, which you can run by typing "make test". These tests 
cover parsing and generation of XmlRpc values and messages, date-time 
parsing and arithmetic, and the server's function call and error 
handling behavior. 

The WordPress example library has been updated to support WordPress 2.3, 
which now provides UTC date-time values. The interface has been kept 
mostly the same. It now uses XmlRpcDateTime.t instead of defining a 
"datetime" type, but this shouldn't break any code since due to 
structural typing. The one thing that doesn't work the same is the 
"suggest_categories" method, since WordPress has completely changed the 
structure of its results. Rather than attempt to make any sense of the 
new result format, which is rather odd, I decided to punt here and just 
return an XmlRpc.value (variant). 

Finally, I have added support for the somewhat controversial "nil" type. 
Not all servers support this type, and Dave Winer has been known to be 
adamantly opposed to it, but it has become a de-facto standard and quite 
a few XmlRpc libraries support it now. If you don't like it, don't use 
it. =)
			

Ocaml(opt) & llvm

Archive: http://groups.google.com/group/fa.caml/browse_frm/thread/1c777227f8efb204#2b201480b60a879d

Basile STARYNKEVITCH said:
As some might probably know, the LLVM compiler http://llvm.org/ has (at 
least in its latest SVN snapshot) a binding for Ocaml. This means that 
one could code in Ocaml some stuff (eg a JIT-ing compiler) which uses 
(and links with) LLVM libraries. 
http://lists.cs.uiuc.edu/pipermail/llvmdev/2007-November/011481.html 
http://lists.cs.uiuc.edu/pipermail/llvmdev/2007-November/011507.html 

However, to generate code with LLVM for Ocamlopt, this is not enough, 
since while LLVM does have hooks to support garbage collection 
http://www.llvm.org/docs/GarbageCollection.html 
I don't know of any actual hooks to fit into the needs of Ocamlopt 
garbage colector (which AFAIK require some specific frame descriptors in 
the code, in some hashtables, which details are tricky and known to very 
few implementors, perhaps only Xavier Leroy & Damien Doligez). 

So is there any code to fit the Ocaml GC requirements into LLVM 
abilities, ie to use LLVM to generate (eg JIT) code which respect Ocaml 
GC requirements. 

Of course, I do know that there are some typing issues and theoritical 
points which I deliberately ignore here. I'm supposing the guy wanting 
to LLVM for Ocaml is knowing that he seeks trouble. 

And Metaocaml is (unfortunately) nearly dead: future (in ocaml 3.11 or 
3.12) dynamic libraries ability is not a full replacement! Even if one 
might generate Ocaml code and compile & dlopen it in a future version of 
Ocaml.
			
Gordon Henriksen then said:
To avoid cross-posting, my followups to this thread will be on llvmdev. 

http://lists.cs.uiuc.edu/pipermail/llvmdev/2007-November/011527.html
			

LLVM: A native-code compiler for MiniML in ~100LOC

Archive: http://groups.google.com/group/fa.caml/browse_frm/thread/8ba2204855fc5e46#5aee553df34548e2

Jon Harrop announced:
I recently rediscovered the Low-Level Virtual Machine (LLVM) project that has 
since been adopted by Apple: 

  http://llvm.org 

This is a library (with OCaml bindings!) that allows you to write a compiler 
that generates their RISC-like intermediate language (IL) that can then be 
compiled to native code. LLVM even supports JIT compilation. 

I went through the usual steps in trying this and was extremely impressed with 
the results. After only two days I was able to create an optimizing 
native-code compiler for a subset of CAML large enough to represent the 
following Fibonacci program: 

  let rec fib n = 
    if n <= 2 then 1 else 
      fib(n-1) + fib(n-2) 

  do fib 40 

The compiler is written entirely in OCaml, using camlp4 for lexing and 
parsing, and the whole thing is only ~100 lines of code! 

I'll detail exactly how you can use LLVM from OCaml in a future OCaml Journal 
article: 

  http://www.ffconsultancy.com/products/ocaml_journal/?ol 

Meanwhile here's my latest source: 

type expr = 
  | Int of int 
  | Var of string 
  | BinOp of [ `Add | `Sub | `Leq ] * expr * expr 
  | If of expr * expr * expr 
  | Apply of expr * expr 

type defn = 
  | LetRec of string * string * expr 

open Camlp4.PreCast 

let expr = Gram.Entry.mk "expr" 
let defn = Gram.Entry.mk "defn" 
let prog = Gram.Entry.mk "prog" 

EXTEND Gram 
  expr: 
  [ [ "if"; p = expr; "then"; t = expr; "else"; f = expr -> 
        If(p, t, f) ] 
  | [ e1 = expr; "<="; e2 = expr -> BinOp(`Leq, e1, e2) ] 
  | [ e1 = expr; "+"; e2 = expr -> BinOp(`Add, e1, e2) 
    | e1 = expr; "-"; e2 = expr -> BinOp(`Sub, e1, e2) ] 
  | [ f = expr; x = expr -> Apply(f, x) ] 
  | [ v = LIDENT -> Var v 
    | n = INT -> Int(int_of_string n) 
    | "("; e = expr; ")" -> e ] ]; 
  defn: 
  [ [ "let"; "rec"; f = LIDENT; x = LIDENT; "="; body = expr -> 
        LetRec(f, x, body) ] ]; 
  prog: 
  [ [ defns = LIST0 defn; "do"; run = expr -> defns, run ] ]; 
END 

open Printf 

let program, run = 
  try Gram.parse prog Loc.ghost (Stream.of_channel stdin) with 
  | Loc.Exc_located(loc, e) -> 
      printf "%s at line %d\n" (Printexc.to_string e) (Loc.start_line loc); 
      exit 1 

open Llvm 

let ty = i64_type 

let ( |> ) x f = f x 

type state = 
    { fn: llvalue; 
      blk: llbasicblock; 
      vars: (string * llvalue) list } 

let bb state = builder_at_end state.blk 
let new_block state name = append_block name state.fn 
let find state v = 
  try List.assoc v state.vars with Not_found -> 
    eprintf "Unknown variable %s\n" v; 
    raise Not_found 
let cont (v, state) dest_blk = 
  build_br dest_blk (bb state) |> ignore; 
  v, state 

let rec expr state = function 
  | Int n -> const_int ty n, state 
  | Var x -> find state x, state 
  | BinOp(op, f, g) -> 
      let f, state = expr state f in 
      let g, state = expr state g in 
      let build, name = match op with 
        | `Add -> build_add, "add" 
        | `Sub -> build_sub, "sub" 
        | `Leq -> build_icmp Icmp_sle, "leq" in 
      build f g name (bb state), state 
  | If(p, t, f) -> 
      let t_blk = new_block state "pass" in 
      let f_blk = new_block state "fail" in 
      let k_blk = new_block state "cont" in 
      let cond, state = expr state p in 
      build_cond_br cond t_blk f_blk (bb state) |> ignore; 
      let t, state = cont (expr { state with blk = t_blk } t) k_blk in 
      let f, state = cont (expr { state with blk = f_blk } f) k_blk in 
      build_phi [t, t_blk; f, f_blk] "join" (bb state), state 
  | Apply(f, arg) -> 
      let f, state = expr state f in 
      let arg, state = expr state arg in 
      build_call f [|arg|] "apply" (bb state), state 

let defn m vars = function 
  | LetRec(f, arg, body) -> 
      let ty = function_type ty [| ty |] in 
      let fn = define_function f ty m in 
      let vars' = (arg, param fn 0) :: (f, fn) :: vars in 
      let body, state = 
        expr { fn = fn; blk = entry_block fn; vars = vars' } body in 
      build_ret body (bb state) |> ignore; 
      (f, fn) :: vars 

let int n = const_int ty n 

let main filename = 
  let m = create_module filename in 

  let string = pointer_type i8_type in 

  let print = 
    declare_function "printf" (var_arg_function_type ty [|string|]) m in 

  let main = define_function "main" (function_type ty [| |]) m in 
  let blk = entry_block main in 
  let bb = builder_at_end blk in 

  let str s = define_global "buf" (const_stringz s) m in 
  let int_spec = build_gep (str "%d\n") [| int 0; int 0 |] "int_spec" bb in 

  let vars = List.fold_left (defn m) [] program in 
  let n, _ = expr { fn = main; blk = blk; vars = vars } run in 

  build_call print [| int_spec; n |] "" bb |> ignore; 

  build_ret (int 0) bb |> ignore; 

  if not (Llvm_bitwriter.write_bitcode_file m filename) then exit 1; 
  dispose_module m 

let () = match Sys.argv with 
  | [|_; filename|] -> main filename 
  | _ as a -> Printf.eprintf "Usage: %s <file>\n" a.(0) 

To use it, simply download and install the latest SVN version of LLVM (which 
even builds and installs the OCaml bindings for you!) and then do: 

$ ocamlc -g -dtypes -pp camlp4oof -I +camlp4 dynlink.cma camlp4lib.cma -cc g++ 
llvm.cma llvm_bitwriter.cma minml.ml -o minml 
$ ./minml run.bc <fib.ml 
$ llc -f run.bc -o run.s 
$ gcc run.s -o run 
$ ./run 
102334155 
$ 

You can look at the generated intermediate representation with: 

$ llvm-dis -f run.bc 
$ cat run.ll 

If anyone improves upon this I'd love to hear about it! :-)
			

Native-code Smoke demos now for Mac OS X on Intel

Archive: http://groups.google.com/group/fa.caml/browse_frm/thread/4f8c5ef33e53a7b0#2264589aa36e105f

Jon Harrop announced:
We just updated the Smoke vector graphics pages with native Mac OS X 
executables of all three demos: 

  http://www.ffconsultancy.com/products/smoke_vector_graphics/?ol 

We'll be adding more demos and functionality to this library (including the 
free bytecode edition) in the new year.
			

Using folding to read the cwn in vim 6+

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}$'?'&lt;1':1
zM

If you know of a better way, please let me know.


Old cwn

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.


Alan Schmitt