Browse Source

[lua] fix issues with typedef/instance/static assignment fixes #6007

Justin Donaldson 8 years ago
parent
commit
75ffa81ee5
3 changed files with 60 additions and 20 deletions
  1. 37 18
      src/generators/genlua.ml
  2. 2 2
      std/lua/_std/Reflect.hx
  3. 21 0
      tests/unit/src/unit/issues/Issue6007.hx

+ 37 - 18
src/generators/genlua.ml

@@ -462,22 +462,13 @@ let rec gen_call ctx e el in_value =
 	| TField (e, ((FInstance _ | FAnon _ | FDynamic _) as ef)), el ->
 		let s = (field_name ef) in
 		if Hashtbl.mem kwds s || not (valid_lua_ident s) then begin
-		    match e.eexpr with
-		    |TNew _-> (
-			add_feature ctx "use._hx_apply_self";
-			spr ctx "_hx_apply_self(";
-			gen_value ctx e;
-			print ctx ",\"%s\"" (field_name ef);
-			if List.length(el) > 0 then spr ctx ",";
-			concat ctx "," (gen_value ctx) el;
-			spr ctx ")";
-		    );
-		    |_ -> (
-			gen_value ctx e;
-			print ctx "%s(" (anon_field s);
-			concat ctx "," (gen_value ctx) (e::el);
-			spr ctx ")"
-		    )
+		    add_feature ctx "use._hx_apply_self";
+		    spr ctx "_hx_apply_self(";
+		    gen_value ctx e;
+		    print ctx ",\"%s\"" (field_name ef);
+		    if List.length(el) > 0 then spr ctx ",";
+		    concat ctx "," (gen_value ctx) el;
+		    spr ctx ")";
 		end else begin
 		    gen_value ctx e;
 		    print ctx ":%s(" (field_name ef);
@@ -840,7 +831,7 @@ and gen_expr ?(local=true) ctx e = begin
 		spr ctx "_hx_o({__fields__={";
 		concat ctx "," (fun (f,e) -> print ctx "%s=" (anon_field f); spr ctx "true") fields;
 		spr ctx "},";
-		concat ctx "," (fun (f,e) -> print ctx "%s=" (anon_field f); gen_value ctx e) fields;
+		concat ctx "," (fun (f,e) -> print ctx "%s=" (anon_field f); gen_anon_value ctx e) fields;
 		spr ctx "})";
 		ctx.separator <- true
 	| TFor (v,it,e) ->
@@ -1024,6 +1015,35 @@ and gen_block_element ctx e  =
 		semicolon ctx;
 	end;
 
+(* values generated in anon structures can get modified.  Functions are bind-ed *)
+(* and include a dummy "self" leading variable so they can be called like normal *)
+(* instance methods *)
+and gen_anon_value ctx e =
+    match e with
+    | { eexpr = TFunction f} ->
+	let old = ctx.in_value, ctx.in_loop in
+	ctx.in_value <- None;
+	ctx.in_loop <- false;
+	print ctx "function(%s) " (String.concat "," ("self" :: (List.map ident (List.map arg_name f.tf_args))));
+	let fblock = fun_block ctx f e.epos in
+	(match fblock.eexpr with
+	| TBlock el ->
+		let bend = open_block ctx in
+		List.iter (gen_block_element ctx) el;
+	    bend();
+	    newline ctx;
+	|_ -> ());
+	spr ctx "end";
+	ctx.in_value <- fst old;
+	ctx.in_loop <- snd old;
+	ctx.separator <- true
+    | { etype = TFun (args, ret)}  ->
+	spr ctx "function(_,...) return ";
+	gen_value ctx e;
+	spr ctx "(...) end";
+    | _->
+	gen_value ctx e
+
 and gen_value ctx e =
 	let assign e =
 		mk (TBinop (Ast.OpAssign,
@@ -2092,7 +2112,6 @@ let generate com =
 	    println ctx "end;";
 	end;
 
-
 	List.iter (generate_enumMeta_fields ctx) com.types;
 
 	(match com.main with

+ 2 - 2
std/lua/_std/Reflect.hx

@@ -61,12 +61,12 @@ import lua.Boot;
 		}
 	}
 
-	public inline static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array<Dynamic> ) : Dynamic  {
+	public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array<Dynamic> ) : Dynamic  {
 		if (args == null || args.length == 0){
 			return func(o);
 		} else {
 			var self_arg = false;
-			if (o != null && Type.getClass(o) != null){
+			if (o != null ){
 				// if o is not null, it means we need to pass it as the "self"
 				// parameter.  However, we should also check to see if it's
 				// a valid class instance in the first place.

+ 21 - 0
tests/unit/src/unit/issues/Issue6007.hx

@@ -0,0 +1,21 @@
+package unit.issues;
+
+class Issue6007 extends Test {
+	function test() {
+		// test anonymous type with borrowed iterator
+        var h = new haxe.ds.IntMap<Null<Int>>();
+        h.set(0, -1);
+        h.set(-4815, 8546);
+        var k = Lambda.array({iterator : h.keys});
+        eq("[0,-4815]", Std.string(k));
+
+		// make sure instance body isn't executed twice
+		var k = [];
+		var f = function(){
+			k.push(1);
+			return {  then : function() k.push(2) }
+		}
+		f().then();
+		eq("[1,2]", Std.string(k));
+	}
+}