Przeglądaj źródła

prevent truncating float dynamic values to int when using numerical operations

Nicolas Cannasse 16 lat temu
rodzic
commit
4e60a610a8
8 zmienionych plików z 60 dodań i 28 usunięć
  1. 1 0
      doc/CHANGES.txt
  2. 2 1
      std/EReg.hx
  3. 1 1
      std/haxe/Int32.hx
  4. 1 1
      std/neko/Boot.hx
  5. 1 1
      std/neko/NekoArray__.hx
  6. 2 1
      std/neko/db/Manager.hx
  7. 4 3
      std/php/PhpDate__.hx
  8. 48 20
      typer.ml

+ 1 - 0
doc/CHANGES.txt

@@ -32,6 +32,7 @@ TODO :
 	flash9 : fixed issue with flash.* string enums verify error
 	compiler : allowed \r line separators for HXML files
 	flash9 : fixed verify error with loop variable beeing a specific class
+	compiler : prevent truncating float dynamic values to int when using numerical operations
 
 2008-11-23: 2.02
 	Std.is(MyInterface, Class) now returns true (haXe/PHP)

+ 2 - 1
std/EReg.hx

@@ -185,7 +185,8 @@ class EReg {
 			return s.substr(rl,s.length - rl);
 		#elseif php
 			if( untyped __call__("count", matches) == 0 ) throw "No string matched";
-			return untyped last.substr(__php__("$this->matches[0][1]") + __php__("strlen")(__php__("$this->matches[0][0]")));
+			var x : Int = untyped __php__("$this->matches[0][1]") + __php__("strlen")(__php__("$this->matches[0][0]"));
+			return last.substr(x);
 		#else
 			return null;
 		#end

+ 1 - 1
std/haxe/Int32.hx

@@ -171,7 +171,7 @@ class Int32 {
 		#if neko
 		return untyped __i32__compare(a,b);
 		#else
-		return (cast a) - (cast b);
+		return untyped a - b;
 		#end
 	}
 

+ 1 - 1
std/neko/Boot.hx

@@ -33,7 +33,7 @@ class Boot {
 	private static function __enum_str(e : Dynamic) {
 		if( e.args == null )
 			return e.tag;
-		var s = e.tag + untyped "(".__s;
+		var s : String = e.tag + untyped "(".__s;
 		var i = 0;
 		var l = untyped __dollar__asize(e.args);
 		var old = e.__string;

+ 1 - 1
std/neko/NekoArray__.hx

@@ -216,7 +216,7 @@ class NekoArray__<T> implements Array<T> {
 		return untyped Array.new1(__dollar__asub(this.__a,pos,len),len);
 	}
 
-	public function sort(f) {
+	public function sort(f:T->T->Int) {
 		untyped {
 			var a = this.__a;
 			var i = 0;

+ 2 - 1
std/neko/db/Manager.hx

@@ -73,7 +73,8 @@ class Manager<T : Object> {
 		var cl : Dynamic = classval;
 
 		// get basic infos
-		table_name = quoteField(if( cl.TABLE_NAME != null ) cl.TABLE_NAME else cl.__name__[cl.__name__.length-1]);
+		var cname : Array<String> = cl.__name__;
+		table_name = quoteField(if( cl.TABLE_NAME != null ) cl.TABLE_NAME else cname[cname.length-1]);
 		table_keys = if( cl.TABLE_IDS != null ) cl.TABLE_IDS else ["id"];
 		class_proto = cl;
 		lock_mode = 2;

+ 4 - 3
std/php/PhpDate__.hx

@@ -36,7 +36,7 @@ class PhpDate__ //implements Date
 	public function getTime() : Float {
 		return __t*1000;
 	}
-	
+
 	public function getPhpTime() : Float {
 		return __t;
 	}
@@ -46,7 +46,8 @@ class PhpDate__ //implements Date
 	}
 
 	public function getMonth() : Int {
-		return -1 + untyped __call__("intval", __call__("date", "n", this.__t));
+		var m : Int = untyped __call__("intval", __call__("date", "n", this.__t));
+		return -1 + m;
 	}
 
 	public function getDate() : Int {
@@ -82,7 +83,7 @@ class PhpDate__ //implements Date
 		d.__t = t;
 		return d;
 	}
-	
+
 	public static function fromTime( t : Float ){
 		var d = new PhpDate__(2000,1,1,0,0,0);
 		d.__t = t/1000;

+ 48 - 20
typer.ml

@@ -520,9 +520,37 @@ let type_field ctx e i p get =
 	from a Dynamic relaxation, we will instead unify with float since
 	we don't want to accidentaly truncate the value
 *)
-let unify_int ctx e =
-	unify ctx e.etype ctx.api.tint e.epos;
-	true
+let unify_int ctx e k =
+	let is_dynamic t = 
+		match follow t with
+		| TDynamic _ -> true
+		| _ -> false
+	in
+	let is_dynamic_array t =
+		match follow t with 
+		| TInst (_,[p]) -> is_dynamic p
+		| _ -> true
+	in
+	let is_dynamic_field t f =
+		match follow t with
+		| TAnon a ->
+			(try is_dynamic (PMap.find f a.a_fields).cf_type with Not_found -> true)
+		| _ -> true
+	in
+	let maybe_dynamic_mono() =
+		match e.eexpr with		
+		| TLocal _ when not (is_dynamic e.etype)  -> false
+		| TArray({ etype = t },_) when not (is_dynamic_array t) -> false
+		| TField({ etype = t },f) when not (is_dynamic_field t f) -> false
+		| _ -> true
+	in
+	match k with
+	| KUnk | KDyn when maybe_dynamic_mono() ->
+		unify ctx e.etype ctx.api.tfloat e.epos;
+		false
+	| _ ->
+		unify ctx e.etype ctx.api.tint e.epos;
+		true		
 
 let rec type_binop ctx op e1 e2 p =
 	match op with
@@ -584,13 +612,13 @@ let rec type_binop ctx op e1 e2 p =
 		| KFloat, KFloat ->
 			ctx.api.tfloat
 		| KUnk , KInt ->
-			if unify_int ctx e1 then ctx.api.tint else ctx.api.tfloat
+			if unify_int ctx e1 KUnk then ctx.api.tint else ctx.api.tfloat
 		| KUnk , KFloat
 		| KUnk , KString  ->
 			unify ctx e1.etype e2.etype e1.epos;
 			e1.etype
 		| KInt , KUnk ->
-			if unify_int ctx e2 then ctx.api.tint else ctx.api.tfloat
+			if unify_int ctx e2 KUnk then ctx.api.tint else ctx.api.tfloat
 		| KFloat , KUnk
 		| KString , KUnk ->
 			unify ctx e2.etype e1.etype e2.epos;
@@ -602,8 +630,8 @@ let rec type_binop ctx op e1 e2 p =
 		| KDyn , _ ->
 			e1.etype
 		| KUnk , KUnk ->
-			let ok1 = unify_int ctx e1 in
-			let ok2 = unify_int ctx e2 in
+			let ok1 = unify_int ctx e1 KUnk in
+			let ok2 = unify_int ctx e2 KUnk in
 			if ok1 && ok2 then ctx.api.tint else ctx.api.tfloat
 		| KParam t1, KParam t2 when t1 == t2 ->
 			t1
@@ -644,15 +672,15 @@ let rec type_binop ctx op e1 e2 p =
 			if op <> OpDiv then result := t
 		| KParam _, KFloat | KFloat, KParam _ ->
 			result := ctx.api.tfloat
-		| KFloat, _ ->
-			ignore(unify_int ctx e2);
+		| KFloat, k ->
+			ignore(unify_int ctx e2 k);
 			result := ctx.api.tfloat
-		| _, KFloat ->
-			ignore(unify_int ctx e1);
+		| k, KFloat ->
+			ignore(unify_int ctx e1 k);
 			result := ctx.api.tfloat
-		| _ , _ ->
-			let ok1 = unify_int ctx e1 in
-			let ok2 = unify_int ctx e2 in
+		| k1 , k2 ->
+			let ok1 = unify_int ctx e1 k1 in
+			let ok2 = unify_int ctx e2 k2 in
 			if not ok1 || not ok2  then result := ctx.api.tfloat;
 		);
 		mk_op !result
@@ -669,13 +697,13 @@ let rec type_binop ctx op e1 e2 p =
 	| OpLte ->
 		(match classify e1.etype, classify e2.etype with
 		| KInt , KInt | KInt , KFloat | KFloat , KInt | KFloat , KFloat | KString , KString -> ()
-		| KInt , KUnk -> ignore(unify_int ctx e2)
+		| KInt , KUnk -> ignore(unify_int ctx e2 KUnk)
 		| KFloat , KUnk | KString , KUnk -> unify ctx e2.etype e1.etype e2.epos
-		| KUnk , KInt -> ignore(unify_int ctx e1)
+		| KUnk , KInt -> ignore(unify_int ctx e1 KUnk)
 		| KUnk , KFloat | KUnk , KString -> unify ctx e1.etype e2.etype e1.epos
 		| KUnk , KUnk ->
-			ignore(unify_int ctx e1);
-			ignore(unify_int ctx e2);
+			ignore(unify_int ctx e1 KUnk);
+			ignore(unify_int ctx e2 KUnk);
 		| KDyn , KInt | KDyn , KFloat | KDyn , KString -> ()
 		| KInt , KDyn | KFloat , KDyn | KString , KDyn -> ()
 		| KDyn , KDyn -> ()
@@ -728,8 +756,8 @@ and type_unop ctx op flag e p =
 			| KParam t ->
 				unify ctx e.etype ctx.api.tfloat e.epos;
 				t
-			| _ ->
-				if unify_int ctx e then ctx.api.tint else ctx.api.tfloat)
+			| k ->
+				if unify_int ctx e k then ctx.api.tint else ctx.api.tfloat)
 		) in
 		match op, e.eexpr with
 		| Neg , TConst (TInt i) -> mk (TConst (TInt (Int32.neg i))) t p