Browse Source

fixed closure comparison

Nicolas Cannasse 17 years ago
parent
commit
1257ee1da5
3 changed files with 20 additions and 21 deletions
  1. 2 8
      doc/CHANGES.txt
  2. 11 12
      genneko.ml
  3. 7 1
      std/Reflect.hx

+ 2 - 8
doc/CHANGES.txt

@@ -1,11 +1,3 @@
-TODO optimizer : optimizations and ast manipulation in a separate module
-TODO optimizer : when an object is only used localy, move its fields on the stack (allow inlined iterators)
-TODO optimizer : precompute constant expressions
-TODO optimizer : reduce expressions such as function()...() , [arr][0] or if(true) (for better inlining)
-TODO optimizer : move multiple statics access into local variables
-TODO inlining : allow inlined getter/setter
-TODO inlining : substitute class+function type parameters in order to have fully typed expressions
-
 2008-??-??: 2.01
 	fixed php.Sys
 	added neko.NativeString and neko.NativeArray
@@ -43,6 +35,8 @@ TODO inlining : substitute class+function type parameters in order to have fully
 	fixed memory leak with PHP closures
 	fixed wrong scope in PHP closures
 	fixed Array.reverse() in PHP
+	fixed Reflect.compareMethods in Neko (require Neko 1.8.0)
+
 2008-07-28: 2.0
 	fixed current package bug in inherited constructor type
 	delayed type-parameter constraints check (allow mutual rec extends for SPOD)

+ 11 - 12
genneko.ml

@@ -233,22 +233,15 @@ and gen_call ctx p e el =
 		let e = (match gen_expr ctx e with EFunction _, _ as e -> (EBlock [e],p) | e -> e) in
 		call p e (List.map (gen_expr ctx) el)
 
-and gen_closure p t e f =
+and gen_closure p ep t e f =
 	match follow t with
 	| TFun (args,_) ->
-		let n = ref 0 in
-		let args = List.map (fun _ -> incr n; "p" ^ string_of_int (!n)) args in
+		let n = List.length args in
+		if n > 5 then error "Cannot create closure with more than 5 arguments" ep;
 		let tmp = ident p "@tmp" in
-		let ifun = ident p "@fun" in
 		EBlock [
 			(EVars ["@tmp", Some e; "@fun", Some (field p tmp f)] , p);
-			(EIf ((EBinop ("==",ifun,null p),p),
-				null p,
-				Some (EFunction (args,(EBlock [
-					(EBinop ("=",this p,tmp),p);
-					(EReturn (Some (call p ifun (List.map (ident p) args))),p)
-				],p)),p)
-			),p)
+			call p (ident p ("@closure" ^ string_of_int n)) [tmp;ident p "@fun"]
 		] , p
 	| _ ->
 		field p e f
@@ -273,7 +266,7 @@ and gen_expr ctx e =
 	| TBinop (op,e1,e2) ->
 		gen_binop ctx p op e1 e2
 	| TField (e2,f) ->
-		gen_closure p e.etype (gen_expr ctx e2) f
+		gen_closure p e.epos e.etype (gen_expr ctx e2) f
 	| TTypeExpr t ->
 		gen_type_path p (t_path t)
 	| TParenthesis e ->
@@ -743,6 +736,12 @@ let generate com libs =
 		"@enum_to_string = function() { return neko.Boot.__enum_str(this); };" ^
 		"@serialize = function() { return neko.Boot.__serialize(this); };" ^
 		"@tag_serialize = function() { return neko.Boot.__tagserialize(this); };" ^
+		"@closure0 = function(@this,@fun) if( @fun == null ) null else function() { this = @this; @fun(); };" ^
+		"@closure1 = function(@this,@fun) if( @fun == null ) null else function(a) { this = @this; @fun(a); };" ^
+		"@closure2 = function(@this,@fun) if( @fun == null ) null else function(a,b) { this = @this; @fun(a,b); };" ^
+		"@closure3 = function(@this,@fun) if( @fun == null ) null else function(a,b,c) { this = @this; @fun(a,b,c); };" ^
+		"@closure4 = function(@this,@fun) if( @fun == null ) null else function(a,b,c,d) { this = @this; @fun(a,b,c,d); };" ^
+		"@closure5 = function(@this,@fun) if( @fun == null ) null else function(a,b,c,d,e) { this = @this; @fun(a,b,c,d,e); };" ^
 		generate_libs_init libs
 	) , { psource = "<header>"; pline = 1; } in
 	let packs = List.concat (List.map (gen_package ctx h) com.types) in

+ 7 - 1
std/Reflect.hx

@@ -223,12 +223,14 @@ class Reflect {
 		Does not work on Neko platform.
 	**/
 	public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool {
+		#if !neko
 		if( f1 == f2 )
 			return true;
 		if( !isFunction(f1) || !isFunction(f2) )
 			return false;
+		#end
 		#if neko
-			return false; // compare already done
+			return same_closure(f1,f2);
 		#elseif flash9
 			return false; // VM-level closures
 		#elseif flash
@@ -356,4 +358,8 @@ class Reflect {
 		#end
 	}
 
+	#if neko
+	static var same_closure = try neko.Lib.load("std","same_closure",2) catch( e : Dynamic ) function(f1,f2) return f1 == f2;
+	#end
+
 }