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

Contents of /ocamliface/mlstub.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1848 - (show annotations)
Tue Jul 10 19:26:57 2007 UTC (5 years, 10 months ago) by abate
File size: 20283 byte(s)
[r2006-03-17 15:49:43 by afrisch] Empty log message

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

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