Browse Source

Merge pull request #3677 from Simn/abstract_recursion_fixes

Abstract recursion fixes
Simon Krajewski 10 years ago
parent
commit
011ba9b3de
7 changed files with 21 additions and 13 deletions
  1. 1 0
      ast.ml
  2. 1 0
      common.ml
  3. 2 2
      std/UInt.hx
  4. 10 10
      std/haxe/Int32.hx
  5. 3 1
      tests/unit/src/unit/issues/Issue2130.hx
  6. 1 0
      typeload.ml
  7. 3 0
      typer.ml

+ 1 - 0
ast.ml

@@ -109,6 +109,7 @@ module Meta = struct
 		| NoCompletion
 		| NoDebug
 		| NoDoc
+		| NoExpr
 		| NoImportGlobal
 		| NoPackageRestrict
 		| NoStack

+ 1 - 0
common.ml

@@ -423,6 +423,7 @@ module MetaInfo = struct
 		| NoCompletion -> ":noCompletion",("Prevents the compiler from suggesting completion on this field",[UsedOn TClassField])
 		| NoDebug -> ":noDebug",("Does not generate debug information into the Swf even if -debug is set",[UsedOnEither [TClass;TClassField];Platform Flash])
 		| NoDoc -> ":noDoc",("Prevents a type from being included in documentation generation",[])
+		| NoExpr -> ":noExpr",("Internally used to mark abstract fields which have no expression by design",[Internal])
 		| NoImportGlobal -> ":noImportGlobal",("Prevents a static field from being imported with import Class.*",[UsedOn TAnyField])
 		| NoPackageRestrict -> ":noPackageRestrict",("Allows a module to be accessed across all targets if found on its first type.",[Internal])
 		| NoStack -> ":noStack",("",[Platform Cpp])

+ 2 - 2
std/UInt.hx

@@ -94,11 +94,11 @@ abstract UInt(Int) from Int to Int {
 	}
 
 	@:op(A >> B) private static inline function shr(a:UInt, b:UInt):UInt {
-		return a.toInt() >> b;
+		return a.toInt() >> b.toInt();
 	}
 
 	@:op(A >>> B) private static inline function ushr(a:UInt, b:UInt):UInt {
-		return a.toInt() >>> b;
+		return a.toInt() >>> b.toInt();
 	}
 
 	@:op(A % B) private static inline function mod(a:UInt, b:UInt):UInt {

+ 10 - 10
std/haxe/Int32.hx

@@ -47,21 +47,21 @@ abstract Int32(Int) from Int to Int {
 	}
 
 	@:op(A + B) private static inline function add(a:Int32, b:Int32):Int32
-		return clamp( a + b );
+		return clamp( (a : Int) + (b : Int) );
 
 	@:op(A + B) @:commutative private static inline function addInt(a:Int32, b:Int):Int32
-		return clamp( (a : Int) + b );
+		return clamp( (a : Int) + (b : Int) );
 
 	@:op(A + B) @:commutative private static function addFloat(a:Int32, b:Float):Float;
 
 	@:op(A - B) private static inline function sub(a:Int32, b:Int32):Int32
-		return clamp( a - b );
+		return clamp( (a : Int) - (b : Int) );
 
 	@:op(A - B) private static inline function subInt(a:Int32, b:Int):Int32
-		return clamp( (a : Int) - b );
+		return clamp( (a : Int) - (b : Int) );
 
 	@:op(A - B) private static inline function intSub(a:Int, b:Int32):Int32
-		return clamp( a - (b : Int) );
+		return clamp( (a : Int) - (b : Int) );
 
 	@:op(A - B) private static function subFloat(a:Int32, b:Float):Float;
 
@@ -70,7 +70,7 @@ abstract Int32(Int) from Int to Int {
 	#if (as3 || flash8 || js || php || python)
 
 	@:op(A * B) private static function mul(a:Int32, b:Int32):Int32
-		return clamp( a * (b & 0xFFFF) + clamp( a * (b >>> 16) << 16 ) );
+		return clamp( (a : Int) * ((b : Int) & 0xFFFF) + clamp( (a : Int) * ((b : Int) >>> 16) << 16 ) );
 
 	@:op(A * B) @:commutative private static inline function mulInt(a:Int32, b:Int):Int32
 		return mul(a, b);
@@ -152,13 +152,13 @@ abstract Int32(Int) from Int to Int {
 
 	// PHP may be 64-bit, so shifts must be clamped
 	@:op(A << B) private static inline function shl(a:Int32, b:Int32):Int32
-		return clamp( a << b );
+		return clamp( (a : Int) << (b : Int) );
 
 	@:op(A << B) private static inline function shlInt(a:Int32, b:Int):Int32
-		return clamp( a << b );
+		return clamp( (a : Int) << b );
 
-	@:op(A << B) private static inline function intShl(a:Int32, b:Int):Int32
-		return clamp( a << b );
+	@:op(A << B) private static inline function intShl(a:Int, b:Int32):Int32
+		return clamp( a << (b : Int) );
 
 	#else
 

+ 3 - 1
tests/unit/src/unit/issues/Issue2130.hx

@@ -17,7 +17,9 @@ private abstract ZeroOneFloat(Float) to Float {
         return this = new ZeroOneFloat(this*r);
     }
 
-    @:op(A * B) @:commutative public static inline function mul_i(l:ZeroOneFloat, r:Float) return l*r;
+    @:op(A * B) @:commutative public static inline function mul_i(l:ZeroOneFloat, r:Float) {
+		return (l : Float) * r;
+	}
 }
 
 class Issue2130 extends Test {

+ 1 - 0
typeload.ml

@@ -2007,6 +2007,7 @@ let init_class ctx c p context_init herits fields =
 								| None -> error (f.cff_name ^ ": Functions without expressions must have an explicit return type") f.cff_pos
 								| Some _ -> ()
 							end;
+							cf.cf_meta <- (Meta.NoExpr,[],cf.cf_pos) :: cf.cf_meta;
 							do_add := false;
 							do_bind := false;
 						end

+ 3 - 0
typer.ml

@@ -940,6 +940,7 @@ let make_call ctx e params t p =
 
 let mk_array_get_call ctx (cf,tf,r,e1,e2o) c ebase p = match cf.cf_expr with
 	| None ->
+		if not (Meta.has Meta.NoExpr cf.cf_meta) then display_error ctx "Recursive array get method" p;
 		mk (TArray(ebase,e1)) r p
 	| Some _ ->
 		let et = type_module_type ctx (TClassDecl c) None p in
@@ -950,6 +951,7 @@ let mk_array_set_call ctx (cf,tf,r,e1,e2o) c ebase p =
 	let evalue = match e2o with None -> assert false | Some e -> e in
 	match cf.cf_expr with
 		| None ->
+			if not (Meta.has Meta.NoExpr cf.cf_meta) then display_error ctx "Recursive array get method" p;
 			let ea = mk (TArray(ebase,e1)) r p in
 			mk (TBinop(OpAssign,ea,evalue)) r p
 		| Some _ ->
@@ -2160,6 +2162,7 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p =
 		let map = apply_params a.a_params tl in
 		let make op_cf cf e1 e2 tret =
 			if cf.cf_expr = None then begin
+				if not (Meta.has Meta.NoExpr cf.cf_meta) then display_error ctx "Recursive operator method" p;
 				if not (Meta.has Meta.CoreType a.a_meta) then begin
 					(* for non core-types we require that the return type is compatible to the native result type *)
 					let e' = make {e1 with etype = Abstract.follow_with_abstracts e1.etype} {e1 with etype = Abstract.follow_with_abstracts e2.etype} in