Bläddra i källkod

[java] Initial Java lib support; Still doesn't handle fields

Caue Waneck 13 år sedan
förälder
incheckning
d093466117
5 ändrade filer med 178 tillägg och 3 borttagningar
  1. 4 2
      Makefile
  2. 2 0
      common.ml
  3. 9 0
      doc/install.ml
  4. 160 1
      genjava.ml
  5. 3 0
      main.ml

+ 4 - 2
Makefile

@@ -14,13 +14,13 @@ OUTPUT=haxe
 EXTENSION=
 OCAMLOPT=ocamlopt
 
-CFLAGS= -g -I libs/extlib -I libs/extc -I libs/neko -I libs/swflib -I libs/xml-light
+CFLAGS= -g -I libs/extlib -I libs/extc -I libs/neko -I libs/javalib -I libs/swflib -I libs/xml-light
 
 CC_CMD = $(OCAMLOPT) $(CFLAGS) -c $<
 CC_PARSER_CMD = $(OCAMLOPT) -pp camlp4o $(CFLAGS) -c parser.ml
 
 LIBS=unix.cmxa str.cmxa libs/extlib/extLib.cmxa libs/xml-light/xml-light.cmxa libs/swflib/swflib.cmxa \
-	libs/extc/extc.cmxa libs/neko/neko.cmxa
+	libs/extc/extc.cmxa libs/neko/neko.cmxa libs/javalib/java.cmxa
 
 NATIVE_LIBS=-cclib libs/extc/extc_stubs.o -cclib -lz
 
@@ -40,6 +40,7 @@ libs:
 	make -C libs/extlib opt
 	make -C libs/extc native
 	make -C libs/neko
+	make -C libs/javalib
 	make -C libs/swflib
 	make -C libs/xml-light xml-light.cmxa
 
@@ -118,6 +119,7 @@ clean_libs:
 	make -C libs/extlib clean
 	make -C libs/extc clean
 	make -C libs/neko clean
+	make -C libs/javalib clean
 	make -C libs/swflib clean
 	make -C libs/xml-light clean
 

+ 2 - 0
common.ml

@@ -123,6 +123,7 @@ type context = {
 	mutable php_lib : string option;
 	mutable php_prefix : string option;
 	mutable swf_libs : (string * (unit -> Swf.swf) * (unit -> ((string list * string),As3hl.hl_class) Hashtbl.t)) list;
+	mutable java_libs : (string * (unit -> unit)) list;
 	mutable js_gen : (unit -> unit) option;
 	(* typing *)
 	mutable basic : basic_types;
@@ -300,6 +301,7 @@ let create v args =
 		php_front = None;
 		php_lib = None;
 		swf_libs = [];
+		java_libs = [];
 		neko_libs = [];
 		php_prefix = None;
 		js_gen = None;

+ 9 - 0
doc/install.ml

@@ -107,6 +107,13 @@ let compile_libs() =
 	if native then command ("ocamlopt -a -o neko.cmxa " ^ files);
 	Sys.chdir "..";
 
+	(* JAVALIB *)
+	Sys.chdir "javalib";
+	let files = "-I .. jData.mli jReader.ml" in
+	if bytecode then command ("ocamlc -a -o java.cma " ^ files);
+	if native then command ("ocamlopt -a -o java.cmxa " ^ files);
+	Sys.chdir "..";
+
 	(* XML-LIGHT *)
 	Sys.chdir "xml-light";
 	command ("ocamlyacc	xml_parser.mly");
@@ -133,6 +140,7 @@ let compile() =
 		"libs/swflib/swflib";
 		"libs/xml-light/xml-light";
 		"libs/neko/neko";
+		"libs/javalib/java";
 		"unix";
 		"str"
 	] in
@@ -142,6 +150,7 @@ let compile() =
 		"libs/xml-light";
 		"libs/extc";
 		"libs/neko"
+		"libs/javalib"
 	] in
 	let mlist = [
 		"ast";"lexer";"type";"common";"parser";"typecore";

+ 160 - 1
genjava.ml

@@ -24,6 +24,7 @@ open Gencommon.SourceWriter
 open Type
 open Printf
 open Option
+open ExtString
 
 let is_boxed_type t = match follow t with
   | TInst ({ cl_path = (["java";"lang"], "Boolean") }, [])
@@ -1866,4 +1867,162 @@ let generate con =
   (try
     configure gen
   with | TypeNotFound path -> con.error ("Error. Module '" ^ (path_s path) ^ "' is required and was not included in build.")  Ast.null_pos);
-  debug_mode := false
+  debug_mode := false
+
+(** Java lib *)
+
+open JData
+
+let mk_type_path path params =
+  CTPath {
+    tpackage = fst path;
+    tname = snd (String.replace ~str:(snd path) ~sub:"$" ~by:"_"); (* handle with inner classes *)
+    tparams = params;
+    tsub = None;
+  }
+
+let rec convert_arg p arg =
+  match arg with
+  | TAny | TType (WSuper, _) -> TPType (mk_type_path ([], "Dynamic") [])
+  | TType (_, jsig) -> TPType (convert_signature p jsig)
+
+and convert_signature p jsig =
+  match jsig with
+  | TByte -> mk_type_path (["java"; "StdTypes"], "Int8") []
+  | TChar -> mk_type_path (["java"; "StdTypes"], "Char16") []
+  | TDouble -> mk_type_path ([], "Float") []
+  | TFloat -> mk_type_path ([], "Single") []
+  | TInt -> mk_type_path ([], "Int") []
+  | TLong -> mk_type_path (["haxe"], "Int64") []
+  | TShort -> mk_type_path (["java"; "StdTypes"], "Int16") []
+  | TBool -> mk_type_path ([], "Bool") []
+  | TObject ( (["haxe";"root"], name), args ) -> mk_type_path ([], name) (List.map (convert_arg p) args)
+  (** nullable types *)
+  | TObject ( (["java";"lang"], "Integer"), [] ) -> mk_type_path ([], "Null") [ TPType (mk_type_path ([], "Int") []) ]
+  | TObject ( (["java";"lang"], "Double"), [] ) -> mk_type_path ([], "Null") [ TPType (mk_type_path ([], "Float") []) ]
+  | TObject ( (["java";"lang"], "Single"), [] ) -> mk_type_path ([], "Null") [ TPType (mk_type_path ([], "Single") []) ]
+  | TObject ( (["java";"lang"], "Boolean"), [] ) -> mk_type_path ([], "Null") [ TPType (mk_type_path ([], "Bool") []) ]
+  | TObject ( (["java";"lang"], "Byte"), [] ) -> mk_type_path ([], "Null") [ TPType (mk_type_path (["java";"StdTypes"], "Int8") []) ]
+  | TObject ( (["java";"lang"], "Character"), [] ) -> mk_type_path ([], "Null") [ TPType (mk_type_path (["java";"StdTypes"], "Char16") []) ]
+  | TObject ( (["java";"lang"], "Short"), [] ) -> mk_type_path ([], "Null") [ TPType (mk_type_path (["java";"StdTypes"], "Int16") []) ]
+  | TObject ( (["java";"lang"], "Long"), [] ) -> mk_type_path ([], "Null") [ TPType (mk_type_path (["haxe"], "Int64") []) ]
+  (** other std types *)
+  | TObject ( (["java";"lang"], "Object"), [] ) -> mk_type_path ([], "Dynamic") []
+  | TObject ( (["java";"lang"], "String"), [] ) -> mk_type_path ([], "String") []
+  | TObject ( (["java";"lang"], "Class"), args ) -> mk_type_path ([], "Class") (List.map (convert_arg p) args)
+  (** other types *)
+  | TObject ( path, args ) -> mk_type_path path (List.map (convert_arg p) args)
+  | TArray (jsig, _) -> mk_type_path (["java"], "NativeArray") [ TPType (convert_signature p jsig) ]
+  | TMethod _ -> JReader.error "TMethod cannot be converted directly into Complex Type"
+  | TTypeParameter s -> mk_type_path ([], s) []
+
+let convert_param p param =
+  let name, constraints = match param with
+    | (name, Some extends_sig, implem_sig) ->
+      name, extends_sig :: implem_sig
+    | (name, None, implemem_sig) ->
+      name, implemem_sig
+    in
+    {
+      tp_name = name;
+      tp_params = [];
+      tp_constraints = List.map (convert_signature p) constraints;
+    }
+
+
+let get_type_path ct = match ct with | CTPath p -> p | _ -> assert false
+
+let convert_java_enum p pe =
+  let meta = ref [":$javaNative", [], p] in
+  let data = ref [] in
+  List.iter (fun f ->
+    if List.mem JEnum f.jf_flags then
+      data := (f.jf_name, None, [], [], p) :: !data
+  ) pe.cfields;
+
+  EEnum {
+    d_name = snd pe.cpath;
+    d_doc = None;
+    d_params = []; (* enums never have type parameters *)
+    d_meta = !meta;
+    d_flags = [EExtern];
+    d_data = !data;
+  }
+
+let convert_java_class p jc =
+  match List.mem JEnum jc.cflags with
+  | true -> (* is enum *)
+    convert_java_enum p jc
+  | false ->
+    let flags = ref [HExtern] in
+    let meta = ref [":$javaNative", [], p] in
+
+    List.iter (fun f -> match f with
+      | JFinal -> meta := (":final", [], p) :: !meta
+      | JInterface -> flags := HInterface :: !flags
+      | JAbstract -> meta := (":abstract", [], p) :: !meta
+      | JAnnotation -> meta := (":annotation", [], p) :: !meta
+      | _ -> ()
+    ) jc.cflags;
+    
+    (match jc.csuper with
+      | TObject( (["java";"lang"], "Object"), _ ) -> ()
+      | _ -> flags := HExtends (get_type_path (convert_signature p jc.csuper)) :: !flags
+    );
+
+    List.iter (fun i ->
+      flags := HImplements (get_type_path (convert_signature p i)) :: !flags
+    ) jc.cinterfaces;
+
+    EClass {
+      d_name = snd jc.cpath;
+      d_doc = None;
+      d_params = List.map (convert_param p) jc.ctypes;
+      d_meta = !meta;
+      d_flags = !flags;
+      d_data = [];
+    }
+
+
+let add_java_lib com file =
+  let get_raw_class, close = 
+    let file = if Sys.file_exists file then
+      file
+    else if Sys.file_exists (file ^ ".jar") then
+      file ^ ".jar"
+    else
+      failwith "JAR lib " ^ file ^ " not found"
+    in
+
+    (* check if it is a directory or jar file *)
+    match Sys.is_directory file with
+    | true -> (* open classes directly from directory *)
+      (fun (pack, name) ->
+        let real_path = file ^ "/" ^ (String.concat "." pack) ^ "/" ^ name ^ ".class" in
+        try
+          let data = Std.input_file ~bin:true real_path in
+          Some (IO.input_string data), real_path, real_path
+        with 
+          | _ -> None, real_path, real_path), (fun () -> ())
+    | false -> (* open zip file *)
+      (fun (pack, name) -> None, file, file ^ "@" ^ (String.concat "." pack) ^ "/" ^ name ^ ".class" (* TODO *)), (fun () -> ())
+  in
+  let rec build path p =
+    match get_raw_class path, path with
+    | (None, _, _), ([], c) -> build (["haxe";"root"], c) p
+    | (None, _, _), _ -> None
+    | (Some i, real_path, pos_path), _ ->
+      (*try*)
+        let pos = { pfile = pos_path; pmin = 0; pmax = 0; } in
+        let cls = JReader.parse_class i in
+        let pack = match fst path with | ["haxe";"root"] -> [] | p -> p in
+        Some ( real_path, (pack, [convert_java_class pos cls, pos]) )
+      (*with JReader.Error_message msg ->
+        if com.verbose then prerr_endline ("Class reader failed: " ^ msg);
+        None
+        | _ -> None*)
+  in
+
+  (* TODO: add_dependency m mdep *)
+  com.load_extern_type <- com.load_extern_type @ [build];
+  com.java_libs <- (file, close) :: com.java_libs

+ 3 - 0
main.ml

@@ -803,6 +803,9 @@ try
 		("-swf-lib",Arg.String (fun file ->
 			Genswf.add_swf_lib com file
 		),"<file> : add the SWF library to the compiled SWF");
+		("-java-lib",Arg.String (fun file ->
+			Genjava.add_java_lib com file
+		),"<file> : add an external JAR or class directory library");
 		("-x", Arg.String (fun file ->
 			let neko_file = file ^ ".n" in
 			set_platform Neko neko_file;