Ver Fonte

sanitize binops for text platforms

Nicolas Cannasse há 15 anos atrás
pai
commit
c1839c629e
4 ficheiros alterados com 34 adições e 4 exclusões
  1. 1 0
      doc/CHANGES.txt
  2. 1 0
      main.ml
  3. 28 0
      optimizer.ml
  4. 4 4
      parser.ml

+ 1 - 0
doc/CHANGES.txt

@@ -40,6 +40,7 @@
 	all : improved completion with lambda function
 	as3 : several generation fixes
 	all : bugfix haxe.rtti.Generic on private class
+	php/js/cpp : sanitize binary expressions to prevent inlining errors
 
 2009-07-26: 2.04
 	flash9 : fixed get_full_path error with -D fdb

+ 1 - 0
main.ml

@@ -491,6 +491,7 @@ try
 		let tfilters = [
 			Codegen.fix_overrides com;
 		] in
+		let filters = (match com.platform with Js | Php | Cpp -> Optimizer.sanitize :: filters | _ -> filters) in
 		let filters = (if not com.foptimize then filters else Optimizer.reduce_expression ctx :: filters) in
 		Codegen.post_process com filters tfilters;
 		if Common.defined com "dump" then Codegen.dump_types com;

+ 28 - 0
optimizer.ml

@@ -454,3 +454,31 @@ let rec reduce_loop ctx is_sub e =
 
 let reduce_expression ctx e =
 	if ctx.com.foptimize then reduce_loop ctx false e else e
+
+(* ---------------------------------------------------------------------- *)
+(* SANITIZE *)
+
+(*
+	makes sure that when an AST get generated to source code, it will not
+	generate expressions that evaluate differently. It is then necessary to
+	add parenthesises around some binary expressions when the AST does not
+	correspond to the natural operand priority order for the platform
+*)
+
+let rec sanitize e =	
+	match e.eexpr with
+	| TBinop (op,e1,e2) ->
+		let parent e = mk (TParenthesis e) e.etype e.epos in
+		let e1 = sanitize e1 in
+		let e2 = sanitize e2 in
+		let e1 = (match e1.eexpr with
+			| TBinop (op2,_,_) when Parser.swap op2 op -> parent e1
+			| _ -> e1
+		) in
+		let e2 = (match e2.eexpr with
+			| TBinop (op2,_,_) when Parser.swap op2 op -> parent e2
+			| _ -> e2
+		) in
+		{ e with eexpr = TBinop (op,e1,e2) }
+	| _ -> Type.map_expr sanitize e
+

+ 4 - 4
parser.ml

@@ -76,19 +76,19 @@ let is_not_assign = function
 	| OpAssign | OpAssignOp _ -> false
 	| _ -> true
 
-let can_swap _op op =
+let swap _op op =
 	let p1 = priority _op in
 	let p2 = priority op in
 	if p1 < p2 then
-		true
+		is_not_assign _op || is_not_assign op
 	else if p1 = p2 && p1 >= 0 then (* numerical ops are left-assoc *)
-		true
+		is_not_assign _op || is_not_assign op
 	else
 		false
 
 let rec make_binop op e ((v,p2) as e2) =
 	match v with
-	| EBinop (_op,_e,_e2) when can_swap _op op && (is_not_assign _op || is_not_assign op) ->
+	| EBinop (_op,_e,_e2) when swap _op op ->
 		let _e = make_binop op e _e in
 		EBinop (_op,_e,_e2) , punion (pos _e) (pos _e2)
 	| ETernary (e1,e2,e3) when is_not_assign op ->