瀏覽代碼

fixed closure comparison

Nicolas Cannasse 17 年之前
父節點
當前提交
1257ee1da5
共有 3 個文件被更改,包括 20 次插入21 次删除
  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
 2008-??-??: 2.01
 	fixed php.Sys
 	fixed php.Sys
 	added neko.NativeString and neko.NativeArray
 	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 memory leak with PHP closures
 	fixed wrong scope in PHP closures
 	fixed wrong scope in PHP closures
 	fixed Array.reverse() in PHP
 	fixed Array.reverse() in PHP
+	fixed Reflect.compareMethods in Neko (require Neko 1.8.0)
+
 2008-07-28: 2.0
 2008-07-28: 2.0
 	fixed current package bug in inherited constructor type
 	fixed current package bug in inherited constructor type
 	delayed type-parameter constraints check (allow mutual rec extends for SPOD)
 	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
 		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)
 		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
 	match follow t with
 	| TFun (args,_) ->
 	| 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 tmp = ident p "@tmp" in
-		let ifun = ident p "@fun" in
 		EBlock [
 		EBlock [
 			(EVars ["@tmp", Some e; "@fun", Some (field p tmp f)] , p);
 			(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
 		] , p
 	| _ ->
 	| _ ->
 		field p e f
 		field p e f
@@ -273,7 +266,7 @@ and gen_expr ctx e =
 	| TBinop (op,e1,e2) ->
 	| TBinop (op,e1,e2) ->
 		gen_binop ctx p op e1 e2
 		gen_binop ctx p op e1 e2
 	| TField (e2,f) ->
 	| 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 ->
 	| TTypeExpr t ->
 		gen_type_path p (t_path t)
 		gen_type_path p (t_path t)
 	| TParenthesis e ->
 	| TParenthesis e ->
@@ -743,6 +736,12 @@ let generate com libs =
 		"@enum_to_string = function() { return neko.Boot.__enum_str(this); };" ^
 		"@enum_to_string = function() { return neko.Boot.__enum_str(this); };" ^
 		"@serialize = function() { return neko.Boot.__serialize(this); };" ^
 		"@serialize = function() { return neko.Boot.__serialize(this); };" ^
 		"@tag_serialize = function() { return neko.Boot.__tagserialize(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
 		generate_libs_init libs
 	) , { psource = "<header>"; pline = 1; } in
 	) , { psource = "<header>"; pline = 1; } in
 	let packs = List.concat (List.map (gen_package ctx h) com.types) 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.
 		Does not work on Neko platform.
 	**/
 	**/
 	public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool {
 	public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool {
+		#if !neko
 		if( f1 == f2 )
 		if( f1 == f2 )
 			return true;
 			return true;
 		if( !isFunction(f1) || !isFunction(f2) )
 		if( !isFunction(f1) || !isFunction(f2) )
 			return false;
 			return false;
+		#end
 		#if neko
 		#if neko
-			return false; // compare already done
+			return same_closure(f1,f2);
 		#elseif flash9
 		#elseif flash9
 			return false; // VM-level closures
 			return false; // VM-level closures
 		#elseif flash
 		#elseif flash
@@ -356,4 +358,8 @@ class Reflect {
 		#end
 		#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
+
 }
 }