summaryrefslogtreecommitdiff
path: root/ocaml-binary-annot/otherlibs/labltk/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml-binary-annot/otherlibs/labltk/compiler')
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/.cvsignore11
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/.depend28
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/Makefile63
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/Makefile.nt1
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/code.mli22
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/compile.ml1074
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/copyright15
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/flags.ml17
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/intf.ml191
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/lexer.mll170
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/maincompile.ml418
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/parser.mly330
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/pp.ml23
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/ppexec.ml60
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/pplex.mli18
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/pplex.mll56
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/ppparse.ml36
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/ppyac.mly52
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/printer.ml173
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/tables.ml427
-rw-r--r--ocaml-binary-annot/otherlibs/labltk/compiler/tsort.ml87
21 files changed, 3272 insertions, 0 deletions
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/.cvsignore b/ocaml-binary-annot/otherlibs/labltk/compiler/.cvsignore
new file mode 100644
index 0000000000..060114e624
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/.cvsignore
@@ -0,0 +1,11 @@
+lexer.ml
+parser.output
+parser.ml
+parser.mli
+tkcompiler
+pp
+copyright.ml
+pplex.ml
+ppyac.ml
+ppyac.output
+ppyac.mli
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/.depend b/ocaml-binary-annot/otherlibs/labltk/compiler/.depend
new file mode 100644
index 0000000000..91ee430407
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/.depend
@@ -0,0 +1,28 @@
+pplex.cmi: ppyac.cmi
+ppyac.cmi: code.cmi
+compile.cmo: code.cmi flags.cmo ppexec.cmo ppparse.cmo tables.cmo
+compile.cmx: code.cmi flags.cmx ppexec.cmx ppparse.cmx tables.cmx
+intf.cmo: code.cmi compile.cmo flags.cmo ppexec.cmo ppparse.cmo tables.cmo
+intf.cmx: code.cmi compile.cmx flags.cmx ppexec.cmx ppparse.cmx tables.cmx
+lexer.cmo: parser.cmi
+lexer.cmx: parser.cmx
+maincompile.cmo: code.cmi compile.cmo flags.cmo intf.cmo lexer.cmo parser.cmi \
+ ppexec.cmo ppparse.cmo printer.cmo tables.cmo tsort.cmo
+maincompile.cmx: code.cmi compile.cmx flags.cmx intf.cmx lexer.cmx parser.cmx \
+ ppexec.cmx ppparse.cmx printer.cmx tables.cmx tsort.cmx
+parser.cmo: flags.cmo tables.cmo parser.cmi
+parser.cmx: flags.cmx tables.cmx parser.cmi
+pp.cmo: ppexec.cmo ppparse.cmo
+pp.cmx: ppexec.cmx ppparse.cmx
+ppexec.cmo: code.cmi
+ppexec.cmx: code.cmi
+pplex.cmo: ppyac.cmi pplex.cmi
+pplex.cmx: ppyac.cmx pplex.cmi
+ppparse.cmo: pplex.cmi ppyac.cmi
+ppparse.cmx: pplex.cmx ppyac.cmx
+ppyac.cmo: code.cmi ppyac.cmi
+ppyac.cmx: code.cmi ppyac.cmi
+printer.cmo: tables.cmo
+printer.cmx: tables.cmx
+tables.cmo: tsort.cmo
+tables.cmx: tsort.cmx
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/Makefile b/ocaml-binary-annot/otherlibs/labltk/compiler/Makefile
new file mode 100644
index 0000000000..b7db380f65
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/Makefile
@@ -0,0 +1,63 @@
+include ../support/Makefile.common
+
+OBJS= ../support/support.cmo flags.cmo copyright.cmo \
+ tsort.cmo tables.cmo printer.cmo lexer.cmo \
+ pplex.cmo ppyac.cmo ppexec.cmo ppparse.cmo \
+ parser.cmo compile.cmo intf.cmo maincompile.cmo
+
+PPOBJS= pplex.cmo ppyac.cmo ppexec.cmo ppparse.cmo pp.cmo
+
+all: tkcompiler$(EXE) pp$(EXE)
+
+tkcompiler$(EXE) : $(OBJS)
+ $(CAMLC) -g $(LINKFLAGS) -o tkcompiler$(EXE) $(OBJS)
+
+pp$(EXE): $(PPOBJS)
+ $(CAMLC) -g $(LINKFLAGS) -o pp$(EXE) $(PPOBJS)
+
+lexer.ml: lexer.mll
+ $(CAMLLEX) lexer.mll
+
+parser.ml parser.mli: parser.mly
+ $(CAMLYACC) -v parser.mly
+
+pplex.ml: pplex.mll
+ $(CAMLLEX) pplex.mll
+
+pplex.mli: ppyac.cmi
+
+ppyac.ml ppyac.mli: ppyac.mly
+ $(CAMLYACC) -v ppyac.mly
+
+copyright.ml: copyright
+ (echo "let copyright=\"\\"; \
+ sed -e 's/$$/\\n\\/' copyright; \
+ echo "\""; \
+ echo "let write ~w = w copyright;;") > copyright.ml
+
+clean :
+ rm -f *.cm* parser.ml parser.mli lexer.ml copyright.ml
+ rm -f pplex.ml ppyac.ml ppyac.mli ppyac.output
+ rm -f tkcompiler$(EXE) pp$(EXE) parser.output
+
+scratch :
+ rm -f *.cm* parser.ml parser.mli lexer.ml tkcompiler$(EXE)
+ rm -f *.cm* pplex.ml ppyac.ml ppyac.mli pp$(EXE)
+
+install:
+ cp tkcompiler$(EXE) $(INSTALLDIR)
+ cp pp$(EXE) $(INSTALLDIR)
+
+.SUFFIXES :
+.SUFFIXES : .mli .ml .cmi .cmo .mlp
+
+.mli.cmi:
+ $(CAMLCOMP) $(COMPFLAGS) -I ../support $<
+
+.ml.cmo:
+ $(CAMLCOMP) $(COMPFLAGS) -I ../support $<
+
+depend: parser.ml parser.mli lexer.ml pplex.ml ppyac.ml ppyac.mli
+ $(CAMLDEP) *.mli *.ml > .depend
+
+include .depend
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/Makefile.nt b/ocaml-binary-annot/otherlibs/labltk/compiler/Makefile.nt
new file mode 100644
index 0000000000..2b0b5ab535
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/Makefile.nt
@@ -0,0 +1 @@
+include Makefile
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/code.mli b/ocaml-binary-annot/otherlibs/labltk/compiler/code.mli
new file mode 100644
index 0000000000..6f3e292134
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/code.mli
@@ -0,0 +1,22 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file LICENSE found in the Objective Caml source tree. *)
+(* *)
+(***********************************************************************)
+
+type code =
+ | Line of string
+ | Ifdef of bool * string * code list * code list option
+ | Define of string
+ | Undef of string
+;;
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/compile.ml b/ocaml-binary-annot/otherlibs/labltk/compiler/compile.ml
new file mode 100644
index 0000000000..fd74bc173d
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/compile.ml
@@ -0,0 +1,1074 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file LICENSE found in the Objective Caml source tree. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open StdLabels
+open Tables
+
+(* CONFIGURE *)
+(* if you set it true, ImagePhoto and ImageBitmap will annoy you... *)
+let safetype = true
+
+let labeloff ~at l = match l with
+ "", t -> t
+| l, t -> raise (Failure ("labeloff: " ^ l ^ " at " ^ at))
+
+let labltk_labelstring l =
+ if l = "" then l else
+ if l.[0] = '?' then l ^ ":" else
+ "~" ^ l ^ ":"
+
+let camltk_labelstring l =
+ if l = "" then l else
+ if l.[0] = '?' then l ^ ":" else ""
+
+let labelstring l =
+ if !Flags.camltk then camltk_labelstring l
+ else labltk_labelstring l
+
+let labltk_typelabel l =
+ if l = "" then l else l ^ ":"
+
+let camltk_typelabel l =
+ if l = "" then l
+ else if l.[0] = '?' then l ^ ":" else ""
+
+let typelabel l =
+ if !Flags.camltk then camltk_typelabel l
+ else labltk_typelabel l
+
+let forbidden = [ "class"; "type"; "in"; "from"; "to" ]
+let nicknames =
+ [ "class", "clas";
+ "type", "typ" ]
+
+let small = String.lowercase
+
+let gettklabel fc =
+ match fc.template with
+ ListArg( StringArg s :: _ ) ->
+ let s = small s in
+ if s = "" then s else
+ let s =
+ if s.[0] = '-'
+ then String.sub s ~pos:1 ~len:(String.length s - 1)
+ else s
+ in begin
+ if List.mem s forbidden then
+ try List.assoc s nicknames
+ with Not_found -> small fc.var_name
+ else s
+ end
+ | _ -> raise (Failure "gettklabel")
+
+let count ~item:x l =
+ let count = ref 0 in
+ List.iter ~f:(fun y -> if x = y then incr count) l;
+ !count
+
+(* Extract all types from a template *)
+let rec types_of_template = function
+ StringArg _ -> []
+ | TypeArg (l, t) -> [l, t]
+ | ListArg l -> List.flatten (List.map ~f:types_of_template l)
+ | OptionalArgs (l, tl, _) ->
+ begin
+ match List.flatten (List.map ~f:types_of_template tl) with
+ ["", t] -> ["?" ^ l, t]
+ | [_, _] -> raise (Failure "0 label required")
+ | _ -> raise (Failure "0 or more than 1 args in for optionals")
+ end
+
+(*
+ * Pretty print a type
+ * used to write ML type definitions
+ *)
+let ppMLtype ?(any=false) ?(return=false) ?(def=false) ?(counter=ref 0) =
+ let rec ppMLtype =
+ function
+ Unit -> "unit"
+ | Int -> "int"
+ | Float -> "float"
+ | Bool -> "bool"
+ | Char -> "char"
+ | String -> "string"
+(* new *)
+ | List (Subtype (sup, sub)) ->
+ if !Flags.camltk then "(* " ^ sub ^ " *) " ^ sup ^ " list"
+ else begin
+ if return then
+ sub ^ "_" ^ sup ^ " list"
+ else begin
+ try
+ let typdef = Hashtbl.find types_table sup in
+ let fcl = List.assoc sub typdef.subtypes in
+ let tklabels = List.map ~f:gettklabel fcl in
+ let l = List.map fcl ~f:
+ begin fun fc ->
+ "?" ^ begin let p = gettklabel fc in
+ if count ~item:p tklabels > 1 then small fc.var_name else p
+ end
+ ^ ":" ^
+ let l = types_of_template fc.template in
+ match l with
+ [] -> "unit"
+ | [lt] -> ppMLtype (labeloff lt ~at:"ppMLtype")
+ | l ->
+ "(" ^ String.concat ~sep:"*"
+ (List.map l
+ ~f:(fun lt -> ppMLtype (labeloff lt ~at:"ppMLtype")))
+ ^ ")"
+ end in
+ String.concat ~sep:" ->\n" l
+ with
+ Not_found -> Printf.eprintf "ppMLtype %s/%s\n" sup sub; exit (-1)
+ end
+ end
+ | List ty -> (ppMLtype ty) ^ " list"
+ | Product tyl ->
+ "(" ^ String.concat ~sep:" * " (List.map ~f:ppMLtype tyl) ^ ")"
+ | Record tyl ->
+ String.concat ~sep:" * "
+ (List.map tyl ~f:(fun (l, t) -> typelabel l ^ ppMLtype t))
+ | Subtype ("widget", sub) ->
+ if !Flags.camltk then "(* " ^ sub ^" *) widget" else sub ^ " widget"
+ | UserDefined "widget" ->
+ if !Flags.camltk then "widget"
+ else begin
+ if any then "any widget" else
+ let c = String.make 1 (Char.chr(Char.code 'a' + !counter)) in
+ incr counter;
+ "'" ^ c ^ " widget"
+ end
+ | UserDefined s ->
+ if !Flags.camltk then s
+ else begin
+ (* a bit dirty hack for ImageBitmap and ImagePhoto *)
+ try
+ let typdef = Hashtbl.find types_table s in
+ if typdef.variant then
+ if return then try
+ "[>" ^
+ String.concat ~sep:"|"
+ (List.map typdef.constructors ~f:
+ begin
+ fun c ->
+ "`" ^ c.var_name ^
+ (match types_of_template c.template with
+ [] -> ""
+ | l -> " of " ^ ppMLtype (Product (List.map l
+ ~f:(labeloff ~at:"ppMLtype UserDefined"))))
+ end) ^ "]"
+ with
+ Not_found -> prerr_endline ("ppMLtype " ^ s ^ " ?"); s
+ else if not def && List.length typdef.constructors > 1 then
+ "[< " ^ s ^ "]"
+ else s
+ else s
+ with Not_found -> s
+ end
+ | Subtype (s, s') ->
+ if !Flags.camltk then "(* " ^ s' ^ " *) " ^ s else s' ^ "_" ^ s
+ | Function (Product tyl) ->
+ raise (Failure "Function (Product tyl) ? ppMLtype")
+ | Function (Record tyl) ->
+ "(" ^ String.concat ~sep:" -> "
+ (List.map tyl ~f:(fun (l, t) -> typelabel l ^ ppMLtype t))
+ ^ " -> unit)"
+ | Function ty ->
+ "(" ^ (ppMLtype ty) ^ " -> unit)"
+ | As (t, s) ->
+ if !Flags.camltk then ppMLtype t
+ else s
+ in
+ ppMLtype
+
+(* Produce a documentation version of a template *)
+let rec ppTemplate = function
+ StringArg s -> s
+ | TypeArg (l, t) -> "<" ^ ppMLtype t ^ ">"
+ | ListArg l -> "{" ^ String.concat ~sep:" " (List.map ~f:ppTemplate l) ^ "}"
+ | OptionalArgs (l, tl, d) ->
+ "?" ^ l ^ "{" ^ String.concat ~sep:" " (List.map ~f:ppTemplate tl)
+ ^ "}[<" ^ String.concat ~sep:" " (List.map ~f:ppTemplate d) ^ ">]"
+
+let doc_of_template = function
+ ListArg l -> String.concat ~sep:" " (List.map ~f:ppTemplate l)
+ | t -> ppTemplate t
+
+(*
+ * Type definitions
+ *)
+
+(* Write an ML constructor *)
+let write_constructor ~w {ml_name = mlconstr; template = t} =
+ w mlconstr;
+ begin match types_of_template t with
+ [] -> ()
+ | l -> w " of ";
+ w (ppMLtype ~any:true (Product (List.map l
+ ~f:(labeloff ~at:"write_constructor"))))
+ end;
+ w " (* tk option: "; w (doc_of_template t); w " *)"
+
+(* Write a rhs type decl *)
+let write_constructors ~w = function
+ [] -> fatal_error "empty type"
+ | x :: l ->
+ write_constructor ~w x;
+ List.iter l ~f:
+ begin fun x ->
+ w "\n | ";
+ write_constructor ~w x
+ end
+
+(* Write an ML variant *)
+let write_variant ~w {var_name = varname; template = t} =
+ w "`";
+ w varname;
+ begin match types_of_template t with
+ [] -> ()
+ | l ->
+ w " of ";
+ w (ppMLtype ~any:true ~def:true
+ (Product (List.map l ~f:(labeloff ~at:"write_variant"))))
+ end;
+ w " (* tk option: "; w (doc_of_template t); w " *)"
+
+let write_variants ~w = function
+ [] -> fatal_error "empty variants"
+ | l ->
+ List.iter l ~f:
+ begin fun x ->
+ w "\n | ";
+ write_variant ~w x
+ end
+
+(* Definition of a type *)
+let labltk_write_type ~intf:w ~impl:w' name ~def:typdef =
+ (* Only needed if no subtypes, otherwise use optionals *)
+ if typdef.subtypes = [] then begin
+ w "(* Variant type *)\n";
+ w ("type " ^ name ^ " = [");
+ write_variants ~w (sort_components typdef.constructors);
+ w "\n]\n\n"
+ end
+
+(* CamlTk: List of constructors, for runtime subtyping *)
+let write_constructor_set ~w ~sep = function
+ | [] -> fatal_error "empty type"
+ | x::l ->
+ w ("C" ^ x.ml_name);
+ List.iter l ~f: (function x ->
+ w sep;
+ w ("C" ^ x.ml_name))
+
+(* CamlTk: Definition of a type *)
+let camltk_write_type ~intf:w ~impl:w' name ~def:typdef =
+ (* Put markers for extraction *)
+ w "(* type *)\n";
+ w ("type " ^ name ^ " =\n");
+ w " | ";
+ write_constructors ~w (sort_components typdef.constructors);
+ w "\n(* /type *)\n\n";
+ (* Dynamic Subtyping *)
+ if typdef.subtypes <> [] then begin
+ (* The set of its constructors *)
+ if name = "options" then begin
+ w "(* type *)\n";
+ w ("type "^name^"_constrs =\n\t")
+ end else begin
+ (* added some prefix to avoid being picked up in documentation *)
+ w ("(* no doc *) type "^name^"_constrs =\n")
+ end;
+ w " | ";
+ write_constructor_set ~w:w ~sep: "\n | "
+ (sort_components typdef.constructors);
+ w "\n\n";
+ (* The set of all constructors *)
+ w' ("let "^name^"_any_table = [");
+ write_constructor_set ~w:w' ~sep:"; "
+ (sort_components typdef.constructors);
+ w' ("]\n\n");
+ (* The subset of constructors for each subtype *)
+ List.iter ~f:(function (s,l) ->
+ w' ("let "^name^"_"^s^"_table = [");
+ write_constructor_set ~w:w' ~sep:"; " (sort_components l);
+ w' ("]\n\n"))
+ typdef.subtypes
+ end
+
+let write_type ~intf:w ~impl:w' name ~def:typdef =
+ (if !Flags.camltk then camltk_write_type else labltk_write_type)
+ ~intf:w ~impl:w' name ~def:typdef
+
+(************************************************************)
+(* Converters *)
+(************************************************************)
+
+let rec converterTKtoCAML ~arg = function
+ | Int -> "int_of_string " ^ arg
+ | Float -> "float_of_string " ^ arg
+ | Bool -> "(match " ^ arg ^ " with\n\
+ | \"1\" -> true\n\
+ | \"0\" -> false\n\
+ | s -> Pervasives.raise (Invalid_argument (\"cTKtoCAMLbool\" ^ s)))"
+ | Char -> "String.get " ^ arg ^ " 0"
+ | String -> arg
+ | UserDefined s -> "cTKtoCAML" ^ s ^ " " ^ arg
+ | Subtype ("widget", s') when not !Flags.camltk ->
+ String.concat ~sep:" "
+ ["(Obj.magic (cTKtoCAMLwidget "; arg; ") :"; s'; "widget)"]
+ | Subtype (s, s') ->
+ if !Flags.camltk then
+ "cTKtoCAML" ^ s ^ " " ^ arg
+ else
+ "cTKtoCAML" ^ s' ^ "_" ^ s ^ " " ^ arg
+ | List ty ->
+ begin match type_parser_arity ty with
+ OneToken ->
+ String.concat ~sep:" "
+ ["(List.map (function x ->";
+ converterTKtoCAML ~arg:"x" ty; ")"; arg; ")"]
+ | MultipleToken ->
+ String.concat ~sep:" "
+ ["iterate_converter (function x ->";
+ converterTKtoCAML ~arg:"x" ty; ")"; arg; ")"]
+ end
+ | As (ty, _) -> converterTKtoCAML ~arg ty
+ | t ->
+ prerr_endline ("ERROR with " ^ arg ^ " " ^ ppMLtype t);
+ fatal_error "converterTKtoCAML"
+
+
+(*******************************)
+(* Wrappers *)
+(*******************************)
+let varnames ~prefix n =
+ let rec var i =
+ if i > n then []
+ else (prefix ^ string_of_int i) :: var (succ i)
+ in var 1
+
+(*
+ * generate wrapper source for callbacks
+ * transform a function ... -> unit in a function : unit -> unit
+ * using primitives arg_ ... from the protocol
+ * Warning: sequentiality is important in generated code
+ * TODO: remove arg_ stuff and process lists directly ?
+ *)
+
+let rec wrapper_code ~name ty =
+ match ty with
+ Unit -> "(fun _ -> " ^ name ^ " ())"
+ | As (ty, _) -> wrapper_code ~name ty
+ | ty ->
+ "(fun args ->\n " ^
+ begin match ty with
+ Product tyl -> raise (Failure "Product -> record was done. ???")
+ | Record tyl ->
+ (* variables for each component of the product *)
+ let vnames = varnames ~prefix:"a" (List.length tyl) in
+ (* getting the arguments *)
+ let readarg =
+ List.map2 vnames tyl ~f:
+ begin fun v (l, ty) ->
+ match type_parser_arity ty with
+ OneToken ->
+ "let (" ^ v ^ ", args) = " ^
+ converterTKtoCAML ~arg:"(List.hd args)" ty ^
+ ", List.tl args in\n "
+ | MultipleToken ->
+ "let (" ^ v ^ ", args) = " ^
+ converterTKtoCAML ~arg:"args" ty ^
+ " in\n "
+ end in
+ String.concat ~sep:"" readarg ^ name ^ " " ^
+ String.concat ~sep:" "
+ (List.map2 ~f:(fun v (l, _) ->
+ if !Flags.camltk then v
+ else labelstring l ^ v) vnames tyl)
+
+ (* all other types are read in one operation *)
+ | List ty ->
+ name ^ "(" ^ converterTKtoCAML ~arg:"args" ty ^ ")"
+ | String ->
+ name ^ "(" ^ converterTKtoCAML ~arg:"(List.hd args)" ty ^ ")"
+ | ty ->
+ begin match type_parser_arity ty with
+ OneToken ->
+ name ^ "(" ^ converterTKtoCAML ~arg:"(List.hd args)" ty ^ ")"
+ | MultipleToken ->
+ "let (v, _) = " ^ converterTKtoCAML ~arg:"args" ty ^
+ " in\n " ^ name ^ " v"
+ end
+ end ^ ")"
+
+(*************************************************************)
+(* Parsers *)
+(* are required only for values returned by commands and *)
+(* functions (table is computed by the parser) *)
+
+(* Tuples/Lists are Ok if they don't contain strings *)
+(* they will be returned as list of strings *)
+
+(* Can we generate a "parser" ?
+ -> all constructors are unit and at most one int and one string, with null constr
+*)
+type parser_pieces =
+ { mutable zeroary : (string * string) list ; (* kw string, ml name *)
+ mutable intpar : string list; (* one at most, mlname *)
+ mutable stringpar : string list (* idem *)
+ }
+
+type mini_parser =
+ NoParser
+ | ParserPieces of parser_pieces
+
+let can_generate_parser constructors =
+ let pp = {zeroary = []; intpar = []; stringpar = []} in
+ if List.for_all constructors ~f:
+ begin fun c ->
+ let vname = if !Flags.camltk then c.ml_name else c.var_name in
+ match c.template with
+ ListArg [StringArg s] ->
+ pp.zeroary <- (s, vname) ::
+ pp.zeroary; true
+ | ListArg [TypeArg(_, Int)] | ListArg[TypeArg(_, Float)] ->
+ if pp.intpar <> [] then false
+ else (pp.intpar <- [vname]; true)
+ | ListArg [TypeArg(_, String)] ->
+ if pp.stringpar <> [] then false
+ else (pp.stringpar <- [vname]; true)
+ | _ -> false
+ end
+ then ParserPieces pp
+ else NoParser
+
+
+(* We can generate parsers only for simple types *)
+(* we should avoid multiple walks *)
+let labltk_write_TKtoCAML ~w name ~def:typdef =
+ if typdef.parser_arity = MultipleToken then
+ prerr_string ("You must write cTKtoCAML" ^ name ^
+ " : string list ->" ^ name ^ " * string list\n")
+ else
+ let write ~consts ~name =
+ match can_generate_parser consts with
+ NoParser ->
+ prerr_string
+ ("You must write cTKtoCAML" ^ name ^ " : string ->" ^ name ^ "\n")
+ | ParserPieces pp ->
+ w ("let cTKtoCAML" ^ name ^ " n =\n");
+ (* First check integer *)
+ if pp.intpar <> [] then
+ begin
+ w (" try `" ^ List.hd pp.intpar ^ " (int_of_string n)\n");
+ w (" with _ ->\n")
+ end;
+ w (" match n with\n");
+ List.iter pp.zeroary ~f:
+ begin fun (tk, ml) ->
+ w " | \""; w tk; w "\" -> `"; w ml; w "\n"
+ end;
+ let final = if pp.stringpar <> [] then
+ "n -> `" ^ List.hd pp.stringpar ^ " n"
+ else "s -> Pervasives.raise (Invalid_argument (\"cTKtoCAML"
+ ^ name ^ ": \" ^ s))"
+ in
+ w " | ";
+ w final;
+ w "\n\n"
+ in
+ begin
+ write ~name ~consts:typdef.constructors;
+ List.iter typdef.subtypes ~f: begin
+ fun (subname, consts) -> write ~name:(subname ^ "_" ^ name) ~consts
+ end
+ end
+
+let camltk_write_TKtoCAML ~w name ~def:typdef =
+ if typdef.parser_arity = MultipleToken then
+ prerr_string ("You must write cTKtoCAML" ^ name ^
+ " : string list ->" ^ name ^ " * string list\n")
+ else
+ let write ~consts ~name =
+ match can_generate_parser consts with
+ NoParser ->
+ prerr_string
+ ("You must write cTKtoCAML" ^ name ^ " : string ->" ^ name ^ "\n")
+ | ParserPieces pp ->
+ w ("let cTKtoCAML" ^ name ^ " n =\n");
+ (* First check integer *)
+ if pp.intpar <> [] then
+ begin
+ w (" try " ^ List.hd pp.intpar ^ " (int_of_string n)\n");
+ w (" with _ ->\n")
+ end;
+ w (" match n with\n");
+ List.iter pp.zeroary ~f:
+ begin fun (tk, ml) ->
+ w " | \""; w tk; w "\" -> "; w ml; w "\n"
+ end;
+ let final = if pp.stringpar <> [] then
+ "n -> " ^ List.hd pp.stringpar ^ " n"
+ else "s -> Pervasives.raise (Invalid_argument (\"cTKtoCAML"
+ ^ name ^ ": \" ^ s))"
+ in
+ w " | ";
+ w final;
+ w "\n\n"
+ in
+ begin
+ write ~name ~consts:typdef.constructors;
+ List.iter typdef.subtypes ~f: begin
+ fun (subname, consts) -> write ~name:(subname ^ "_" ^ name) ~consts
+ end
+ end
+
+let write_TKtoCAML ~w name ~def:typdef =
+ (if !Flags.camltk then camltk_write_TKtoCAML else labltk_write_TKtoCAML)
+ ~w name ~def: typdef
+
+(******************************)
+(* Converters *)
+(******************************)
+
+(* Produce an in-lined converter Caml -> Tk for simple types *)
+(* the converter is a function of type: <type> -> string *)
+let rec converterCAMLtoTK ~context_widget argname ty =
+ match ty with
+ Int -> "TkToken (string_of_int " ^ argname ^ ")"
+ | Float -> "TkToken (Printf.sprintf \"%g\" " ^ argname ^ ")"
+ | Bool -> "if " ^ argname ^ " then TkToken \"1\" else TkToken \"0\""
+ | Char -> "TkToken (Char.escaped " ^ argname ^ ")"
+ | String -> "TkToken " ^ argname
+ | As (ty, _) -> converterCAMLtoTK ~context_widget argname ty
+ | UserDefined s ->
+ let name = "cCAMLtoTK" ^ s ^ " " in
+ let args = argname in
+ let args =
+ if !Flags.camltk then begin
+ if is_subtyped s then (* unconstraint subtype *)
+ s ^ "_any_table " ^ args
+ else args
+ end else args
+ in
+ let args =
+ if requires_widget_context s then
+ context_widget ^ " " ^ args
+ else args in
+ name ^ args
+ | Subtype ("widget", s') ->
+ if !Flags.camltk then
+ let name = "cCAMLtoTKwidget " in
+ let args = "widget_"^s'^"_table "^argname in
+ let args =
+ if requires_widget_context "widget" then
+ context_widget^" "^args
+ else args in
+ name^args
+ else begin
+ let name = "cCAMLtoTKwidget " in
+ let args = "(" ^ argname ^ " : " ^ s' ^ " widget)" in
+ name ^ args
+ end
+ | Subtype (s, s') ->
+ let name =
+ if !Flags.camltk then "cCAMLtoTK" ^ s ^ " "
+ else "cCAMLtoTK" ^ s' ^ "_" ^ s ^ " "
+ in
+ let args =
+ if !Flags.camltk then begin
+ s^"_"^s'^"_table "^argname
+ end else begin
+ if safetype then "(" ^ argname ^ " : [< " ^ s' ^ "_" ^ s ^ "])"
+ else argname
+ end
+ in
+ let args =
+ if requires_widget_context s then context_widget ^ " " ^ args
+ else args in
+ name ^ args
+ | Product tyl ->
+ let vars = varnames ~prefix:"z" (List.length tyl) in
+ String.concat ~sep:" "
+ ("let" :: String.concat ~sep:"," vars :: "=" :: argname ::
+ "in TkTokenList [" ::
+ String.concat ~sep:"; "
+ (List.map2 vars tyl ~f:(converterCAMLtoTK ~context_widget)) ::
+ ["]"])
+ | List ty -> (* Just added for Imagephoto.put *)
+ String.concat ~sep:" "
+ [(if !Flags.camltk then
+ "TkQuote (TkTokenList (List.map (fun y -> "
+ else
+ "TkQuote (TkTokenList (List.map ~f:(fun y -> ");
+ converterCAMLtoTK ~context_widget "y" ty;
+ ")";
+ argname;
+ "))"]
+ | Function _ -> fatal_error "unexpected function type in converterCAMLtoTK"
+ | Unit -> fatal_error "unexpected unit type in converterCAMLtoTK"
+ | Record _ -> fatal_error "unexpected product type in converterCAMLtoTK"
+
+(*
+ * Produce a list of arguments from a template
+ * The idea here is to avoid allocation as much as possible
+ *
+ *)
+
+let code_of_template ~context_widget ?func:(funtemplate=false) template =
+ let catch_opts = ref ("", "") in (* class name and first option *)
+ let variables = ref [] in
+ let variables2 = ref [] in
+ let varcnter = ref 0 in
+ let optionvar = ref None in
+ let newvar1 l =
+ match !optionvar with
+ Some v -> optionvar := None; v
+ | None ->
+ incr varcnter;
+ let v = "v" ^ (string_of_int !varcnter) in
+ variables := (l, v) :: !variables; v in
+ let newvar2 l =
+ match !optionvar with
+ Some v -> optionvar := None; v
+ | None ->
+ incr varcnter;
+ let v = "v" ^ (string_of_int !varcnter) in
+ variables2 := (l, v) :: !variables2; v in
+ let newvar = ref newvar1 in
+ let rec coderec = function
+ StringArg s -> "TkToken \"" ^ s ^ "\""
+ | TypeArg (_, List (Subtype (sup, sub))) when not !Flags.camltk ->
+ begin try
+ let typdef = Hashtbl.find types_table sup in
+ let classdef = List.assoc sub typdef.subtypes in
+ let lbl = gettklabel (List.hd classdef) in
+ catch_opts := (sub ^ "_" ^ sup, lbl);
+ newvar := newvar2;
+ "TkTokenList opts"
+ with Not_found ->
+ raise (Failure (Printf.sprintf "type %s(%s) not found" sup sub));
+ end
+ | TypeArg (l, List ty) ->
+ (if !Flags.camltk then
+ "TkTokenList (List.map (function x -> "
+ else
+ "TkTokenList (List.map ~f:(function x -> ")
+ ^ converterCAMLtoTK ~context_widget "x" ty
+ ^ ") " ^ !newvar l ^ ")"
+ | TypeArg (l, Function tyarg) ->
+ "let id = register_callback " ^ context_widget
+ ^ " ~callback: " ^ wrapper_code ~name:(!newvar l) tyarg
+ ^ " in TkToken (\"camlcb \" ^ id)"
+ | TypeArg (l, ty) -> converterCAMLtoTK ~context_widget (!newvar l) ty
+ | ListArg l ->
+ "TkQuote (TkTokenList ["
+ ^ String.concat ~sep:";\n " (List.map ~f:coderec l) ^ "])"
+ | OptionalArgs (l, tl, d) ->
+ let nv = !newvar ("?" ^ l) in
+ optionvar := Some nv; (* Store *)
+ let argstr = String.concat ~sep:"; " (List.map ~f:coderec tl) in
+ let defstr = String.concat ~sep:"; " (List.map ~f:coderec d) in
+ "TkTokenList (match " ^ nv ^ " with\n"
+ ^ " | Some " ^ nv ^ " -> [" ^ argstr ^ "]\n"
+ ^ " | None -> [" ^ defstr ^ "])"
+ in
+ let code =
+ if funtemplate then
+ match template with
+ ListArg l ->
+ "[|" ^ String.concat ~sep:";\n " (List.map ~f:coderec l) ^ "|]"
+ | _ -> "[|" ^ coderec template ^ "|]"
+ else
+ match template with
+ ListArg [x] -> coderec x
+ | ListArg l ->
+ "TkTokenList [" ^
+ String.concat ~sep:";\n " (List.map ~f:coderec l) ^
+ "]"
+ | _ -> coderec template
+ in
+ code, List.rev !variables, List.rev !variables2, !catch_opts
+
+(*
+ * Converters for user defined types
+ *)
+
+(* For each case of a concrete type *)
+let labltk_write_clause ~w ~context_widget comp =
+ let warrow () = w " -> " in
+ w "`";
+ w comp.var_name;
+
+ let code, variables, variables2, (co, _) =
+ code_of_template ~context_widget comp.template in
+
+ (* no subtype I think ... *)
+ if co <> "" then raise (Failure "write_clause subtype ?");
+ begin match variables with
+ | [] -> warrow()
+ | [x] -> w " "; w (labeloff x ~at:"write_clause"); warrow()
+ | l ->
+ w " ( ";
+ w (String.concat ~sep:", " (List.map ~f:(labeloff ~at:"write_clause") l));
+ w ")";
+ warrow()
+ end;
+ w code
+
+let camltk_write_clause ~w ~context_widget ~subtype comp =
+ let warrow () =
+ w " -> ";
+ if subtype then
+ w ("chk_sub \""^comp.ml_name^"\" table C" ^ comp.ml_name ^ "; ")
+ in
+
+ w comp.ml_name; (* we use ml_name, not var_name, specialized for labltk *)
+
+ let code, variables, variables2, (co, _) =
+ code_of_template ~context_widget comp.template in
+
+ (* no subtype I think ... *)
+ if co <> "" then raise (Failure "write_clause subtype ?");
+ begin match variables with
+ | [] -> warrow()
+ | [x] -> w " "; w (labeloff x ~at:"write_clause"); warrow()
+ | l ->
+ w " ( ";
+ w (String.concat ~sep:", " (List.map ~f:(labeloff ~at:"write_clause") l));
+ w ")";
+ warrow()
+ end;
+ w code
+
+let write_clause ~w ~context_widget ~subtype comp =
+ if !Flags.camltk then camltk_write_clause ~w ~context_widget ~subtype comp
+ else labltk_write_clause ~w ~context_widget comp
+
+(* The full converter *)
+let write_CAMLtoTK ~w ~def:typdef ?safetype:(st = true) name =
+ let write_one name constrs =
+ let subtype = typdef.subtypes <> [] in
+ w ("let cCAMLtoTK" ^ name);
+ let context_widget =
+ if typdef.requires_widget_context then begin
+ w " w"; "w"
+ end
+ else
+ "dummy" in
+ if !Flags.camltk && subtype then w " table";
+ if st then begin
+ w " : ";
+ if typdef.variant then w ("[< " ^ name ^ "]") else w name;
+ w " -> tkArgs "
+ end;
+ w (" = function");
+ List.iter constrs
+ ~f:(fun c -> w "\n | "; write_clause ~w ~context_widget ~subtype c);
+ w "\n\n\n"
+ in
+
+ let constrs = typdef.constructors in
+ if !Flags.camltk then write_one name constrs
+ else begin
+ (* Only needed if no subtypes, otherwise use optionals *)
+ if typdef.subtypes == [] then
+ write_one name constrs
+ else
+ List.iter constrs ~f:
+ begin fun fc ->
+ let code, vars, _, (co, _) =
+ code_of_template ~context_widget:"dummy" fc.template in
+ if co <> "" then fatal_error "optionals in optionals";
+ let vars = List.map ~f:snd vars in
+ w "let ccCAMLtoTK"; w name; w "_"; w (small fc.ml_name);
+ w " ("; w (String.concat ~sep:", " vars); w ") =\n ";
+ w code; w "\n\n"
+ end
+ end
+
+(* Tcl does not really return "lists". It returns sp separated tokens *)
+let rec write_result_parsing ~w = function
+ List String ->
+ w "(splitlist res)"
+ | List ty ->
+ if !Flags.camltk then
+ w (" List.map " ^ converterTKtoCAML ~arg:"(splitlist res)" ty)
+ else
+ w (" List.map ~f: " ^ converterTKtoCAML ~arg:"(splitlist res)" ty)
+ | Product tyl -> raise (Failure "Product -> record was done. ???")
+ | Record tyl -> (* of course all the labels are "" *)
+ let rnames = varnames ~prefix:"r" (List.length tyl) in
+ w " let l = splitlist res in";
+ w ("\n if List.length l <> " ^ string_of_int (List.length tyl));
+ w ("\n then Pervasives.raise (TkError (\"unexpected result: \" ^ res))");
+ w ("\n else ");
+ List.iter2 rnames tyl ~f:
+ begin fun r (l, ty) ->
+ if l <> "" then raise (Failure "lables in return type!!!");
+ w (" let " ^ r ^ ", l = ");
+ begin match type_parser_arity ty with
+ OneToken ->
+ w (converterTKtoCAML ~arg:"(List.hd l)" ty); w (", List.tl l")
+ | MultipleToken ->
+ w (converterTKtoCAML ~arg:"l" ty)
+ end;
+ w (" in\n")
+ end;
+ w (String.concat ~sep:", " rnames)
+ | String ->
+ w (converterTKtoCAML ~arg:"res" String)
+ | As (ty, _) -> write_result_parsing ~w ty
+ | ty ->
+ match type_parser_arity ty with
+ OneToken -> w (converterTKtoCAML ~arg:"res" ty)
+ | MultipleToken -> w (converterTKtoCAML ~arg:"(splitlist res)" ty)
+
+let labltk_write_function ~w def =
+ w ("let " ^ def.ml_name);
+ (* a bit approximative *)
+ let context_widget = match def.template with
+ ListArg (TypeArg(_, UserDefined("widget")) :: _) -> "v1"
+ | ListArg (TypeArg(_, Subtype("widget", _)) :: _) -> "v1"
+ | _ -> "dummy" in
+
+ let code, variables, variables2, (co, lbl) =
+ code_of_template ~func:true ~context_widget def.template in
+ (* Arguments *)
+ let uv, lv, ov =
+ let rec replace_args ~u ~l ~o = function
+ [] -> u, l, o
+ | ("", x) :: ls ->
+ replace_args ~u:(x :: u) ~l ~o ls
+ | (p, _ as x) :: ls when p.[0] = '?' ->
+ replace_args ~u ~l ~o:(x :: o) ls
+ | x :: ls ->
+ replace_args ~u ~l:(x :: l) ~o ls
+ in
+ replace_args ~u:[] ~l:[] ~o:[] (List.rev (variables @ variables2))
+ in
+ let has_opts = (ov <> [] || co <> "") in
+ if not has_opts then List.iter uv ~f:(fun x -> w " "; w x);
+ List.iter (lv@ov) ~f:(fun (l, v) -> w " "; w (labelstring l); w v);
+ if co <> "" then begin
+ if lv = [] && ov = [] then w (" ?" ^ lbl ^ ":eta");
+ w " =\n";
+ w (co ^ "_optionals");
+ if lv = [] && ov = [] then w (" ?" ^ lbl ^ ":eta");
+ w " (fun opts";
+ if uv = [] then w " ()" else
+ if has_opts then List.iter uv ~f:(fun x -> w " "; w x);
+ w " ->\n"
+ end else begin
+ if (ov <> [] || lv = []) && uv = [] then w " ()" else
+ if has_opts then List.iter uv ~f:(fun x -> w " "; w x);
+ w " =\n"
+ end;
+ begin match def.result with
+ | Unit | As (Unit, _) -> w "tkCommand "; w code
+ | ty ->
+ w "let res = tkEval "; w code ; w " in \n";
+ write_result_parsing ~w ty
+ end;
+ if co <> "" then w ")";
+ w "\n\n"
+
+let camltk_write_function ~w def =
+ w ("let " ^ def.ml_name);
+ (* a bit approximative *)
+ let context_widget = match def.template with
+ ListArg (TypeArg(_, UserDefined("widget")) :: _) -> "v1"
+ | ListArg (TypeArg(_, Subtype("widget", _)) :: _) -> "v1"
+ | _ -> "dummy" in
+
+ let code, variables, variables2, (co, lbl) =
+ code_of_template ~func:true ~context_widget def.template in
+ (* Arguments *)
+ let uv, ov =
+ let rec replace_args ~u ~o = function
+ [] -> u, o
+ | ("", x) :: ls ->
+ replace_args ~u:(x :: u) ~o ls
+ | (p, _ as x) :: ls when p.[0] = '?' ->
+ replace_args ~u ~o:(x :: o) ls
+ | (_,x) :: ls ->
+ replace_args ~u:(x::u) ~o ls
+ in
+ replace_args ~u:[] ~o:[] (List.rev (variables @ variables2))
+ in
+ let has_opts = ov <> [] (* (ov <> [] || co <> "") *) in
+ if not has_opts then List.iter uv ~f:(fun x -> w " "; w x);
+ List.iter ov ~f:(fun (l, v) -> w " "; w (labelstring l); w v);
+ begin
+ if uv = [] then w " ()" else
+ if has_opts then List.iter uv ~f:(fun x -> w " "; w x);
+ w " =\n"
+ end;
+ begin match def.result with
+ | Unit | As (Unit, _) -> w "tkCommand "; w code
+ | ty ->
+ w "let res = tkEval "; w code ; w " in \n";
+ write_result_parsing ~w ty
+ end;
+ w "\n\n"
+
+(*
+ w ("let " ^ def.ml_name);
+ (* a bit approximative *)
+ let context_widget = match def.template with
+ ListArg (TypeArg(_, UserDefined("widget")) :: _) -> "v1"
+ | ListArg (TypeArg(_, Subtype("widget", _)) :: _) -> "v1"
+ | _ -> "dummy" in
+
+ let code, variables, variables2, (co, lbl) =
+ code_of_template ~func:true ~context_widget def.template in
+ let variables = variables @ variables2 in
+ (* Arguments *)
+ begin match variables with
+ [] -> w " () =\n"
+ | l ->
+ let has_normal_argument = ref false in
+ List.iter (fun (l,x) ->
+ w " ";
+ if l <> "" then
+ if l.[0] = '?' then w (l ^ ":") else has_normal_argument := true
+ else has_normal_argument := true;
+ w x) l;
+ if not !has_normal_argument then w " ()";
+ w " =\n"
+ end;
+ begin match def.result with
+ | Unit | As (Unit, _) -> w "tkCommand "; w code
+ | ty ->
+ w "let res = tkEval "; w code ; w " in \n";
+ write_result_parsing ~w ty
+ end;
+ w "\n\n"
+*)
+
+let write_function ~w def =
+ if !Flags.camltk then camltk_write_function ~w def
+ else labltk_write_function ~w def
+;;
+
+let labltk_write_create ~w clas =
+ w ("let create ?name =\n");
+ w (" " ^ clas ^ "_options_optionals (fun opts parent ->\n");
+ w (" let w = new_atom \"" ^ clas ^ "\" ~parent ?name in\n");
+ w " tkCommand [|";
+ w ("TkToken \"" ^ clas ^ "\";\n");
+ w (" TkToken (Widget.name w);\n");
+ w (" TkTokenList opts |];\n");
+ w (" w)\n\n\n")
+
+let camltk_write_create ~w clas =
+ w ("let create ?name parent options =\n");
+ w (" let w = new_atom \"" ^ clas ^ "\" ~parent ?name in\n");
+ w " tkCommand [|";
+ w ("TkToken \"" ^ clas ^ "\";\n");
+ w (" TkToken (Widget.name w);\n");
+ w (" TkTokenList (List.map (function x -> "^
+ converterCAMLtoTK "w" "x" (Subtype("options",clas)) ^ ") options)\n");
+ w (" |];\n");
+ w (" w\n\n")
+
+let camltk_write_named_create ~w clas =
+ w ("let create_named parent name options =\n");
+ w (" let w = new_atom \"" ^ clas ^ "\" ~parent ~name in\n");
+ w " tkCommand [|";
+ w ("TkToken \"" ^ clas ^ "\";\n");
+ w (" TkToken (Widget.name w);\n");
+ w (" TkTokenList (List.map (function x -> "^
+ converterCAMLtoTK "w" "x" (Subtype("options",clas)) ^ ") options)\n");
+ w (" |];\n");
+ w (" w\n\n")
+
+(* Search Path. *)
+let search_path = ref ["."]
+
+(* taken from utils/misc.ml *)
+let find_in_path path name =
+ if not (Filename.is_implicit name) then
+ if Sys.file_exists name then name else raise Not_found
+ else begin
+ let rec try_dir = function
+ [] -> raise Not_found
+ | dir :: rem ->
+ let fullname = Filename.concat dir name in
+ if Sys.file_exists fullname then fullname else try_dir rem
+ in try_dir path
+ end
+
+(* builtin-code: the file (without suffix) is in .template... *)
+(* not efficient, but hell *)
+let write_external ~w def =
+ match def.template with
+ | StringArg fname ->
+ begin try
+ let realname = find_in_path !search_path (fname ^ ".ml") in
+ let ic = open_in_bin realname in
+ try
+ let code_list = Ppparse.parse_channel ic in
+ close_in ic;
+ List.iter (Ppexec.exec (fun _ -> ()) w)
+ (if !Flags.camltk then
+ Code.Define "CAMLTK" :: code_list else code_list );
+ with
+ | Ppparse.Error s ->
+ close_in ic;
+ raise (Compiler_Error (Printf.sprintf "Preprocess error: %s" s))
+ with
+ | Not_found ->
+ raise (Compiler_Error ("can't find external file: " ^ fname))
+ end
+ | _ -> raise (Compiler_Error "invalid external definition")
+
+let write_catch_optionals ~w clas ~def:typdef =
+ if typdef.subtypes = [] then () else
+ List.iter typdef.subtypes ~f:
+ begin fun (subclass, classdefs) ->
+ w ("let " ^ subclass ^ "_" ^ clas ^ "_optionals f = fun\n");
+ let tklabels = List.map ~f:gettklabel classdefs in
+ let l =
+ List.map classdefs ~f:
+ begin fun fc ->
+ (*
+ let code, vars, _, (co, _) =
+ code_of_template ~context_widget:"dummy" fc.template in
+ if co <> "" then fatal_error "optionals in optionals";
+ *)
+ let p = gettklabel fc in
+ (if count ~item:p tklabels > 1 then small fc.var_name else p),
+ small fc.ml_name
+ end in
+ let p = List.map l ~f:(fun (si, _) -> " ?" ^ si) in
+ let v =
+ List.map l ~f:
+ begin fun (si, s) ->
+ "(maycons ccCAMLtoTK" ^ clas ^ "_" ^ s ^ " " ^ si
+ end in
+ w (String.concat ~sep:"\n" p);
+ w " ->\n";
+ w " f ";
+ w (String.concat ~sep:"\n " v);
+ w "\n []";
+ w (String.make (List.length v) ')');
+ w "\n\n"
+ end
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/copyright b/ocaml-binary-annot/otherlibs/labltk/compiler/copyright
new file mode 100644
index 0000000000..23dff46dce
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/copyright
@@ -0,0 +1,15 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file LICENSE found in the Objective Caml source tree. *)
+(* *)
+(***********************************************************************)
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/flags.ml b/ocaml-binary-annot/otherlibs/labltk/compiler/flags.ml
new file mode 100644
index 0000000000..009d5e725a
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/flags.ml
@@ -0,0 +1,17 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file LICENSE found in the Objective Caml source tree. *)
+(* *)
+(***********************************************************************)
+
+let camltk = ref false;;
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/intf.ml b/ocaml-binary-annot/otherlibs/labltk/compiler/intf.ml
new file mode 100644
index 0000000000..59608b3815
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/intf.ml
@@ -0,0 +1,191 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file LICENSE found in the Objective Caml source tree. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open StdLabels
+
+(* Write .mli for widgets *)
+
+open Tables
+open Compile
+
+let labltk_write_create_p ~w wname =
+ w "val create :\n ?name:string ->\n";
+ begin
+ try
+ let option = Hashtbl.find types_table "options" in
+ let classdefs = List.assoc wname option.subtypes in
+ let tklabels = List.map ~f:gettklabel classdefs in
+ let l = List.map classdefs ~f:
+ begin fun fc ->
+ begin let p = gettklabel fc in
+ if count ~item:p tklabels > 1 then small fc.var_name else p
+ end,
+ fc.template
+ end in
+ w (String.concat ~sep:" ->\n"
+ (List.map l ~f:
+ begin fun (s, t) ->
+ " ?" ^ s ^ ":"
+ ^(ppMLtype
+ (match types_of_template t with
+ | [t] -> labeloff t ~at:"write_create_p"
+ | [] -> fatal_error "multiple"
+ | l -> Product (List.map ~f:(labeloff ~at:"write_create_p") l)))
+ end))
+ with Not_found -> fatal_error "in write_create_p"
+ end;
+ w (" ->\n 'a widget -> " ^ wname ^ " widget\n");
+ w "(** [create ?name parent options...] creates a new widget with\n";
+ w " parent [parent] and new patch component [name], if specified. *)\n\n"
+;;
+
+let camltk_write_create_p ~w wname =
+ w "val create : ?name: string -> widget -> options list -> widget \n";
+ w "(** [create ?name parent options] creates a new widget with\n";
+ w " parent [parent] and new patch component [name] if specified.\n";
+ w " Options are restricted to the widget class subset, and checked\n";
+ w " dynamically. *)\n\n"
+;;
+
+let camltk_write_named_create_p ~w wname =
+ w "val create_named : widget -> string -> options list -> widget \n";
+ w "(** [create_named parent name options] creates a new widget with\n";
+ w " parent [parent] and new patch component [name].\n";
+ w " This function is now obsolete and unified with [create]. *)\n\n";
+;;
+
+(* Unsafe: write special comment *)
+let labltk_write_function_type ~w def =
+ if not def.safe then w "(* unsafe *)\n";
+ w "val "; w def.ml_name; w " : ";
+ let us, ls, os =
+ let tys = types_of_template def.template in
+ let rec replace_args ~u ~l ~o = function
+ [] -> u, l, o
+ | (_, List(Subtype _) as x)::ls ->
+ replace_args ~u ~l ~o:(x::o) ls
+ | ("", _ as x)::ls ->
+ replace_args ~u:(x::u) ~l ~o ls
+ | (p, _ as x)::ls when p.[0] = '?' ->
+ replace_args ~u ~l ~o:(x::o) ls
+ | x::ls ->
+ replace_args ~u ~l:(x::l) ~o ls
+ in
+ replace_args ~u:[] ~l:[] ~o:[] (List.rev tys)
+ in
+ let counter = ref 0 in
+ let params =
+ if os = [] then us @ ls else ls @ os @ us in
+ List.iter params ~f:
+ begin fun (l, t) ->
+ if l <> "" then w (l ^ ":");
+ w (ppMLtype t ~counter);
+ w " -> "
+ end;
+ if (os <> [] || ls = []) && us = [] then w "unit -> ";
+ w (ppMLtype ~any:true ~return:true def.result); (* RETURN TYPE !!! *)
+ w " \n";
+(* w "(* tk invocation: "; w (doc_of_template def.template); w " *)"; *)
+ if def.safe then w "\n"
+ else w "\n(* /unsafe *)\n"
+
+let camltk_write_function_type ~w def =
+ if not def.safe then w "(* unsafe *)\n";
+ w "val "; w def.ml_name; w " : ";
+ let us, os =
+ let tys = types_of_template def.template in
+ let rec replace_args ~u ~o = function
+ [] -> u, o
+ | ("", _ as x)::ls ->
+ replace_args ~u:(x::u) ~o ls
+ | (p, _ as x)::ls when p.[0] = '?' ->
+ replace_args ~u ~o:(x::o) ls
+ | x::ls ->
+ replace_args ~u:(x::u) ~o ls
+ in
+ replace_args ~u:[] ~o:[] (List.rev tys)
+ in
+ let counter = ref 0 in
+ let params =
+ if os = [] then us else os @ us in
+ List.iter params ~f:
+ begin fun (l, t) ->
+ if l <> "" then if l.[0] = '?' then w (l ^ ":");
+ w (ppMLtype t ~counter);
+ w " -> "
+ end;
+ if us = [] then w "unit -> ";
+ w (ppMLtype ~any:true ~return:true def.result); (* RETURN TYPE !!! *)
+ w " \n";
+(* w "(* tk invocation: "; w (doc_of_template def.template); w " *)"; *)
+ if def.safe then w "\n"
+ else w "\n(* /unsafe *)\n"
+
+(*
+ if not def.safe then w "(* unsafe *)\n";
+ w "val "; w def.ml_name; w " : ";
+ let tys = types_of_template def.template in
+ let counter = ref 0 in
+ let have_normal_arg = ref false in
+ List.iter tys ~f:
+ begin fun (l, t) ->
+ if l <> "" then
+ if l.[0] = '?' then w (l^":")
+ else begin
+ have_normal_arg := true;
+ w (" (* " ^ l ^ ":*)")
+ end
+ else have_normal_arg := true;
+ w (ppMLtype t ~counter);
+ w " -> "
+ end;
+ if not !have_normal_arg then w "unit -> ";
+ w (ppMLtype ~any:true ~return:true def.result); (* RETURN TYPE !!! *)
+ w " \n";
+ if def.safe then w "\n"
+ else w "\n(* /unsafe *)\n"
+*)
+
+let write_function_type ~w def =
+ if !Flags.camltk then camltk_write_function_type ~w def
+ else labltk_write_function_type ~w def
+
+let write_external_type ~w def =
+ match def.template with
+ | StringArg fname ->
+ begin try
+ let realname = find_in_path !search_path (fname ^ ".mli") in
+ let ic = open_in_bin realname in
+ try
+ let code_list = Ppparse.parse_channel ic in
+ close_in ic;
+ if not def.safe then w "(* unsafe *)\n";
+ List.iter (Ppexec.exec (fun _ -> ()) w)
+ (if !Flags.camltk then
+ Code.Define "CAMLTK" :: code_list else code_list );
+ if def.safe then w "\n\n"
+ else w "\n(* /unsafe *)\n\n"
+ with
+ | Ppparse.Error s ->
+ close_in ic;
+ raise (Compiler_Error (Printf.sprintf "Preprocess error: %s" s))
+ with
+ | Not_found ->
+ raise (Compiler_Error ("can't find external file: " ^ fname))
+ end
+ | _ -> raise (Compiler_Error "invalid external definition")
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/lexer.mll b/ocaml-binary-annot/otherlibs/labltk/compiler/lexer.mll
new file mode 100644
index 0000000000..f51f0c01f3
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/lexer.mll
@@ -0,0 +1,170 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file ../LICENSE. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+{
+open StdLabels
+open Lexing
+open Parser
+open Support
+
+exception Lexical_error of string
+let current_line = ref 1
+
+
+(* The table of keywords *)
+
+let keyword_table = (Hashtbl.create 149 : (string, token) Hashtbl.t)
+
+let _ = List.iter
+ ~f:(fun (str,tok) -> Hashtbl.add keyword_table str tok)
+ [
+ "int", TYINT;
+ "float", TYFLOAT;
+ "bool", TYBOOL;
+ "char", TYCHAR;
+ "string", TYSTRING;
+ "list", LIST;
+ "as", AS;
+ "variant", VARIANT;
+ "widget", WIDGET;
+ "option", OPTION;
+ "type", TYPE;
+ "subtype", SUBTYPE;
+ "function", FUNCTION;
+ "module", MODULE;
+ "external", EXTERNAL;
+ "sequence", SEQUENCE;
+ "unsafe", UNSAFE
+]
+
+
+(* To buffer string literals *)
+
+let initial_string_buffer = String.create 256
+let string_buff = ref initial_string_buffer
+let string_index = ref 0
+
+let reset_string_buffer () =
+ string_buff := initial_string_buffer;
+ string_index := 0;
+ ()
+
+let store_string_char c =
+ if !string_index >= String.length (!string_buff) then begin
+ let new_buff = String.create (String.length (!string_buff) * 2) in
+ String.blit ~src:(!string_buff) ~src_pos:0 ~dst:new_buff ~dst_pos:0
+ ~len:(String.length (!string_buff));
+ string_buff := new_buff
+ end;
+ String.set (!string_buff) (!string_index) c;
+ incr string_index
+
+let get_stored_string () =
+ let s = String.sub (!string_buff) ~pos:0 ~len:(!string_index) in
+ string_buff := initial_string_buffer;
+ s
+(* To translate escape sequences *)
+
+let char_for_backslash = function
+ 'n' -> '\010'
+ | 'r' -> '\013'
+ | 'b' -> '\008'
+ | 't' -> '\009'
+ | c -> c
+
+let char_for_decimal_code lexbuf i =
+ Char.chr(100 * (Char.code(Lexing.lexeme_char lexbuf i) - 48) +
+ 10 * (Char.code(Lexing.lexeme_char lexbuf (i+1)) - 48) +
+ (Char.code(Lexing.lexeme_char lexbuf (i+2)) - 48))
+
+let saved_string_start = ref 0
+
+}
+
+rule main = parse
+ '\010' { incr current_line; main lexbuf }
+ | [' ' '\013' '\009' '\026' '\012'] +
+ { main lexbuf }
+ | ['A'-'Z' 'a'-'z' '\192'-'\214' '\216'-'\246' '\248'-'\255' ]
+ ( '_' ? ['A'-'Z' 'a'-'z' '\192'-'\214' '\216'-'\246' '\248'-'\255' (*'*) '0'-'9' ] ) *
+ { let s = Lexing.lexeme lexbuf in
+ try
+ Hashtbl.find keyword_table s
+ with Not_found ->
+ IDENT s }
+
+ | "\""
+ { reset_string_buffer();
+ (* Start of token is start of string. *)
+ saved_string_start := lexbuf.lex_start_pos;
+ string lexbuf;
+ lexbuf.lex_start_pos <- !saved_string_start;
+ STRING (get_stored_string()) }
+ | "(" { LPAREN }
+ | ")" { RPAREN }
+ | "[" { LBRACKET }
+ | "]" { RBRACKET }
+ | "{" { LBRACE }
+ | "}" { RBRACE }
+ | "," { COMMA }
+ | ";" { SEMICOLON }
+ | ":" {COLON}
+ | "?" {QUESTION}
+ | "/" {SLASH}
+ | "%" { comment lexbuf; main lexbuf }
+ | "##line" { line lexbuf; main lexbuf }
+ | eof { EOF }
+ | _
+ { raise (Lexical_error("illegal character")) }
+
+
+and string = parse
+ '"'
+ { () }
+ | '\\' [' ' '\010' '\013' '\009' '\026' '\012'] +
+ { string lexbuf }
+ | '\\' ['\\' '"' 'n' 't' 'b' 'r']
+ { store_string_char(char_for_backslash(Lexing.lexeme_char lexbuf 1));
+ string lexbuf }
+ | '\\' ['0'-'9'] ['0'-'9'] ['0'-'9']
+ { store_string_char(char_for_decimal_code lexbuf 1);
+ string lexbuf }
+ | eof
+ { raise (Lexical_error("string not terminated")) }
+ | '\010'
+ { incr current_line;
+ store_string_char(Lexing.lexeme_char lexbuf 0);
+ string lexbuf }
+ | _
+ { store_string_char(Lexing.lexeme_char lexbuf 0);
+ string lexbuf }
+
+and comment = parse
+ '\010' { incr current_line }
+ | eof { () }
+ | _ { comment lexbuf }
+
+and linenum = parse
+ | ['0'-'9']+ {
+ let next_line = int_of_string (Lexing.lexeme lexbuf) in
+ current_line := next_line - 1
+ }
+ | _ { raise (Lexical_error("illegal ##line directive: no line number"))}
+
+and line = parse
+ | [' ' '\t']* { linenum lexbuf }
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/maincompile.ml b/ocaml-binary-annot/otherlibs/labltk/compiler/maincompile.ml
new file mode 100644
index 0000000000..d8c72a312d
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/maincompile.ml
@@ -0,0 +1,418 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file LICENSE found in the Objective Caml source tree. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open StdLabels
+open Support
+open Tables
+open Printer
+open Compile
+open Intf
+
+let flag_verbose = ref false
+let verbose_string s =
+ if !flag_verbose then prerr_string s
+let verbose_endline s =
+ if !flag_verbose then prerr_endline s
+
+let input_name = ref "Widgets.src"
+let output_dir = ref ""
+let destfile f = Filename.concat !output_dir f
+
+let usage () =
+ prerr_string "Usage: tkcompiler input.src\n";
+ flush stderr;
+ exit 1
+
+
+let prerr_error_header () =
+ prerr_string "File \""; prerr_string !input_name;
+ prerr_string "\", line ";
+ prerr_string (string_of_int !Lexer.current_line);
+ prerr_string ": "
+
+(* parse Widget.src config file *)
+let parse_file filename =
+ let ic = open_in_bin filename in
+ let lexbuf =
+ try
+ let code_list = Ppparse.parse_channel ic in
+ close_in ic;
+ let buf = Buffer.create 50000 in
+ List.iter (Ppexec.exec
+ (fun l -> Buffer.add_string buf
+ (Printf.sprintf "##line %d\n" l))
+ (Buffer.add_string buf))
+ (if !Flags.camltk then Code.Define "CAMLTK" :: code_list
+ else code_list);
+ Lexing.from_string (Buffer.contents buf)
+ with
+ | Ppparse.Error s ->
+ close_in ic;
+ raise (Compiler_Error (Printf.sprintf "Preprocess error: %s" s))
+ in
+ try
+ while true do
+ Parser.entry Lexer.main lexbuf
+ done
+ with
+ | Parsing.Parse_error ->
+ prerr_error_header();
+ prerr_string "Syntax error \n";
+ exit 1
+ | Lexer.Lexical_error s ->
+ prerr_error_header();
+ prerr_string "Lexical error (";
+ prerr_string s;
+ prerr_string ")\n";
+ exit 1
+ | Duplicate_Definition (s,s') ->
+ prerr_error_header();
+ prerr_string s; prerr_string " "; prerr_string s';
+ prerr_string " is defined twice.\n";
+ exit 1
+ | Compiler_Error s ->
+ prerr_error_header();
+ prerr_string "Internal error: "; prerr_string s; prerr_string "\n";
+ prerr_string "Please report bug\n";
+ exit 1
+ | End_of_file ->
+ ()
+
+(* The hack to provoke the production of cCAMLtoTKoptions_constrs *)
+
+(* Auxiliary function: the list of all the elements associated to keys
+ in an hash table. *)
+let elements t =
+ let elems = ref [] in
+ Hashtbl.iter (fun _ d -> elems := d :: !elems) t;
+ !elems;;
+
+(* Verifies that duplicated clauses are semantically equivalent and
+ returns a unique set of clauses. *)
+let uniq_clauses = function
+ | [] -> []
+ | l ->
+ let check_constr constr1 constr2 =
+ if constr1.template <> constr2.template then
+ begin
+ let code1, vars11, vars12, opts1 =
+ code_of_template ~context_widget:"dummy" constr1.template in
+ let code2, vars12, vars22, opts2 =
+ code_of_template ~context_widget:"dummy" constr2.template in
+ let err =
+ Printf.sprintf
+ "uncompatible redondant clauses for variant %s:\n %s\n and\n %s"
+ constr1.var_name code1 code2 in
+ Format.print_newline();
+ print_fullcomponent constr1;
+ Format.print_newline();
+ print_fullcomponent constr2;
+ Format.print_newline();
+ prerr_endline err;
+ fatal_error err
+ end in
+ let t = Hashtbl.create 11 in
+ List.iter l
+ ~f:(fun constr ->
+ let c = constr.var_name in
+ if Hashtbl.mem t c
+ then (check_constr constr (Hashtbl.find t c))
+ else Hashtbl.add t c constr);
+ elements t;;
+
+let option_hack oc =
+ if Hashtbl.mem types_table "options" then
+ let typdef = Hashtbl.find types_table "options" in
+ let hack =
+ { parser_arity = OneToken;
+ constructors = begin
+ let constrs =
+ List.map typdef.constructors ~f:
+ begin fun c ->
+ { component = Constructor;
+ ml_name = (if !Flags.camltk then "C" ^ c.ml_name
+ else c.ml_name);
+ var_name = c.var_name; (* as variants *)
+ template =
+ begin match c.template with
+ ListArg (x :: _) -> x
+ | _ -> fatal_error "bogus hack"
+ end;
+ result = UserDefined "options_constrs";
+ safe = true }
+ end in
+ if !Flags.camltk then constrs else uniq_clauses constrs (* JPF ?? *)
+ end;
+ subtypes = [];
+ requires_widget_context = false;
+ variant = false }
+ in
+ write_CAMLtoTK
+ ~w:(output_string oc) ~def:hack ~safetype:false "options_constrs"
+
+let realname name =
+ (* module name fix for camltk *)
+ if !Flags.camltk then "c" ^ String.capitalize name
+ else name
+;;
+
+(* analize the parsed Widget.src and output source files *)
+let compile () =
+ verbose_endline "Creating _tkgen.ml ...";
+ let oc = open_out_bin (destfile "_tkgen.ml") in
+ let oc' = open_out_bin (destfile "_tkigen.ml") in
+ let oc'' = open_out_bin (destfile "_tkfgen.ml") in
+ let sorted_types = Tsort.sort types_order in
+ verbose_endline " writing types ...";
+ List.iter sorted_types ~f:
+ begin fun typname ->
+ verbose_string (" " ^ typname ^ " ");
+ try
+ let typdef = Hashtbl.find types_table typname in
+ verbose_string "type ";
+ write_type ~intf:(output_string oc)
+ ~impl:(output_string oc')
+ typname ~def:typdef;
+ verbose_string "C2T ";
+ write_CAMLtoTK ~w:(output_string oc') typname ~def:typdef;
+ verbose_string "T2C ";
+ if List.mem typname !types_returned then
+ write_TKtoCAML ~w:(output_string oc') typname ~def:typdef;
+ verbose_string "CO ";
+ if not !Flags.camltk then (* only for LablTk *)
+ write_catch_optionals ~w:(output_string oc') typname ~def:typdef;
+ verbose_endline "."
+ with Not_found ->
+ if not (List.mem_assoc typname !types_external) then
+ begin
+ verbose_string "Type ";
+ verbose_string typname;
+ verbose_string " is undeclared external or undefined\n"
+ end
+ else verbose_endline "."
+ end;
+ verbose_endline " option hacking ...";
+ option_hack oc';
+ verbose_endline " writing functions ...";
+ List.iter ~f:(write_function ~w:(output_string oc'')) !function_table;
+ close_out oc;
+ close_out oc';
+ close_out oc'';
+ (* Write the interface for public functions *)
+ (* this interface is used only for documentation *)
+ verbose_endline "Creating _tkgen.mli ...";
+ let oc = open_out_bin (destfile "_tkgen.mli") in
+ List.iter (sort_components !function_table)
+ ~f:(write_function_type ~w:(output_string oc));
+ close_out oc;
+ verbose_endline "Creating other ml, mli ...";
+ let write_module wname wdef =
+ verbose_endline (" "^wname);
+ let modname = realname wname in
+ let oc = open_out_bin (destfile (modname ^ ".ml"))
+ and oc' = open_out_bin (destfile (modname ^ ".mli")) in
+ Copyright.write ~w:(output_string oc);
+ Copyright.write ~w:(output_string oc');
+ begin match wdef.module_type with
+ Widget -> output_string oc' ("(* The "^wname^" widget *)\n")
+ | Family -> output_string oc' ("(* The "^wname^" commands *)\n")
+ end;
+ List.iter ~f:(fun s -> output_string oc s; output_string oc' s)
+ begin
+ if !Flags.camltk then
+ [ "open CTk\n";
+ "open Tkintf\n";
+ "open Widget\n";
+ "open Textvariable\n\n" ]
+ else
+ [ "open StdLabels\n";
+ "open Tk\n";
+ "open Tkintf\n";
+ "open Widget\n";
+ "open Textvariable\n\n" ]
+ end;
+ output_string oc "open Protocol\n";
+ begin match wdef.module_type with
+ Widget ->
+ if !Flags.camltk then begin
+ camltk_write_create ~w:(output_string oc) wname;
+ camltk_write_named_create ~w:(output_string oc) wname;
+ camltk_write_create_p ~w:(output_string oc') wname;
+ camltk_write_named_create_p ~w:(output_string oc') wname;
+ end else begin
+ labltk_write_create ~w:(output_string oc) wname;
+ labltk_write_create_p ~w:(output_string oc') wname
+ end
+ | Family -> ()
+ end;
+ List.iter ~f:(write_function ~w:(output_string oc))
+ (sort_components wdef.commands);
+ List.iter ~f:(write_function_type ~w:(output_string oc'))
+ (sort_components wdef.commands);
+ List.iter ~f:(write_external ~w:(output_string oc))
+ (sort_components wdef.externals);
+ List.iter ~f:(write_external_type ~w:(output_string oc'))
+ (sort_components wdef.externals);
+ close_out oc;
+ close_out oc'
+ in Hashtbl.iter write_module module_table;
+
+ (* wrapper code camltk.ml and labltk.ml *)
+ if !Flags.camltk then begin
+ let oc = open_out_bin (destfile "camltk.ml") in
+ Copyright.write ~w:(output_string oc);
+ output_string oc
+"(** This module Camltk provides the module name spaces of the CamlTk API.\n\
+\n\
+ The users of the CamlTk API should open this module first to access\n\
+ the types, functions and modules of the CamlTk API easier.\n\
+ For the documentation of each sub modules such as [Button] and [Toplevel],\n\
+ refer to its defintion file, [cButton.mli], [cToplevel.mli], etc.\n\
+ *)\n\
+\n\
+";
+ output_string oc "include CTk\n";
+ output_string oc "module Tk = CTk\n";
+ Hashtbl.iter (fun name _ ->
+ let cname = realname name in
+ output_string oc (Printf.sprintf "module %s = %s;;\n"
+ (String.capitalize name)
+ (String.capitalize cname))) module_table;
+ close_out oc
+ end else begin
+ let oc = open_out_bin (destfile "labltk.ml") in
+ Copyright.write ~w:(output_string oc);
+ output_string oc
+"(** This module Labltk provides the module name spaces of the LablTk API,\n\
+ useful to call LablTk functions inside CamlTk programs. 100% LablTk users\n\
+ do not need to use this. *)\n\
+\n\
+";
+ output_string oc "module Widget = Widget;;\n\
+module Protocol = Protocol;;\n\
+module Textvariable = Textvariable;;\n\
+module Fileevent = Fileevent;;\n\
+module Timer = Timer;;\n\
+";
+ Hashtbl.iter (fun name _ ->
+ let cname = realname name in
+ output_string oc (Printf.sprintf "module %s = %s;;\n"
+ (String.capitalize name)
+ (String.capitalize cname))) module_table;
+ (* widget typer *)
+ output_string oc "\n(** Widget typers *)\n\nopen Widget\n\n";
+ Hashtbl.iter (fun name def ->
+ match def.module_type with
+ | Widget ->
+ output_string oc (Printf.sprintf
+ "let %s (w : any widget) =\n" name);
+ output_string oc (Printf.sprintf
+ " Rawwidget.check_class w widget_%s_table;\n" name);
+ output_string oc (Printf.sprintf
+ " (Obj.magic w : %s widget);;\n\n" name);
+ | _ -> () ) module_table;
+ close_out oc
+ end;
+
+ (* write the module list for the Makefile *)
+ (* and hack to death until it works *)
+ let oc = open_out_bin (destfile "modules") in
+ if !Flags.camltk then output_string oc "CWIDGETOBJS="
+ else output_string oc "WIDGETOBJS=";
+ Hashtbl.iter
+ (fun name _ ->
+ let name = realname name in
+ output_string oc name;
+ output_string oc ".cmo ")
+ module_table;
+ output_string oc "\n";
+ Hashtbl.iter
+ (fun name _ ->
+ let name = realname name in
+ output_string oc name;
+ output_string oc ".ml ")
+ module_table;
+ output_string oc ": _tkgen.ml\n\n";
+ Hashtbl.iter
+ (fun name _ ->
+ let name = realname name in
+ output_string oc name;
+ output_string oc ".cmo : ";
+ output_string oc name;
+ output_string oc ".ml\n";
+ output_string oc name;
+ output_string oc ".cmi : ";
+ output_string oc name;
+ output_string oc ".mli\n")
+ module_table;
+
+ (* for camltk.ml wrapper *)
+ if !Flags.camltk then begin
+ output_string oc "camltk.cmo : cTk.cmo ";
+ Hashtbl.iter
+ (fun name _ ->
+ let name = realname name in
+ output_string oc name;
+ output_string oc ".cmo ") module_table;
+ output_string oc "\n"
+ end;
+ close_out oc
+
+let main () =
+ Arg.parse
+ [ "-verbose", Arg.Unit (fun () -> flag_verbose := true),
+ "Make output verbose";
+ "-camltk", Arg.Unit (fun () -> Flags.camltk := true),
+ "Make CamlTk interface";
+ "-outdir", Arg.String (fun s -> output_dir := s),
+ "output directory";
+ "-debugpp", Arg.Unit (fun () -> Ppexec.debug := true),
+ "debug preprocessor"
+ ]
+ (fun filename -> input_name := filename)
+ "Usage: tkcompiler <source file>" ;
+ if !output_dir = "" then begin
+ prerr_endline "specify -outdir option";
+ exit 1
+ end;
+ try
+ verbose_endline "Parsing...";
+ parse_file !input_name;
+ verbose_endline "Compiling...";
+ compile ();
+ verbose_endline "Finished";
+ exit 0
+ with
+ | Lexer.Lexical_error s ->
+ prerr_string "Invalid lexical character: ";
+ prerr_endline s;
+ exit 1
+ | Duplicate_Definition (s, s') ->
+ prerr_string s; prerr_string " "; prerr_string s';
+ prerr_endline " is redefined illegally";
+ exit 1
+ | Invalid_implicit_constructor c ->
+ prerr_string "Constructor ";
+ prerr_string c;
+ prerr_endline " is used implicitly before defined";
+ exit 1
+ | Tsort.Cyclic ->
+ prerr_endline "Cyclic dependency of types";
+ exit 1
+
+let () = Printexc.catch main ()
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/parser.mly b/ocaml-binary-annot/otherlibs/labltk/compiler/parser.mly
new file mode 100644
index 0000000000..15ced65f8d
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/parser.mly
@@ -0,0 +1,330 @@
+/***********************************************************************/
+/* */
+/* MLTk, Tcl/Tk interface of Objective Caml */
+/* */
+/* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis */
+/* projet Cristal, INRIA Rocquencourt */
+/* Jacques Garrigue, Kyoto University RIMS */
+/* */
+/* Copyright 2002 Institut National de Recherche en Informatique et */
+/* en Automatique and Kyoto University. All rights reserved. */
+/* This file is distributed under the terms of the GNU Library */
+/* General Public License, with the special exception on linking */
+/* described in file ../LICENSE. */
+/* */
+/***********************************************************************/
+
+/* $Id$ */
+
+%{
+
+open Tables
+
+%}
+
+/* Tokens */
+%token <string> IDENT
+%token <string> STRING
+%token EOF
+
+%token LPAREN /* "(" */
+%token RPAREN /* ")" */
+%token COMMA /* "," */
+%token SEMICOLON /* ";" */
+%token COLON /* ":" */
+%token QUESTION /* "?" */
+%token LBRACKET /* "[" */
+%token RBRACKET /* "]" */
+%token LBRACE /* "{" */
+%token RBRACE /* "}" */
+%token SLASH /* "/" */
+
+%token TYINT /* "int" */
+%token TYFLOAT /* "float" */
+%token TYBOOL /* "bool" */
+%token TYCHAR /* "char" */
+%token TYSTRING /* "string" */
+%token LIST /* "list" */
+
+%token AS /* "as" */
+%token VARIANT /* "variant" */
+%token WIDGET /* "widget" */
+%token OPTION /* "option" */
+%token TYPE /* "type" */
+%token SEQUENCE /* "sequence" */
+%token SUBTYPE /* "subtype" */
+%token FUNCTION /* "function" */
+%token MODULE /* "module" */
+%token EXTERNAL /* "external" */
+%token UNSAFE /* "unsafe" */
+/* Entry points */
+%start entry
+%type <unit> entry
+
+%%
+TypeName:
+ IDENT { String.uncapitalize $1 }
+ | WIDGET { "widget" }
+;
+
+/* Atomic types */
+Type0 :
+ TYINT
+ { Int }
+ | TYFLOAT
+ { Float }
+ | TYBOOL
+ { Bool }
+ | TYCHAR
+ { Char }
+ | TYSTRING
+ { String }
+ | TypeName
+ { UserDefined $1 }
+;
+
+/* Camltk/Labltk types */
+Type0_5:
+ | Type0 SLASH Type0 { if !Flags.camltk then $1 else $3 }
+ | Type0 { $1 }
+;
+
+/* with subtypes */
+Type1 :
+ Type0_5
+ { $1 }
+ | TypeName LPAREN IDENT RPAREN
+ { Subtype ($1, $3) }
+ | WIDGET LPAREN IDENT RPAREN
+ { Subtype ("widget", $3) }
+ | OPTION LPAREN IDENT RPAREN
+ { Subtype ("options", $3) }
+ | Type1 AS STRING
+ { As ($1, $3) }
+ | LBRACE Type_list RBRACE
+ { Product $2 }
+;
+
+/* with list constructors */
+Type2 :
+ Type1
+ { $1 }
+ | Type2 LIST
+ { List $1 }
+;
+
+Labeled_type2 :
+ Type2
+ { "", $1 }
+ | IDENT COLON Type2
+ { $1, $3 }
+;
+
+/* products */
+Type_list :
+ Type2 COMMA Type_list
+ { $1 :: $3 }
+ | Type2
+ { [$1] }
+;
+
+/* records */
+Type_record :
+ Labeled_type2 COMMA Type_record
+ { $1 :: $3 }
+ | Labeled_type2
+ { [$1] }
+;
+
+/* callback arguments or function results*/
+FType :
+ LPAREN RPAREN
+ { Unit }
+ | LPAREN Type2 RPAREN
+ { $2 }
+ | LPAREN Type_record RPAREN
+ { Record $2 }
+;
+
+Type :
+ Type2
+ { $1 }
+ | FUNCTION FType
+ { Function $2 }
+;
+
+
+
+SimpleArg:
+ STRING
+ {StringArg $1}
+ | Type
+ {TypeArg ("", $1) }
+;
+
+Arg:
+ STRING
+ {StringArg $1}
+ | Type
+ {TypeArg ("", $1) }
+ | IDENT COLON Type
+ {TypeArg ($1, $3)}
+ | QUESTION IDENT COLON LBRACKET SimpleArgList RBRACKET DefaultList
+ {OptionalArgs ( $2, $5, $7 )}
+ | QUESTION WIDGET COLON LBRACKET SimpleArgList RBRACKET DefaultList
+ {OptionalArgs ( "widget", $5, $7 )}
+ | QUESTION IDENT COLON LBRACKET SimpleArgList RBRACKET
+ {OptionalArgs ( $2, $5, [] )}
+ | QUESTION WIDGET COLON LBRACKET SimpleArgList RBRACKET
+ {OptionalArgs ( "widget", $5, [] )}
+ | WIDGET COLON Type
+ {TypeArg ("widget", $3)}
+ | Template
+ { $1 }
+;
+
+SimpleArgList:
+ SimpleArg SEMICOLON SimpleArgList
+ { $1 :: $3}
+ | SimpleArg
+ { [$1] }
+;
+
+ArgList:
+ Arg SEMICOLON ArgList
+ { $1 :: $3}
+ | Arg
+ { [$1] }
+;
+
+/* DefaultList Only one TypeArg in ArgList and it must be unlabeled */
+DefaultList :
+ LBRACKET LBRACE ArgList RBRACE RBRACKET
+ {$3}
+
+/* Template */
+Template :
+ LBRACKET ArgList RBRACKET
+ { ListArg $2 }
+;
+
+
+/* Constructors for type declarations */
+Constructor :
+ IDENT Template
+ {{ component = Constructor;
+ ml_name = $1;
+ var_name = getvarname $1 $2;
+ template = $2;
+ result = Unit;
+ safe = true }}
+ | IDENT LPAREN IDENT RPAREN Template
+ {{ component = Constructor;
+ ml_name = $1;
+ var_name = $3;
+ template = $5;
+ result = Unit;
+ safe = true }}
+;
+
+AbbrevConstructor :
+ Constructor
+ { Full $1 }
+ | IDENT
+ { Abbrev $1 }
+;
+
+Constructors :
+ Constructor Constructors
+ { $1 :: $2 }
+| Constructor
+ { [$1] }
+;
+
+AbbrevConstructors :
+ AbbrevConstructor AbbrevConstructors
+ { $1 :: $2 }
+| AbbrevConstructor
+ { [$1] }
+;
+
+Safe:
+ /* */
+ { true }
+ | UNSAFE
+ { false }
+
+Command :
+ Safe FUNCTION FType IDENT Template
+ {{component = Command; ml_name = $4; var_name = "";
+ template = $5; result = $3; safe = $1 }}
+;
+
+External :
+ Safe EXTERNAL IDENT STRING
+ {{component = External; ml_name = $3; var_name = "";
+ template = StringArg $4; result = Unit; safe = $1}}
+;
+
+Option :
+ OPTION IDENT Template
+ {{component = Constructor; ml_name = $2; var_name = getvarname $2 $3;
+ template = $3; result = Unit; safe = true }}
+ /* Abbreviated */
+| OPTION IDENT LPAREN IDENT RPAREN Template
+ {{component = Constructor; ml_name = $2; var_name = $4;
+ template = $6; result = Unit; safe = true }}
+ /* Abbreviated */
+| OPTION IDENT
+ { retrieve_option $2 }
+;
+
+WidgetComponents :
+ /* */
+ { [] }
+ | Command WidgetComponents
+ { $1 :: $2 }
+ | Option WidgetComponents
+ { $1 :: $2 }
+ | External WidgetComponents
+ { $1 :: $2 }
+;
+
+ModuleComponents :
+ /* */
+ { [] }
+ | Command ModuleComponents
+ { $1 :: $2 }
+ | External ModuleComponents
+ { $1 :: $2 }
+;
+
+ParserArity :
+ /* */
+ { OneToken }
+ | SEQUENCE
+ { MultipleToken }
+;
+
+
+
+entry :
+ TYPE ParserArity TypeName LBRACE Constructors RBRACE
+ { enter_type $3 $2 $5 }
+| VARIANT TYPE ParserArity TypeName LBRACE Constructors RBRACE
+ { enter_type $4 $3 $6 ~variant: true }
+| TYPE ParserArity TypeName EXTERNAL
+ { enter_external_type $3 $2 }
+| SUBTYPE ParserArity OPTION LPAREN IDENT RPAREN LBRACE AbbrevConstructors RBRACE
+ { enter_subtype "options" $2 $5 $8 }
+| SUBTYPE ParserArity TypeName LPAREN IDENT RPAREN LBRACE AbbrevConstructors RBRACE
+ { enter_subtype $3 $2 $5 $8 }
+| Command
+ { enter_function $1 }
+| WIDGET IDENT LBRACE WidgetComponents RBRACE
+ { enter_widget $2 $4 }
+| MODULE IDENT LBRACE ModuleComponents RBRACE
+ { enter_module (String.uncapitalize $2) $4 }
+| EOF
+ { raise End_of_file }
+;
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/pp.ml b/ocaml-binary-annot/otherlibs/labltk/compiler/pp.ml
new file mode 100644
index 0000000000..5c46766af7
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/pp.ml
@@ -0,0 +1,23 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file LICENSE found in the Objective Caml source tree. *)
+(* *)
+(***********************************************************************)
+
+let _ =
+ try
+ let code_list = Ppparse.parse_channel stdin in
+ List.iter (Ppexec.exec (fun _ -> ()) print_string) code_list
+ with
+ | Ppparse.Error s -> prerr_endline s; exit 2
+;;
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/ppexec.ml b/ocaml-binary-annot/otherlibs/labltk/compiler/ppexec.ml
new file mode 100644
index 0000000000..71118b9601
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/ppexec.ml
@@ -0,0 +1,60 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file LICENSE found in the Objective Caml source tree. *)
+(* *)
+(***********************************************************************)
+
+open Code
+
+let debug = ref false
+let defined = ref []
+let linenum = ref 1
+
+let rec nop = function
+ | Line _ -> incr linenum
+ | Ifdef (_, _, c1, c2o) ->
+ List.iter nop c1;
+ begin match c2o with
+ | Some c2 -> List.iter nop c2
+ | None -> ()
+ end
+ | _ -> ()
+;;
+
+let rec exec lp f = function
+ | Line line ->
+ if !debug then
+ prerr_endline (Printf.sprintf "%03d: %s" !linenum
+ (String.sub line 0 ((String.length line) - 1)));
+ f line; incr linenum
+ | Ifdef (sw, k, c1, c2o) ->
+ if List.mem k !defined = sw then begin
+ List.iter (exec lp f) c1;
+ begin match c2o with
+ | Some c2 -> List.iter nop c2
+ | None -> ()
+ end;
+ lp !linenum
+ end else begin
+ List.iter nop c1;
+ match c2o with
+ | Some c2 ->
+ lp !linenum;
+ List.iter (exec lp f) c2
+ | None -> ()
+ end
+ | Define k -> defined := k :: !defined
+ | Undef k ->
+ defined := List.fold_right (fun k' s ->
+ if k = k' then s else k' :: s) [] !defined
+;;
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/pplex.mli b/ocaml-binary-annot/otherlibs/labltk/compiler/pplex.mli
new file mode 100644
index 0000000000..4eaa183b24
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/pplex.mli
@@ -0,0 +1,18 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file LICENSE found in the Objective Caml source tree. *)
+(* *)
+(***********************************************************************)
+
+exception Error of string
+val token : Lexing.lexbuf -> Ppyac.token
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/pplex.mll b/ocaml-binary-annot/otherlibs/labltk/compiler/pplex.mll
new file mode 100644
index 0000000000..313d1f2dd5
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/pplex.mll
@@ -0,0 +1,56 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file ../LICENSE. *)
+(* *)
+(***********************************************************************)
+
+{
+open Ppyac
+exception Error of string
+let linenum = ref 1
+}
+
+let blank = [' ' '\013' '\009' '\012']
+let identchar =
+ ['A'-'Z' 'a'-'z' '_' '\192'-'\214' '\216'-'\246' '\248'-'\255' '\'' '0'-'9']
+let lowercase = ['a'-'z' '\223'-'\246' '\248'-'\255' '_']
+let uppercase = ['A'-'Z' '\192'-'\214' '\216'-'\222']
+
+rule token = parse
+ blank + { token lexbuf }
+| "##" [' ' '\t']* { directive lexbuf }
+| ("#")? [^ '#' '\n']* '\n'? {
+ begin
+ let str = Lexing.lexeme lexbuf in
+ if String.length str <> 0 && str.[String.length str - 1] = '\n' then
+ begin
+ incr linenum
+ end;
+ OTHER (str)
+ end
+ }
+| eof { EOF }
+
+and directive = parse
+| "ifdef" [' ' '\t']+ { IFDEF (ident lexbuf)}
+| "ifndef" [' ' '\t']+ { IFNDEF (ident lexbuf)}
+| "else" { ELSE }
+| "endif" { ENDIF }
+| "define" [' ' '\t']+* { DEFINE (ident lexbuf)}
+| "undef" [' ' '\t']+ { UNDEF (ident lexbuf)}
+| _ { raise (Error (Printf.sprintf "unknown directive at line %d" !linenum))}
+
+and ident = parse
+| lowercase identchar* | uppercase identchar*
+ { Lexing.lexeme lexbuf }
+| _ { raise (Error (Printf.sprintf "illegal identifier at line %d" !linenum)) }
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/ppparse.ml b/ocaml-binary-annot/otherlibs/labltk/compiler/ppparse.ml
new file mode 100644
index 0000000000..630d675dec
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/ppparse.ml
@@ -0,0 +1,36 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file LICENSE found in the Objective Caml source tree. *)
+(* *)
+(***********************************************************************)
+
+exception Error of string
+
+let parse_channel ic =
+ let lexbuf = Lexing.from_channel ic in
+ try
+ Ppyac.code_list Pplex.token lexbuf
+ with
+ | Pplex.Error s ->
+ let loc_start = Lexing.lexeme_start lexbuf
+ and loc_end = Lexing.lexeme_end lexbuf
+ in
+ raise (Error (Printf.sprintf "parse error at char %d, %d: %s"
+ loc_start loc_end s))
+ | Parsing.Parse_error ->
+ let loc_start = Lexing.lexeme_start lexbuf
+ and loc_end = Lexing.lexeme_end lexbuf
+ in
+ raise (Error (Printf.sprintf "parse error at char %d, %d"
+ loc_start loc_end))
+;;
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/ppyac.mly b/ocaml-binary-annot/otherlibs/labltk/compiler/ppyac.mly
new file mode 100644
index 0000000000..da7ee681f2
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/ppyac.mly
@@ -0,0 +1,52 @@
+/***********************************************************************/
+/* */
+/* MLTk, Tcl/Tk interface of Objective Caml */
+/* */
+/* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis */
+/* projet Cristal, INRIA Rocquencourt */
+/* Jacques Garrigue, Kyoto University RIMS */
+/* */
+/* Copyright 2002 Institut National de Recherche en Informatique et */
+/* en Automatique and Kyoto University. All rights reserved. */
+/* This file is distributed under the terms of the GNU Library */
+/* General Public License, with the special exception on linking */
+/* described in file ../LICENSE. */
+/* */
+/***********************************************************************/
+
+%{
+open Code
+%}
+
+%token <string> IFDEF
+%token <string> IFNDEF
+%token ELSE
+%token ENDIF
+%token <string> DEFINE
+%token <string> UNDEF
+%token <string> OTHER
+%token EOF
+
+/* entry */
+
+%start code_list
+%type <Code.code list> code_list
+
+%%
+
+code_list:
+ /* empty */ { [] }
+ | code code_list { $1 :: $2 }
+;
+
+code:
+ | DEFINE { Define $1 }
+ | UNDEF { Undef $1 }
+ | IFDEF code_list ELSE code_list ENDIF { Ifdef (true, $1, $2, Some ($4)) }
+ | IFNDEF code_list ELSE code_list ENDIF { Ifdef (false, $1, $2, Some ($4)) }
+ | IFDEF code_list ENDIF { Ifdef (true, $1, $2, None) }
+ | IFNDEF code_list ENDIF { Ifdef (false, $1, $2, None) }
+ | OTHER { Line $1 }
+;
+
+%%
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/printer.ml b/ocaml-binary-annot/otherlibs/labltk/compiler/printer.ml
new file mode 100644
index 0000000000..be70612aa2
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/printer.ml
@@ -0,0 +1,173 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file LICENSE found in the Objective Caml source tree. *)
+(* *)
+(***********************************************************************)
+
+open Tables;;
+
+open Format;;
+
+let escape_string s =
+ let more = ref 0 in
+ for i = 0 to String.length s - 1 do
+ match s.[i] with
+ | '\\' | '"' -> incr more
+ | _ -> ()
+ done;
+ if !more = 0 then s else
+ let res = String.create (String.length s + !more) in
+ let j = ref 0 in
+ for i = 0 to String.length s - 1 do
+ let c = s.[i] in
+ match c with
+ | '\\' | '"' -> res.[!j] <- '\\'; incr j; res.[!j] <- c; incr j
+ | _ -> res.[!j] <- c; incr j
+ done;
+ res;;
+
+let escape_char c = if c = '\'' then "\\'" else String.make 1 c;;
+
+let print_quoted_string s = printf "\"%s\"" (escape_string s);;
+let print_quoted_char c = printf "'%s'" (escape_char c);;
+let print_quoted_int i =
+ if i < 0 then printf "(%d)" i else printf "%d" i;;
+let print_quoted_float f =
+ if f <= 0.0 then printf "(%f)" f else printf "%f" f;;
+
+(* Iterators *)
+let print_list f l =
+ printf "@[<1>[";
+ let rec pl = function
+ | [] -> printf "@;<0 -1>]@]"
+ | [x] -> f x; pl []
+ | x :: xs -> f x; printf ";@ "; pl xs in
+ pl l;;
+
+let print_array f v =
+ printf "@[<2>[|";
+ let l = Array.length v in
+ if l >= 1 then f v.(0);
+ if l >= 2 then
+ for i = 1 to l - 1 do
+ printf ";@ "; f v.(i)
+ done;
+ printf "@;<0 -1>|]@]";;
+
+let print_option f = function
+ | None -> print_string "None"
+ | Some x -> printf "@[<1>Some@ "; f x; printf "@]";;
+
+let print_bool = function
+ | true -> print_string "true" | _ -> print_string "false";;
+
+let print_poly x = print_string "<poly>";;
+
+(* Types of the description language *)
+let rec print_mltype = function
+ | Unit -> printf "Unit" | Int -> printf "Int" | Float -> printf "Float"
+ | Bool -> printf "Bool" | Char -> printf "Char" | String -> printf "String"
+ | List m -> printf "@[<1>(%s@ " "List"; print_mltype m; printf ")@]"
+ | Product l_m ->
+ printf "@[<1>(%s@ " "Product"; print_list print_mltype l_m; printf ")@]"
+ | Record l_t_s_m ->
+ printf "@[<1>(%s@ " "Record";
+ print_list
+ (function (s, m) ->
+ printf "@[<1>("; print_quoted_string s; printf ",@ "; print_mltype m;
+ printf ")@]")
+ l_t_s_m;
+ printf ")@]"
+ | UserDefined s ->
+ printf "@[<1>(%s@ " "UserDefined"; print_quoted_string s; printf ")@]"
+ | Subtype (s, s0) ->
+ printf "@[<1>(%s@ " "Subtype"; printf "@[<1>("; print_quoted_string s;
+ printf ",@ "; print_quoted_string s0; printf ")@]"; printf ")@]"
+ | Function m ->
+ printf "@[<1>(%s@ " "Function"; print_mltype m; printf ")@]"
+ | As (m, s) ->
+ printf "@[<1>(%s@ " "As"; printf "@[<1>("; print_mltype m; printf ",@ ";
+ print_quoted_string s; printf ")@]"; printf ")@]";;
+
+let rec print_template = function
+ | StringArg s ->
+ printf "@[<1>(%s@ " "StringArg"; print_quoted_string s; printf ")@]"
+ | TypeArg (s, m) ->
+ printf "@[<1>(%s@ " "TypeArg"; printf "@[<1>("; print_quoted_string s;
+ printf ",@ "; print_mltype m; printf ")@]"; printf ")@]"
+ | ListArg l_t ->
+ printf "@[<1>(%s@ " "ListArg"; print_list print_template l_t;
+ printf ")@]"
+ | OptionalArgs (s, l_t, l_t0) ->
+ printf "@[<1>(%s@ " "OptionalArgs"; printf "@[<1>(";
+ print_quoted_string s; printf ",@ "; print_list print_template l_t;
+ printf ",@ "; print_list print_template l_t0; printf ")@]"; printf ")@]";;
+
+(* Sorts of components *)
+let rec print_component_type = function
+ | Constructor -> printf "Constructor" | Command -> printf "Command"
+ | External -> printf "External";;
+
+(* Full definition of a component *)
+let rec print_fullcomponent = function
+ {component = c; ml_name = s; var_name = s0; template = t; result = m;
+ safe = b;
+ } ->
+ printf "@[<1>{"; printf "@[<1>component =@ "; print_component_type c;
+ printf ";@]@ "; printf "@[<1>ml_name =@ "; print_quoted_string s;
+ printf ";@]@ "; printf "@[<1>var_name =@ "; print_quoted_string s0;
+ printf ";@]@ "; printf "@[<1>template =@ "; print_template t;
+ printf ";@]@ "; printf "@[<1>result =@ "; print_mltype m; printf ";@]@ ";
+ printf "@[<1>safe =@ "; print_bool b; printf ";@]@ "; printf "@,}@]";;
+
+(* components are given either in full or abbreviated *)
+let rec print_component = function
+ | Full f -> printf "@[<1>(%s@ " "Full"; print_fullcomponent f; printf ")@]"
+ | Abbrev s ->
+ printf "@[<1>(%s@ " "Abbrev"; print_quoted_string s; printf ")@]";;
+
+(* A type definition *)
+(*
+ requires_widget_context: the converter of the type MUST be passed
+ an additional argument of type Widget.
+*)
+let rec print_parser_arity = function
+ | OneToken -> printf "OneToken" | MultipleToken -> printf "MultipleToken";;
+
+let rec print_type_def = function
+ {parser_arity = p; constructors = l_f; subtypes = l_t_s_l_f;
+ requires_widget_context = b; variant = b0;
+ } ->
+ printf "@[<1>{"; printf "@[<1>parser_arity =@ "; print_parser_arity p;
+ printf ";@]@ "; printf "@[<1>constructors =@ ";
+ print_list print_fullcomponent l_f; printf ";@]@ ";
+ printf "@[<1>subtypes =@ ";
+ print_list
+ (function (s, l_f0) ->
+ printf "@[<1>("; print_quoted_string s; printf ",@ ";
+ print_list print_fullcomponent l_f0; printf ")@]")
+ l_t_s_l_f;
+ printf ";@]@ "; printf "@[<1>requires_widget_context =@ "; print_bool b;
+ printf ";@]@ "; printf "@[<1>variant =@ "; print_bool b0; printf ";@]@ ";
+ printf "@,}@]";;
+
+let rec print_module_type = function
+ | Widget -> printf "Widget" | Family -> printf "Family";;
+
+let rec print_module_def = function
+ {module_type = m; commands = l_f; externals = l_f0; } ->
+ printf "@[<1>{"; printf "@[<1>module_type =@ "; print_module_type m;
+ printf ";@]@ "; printf "@[<1>commands =@ ";
+ print_list print_fullcomponent l_f; printf ";@]@ ";
+ printf "@[<1>externals =@ "; print_list print_fullcomponent l_f0;
+ printf ";@]@ "; printf "@,}@]";;
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/tables.ml b/ocaml-binary-annot/otherlibs/labltk/compiler/tables.ml
new file mode 100644
index 0000000000..0663dfaadd
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/tables.ml
@@ -0,0 +1,427 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file LICENSE found in the Objective Caml source tree. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open StdLabels
+open Support
+
+(* Internal compiler errors *)
+
+exception Compiler_Error of string
+let fatal_error s = raise (Compiler_Error s)
+
+
+(* Types of the description language *)
+type mltype =
+ Unit
+ | Int
+ | Float
+ | Bool
+ | Char
+ | String
+ | List of mltype
+ | Product of mltype list
+ | Record of (string * mltype) list
+ | UserDefined of string
+ | Subtype of string * string
+ | Function of mltype (* arg type only *)
+ | As of mltype * string
+
+type template =
+ StringArg of string
+ | TypeArg of string * mltype
+ | ListArg of template list
+ | OptionalArgs of string * template list * template list
+
+(* Sorts of components *)
+type component_type =
+ Constructor
+ | Command
+ | External
+
+(* Full definition of a component *)
+type fullcomponent = {
+ component : component_type;
+ ml_name : string; (* used for camltk *)
+ var_name : string; (* used just for labltk *)
+ template : template;
+ result : mltype;
+ safe : bool
+ }
+
+let sort_components =
+ List.sort ~cmp:(fun c1 c2 -> compare c1.ml_name c2.ml_name)
+
+
+(* components are given either in full or abbreviated *)
+type component =
+ Full of fullcomponent
+ | Abbrev of string
+
+(* A type definition *)
+(*
+ requires_widget_context: the converter of the type MUST be passed
+ an additional argument of type Widget.
+*)
+
+type parser_arity =
+ OneToken
+| MultipleToken
+
+type type_def = {
+ parser_arity : parser_arity;
+ mutable constructors : fullcomponent list;
+ mutable subtypes : (string * fullcomponent list) list;
+ mutable requires_widget_context : bool;
+ mutable variant : bool
+}
+
+type module_type =
+ Widget
+ | Family
+
+type module_def = {
+ module_type : module_type;
+ commands : fullcomponent list;
+ externals : fullcomponent list
+}
+
+(******************** The tables ********************)
+
+(* the table of all explicitly defined types *)
+let types_table = (Hashtbl.create 37 : (string, type_def) Hashtbl.t)
+(* "builtin" types *)
+let types_external = ref ([] : (string * parser_arity) list)
+(* dependancy order *)
+let types_order = (Tsort.create () : string Tsort.porder)
+(* Types of atomic values returned by Tk functions *)
+let types_returned = ref ([] : string list)
+(* Function table *)
+let function_table = ref ([] : fullcomponent list)
+(* Widget/Module table *)
+let module_table = (Hashtbl.create 37 : (string, module_def) Hashtbl.t)
+
+
+(* variant name *)
+let rec getvarname ml_name temp =
+ let offhypben s =
+ let s = String.copy s in
+ if (try String.sub s ~pos:0 ~len:1 with _ -> "") = "-" then
+ String.sub s ~pos:1 ~len:(String.length s - 1)
+ else s
+ and makecapital s =
+ begin
+ try
+ let cd = s.[0] in
+ if cd >= 'a' && cd <= 'z' then
+ s.[0] <- Char.chr (Char.code cd + (Char.code 'A' - Char.code 'a'))
+ with
+ _ -> ()
+ end;
+ s
+ in
+ let head = makecapital (offhypben begin
+ match temp with
+ StringArg s -> s
+ | TypeArg (s,t) -> s
+ | ListArg (h::_) -> getvarname ml_name h
+ | OptionalArgs (s,_,_) -> s
+ | ListArg [] -> ""
+ end)
+ in
+ let varname = if head = "" then ml_name
+ else if head.[0] >= 'A' && head.[0] <= 'Z' then head
+ else ml_name
+ in varname
+
+(***** Some utilities on the various tables *****)
+(* Enter a new empty type *)
+let new_type typname arity =
+ Tsort.add_element types_order typname;
+ let typdef = {parser_arity = arity;
+ constructors = [];
+ subtypes = [];
+ requires_widget_context = false;
+ variant = false} in
+ Hashtbl.add types_table typname typdef;
+ typdef
+
+
+(* Assume that types not yet defined are not subtyped *)
+(* Widget is builtin and implicitly subtyped *)
+let is_subtyped s =
+ s = "widget" ||
+ try
+ let typdef = Hashtbl.find types_table s in
+ typdef.subtypes <> []
+ with
+ Not_found -> false
+
+let requires_widget_context s =
+ try
+ (Hashtbl.find types_table s).requires_widget_context
+ with
+ Not_found -> false
+
+let declared_type_parser_arity s =
+ try
+ (Hashtbl.find types_table s).parser_arity
+ with
+ Not_found ->
+ try List.assoc s !types_external
+ with
+ Not_found ->
+ prerr_string "Type "; prerr_string s;
+ prerr_string " is undeclared external or undefined\n";
+ prerr_string ("Assuming cTKtoCAML"^s^" : string -> "^s^"\n");
+ OneToken
+
+let rec type_parser_arity = function
+ Unit -> OneToken
+ | Int -> OneToken
+ | Float -> OneToken
+ | Bool -> OneToken
+ | Char -> OneToken
+ | String -> OneToken
+ | List _ -> MultipleToken
+ | Product _ -> MultipleToken
+ | Record _ -> MultipleToken
+ | UserDefined s -> declared_type_parser_arity s
+ | Subtype (s,_) -> declared_type_parser_arity s
+ | Function _ -> OneToken
+ | As (ty, _) -> type_parser_arity ty
+
+let enter_external_type s v =
+ types_external := (s,v)::!types_external
+
+(*** Stuff for topological Sort.list of types ***)
+(* Make sure all types used in commands and functions are in *)
+(* the table *)
+let rec enter_argtype = function
+ Unit | Int | Float | Bool | Char | String -> ()
+ | List ty -> enter_argtype ty
+ | Product tyl -> List.iter ~f:enter_argtype tyl
+ | Record tyl -> List.iter tyl ~f:(fun (l,t) -> enter_argtype t)
+ | UserDefined s -> Tsort.add_element types_order s
+ | Subtype (s,_) -> Tsort.add_element types_order s
+ | Function ty -> enter_argtype ty
+ | As (ty, _) -> enter_argtype ty
+
+let rec enter_template_types = function
+ StringArg _ -> ()
+ | TypeArg (l,t) -> enter_argtype t
+ | ListArg l -> List.iter ~f:enter_template_types l
+ | OptionalArgs (_,tl,_) -> List.iter ~f:enter_template_types tl
+
+(* Find type dependancies on s *)
+let rec add_dependancies s =
+ function
+ List ty -> add_dependancies s ty
+ | Product tyl -> List.iter ~f:(add_dependancies s) tyl
+ | Subtype(s',_) -> if s <> s' then Tsort.add_relation types_order (s', s)
+ | UserDefined s' -> if s <> s' then Tsort.add_relation types_order (s', s)
+ | Function ty -> add_dependancies s ty
+ | As (ty, _) -> add_dependancies s ty
+ | _ -> ()
+
+let rec add_template_dependancies s = function
+ StringArg _ -> ()
+ | TypeArg (l,t) -> add_dependancies s t
+ | ListArg l -> List.iter ~f:(add_template_dependancies s) l
+ | OptionalArgs (_,tl,_) -> List.iter ~f:(add_template_dependancies s) tl
+
+(* Assumes functions are not nested in products, which is reasonable due to syntax*)
+let rec has_callback = function
+ StringArg _ -> false
+ | TypeArg (l,Function _ ) -> true
+ | TypeArg _ -> false
+ | ListArg l -> List.exists ~f:has_callback l
+ | OptionalArgs (_,tl,_) -> List.exists ~f:has_callback tl
+
+(*** Returned types ***)
+let really_add ty =
+ if List.mem ty !types_returned then ()
+ else types_returned := ty :: !types_returned
+
+let rec add_return_type = function
+ Unit -> ()
+ | Int -> ()
+ | Float -> ()
+ | Bool -> ()
+ | Char -> ()
+ | String -> ()
+ | List ty -> add_return_type ty
+ | Product tyl -> List.iter ~f:add_return_type tyl
+ | Record tyl -> List.iter tyl ~f:(fun (l,t) -> add_return_type t)
+ | UserDefined s -> really_add s
+ | Subtype (s,_) -> really_add s
+ | Function _ -> fatal_error "unexpected return type (function)" (* whoah *)
+ | As (ty, _) -> add_return_type ty
+
+(*** Update tables for a component ***)
+let enter_component_types {template = t; result = r} =
+ add_return_type r;
+ enter_argtype r;
+ enter_template_types t
+
+
+(******************** Types and subtypes ********************)
+exception Duplicate_Definition of string * string
+exception Invalid_implicit_constructor of string
+
+(* Checking duplicate definition of constructor in subtypes *)
+let rec check_duplicate_constr allowed c =
+ function
+ [] -> false (* not defined *)
+ | c'::rest ->
+ if c.ml_name = c'.ml_name then (* defined *)
+ if allowed then
+ if c.template = c'.template then true (* same arg *)
+ else raise (Duplicate_Definition ("constructor",c.ml_name))
+ else raise (Duplicate_Definition ("constructor", c.ml_name))
+ else check_duplicate_constr allowed c rest
+
+(* Retrieve constructor *)
+let rec find_constructor cname = function
+ [] -> raise (Invalid_implicit_constructor cname)
+ | c::l -> if c.ml_name = cname then c
+ else find_constructor cname l
+
+(* Enter a type, must not be previously defined *)
+let enter_type typname ?(variant = false) arity constructors =
+ if Hashtbl.mem types_table typname then
+ raise (Duplicate_Definition ("type", typname)) else
+ let typdef = new_type typname arity in
+ if variant then typdef.variant <- true;
+ List.iter constructors ~f:
+ begin fun c ->
+ if not (check_duplicate_constr false c typdef.constructors)
+ then begin
+ typdef.constructors <- c :: typdef.constructors;
+ add_template_dependancies typname c.template
+ end;
+ (* Callbacks require widget context *)
+ typdef.requires_widget_context <-
+ typdef.requires_widget_context ||
+ has_callback c.template
+ end
+
+(* Enter a subtype *)
+let enter_subtype typ arity subtyp constructors =
+ (* Retrieve the type if already defined, else add a new one *)
+ let typdef =
+ try Hashtbl.find types_table typ
+ with Not_found -> new_type typ arity
+ in
+ if List.mem_assoc subtyp typdef.subtypes
+ then raise (Duplicate_Definition ("subtype", typ ^" "^subtyp))
+ else begin
+ let real_constructors =
+ List.map constructors ~f:
+ begin function
+ Full c ->
+ if not (check_duplicate_constr true c typdef.constructors)
+ then begin
+ add_template_dependancies typ c.template;
+ typdef.constructors <- c :: typdef.constructors
+ end;
+ typdef.requires_widget_context <-
+ typdef.requires_widget_context ||
+ has_callback c.template;
+ c
+ | Abbrev name -> find_constructor name typdef.constructors
+ end
+ in
+ (* TODO: duplicate def in subtype are not checked *)
+ typdef.subtypes <-
+ (subtyp , List.sort real_constructors
+ ~cmp:(fun c1 c2 -> compare c1.var_name c2.var_name)) ::
+ typdef.subtypes
+ end
+
+(******************** Widgets ********************)
+(* used by the parser; when enter_widget is called,
+ all components are assumed to be in Full form *)
+let retrieve_option optname =
+ let optiontyp =
+ try Hashtbl.find types_table "options"
+ with
+ Not_found -> raise (Invalid_implicit_constructor optname)
+ in find_constructor optname optiontyp.constructors
+
+(* Sort components by type *)
+let rec add_sort l obj =
+ match l with
+ [] -> [obj.component ,[obj]]
+ | (s',l)::rest ->
+ if obj.component = s' then
+ (s',obj::l)::rest
+ else
+ (s',l)::(add_sort rest obj)
+
+let separate_components = List.fold_left ~f:add_sort ~init:[]
+
+let enter_widget name components =
+ if Hashtbl.mem module_table name then
+ raise (Duplicate_Definition ("widget/module", name)) else
+ let sorted_components = separate_components components in
+ List.iter sorted_components ~f:
+ begin function
+ Constructor, l ->
+ enter_subtype "options" MultipleToken
+ name (List.map ~f:(fun c -> Full c) l)
+ | Command, l ->
+ List.iter ~f:enter_component_types l
+ | External, _ -> ()
+ end;
+ let commands =
+ try List.assoc Command sorted_components
+ with Not_found -> []
+ and externals =
+ try List.assoc External sorted_components
+ with Not_found -> []
+ in
+ Hashtbl.add module_table name
+ {module_type = Widget; commands = commands; externals = externals}
+
+(******************** Functions ********************)
+
+let enter_function comp =
+ enter_component_types comp;
+ function_table := comp :: !function_table
+
+
+(******************** Modules ********************)
+let enter_module name components =
+ if Hashtbl.mem module_table name then
+ raise (Duplicate_Definition ("widget/module", name)) else
+ let sorted_components = separate_components components in
+ List.iter sorted_components ~f:
+ begin function
+ Constructor, l -> fatal_error "unexpected Constructor"
+ | Command, l -> List.iter ~f:enter_component_types l
+ | External, _ -> ()
+ end;
+ let commands =
+ try List.assoc Command sorted_components
+ with Not_found -> []
+ and externals =
+ try List.assoc External sorted_components
+ with Not_found -> []
+ in
+ Hashtbl.add module_table name
+ {module_type = Family; commands = commands; externals = externals}
diff --git a/ocaml-binary-annot/otherlibs/labltk/compiler/tsort.ml b/ocaml-binary-annot/otherlibs/labltk/compiler/tsort.ml
new file mode 100644
index 0000000000..6496eaae22
--- /dev/null
+++ b/ocaml-binary-annot/otherlibs/labltk/compiler/tsort.ml
@@ -0,0 +1,87 @@
+(***********************************************************************)
+(* *)
+(* MLTk, Tcl/Tk interface of Objective Caml *)
+(* *)
+(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
+(* projet Cristal, INRIA Rocquencourt *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique and Kyoto University. All rights reserved. *)
+(* This file is distributed under the terms of the GNU Library *)
+(* General Public License, with the special exception on linking *)
+(* described in file LICENSE found in the Objective Caml source tree. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open StdLabels
+
+(* Topological Sort.list *)
+(* d'apres More Programming Pearls *)
+
+(* node * pred count * successors *)
+
+type 'a entry =
+ {node : 'a;
+ mutable pred_count : int;
+ mutable successors : 'a entry list
+ }
+
+type 'a porder = 'a entry list ref
+
+exception Cyclic
+
+let find_entry order node =
+ let rec search_entry =
+ function
+ [] -> raise Not_found
+ | x::l -> if x.node = node then x else search_entry l
+ in
+ try
+ search_entry !order
+ with
+ Not_found -> let entry = {node = node;
+ pred_count = 0;
+ successors = []} in
+ order := entry::!order;
+ entry
+
+let create () = ref []
+
+(* Inverted args because Sort.list builds list in reverse order *)
+let add_relation order (succ,pred) =
+ let pred_entry = find_entry order pred
+ and succ_entry = find_entry order succ in
+ succ_entry.pred_count <- succ_entry.pred_count + 1;
+ pred_entry.successors <- succ_entry::pred_entry.successors
+
+(* Just add it *)
+let add_element order e =
+ ignore (find_entry order e)
+
+let sort order =
+ let q = Queue.create ()
+ and result = ref [] in
+ List.iter !order
+ ~f:(function {pred_count = n} as node ->
+ if n = 0 then Queue.add node q);
+ begin try
+ while true do
+ let t = Queue.take q in
+ result := t.node :: !result;
+ List.iter t.successors ~f:
+ begin fun s ->
+ let n = s.pred_count - 1 in
+ s.pred_count <- n;
+ if n = 0 then Queue.add s q
+ end
+ done
+ with
+ Queue.Empty ->
+ List.iter !order
+ ~f:(fun node -> if node.pred_count <> 0
+ then raise Cyclic)
+ end;
+ !result