Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > a2da5eab8fb68605fe995d94e514eeb0 > files > 21

cduce-0.5.3-2mdv2010.0.i586.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>CDuce: Interfacing CDuce with OCaml</title><meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type"/><link type="text/css" rel="stylesheet" href="cduce.css"/></head><body style="margin: 0; padding : 0;"><table border="0" width="100&#37;" cellspacing="10" cellpadding="0"><tr><td valign="top" align="left" style="width:20&#37;;"><div class="leftbar" id="leftbar"><div class="smallbox"><ul><li><a href="#intro">Introduction</a></li><li><a href="#transl">Translating types</a></li><li><a href="#call_ocaml">Calling OCaml from CDuce</a></li><li><a href="#call_cduce">Calling CDuce from OCaml</a></li><li><a href="#link">How to compile and link</a></li><li><a href="#topl">Calling OCaml from the toplevel</a></li><li><a href="#examples">Examples</a></li></ul></div></div></td><td><h1>Interfacing CDuce with OCaml</h1><div class="mainpanel"><div class="smallbox"><p><a href="index.html">CDuce: documentation</a>: <a href="manual.html">User's manual</a>: Interfacing CDuce with OCaml</p><p><a href="manual_schema_samples.html"><img class="icon" width="16" alt="Previous page:" height="16" src="img/left.gif"/> XML Schema sample documents</a> <a href="memento.html"><img class="icon" width="16" alt="Next page:" height="16" src="img/right.gif"/> Quick reference</a></p></div><div><h2><a name="intro">Introduction</a></h2><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></div><div><h2><a name="transl">Translating types</a></h2><p>
The heart of the interface is a mapping from OCaml types to CDuce
types. An OCaml type <b><tt><i>t</i></tt></b> is translated to a CDuce type
<b><tt>T(<i>t</i>)</tt></b>, which is meant to be isomorphic to <b><tt><i>t</i></tt></b>:
there is a canonical function <b><tt><i>t</i></tt></b> &#8594; <b><tt>T(<i>t</i>)</tt></b>
from OCaml values of type <b><tt><i>t</i></tt></b> to CDuce values of type
<b><tt>T(<i>t</i>)</tt></b>, and another canonical function <b><tt>T(<i>t</i>)</tt></b> &#8594; <b><tt><i>t</i></tt></b>.
</p><ul><li>
Basic OCaml types <b><tt>char</tt></b>, <b><tt>int</tt></b>, <b><tt>string</tt></b>,
<b><tt>unit</tt></b> are translated respectively to
<b><tt>Byte = '\0;'--'\255;'</tt></b>, <b><tt>-1073741824 --
1073741823</tt></b>, <b><tt>Latin1 = [ Byte* ]</tt></b>, <b><tt>[] = `nil</tt></b>.
</li><li>
Tuple types <b><tt><i>t</i>1 * ... * <i>t</i>n</tt></b> are translated to nested CDuce
product types <b><tt>(T(<i>t</i>1),(...,T(<i>t</i>n))...)</tt></b>. A function type
<b><tt><i>t</i> -&gt; <i>s</i></tt></b> is translated to <b><tt>T(<i>t</i>) -&gt; T(<i>s</i>)</tt></b>.
Labels on the argument of the arrow are discarded.
</li><li>
A list type <b><tt><i>t</i> list</tt></b> is translated to an homogeneous
sequence type <b><tt>[ T(<i>t</i>)* ]</tt></b>. An array type
<b><tt><i>t</i> array</tt></b> has the same translation.
</li><li>
A option type <b><tt><i>t</i> option</tt></b> is translated to 
the type <b><tt>[ T(<i>t</i>)? ]</tt></b>.
</li><li>
A variant type with a declaration <b><tt>A1 of <i>t</i>1 | ... | An of
<i>t</i>n</tt></b> is translated to a type <b><tt>(`A1,T(<i>t</i>1)) | ... |
(`An,T(<i>t</i>n))</tt></b>. If a constructor <b><tt>Ai</tt></b> has no argument, the resulting
term is <b><tt>`Ai</tt></b>, not <b><tt>(`Ai,[])</tt></b>.
Polymorphic variant types are treated similarly.
</li><li>
A record type with a declaration <b><tt>{ l1 : <i>t</i>1; ...; ln : <i>t</i>n
}</tt></b> is translated to a closed record type <b><tt>{ l1 = T(<i>t</i>1);
... ; ln = T(<i>t</i>n) }</tt></b>. 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 <b><tt><i>t</i> ref</tt></b> is translated to the CDuce
reference type <b><tt>ref T(<i>t</i>)</tt></b>. 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 <b><tt>Cduce_lib.Value.t</tt></b> is translated to the CDuce
type <b><tt>Any</tt></b>. 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 <b><tt>Cduce_lib.Encodings.Utf8.t</tt></b> is translated to the CDuce
type <b><tt>String</tt></b>. 
The type <b><tt>Big_int.big_int</tt></b> is translated to the CDuce
type <b><tt>Int</tt></b>.
</li><li>
A <em>monomorphic</em> abstract type <b><tt>t</tt></b> is translated to
the CDuce type <b><tt>!t</tt></b>. 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 width="100&#37;"><tr><td align="center"><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> -&gt; <i>s</i></tt></td><td><tt>T(<i>t</i>) -&gt; 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></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 <b><tt>-rectypes</tt></b> of the OCaml compiler)
are accepted. In the following example:
</p><div class="code"><pre>
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
</pre></div><p>
the type <b><tt>s</tt></b> can be translated, but the type <b><tt>v</tt></b>
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></div><div><h2><a name="call_ocaml">Calling OCaml from CDuce</a></h2><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 <b><tt>M.f</tt></b>
to denote the result of translating the OCaml value <b><tt>M.f</tt></b>
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 <b><tt>M.f with { t1
... tn }</tt></b> where the <b><tt>ti</tt></b> 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><div class="code"><pre>
let listmap = List.map with { Int String }
</pre></div><p>
will return a function of type <b><tt>(Int -&gt; String) -&gt; ([Int*] -&gt; [String*])</tt></b></p></div><div><h2><a name="call_cduce">Calling CDuce from OCaml</a></h2><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><div class="code"><pre>
type s = (`A,int) | `B
let double (x : Latin1) : Latin1 = x @ x
let dump (x : s) : Latin1 = string_of x
</pre></div><p>
You can define an OCaml interface for it (foo.mli):
</p><div class="code"><pre>
type t = A of int | B
val double: string -&gt; string
val dump: t -&gt; string
</pre></div><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
<b><tt>Foo</tt></b> with the given interface. This module can then be
linked together with other &quot;regular&quot; 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></div><div><h2><a name="link">How to compile and link</a></h2><p>
Here is the protocol to compile a single CDuce module:
</p><ul><li>
    Create a <b><tt>.cmi</tt></b> from your OCaml file with 
    <b><tt>ocamlc -c foo.mli</tt></b>.
  </li><li>
    Compile your CDuce file <b><tt>cduce --compile foo.cd</tt></b>. This command
    will create a CDuce bytecode file <b><tt>foo.cdo</tt></b>, 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 
    <b><tt>ocamlfind ocamlc -c -package cduce -pp &quot;cduce --mlstub&quot; -impl foo.cdo</tt></b>.
    The <b><tt>--mlstub</tt></b> option tells CDuce to extract the OCaml
    glue code from the CDuce bytecode file. You can directly run
    <b><tt>cduce --mlstub</tt></b> on a <b><tt>.cdo</tt></b> file to better 
    understand how the OCaml/CDuce interface works.
  </li></ul><div class="note"><b>Note:  </b>
The command <b><tt>cduce --mlstub</tt></b> must find the
<b><tt>.cmi</tt></b> file for the unit. You need to add an <b><tt>-I</tt></b>
flag if this file is not in the current directory (and additional
flags if other <b><tt>.cmi</tt></b> are referenced).
</div><p>
  You can then link the resulting OCaml module, maybe with other
  modules (either regular ones, or wrapping a CDuce module):
  <b><tt>ocamlfind ocamlc -o <strong class="highlight">...</strong> -package cduce -linkpkg foo.cmo
  <strong class="highlight">...</strong></tt></b>.
  The content of <b><tt>foo.cdo</tt></b> 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 <b><tt>-I</tt></b> flags to CDuce so that
  it could find the referenced <b><tt>.cmi</tt></b> files.
</p><p>
  It is possible to run a CDuce module with <b><tt>cduce --run
  foo.cdo</tt></b>, but only if it doesn't use OCaml values. If it
  does use OCaml values, you need to produce a custom version
  of <b><tt>cduce</tt></b> (to compile and run), see:
  <a href="#topl">Calling OCaml from the toplevel</a> section.
</p></div><div><h2><a name="topl">Calling OCaml from the toplevel</a></h2><p>
The tool <b><tt>cduce_mktop</tt></b> creates custom versions of the CDuce 
toplevel/compiler/interpreter with built-in support for some OCaml 
modules / functions.
</p><div class="code"><pre>
cduce_mktop [-I path | -p package | -l unit ... | -byte ] [target] [primitive file]
</pre></div><p>
The <b><tt>target</tt></b> argument is the file name of the resulting toplevel.
The <b><tt>primitive file</tt></b> 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 <b><tt>List.map</tt></b>) or
the name of an OCaml unit (like <b><tt>List</tt></b>). Empty lines
and lines starting with a sharp character are ignored.
</p><p>
The <b><tt>-byte</tt></b> flag forces the creation of the bytecode
version of the toplevel (by defaut, the toplevel is produced with ocamlopt).
</p><p>
The leading <b><tt>-I</tt></b> options enrich the search path for OCaml
units. The <b><tt>-p</tt></b> options serves a similar purpose; their
arguments are findlib package names. All these paths are included
in the produced toplevel. The <b><tt>-l</tt></b> options give
the OCaml units to be linked in (e.g. <b><tt>x.cmx</tt></b> or
<b><tt>x.cmxa</tt></b>)(the <b><tt>-p</tt></b> option automatically
include the units).
</p><p>
In a custom toplevel, the directive <b><tt>#builtins</tt></b> prints the name
of embedded OCaml values.
</p></div><div><h2><a name="examples">Examples</a></h2><h3>Getting the value of an environment variable</h3><div class="code"><pre>
let home = Sys.getenv &quot;home&quot;;;
</pre></div><h3>Ejecting your CD with CDuce</h3><p>
This example demonstrates how to use OCamlSDL library.
</p><div class="code"><pre>
Sdl.init `None [ `EVERYTHING ];;
let cd = Sdlcdrom.cd_open 0;; 
Sdlcdrom.cd_eject cd;;
</pre></div><p>
If you put these lines in a file <b><tt>cdsdl.cd</tt></b>, you can
compile and link it with:
</p><div class="code"><pre>
cduce --compile cdsdl.cd -I `ocamlfind query ocamlsdl`
ocamlfind ocamlc -o cdsdl -pp &quot;cduce --mlstub&quot; -impl cdsdl.cdo   \ 
  -package cduce,ocamlsdl -linkpkg
</pre></div><h3>Accessing MySQL</h3><p>
This example demonstrates how to use ocaml-mysql library.
</p><div class="code"><pre>
let db = Mysql.connect Mysql.defaults;;

match Mysql.list_dbs db `None [] with
 | (`Some,l) -&gt; print [ 'Databases: ' !(string_of l) '\n' ]
 | `None -&gt; [];;

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'
];;
</pre></div><p>
If you put these lines in a file <b><tt>cdmysql.cd</tt></b>, you can
compile and link it with:
</p><div class="code"><pre>
cduce --compile cdmysql.cd -I `ocamlfind query mysql`
ocamlfind ocamlc -o cdmysql -pp &quot;cduce --mlstub&quot; -impl cdmysql.cdo   \ 
  -package cduce,mysql -linkpkg
</pre></div><h3>Evaluating CDuce expressions</h3><p>
This example demonstrates how to dynamically compile
and evaluate CDuce programs contained in a string.
</p><div class="code"><pre>

let pr = Cduce_lib.Value.print_utf8

try
 let l = Cduce_lib.Cduce.eval 
  &quot;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);;
  &quot;
 in
 let _ = map l with
  | ([id], v) -&gt; 
	pr [ !(string_of id) ' = ' !(string_of v) '\n' ]
  | ([], f &amp; (Int -&gt; Int)) -&gt;
        pr [ !(string_of (f 100)) '\n' ]
  | ([], v) -&gt; 
	pr [ !(string_of v) '\n' ]
 in []
with (exn &amp; Latin1) -&gt;
  print [ 'Exception: ' !exn  '\n' ]

</pre></div><p>
If you put these lines in a file <b><tt>eval.cd</tt></b>, you can
compile and link it with:
</p><div class="code"><pre>
cduce --compile eval.cd -I `ocamlfind query cduce`
ocamlfind ocamlc -o eval -pp &quot;cduce --mlstub&quot; -impl eval.cdo -package cduce -linkpkg
</pre></div><h3>Use CDuce to compute the factorial on big integers</h3><div class="code"><pre>
(* File cdnum.mli: *)

val fact: Big_int.big_int -&gt; Big_int.big_int


(* File cdnum.cd: *)

let aux ((Int,Int) -&gt; Int)
 | (x, 0 | 1) -&gt; x
 | (x, n) -&gt; 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. *)

</pre></div></div><div class="meta"><p><a href="sitemap.html">Site map</a></p></div><div class="smallbox"><p><a href="index.html">CDuce: documentation</a>: <a href="manual.html">User's manual</a>: Interfacing CDuce with OCaml</p><p><a href="manual_schema_samples.html"><img class="icon" width="16" alt="Previous page:" height="16" src="img/left.gif"/> XML Schema sample documents</a> <a href="memento.html"><img class="icon" width="16" alt="Next page:" height="16" src="img/right.gif"/> Quick reference</a></p></div></div></td></tr></table></body></html>