Explorar el Código

code generator beautify

Nicolas Cannasse hace 14 años
padre
commit
8d75c7d9c5
Se han modificado 3 ficheros con 105 adiciones y 47 borrados
  1. 1 0
      doc/CHANGES.txt
  2. 86 46
      genjs.ml
  3. 18 1
      optimizer.ml

+ 1 - 0
doc/CHANGES.txt

@@ -2,6 +2,7 @@
 	js : added js.JQuery
 	all : added @:multitype
 	js : upgraded js.SWFObject from 1.4.4 inlined to 1.5 embedded
+	js : code generator beautify
 
 2011-01-30: 2.07
 	all : fixed completion support with --remap

+ 86 - 46
genjs.ml

@@ -101,6 +101,13 @@ let open_block ctx =
 	ctx.tabs <- "\t" ^ ctx.tabs;
 	(fun() -> ctx.tabs <- oldt)
 
+let rec has_return e =
+	match e.eexpr with
+	| TBlock [] -> false
+	| TBlock el -> has_return (List.hd (List.rev el))
+	| TReturn _ -> true
+	| _ -> false
+
 let rec iter_switch_break in_switch e =
 	match e.eexpr with
 	| TFunction _ | TWhile _ | TFor _ -> ()
@@ -243,12 +250,10 @@ and gen_expr ctx e =
 	| TContinue ->
 		if not ctx.in_loop then unsupported e.epos;
 		spr ctx "continue"
-	| TBlock [] ->
-		spr ctx "null"
 	| TBlock el ->
 		print ctx "{";
 		let bend = open_block ctx in
-		List.iter (fun e -> newline ctx; gen_expr ctx e) el;
+		List.iter (gen_block ctx) el;
 		bend();
 		newline ctx;
 		print ctx "}";
@@ -329,26 +334,37 @@ and gen_expr ctx e =
 		ctx.separator <- true
 	| TFor (v,_,it,e) ->
 		let handle_break = handle_break ctx e in
-		let id = ctx.id_counter in
-		ctx.id_counter <- ctx.id_counter + 1;
-		print ctx "{ var $it%d = " id;
-		gen_value ctx it;
-		newline ctx;
-		print ctx "while( $it%d.hasNext() ) { var %s = $it%d.next()" id (ident v) id;
+		let it = (match it.eexpr with
+			| TLocal v -> v
+			| _ ->
+				let id = ctx.id_counter in
+				ctx.id_counter <- ctx.id_counter + 1;
+				let name = "$it" ^ string_of_int id in
+				print ctx "var %s = " name;
+				gen_value ctx it;
+				newline ctx;
+				name
+		) in
+		print ctx "while( %s.hasNext() ) {" it;
+		let bend = open_block ctx in
 		newline ctx;
-		gen_expr ctx e;
+		print ctx "var %s = %s.next()" (ident v) it;
+		gen_block ctx e;
+		bend();
 		newline ctx;
-		spr ctx "}}";
+		spr ctx "}";
 		handle_break();
 	| TTry (e,catchs) ->
 		spr ctx "try ";
 		gen_expr ctx (mk_block e);
 		newline ctx;
-		let id = ctx.id_counter in
-		ctx.id_counter <- ctx.id_counter + 1;
-		print ctx "catch( $e%d ) {" id;
+		let vname = (match catchs with [(v,_,_)] -> v | _ ->
+			let id = ctx.id_counter in
+			ctx.id_counter <- ctx.id_counter + 1;
+			"$e" ^ string_of_int id
+		) in
+		print ctx "catch( %s ) {" vname;
 		let bend = open_block ctx in
-		newline ctx;
 		let last = ref false in
 		List.iter (fun (v,t,e) ->
 			if !last then () else
@@ -367,29 +383,30 @@ and gen_expr ctx e =
 			match t with
 			| None ->
 				last := true;
-				spr ctx "{";
-				let bend = open_block ctx in
-				newline ctx;
-				print ctx "var %s = $e%d" v id;
-				newline ctx;
-				gen_expr ctx e;
-				bend();
-				newline ctx;
-				spr ctx "}"
+				if vname <> v then begin
+					newline ctx;
+					print ctx "var %s = %s" v vname;
+				end;
+				gen_block ctx e;
 			| Some t ->
-				print ctx "if( %s.__instanceof($e%d," (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js"],"Boot" })) id;
+				newline ctx;
+				print ctx "if( %s.__instanceof(%s," (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js"],"Boot" })) vname;
 				gen_value ctx (mk (TTypeExpr t) (mk_mono()) e.epos);
 				spr ctx ") ) {";
 				let bend = open_block ctx in
-				newline ctx;
-				print ctx "var %s = $e%d" v id;
-				newline ctx;
-				gen_expr ctx e;
+				if vname <> v then begin
+					newline ctx;
+					print ctx "var %s = %s" v vname;
+				end;
+				gen_block ctx e;
 				bend();
 				newline ctx;
 				spr ctx "} else "
 		) catchs;
-		if not !last then print ctx "throw($e%d)" id;
+		if not !last then begin
+			newline ctx;
+			print ctx "throw(%s)" vname;
+		end;
 		bend();
 		newline ctx;
 		spr ctx "}";
@@ -398,12 +415,12 @@ and gen_expr ctx e =
 		gen_value ctx e;
 		newline ctx;
 		spr ctx "switch( $e[1] ) {";
-		newline ctx;
 		List.iter (fun (cl,params,e) ->
 			List.iter (fun c ->
-				print ctx "case %d:" c;
 				newline ctx;
+				print ctx "case %d:" c;
 			) cl;
+			let bend = open_block ctx in
 			(match params with
 			| None | Some [] -> ()
 			| Some l ->
@@ -412,23 +429,28 @@ and gen_expr ctx e =
 				match l with
 				| [] -> ()
 				| l ->
+					newline ctx;
 					spr ctx "var ";
 					concat ctx ", " (fun (v,n) ->
 						print ctx "%s = $e[%d]" v n;
-					) l;
-					newline ctx);
-			gen_expr ctx (mk_block e);
-			print ctx "break";
-			newline ctx
+					) l);
+			gen_block ctx e;
+			if not (has_return e) then begin
+				newline ctx;
+				print ctx "break";
+			end;
+			bend();
 		) cases;
 		(match def with
 		| None -> ()
 		| Some e ->
-			spr ctx "default:";
-			gen_expr ctx (mk_block e);
-			print ctx "break";
 			newline ctx;
+			spr ctx "default:";
+			let bend = open_block ctx in
+			gen_block ctx e;
+			bend();
 		);
+		newline ctx;
 		spr ctx "}"
 	| TSwitch (e,cases,def) ->
 		spr ctx "switch";
@@ -445,16 +467,22 @@ and gen_expr ctx e =
 					gen_value ctx e;
 					spr ctx ":"
 			) el;
-			gen_expr ctx (mk_block e2);
-			print ctx "break";
+			let bend = open_block ctx in
+			gen_block ctx e2;
+			if not (has_return e2) then begin
+				newline ctx;
+				print ctx "break";
+			end;
+			bend();
 			newline ctx;
 		) cases;
 		(match def with
 		| None -> ()
 		| Some e ->
 			spr ctx "default:";
-			gen_expr ctx (mk_block e);
-			print ctx "break";
+			let bend = open_block ctx in
+			gen_block ctx e;
+			bend();
 			newline ctx;
 		);
 		spr ctx "}"
@@ -463,6 +491,11 @@ and gen_expr ctx e =
 	| TCast (e1,Some t) ->
 		gen_expr ctx (Codegen.default_cast ctx.com e1 t e.etype e.epos)
 
+and gen_block ctx e =
+	match e.eexpr with
+	| TBlock el -> List.iter (gen_block ctx) el
+	| _ -> newline ctx; gen_expr ctx e
+
 and gen_value ctx e =
 	let assign e =
 		mk (TBinop (Ast.OpAssign,
@@ -638,8 +671,15 @@ let gen_constructor ctx e =
 	| TFunction f  ->
 		let args  = List.map arg_name f.tf_args in
 		let a, args = (match args with [] -> "p" , ["p"] | x :: _ -> x, args) in
-		print ctx "function(%s) { if( %s === $_ ) return; " (String.concat "," (List.map ident args)) a;
-		gen_expr ctx (fun_block ctx f e.epos);
+		print ctx "function(%s) {" (String.concat "," (List.map ident args));
+		let bend = open_block ctx in
+		if Codegen.constructor_side_effects f.tf_expr then begin
+			newline ctx;
+			print ctx "if( %s === $_ ) return" a;
+		end;
+		gen_block ctx (fun_block ctx f e.epos);
+		bend();
+		newline ctx;
 		print ctx "}";
 	| _ -> assert false
 

+ 18 - 1
optimizer.ml

@@ -380,6 +380,12 @@ let sanitize_expr e =
 	let block e =
 		mk (TBlock [e]) e.etype e.epos
 	in
+	let complex e =
+		(* complex expressions are the one that once generated to source consists in several expressions *)
+		match e.eexpr with
+		| TFor _ -> block e (* a temp var is needed for holding iterator *)
+		| _ -> e
+	in
 	let need_parent e =
 		match e.eexpr with
 		| TConst _ | TLocal _ | TEnumField _ | TArray _ | TField _ | TParenthesis _ | TCall _ | TClosure _ | TNew _ | TTypeExpr _ | TObjectDecl _ | TArrayDecl _ -> false
@@ -418,9 +424,20 @@ let sanitize_expr e =
 		) in
 		let e2 = (match e2.eexpr, eelse with
 			| TIf (_,_,Some _) , _ | TIf (_,_,None), Some _ -> block e2
-			| _ -> e2
+			| _ -> complex e2
 		) in
+		let eelse = (match eelse with None -> None | Some e -> Some (complex e)) in
 		{ e with eexpr = TIf (e1,e2,eelse) }
+	| TWhile (e1,e2,flag) ->
+		let e1 = (match e1.eexpr with
+			| TParenthesis _ -> e1
+			| _ -> parent e1
+		) in
+		let e2 = complex e2 in
+		{ e with eexpr = TWhile (e1,e2,flag) }
+	| TFor (v,t,e1,e2) ->
+		let e2 = complex e2 in
+		{ e with eexpr = TFor (v,t,e1,e2) }
 	| TFunction f ->
 		(match f.tf_expr.eexpr with
 		| TBlock _ -> e