Bläddra i källkod

Merge pull request #2942 from nadako/genpy_import

Support @:import meta-data for extern python modules.
Dan Korostelev 11 år sedan
förälder
incheckning
ad2998e57d
7 ändrade filer med 70 tillägg och 1 borttagningar
  1. 1 0
      .gitignore
  2. 1 0
      ast.ml
  3. 1 0
      common.ml
  4. 32 1
      genpy.ml
  5. 24 0
      tests/unit/TestPython.hx
  6. 0 0
      tests/unit/native_python/__init__.py
  7. 11 0
      tests/unit/native_python/sample.py

+ 1 - 0
.gitignore

@@ -57,6 +57,7 @@ build.bat
 tests/unit/compile.php.hxml
 /extra/*.xml
 tests/optimization/testopt.js
+tests/unit/native_python/__pycache__
 tests/unit/unit.py
 tests/unit/unit.py.res1.txt
 tests/unit/unit.py.res2.bin

+ 1 - 0
ast.ml

@@ -83,6 +83,7 @@ module Meta = struct
 		| HxGen
 		| IfFeature
 		| Impl
+		| Import
 		| Include
 		| InitPackage
 		| Internal

+ 1 - 0
common.ml

@@ -385,6 +385,7 @@ module MetaInfo = struct
 		| HxGen -> ":hxGen",("Annotates that an extern class was generated by Haxe",[Platforms [Java;Cs]; UsedOnEither [TClass;TEnum]])
 		| IfFeature -> ":ifFeature",("Causes a field to be kept by DCE if the given feature is part of the compilation",[HasParam "Feature name";UsedOn TClassField])
 		| Impl -> ":impl",("Used internally to mark abstract implementation fields",[UsedOn TAbstractField; Internal])
+		| Import -> ":import",("Generates python import statement for extern classes",[Platforms [Python]; UsedOn TClass])
 		| Include -> ":include",("",[Platform Cpp])
 		| InitPackage -> ":initPackage",("?",[])
 		| Meta.Internal -> ":internal",("Generates the annotated field/class with 'internal' access",[Platforms [Java;Cs]; UsedOnEither[TClass;TEnum;TClassField]])

+ 32 - 1
genpy.ml

@@ -1710,7 +1710,38 @@ module Generator = struct
 	let gen_class ctx c =
 		gen_pre_code_meta ctx c.cl_meta;
 		(* print ctx "# print %s.%s\n" (s_type_path c.cl_module.m_path) (snd c.cl_path); *)
-		if not c.cl_extern then begin
+		if c.cl_extern then begin
+			if Meta.has Meta.Import c.cl_meta then begin
+				let _, args, mp = Meta.get Meta.Import c.cl_meta in
+
+				let class_name = match c.cl_path with
+					| [],name -> name
+					| path,name -> (ExtString.String.join "_" path) ^ "_" ^ name
+				in
+
+				let import = match args with 
+					| [(EConst(String(module_name)), _)] ->
+						(* importing whole module *)
+						"import " ^ module_name ^ " as " ^ class_name
+
+					| [(EConst(String(module_name)), _); (EConst(String(object_name)), _)] ->
+						if String.contains object_name '.' then
+							(* importing nested class *)
+							"import " ^ module_name ^ " as _hx_temp_import; " ^ class_name ^ " = _hx_temp_import." ^ object_name ^ "; del _hx_temp_import"
+						else
+							(* importing a class from a module *)
+							"from " ^ module_name ^ " import " ^ object_name ^ " as " ^ class_name
+					| _ ->
+						error "Unsupported @:import format" mp
+				in
+
+				let f = fun () ->
+					spr_line ctx import;
+					spr_line ctx ("_hx_c." ^ class_name ^ " = " ^ class_name)
+				in
+				ctx.class_inits <- f :: ctx.class_inits
+			end
+		end else begin
 			let mt = (t_infos (TClassDecl c)) in
 			let p = get_path mt in
 			let p_name = get_full_name mt in

+ 24 - 0
tests/unit/TestPython.hx

@@ -84,6 +84,23 @@ private class B extends A {
     public function new() {}
 }
 
+@:import("native_python.sample", "A")
+extern class ExternClass {
+	function new();
+	function f(v:Int):Int;
+}
+
+@:import("native_python.sample", "A.Nested")
+extern class ExternNestedClass {
+	function new();
+	function f(v:Int):Int;
+}
+
+@:import("native_python.sample")
+extern class ExternModule {
+	static function f(v:Int):Int;
+}
+
 class TestPython extends Test {
 
 	public function testDoWhileAsExpression () {
@@ -303,4 +320,11 @@ class TestPython extends Test {
 		eq(test4a(1), test4b(1));
 	}
 
+	function testExtern()
+	{
+		eq(new ExternClass().f(1), 2);
+		eq(new ExternNestedClass().f(1), 3);
+		eq(ExternModule.f(1), 4);
+	}
+
 }

+ 0 - 0
tests/unit/native_python/__init__.py


+ 11 - 0
tests/unit/native_python/sample.py

@@ -0,0 +1,11 @@
+class A:
+
+    def f(self, v):
+        return v + 1
+
+    class Nested:
+        def f(self, v):
+            return v + 2
+
+def f(v):
+    return v + 3