interface.xml 14.4 KB
Newer Older
1
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
2
3
4
<!DOCTYPE page [
  <!ENTITY rarr     "&#8594;"> <!-- rightwards arrow, U+2192 ISOnum -->
]>
5
<page name="manual_interfacewithocaml">
6
7
8
9
10
11

<title>Interfacing CDuce with OCaml</title>

<box title="Introduction" link="intro">

<p>
12
This page describes the CDuce/OCaml interface. This interface allows
13
the programmer to:
14
</p>
15
16
<ul>
<li>call OCaml functions from a CDuce module;</li>
17
<li>export a CDuce model as an OCaml module, by giving it an explicit OCaml signature.</li>
18
</ul>
19
20

<p>
21
The intended usages for the interface are:
22
</p>
23
24
<ul>
<li>Piggyback existing OCaml libraries, such as database, 
25
    network, GUI, data structures;</li>
26
27
28
29
<li>Use CDuce as an XML layer (input/output/transformation) for OCaml
    projects;</li>
<li>Develop fully mixed OCaml/CDuce projects.</li>
</ul>
30

31
32
<p>
To see how to build CDuce with support for the OCaml interface, 
33
see the <a href="INSTALL">INSTALL</a> file from the CDuce distribution.
34
35
36
37
38
39
40
41
42
</p>


</box>

<box title="Translating types" link="transl">

<p>
The heart of the interface is a mapping from OCaml types to CDuce
43
44
45
46
47
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>.
48
</p>
49

50
51
<ul>
<li>
52
53
54
55
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>.
56
</li>
57

58
59
60
61
<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>.
62
Labels and optional labels on the argument of the arrow are discarded.
63
</li>
64

65
<li>
66
A list type <code>%%t%% list</code> is translated to an homogeneous
67
68
sequence type <code>[ T(%%t%%)* ]</code>. An array type
<code>%%t%% array</code> has the same translation.
69
</li>
70

71
72
73
74
<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
75
76
term is <code>`Ai</code>, not <code>(`Ai,[])</code>.
Polymorphic variant types are treated similarly.
77
</li>
78

79
80
81
82
83
<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>
84

85
<li>
86
87
88
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.
89
</li>
90

91
92
93
<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
94
95
96
97
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).
98
</li>
99

100
<li>
101
The type <code>Cduce_lib.Value.t</code> is translated to the CDuce
102
103
104
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.
105
The type <code>Cduce_lib.Encodings.Utf8.t</code> is translated to the CDuce
106
107
108
type <code>String</code>. 
The type <code>Big_int.big_int</code> is translated to the CDuce
type <code>Int</code>.
109
</li>
110

111
<li>
112
113
114
115
116
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).
117
118
119
120
121
</li>
</ul>

<p>
The canonical translation is summarized in the following box:
122
</p>
123

124
125
126

<table border="1" style="align:middle">
<tr>
127
128
<th>OCaml type <tt><i>t</i></tt></th>
<th>CDuce type <tt>T(<i>t</i>)</tt></th>
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
</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>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>
161
<tr><td><tt>Cduce_lib.Encodings.Utf8.t</tt></td><td><tt>String</tt></td></tr>
162
<tr><td><tt>Big_int.big_int</tt></td><td><tt>Int</tt></td></tr>
163
164
</table>

165
<p>
166
167
Only monomorphic types are handled by the interface. It is allowed to
use polymorphic constructors as an intermediate, as long as the final
168
type to be translated is monomorphic. Recursive types, including
169
170
unguarded ones (option <code>-rectypes</code> of the OCaml compiler)
are accepted. In the following example:
171
172
</p>

173
174
175
176
177
178
179
<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>
180
181

<p>
182
183
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.
184
</p>
185

186
<p>
187
OCaml object types are not supported.
188
</p>
189

190
191
192
<p>
Note that values are copied in depth (until reaching an abstract type,
a function types, etc...). In particular, translating an OCaml cyclic
193
values to CDuce will not terminate (well, with a stack overflow!).
194
</p>
195

196
197
198
199
200
201
202
203
204
205
</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>

206
<p>
207
In a CDuce module, you can write <code>M.f</code>
208
to denote the result of translating the OCaml value <code>M.f</code>
209
to CDuce.
210
</p>
211
212
213
214

<p>
If the value you want to use has a polymorphic type, you can make
the translation work by explicitly instantiating its type
215
variables with CDuce types. The syntax is <code>M.f with { t1
216
217
218
219
220
221
... 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>
222
let listmap = List.map with { Int String }
223
224
225
226
227
228
</sample>

<p>
will return a function of type <code>(Int -> String) -> ([Int*] -> [String*])</code>
</p>

229
230
</box>

231
<box title="Calling CDuce from OCaml" link="call_cduce">
232
233

<p>
234
235
236
237
238
239
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).
240
241
</p>

242
243
244
245
246
247
248
249
250
<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>
251

252
<p>
253
You can define an OCaml interface for it (foo.mli):
254
</p>
255

256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
<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>

285
286
</box>

287
<box title="How to compile and link" link="link">
288
289

<p>
290
Here is the protocol to compile a single CDuce module:
291
292
293
294
295
296
297
298
299
</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
300
301
302
    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.
303
304
  </li>
  <li>
305
    Compile the OCaml glue code 
306
    <code>ocamlfind ocamlc -c -package cduce -pp cdo2ml -impl foo.cdo</code>.
307
308
    The<code>cdo2ml</code> tool extracts the OCaml glue code from the
    CDuce bytecode file.
309
310
311
  </li>
</ul>

312
313
314
315
316
317
318
319
320
321
322
323
324
<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>.
  When the program is run, the CDuce bytecode file
  <code>foo.cdo</code> is looked in the <em>current directory</em>
  only, and loaded dynamically (with a checksum test).
</p>

<p>
  It might be preferable to include the CDuce bytecode directly into
  the OCaml glue code. You can do this by giving <code>cdo2ml</code>
  the <code>-static</code> option:
325
  <code>ocamlfind ocamlc -c -package cduce -pp "cdo2ml -static" -impl foo.cdo</code>.
326
327
328
329
330
331
332
333
334
335
336
  Modules which have been compiled this way don't need the
  corresponding <code>.cdo</code> at runtime.
</p>

<p>
  If you choose static linking, you have to use a correct ordering
  when linking with OCaml. Note that it is possible to mix static and
  dynamic linking for various CDuce modules in a same program.
</p>

<p>
337
  Everything works <i>mutatis mutandis</i> with the native OCaml compiler ocamlopt.
338
339
340
341
342
343
344
345
346
</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
347
  foo.cdo</code>, but only if it doesn't use OCaml values.
348
349
350
351
352
353
354
</p>

<p>
  Interested users can look at the output of <code>cdo2ml</code> to
  better understand how the interface works.
</p>

355
</box>
356

357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
<box title="Calling OCaml from the toplevel" link="topl">

<p>
The tool <code>cduce_mktop</code> creates custom versions of the CDuce 
toplevel with built-in support for some OCaml modules / functions.
</p>

<sample>
cduce_mktop [target] [primitive file]
</sample>

<p>
The first argument is the file name of the resulting toplevel.
The second 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
373
374
the name of an OCaml unit (like <code>List</code>). Empty lines
and lines starting with a sharp character are ignored.
375
376
</p>

377
378
379
380
381
<p>
In a custom toplevel, the directive <code>#builtins</code> prints the name
of embedded OCaml values.
</p>

382
383
</box>

384
385
386
387
388
<box title="Examples" link="examples">

<section title="Getting the value of an environment variable">

<sample>
389
let home = Sys.getenv "home";;
390
391
392
393
394
395
396
397
398
399
400
</sample>

</section>

<section title="Ejecting your CD with CDuce">

<p>
This example demonstrates how to use OCamlSDL library.
</p>

<sample>
401
402
403
Sdl.init `None [ `EVERYTHING ];;
let cd = Sdlcdrom.cd_open 0;; 
Sdlcdrom.cd_eject cd;;
404
405
406
407
408
409
410
411
412
</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`
413
ocamlfind ocamlc -o cdsdl -pp "cdo2ml -static" -impl cdsdl.cdo   \ 
414
  -package cduce,ocamlsdl -linkpkg
415
416
417
</sample>


418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
</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`
448
ocamlfind ocamlc -o cdmysql -pp "cdo2ml -static" -impl cdmysql.cdo   \ 
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
  -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;;
   f;; g;; 
   let a = g (f 10);;
  "
 in
 transform l with
  | ((`Some,id),v) -> 
	pr [ !id ' = ' !(string_of v) '\n' ]
  | (`None, f & (Int -> Int)) ->
        pr [ !(string_of (f 100)) '\n' ]
  | (`None,v) -> 
	pr [ !(string_of v) '\n' ]
with (exn & Latin1) ->
  print [ 'Exception: ' !exn  '\n' ]
]]>
</sample>

<p>
488
If you put these lines in a file <code>eval.cd</code>, you can
489
490
491
492
493
494
495
compile and link it with:
</p>

<sample>
cduce --compile eval.cd -I `ocamlfind query cduce`
ocamlfind ocamlc -o eval -pp "cdo2ml -static" -impl eval.cdo   \ 
  -package cduce -linkpkg
496
497
</sample>

498
499
</section>

500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
<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>

521
522
</box>

523
</page>