Commit 3af01457 authored by Pietro Abate's avatar Pietro Abate
Browse files

add tutorial and manual to the distribution

parent afcb4bdd
This diff is collapsed.
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<!DOCTYPE page [
<!ENTITY rarr "&#8594;"> <!-- rightwards arrow, U+2192 ISOnum -->
]>
<page name="manual_interfacewithocaml">
<title>Interfacing CDuce with OCaml</title>
<box title="Introduction" link="intro">
<p>
This page describes the CDuce/OCaml interface. This interface allows
the programmer to:
</p>
<ul>
<li>call OCaml functions from a CDuce module;</li>
<li>export a CDuce model as an OCaml module, by giving it an explicit OCaml signature.</li>
</ul>
<p>
The intended usages for the interface are:
</p>
<ul>
<li>Reuse existing OCaml libraries, such as database,
network, GUI, data structures;</li>
<li>Use CDuce as an XML layer (input/output/transformation) for OCaml
projects;</li>
<li>Develop fully mixed OCaml/CDuce projects.</li>
</ul>
<p>
To see how to build CDuce with support for the OCaml interface,
see the <a href="INSTALL">INSTALL</a> file from the CDuce distribution.
</p>
</box>
<box title="Translating types" link="transl">
<p>
The heart of the interface is a mapping from OCaml types to CDuce
types. An OCaml type <code>%%t%%</code> is translated to a CDuce type
<code>T(%%t%%)</code>, which is meant to be isomorphic to <code>%%t%%</code>:
there is a canonical function <code>%%t%%</code> &rarr; <code>T(%%t%%)</code>
from OCaml values of type <code>%%t%%</code> to CDuce values of type
<code>T(%%t%%)</code>, and another canonical function <code>T(%%t%%)</code> &rarr; <code>%%t%%</code>.
</p>
<ul>
<li>
Basic OCaml types <code>char</code>, <code>int</code>, <code>string</code>,
<code>unit</code> are translated respectively to
<code>Byte = '\0;'--'\255;'</code>, <code>-1073741824 --
1073741823</code>, <code>Latin1 = [ Byte* ]</code>, <code>[] = `nil</code>.
</li>
<li>
Tuple types <code>%%t%%1 * ... * %%t%%n</code> are translated to nested CDuce
product types <code>(T(%%t%%1),(...,T(%%t%%n))...)</code>. A function type
<code>%%t%% -> %%s%%</code> is translated to <code>T(%%t%%) -> T(%%s%%)</code>.
Labels on the argument of the arrow are discarded.
</li>
<li>
A list type <code>%%t%% list</code> is translated to an homogeneous
sequence type <code>[ T(%%t%%)* ]</code>. An array type
<code>%%t%% array</code> has the same translation.
</li>
<li>
A option type <code>%%t%% option</code> is translated to
the type <code>[ T(%%t%%)? ]</code>.
</li>
<li>
A variant type with a declaration <code>A1 of %%t%%1 | ... | An of
%%t%%n</code> is translated to a type <code>(`A1,T(%%t%%1)) | ... |
(`An,T(%%t%%n))</code>. If a constructor <code>Ai</code> has no argument, the resulting
term is <code>`Ai</code>, not <code>(`Ai,[])</code>.
Polymorphic variant types are treated similarly.
</li>
<li>
A record type with a declaration <code>{ l1 : %%t%%1; ...; ln : %%t%%n
}</code> is translated to a closed record type <code>{ l1 = T(%%t%%1);
... ; ln = T(%%t%%n) }</code>. Mutable fields are just copied.
</li>
<li>
Private variant and record types are treated correctly: the interface
never tries to generate OCaml values of these types, but it will happily
translate them to CDuce values.
</li>
<li>
A reference type <code>%%t%% ref</code> is translated to the CDuce
reference type <code>ref T(%%t%%)</code>. When converting a Caml reference
to CDuce, the operation (set,get) on the resulting reference refers
to the original reference. However, when converting a CDuce reference
to OCaml, the content of the reference is fetched (set), and a fresh
OCaml reference is created (copy semantics).
</li>
<li>
The type <code>Cduce_lib.Value.t</code> is translated to the CDuce
type <code>Any</code>. The corresponding translation functions are the
identity. This can be used to avoid multiple copies when translating
a complex value back and forth between CDuce and OCaml.
The type <code>Cduce_lib.Encodings.Utf8.t</code> is translated to the CDuce
type <code>String</code>.
The type <code>Big_int.big_int</code> is translated to the CDuce
type <code>Int</code>.
</li>
<li>
A <em>monomorphic</em> abstract type <code>t</code> is translated to
the CDuce type <code>!t</code>. This type just acts as a container for
values of the abstract type. CDuce never produces a value of this
type, and it cannot inspect the content of such a value (apart
from checking its type).
</li>
</ul>
<p>
The canonical translation is summarized in the following box:
</p>
<table border="1" style="align:middle">
<col/>
<col/>
<tr>
<th>OCaml type <tt><i>t</i></tt></th>
<th>CDuce type <tt>T(<i>t</i>)</tt></th>
</tr>
<tr><td><tt>char</tt></td><td><tt>Byte = '\0;'--'\255;'</tt></td></tr>
<tr><td><tt>int</tt></td><td><tt>-1073741824 -- 1073741823</tt></td></tr>
<tr><td><tt>string</tt></td><td><tt>Latin1 = [ Byte* ]</tt></td></tr>
<tr><td><tt>unit</tt></td><td><tt>[] = `nil</tt></td></tr>
<tr><td><tt>bool</tt></td><td><tt>Bool = `true | `false</tt></td></tr>
<tr><td><tt><i>t1</i> * ... * <i>tn</i></tt></td>
<td><tt>(T(<i>t1</i>),(...,T(<i>tn</i>))...)</tt></td></tr>
<tr><td><tt><i>t</i> -> <i>s</i></tt></td>
<td><tt>T(<i>t</i>) -> T(<i>s</i>)</tt></td></tr>
<tr><td><tt><i>t</i> list</tt></td>
<td><tt>[ T(<i>t</i>)* ]</tt></td></tr>
<tr><td><tt><i>t</i> array</tt></td>
<td><tt>[ T(<i>t</i>)* ]</tt></td></tr>
<tr><td><tt><i>t</i> option</tt></td>
<td><tt>[ T(<i>t</i>)? ]</tt></td></tr>
<tr><td><tt>A of <i>t</i> | B of <i>s</i> | C</tt></td>
<td><tt>(`A, T(<i>t</i>)) | (`B, T(<i>s</i>)) | `C</tt></td></tr>
<tr><td><tt>[ `A of <i>t</i> | `B of <i>s</i> | `C ]</tt></td>
<td><tt>(`A, T(<i>t</i>)) | (`B, T(<i>s</i>)) | `C</tt></td></tr>
<tr><td><tt>{ x : <i>t</i>; y : <i>s</i> }</tt></td>
<td><tt>{ x = T(<i>t</i>); y = T(<i>s</i>) }</tt></td></tr>
<tr><td><tt><i>t</i> ref</tt></td>
<td><tt>ref T(<i>t</i>)</tt></td></tr>
<tr><td><tt>Cduce_lib.Value.t</tt></td><td><tt>Any</tt></td></tr>
<tr><td><tt>Cduce_lib.Encodings.Utf8.t</tt></td><td><tt>String</tt></td></tr>
<tr><td><tt>Big_int.big_int</tt></td><td><tt>Int</tt></td></tr>
</table>
<p>
Only monomorphic types are handled by the interface. It is allowed to
use polymorphic constructors as an intermediate, as long as the final
type to be translated is monomorphic. Recursive types, including
unguarded ones (option <code>-rectypes</code> of the OCaml compiler)
are accepted. In the following example:
</p>
<sample>
type 'a t = A of int | B of 'a t
type s = int t
type 'a u = A of ('a * 'a) u | B
type v = int u
</sample>
<p>
the type <code>s</code> can be translated, but the type <code>v</code>
can't, because its infinite unfolding is not a regular type.
</p>
<p>
OCaml object types are not supported.
</p>
<p>
Note that values are copied in depth (until reaching an abstract type,
a function types, etc...). In particular, translating an OCaml cyclic
values to CDuce will not terminate (well, with a stack overflow!).
</p>
</box>
<box title="Calling OCaml from CDuce" link="call_ocaml">
<p>
If an OCaml value has a type that can be translated, it is possible to
use it from CDuce (see the <a href="#link">How to compile and link</a> section for
more details).
</p>
<p>
In a CDuce module, you can write <code>M.f</code>
to denote the result of translating the OCaml value <code>M.f</code>
to CDuce.
</p>
<p>
If the value you want to use has a polymorphic type, you can make
the translation work by explicitly instantiating its type
variables with CDuce types. The syntax is <code>M.f with { t1
... tn }</code> where the <code>ti</code> are CDuce types. The type
variables are listed in the order they appear in a left-to-right
reading of the OCaml type. Example:
</p>
<sample>
let listmap = List.map with { Int String }
</sample>
<p>
will return a function of type <code>(Int -> String) -> ([Int*] -> [String*])</code>
</p>
</box>
<box title="Calling CDuce from OCaml" link="call_cduce">
<p>
We have seen in the section above how OCaml values can be used from a
CDuce module. It is also possible to use CDuce values from OCaml. To
do so, you must give an OCaml interface (.mli) for the CDuce module
(.cdo). The interface can define arbitrary types, and declare
monomorphic values. These values must be defined in the CDuce module
with a compatible type (subtype of the translation).
</p>
<p>
As an example, suppose you have this CDuce module (foo.cd):
</p>
<sample>
type s = (`A,int) | `B
let double (x : Latin1) : Latin1 = x @ x
let dump (x : s) : Latin1 = string_of x
</sample>
<p>
You can define an OCaml interface for it (foo.mli):
</p>
<sample>
type t = A of int | B
val double: string -> string
val dump: t -> string
</sample>
<p>
When the foo.cdo module is compiled, CDuce will look for the foo.cmi
compiled interface (hence, you must first compile it yourself with
OCaml), and generate stub code, so as to define an OCaml module
<code>Foo</code> with the given interface. This module can then be
linked together with other "regular" OCaml modules, and used from them.
</p>
<p>
Notes:
</p>
<ul>
<li>
It is not mandatory to export all the values of the CDuce module in
the OCaml interface.
</li>
<li>
The types defined in the interface cannot (currently) be used
within the CDuce module.
</li>
</ul>
</box>
<box title="How to compile and link" link="link">
<p>
Here is the protocol to compile a single CDuce module:
</p>
<ul>
<li>
Create a <code>.cmi</code> from your OCaml file with
<code>ocamlc -c foo.mli</code>.
</li>
<li>
Compile your CDuce file <code>cduce --compile foo.cd</code>. This command
will create a CDuce bytecode file <code>foo.cdo</code>, which
also contains the OCaml glue code to export CDuce values as OCaml
ones, and to bind OCaml values used within the CDuce module.
</li>
<li>
Compile the OCaml glue code
<code>ocamlfind ocamlc -c -package cduce -pp "cduce --mlstub" -impl foo.cdo</code>.
The <code>--mlstub</code> option tells CDuce to extract the OCaml
glue code from the CDuce bytecode file. You can directly run
<code>cduce --mlstub</code> on a <code>.cdo</code> file to better
understand how the OCaml/CDuce interface works.
</li>
</ul>
<note>
The command <code>cduce --mlstub</code> must find the
<code>.cmi</code> file for the unit. You need to add an <code>-I</code>
flag if this file is not in the current directory (and additional
flags if other <code>.cmi</code> are referenced).
</note>
<p>
You can then link the resulting OCaml module, maybe with other
modules (either regular ones, or wrapping a CDuce module):
<code>ocamlfind ocamlc -o {{...}} -package cduce -linkpkg foo.cmo
{{...}}</code>.
The content of <code>foo.cdo</code> is wrapped inside the OCaml glue
code; as a consequence, this file is not needed at runtime.
</p>
<p>
Everything works <i>mutatis mutandis</i> with the native OCaml compiler ocamlopt.
</p>
<p>
You might need to pass extra <code>-I</code> flags to CDuce so that
it could find the referenced <code>.cmi</code> files.
</p>
<p>
It is possible to run a CDuce module with <code>cduce --run
foo.cdo</code>, but only if it doesn't use OCaml values. If it
does use OCaml values, you need to produce a custom version
of <code>cduce</code> (to compile and run), see:
<a href="#topl">Calling OCaml from the toplevel</a> section.
</p>
</box>
<box title="Calling OCaml from the toplevel" link="topl">
<p>
The tool <code>cduce_mktop</code> creates custom versions of the CDuce
toplevel/compiler/interpreter with built-in support for some OCaml
modules / functions.
</p>
<sample>
cduce_mktop [-I path | -p package | -l unit ... | -byte ] [target] [primitive file]
</sample>
<p>
The <code>target</code> argument is the file name of the resulting toplevel.
The <code>primitive file</code> argument points to a file whose contents specify a set of built-in
OCaml values to be embedded in the toplevel. Each line must either
be a qualified value (like <code>List.map</code>) or
the name of an OCaml unit (like <code>List</code>). Empty lines
and lines starting with a sharp character are ignored.
</p>
<p>
The <code>-byte</code> flag forces the creation of the bytecode
version of the toplevel (by defaut, the toplevel is produced with ocamlopt).
</p>
<p>
The leading <code>-I</code> options enrich the search path for OCaml
units. The <code>-p</code> options serves a similar purpose; their
arguments are findlib package names. All these paths are included
in the produced toplevel. The <code>-l</code> options give
the OCaml units to be linked in (e.g. <code>x.cmx</code> or
<code>x.cmxa</code>)(the <code>-p</code> option automatically
include the units).
</p>
<p>
In a custom toplevel, the directive <code>#builtins</code> prints the name
of embedded OCaml values.
</p>
</box>
<box title="Examples" link="examples">
<section title="Getting the value of an environment variable">
<sample>
let home = Sys.getenv "home";;
</sample>
</section>
<section title="Ejecting your CD with CDuce">
<p>
This example demonstrates how to use OCamlSDL library.
</p>
<sample>
Sdl.init `None [ `EVERYTHING ];;
let cd = Sdlcdrom.cd_open 0;;
Sdlcdrom.cd_eject cd;;
</sample>
<p>
If you put these lines in a file <code>cdsdl.cd</code>, you can
compile and link it with:
</p>
<sample>
cduce --compile cdsdl.cd -I `ocamlfind query ocamlsdl`
ocamlfind ocamlc -o cdsdl -pp "cduce --mlstub" -impl cdsdl.cdo \
-package cduce,ocamlsdl -linkpkg
</sample>
</section>
<section title="Accessing MySQL">
<p>
This example demonstrates how to use ocaml-mysql library.
</p>
<sample>
let db = Mysql.connect Mysql.defaults;;
match Mysql.list_dbs db `None [] with
| (`Some,l) -> print [ 'Databases: ' !(string_of l) '\n' ]
| `None -> [];;
print [
'Client info: ' !(Mysql.client_info []) '\n'
'Host info: ' !(Mysql.host_info db) '\n'
'Server info: ' !(Mysql.server_info db) '\n'
'Proto info: ' !(string_of (Mysql.proto_info db)) '\n'
];;
</sample>
<p>
If you put these lines in a file <code>cdmysql.cd</code>, you can
compile and link it with:
</p>
<sample>
cduce --compile cdmysql.cd -I `ocamlfind query mysql`
ocamlfind ocamlc -o cdmysql -pp "cduce --mlstub" -impl cdmysql.cdo \
-package cduce,mysql -linkpkg
</sample>
</section>
<section title="Evaluating CDuce expressions">
<p>
This example demonstrates how to dynamically compile
and evaluate CDuce programs contained in a string.
</p>
<sample>
<![CDATA[
let pr = Cduce_lib.Value.print_utf8
try
let l = Cduce_lib.Cduce.eval
"let fun f (x : Int) : Int = x + 1;;
let fun g (x : Int) : Int = 2 * x;;
let x = getenv ['HOME'];;
f;; g;;
let a = g (f 10);;
"
in
let _ = map l with
| ([id], v) ->
pr [ !(string_of id) ' = ' !(string_of v) '\n' ]
| ([], f & (Int -> Int)) ->
pr [ !(string_of (f 100)) '\n' ]
| ([], v) ->
pr [ !(string_of v) '\n' ]
in []
with (exn & Latin1) ->
print [ 'Exception: ' !exn '\n' ]
]]>
</sample>
<p>
If you put these lines in a file <code>eval.cd</code>, you can
compile and link it with:
</p>
<sample>
cduce --compile eval.cd -I `ocamlfind query cduce`
ocamlfind ocamlc -o eval -pp "cduce --mlstub" -impl eval.cdo -package cduce -linkpkg
</sample>
</section>
<section title="Use CDuce to compute the factorial on big integers">
<sample>
(* File cdnum.mli: *)
val fact: Big_int.big_int -> Big_int.big_int
(* File cdnum.cd: *)
let aux ((Int,Int) -> Int)
| (x, 0 | 1) -> x
| (x, n) -> aux (x * n, n - 1)
let fact (x : Int) : Int = aux (Big_int.unit_big_int, x)
(* Could write 1 instead of Big_int.unit_big_int. Just for fun. *)
</sample>
</section>
</box>
</page>
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<page name="manual_interpreter">
<title>Compiler/interpreter/toplevel</title>
<box title="Command-line" link="cmdline">
<p>
According to the command line arguments,
the <code>cduce</code> command behaves
either as an interactive toplevel, an interpreter, a compiler, or
a loader.
</p>
<ul>
<li>
<sample>
cduce [OPTIONS ...] [--arg ARGUMENT ...]
</sample>
<p>
The command operates as an interactive
toplevel. See the <a href="#toplevl">Toplevel</a> section below.
</p>
</li>
<li>
<sample>
cduce [OPTIONS ...] [ {{script}}.cd | --stdin ] [--arg ARGUMENT ...]
</sample>
<sample>
cduce [OPTIONS ...] --script {{script}}.cd [ ARGUMENT ...]
</sample>
<p>
The command runs the script <code>{{script}}.cd</code>.
</p>
</li>
<li>
<sample>
cduce [OPTIONS ...] --compile {{script}}.cd
</sample>
<p>
The command compiles the script <code>{{script}}.cd</code> and
produces <code>{{script}}.cdo</code>. If the OCaml/CDuce interface
is available and enabled, the compilers looks for a corresponding OCaml interface
<code>{{script}}.cmi</code>. See the <local
href="manual_interfacewithocaml"/> page for more information.
</p>
</li>
<li>
<sample>
cduce [OPTIONS ...] --run [ {{script}}.cdo ... ] [--arg ARGUMENT ...]
</sample>
<p>
The command runs one or several pre-compiled scripts.
</p>
</li>
</ul>
<p>
The arguments that follow the <code>--arg</code> option
are the scripts' command line. They can be accessed within
CDuce using the <code>argv</code> operator
(of type <code>[] -> [ String* ]</code>).
</p>
<p>
The options and arguments are:
</p>
<ul>
<li> <code>--verbose</code> (for <code>--compile</code> mode only).
Display the type of values in the compiled unit.</li>
<li> <code>--obj-dir %%directory%%</code> (for <code>--compile</code>
mode only).
Specify where to put the <code>.cdo</code> file (default: same directory as the
source file).</li>
<li> <code>--I %%directory%%</code>
Add a directory to the search path for <code>.cdo</code>,
<code>.cmi</code> and include files. </li>
<li> <code>--stdin</code>. Read CDuce script from standard input. </li>
<li> <code>--no %%feature%%</code>.
Disable one of the built-in optional features. The list of feature and
their symbolic name can be obtained with the <code>-v</code>
option. Can be used for instance to turn the Expat parser off, in
order to use PXP, if both have been included at compile time.
</li>
<li> <code>-v</code>, <code>--version</code>. Show version information
and built-in optional features, and exit.
</li>
<li> <code>--mlstub</code>. See <local href="manual_interfacewithocaml"/>.
</li>