Franco Ponticelli 12 jaren geleden
bovenliggende
commit
52b8b04082
4 gewijzigde bestanden met toevoegingen van 69 en 42 verwijderingen
  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 se1 = s_expr_name e1 in
 			let se2 = s_expr_name e2 in
 			let se2 = s_expr_name e2 in
 			if
 			if
-				e1.eexpr = TConst (TNull)
+				   e1.eexpr = TConst (TNull)
 				|| e2.eexpr = TConst (TNull)
 				|| e2.eexpr = TConst (TNull)
 			then begin
 			then begin
 				(match e1.eexpr with
 				(match e1.eexpr with
@@ -1179,8 +1179,8 @@ and gen_expr ctx e =
 				| _ ->
 				| _ ->
 					gen_field_op ctx e2);
 					gen_field_op ctx e2);
 			end else if
 			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
 			then begin
 				gen_field_op ctx e1;
 				gen_field_op ctx e1;
 				spr ctx s_phop;
 				spr ctx s_phop;
@@ -1217,9 +1217,14 @@ and gen_expr ctx e =
 				spr ctx s_phop;
 				spr ctx s_phop;
 				gen_field_op ctx e2;
 				gen_field_op ctx e2;
 			end else begin
 			end else begin
+				let tmp = define_local ctx "_t" in
+				print ctx "(is_object($%s = " tmp;
 				gen_field_op ctx e1;
 				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;
 				gen_field_op ctx e2;
+				print ctx " : $%s%s" tmp s_op;
+				gen_field_op ctx e2;
+				spr ctx ")";
 			end
 			end
 		| _ ->
 		| _ ->
 			leftside e1;
 			leftside e1;

+ 31 - 31
std/Lambda.hx

@@ -24,11 +24,11 @@
 	The `Lambda` class is a collection of methods to support functional
 	The `Lambda` class is a collection of methods to support functional
 	programming. It is ideally used with 'using Lambda' and then acts as an
 	programming. It is ideally used with 'using Lambda' and then acts as an
 	extension to Iterable types.
 	extension to Iterable types.
-	
+
 	On static platforms, working with the Iterable structure might be slower
 	On static platforms, working with the Iterable structure might be slower
 	than performing the operations directly on known types, such as Array and
 	than performing the operations directly on known types, such as Array and
 	List.
 	List.
-	
+
 	If the first argument to any of the methods is null, the result is
 	If the first argument to any of the methods is null, the result is
 	unspecified.
 	unspecified.
 **/
 **/
@@ -36,7 +36,7 @@ class Lambda {
 
 
 	/**
 	/**
 		Creates an Array from Iterable `it`.
 		Creates an Array from Iterable `it`.
-		
+
 		If `it` is an Array, this function returns a copy of it.
 		If `it` is an Array, this function returns a copy of it.
 	**/
 	**/
 	public static function array<A>( it : Iterable<A> ) : Array<A> {
 	public static function array<A>( it : Iterable<A> ) : Array<A> {
@@ -48,7 +48,7 @@ class Lambda {
 
 
 	/**
 	/**
 		Creates a List form Iterable `it`.
 		Creates a List form Iterable `it`.
-		
+
 		If `it` is a List, this function returns a copy of it.
 		If `it` is a List, this function returns a copy of it.
 	**/
 	**/
 	public static function list<A>( it : Iterable<A> ) : List<A> {
 	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`.
 		Creates a new List by applying function `f` to all elements of `it`.
-		
+
 		The order of elements is preserved.
 		The order of elements is preserved.
-		
+
 		If `f` is null, the result is unspecified.
 		If `f` is null, the result is unspecified.
 	**/
 	**/
 	public static function map<A,B>( it : Iterable<A>, f : A -> B ) : List<B> {
 	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`.
 		Similar to map, but also passes the index of each element to `f`.
-		
+
 		The order of elements is preserved.
 		The order of elements is preserved.
-		
+
 		If `f` is null, the result is unspecified.
 		If `f` is null, the result is unspecified.
 	**/
 	**/
 	public static function mapi<A,B>( it : Iterable<A>, f : Int -> A -> B ) : List<B> {
 	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`.
 		Tells if `it` contains `elt`.
-		
+
 		This function returns true as soon as an element is found which is equal
 		This function returns true as soon as an element is found which is equal
 		to `elt` according to the `==` operator.
 		to `elt` according to the `==` operator.
-		
+
 		If no such element is found, the result is false.
 		If no such element is found, the result is false.
 	**/
 	**/
 	public static function has<A>( it : Iterable<A>, elt : A ) : Bool {
 	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.
 		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
 		This function returns true as soon as an element is found for which a
 		call to `f` returns true.
 		call to `f` returns true.
-		
+
 		If no such element is found, the result is false.
 		If no such element is found, the result is false.
-		
+
 		If `f` is null, the result is unspecified.
 		If `f` is null, the result is unspecified.
 	**/
 	**/
 	public static function exists<A>( it : Iterable<A>, f : A -> Bool ) {
 	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`.
 		Tells if `f` is true for all elements of `it`.
-		
+
 		This function returns false as soon as an element is found for which a
 		This function returns false as soon as an element is found for which a
 		call to `f` returns false.
 		call to `f` returns false.
-		
+
 		If no such element is found, the result is true.
 		If no such element is found, the result is true.
-		
+
 		In particular, this function always returns true if `it` is empty.
 		In particular, this function always returns true if `it` is empty.
-		
+
 		If `f` is null, the result is unspecified.
 		If `f` is null, the result is unspecified.
 	**/
 	**/
 	public static function foreach<A>( it : Iterable<A>, f : A -> Bool ) {
 	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.
 		Calls `f` on all elements of `it`, in order.
-		
+
 		If `f` is null, the result is unspecified.
 		If `f` is null, the result is unspecified.
 	**/
 	**/
 	public static function iter<A>( it : Iterable<A>, f : A -> Void ) {
 	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
 		Returns a List containing those elements of `it` for which `f` returned
 		true.
 		true.
-		
+
 		If `it` is empty, the result is the empty List even if `f` is null.
 		If `it` is empty, the result is the empty List even if `f` is null.
-		
+
 		Otherwise if `f` is null, the result is unspecified.
 		Otherwise if `f` is null, the result is unspecified.
 	**/
 	**/
 	public static function filter<A>( it : Iterable<A>, f : A -> Bool ) {
 	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
 		Functional fold on Iterable `it`, using function `f` with start argument
 		`first`.
 		`first`.
-		
+
 		If `it` has no elements, the result is `first`.
 		If `it` has no elements, the result is `first`.
-		
+
 		Otherwise the first element of `it` is passed to `f` alongside `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
 		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.
 		`it`, and so on until `it` has no more elements.
-		
+
 		If `it` or `f` are null, the result is unspecified.
 		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 {
 	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
 		Returns the number of elements in `it` for which `pred` is true, or the
 		total number of elements in `it` if `pred` is null.
 		total number of elements in `it` if `pred` is null.
-		
+
 		This function traverses all elements.
 		This function traverses all elements.
 	**/
 	**/
 	public static function count<A>( it : Iterable<A>, ?pred : A -> Bool ) {
 	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`.
 		Returns the index of the first element `v` within Iterable `it`.
-		
+
 		This function uses operator `==` to check for equality.
 		This function uses operator `==` to check for equality.
-		
+
 		If `v` does not exist in `it`, the result is -1.
 		If `v` does not exist in `it`, the result is -1.
 	**/
 	**/
 	public static function indexOf<T>( it : Iterable<T>, v : T ) : Int {
 	public static function indexOf<T>( it : Iterable<T>, v : T ) : Int {
@@ -223,15 +223,15 @@ class Lambda {
 		}
 		}
 		return -1;
 		return -1;
 	}
 	}
-	
+
 	/**
 	/**
 		Returns the first element of `it` for which `f` is true.
 		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
 		This function returns true as soon as an element is found for which a
 		call to `f` returns true.
 		call to `f` returns true.
-		
+
 		If no such element is found, the result is null.
 		If no such element is found, the result is null.
-		
+
 		If `f` is null, the result is unspecified.
 		If `f` is null, the result is unspecified.
 	**/
 	**/
 	public static function find<T>( it : Iterable<T>, f : T -> Bool ) : Null<T> {
 	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
 		Returns a new List containing all elements of Iterable `a` followed by
 		all elements of Iterable `b`.
 		all elements of Iterable `b`.
-		
+
 		If `a` or `b` are null, the result is unspecified.
 		If `a` or `b` are null, the result is unspecified.
 	**/
 	**/
 	public static function concat<T>( a : Iterable<T>, b : Iterable<T> ) : List<T> {
 	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() {
 	function testBasic() {
 		var ti = 1.22;
 		var ti = 1.22;
 		var tb = false;
 		var tb = false;
-		
+
 		var e1 = EConst(CFloat("12"));
 		var e1 = EConst(CFloat("12"));
 		var e2 = EConst(CFloat("8"));
 		var e2 = EConst(CFloat("8"));
 		var e3 = EConst(CFloat("12"));
 		var e3 = EConst(CFloat("12"));
-		
+
 		var eadd = EBinop(OpAdd,e1,e2);
 		var eadd = EBinop(OpAdd,e1,e2);
 		var s = eval(eadd);
 		var s = eval(eadd);
 		TestType.typedAs(s, ti);
 		TestType.typedAs(s, ti);
 		eq(s,20);
 		eq(s,20);
-		
+
 		var eeq = EBinop(OpEq,e1,e2);
 		var eeq = EBinop(OpEq,e1,e2);
 		var s = eval(eeq);
 		var s = eval(eeq);
 		TestType.typedAs(s, tb);
 		TestType.typedAs(s, tb);
 		eq(s,false);
 		eq(s,false);
-		
+
 		var eeq = EBinop(OpEq,e1,e3);
 		var eeq = EBinop(OpEq,e1,e3);
 		var s = eval(eeq);
 		var s = eval(eeq);
 		TestType.typedAs(s, tb);
 		TestType.typedAs(s, tb);
 		eq(s,true);
 		eq(s,true);
 	}
 	}
-	
+
 	static function evalConst<T>(c:Constant<T>):T {
 	static function evalConst<T>(c:Constant<T>):T {
 		return switch (c) {
 		return switch (c) {
 			case CString(s): s;
 			case CString(s): s;
@@ -49,14 +49,14 @@ class TestGADT extends Test {
 			case CFloat(f): Std.parseFloat(f);
 			case CFloat(f): Std.parseFloat(f);
 		}
 		}
 	}
 	}
-	
+
 	static function evalBinop<T,C>(op:Binop<C,T>, e1:Expr<C>, e2:Expr<C>):T {
 	static function evalBinop<T,C>(op:Binop<C,T>, e1:Expr<C>, e2:Expr<C>):T {
 		return switch(op) {
 		return switch(op) {
 			case OpAdd: eval(e1) + eval(e2);
 			case OpAdd: eval(e1) + eval(e2);
 			case OpEq: eval(e1) == eval(e2);
 			case OpEq: eval(e1) == eval(e2);
 		}
 		}
 	}
 	}
-	
+
 	static function eval<T>(e:Expr<T>):T {
 	static function eval<T>(e:Expr<T>):T {
 		return switch(e) {
 		return switch(e) {
 			case EConst(c): evalConst(c);
 			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");
 		var result = pattern.replace("$a","A").replace("$b","B");
 		eq("AB", result);
 		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 {
 enum Annotation {