瀏覽代碼

transforms.

Nicolas Cannasse 19 年之前
父節點
當前提交
8d7d7516de
共有 6 個文件被更改,包括 241 次插入114 次删除
  1. 1 0
      doc/CHANGES.txt
  2. 1 1
      doc/install.ml
  3. 12 6
      genjs.ml
  4. 28 107
      genswf8.ml
  5. 3 0
      haxe.vcproj
  6. 196 0
      transform.ml

+ 1 - 0
doc/CHANGES.txt

@@ -8,6 +8,7 @@
 	fixed bug in inheritend constructor type parameters
 	fixed bug in type_field with inherited type parameters
 	added haxe.Proxy
+	added code transformations for swf/js block variables
 	
 2006-06-08: 1.02
 	fixed stack overflow when recursive class <: recursive signature

+ 1 - 1
doc/install.ml

@@ -118,7 +118,7 @@ let compile() =
 	ocamlc "-I ../ocaml -I ../ocaml/swflib type.ml plugin.ml typer.ml genswf.ml genxml.ml genjs.ml";
 	ocamlc "-I ../ocaml -I ../neko/libs/include/ocaml ../neko/libs/include/ocaml/nast.ml ../neko/libs/include/ocaml/nxml.ml genneko.ml";
 	ocamlc "-I ../ocaml -I ../ocaml/extc main.ml";
-	let mlist = ["plugin";"ast";"lexer";"parser";"type";"typer";"genswf";"../neko/libs/include/ocaml/nast";"../neko/libs/include/ocaml/nxml";"genneko";"genxml";"genjs";"main"] in
+	let mlist = ["plugin";"ast";"lexer";"parser";"type";"typer";"transform";"genswf";"../neko/libs/include/ocaml/nast";"../neko/libs/include/ocaml/nxml";"genneko";"genxml";"genjs";"main"] in
 	if bytecode then command ("ocamlc -custom -o ../bin/haxe-byte" ^ exe_ext ^ " ../ocaml/extLib.cma ../ocaml/extc/extc.cma ../ocaml/swflib/swflib.cma " ^ modules mlist ".cmo");
 	if native then command ("ocamlopt -o ../bin/haxe" ^ exe_ext ^ " ../ocaml/extLib.cmxa ../ocaml/extc/extc.cmxa ../ocaml/swflib/swflib.cmxa " ^ modules mlist ".cmx");
 

+ 12 - 6
genjs.ml

@@ -145,6 +145,13 @@ let rec gen_call ctx e el =
 		spr ctx "(";
 		concat ctx "," (gen_value ctx) el;
 		spr ctx ")"
+	| TCall _ , el ->
+		spr ctx "(";
+		gen_value ctx e;
+		spr ctx ")";
+		spr ctx "(";
+		concat ctx "," (gen_value ctx) el;
+		spr ctx ")";
 	| TLocal "__new__" , { eexpr = TConst (TString cl) } :: params ->
 		print ctx "new %s(" cl;
 		concat ctx "," (gen_value ctx) params;
@@ -304,9 +311,7 @@ and gen_expr ctx e =
 		handle_break();
 	| TTry (e,catchs) ->
 		spr ctx "try ";
-		(match e.eexpr with
-		| TBlock _ -> gen_expr ctx e
-		| _ -> gen_expr ctx (mk (TBlock [e]) e.etype e.epos));
+		gen_expr ctx (block e);
 		newline ctx;
 		let id = ctx.id_counter in
 		ctx.id_counter <- ctx.id_counter + 1;
@@ -545,6 +550,7 @@ let gen_class_static_field ctx c f =
 		print ctx "%s%s = null" (s_path c.cl_path) (field f.cf_name);
 		newline ctx
 	| Some e ->
+		let e = Transform.block_vars e in
 		match e.eexpr with
 		| TFunction _ ->
 			print ctx "%s%s = " (s_path c.cl_path) (field f.cf_name);
@@ -560,7 +566,7 @@ let gen_class_field ctx c f =
 		print ctx "null";
 		newline ctx
 	| Some e ->
-		gen_value ctx e;
+		gen_value ctx (Transform.block_vars e);
 		newline ctx
 
 let generate_class ctx c =
@@ -570,7 +576,7 @@ let generate_class ctx c =
 	print ctx "%s = " p;
 	(match c.cl_constructor with
 	| Some { cf_expr = Some e } ->
-		gen_value ctx e;
+		gen_value ctx (Transform.block_vars e);
 		newline ctx;
 		print ctx "%s.__construct__ = %s" p p;
 	| _ ->
@@ -629,7 +635,7 @@ let generate_type ctx = function
 	| TClassDecl c ->
 		(match c.cl_init with
 		| None -> ()
-		| Some e -> ctx.inits <- e :: ctx.inits);
+		| Some e -> ctx.inits <- Transform.block_vars e :: ctx.inits);
 		if not c.cl_extern then generate_class ctx c
 	| TEnumDecl { e_path = ([],"Bool") } ->
 		()

+ 28 - 107
genswf8.ml

@@ -21,7 +21,7 @@ open Ast
 open Type
 
 type register =
-	| NoReg of bool
+	| NoReg
 	| Reg of int
 
 type context = {
@@ -410,61 +410,10 @@ let free_reg ctx r p =
 (* -------------------------------------------------------------- *)
 (* Generation Helpers *)
 
-let cfind flag cst e =
-	let vname = (match cst with TConst TSuper -> "super" | TLocal v -> v | _ -> assert false) in
-	let rec loop2 e =
-		match e.eexpr with
-		| TFunction f ->
-			if not flag && not (List.exists (fun (a,_,_) -> a = vname) f.tf_args) then loop2 f.tf_expr
-		| TBlock _ ->
-			(try
-				iter loop2 e;
-			with
-				Not_found -> ())
-		| TVars vl ->
-			List.iter (fun (v,t,e) ->
-				(match e with
-				| None -> ()
-				| Some e -> loop2 e);
-				if v = vname then raise Not_found;
-			) vl
-		| TConst TSuper ->
-			if vname = "super" then raise Exit
-		| TLocal v ->
-			if v = vname then raise Exit
-		| _ ->
-			iter loop2 e
-	in
-	let rec loop e =
-		match e.eexpr with
-		| TFunction f ->
-			if not (List.exists (fun (a,_,_) -> a = vname) f.tf_args) then loop2 f.tf_expr
-		| TBlock _ ->
-			(try
-				iter loop e;
-			with
-				Not_found -> ())
-		| TVars vl ->
-			List.iter (fun (v,t,e) ->
-				(match e with
-				| None -> ()
-				| Some e -> loop e);
-				if v = vname then raise Not_found;
-			) vl
-		| _ ->
-			iter loop e
-	in
-	try
-		(if flag then loop2 else loop) e;
-		false
-	with
-		Exit ->
-			true
-
 let define_var ctx v ef exprs =
-	if ctx.version = 6 || List.exists (cfind false (TLocal v)) exprs then begin
+	if ctx.version = 6 || List.exists (Transform.local_find false v) exprs then begin
 		push ctx [VStr (v,false)];
-		ctx.regs <- PMap.add v (NoReg ctx.in_loop) ctx.regs;
+		ctx.regs <- PMap.add v NoReg ctx.regs;
 		match ef with
 		| None ->
 			write ctx ALocalVar
@@ -533,8 +482,8 @@ let rec gen_constant ctx c p =
 	| TSuper -> assert false
 
 let access_local ctx s =
-	match (try PMap.find s ctx.regs , false with Not_found -> NoReg false , true) with
-	| NoReg _ , flag ->
+	match (try PMap.find s ctx.regs , false with Not_found -> NoReg, true) with
+	| NoReg , flag ->
 		push ctx [VStr (s,flag)];
 		VarStr
 	| Reg r , _ ->
@@ -614,35 +563,24 @@ and gen_try_catch ctx retval e catchs =
 		let next_catch = (match t with
 		| None ->
 			end_throw := false;
-			(* @exc.pop() *)
-			push ctx [VInt 0;VStr ("@exc",false)];
-			write ctx AEval;
-			push ctx [VStr ("pop",true)];
-			call ctx VarObj 0;
-			write ctx APop;
-			let block = open_block ctx in
-			define_var ctx name (Some (fun() -> push ctx [VReg 0])) [e];
-			gen_expr ctx retval e;
-			block();
 			(fun() -> ())
 		| Some t ->
 			getvar ctx (gen_access ctx false (mk (TType t) (mk_mono()) e.epos));
 			push ctx [VReg 0; VInt 2; VStr ("@instanceof",false)];
 			call ctx VarStr 2;
 			write ctx ANot;
-			let c = cjmp ctx in
-			(* @exc.pop() *)
-			push ctx [VInt 0;VStr ("@exc",false)];
-			write ctx AEval;
-			push ctx [VStr ("pop",true)];
-			call ctx VarObj 0;
-			write ctx APop;
-			let block = open_block ctx in
-			define_var ctx name (Some (fun() -> push ctx [VReg 0])) [e];
-			gen_expr ctx retval e;
-			block();
-			c
+			cjmp ctx
 		) in
+		(* @exc.pop() *)
+		push ctx [VInt 0;VStr ("@exc",false)];
+		write ctx AEval;
+		push ctx [VStr ("pop",true)];
+		call ctx VarObj 0;
+		write ctx APop;
+		let block = open_block ctx in
+		define_var ctx name (Some (fun() -> push ctx [VReg 0])) [e];
+		gen_expr ctx retval e;
+		block();
 		if retval then ctx.stack_size <- ctx.stack_size - 1;
 		let j = jmp ctx in
 		next_catch();
@@ -944,41 +882,22 @@ and gen_expr_2 ctx retval e =
 		write ctx AObject;
 		ctx.stack_size <- ctx.stack_size - (nfields * 2);
 	| TFunction f ->
-		let loop_params = PMap.foldi (fun v x acc ->
-			match x with
-			| NoReg loop ->
-				if loop && cfind true (TLocal v) f.tf_expr then
-					v :: acc
-				else
-					acc
-			| _ -> acc
-		) ctx.regs [] in
-		(match loop_params with
-		| _ :: _ ->
-			gen_expr ctx retval (mk (TCall (
-				(mk (TFunction {
-					tf_args = List.map (fun v -> v , false, t_dynamic) loop_params;
-					tf_type = t_dynamic;
-					tf_expr = mk (TReturn (Some e)) t_dynamic e.epos;
-				}) t_dynamic e.epos),
-				List.map (fun v -> mk (TLocal v) t_dynamic e.epos) loop_params)
-			) t_dynamic e.epos)
-		| _ ->
 		let block = open_block ctx in
-		let reg_super = cfind true (TConst TSuper) f.tf_expr in
+		let old_in_loop = ctx.in_loop in
+		let reg_super = Transform.local_find true "super" f.tf_expr in
 		(* only keep None bindings, for protect *)
 		ctx.regs <- PMap.foldi (fun v x acc ->
 			match x with
-			| NoReg _ -> PMap.add v x acc
+			| NoReg -> PMap.add v x acc
 			| Reg _ -> acc
 		) ctx.regs PMap.empty;
 		ctx.reg_count <- (if reg_super then 2 else 1);
 		ctx.in_loop <- false;
 		let pargs = ref [] in
 		let rargs = List.map (fun (a,_,t) ->
-			let no_reg = ctx.version = 6 || cfind false (TLocal a) f.tf_expr in
+			let no_reg = ctx.version = 6 || Transform.local_find false a f.tf_expr in
 			if no_reg then begin
-				ctx.regs <- PMap.add a (NoReg false) ctx.regs;
+				ctx.regs <- PMap.add a NoReg ctx.regs;
 				pargs := unprotect a :: !pargs;
 				0 , a
 			end else begin
@@ -988,11 +907,12 @@ and gen_expr_2 ctx retval e =
 				r , ""
 			end
 		) f.tf_args in
-		let tf = func ctx reg_super (cfind true (TLocal "__arguments__") f.tf_expr) rargs in
+		let tf = func ctx reg_super (Transform.local_find true "__arguments__" f.tf_expr) rargs in
 		ctx.fun_pargs <- (ctx.code_pos, List.rev !pargs) :: ctx.fun_pargs;
 		gen_expr ctx false f.tf_expr;
+		ctx.in_loop <- old_in_loop;
 		tf();
-		block());
+		block();
 	| TIf (cond,e,None) ->
 		if retval then assert false;
 		gen_expr ctx true cond;
@@ -1115,6 +1035,7 @@ let gen_class_static_field ctx c flag f =
 		push ctx [VReg 0; VStr (f.cf_name,flag); VNull];
 		setvar ctx VarObj
 	| Some e ->
+		let e = Transform.block_vars e in
 		match e.eexpr with
 		| TFunction _ ->
 			push ctx [VReg 0; VStr (f.cf_name,flag)];
@@ -1139,7 +1060,7 @@ let gen_class_field ctx f flag =
 		push ctx [VNull]
 	| Some e ->
 		ctx.curmethod <- f.cf_name;
-		gen_expr ctx true e);
+		gen_expr ctx true (Transform.block_vars e));
 	setvar ctx VarObj
 
 let gen_enum_field ctx e f =
@@ -1225,7 +1146,7 @@ let gen_type_def ctx t =
 	| TClassDecl c ->
 		(match c.cl_init with
 		| None -> ()
-		| Some e -> ctx.inits <- e :: ctx.inits);
+		| Some e -> ctx.inits <- Transform.block_vars e :: ctx.inits);
 		gen_package ctx (fst c.cl_path);
 		if c.cl_extern then
 			()
@@ -1248,7 +1169,7 @@ let gen_type_def ctx t =
 		| Some { cf_expr = Some e } ->
 			have_constr := true;
 			ctx.curmethod <- "new";
-			gen_expr ctx true e
+			gen_expr ctx true (Transform.block_vars e)
 		| _ ->
 			let f = func ctx true false [] in
 			f());

+ 3 - 0
haxe.vcproj

@@ -75,6 +75,9 @@
 		<File
 			RelativePath=".\plugin.ml">
 		</File>
+		<File
+			RelativePath=".\transform.ml">
+		</File>
 		<File
 			RelativePath=".\type.ml">
 		</File>

+ 196 - 0
transform.ml

@@ -0,0 +1,196 @@
+(*
+ *  Haxe Compiler
+ *  Copyright (c)2005 Nicolas Cannasse
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *)
+open Type
+
+let rec map f e =
+	match e.eexpr with
+	| TConst _
+	| TLocal _
+	| TEnumField _
+	| TBreak
+	| TContinue
+	| TType _ ->
+		e
+	| TArray (e1,e2) ->
+		{ e with eexpr = TArray (f e1,f e2) }
+	| TBinop (op,e1,e2) ->
+		{ e with eexpr = TBinop (op,f e1,f e2) }
+	| TFor (v,e1,e2) ->
+		{ e with eexpr = TFor (v,f e1,f e2) }
+	| TWhile (e1,e2,flag) ->
+		{ e with eexpr = TWhile (f e1,f e2,flag) }
+	| TThrow e ->
+		{ e with eexpr = TThrow (f e) }
+	| TField (e,v) ->
+		{ e with eexpr = TField (f e,v) }
+	| TParenthesis e ->
+		{ e with eexpr = TParenthesis (f e) }
+	| TUnop (op,pre,e) ->
+		{ e with eexpr = TUnop (op,pre,f e) }
+	| TArrayDecl el ->
+		{ e with eexpr = TArrayDecl (List.map f el) }
+	| TNew (t,pl,el) ->
+		{ e with eexpr = TNew (t,pl,List.map f el) }
+	| TBlock el ->
+		{ e with eexpr = TBlock (List.map f el) }
+	| TObjectDecl el ->
+		{ e with eexpr = TObjectDecl (List.map (fun (v,e) -> v, f e) el) }
+	| TCall (e,el) ->
+		{ e with eexpr = TCall (f e, List.map f el) }
+	| TVars vl ->
+		{ e with eexpr = TVars (List.map (fun (v,t,e) -> v , t , match e with None -> None | Some e -> Some (f e)) vl) }
+	| TFunction fu ->
+		{ e with eexpr = TFunction { fu with tf_expr = f fu.tf_expr } }
+	| TIf (e,e1,e2) ->
+		{ e with eexpr = TIf (f e,f e1,match e2 with None -> None | Some e -> Some (f e)) }
+	| TSwitch (e,cases,def) ->
+		{ e with eexpr = TSwitch (f e, List.map (fun (e1,e2) -> f e1, f e2) cases, match def with None -> None | Some e -> Some (f e)) }
+	| TMatch (e,t,cases,def) ->
+		{ e with eexpr = TMatch (f e, t, List.map (fun (c,l,e) -> c, l, f e) cases, match def with None -> None | Some e -> Some (f e)) }
+	| TTry (e,catches) ->
+		{ e with eexpr = TTry (f e, List.map (fun (v,t,e) -> v, t, f e) catches) }
+	| TReturn eo ->
+		{ e with eexpr = TReturn (match eo with None -> None | Some e -> Some (f e)) }
+
+let local_find flag vname e =
+	let rec loop2 e =
+		match e.eexpr with
+		| TFunction f ->
+			if not flag && not (List.exists (fun (a,_,_) -> a = vname) f.tf_args) then loop2 f.tf_expr
+		| TBlock _ ->
+			(try
+				iter loop2 e;
+			with
+				Not_found -> ())
+		| TVars vl ->
+			List.iter (fun (v,t,e) ->
+				(match e with
+				| None -> ()
+				| Some e -> loop2 e);
+				if v = vname then raise Not_found;
+			) vl
+		| TConst TSuper ->
+			if vname = "super" then raise Exit
+		| TLocal v ->
+			if v = vname then raise Exit
+		| _ ->
+			iter loop2 e
+	in
+	let rec loop e =
+		match e.eexpr with
+		| TFunction f ->
+			if not (List.exists (fun (a,_,_) -> a = vname) f.tf_args) then loop2 f.tf_expr
+		| TBlock _ ->
+			(try
+				iter loop e;
+			with
+				Not_found -> ())
+		| TVars vl ->
+			List.iter (fun (v,t,e) ->
+				(match e with
+				| None -> ()
+				| Some e -> loop e);
+				if v = vname then raise Not_found;
+			) vl
+		| _ ->
+			iter loop e
+	in
+	try
+		(if flag then loop2 else loop) e;
+		false
+	with
+		Exit ->
+			true
+
+let block_vars e =
+	let add_var map v = map := PMap.add v () (!map) in
+	let wrap e used =
+		match PMap.foldi (fun v _ acc -> v :: acc) used [] with
+		| [] -> e
+		| vars ->
+			mk (TCall (
+				(mk (TFunction {
+					tf_args = List.map (fun v -> v , false, t_dynamic) vars;
+					tf_type = t_dynamic;
+					tf_expr = mk (TReturn (Some e)) t_dynamic e.epos;
+				}) t_dynamic e.epos),
+				List.map (fun v -> mk (TLocal v) t_dynamic e.epos) vars)
+			) t_dynamic e.epos
+	in
+	let rec in_fun vars used_locals e =
+		match e.eexpr with
+		| TLocal v ->
+			if PMap.mem v vars then add_var used_locals v
+		| TFunction _ ->
+			()
+		| _ ->
+			iter (in_fun vars used_locals) e
+
+	and in_loop vars e =
+		match e.eexpr with
+		| TVars l ->
+			{ e with eexpr = TVars (List.map (fun (v,t,e) ->
+				let e = (match e with None -> None | Some e -> Some (in_loop vars e)) in
+				add_var vars v;
+				v, t, e
+			) l) }
+		| TTry (e,cases) ->
+			let e = in_loop vars e in
+			let cases = List.map (fun (v,t,e) ->
+				let new_vars = PMap.add v () (!vars) in
+				v , t, in_loop (ref new_vars) e
+			) cases in
+			{ e with eexpr = TTry (e,cases) }
+		| TMatch (e,t,cases,def) ->
+			let e = in_loop vars e in
+			let cases = List.map (fun (c,params,e) ->
+				let e = (match params with
+					| None -> in_loop vars e
+					| Some l ->
+						let new_vars = List.fold_left (fun acc (v,t) ->
+							match v with
+							| None -> acc
+							| Some name -> PMap.add name () acc
+						) (!vars) l in
+						in_loop (ref new_vars) e
+				) in
+				c , params , e
+			) cases in
+			let def = (match def with None -> None | Some e -> Some (in_loop vars e)) in
+			{ e with eexpr = TMatch (e, t, cases, def) }
+		| TBlock l ->
+			let new_vars = (ref !vars) in
+			map (in_loop new_vars) e
+		| TFunction _ ->
+			let new_vars = !vars in
+			let used = ref PMap.empty in
+			iter (in_fun new_vars used) e;
+			let e = wrap e (!used) in
+			let new_vars = ref (PMap.foldi (fun v _ acc -> PMap.remove v acc) (!used) new_vars) in
+			map (in_loop new_vars) e
+		| _ ->
+			map (in_loop vars) e
+	and out_loop e =
+		match e.eexpr with
+		| TFor _ | TWhile _ ->
+			map (in_loop (ref PMap.empty)) e
+		| _ ->
+			map out_loop e
+	in
+	out_loop e