Previous week Up Next week


Here is the latest Caml Weekly News, for the week of 28 June to 05 July, 2005.

  1. Caml type rules
  2. ARM or MIPS?
  3. toplevels / bytecode interpreter
  4. New location for OCaml tutorial
  5. How to find out free diskspace?

Caml type rules


Swaroop Sridhar asked and Jacques Garrigue answered:
> Is there a document that contains all of the type-inference rules of 
> Ocaml? If so, I would appreciate a reference.

No document contains all the rules.
(It would be soon obsolete, due to the speed of changes :)

But most of the type system is accounted for in papers and technical

The following list may not be 100% accurate, nor complete, but it
should give you most of the type system:

Core language = HM type inference + algebraic datatypes:
Any good textbook on ML.

For the module system:
Applicative functors and fully transparent higher-order modules.
Xavier Leroy, POPL'95.

For objects and classes:
Objective ML: An effective object-oriented extension to ML.
Didier Remy and Jerome Vouillon, POPL'97.

For polymorphic variants and object typing:
Simple Type Inference for Structural Polymorphism
Jacques Garrigue, FOOL'2002.

For the typing of imperative features:
Relaxing the value restriction. Jacques Garrigue, FLOPS'04.

You can also find various papers on more specific aspects on
developpers' home pages.

Note however that some experimental features lack a detailed
presentation. For instance, recursive modules seem to be in this



Leszek Holenderski asked and Eric Cooper answered:
> Has OCaml been ported to ARM? If so, is the port really usable?

Yes, it's part of the standard distribution (see asmcomp/arm).  I
hacked it into a cross-compiler a while ago so I could run OCaml
programs on a Sharp Zaurus.  I haven't used it extensively, but both
byte-code and native-code programs worked fine.

toplevels / bytecode interpreter


Jonathan Roewen asked and Jean-Marc Eber answered:
> Can the OCaml bytecode interpreter be embedded in C programs? For
> example, a C program that mimics the top-level to a simpler degree.
> I'm thinking of changing DST so that it runs a bytecode interpreter on
> the bare metal instead of native code. Although, I'm sure I'd need a
> lot more libc underneath to get it working compared to native code :)
> I was also thinking the toplevel might be a good place to start
> (though, don't exactly need the shell-like interface...).
> Some pointers on general directions to take would be great.

Nive work has been done by Clément Capel on this topic:

Many hacks that were necessary at this time are no more needed due to cleanup 
work and necessary extensions done by Xavier before the release of ocaml 3.08, I 

But definitively, its possible, yes.
Clément Capel also answered:
yes, you can. I've developed that embedded interpreter you look for :)
At current time, It only works on ocaml 3.06, but the modifications to
perform are quite simple (i think) to make it works with the 3.08.

some links:

New location for OCaml tutorial


Richard Jones announced:
I'm in the process of moving the OCaml tutorial to an open wiki here:

How to find out free diskspace?


Bernd Kuhls asked and Richard Jones answered:
> I am looking for some Ocaml code (or C bindings which work on 
> Linux/Solaris/Cygwin) to get the amount of free diskspace on a volume. 
> The function should receive a string and return an int64 value or 
> something similar.

The attached files have only been very lightly tested, but they appear
to work.  You can work out the amount of free disk space by
multiplying the f_bfree and f_bsize fields.

Note the functions as they stand assume that Unix.file_descr = int and
don't throw a useful Unix error if the underlying call fails.


type statfs = {
  f_type : int64;
  f_bsize : int64;
  f_blocks : int64;
  f_bfree : int64;
  f_bavail : int64;
  f_files : int64;
  f_ffree : int64;
  f_fsid : unit;  (* See note in statfs(2) *)
  f_fnamelen : int64;

external statfs : string -> statfs = "statfs_statfs"
external fstatfs : Unix.file_descr -> statfs = "statfs_fstatfs"

---------------------------------------------------------------- statfs_c.c
#include <errno.h>
#include <string.h>
#include <sys/vfs.h>

#include <caml/alloc.h>
#include <caml/fail.h>
#include <caml/memory.h>
#include <caml/mlvalues.h>

static value
copy_statfs (struct statfs *buf)
  CAMLparam0 ();
  CAMLlocal1 (bufv);
  bufv = caml_alloc (9, 0);
  caml_modify (&Field (bufv, 0), copy_int64 (buf->f_type));
  caml_modify (&Field (bufv, 1), copy_int64 (buf->f_bsize));
  caml_modify (&Field (bufv, 2), copy_int64 (buf->f_blocks));
  caml_modify (&Field (bufv, 3), copy_int64 (buf->f_bfree));
  caml_modify (&Field (bufv, 4), copy_int64 (buf->f_bavail));
  caml_modify (&Field (bufv, 5), copy_int64 (buf->f_files));
  caml_modify (&Field (bufv, 6), copy_int64 (buf->f_ffree));
  caml_modify (&Field (bufv, 7), Val_unit);
  caml_modify (&Field (bufv, 8), copy_int64 (buf->f_namelen));
  CAMLreturn (bufv);

CAMLprim value
statfs_statfs (value pathv)
  CAMLparam1 (pathv);
  CAMLlocal1 (bufv);
  const char *path = String_val (pathv);
  struct statfs buf;
  if (statfs (path, &buf) == -1)
    caml_failwith (strerror (errno));
  bufv = copy_statfs (&buf);
  CAMLreturn (bufv);

CAMLprim value
statfs_fstatfs (value fdv)
  CAMLparam1 (fdv);
  CAMLlocal1 (bufv);
  int fd = Int_val (fdv);
  struct statfs buf;
  if (fstatfs (fd, &buf) == -1)
    caml_failwith (strerror (errno));
  bufv = copy_statfs (&buf);
  CAMLreturn (bufv);
Damien Doligez then said:
> static value
> copy_statfs (struct statfs *buf)
> {
>   CAMLparam0 ();
>   CAMLlocal1 (bufv);
>   bufv = caml_alloc (9, 0);
>   caml_modify (&Field (bufv, 0), copy_int64 (buf->f_type));
>   [...]

There's a nasty bug lurking in this code.  Depending on your
C compiler, you might be computing &Field (bufv, 0) before
the call to copy_int64, which can trigger a GC and change the
value of bufv, hence invalidating the address you've just

You should do it this way:

static value
copy_statfs (struct statfs *buf)
   CAMLparam0 ();
   CAMLlocal1 (bufv, v);
   bufv = caml_alloc (9, 0);
   v = copy_int64 (buf->f_type); caml_modify (&Field (bufv, 0), v);
   v = copy_int64 (buf->f_bsize); caml_modify (&Field (bufv, 1), v);
   v = copy_int64 (buf->f_blocks); caml_modify (&Field (bufv, 2), v);
   v = copy_int64 (buf->f_bfree); caml_modify (&Field (bufv, 3), v);
   v = copy_int64 (buf->f_bavail); caml_modify (&Field (bufv, 4), v);
   v = copy_int64 (buf->f_files); caml_modify (&Field (bufv, 5), v);
   v = copy_int64 (buf->f_ffree); caml_modify (&Field (bufv, 6), v);
   caml_modify (&Field (bufv, 7), Val_unit);
   v = copy_int64 (buf->f_namelen); caml_modify (&Field (bufv, 8), v);
   CAMLreturn (bufv);

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

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