Franco Ponticelli 12 years ago
parent
commit
52b8b04082
4 changed files with 69 additions and 42 deletions
  1. 9 4
      genphp.ml
  2. 31 31
      std/Lambda.hx
  3. 7 7
      tests/unit/TestGADT.hx
  4. 22 0
      tests/unit/TestPhp.hx

+ 9 - 4
genphp.ml

@@ -1158,7 +1158,7 @@ and gen_expr ctx e =
 			let se1 = s_expr_name e1 in
 			let se2 = s_expr_name e2 in
 			if
-				e1.eexpr = TConst (TNull)
+				   e1.eexpr = TConst (TNull)
 				|| e2.eexpr = TConst (TNull)
 			then begin
 				(match e1.eexpr with
@@ -1179,8 +1179,8 @@ and gen_expr ctx e =
 				| _ ->
 					gen_field_op ctx e2);
 			end else if
-					((se1 = "Int" || se1 = "Null<Int>") && (se2 = "Int" || se2 = "Null<Int>"))
-					|| ((se1 = "Float" || se1 = "Null<Float>") && (se2 = "Float" || se2 = "Null<Float>"))
+				   ((se1 = "Int" || se1 = "Null<Int>") && (se2 = "Int" || se2 = "Null<Int>"))
+				|| ((se1 = "Float" || se1 = "Null<Float>") && (se2 = "Float" || se2 = "Null<Float>"))
 			then begin
 				gen_field_op ctx e1;
 				spr ctx s_phop;
@@ -1217,9 +1217,14 @@ and gen_expr ctx e =
 				spr ctx s_phop;
 				gen_field_op ctx e2;
 			end else begin
+				let tmp = define_local ctx "_t" in
+				print ctx "(is_object($%s = " tmp;
 				gen_field_op ctx e1;
-				spr ctx s_op;
+				print ctx ") && !($%s instanceof Enum) ? $%s%s" tmp tmp s_phop;
 				gen_field_op ctx e2;
+				print ctx " : $%s%s" tmp s_op;
+				gen_field_op ctx e2;
+				spr ctx ")";
 			end
 		| _ ->
 			leftside e1;

+ 31 - 31
std/Lambda.hx

@@ -24,11 +24,11 @@
 	The `Lambda` class is a collection of methods to support functional
 	programming. It is ideally used with 'using Lambda' and then acts as an
 	extension to Iterable types.
-	
+
 	On static platforms, working with the Iterable structure might be slower
 	than performing the operations directly on known types, such as Array and
 	List.
-	
+
 	If the first argument to any of the methods is null, the result is
 	unspecified.
 **/
@@ -36,7 +36,7 @@ class Lambda {
 
 	/**
 		Creates an Array from Iterable `it`.
-		
+
 		If `it` is an Array, this function returns a copy of it.
 	**/
 	public static function array<A>( it : Iterable<A> ) : Array<A> {
@@ -48,7 +48,7 @@ class Lambda {
 
 	/**
 		Creates a List form Iterable `it`.
-		
+
 		If `it` is a List, this function returns a copy of it.
 	**/
 	public static function list<A>( it : Iterable<A> ) : List<A> {
@@ -60,9 +60,9 @@ class Lambda {
 
 	/**
 		Creates a new List by applying function `f` to all elements of `it`.
-		
+
 		The order of elements is preserved.
-		
+
 		If `f` is null, the result is unspecified.
 	**/
 	public static function map<A,B>( it : Iterable<A>, f : A -> B ) : List<B> {
@@ -74,9 +74,9 @@ class Lambda {
 
 	/**
 		Similar to map, but also passes the index of each element to `f`.
-		
+
 		The order of elements is preserved.
-		
+
 		If `f` is null, the result is unspecified.
 	**/
 	public static function mapi<A,B>( it : Iterable<A>, f : Int -> A -> B ) : List<B> {
@@ -89,10 +89,10 @@ class Lambda {
 
 	/**
 		Tells if `it` contains `elt`.
-		
+
 		This function returns true as soon as an element is found which is equal
 		to `elt` according to the `==` operator.
-		
+
 		If no such element is found, the result is false.
 	**/
 	public static function has<A>( it : Iterable<A>, elt : A ) : Bool {
@@ -104,12 +104,12 @@ class Lambda {
 
 	/**
 		Tells if `it` contains an element for which `f` is true.
-		
+
 		This function returns true as soon as an element is found for which a
 		call to `f` returns true.
-		
+
 		If no such element is found, the result is false.
-		
+
 		If `f` is null, the result is unspecified.
 	**/
 	public static function exists<A>( it : Iterable<A>, f : A -> Bool ) {
@@ -121,14 +121,14 @@ class Lambda {
 
 	/**
 		Tells if `f` is true for all elements of `it`.
-		
+
 		This function returns false as soon as an element is found for which a
 		call to `f` returns false.
-		
+
 		If no such element is found, the result is true.
-		
+
 		In particular, this function always returns true if `it` is empty.
-		
+
 		If `f` is null, the result is unspecified.
 	**/
 	public static function foreach<A>( it : Iterable<A>, f : A -> Bool ) {
@@ -140,7 +140,7 @@ class Lambda {
 
 	/**
 		Calls `f` on all elements of `it`, in order.
-		
+
 		If `f` is null, the result is unspecified.
 	**/
 	public static function iter<A>( it : Iterable<A>, f : A -> Void ) {
@@ -151,9 +151,9 @@ class Lambda {
 	/**
 		Returns a List containing those elements of `it` for which `f` returned
 		true.
-		
+
 		If `it` is empty, the result is the empty List even if `f` is null.
-		
+
 		Otherwise if `f` is null, the result is unspecified.
 	**/
 	public static function filter<A>( it : Iterable<A>, f : A -> Bool ) {
@@ -167,13 +167,13 @@ class Lambda {
 	/**
 		Functional fold on Iterable `it`, using function `f` with start argument
 		`first`.
-		
+
 		If `it` has no elements, the result is `first`.
-		
+
 		Otherwise the first element of `it` is passed to `f` alongside `first`.
 		The result of that call is then passed to `f` with the next element of
 		`it`, and so on until `it` has no more elements.
-		
+
 		If `it` or `f` are null, the result is unspecified.
 	**/
 	public static function fold<A,B>( it : Iterable<A>, f : A -> B -> B, first : B ) : B {
@@ -185,7 +185,7 @@ class Lambda {
 	/**
 		Returns the number of elements in `it` for which `pred` is true, or the
 		total number of elements in `it` if `pred` is null.
-		
+
 		This function traverses all elements.
 	**/
 	public static function count<A>( it : Iterable<A>, ?pred : A -> Bool ) {
@@ -209,9 +209,9 @@ class Lambda {
 
 	/**
 		Returns the index of the first element `v` within Iterable `it`.
-		
+
 		This function uses operator `==` to check for equality.
-		
+
 		If `v` does not exist in `it`, the result is -1.
 	**/
 	public static function indexOf<T>( it : Iterable<T>, v : T ) : Int {
@@ -223,15 +223,15 @@ class Lambda {
 		}
 		return -1;
 	}
-	
+
 	/**
 		Returns the first element of `it` for which `f` is true.
-		
+
 		This function returns true as soon as an element is found for which a
 		call to `f` returns true.
-		
+
 		If no such element is found, the result is null.
-		
+
 		If `f` is null, the result is unspecified.
 	**/
 	public static function find<T>( it : Iterable<T>, f : T -> Bool ) : Null<T> {
@@ -244,7 +244,7 @@ class Lambda {
 	/**
 		Returns a new List containing all elements of Iterable `a` followed by
 		all elements of Iterable `b`.
-		
+
 		If `a` or `b` are null, the result is unspecified.
 	**/
 	public static function concat<T>( a : Iterable<T>, b : Iterable<T> ) : List<T> {

+ 7 - 7
tests/unit/TestGADT.hx

@@ -21,27 +21,27 @@ class TestGADT extends Test {
 	function testBasic() {
 		var ti = 1.22;
 		var tb = false;
-		
+
 		var e1 = EConst(CFloat("12"));
 		var e2 = EConst(CFloat("8"));
 		var e3 = EConst(CFloat("12"));
-		
+
 		var eadd = EBinop(OpAdd,e1,e2);
 		var s = eval(eadd);
 		TestType.typedAs(s, ti);
 		eq(s,20);
-		
+
 		var eeq = EBinop(OpEq,e1,e2);
 		var s = eval(eeq);
 		TestType.typedAs(s, tb);
 		eq(s,false);
-		
+
 		var eeq = EBinop(OpEq,e1,e3);
 		var s = eval(eeq);
 		TestType.typedAs(s, tb);
 		eq(s,true);
 	}
-	
+
 	static function evalConst<T>(c:Constant<T>):T {
 		return switch (c) {
 			case CString(s): s;
@@ -49,14 +49,14 @@ class TestGADT extends Test {
 			case CFloat(f): Std.parseFloat(f);
 		}
 	}
-	
+
 	static function evalBinop<T,C>(op:Binop<C,T>, e1:Expr<C>, e2:Expr<C>):T {
 		return switch(op) {
 			case OpAdd: eval(e1) + eval(e2);
 			case OpEq: eval(e1) == eval(e2);
 		}
 	}
-	
+
 	static function eval<T>(e:Expr<T>):T {
 		return switch(e) {
 			case EConst(c): evalConst(c);

+ 22 - 0
tests/unit/TestPhp.hx

@@ -54,6 +54,28 @@ class TestPhp extends Test
 		var result = pattern.replace("$a","A").replace("$b","B");
 		eq("AB", result);
 	}
+
+	function testIssue2146()
+	{
+		f(Class2146.test());
+	}
+}
+
+class Class2146 {
+    var array:Array<Class2146>;
+    function new() {
+        array = new Array<Class2146>();
+    }
+
+    public static function test() {
+        var a = new Class2146();
+        var b = new Class2146();
+        var c = new Class2146();
+        a.array.push(b);
+        b.array.push(a);
+        c.array.push(a);
+        return Lambda.has(c.array,b);
+    }
 }
 
 enum Annotation {