/[svn]/cduce/trunk/ocamliface/mlstub.ml
ViewVC logotype

Contents of /cduce/trunk/ocamliface/mlstub.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4021 - (show annotations)
Sun Sep 26 07:23:38 2010 UTC (2 years, 7 months ago) by jmaloberti
File size: 21156 byte(s)
Fix a compilation issue with the previous patch.
1 #load "q_MLast.cmo";;
2 (* TODO:
3 - optimizations: generate labels and atoms only once.
4 - translate record to open record on positive occurence
5 *)
6
7 open Mltypes
8 open Ident
9 open Camlp4.PreCast
10
11 let _loc = Loc.ghost
12
13 module IntMap =
14 Map.Make(struct type t = int let compare : t -> t -> int = compare end)
15
16 module IntHash =
17 Hashtbl.Make(struct type t = int let hash i = i let equal i j = i == j end)
18
19 (* Compute CDuce type *)
20
21 let vars = ref [||]
22
23 let memo_typ = IntHash.create 13
24
25 let atom lab = Types.atom (Atoms.atom (Atoms.V.mk_ascii lab))
26 let label lab = Label.mk (Ns.empty, U.mk lab)
27 let bigcup f l = List.fold_left (fun accu x -> Types.cup accu (f x)) Types.empty l
28
29 let id s =
30 let rec aux i : Ast.ident =
31 try
32 let j = String.index_from s i '.' in
33 <:ident< $uid:String.sub s i (j - i)$.$aux (j+1)$ >>
34 with Not_found ->
35 <:ident< $lid:String.sub s i (String.length s - i)$ >>
36 in
37 (* Printf.eprintf "*** %S\n" s; *)
38 aux 0
39
40 let consId s =
41 let rec aux i : Ast.ident =
42 try
43 let j = String.index_from s i '.' in
44 <:ident< $uid:String.sub s i (j - i)$.$aux (j+1)$ >>
45 with Not_found ->
46 <:ident< $uid:String.sub s i (String.length s - i)$ >>
47 in
48 aux 0
49
50 let rec typ t =
51 try IntHash.find memo_typ t.uid
52 with Not_found ->
53 (* print_int t.uid; print_char ' '; flush stdout; *)
54 let node = Types.make () in
55 IntHash.add memo_typ t.uid node;
56 Types.define node (typ_descr t.def);
57 node
58
59 and typ_descr = function
60 | Link t -> typ_descr t.def
61 | Arrow (_,t,s) -> Types.arrow (typ t) (typ s)
62 | Tuple tl -> Types.tuple (List.map typ tl)
63 | PVariant l -> bigcup pvariant l
64 | Variant (_,l,_) -> bigcup variant l
65 | Record (_,l,_) ->
66 let l = List.map (fun (lab,t) -> label lab, typ t) l in
67 Types.record_fields (false,(LabelMap.from_list_disj l))
68 | Abstract "int" -> Builtin_defs.caml_int
69 | Abstract "char" -> Builtin_defs.char_latin1
70 | Abstract "string" -> Builtin_defs.string_latin1
71 | Abstract s -> Types.abstract (Types.Abstract.atom s)
72 | Builtin ("list", [t])
73 | Builtin ("array", [t]) -> Types.descr (Sequence.star_node (typ t))
74 | Builtin ("Pervasives.ref", [t]) -> Builtin_defs.ref_type (typ t)
75 | Builtin ("Big_int.big_int", []) -> Builtin_defs.int
76 | Builtin ("Cduce_lib.Value.t", []) -> Types.any
77 | Builtin ("Cduce_lib.Encodings.Utf8.t", []) -> Builtin_defs.string
78 | Builtin ("Cduce_lib.Atoms.V.t", []) -> Builtin_defs.atom
79 | Builtin ("unit", []) -> Sequence.nil_type
80 | Builtin ("option", [t]) -> Sequence.option (typ t)
81 | Var i -> Types.descr (!vars).(i)
82 | _ -> assert false
83
84 and pvariant = function
85 | (lab, None) -> atom lab
86 | (lab, Some t) -> Types.times (Types.cons (atom lab)) (typ t)
87
88 and variant = function
89 | (lab, []) -> atom lab
90 | (lab, c) -> Types.tuple (Types.cons (atom lab) :: List.map typ c)
91
92
93 (* Syntactic tools *)
94
95 let var_counter = ref 0
96 let mk_var _ =
97 incr var_counter;
98 Printf.sprintf "x%i" !var_counter
99
100 let mk_vars = List.map mk_var
101
102 let atom_ascii lab =
103 <:expr< Value.atom_ascii $str: String.escaped lab$ >>
104
105 let label_ascii lab =
106 <:expr< Value.label_ascii $str: String.escaped lab$ >>
107
108 let pair e1 e2 = <:expr< Value.Pair ($e1$,$e2$) >>
109
110 let pmatch e l =
111 <:expr< match $e$ with [ $list:l$ ] >>
112
113 let rec matches ine oute = function
114 | [v1;v2] ->
115 <:expr< let ($lid:v1$,$lid:v2$) = Value.get_pair $ine$ in $oute$ >>
116 | v::vl ->
117 let r = mk_var () in
118 let oute = matches <:expr< $lid:r$ >> oute vl in
119 <:expr< let ($lid:v$,$lid:r$) = Value.get_pair $ine$ in $oute$ >>
120 | [] -> assert false
121
122 let list_lit el =
123 List.fold_right (fun a e -> <:expr< [$a$ :: $e$] >>) el <:expr< [] >>
124
125 let protect e f =
126 match e with
127 | <:expr< $lid:x$ >> -> f e
128 | e ->
129 let x = mk_var () in
130 let r = f <:expr< $lid:x$ >> in
131 <:expr< let $lid:x$ = $e$ in $r$ >>
132
133 (* Registered types *)
134
135 let gen_types = ref true
136 (* currently always off *)
137
138
139 module HashTypes = Hashtbl.Make(Types)
140 let registered_types = HashTypes.create 13
141 let nb_registered_types = ref 0
142
143 let register_type t =
144 assert(!gen_types);
145 let n =
146 try HashTypes.find registered_types t
147 with Not_found ->
148 let i = !nb_registered_types in
149 HashTypes.add registered_types t i;
150 incr nb_registered_types;
151 i
152 in
153 <:expr< types.($int:string_of_int n$) >>
154
155 let get_registered_types () =
156 let a = Array.make !nb_registered_types Types.empty in
157 HashTypes.iter (fun t i -> a.(i) <- t) registered_types;
158 a
159
160 (* OCaml -> CDuce conversions *)
161
162
163 let to_cd_gen = ref []
164
165 let to_cd_fun_name t =
166 Printf.sprintf "to_cd_%i" t.uid
167
168 let to_cd_fun t =
169 to_cd_gen := t :: !to_cd_gen;
170 to_cd_fun_name t
171
172 let to_ml_gen = ref []
173
174 let to_ml_fun_name t =
175 Printf.sprintf "to_ml_%i" t.uid
176
177 let to_ml_fun t =
178 to_ml_gen := t :: !to_ml_gen;
179 to_ml_fun_name t
180
181 let rec tuple = function
182 | [v] -> v
183 | v::l -> <:expr< Value.Pair ($v$, $tuple l$) >>
184 | [] -> assert false
185
186 let pat_tuple vars =
187 let pl = List.map (fun id -> <:patt< $lid:id$ >>) vars in
188 <:patt< ($Ast.paCom_of_list pl$) >>
189
190
191 let call_lab f l x =
192 if l = "" then <:expr< $f$ $x$ >>
193 else
194 if l.[0] = '?' then
195 let l = String.sub l 1 (String.length l - 1) in
196 <:expr< $f$ (? $l$ : $x$) >>
197 else
198 <:expr< $f$ (~ $l$ : $x$) >>
199
200 let abstr_lab l x res =
201 if l = "" then <:expr< fun $lid:x$ -> $res$ >>
202 else
203 if l.[0] = '?' then
204 let l = String.sub l 1 (String.length l - 1) in
205 <:expr< fun ? $l$ : ( $lid:x$ ) -> $res$ >>
206 else
207 <:expr< fun ~ $l$ : $lid:x$ -> $res$ >>
208
209
210
211 let rec to_cd e t =
212 (* Format.fprintf Format.err_formatter "to_cd %a [uid=%i; recurs=%i]@."
213 Mltypes.print t t.uid t.recurs; *)
214 if t.recurs > 0 then <:expr< $lid:to_cd_fun t$ $e$ >>
215 else to_cd_descr e t.def
216
217 and to_cd_descr e = function
218 | Link t -> to_cd e t
219 | Arrow (l,t,s) ->
220 (* let y = <...> in Value.Abstraction ([t,s], fun x -> s(y ~l:(t(x))) *)
221 protect e
222 (fun y ->
223 let x = mk_var () in
224 let arg = to_ml <:expr< $lid:x$ >> t in
225 let res = to_cd (call_lab y l arg) s in
226 let abs = <:expr< fun $lid:x$ -> $res$ >> in
227 let iface =
228 if !gen_types then
229 let tt = register_type (Types.descr (typ t)) in
230 let ss = register_type (Types.descr (typ s)) in
231 <:expr< Some [($tt$,$ss$)] >>
232 else <:expr< None >> in
233 <:expr< Value.Abstraction ($iface$,$abs$) >>
234 )
235 | Tuple tl ->
236 (* let (x1,...,xn) = ... in Value.Pair (t1(x1), Value.Pair(...,tn(xn))) *)
237 let vars = mk_vars tl in
238 <:expr< let $pat_tuple vars$ = $e$ in $tuple (tuple_to_cd tl vars)$ >>
239 | PVariant l ->
240 (* match <...> with
241 | `A -> Value.atom_ascii "A"
242 | `B x -> Value.Pair (Value.atom_ascii "B",t(x))
243 *)
244 let cases =
245 List.map
246 (function
247 | (lab,None) -> <:match_case< `$lid:lab$ -> $atom_ascii lab$ >>
248 | (lab,Some t) -> <:match_case< `$lid:lab$ x ->
249 $pair (atom_ascii lab) (to_cd <:expr< x >> t)$ >>
250 ) l in
251 pmatch e cases
252 | Variant (p,l,_) ->
253 (* match <...> with
254 | P.A -> Value.atom_ascii "A"
255 | P.B (x1,x2,..) -> Value.Pair (Value.atom_ascii "B",...,Value.Pair(tn(x)))
256 *)
257 let cases =
258 List.map
259 (function
260 | (lab,[]) ->
261 let pat = match lab with (* Stupid Camlp4 *)
262 | "true" -> <:patt< True >>
263 | "false" -> <:patt< False >>
264 | lab -> <:patt< $id: id (p^lab)$ >>
265 in
266 <:match_case< $pat$ -> $atom_ascii lab$ >>
267 | (lab,tl) ->
268 let vars = mk_vars tl in
269 <:match_case< $id: id (p^lab)$ $pat_tuple vars$ ->
270 $tuple (atom_ascii lab :: tuple_to_cd tl vars)$ >>
271 ) l in
272 pmatch e cases
273 | Record (p,l,_) ->
274 (* let x = <...> in Value.record [ l1,t1(x.P.l1); ...; ln,x.P.ln ] *)
275 protect e
276 (fun x ->
277 let l =
278 List.map
279 (fun (lab,t) ->
280 let e = to_cd <:expr<$x$.$id:id (p^lab)$>> t in
281 <:expr< ($label_ascii lab$, $e$) >>)
282 l
283 in
284 <:expr< Value.record $list_lit l$ >>)
285
286 | Abstract "int" -> <:expr< Value.ocaml2cduce_int $e$ >>
287 | Abstract "char" -> <:expr< Value.ocaml2cduce_char $e$ >>
288 | Abstract "string" -> <:expr< Value.ocaml2cduce_string $e$ >>
289 | Abstract s -> <:expr< Value.abstract $str:String.escaped s$ $e$ >>
290 | Builtin ("list",[t]) ->
291 (* Value.sequence_rev (List.rev_map fun_t <...>) *)
292 <:expr< Value.sequence_rev (List.rev_map $lid:to_cd_fun t$ $e$) >>
293 | Builtin ("array",[t]) ->
294 <:expr< Value.sequence_rev (List.rev_map $lid:to_cd_fun t$ (Array.to_list $e$)) >>
295 | Builtin ("Pervasives.ref",[t]) ->
296 (* let x = <...> in
297 Value.mk_ext_ref t (fun () -> t(!x)) (fun y -> x := t'(y)) *)
298 protect e
299 (fun e ->
300 let y = mk_var () in
301 let tt = if !gen_types then
302 let t = register_type (Types.descr (typ t)) in
303 <:expr< Some $t$ >>
304 else
305 <:expr< None >> in
306 let get_x = <:expr< $e$.val >> in
307 let get = <:expr< fun () -> $to_cd get_x t$ >> in
308 let tr_y = to_ml <:expr< $lid:y$ >> t in
309 let set = <:expr< fun $lid:y$ -> $e$.val := $tr_y$ >> in
310 <:expr< Value.mk_ext_ref $tt$ $get$ $set$ >>
311 )
312 | Builtin ("Big_int.big_int", []) ->
313 <:expr< Value.ocaml2cduce_bigint $e$ >>
314 | Builtin ("Cduce_lib.Value.t", []) -> e
315 | Builtin ("Cduce_lib.Encodings.Utf8.t", []) ->
316 <:expr< Value.ocaml2cduce_string_utf8 $e$ >>
317 | Builtin ("Cduce_lib.Atoms.V.t", []) ->
318 <:expr< Value.ocaml2cduce_atom $e$ >>
319 | Builtin ("unit", []) -> <:expr< do { $e$; Value.nil } >>
320 | Var _ -> e
321 | Builtin ("option", [t]) ->
322 <:expr< Value.ocaml2cduce_option $lid:to_cd_fun t$ $e$ >>
323
324 | _ -> assert false
325
326 and tuple_to_cd tl vars = List.map2 (fun t id -> to_cd <:expr< $lid:id$ >> t) tl vars
327
328 (* CDuce -> OCaml conversions *)
329
330
331
332 and to_ml (e : Ast.expr) (t : Mltypes.t) =
333 (* Format.fprintf Format.err_formatter "to_ml %a@."
334 Mltypes.print t; *)
335 if t.recurs > 0 then <:expr< $lid:to_ml_fun t$ $e$ >>
336 else to_ml_descr e t.def
337
338 and to_ml_descr e = function
339 | Link t -> to_ml e t
340 | Arrow (l,t,s) ->
341 (* let y = <...> in fun ~l:x -> s(Eval.eval_apply y (t(x))) *)
342 protect e
343 (fun y ->
344 let x = mk_var () in
345 let arg = to_cd <:expr< $lid:x$ >> t in
346 let res = to_ml <:expr< Eval.eval_apply $y$ $arg$ >> s in
347 abstr_lab l x res
348 )
349
350 | Tuple tl ->
351 (* let (x1,r) = Value.get_pair <...> in
352 let (x2,r) = Value.get_pair r in
353 ...
354 let (xn-1,xn) = Value.get_pair r in
355 (t1(x1),...,tn(xn)) *)
356
357 let vars = mk_vars tl in
358 matches e <:expr< $tuple_to_ml tl vars$ >> vars
359 | PVariant l ->
360 (* match Value.get_variant <...> with
361 | "A",None -> `A
362 | "B",Some x -> `B (t(x))
363 | _ -> assert false
364 *)
365 let cases =
366 List.map
367 (function
368 | (lab,None) ->
369 <:match_case<
370 ($str: String.escaped lab$, None) -> `$lid:lab$ >>
371 | (lab,Some t) ->
372 let x = mk_var () in
373 let ex = <:expr< $lid:x$ >> in
374 <:match_case<
375 ($str: String.escaped lab$, Some $lid:x$) ->
376 `$lid:lab$ $to_ml ex t$ >>
377 ) l in
378 let cases = cases @ [ <:match_case< _ -> assert False >> ] in
379 pmatch <:expr< Value.get_variant $e$ >> cases
380 | Variant (_,l,false) ->
381 failwith "Private Sum type"
382 | Variant (p,l,true) ->
383 (* match Value.get_variant <...> with
384 | "A",None -> P.A
385 | "B",Some x -> let (x1,r) = x in ...
386 *)
387 let cases =
388 List.map
389 (function
390 | (lab,[]) ->
391 let pa = <:patt< ($str: String.escaped lab$, None) >>
392 and e = match lab with (* Stupid Camlp4 *)
393 | "true" -> <:expr< True >>
394 | "false" -> <:expr< False >>
395 | lab -> <:expr< $id:id (p ^ lab)$ >> in
396 <:match_case< $pa$ -> $e$ >>
397 | (lab,[t]) ->
398 let x = mk_var () in
399 let ex = <:expr< $lid:x$ >> in
400 <:match_case< ($str: String.escaped lab$, Some $lid:x$) ->
401 $id:id (p ^ lab)$ $to_ml ex t$ >>
402 | (lab,tl) ->
403 let vars = mk_vars tl in
404 let x = mk_var () in
405 <:match_case< ($str: String.escaped lab$, Some $lid:x$) ->
406 $ matches
407 <:expr< $lid:x$ >> (
408 List.fold_left
409 (fun x (t, id) ->
410 Ast.ExApp(_loc, x, <:expr<$to_ml <:expr< $lid:id$ >> t$>>))
411 <:expr< $id:consId (p ^ lab)$ >>
412 (List.combine tl vars))
413 vars $ >>
414 ) l in
415 let cases = cases @ [ <:match_case< _ -> assert False >> ] in
416 pmatch <:expr< Value.get_variant $e$ >> cases
417 | Record (_,l,false) ->
418 failwith "Private Record type"
419 | Record (p,l,true) ->
420 (* let x = <...> in
421 { P.l1 = t1(Value.get_field x "l1"); ... } *)
422 protect e
423 (fun x ->
424 let l =
425 List.map
426 (fun (lab,t) ->
427 let e =
428 to_ml <:expr< Value.get_field $x$ $label_ascii lab$ >> t in
429 <:rec_binding< $id: id (p^lab)$ = $e$ >>) l in
430 <:expr< {$list:l$} >>)
431
432 | Abstract "int" -> <:expr< Value.cduce2ocaml_int $e$ >>
433 | Abstract "char" -> <:expr< Value.cduce2ocaml_char $e$ >>
434 | Abstract "string" -> <:expr< Value.cduce2ocaml_string $e$ >>
435 | Abstract s -> <:expr< Value.get_abstract $e$ >>
436 | Builtin ("list",[t]) ->
437 (* List.rev_map fun_t (Value.get_sequence_rev <...> *)
438 <:expr< List.rev_map $lid:to_ml_fun t$ (Value.get_sequence_rev $e$) >>
439 | Builtin ("array",[t]) ->
440 (* List.rev_map fun_t (Value.get_sequence_rev <...> *)
441 <:expr< Array.of_list (List.rev_map $lid:to_ml_fun t$ (Value.get_sequence_rev $e$)) >>
442 | Builtin ("Pervasives.ref",[t]) ->
443 (* ref t(Eval.eval_apply (Value.get_field <...> "get") Value.nil) *)
444 let e = <:expr< Value.get_field $e$ $label_ascii "get"$ >> in
445 let e = <:expr< Eval.eval_apply $e$ Value.nil >> in
446 <:expr< Pervasives.ref $to_ml e t$ >>
447 | Builtin ("Big_int.big_int", []) ->
448 <:expr< Value.cduce2ocaml_bigint $e$ >>
449 | Builtin ("Cduce_lib.Value.t", []) -> e
450 | Builtin ("Cduce_lib.Encodings.Utf8.t", []) ->
451 <:expr< Value.cduce2ocaml_string_utf8 $e$ >>
452 | Builtin ("Cduce_lib.Atoms.V.t", []) ->
453 <:expr< Value.cduce2ocaml_atom $e$ >>
454 | Builtin ("unit", []) -> <:expr< ignore $e$ >>
455 | Builtin ("option", [t]) ->
456 <:expr< Value.cduce2ocaml_option $lid:to_ml_fun t$ $e$ >>
457 | Var _ -> e
458 | _ -> assert false
459
460 and tuple_to_ml tl vars =
461 Ast.exCom_of_list
462 (List.map2 (fun t id -> to_ml <:expr< $lid:id$ >> t) tl vars)
463
464
465 let to_ml_done = IntHash.create 13
466 let to_cd_done = IntHash.create 13
467
468 let global_transl () =
469 let defs = ref [] in
470 let rec aux hd tl gen don fun_name to_descr =
471 gen := tl;
472 if not (IntHash.mem don hd.uid) then (
473 IntHash.add don hd.uid ();
474 let p = <:patt< $lid:fun_name hd$ >> in
475 let e = <:expr< fun x -> $to_descr <:expr< x >> hd.def$ >> in
476 defs := <:binding< $p$ = $e$ >> :: !defs
477 );
478 loop ()
479 and loop () = match !to_cd_gen,!to_ml_gen with
480 | hd::tl,_ -> aux hd tl to_cd_gen to_cd_done to_cd_fun_name to_cd_descr
481 | _,hd::tl -> aux hd tl to_ml_gen to_ml_done to_ml_fun_name to_ml_descr
482 | [],[] -> ()
483 in
484 loop ();
485 !defs
486
487 (* Check type constraints and generate stub code *)
488
489 let err_ppf = Format.err_formatter
490
491 let exts = ref []
492
493 let check_value ty_env c_env (s,caml_t,t) =
494 (* Find the type for the value in the CDuce module *)
495 let id = (Ns.empty, U.mk s) in
496 let vt =
497 try Typer.find_value id ty_env
498 with Not_found ->
499 Format.fprintf err_ppf
500 "The interface exports a value %s which is not available in the module@." s;
501 exit 1
502 in
503 (* Compute expected CDuce type *)
504 let et = Types.descr (typ t) in
505
506 (* Check subtyping *)
507 if not (Types.subtype vt et) then
508 (
509 Format.fprintf
510 err_ppf
511 "The type for the value %s is invalid@\n\
512 Expected Caml type:@[%a@]@\n\
513 Expected CDuce type:@[%a@]@\n\
514 Inferred type:@[%a@]@."
515 s
516 print_ocaml caml_t
517 Types.Print.print et
518 Types.Print.print vt;
519 exit 1
520 );
521
522 (* Generate stub code *)
523 let x = mk_var () in
524 let slot = Compile.find_slot id c_env in
525 let e = to_ml <:expr< slots.($int:string_of_int slot$) >> t in
526 <:patt< $lid:s$ >>, <:expr< C.$lid:x$ >>, <:binding< $lid:x$ = $e$ >>
527
528 module Cleaner = Camlp4.Struct.CleanAst.Make(Ast)
529
530 let cleaner = object
531 inherit Cleaner.clean_ast as super
532 method str_item st =
533 match super#str_item st with
534 | <:str_item< value $rec:_$ $ <:binding< >> $ >> ->
535 <:str_item< >>
536 | x -> x
537 end
538
539
540 let stub ty_env c_env exts values mk prolog =
541 gen_types := false;
542 let items = List.map (check_value ty_env c_env) values in
543
544 let exts = List.rev_map (fun (s,t) -> to_cd <:expr< $id:id s$ >> t) exts in
545 let g = global_transl () in
546
547 let types = get_registered_types () in
548 let raw = mk types in
549
550 let items_def = List.map (fun (_,_,d) -> d) items in
551 let items_expr = List.map (fun (_,e,_) -> e) items in
552 let items_pat = List.map (fun (p,_,_) -> p) items in
553
554 let str_items =
555 <:str_item<
556 value $tup:Ast.paCom_of_list items_pat$ =
557 let module C = struct
558 open Cduce_lib;
559 Cduce_config.init_all ();
560 value (types,set_externals,slots,run) =
561 Librarian.ocaml_stub $str:String.escaped raw$;
562 value rec $Ast.biAnd_of_list g$;
563 set_externals [|$Ast.exSem_of_list exts$|];
564 run ();
565 value $Ast.biAnd_of_list items_def$;
566 end in $tup:Ast.exCom_of_list items_expr$ >> in
567
568 print_endline prolog;
569 try Printers.OCaml.print_implem (cleaner # str_item str_items)
570 with exn -> Format.printf "@."; raise exn
571 (* let exe = Filename.concat (Filename.dirname Sys.argv.(0)) "cdo2ml" in
572 let oc = Unix.open_process_out exe in
573 Marshal.to_channel oc str_items [];
574 flush oc;
575 ignore (Unix.close_process_out oc) *)
576
577
578 let stub_ml name ty_env c_env exts mk =
579 try
580 let name = String.capitalize name in
581 let exts = match (Obj.magic exts : (string * Mltypes.t) list option) with
582 | None -> []
583 | Some exts -> List.iter (fun (_,t) -> Mltypes.reg_uid t) exts; exts in
584 (* First, read the description of ML types for externals.
585 Don't forget to call reg_uid to avoid uid clashes...
586 Do that before reading the cmi. *)
587 let (prolog, values) =
588 try Mltypes.read_cmi name
589 with Not_found -> ("",[]) in
590 stub ty_env c_env exts values mk prolog
591 with Mltypes.Error s -> raise (Cduce_loc.Generic s)
592
593
594 let register b s args =
595 try
596 let (t,n) = Mltypes.find_value s in
597 let m = List.length args in
598 if n <> m then
599 Cduce_loc.raise_generic
600 (Printf.sprintf
601 "Wrong arity for external symbol %s (real arity = %i; given = %i)" s n m);
602 let i = if b then
603 let i = List.length !exts in
604 exts := (s, t) :: !exts;
605 i
606 else
607 0 in
608
609 vars := Array.of_list args;
610 let cdt = Types.descr (typ t) in
611 vars := [| |];
612 i,cdt
613 with Not_found ->
614 Cduce_loc.raise_generic
615 (Printf.sprintf "Cannot resolve ocaml external %s" s)
616
617 (* Generation of wrappers *)
618
619 let wrapper values =
620 gen_types := false;
621 let exts = List.rev_map
622 (fun (s,t) ->
623 let v = to_cd <:expr< $lid:s$ >> t in
624 <:str_item<
625 Librarian.register_static_external $str:String.escaped s$ $v$ >>)
626 values in
627 let g = global_transl () in
628
629 <:str_item<
630 open Cduce_lib;
631 Cduce_config.init_all ();
632 value rec $Ast.biAnd_of_list g$;
633 $Ast.stSem_of_list exts$;
634 >>
635
636 let gen_wrapper vals =
637 try
638 let values = List.fold_left
639 (fun accu s ->
640 try (s,fst (Mltypes.find_value s)) :: accu
641 with Not_found ->
642 let vals =
643 try Mltypes.load_module s
644 with Not_found ->
645 failwith ("Cannot resolve " ^ s)
646 in
647 vals @ accu
648 ) [] vals in
649
650 wrapper values
651 with Mltypes.Error s -> raise (Cduce_loc.Generic s)
652
653 let make_wrapper fn =
654 let ic = open_in fn in
655 let v = ref [] in
656 (try while true do
657 let s = input_line ic in
658 if s <> "" then
659 match s.[0] with
660 | 'A'..'Z' -> v := s :: !v
661 | '#' -> ()
662 | _ -> failwith "Error in primitive file: names must start with a capitalized letter"
663 done
664 with End_of_file -> ());
665 let s = gen_wrapper !v in
666 Printers.OCaml.print_implem s;
667 print_endline "let () = Cduce_loc.obj_path := [";
668 List.iter (fun s -> Printf.printf " %S;\n" s) !Cduce_loc.obj_path;
669 print_endline " ];;";
670 print_endline "let () = Run.main ();;"
671
672
673 (* Dynamic coercions *)
674
675
676 (*
677 let to_cd_dyn = function
678 | Link t -> to_cd_dyn e t
679 | Arrow (l,t,s) ->
680 let tt = Types.descr (typ t) in
681 let ss = Types.descr (typ s) in
682 let tf = to_ml_dyn t in
683 let sf = to_cd_dyn t in
684 (fun (f : Obj.repr) ->
685 let f = (Obj.magic f : Obj.repr -> Obj.repr) in
686 Value.Abstraction ([tt,ss],fun x -> sf (f (tf x))))
687 | Tuple tl ->
688 let fs = List.map to_cd_dyn tl in
689 (fun (x : Obj.repr) ->
690 let x = (Obj.magic x : Obj.repr array) in
691 let rec aux i = function
692 | [] -> assert false
693 | [f] -> f x.(i)
694 | f::tl -> Value.Pair (f x.(i), aux (succ i) tl) in
695 aux 0 fs)
696 *)
697
698
699 let register () =
700 Typer.has_ocaml_unit :=
701 (fun cu -> Mltypes.has_cmi (U.get_str cu));
702 Librarian.stub_ml := stub_ml;
703 Externals.register := register;
704 Externals.ext_info := (fun () -> Obj.magic !exts);
705 Librarian.make_wrapper := make_wrapper
706
707 let () =
708 Cduce_config.register
709 "ocaml"
710 "OCaml interface"
711 register

CVS Admin">CVS Admin
ViewVC Help
Powered by ViewVC 1.1.5