|
Packit |
bd2e5d |
(***********************************************************************)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(* MLTk, Tcl/Tk interface of OCaml *)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
|
|
Packit |
bd2e5d |
(* projet Cristal, INRIA Rocquencourt *)
|
|
Packit |
bd2e5d |
(* Jacques Garrigue, Kyoto University RIMS *)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(* Copyright 2002 Institut National de Recherche en Informatique et *)
|
|
Packit |
bd2e5d |
(* en Automatique and Kyoto University. All rights reserved. *)
|
|
Packit |
bd2e5d |
(* This file is distributed under the terms of the GNU Library *)
|
|
Packit |
bd2e5d |
(* General Public License, with the special exception on linking *)
|
|
Packit |
bd2e5d |
(* described in file LICENSE found in the OCaml source tree. *)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(***********************************************************************)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* $Id$ *)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
open StdLabels
|
|
Packit |
bd2e5d |
open Tables
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* CONFIGURE *)
|
|
Packit |
bd2e5d |
(* if you set it true, ImagePhoto and ImageBitmap will annoy you... *)
|
|
Packit |
bd2e5d |
let safetype = true
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let labeloff ~at l = match l with
|
|
Packit |
bd2e5d |
"", t -> t
|
|
Packit |
bd2e5d |
| l, t -> raise (Failure ("labeloff: " ^ l ^ " at " ^ at))
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let labltk_labelstring l =
|
|
Packit |
bd2e5d |
if l = "" then l else
|
|
Packit |
bd2e5d |
if l.[0] = '?' then l ^ ":" else
|
|
Packit |
bd2e5d |
"~" ^ l ^ ":"
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let camltk_labelstring l =
|
|
Packit |
bd2e5d |
if l = "" then l else
|
|
Packit |
bd2e5d |
if l.[0] = '?' then l ^ ":" else ""
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let labelstring l =
|
|
Packit |
bd2e5d |
if !Flags.camltk then camltk_labelstring l
|
|
Packit |
bd2e5d |
else labltk_labelstring l
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let labltk_typelabel l =
|
|
Packit |
bd2e5d |
if l = "" then l else l ^ ":"
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let camltk_typelabel l =
|
|
Packit |
bd2e5d |
if l = "" then l
|
|
Packit |
bd2e5d |
else if l.[0] = '?' then l ^ ":" else ""
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let typelabel l =
|
|
Packit |
bd2e5d |
if !Flags.camltk then camltk_typelabel l
|
|
Packit |
bd2e5d |
else labltk_typelabel l
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let forbidden = [ "class"; "type"; "in"; "from"; "to" ]
|
|
Packit |
bd2e5d |
let nicknames =
|
|
Packit |
bd2e5d |
[ "class", "clas";
|
|
Packit |
bd2e5d |
"type", "typ" ]
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let small = String.lowercase_ascii
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let gettklabel fc =
|
|
Packit |
bd2e5d |
match fc.template with
|
|
Packit |
bd2e5d |
ListArg( StringArg s :: _ ) ->
|
|
Packit |
bd2e5d |
let s = small s in
|
|
Packit |
bd2e5d |
if s = "" then s else
|
|
Packit |
bd2e5d |
let s =
|
|
Packit |
bd2e5d |
if s.[0] = '-'
|
|
Packit |
bd2e5d |
then String.sub s ~pos:1 ~len:(String.length s - 1)
|
|
Packit |
bd2e5d |
else s
|
|
Packit |
bd2e5d |
in begin
|
|
Packit |
bd2e5d |
if List.mem s forbidden then
|
|
Packit |
bd2e5d |
try List.assoc s nicknames
|
|
Packit |
bd2e5d |
with Not_found -> small fc.var_name
|
|
Packit |
bd2e5d |
else s
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
| _ -> raise (Failure "gettklabel")
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let count ~item:x l =
|
|
Packit |
bd2e5d |
let count = ref 0 in
|
|
Packit |
bd2e5d |
List.iter ~f:(fun y -> if x = y then incr count) l;
|
|
Packit |
bd2e5d |
!count
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let caml_name s =
|
|
Packit |
bd2e5d |
let b = Buffer.create (String.length s) in
|
|
Packit |
bd2e5d |
for i = 0 to String.length s - 1 do
|
|
Packit |
bd2e5d |
let c = s.[i] in
|
|
Packit |
bd2e5d |
if c <> ':' then Buffer.add_char b c
|
|
Packit |
bd2e5d |
else if i > 0 && s.[i-1] = ':' then Buffer.add_char b '_'
|
|
Packit |
bd2e5d |
done;
|
|
Packit |
bd2e5d |
Buffer.contents b
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Extract all types from a template *)
|
|
Packit |
bd2e5d |
let rec types_of_template = function
|
|
Packit |
bd2e5d |
StringArg _ -> []
|
|
Packit |
bd2e5d |
| TypeArg (l, t) -> [l, t]
|
|
Packit |
bd2e5d |
| ListArg l -> List.flatten (List.map ~f:types_of_template l)
|
|
Packit |
bd2e5d |
| OptionalArgs (l, tl, _) ->
|
|
Packit |
bd2e5d |
begin
|
|
Packit |
bd2e5d |
match List.flatten (List.map ~f:types_of_template tl) with
|
|
Packit |
bd2e5d |
["", t] -> ["?" ^ l, t]
|
|
Packit |
bd2e5d |
| [_, _] -> raise (Failure "0 label required")
|
|
Packit |
bd2e5d |
| _ -> raise (Failure "0 or more than 1 args in for optionals")
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(*
|
|
Packit |
bd2e5d |
* Pretty print a type
|
|
Packit |
bd2e5d |
* used to write ML type definitions
|
|
Packit |
bd2e5d |
*)
|
|
Packit |
bd2e5d |
let ppMLtype ?(any=false) ?(return=false) ?(def=false) ?(counter=ref 0) =
|
|
Packit |
bd2e5d |
let rec ppMLtype =
|
|
Packit |
bd2e5d |
function
|
|
Packit |
bd2e5d |
Unit -> "unit"
|
|
Packit |
bd2e5d |
| Int -> "int"
|
|
Packit |
bd2e5d |
| Float -> "float"
|
|
Packit |
bd2e5d |
| Bool -> "bool"
|
|
Packit |
bd2e5d |
| Char -> "char"
|
|
Packit |
bd2e5d |
| String -> "string"
|
|
Packit |
bd2e5d |
(* new *)
|
|
Packit |
bd2e5d |
| List (Subtype (sup, sub)) ->
|
|
Packit |
bd2e5d |
if !Flags.camltk then "(* " ^ sub ^ " *) " ^ caml_name sup ^ " list"
|
|
Packit |
bd2e5d |
else begin
|
|
Packit |
bd2e5d |
if return then
|
|
Packit |
bd2e5d |
caml_name sub ^ "_" ^ caml_name sup ^ " list"
|
|
Packit |
bd2e5d |
else begin
|
|
Packit |
bd2e5d |
try
|
|
Packit |
bd2e5d |
let typdef = Hashtbl.find types_table sup in
|
|
Packit |
bd2e5d |
let fcl = List.assoc sub typdef.subtypes in
|
|
Packit |
bd2e5d |
let tklabels = List.map ~f:gettklabel fcl in
|
|
Packit |
bd2e5d |
let l = List.map fcl ~f:
|
|
Packit |
bd2e5d |
begin fun fc ->
|
|
Packit |
bd2e5d |
"?" ^ begin let p = gettklabel fc in
|
|
Packit |
bd2e5d |
if count ~item:p tklabels > 1 then small fc.var_name else p
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
^ ":" ^
|
|
Packit |
bd2e5d |
let l = types_of_template fc.template in
|
|
Packit |
bd2e5d |
match l with
|
|
Packit |
bd2e5d |
[] -> "unit"
|
|
Packit |
bd2e5d |
| [lt] -> ppMLtype (labeloff lt ~at:"ppMLtype")
|
|
Packit |
bd2e5d |
| l ->
|
|
Packit |
bd2e5d |
"(" ^ String.concat ~sep:"*"
|
|
Packit |
bd2e5d |
(List.map l
|
|
Packit |
bd2e5d |
~f:(fun lt -> ppMLtype (labeloff lt ~at:"ppMLtype")))
|
|
Packit |
bd2e5d |
^ ")"
|
|
Packit |
bd2e5d |
end in
|
|
Packit |
bd2e5d |
String.concat ~sep:" ->\n" l
|
|
Packit |
bd2e5d |
with
|
|
Packit |
bd2e5d |
Not_found -> Printf.eprintf "ppMLtype %s/%s\n" sup sub; exit (-1)
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
| List ty -> (ppMLtype ty) ^ " list"
|
|
Packit |
bd2e5d |
| Product tyl ->
|
|
Packit |
bd2e5d |
"(" ^ String.concat ~sep:" * " (List.map ~f:ppMLtype tyl) ^ ")"
|
|
Packit |
bd2e5d |
| Record tyl ->
|
|
Packit |
bd2e5d |
String.concat ~sep:" * "
|
|
Packit |
bd2e5d |
(List.map tyl ~f:(fun (l, t) -> typelabel l ^ ppMLtype t))
|
|
Packit |
bd2e5d |
| Subtype ("widget", sub) ->
|
|
Packit |
bd2e5d |
if !Flags.camltk then "(* " ^ sub ^" *) widget" else
|
|
Packit |
bd2e5d |
caml_name sub ^ " widget"
|
|
Packit |
bd2e5d |
| UserDefined "widget" ->
|
|
Packit |
bd2e5d |
if !Flags.camltk then "widget"
|
|
Packit |
bd2e5d |
else begin
|
|
Packit |
bd2e5d |
if any then "any widget" else
|
|
Packit |
bd2e5d |
let c = String.make 1 (Char.chr(Char.code 'a' + !counter)) in
|
|
Packit |
bd2e5d |
incr counter;
|
|
Packit |
bd2e5d |
"'" ^ c ^ " widget"
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
| UserDefined s ->
|
|
Packit |
bd2e5d |
if !Flags.camltk then s
|
|
Packit |
bd2e5d |
else begin
|
|
Packit |
bd2e5d |
(* a bit dirty hack for ImageBitmap and ImagePhoto *)
|
|
Packit |
bd2e5d |
try
|
|
Packit |
bd2e5d |
let typdef = Hashtbl.find types_table s in
|
|
Packit |
bd2e5d |
if typdef.variant then
|
|
Packit |
bd2e5d |
if return then try
|
|
Packit |
bd2e5d |
"[>" ^
|
|
Packit |
bd2e5d |
String.concat ~sep:"|"
|
|
Packit |
bd2e5d |
(List.map typdef.constructors ~f:
|
|
Packit |
bd2e5d |
begin
|
|
Packit |
bd2e5d |
fun c ->
|
|
Packit |
bd2e5d |
"`" ^ c.var_name ^
|
|
Packit |
bd2e5d |
(match types_of_template c.template with
|
|
Packit |
bd2e5d |
[] -> ""
|
|
Packit |
bd2e5d |
| l -> " of " ^ ppMLtype (Product (List.map l
|
|
Packit |
bd2e5d |
~f:(labeloff ~at:"ppMLtype UserDefined"))))
|
|
Packit |
bd2e5d |
end) ^ "]"
|
|
Packit |
bd2e5d |
with
|
|
Packit |
bd2e5d |
Not_found -> prerr_endline ("ppMLtype " ^ s ^ " ?"); s
|
|
Packit |
bd2e5d |
else if not def && List.length typdef.constructors > 1 then
|
|
Packit |
bd2e5d |
"[< " ^ s ^ "]"
|
|
Packit |
bd2e5d |
else s
|
|
Packit |
bd2e5d |
else s
|
|
Packit |
bd2e5d |
with Not_found -> s
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
| Subtype (s, s') ->
|
|
Packit |
bd2e5d |
if !Flags.camltk then "(* " ^ s' ^ " *) " ^ caml_name s else
|
|
Packit |
bd2e5d |
caml_name s' ^ "_" ^ caml_name s
|
|
Packit |
bd2e5d |
| Function (Product tyl) ->
|
|
Packit |
bd2e5d |
raise (Failure "Function (Product tyl) ? ppMLtype")
|
|
Packit |
bd2e5d |
| Function (Record tyl) ->
|
|
Packit |
bd2e5d |
"(" ^ String.concat ~sep:" -> "
|
|
Packit |
bd2e5d |
(List.map tyl ~f:(fun (l, t) -> typelabel l ^ ppMLtype t))
|
|
Packit |
bd2e5d |
^ " -> unit)"
|
|
Packit |
bd2e5d |
| Function ty ->
|
|
Packit |
bd2e5d |
"(" ^ (ppMLtype ty) ^ " -> unit)"
|
|
Packit |
bd2e5d |
| As (t, s) ->
|
|
Packit |
bd2e5d |
if !Flags.camltk then ppMLtype t
|
|
Packit |
bd2e5d |
else s
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
ppMLtype
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Produce a documentation version of a template *)
|
|
Packit |
bd2e5d |
let rec ppTemplate = function
|
|
Packit |
bd2e5d |
StringArg s -> s
|
|
Packit |
bd2e5d |
| TypeArg (l, t) -> "<" ^ ppMLtype t ^ ">"
|
|
Packit |
bd2e5d |
| ListArg l -> "{" ^ String.concat ~sep:" " (List.map ~f:ppTemplate l) ^ "}"
|
|
Packit |
bd2e5d |
| OptionalArgs (l, tl, d) ->
|
|
Packit |
bd2e5d |
"?" ^ l ^ "{" ^ String.concat ~sep:" " (List.map ~f:ppTemplate tl)
|
|
Packit |
bd2e5d |
^ "}[<" ^ String.concat ~sep:" " (List.map ~f:ppTemplate d) ^ ">]"
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let doc_of_template = function
|
|
Packit |
bd2e5d |
ListArg l -> String.concat ~sep:" " (List.map ~f:ppTemplate l)
|
|
Packit |
bd2e5d |
| t -> ppTemplate t
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(*
|
|
Packit |
bd2e5d |
* Type definitions
|
|
Packit |
bd2e5d |
*)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Write an ML constructor *)
|
|
Packit |
bd2e5d |
let write_constructor ~w {ml_name = mlconstr; template = t} =
|
|
Packit |
bd2e5d |
w mlconstr;
|
|
Packit |
bd2e5d |
begin match types_of_template t with
|
|
Packit |
bd2e5d |
[] -> ()
|
|
Packit |
bd2e5d |
| l -> w " of ";
|
|
Packit |
bd2e5d |
w (ppMLtype ~any:true (Product (List.map l
|
|
Packit |
bd2e5d |
~f:(labeloff ~at:"write_constructor"))))
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
w " (* tk option: "; w (doc_of_template t); w " *)"
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Write a rhs type decl *)
|
|
Packit |
bd2e5d |
let write_constructors ~w = function
|
|
Packit |
bd2e5d |
[] -> fatal_error "empty type"
|
|
Packit |
bd2e5d |
| x :: l ->
|
|
Packit |
bd2e5d |
write_constructor ~w x;
|
|
Packit |
bd2e5d |
List.iter l ~f:
|
|
Packit |
bd2e5d |
begin fun x ->
|
|
Packit |
bd2e5d |
w "\n | ";
|
|
Packit |
bd2e5d |
write_constructor ~w x
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Write an ML variant *)
|
|
Packit |
bd2e5d |
let write_variant ~w {var_name = varname; template = t} =
|
|
Packit |
bd2e5d |
w "`";
|
|
Packit |
bd2e5d |
w varname;
|
|
Packit |
bd2e5d |
begin match types_of_template t with
|
|
Packit |
bd2e5d |
[] -> ()
|
|
Packit |
bd2e5d |
| l ->
|
|
Packit |
bd2e5d |
w " of ";
|
|
Packit |
bd2e5d |
w (ppMLtype ~any:true ~def:true
|
|
Packit |
bd2e5d |
(Product (List.map l ~f:(labeloff ~at:"write_variant"))))
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
w " (* tk option: "; w (doc_of_template t); w " *)"
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let write_variants ~w = function
|
|
Packit |
bd2e5d |
[] -> fatal_error "empty variants"
|
|
Packit |
bd2e5d |
| l ->
|
|
Packit |
bd2e5d |
List.iter l ~f:
|
|
Packit |
bd2e5d |
begin fun x ->
|
|
Packit |
bd2e5d |
w "\n | ";
|
|
Packit |
bd2e5d |
write_variant ~w x
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Definition of a type *)
|
|
Packit |
bd2e5d |
let labltk_write_type ~intf:w ~impl:w' name ~def:typdef =
|
|
Packit |
bd2e5d |
(* Only needed if no subtypes, otherwise use optionals *)
|
|
Packit |
bd2e5d |
if typdef.subtypes = [] then begin
|
|
Packit |
bd2e5d |
w "(* Variant type *)\n";
|
|
Packit |
bd2e5d |
w ("type " ^ name ^ " = [");
|
|
Packit |
bd2e5d |
write_variants ~w (sort_components typdef.constructors);
|
|
Packit |
bd2e5d |
w "\n]\n\n"
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* CamlTk: List of constructors, for runtime subtyping *)
|
|
Packit |
bd2e5d |
let write_constructor_set ~w ~sep = function
|
|
Packit |
bd2e5d |
| [] -> fatal_error "empty type"
|
|
Packit |
bd2e5d |
| x::l ->
|
|
Packit |
bd2e5d |
w ("C" ^ x.ml_name);
|
|
Packit |
bd2e5d |
List.iter l ~f: (function x ->
|
|
Packit |
bd2e5d |
w sep;
|
|
Packit |
bd2e5d |
w ("C" ^ x.ml_name))
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* CamlTk: Definition of a type *)
|
|
Packit |
bd2e5d |
let camltk_write_type ~intf:w ~impl:w' name ~def:typdef =
|
|
Packit |
bd2e5d |
(* Put markers for extraction *)
|
|
Packit |
bd2e5d |
w "(* type *)\n";
|
|
Packit |
bd2e5d |
w ("type " ^ name ^ " =\n");
|
|
Packit |
bd2e5d |
w " | ";
|
|
Packit |
bd2e5d |
write_constructors ~w (sort_components typdef.constructors);
|
|
Packit |
bd2e5d |
w "\n(* /type *)\n\n";
|
|
Packit |
bd2e5d |
(* Dynamic Subtyping *)
|
|
Packit |
bd2e5d |
if typdef.subtypes <> [] then begin
|
|
Packit |
bd2e5d |
(* The set of its constructors *)
|
|
Packit |
bd2e5d |
if name = "options" then begin
|
|
Packit |
bd2e5d |
w "(* type *)\n";
|
|
Packit |
bd2e5d |
w ("type "^name^"_constrs =\n\t")
|
|
Packit |
bd2e5d |
end else begin
|
|
Packit |
bd2e5d |
(* added some prefix to avoid being picked up in documentation *)
|
|
Packit |
bd2e5d |
w ("(* no doc *) type "^name^"_constrs =\n")
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
w " | ";
|
|
Packit |
bd2e5d |
write_constructor_set ~w:w ~sep: "\n | "
|
|
Packit |
bd2e5d |
(sort_components typdef.constructors);
|
|
Packit |
bd2e5d |
w "\n\n";
|
|
Packit |
bd2e5d |
(* The set of all constructors *)
|
|
Packit |
bd2e5d |
w' ("let "^caml_name name^"_any_table = [");
|
|
Packit |
bd2e5d |
write_constructor_set ~w:w' ~sep:"; "
|
|
Packit |
bd2e5d |
(sort_components typdef.constructors);
|
|
Packit |
bd2e5d |
w' ("]\n\n");
|
|
Packit |
bd2e5d |
(* The subset of constructors for each subtype *)
|
|
Packit |
bd2e5d |
List.iter ~f:(function (s,l) ->
|
|
Packit |
bd2e5d |
w' ("let "^caml_name name^"_"^caml_name s^"_table = [");
|
|
Packit |
bd2e5d |
write_constructor_set ~w:w' ~sep:"; " (sort_components l);
|
|
Packit |
bd2e5d |
w' ("]\n\n"))
|
|
Packit |
bd2e5d |
typdef.subtypes
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let write_type ~intf:w ~impl:w' name ~def:typdef =
|
|
Packit |
bd2e5d |
(if !Flags.camltk then camltk_write_type else labltk_write_type)
|
|
Packit |
bd2e5d |
~intf:w ~impl:w' name ~def:typdef
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(************************************************************)
|
|
Packit |
bd2e5d |
(* Converters *)
|
|
Packit |
bd2e5d |
(************************************************************)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let rec converterTKtoCAML ~arg = function
|
|
Packit |
bd2e5d |
| Int -> "int_of_string " ^ arg
|
|
Packit |
bd2e5d |
| Float -> "float_of_string " ^ arg
|
|
Packit |
bd2e5d |
| Bool -> "(match " ^ arg ^ " with\n\
|
|
Packit |
bd2e5d |
| \"1\" -> true\n\
|
|
Packit |
bd2e5d |
| \"0\" -> false\n\
|
|
Packit |
bd2e5d |
| s -> Pervasives.raise (Invalid_argument (\"cTKtoCAMLbool\" ^ s)))"
|
|
Packit |
bd2e5d |
| Char -> "String.get " ^ arg ^ " 0"
|
|
Packit |
bd2e5d |
| String -> arg
|
|
Packit |
bd2e5d |
| UserDefined s -> "cTKtoCAML" ^ s ^ " " ^ arg
|
|
Packit |
bd2e5d |
| Subtype ("widget", s') when not !Flags.camltk ->
|
|
Packit |
bd2e5d |
String.concat ~sep:" "
|
|
Packit |
bd2e5d |
["(Obj.magic (cTKtoCAMLwidget "; arg; ") :"; s'; "widget)"]
|
|
Packit |
bd2e5d |
| Subtype (s, s') ->
|
|
Packit |
bd2e5d |
if !Flags.camltk then
|
|
Packit |
bd2e5d |
"cTKtoCAML" ^ s ^ " " ^ arg
|
|
Packit |
bd2e5d |
else
|
|
Packit |
bd2e5d |
"cTKtoCAML" ^ s' ^ "_" ^ s ^ " " ^ arg
|
|
Packit |
bd2e5d |
| List ty ->
|
|
Packit |
bd2e5d |
begin match type_parser_arity ty with
|
|
Packit |
bd2e5d |
OneToken ->
|
|
Packit |
bd2e5d |
String.concat ~sep:" "
|
|
Packit |
bd2e5d |
["(List.map (function x ->";
|
|
Packit |
bd2e5d |
converterTKtoCAML ~arg:"x" ty; ")"; arg; ")"]
|
|
Packit |
bd2e5d |
| MultipleToken ->
|
|
Packit |
bd2e5d |
String.concat ~sep:" "
|
|
Packit |
bd2e5d |
["iterate_converter (function x ->";
|
|
Packit |
bd2e5d |
converterTKtoCAML ~arg:"x" ty; ")"; arg; ")"]
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
| As (ty, _) -> converterTKtoCAML ~arg ty
|
|
Packit |
bd2e5d |
| t ->
|
|
Packit |
bd2e5d |
prerr_endline ("ERROR with " ^ arg ^ " " ^ ppMLtype t);
|
|
Packit |
bd2e5d |
fatal_error "converterTKtoCAML"
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(*******************************)
|
|
Packit |
bd2e5d |
(* Wrappers *)
|
|
Packit |
bd2e5d |
(*******************************)
|
|
Packit |
bd2e5d |
let varnames ~prefix n =
|
|
Packit |
bd2e5d |
let rec var i =
|
|
Packit |
bd2e5d |
if i > n then []
|
|
Packit |
bd2e5d |
else (prefix ^ string_of_int i) :: var (succ i)
|
|
Packit |
bd2e5d |
in var 1
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(*
|
|
Packit |
bd2e5d |
* generate wrapper source for callbacks
|
|
Packit |
bd2e5d |
* transform a function ... -> unit in a function : unit -> unit
|
|
Packit |
bd2e5d |
* using primitives arg_ ... from the protocol
|
|
Packit |
bd2e5d |
* Warning: sequentiality is important in generated code
|
|
Packit |
bd2e5d |
* TODO: remove arg_ stuff and process lists directly ?
|
|
Packit |
bd2e5d |
*)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let rec wrapper_code ~name ty =
|
|
Packit |
bd2e5d |
match ty with
|
|
Packit |
bd2e5d |
Unit -> "(fun _ -> " ^ name ^ " ())"
|
|
Packit |
bd2e5d |
| As (ty, _) -> wrapper_code ~name ty
|
|
Packit |
bd2e5d |
| ty ->
|
|
Packit |
bd2e5d |
"(fun args ->\n " ^
|
|
Packit |
bd2e5d |
begin match ty with
|
|
Packit |
bd2e5d |
Product tyl -> raise (Failure "Product -> record was done. ???")
|
|
Packit |
bd2e5d |
| Record tyl ->
|
|
Packit |
bd2e5d |
(* variables for each component of the product *)
|
|
Packit |
bd2e5d |
let vnames = varnames ~prefix:"a" (List.length tyl) in
|
|
Packit |
bd2e5d |
(* getting the arguments *)
|
|
Packit |
bd2e5d |
let readarg =
|
|
Packit |
bd2e5d |
List.map2 vnames tyl ~f:
|
|
Packit |
bd2e5d |
begin fun v (l, ty) ->
|
|
Packit |
bd2e5d |
match type_parser_arity ty with
|
|
Packit |
bd2e5d |
OneToken ->
|
|
Packit |
bd2e5d |
"let (" ^ v ^ ", args) = " ^
|
|
Packit |
bd2e5d |
converterTKtoCAML ~arg:"(List.hd args)" ty ^
|
|
Packit |
bd2e5d |
", List.tl args in\n "
|
|
Packit |
bd2e5d |
| MultipleToken ->
|
|
Packit |
bd2e5d |
"let (" ^ v ^ ", args) = " ^
|
|
Packit |
bd2e5d |
converterTKtoCAML ~arg:"args" ty ^
|
|
Packit |
bd2e5d |
" in\n "
|
|
Packit |
bd2e5d |
end in
|
|
Packit |
bd2e5d |
String.concat ~sep:"" readarg ^ name ^ " " ^
|
|
Packit |
bd2e5d |
String.concat ~sep:" "
|
|
Packit |
bd2e5d |
(List.map2 ~f:(fun v (l, _) ->
|
|
Packit |
bd2e5d |
if !Flags.camltk then v
|
|
Packit |
bd2e5d |
else labelstring l ^ v) vnames tyl)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* all other types are read in one operation *)
|
|
Packit |
bd2e5d |
| List ty ->
|
|
Packit |
bd2e5d |
name ^ "(" ^ converterTKtoCAML ~arg:"args" ty ^ ")"
|
|
Packit |
bd2e5d |
| String ->
|
|
Packit |
bd2e5d |
name ^ "(" ^ converterTKtoCAML ~arg:"(List.hd args)" ty ^ ")"
|
|
Packit |
bd2e5d |
| ty ->
|
|
Packit |
bd2e5d |
begin match type_parser_arity ty with
|
|
Packit |
bd2e5d |
OneToken ->
|
|
Packit |
bd2e5d |
name ^ "(" ^ converterTKtoCAML ~arg:"(List.hd args)" ty ^ ")"
|
|
Packit |
bd2e5d |
| MultipleToken ->
|
|
Packit |
bd2e5d |
"let (v, _) = " ^ converterTKtoCAML ~arg:"args" ty ^
|
|
Packit |
bd2e5d |
" in\n " ^ name ^ " v"
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
end ^ ")"
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(*************************************************************)
|
|
Packit |
bd2e5d |
(* Parsers *)
|
|
Packit |
bd2e5d |
(* are required only for values returned by commands and *)
|
|
Packit |
bd2e5d |
(* functions (table is computed by the parser) *)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Tuples/Lists are Ok if they don't contain strings *)
|
|
Packit |
bd2e5d |
(* they will be returned as list of strings *)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Can we generate a "parser" ?
|
|
Packit |
bd2e5d |
-> all constructors are unit and at most one int and one string, with null constr
|
|
Packit |
bd2e5d |
*)
|
|
Packit |
bd2e5d |
type parser_pieces =
|
|
Packit |
bd2e5d |
{ mutable zeroary : (string * string) list ; (* kw string, ml name *)
|
|
Packit |
bd2e5d |
mutable intpar : string list; (* one at most, mlname *)
|
|
Packit |
bd2e5d |
mutable stringpar : string list (* idem *)
|
|
Packit |
bd2e5d |
}
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
type mini_parser =
|
|
Packit |
bd2e5d |
NoParser
|
|
Packit |
bd2e5d |
| ParserPieces of parser_pieces
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let can_generate_parser constructors =
|
|
Packit |
bd2e5d |
let pp = {zeroary = []; intpar = []; stringpar = []} in
|
|
Packit |
bd2e5d |
if List.for_all constructors ~f:
|
|
Packit |
bd2e5d |
begin fun c ->
|
|
Packit |
bd2e5d |
let vname = if !Flags.camltk then c.ml_name else c.var_name in
|
|
Packit |
bd2e5d |
match c.template with
|
|
Packit |
bd2e5d |
ListArg [StringArg s] ->
|
|
Packit |
bd2e5d |
pp.zeroary <- (s, vname) ::
|
|
Packit |
bd2e5d |
pp.zeroary; true
|
|
Packit |
bd2e5d |
| ListArg [TypeArg(_, Int)] | ListArg[TypeArg(_, Float)] ->
|
|
Packit |
bd2e5d |
if pp.intpar <> [] then false
|
|
Packit |
bd2e5d |
else (pp.intpar <- [vname]; true)
|
|
Packit |
bd2e5d |
| ListArg [TypeArg(_, String)] ->
|
|
Packit |
bd2e5d |
if pp.stringpar <> [] then false
|
|
Packit |
bd2e5d |
else (pp.stringpar <- [vname]; true)
|
|
Packit |
bd2e5d |
| _ -> false
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
then ParserPieces pp
|
|
Packit |
bd2e5d |
else NoParser
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* We can generate parsers only for simple types *)
|
|
Packit |
bd2e5d |
(* we should avoid multiple walks *)
|
|
Packit |
bd2e5d |
let labltk_write_TKtoCAML ~w name ~def:typdef =
|
|
Packit |
bd2e5d |
if typdef.parser_arity = MultipleToken then
|
|
Packit |
bd2e5d |
prerr_string ("You must write cTKtoCAML" ^ name ^
|
|
Packit |
bd2e5d |
" : string list ->" ^ name ^ " * string list\n")
|
|
Packit |
bd2e5d |
else
|
|
Packit |
bd2e5d |
let write ~consts ~name =
|
|
Packit |
bd2e5d |
match can_generate_parser consts with
|
|
Packit |
bd2e5d |
NoParser ->
|
|
Packit |
bd2e5d |
prerr_string
|
|
Packit |
bd2e5d |
("You must write cTKtoCAML" ^ name ^ " : string ->" ^ name ^ "\n")
|
|
Packit |
bd2e5d |
| ParserPieces pp ->
|
|
Packit |
bd2e5d |
w ("let cTKtoCAML" ^ name ^ " n =\n");
|
|
Packit |
bd2e5d |
(* First check integer *)
|
|
Packit |
bd2e5d |
if pp.intpar <> [] then
|
|
Packit |
bd2e5d |
begin
|
|
Packit |
bd2e5d |
w (" try `" ^ List.hd pp.intpar ^ " (int_of_string n)\n");
|
|
Packit |
bd2e5d |
w (" with _ ->\n")
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
w (" match n with\n");
|
|
Packit |
bd2e5d |
List.iter pp.zeroary ~f:
|
|
Packit |
bd2e5d |
begin fun (tk, ml) ->
|
|
Packit |
bd2e5d |
w " | \""; w tk; w "\" -> `"; w ml; w "\n"
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
let final = if pp.stringpar <> [] then
|
|
Packit |
bd2e5d |
"n -> `" ^ List.hd pp.stringpar ^ " n"
|
|
Packit |
bd2e5d |
else "s -> Pervasives.raise (Invalid_argument (\"cTKtoCAML"
|
|
Packit |
bd2e5d |
^ name ^ ": \" ^ s))"
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
w " | ";
|
|
Packit |
bd2e5d |
w final;
|
|
Packit |
bd2e5d |
w "\n\n"
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
begin
|
|
Packit |
bd2e5d |
write ~name ~consts:typdef.constructors;
|
|
Packit |
bd2e5d |
List.iter typdef.subtypes ~f: begin
|
|
Packit |
bd2e5d |
fun (subname, consts) -> write ~name:(subname ^ "_" ^ name) ~consts
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let camltk_write_TKtoCAML ~w name ~def:typdef =
|
|
Packit |
bd2e5d |
if typdef.parser_arity = MultipleToken then
|
|
Packit |
bd2e5d |
prerr_string ("You must write cTKtoCAML" ^ name ^
|
|
Packit |
bd2e5d |
" : string list ->" ^ name ^ " * string list\n")
|
|
Packit |
bd2e5d |
else
|
|
Packit |
bd2e5d |
let write ~consts ~name =
|
|
Packit |
bd2e5d |
match can_generate_parser consts with
|
|
Packit |
bd2e5d |
NoParser ->
|
|
Packit |
bd2e5d |
prerr_string
|
|
Packit |
bd2e5d |
("You must write cTKtoCAML" ^ name ^ " : string ->" ^ name ^ "\n")
|
|
Packit |
bd2e5d |
| ParserPieces pp ->
|
|
Packit |
bd2e5d |
w ("let cTKtoCAML" ^ name ^ " n =\n");
|
|
Packit |
bd2e5d |
(* First check integer *)
|
|
Packit |
bd2e5d |
if pp.intpar <> [] then
|
|
Packit |
bd2e5d |
begin
|
|
Packit |
bd2e5d |
w (" try " ^ List.hd pp.intpar ^ " (int_of_string n)\n");
|
|
Packit |
bd2e5d |
w (" with _ ->\n")
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
w (" match n with\n");
|
|
Packit |
bd2e5d |
List.iter pp.zeroary ~f:
|
|
Packit |
bd2e5d |
begin fun (tk, ml) ->
|
|
Packit |
bd2e5d |
w " | \""; w tk; w "\" -> "; w ml; w "\n"
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
let final = if pp.stringpar <> [] then
|
|
Packit |
bd2e5d |
"n -> " ^ List.hd pp.stringpar ^ " n"
|
|
Packit |
bd2e5d |
else "s -> Pervasives.raise (Invalid_argument (\"cTKtoCAML"
|
|
Packit |
bd2e5d |
^ name ^ ": \" ^ s))"
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
w " | ";
|
|
Packit |
bd2e5d |
w final;
|
|
Packit |
bd2e5d |
w "\n\n"
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
begin
|
|
Packit |
bd2e5d |
write ~name ~consts:typdef.constructors;
|
|
Packit |
bd2e5d |
List.iter typdef.subtypes ~f: begin
|
|
Packit |
bd2e5d |
fun (subname, consts) -> write ~name:(subname ^ "_" ^ name) ~consts
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let write_TKtoCAML ~w name ~def:typdef =
|
|
Packit |
bd2e5d |
(if !Flags.camltk then camltk_write_TKtoCAML else labltk_write_TKtoCAML)
|
|
Packit |
bd2e5d |
~w name ~def: typdef
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(******************************)
|
|
Packit |
bd2e5d |
(* Converters *)
|
|
Packit |
bd2e5d |
(******************************)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Produce an in-lined converter OCaml -> Tk for simple types *)
|
|
Packit |
bd2e5d |
(* the converter is a function of type: <type> -> string *)
|
|
Packit |
bd2e5d |
let rec converterCAMLtoTK ~context_widget argname ty =
|
|
Packit |
bd2e5d |
match ty with
|
|
Packit |
bd2e5d |
Int -> "TkToken (string_of_int " ^ argname ^ ")"
|
|
Packit |
bd2e5d |
| Float -> "TkToken (Printf.sprintf \"%g\" " ^ argname ^ ")"
|
|
Packit |
bd2e5d |
| Bool -> "if " ^ argname ^ " then TkToken \"1\" else TkToken \"0\""
|
|
Packit |
bd2e5d |
| Char -> "TkToken (Char.escaped " ^ argname ^ ")"
|
|
Packit |
bd2e5d |
| String -> "TkToken " ^ argname
|
|
Packit |
bd2e5d |
| As (ty, _) -> converterCAMLtoTK ~context_widget argname ty
|
|
Packit |
bd2e5d |
| UserDefined s ->
|
|
Packit |
bd2e5d |
let name = "cCAMLtoTK" ^ s ^ " " in
|
|
Packit |
bd2e5d |
let args = argname in
|
|
Packit |
bd2e5d |
let args =
|
|
Packit |
bd2e5d |
if !Flags.camltk then begin
|
|
Packit |
bd2e5d |
if is_subtyped s then (* unconstraint subtype *)
|
|
Packit |
bd2e5d |
s ^ "_any_table " ^ args
|
|
Packit |
bd2e5d |
else args
|
|
Packit |
bd2e5d |
end else args
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
let args =
|
|
Packit |
bd2e5d |
if requires_widget_context s then
|
|
Packit |
bd2e5d |
context_widget ^ " " ^ args
|
|
Packit |
bd2e5d |
else args in
|
|
Packit |
bd2e5d |
name ^ args
|
|
Packit |
bd2e5d |
| Subtype ("widget", s') ->
|
|
Packit |
bd2e5d |
if !Flags.camltk then
|
|
Packit |
bd2e5d |
let name = "cCAMLtoTKwidget " in
|
|
Packit |
bd2e5d |
let args = "widget_"^caml_name s'^"_table "^argname in
|
|
Packit |
bd2e5d |
let args =
|
|
Packit |
bd2e5d |
if requires_widget_context "widget" then
|
|
Packit |
bd2e5d |
context_widget^" "^args
|
|
Packit |
bd2e5d |
else args in
|
|
Packit |
bd2e5d |
name^args
|
|
Packit |
bd2e5d |
else begin
|
|
Packit |
bd2e5d |
let name = "cCAMLtoTKwidget " in
|
|
Packit |
bd2e5d |
let args = "(" ^ argname ^ " : " ^ caml_name s' ^ " widget)" in
|
|
Packit |
bd2e5d |
name ^ args
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
| Subtype (s, s') ->
|
|
Packit |
bd2e5d |
let name =
|
|
Packit |
bd2e5d |
if !Flags.camltk then "cCAMLtoTK" ^ s ^ " "
|
|
Packit |
bd2e5d |
else "cCAMLtoTK" ^ s' ^ "_" ^ s ^ " "
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
let args =
|
|
Packit |
bd2e5d |
if !Flags.camltk then begin
|
|
Packit |
bd2e5d |
caml_name s^"_"^caml_name s'^"_table "^argname
|
|
Packit |
bd2e5d |
end else begin
|
|
Packit |
bd2e5d |
if safetype then
|
|
Packit |
bd2e5d |
"(" ^ argname ^ " : [< " ^ caml_name s' ^ "_" ^ caml_name s ^ "])"
|
|
Packit |
bd2e5d |
else argname
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
let args =
|
|
Packit |
bd2e5d |
if requires_widget_context s then context_widget ^ " " ^ args
|
|
Packit |
bd2e5d |
else args in
|
|
Packit |
bd2e5d |
name ^ args
|
|
Packit |
bd2e5d |
| Product tyl ->
|
|
Packit |
bd2e5d |
let vars = varnames ~prefix:"z" (List.length tyl) in
|
|
Packit |
bd2e5d |
String.concat ~sep:" "
|
|
Packit |
bd2e5d |
("let" :: String.concat ~sep:"," vars :: "=" :: argname ::
|
|
Packit |
bd2e5d |
"in TkTokenList [" ::
|
|
Packit |
bd2e5d |
String.concat ~sep:"; "
|
|
Packit |
bd2e5d |
(List.map2 vars tyl ~f:(converterCAMLtoTK ~context_widget)) ::
|
|
Packit |
bd2e5d |
["]"])
|
|
Packit |
bd2e5d |
| List ty -> (* Just added for Imagephoto.put *)
|
|
Packit |
bd2e5d |
String.concat ~sep:" "
|
|
Packit |
bd2e5d |
[(if !Flags.camltk then
|
|
Packit |
bd2e5d |
"TkQuote (TkTokenList (List.map (fun y -> "
|
|
Packit |
bd2e5d |
else
|
|
Packit |
bd2e5d |
"TkQuote (TkTokenList (List.map ~f:(fun y -> ");
|
|
Packit |
bd2e5d |
converterCAMLtoTK ~context_widget "y" ty;
|
|
Packit |
bd2e5d |
")";
|
|
Packit |
bd2e5d |
argname;
|
|
Packit |
bd2e5d |
"))"]
|
|
Packit |
bd2e5d |
| Function _ -> fatal_error "unexpected function type in converterCAMLtoTK"
|
|
Packit |
bd2e5d |
| Unit -> fatal_error "unexpected unit type in converterCAMLtoTK"
|
|
Packit |
bd2e5d |
| Record _ -> fatal_error "unexpected product type in converterCAMLtoTK"
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(*
|
|
Packit |
bd2e5d |
* Produce a list of arguments from a template
|
|
Packit |
bd2e5d |
* The idea here is to avoid allocation as much as possible
|
|
Packit |
bd2e5d |
*
|
|
Packit |
bd2e5d |
*)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let code_of_template ~context_widget ?func:(funtemplate=false) template =
|
|
Packit |
bd2e5d |
let catch_opts = ref ("", "") in (* class name and first option *)
|
|
Packit |
bd2e5d |
let variables = ref [] in
|
|
Packit |
bd2e5d |
let variables2 = ref [] in
|
|
Packit |
bd2e5d |
let varcnter = ref 0 in
|
|
Packit |
bd2e5d |
let optionvar = ref None in
|
|
Packit |
bd2e5d |
let newvar1 l =
|
|
Packit |
bd2e5d |
match !optionvar with
|
|
Packit |
bd2e5d |
Some v -> optionvar := None; v
|
|
Packit |
bd2e5d |
| None ->
|
|
Packit |
bd2e5d |
incr varcnter;
|
|
Packit |
bd2e5d |
let v = "v" ^ (string_of_int !varcnter) in
|
|
Packit |
bd2e5d |
variables := (l, v) :: !variables; v in
|
|
Packit |
bd2e5d |
let newvar2 l =
|
|
Packit |
bd2e5d |
match !optionvar with
|
|
Packit |
bd2e5d |
Some v -> optionvar := None; v
|
|
Packit |
bd2e5d |
| None ->
|
|
Packit |
bd2e5d |
incr varcnter;
|
|
Packit |
bd2e5d |
let v = "v" ^ (string_of_int !varcnter) in
|
|
Packit |
bd2e5d |
variables2 := (l, v) :: !variables2; v in
|
|
Packit |
bd2e5d |
let newvar = ref newvar1 in
|
|
Packit |
bd2e5d |
let rec coderec = function
|
|
Packit |
bd2e5d |
StringArg s -> "TkToken \"" ^ s ^ "\""
|
|
Packit |
bd2e5d |
| TypeArg (_, List (Subtype (sup, sub))) when not !Flags.camltk ->
|
|
Packit |
bd2e5d |
begin try
|
|
Packit |
bd2e5d |
let typdef = Hashtbl.find types_table sup in
|
|
Packit |
bd2e5d |
let classdef = List.assoc sub typdef.subtypes in
|
|
Packit |
bd2e5d |
let lbl = gettklabel (List.hd classdef) in
|
|
Packit |
bd2e5d |
catch_opts := (sub ^ "_" ^ sup, lbl);
|
|
Packit |
bd2e5d |
newvar := newvar2;
|
|
Packit |
bd2e5d |
"TkTokenList opts"
|
|
Packit |
bd2e5d |
with Not_found ->
|
|
Packit |
bd2e5d |
raise (Failure (Printf.sprintf "type %s(%s) not found" sup sub));
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
| TypeArg (l, List ty) ->
|
|
Packit |
bd2e5d |
(if !Flags.camltk then
|
|
Packit |
bd2e5d |
"TkTokenList (List.map (function x -> "
|
|
Packit |
bd2e5d |
else
|
|
Packit |
bd2e5d |
"TkTokenList (List.map ~f:(function x -> ")
|
|
Packit |
bd2e5d |
^ converterCAMLtoTK ~context_widget "x" ty
|
|
Packit |
bd2e5d |
^ ") " ^ !newvar l ^ ")"
|
|
Packit |
bd2e5d |
| TypeArg (l, Function tyarg) ->
|
|
Packit |
bd2e5d |
"let id = register_callback " ^ context_widget
|
|
Packit |
bd2e5d |
^ " ~callback: " ^ wrapper_code ~name:(!newvar l) tyarg
|
|
Packit |
bd2e5d |
^ " in TkToken (\"camlcb \" ^ id)"
|
|
Packit |
bd2e5d |
| TypeArg (l, ty) -> converterCAMLtoTK ~context_widget (!newvar l) ty
|
|
Packit |
bd2e5d |
| ListArg l ->
|
|
Packit |
bd2e5d |
"TkQuote (TkTokenList ["
|
|
Packit |
bd2e5d |
^ String.concat ~sep:";\n " (List.map ~f:coderec l) ^ "])"
|
|
Packit |
bd2e5d |
| OptionalArgs (l, tl, d) ->
|
|
Packit |
bd2e5d |
let nv = !newvar ("?" ^ l) in
|
|
Packit |
bd2e5d |
optionvar := Some nv; (* Store *)
|
|
Packit |
bd2e5d |
let argstr = String.concat ~sep:"; " (List.map ~f:coderec tl) in
|
|
Packit |
bd2e5d |
let defstr = String.concat ~sep:"; " (List.map ~f:coderec d) in
|
|
Packit |
bd2e5d |
"TkTokenList (match " ^ nv ^ " with\n"
|
|
Packit |
bd2e5d |
^ " | Some " ^ nv ^ " -> [" ^ argstr ^ "]\n"
|
|
Packit |
bd2e5d |
^ " | None -> [" ^ defstr ^ "])"
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
let code =
|
|
Packit |
bd2e5d |
if funtemplate then
|
|
Packit |
bd2e5d |
match template with
|
|
Packit |
bd2e5d |
ListArg l ->
|
|
Packit |
bd2e5d |
"[|" ^ String.concat ~sep:";\n " (List.map ~f:coderec l) ^ "|]"
|
|
Packit |
bd2e5d |
| _ -> "[|" ^ coderec template ^ "|]"
|
|
Packit |
bd2e5d |
else
|
|
Packit |
bd2e5d |
match template with
|
|
Packit |
bd2e5d |
ListArg [x] -> coderec x
|
|
Packit |
bd2e5d |
| ListArg l ->
|
|
Packit |
bd2e5d |
"TkTokenList [" ^
|
|
Packit |
bd2e5d |
String.concat ~sep:";\n " (List.map ~f:coderec l) ^
|
|
Packit |
bd2e5d |
"]"
|
|
Packit |
bd2e5d |
| _ -> coderec template
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
code, List.rev !variables, List.rev !variables2, !catch_opts
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(*
|
|
Packit |
bd2e5d |
* Converters for user defined types
|
|
Packit |
bd2e5d |
*)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* For each case of a concrete type *)
|
|
Packit |
bd2e5d |
let labltk_write_clause ~w ~context_widget comp =
|
|
Packit |
bd2e5d |
let warrow () = w " -> " in
|
|
Packit |
bd2e5d |
w "`";
|
|
Packit |
bd2e5d |
w comp.var_name;
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let code, variables, variables2, (co, _) =
|
|
Packit |
bd2e5d |
code_of_template ~context_widget comp.template in
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* no subtype I think ... *)
|
|
Packit |
bd2e5d |
if co <> "" then raise (Failure "write_clause subtype ?");
|
|
Packit |
bd2e5d |
begin match variables with
|
|
Packit |
bd2e5d |
| [] -> warrow()
|
|
Packit |
bd2e5d |
| [x] -> w " "; w (labeloff x ~at:"write_clause"); warrow()
|
|
Packit |
bd2e5d |
| l ->
|
|
Packit |
bd2e5d |
w " ( ";
|
|
Packit |
bd2e5d |
w (String.concat ~sep:", " (List.map ~f:(labeloff ~at:"write_clause") l));
|
|
Packit |
bd2e5d |
w ")";
|
|
Packit |
bd2e5d |
warrow()
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
w code
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let camltk_write_clause ~w ~context_widget ~subtype comp =
|
|
Packit |
bd2e5d |
let warrow () =
|
|
Packit |
bd2e5d |
w " -> ";
|
|
Packit |
bd2e5d |
if subtype then
|
|
Packit |
bd2e5d |
w ("chk_sub \""^comp.ml_name^"\" table C" ^ comp.ml_name ^ "; ")
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
w comp.ml_name; (* we use ml_name, not var_name, specialized for labltk *)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let code, variables, variables2, (co, _) =
|
|
Packit |
bd2e5d |
code_of_template ~context_widget comp.template in
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* no subtype I think ... *)
|
|
Packit |
bd2e5d |
if co <> "" then raise (Failure "write_clause subtype ?");
|
|
Packit |
bd2e5d |
begin match variables with
|
|
Packit |
bd2e5d |
| [] -> warrow()
|
|
Packit |
bd2e5d |
| [x] -> w " "; w (labeloff x ~at:"write_clause"); warrow()
|
|
Packit |
bd2e5d |
| l ->
|
|
Packit |
bd2e5d |
w " ( ";
|
|
Packit |
bd2e5d |
w (String.concat ~sep:", " (List.map ~f:(labeloff ~at:"write_clause") l));
|
|
Packit |
bd2e5d |
w ")";
|
|
Packit |
bd2e5d |
warrow()
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
w code
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let write_clause ~w ~context_widget ~subtype comp =
|
|
Packit |
bd2e5d |
if !Flags.camltk then camltk_write_clause ~w ~context_widget ~subtype comp
|
|
Packit |
bd2e5d |
else labltk_write_clause ~w ~context_widget comp
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* The full converter *)
|
|
Packit |
bd2e5d |
let write_CAMLtoTK ~w ~def:typdef ?safetype:(st = true) name =
|
|
Packit |
bd2e5d |
let write_one name constrs =
|
|
Packit |
bd2e5d |
let subtype = typdef.subtypes <> [] in
|
|
Packit |
bd2e5d |
w ("let cCAMLtoTK" ^ name);
|
|
Packit |
bd2e5d |
let context_widget =
|
|
Packit |
bd2e5d |
if typdef.requires_widget_context then begin
|
|
Packit |
bd2e5d |
w " w"; "w"
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
else
|
|
Packit |
bd2e5d |
"dummy" in
|
|
Packit |
bd2e5d |
if !Flags.camltk && subtype then w " table";
|
|
Packit |
bd2e5d |
if st then begin
|
|
Packit |
bd2e5d |
w " : ";
|
|
Packit |
bd2e5d |
if typdef.variant then w ("[< " ^ name ^ "]") else w name;
|
|
Packit |
bd2e5d |
w " -> tkArgs "
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
w (" = function");
|
|
Packit |
bd2e5d |
List.iter constrs
|
|
Packit |
bd2e5d |
~f:(fun c -> w "\n | "; write_clause ~w ~context_widget ~subtype c);
|
|
Packit |
bd2e5d |
w "\n\n\n"
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let constrs = typdef.constructors in
|
|
Packit |
bd2e5d |
if !Flags.camltk then write_one name constrs
|
|
Packit |
bd2e5d |
else begin
|
|
Packit |
bd2e5d |
(* Only needed if no subtypes, otherwise use optionals *)
|
|
Packit |
bd2e5d |
if typdef.subtypes == [] then
|
|
Packit |
bd2e5d |
write_one name constrs
|
|
Packit |
bd2e5d |
else
|
|
Packit |
bd2e5d |
List.iter constrs ~f:
|
|
Packit |
bd2e5d |
begin fun fc ->
|
|
Packit |
bd2e5d |
let code, vars, _, (co, _) =
|
|
Packit |
bd2e5d |
code_of_template ~context_widget:"dummy" fc.template in
|
|
Packit |
bd2e5d |
if co <> "" then fatal_error "optionals in optionals";
|
|
Packit |
bd2e5d |
let vars = List.map ~f:snd vars in
|
|
Packit |
bd2e5d |
w "let ccCAMLtoTK"; w name; w "_"; w (small fc.ml_name);
|
|
Packit |
bd2e5d |
w " ("; w (String.concat ~sep:", " vars); w ") =\n ";
|
|
Packit |
bd2e5d |
w code; w "\n\n"
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Tcl does not really return "lists". It returns sp separated tokens *)
|
|
Packit |
bd2e5d |
let rec write_result_parsing ~w = function
|
|
Packit |
bd2e5d |
List String ->
|
|
Packit |
bd2e5d |
w "(splitlist res)"
|
|
Packit |
bd2e5d |
| List ty ->
|
|
Packit |
bd2e5d |
if !Flags.camltk then
|
|
Packit |
bd2e5d |
w (" List.map " ^ converterTKtoCAML ~arg:"(splitlist res)" ty)
|
|
Packit |
bd2e5d |
else
|
|
Packit |
bd2e5d |
w (" List.map ~f: " ^ converterTKtoCAML ~arg:"(splitlist res)" ty)
|
|
Packit |
bd2e5d |
| Product tyl -> raise (Failure "Product -> record was done. ???")
|
|
Packit |
bd2e5d |
| Record tyl -> (* of course all the labels are "" *)
|
|
Packit |
bd2e5d |
let rnames = varnames ~prefix:"r" (List.length tyl) in
|
|
Packit |
bd2e5d |
w " let l = splitlist res in";
|
|
Packit |
bd2e5d |
w ("\n if List.length l <> " ^ string_of_int (List.length tyl));
|
|
Packit |
bd2e5d |
w ("\n then Pervasives.raise (TkError (\"unexpected result: \" ^ res))");
|
|
Packit |
bd2e5d |
w ("\n else ");
|
|
Packit |
bd2e5d |
List.iter2 rnames tyl ~f:
|
|
Packit |
bd2e5d |
begin fun r (l, ty) ->
|
|
Packit |
bd2e5d |
if l <> "" then raise (Failure "lables in return type!!!");
|
|
Packit |
bd2e5d |
w (" let " ^ r ^ ", l = ");
|
|
Packit |
bd2e5d |
begin match type_parser_arity ty with
|
|
Packit |
bd2e5d |
OneToken ->
|
|
Packit |
bd2e5d |
w (converterTKtoCAML ~arg:"(List.hd l)" ty); w (", List.tl l")
|
|
Packit |
bd2e5d |
| MultipleToken ->
|
|
Packit |
bd2e5d |
w (converterTKtoCAML ~arg:"l" ty)
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
w (" in\n")
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
w (String.concat ~sep:", " rnames)
|
|
Packit |
bd2e5d |
| String ->
|
|
Packit |
bd2e5d |
w (converterTKtoCAML ~arg:"res" String)
|
|
Packit |
bd2e5d |
| As (ty, _) -> write_result_parsing ~w ty
|
|
Packit |
bd2e5d |
| ty ->
|
|
Packit |
bd2e5d |
match type_parser_arity ty with
|
|
Packit |
bd2e5d |
OneToken -> w (converterTKtoCAML ~arg:"res" ty)
|
|
Packit |
bd2e5d |
| MultipleToken -> w (converterTKtoCAML ~arg:"(splitlist res)" ty)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let labltk_write_function ~w def =
|
|
Packit |
bd2e5d |
w ("let " ^ caml_name def.ml_name);
|
|
Packit |
bd2e5d |
(* a bit approximative *)
|
|
Packit |
bd2e5d |
let context_widget = match def.template with
|
|
Packit |
bd2e5d |
ListArg (TypeArg(_, UserDefined("widget")) :: _) -> "v1"
|
|
Packit |
bd2e5d |
| ListArg (TypeArg(_, Subtype("widget", _)) :: _) -> "v1"
|
|
Packit |
bd2e5d |
| _ -> "dummy" in
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let code, variables, variables2, (co, lbl) =
|
|
Packit |
bd2e5d |
code_of_template ~func:true ~context_widget def.template in
|
|
Packit |
bd2e5d |
(* Arguments *)
|
|
Packit |
bd2e5d |
let uv, lv, ov =
|
|
Packit |
bd2e5d |
let rec replace_args ~u ~l ~o = function
|
|
Packit |
bd2e5d |
[] -> u, l, o
|
|
Packit |
bd2e5d |
| ("", x) :: ls ->
|
|
Packit |
bd2e5d |
replace_args ~u:(x :: u) ~l ~o ls
|
|
Packit |
bd2e5d |
| (p, _ as x) :: ls when p.[0] = '?' ->
|
|
Packit |
bd2e5d |
replace_args ~u ~l ~o:(x :: o) ls
|
|
Packit |
bd2e5d |
| x :: ls ->
|
|
Packit |
bd2e5d |
replace_args ~u ~l:(x :: l) ~o ls
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
replace_args ~u:[] ~l:[] ~o:[] (List.rev (variables @ variables2))
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
let has_opts = (ov <> [] || co <> "") in
|
|
Packit |
bd2e5d |
if not has_opts then List.iter uv ~f:(fun x -> w " "; w x);
|
|
Packit |
bd2e5d |
List.iter (lv@ov) ~f:(fun (l, v) -> w " "; w (labelstring l); w v);
|
|
Packit |
bd2e5d |
if co <> "" then begin
|
|
Packit |
bd2e5d |
if lv = [] && ov = [] then w (" ?" ^ lbl ^ ":eta");
|
|
Packit |
bd2e5d |
w " =\n";
|
|
Packit |
bd2e5d |
w (co ^ "_optionals");
|
|
Packit |
bd2e5d |
if lv = [] && ov = [] then w (" ?" ^ lbl ^ ":eta");
|
|
Packit |
bd2e5d |
w " (fun opts";
|
|
Packit |
bd2e5d |
if uv = [] then w " ()" else
|
|
Packit |
bd2e5d |
if has_opts then List.iter uv ~f:(fun x -> w " "; w x);
|
|
Packit |
bd2e5d |
w " ->\n"
|
|
Packit |
bd2e5d |
end else begin
|
|
Packit |
bd2e5d |
if (ov <> [] || lv = []) && uv = [] then w " ()" else
|
|
Packit |
bd2e5d |
if has_opts then List.iter uv ~f:(fun x -> w " "; w x);
|
|
Packit |
bd2e5d |
w " =\n"
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
begin match def.result with
|
|
Packit |
bd2e5d |
| Unit | As (Unit, _) -> w "tkCommand "; w code
|
|
Packit |
bd2e5d |
| ty ->
|
|
Packit |
bd2e5d |
w "let res = tkEval "; w code ; w " in \n";
|
|
Packit |
bd2e5d |
write_result_parsing ~w ty
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
if co <> "" then w ")";
|
|
Packit |
bd2e5d |
w "\n\n"
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let camltk_write_function ~w def =
|
|
Packit |
bd2e5d |
w ("let " ^ caml_name def.ml_name);
|
|
Packit |
bd2e5d |
(* a bit approximative *)
|
|
Packit |
bd2e5d |
let context_widget = match def.template with
|
|
Packit |
bd2e5d |
ListArg (TypeArg(_, UserDefined("widget")) :: _) -> "v1"
|
|
Packit |
bd2e5d |
| ListArg (TypeArg(_, Subtype("widget", _)) :: _) -> "v1"
|
|
Packit |
bd2e5d |
| _ -> "dummy" in
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let code, variables, variables2, (co, lbl) =
|
|
Packit |
bd2e5d |
code_of_template ~func:true ~context_widget def.template in
|
|
Packit |
bd2e5d |
(* Arguments *)
|
|
Packit |
bd2e5d |
let uv, ov =
|
|
Packit |
bd2e5d |
let rec replace_args ~u ~o = function
|
|
Packit |
bd2e5d |
[] -> u, o
|
|
Packit |
bd2e5d |
| ("", x) :: ls ->
|
|
Packit |
bd2e5d |
replace_args ~u:(x :: u) ~o ls
|
|
Packit |
bd2e5d |
| (p, _ as x) :: ls when p.[0] = '?' ->
|
|
Packit |
bd2e5d |
replace_args ~u ~o:(x :: o) ls
|
|
Packit |
bd2e5d |
| (_,x) :: ls ->
|
|
Packit |
bd2e5d |
replace_args ~u:(x::u) ~o ls
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
replace_args ~u:[] ~o:[] (List.rev (variables @ variables2))
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
let has_opts = ov <> [] (* (ov <> [] || co <> "") *) in
|
|
Packit |
bd2e5d |
if not has_opts then List.iter uv ~f:(fun x -> w " "; w x);
|
|
Packit |
bd2e5d |
List.iter ov ~f:(fun (l, v) -> w " "; w (labelstring l); w v);
|
|
Packit |
bd2e5d |
begin
|
|
Packit |
bd2e5d |
if uv = [] then w " ()" else
|
|
Packit |
bd2e5d |
if has_opts then List.iter uv ~f:(fun x -> w " "; w x);
|
|
Packit |
bd2e5d |
w " =\n"
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
begin match def.result with
|
|
Packit |
bd2e5d |
| Unit | As (Unit, _) -> w "tkCommand "; w code
|
|
Packit |
bd2e5d |
| ty ->
|
|
Packit |
bd2e5d |
w "let res = tkEval "; w code ; w " in \n";
|
|
Packit |
bd2e5d |
write_result_parsing ~w ty
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
w "\n\n"
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(*
|
|
Packit |
bd2e5d |
w ("let " ^ def.ml_name);
|
|
Packit |
bd2e5d |
(* a bit approximative *)
|
|
Packit |
bd2e5d |
let context_widget = match def.template with
|
|
Packit |
bd2e5d |
ListArg (TypeArg(_, UserDefined("widget")) :: _) -> "v1"
|
|
Packit |
bd2e5d |
| ListArg (TypeArg(_, Subtype("widget", _)) :: _) -> "v1"
|
|
Packit |
bd2e5d |
| _ -> "dummy" in
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let code, variables, variables2, (co, lbl) =
|
|
Packit |
bd2e5d |
code_of_template ~func:true ~context_widget def.template in
|
|
Packit |
bd2e5d |
let variables = variables @ variables2 in
|
|
Packit |
bd2e5d |
(* Arguments *)
|
|
Packit |
bd2e5d |
begin match variables with
|
|
Packit |
bd2e5d |
[] -> w " () =\n"
|
|
Packit |
bd2e5d |
| l ->
|
|
Packit |
bd2e5d |
let has_normal_argument = ref false in
|
|
Packit |
bd2e5d |
List.iter (fun (l,x) ->
|
|
Packit |
bd2e5d |
w " ";
|
|
Packit |
bd2e5d |
if l <> "" then
|
|
Packit |
bd2e5d |
if l.[0] = '?' then w (l ^ ":") else has_normal_argument := true
|
|
Packit |
bd2e5d |
else has_normal_argument := true;
|
|
Packit |
bd2e5d |
w x) l;
|
|
Packit |
bd2e5d |
if not !has_normal_argument then w " ()";
|
|
Packit |
bd2e5d |
w " =\n"
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
begin match def.result with
|
|
Packit |
bd2e5d |
| Unit | As (Unit, _) -> w "tkCommand "; w code
|
|
Packit |
bd2e5d |
| ty ->
|
|
Packit |
bd2e5d |
w "let res = tkEval "; w code ; w " in \n";
|
|
Packit |
bd2e5d |
write_result_parsing ~w ty
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
w "\n\n"
|
|
Packit |
bd2e5d |
*)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let write_function ~w def =
|
|
Packit |
bd2e5d |
if !Flags.camltk then camltk_write_function ~w def
|
|
Packit |
bd2e5d |
else labltk_write_function ~w def
|
|
Packit |
bd2e5d |
;;
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let labltk_write_create ~w clas =
|
|
Packit |
bd2e5d |
let oclas = caml_name clas in
|
|
Packit |
bd2e5d |
w ("let create ?name =\n");
|
|
Packit |
bd2e5d |
w (" " ^ oclas ^ "_options_optionals (fun opts parent ->\n");
|
|
Packit |
bd2e5d |
w (" let w = new_atom \"" ^ clas ^ "\" ~parent ?name in\n");
|
|
Packit |
bd2e5d |
w " tkCommand [|";
|
|
Packit |
bd2e5d |
w ("TkToken \"" ^ clas ^ "\";\n");
|
|
Packit |
bd2e5d |
w (" TkToken (Widget.name w);\n");
|
|
Packit |
bd2e5d |
w (" TkTokenList opts |];\n");
|
|
Packit |
bd2e5d |
w (" w)\n\n\n")
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let camltk_write_create ~w clas =
|
|
Packit |
bd2e5d |
w ("let create ?name parent options =\n");
|
|
Packit |
bd2e5d |
w (" let w = new_atom \"" ^ clas ^ "\" ~parent ?name in\n");
|
|
Packit |
bd2e5d |
w " tkCommand [|";
|
|
Packit |
bd2e5d |
w ("TkToken \"" ^ clas ^ "\";\n");
|
|
Packit |
bd2e5d |
w (" TkToken (Widget.name w);\n");
|
|
Packit |
bd2e5d |
w (" TkTokenList (List.map (function x -> "^
|
|
Packit |
bd2e5d |
converterCAMLtoTK "w" "x" (Subtype("options",clas)) ^ ") options)\n");
|
|
Packit |
bd2e5d |
w (" |];\n");
|
|
Packit |
bd2e5d |
w (" w\n\n")
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let camltk_write_named_create ~w clas =
|
|
Packit |
bd2e5d |
w ("let create_named parent name options =\n");
|
|
Packit |
bd2e5d |
w (" let w = new_atom \"" ^ clas ^ "\" ~parent ~name in\n");
|
|
Packit |
bd2e5d |
w " tkCommand [|";
|
|
Packit |
bd2e5d |
w ("TkToken \"" ^ clas ^ "\";\n");
|
|
Packit |
bd2e5d |
w (" TkToken (Widget.name w);\n");
|
|
Packit |
bd2e5d |
w (" TkTokenList (List.map (function x -> "^
|
|
Packit |
bd2e5d |
converterCAMLtoTK "w" "x" (Subtype("options",clas)) ^ ") options)\n");
|
|
Packit |
bd2e5d |
w (" |];\n");
|
|
Packit |
bd2e5d |
w (" w\n\n")
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Search Path. *)
|
|
Packit |
bd2e5d |
let search_path = ref ["."]
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* taken from utils/misc.ml *)
|
|
Packit |
bd2e5d |
let find_in_path path name =
|
|
Packit |
bd2e5d |
if not (Filename.is_implicit name) then
|
|
Packit |
bd2e5d |
if Sys.file_exists name then name else raise Not_found
|
|
Packit |
bd2e5d |
else begin
|
|
Packit |
bd2e5d |
let rec try_dir = function
|
|
Packit |
bd2e5d |
[] -> raise Not_found
|
|
Packit |
bd2e5d |
| dir :: rem ->
|
|
Packit |
bd2e5d |
let fullname = Filename.concat dir name in
|
|
Packit |
bd2e5d |
if Sys.file_exists fullname then fullname else try_dir rem
|
|
Packit |
bd2e5d |
in try_dir path
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* builtin-code: the file (without suffix) is in .template... *)
|
|
Packit |
bd2e5d |
(* not efficient, but hell *)
|
|
Packit |
bd2e5d |
let write_external ~w def =
|
|
Packit |
bd2e5d |
match def.template with
|
|
Packit |
bd2e5d |
| StringArg fname ->
|
|
Packit |
bd2e5d |
begin try
|
|
Packit |
bd2e5d |
let realname = find_in_path !search_path (fname ^ ".ml") in
|
|
Packit |
bd2e5d |
let ic = open_in_bin realname in
|
|
Packit |
bd2e5d |
try
|
|
Packit |
bd2e5d |
let code_list = Ppparse.parse_channel ic in
|
|
Packit |
bd2e5d |
close_in ic;
|
|
Packit |
bd2e5d |
List.iter (Ppexec.exec (fun _ -> ()) w)
|
|
Packit |
bd2e5d |
(if !Flags.camltk then
|
|
Packit |
bd2e5d |
Code.Define "CAMLTK" :: code_list else code_list );
|
|
Packit |
bd2e5d |
with
|
|
Packit |
bd2e5d |
| Ppparse.Error s ->
|
|
Packit |
bd2e5d |
close_in ic;
|
|
Packit |
bd2e5d |
raise (Compiler_Error (Printf.sprintf "Preprocess error: %s" s))
|
|
Packit |
bd2e5d |
with
|
|
Packit |
bd2e5d |
| Not_found ->
|
|
Packit |
bd2e5d |
raise (Compiler_Error ("can't find external file: " ^ fname))
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
| _ -> raise (Compiler_Error "invalid external definition")
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let write_catch_optionals ~w clas ~def:typdef =
|
|
Packit |
bd2e5d |
if typdef.subtypes = [] then () else
|
|
Packit |
bd2e5d |
List.iter typdef.subtypes ~f:
|
|
Packit |
bd2e5d |
begin fun (subclass, classdefs) ->
|
|
Packit |
bd2e5d |
w ("let " ^ caml_name subclass ^ "_" ^ caml_name clas ^
|
|
Packit |
bd2e5d |
"_optionals f = fun\n");
|
|
Packit |
bd2e5d |
let tklabels = List.map ~f:gettklabel classdefs in
|
|
Packit |
bd2e5d |
let l =
|
|
Packit |
bd2e5d |
List.map classdefs ~f:
|
|
Packit |
bd2e5d |
begin fun fc ->
|
|
Packit |
bd2e5d |
(*
|
|
Packit |
bd2e5d |
let code, vars, _, (co, _) =
|
|
Packit |
bd2e5d |
code_of_template ~context_widget:"dummy" fc.template in
|
|
Packit |
bd2e5d |
if co <> "" then fatal_error "optionals in optionals";
|
|
Packit |
bd2e5d |
*)
|
|
Packit |
bd2e5d |
let p = gettklabel fc in
|
|
Packit |
bd2e5d |
(if count ~item:p tklabels > 1 then small fc.var_name else p),
|
|
Packit |
bd2e5d |
small fc.ml_name
|
|
Packit |
bd2e5d |
end in
|
|
Packit |
bd2e5d |
let p = List.map l ~f:(fun (si, _) -> " ?" ^ si) in
|
|
Packit |
bd2e5d |
let v =
|
|
Packit |
bd2e5d |
List.map l ~f:
|
|
Packit |
bd2e5d |
begin fun (si, s) ->
|
|
Packit |
bd2e5d |
"(maycons ccCAMLtoTK" ^ caml_name clas ^ "_" ^ caml_name s ^ " " ^ si
|
|
Packit |
bd2e5d |
end in
|
|
Packit |
bd2e5d |
w (String.concat ~sep:"\n" p);
|
|
Packit |
bd2e5d |
w " ->\n";
|
|
Packit |
bd2e5d |
w " f ";
|
|
Packit |
bd2e5d |
w (String.concat ~sep:"\n " v);
|
|
Packit |
bd2e5d |
w "\n []";
|
|
Packit |
bd2e5d |
w (String.make (List.length v) ')');
|
|
Packit |
bd2e5d |
w "\n\n"
|
|
Packit |
bd2e5d |
end
|