Browse Source

fixed scope bug in try/catch.

Nicolas Cannasse 19 years ago
parent
commit
754c96168b
1 changed files with 38 additions and 11 deletions
  1. 38 11
      genswf9.ml

+ 38 - 11
genswf9.ml

@@ -55,6 +55,13 @@ type code_infos = {
 	mutable iloop : int;
 }
 
+type try_infos = {
+	tr_pos : int;
+	tr_end : int;
+	tr_catch_pos : int;
+	tr_type : t;
+}
+
 type context = {
 	(* globals *)
 	strings : string lookup;
@@ -76,12 +83,13 @@ type context = {
 	mutable locals : (string,local) PMap.t;
 	mutable code : as3_opcode DynArray.t;
 	mutable infos : code_infos;
-	mutable trys : (int * int * int * t) list;
+	mutable trys : try_infos list;
 	mutable breaks : (unit -> unit) list;
 	mutable continues : (int -> unit) list;
 	mutable in_static : bool;
 	mutable curblock : texpr list;
 	mutable block_vars : (int * string) list;
+	mutable try_scope_reg : int option;
 }
 
 let error p = Typer.error "Invalid expression" p
@@ -367,6 +375,7 @@ let begin_fun ctx ?(varargs=false) args el stat =
 	let old_bvars = ctx.block_vars in
 	let old_static = ctx.in_static in
 	let last_line = ctx.last_line in
+	let old_treg = ctx.try_scope_reg in
 	ctx.infos <- default_infos();
 	ctx.code <- DynArray.create();
 	ctx.trys <- [];
@@ -394,6 +403,13 @@ let begin_fun ctx ?(varargs=false) args el stat =
 			write ctx (A3Reg (alloc_reg ctx));
 			setvar ctx acc false
 	) args;
+	let rec loop_try e =
+		match e.eexpr with
+		| TFunction _ -> ()
+		| TTry _ -> raise Exit
+		| _ -> Type.iter loop_try e 
+	in
+	ctx.try_scope_reg <- (try List.iter loop_try el; None with Exit -> Some (alloc_reg ctx));
 	(fun () ->
 		let hasblock = ctx.block_vars <> [] || ctx.trys <> [] in
 		let dparams = ref None in
@@ -415,9 +431,13 @@ let begin_fun ctx ?(varargs=false) args el stat =
 		} in
 		let code = DynArray.to_list ctx.code in
 		let code , delta = (
-			if hasblock then
-				A3This :: A3Scope :: A3NewBlock :: A3Scope :: code , 4
-			else if not stat then
+			if hasblock then begin
+				let scope, delta = (match ctx.try_scope_reg with
+					| None -> A3Scope :: code , 4
+					| Some r -> A3Dup :: A3SetReg r :: A3Scope :: code, 5 + As3code.length (A3SetReg r)
+				) in
+				A3This :: A3Scope :: A3NewBlock :: scope, delta
+			end else if not stat then
 				A3This :: A3Scope :: code , 2
 			else
 				code , 0
@@ -429,12 +449,12 @@ let begin_fun ctx ?(varargs=false) args el stat =
 			fun3_unk3 = 1;
 			fun3_max_scope = ctx.infos.imaxscopes + 1 + (if hasblock then 2 else if not stat then 1 else 0);
 			fun3_code = code;
-			fun3_trys = Array.of_list (List.map (fun (p,size,cp,t) ->
+			fun3_trys = Array.of_list (List.map (fun t ->
 				{
-					tc3_start = p + delta;
-					tc3_end = size + delta;
-					tc3_handle = cp + delta;
-					tc3_type = (match follow t with
+					tc3_start = t.tr_pos + delta;
+					tc3_end = t.tr_end + delta;
+					tc3_handle = t.tr_catch_pos + delta;
+					tc3_type = (match follow t.tr_type with
 						| TInst (c,_) -> Some (fake_type_path ctx c.cl_path)
 						| TEnum (e,_) -> Some (fake_type_path ctx e.e_path)
 						| TDynamic _ -> None
@@ -459,6 +479,7 @@ let begin_fun ctx ?(varargs=false) args el stat =
 		ctx.block_vars <- old_bvars;
 		ctx.in_static <- old_static;
 		ctx.last_line <- last_line;
+		ctx.try_scope_reg <- old_treg;
 		f.fun3_id
 	)
 
@@ -661,12 +682,17 @@ let rec gen_expr_content ctx retval e =
 			| [] -> []
 			| (ename,t,e) :: l ->
 				let b = open_block ctx [e] retval in
-				ctx.trys <- (p,pend,ctx.infos.ipos,t) :: ctx.trys;
+				ctx.trys <- {
+					tr_pos = p;
+					tr_end = pend;
+					tr_catch_pos = ctx.infos.ipos;
+					tr_type = t;
+				} :: ctx.trys;
 				ctx.infos.istack <- ctx.infos.istack + 1;
 				if ctx.infos.imax < ctx.infos.istack then ctx.infos.imax <- ctx.infos.istack;
 				write ctx A3This;
 				write ctx A3Scope;
-				write ctx A3NewBlock;
+				write ctx (A3Reg (match ctx.try_scope_reg with None -> assert false | Some r -> r));
 				write ctx A3Scope;
 				(match follow t with TDynamic _ -> () | _ -> write ctx A3ToObject);
 				define_local ctx ename [e];
@@ -1401,6 +1427,7 @@ let generate types hres =
 		in_static = false;
 		debug = Plugin.defined "debug";
 		last_line = -1;
+		try_scope_reg = None;
 	} in
 	List.iter (generate_type ctx) types;
 	Hashtbl.iter (fun _ _ -> assert false) hres;