Przeglądaj źródła

improve performance of string concatenation, reflect.field

frabbit 11 lat temu
rodzic
commit
bf4a7fc18c

+ 21 - 4
genpy.ml

@@ -1097,10 +1097,27 @@ module Printer = struct
 			| TBinop(OpUShr,e1,e2) ->
 				Printf.sprintf "HxOverrides.rshift(%s, %s)" (print_expr pctx e1) (print_expr pctx e2)
 			| TBinop(OpAdd,e1,e2) when (is_type1 "" "String")(e.etype) || is_underlying_string e.etype ->
-				let safe_string ex =
-					match ex.eexpr with
-						| TConst(TString _) -> print_expr pctx ex
-						| _ -> Printf.sprintf "Std.string(%s)" (print_expr pctx ex)
+				let follow_parens e = match e.eexpr with
+					| TParenthesis e -> e
+					| _ -> e
+				in
+				let rec is_safe_string x =
+					match (follow_parens x).eexpr with
+					| TBinop(OpAdd, e1, e2) -> is_safe_string e1 && is_safe_string e2
+					| TCall (e1,_) ->
+						let id = print_expr pctx (follow_parens e1) in
+						(match id with
+						| "Std.string" -> true
+						| _ -> false)
+					| TConst (TString s) -> true
+					| _ -> false
+				in
+				let rec safe_string ex =
+					match ex.eexpr, ex.etype with
+						| TBinop(OpAdd, e1, e2), _ -> Printf.sprintf "(%s + %s)" (safe_string e1) (safe_string e2)
+						| e, _ when is_safe_string ex -> print_expr pctx ex
+						| _,x when (is_type1 "" "String")(x) -> Printf.sprintf "HxOverrides.stringOrNull(%s)" (print_expr pctx ex)
+						| _,_ -> Printf.sprintf "Std.string(%s)" (print_expr pctx ex)
 				in
 				let e1_str = safe_string e1 in
 				let e2_str = safe_string e2 in

+ 7 - 3
std/python/Boot.hx

@@ -394,7 +394,6 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 
 		switch (field) {
 			case "length" if (isString(o)): return StringImpl.get_length(o);
-			case "length" if (isArray(o)): return ArrayImpl.get_length(o);
 			case "toLowerCase" if (isString(o)): return StringImpl.toLowerCase.bind(o);
 			case "toUpperCase" if (isString(o)): return StringImpl.toUpperCase.bind(o);
 			case "charAt" if (isString(o)): return StringImpl.charAt.bind(o);
@@ -405,7 +404,7 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 			case "substr" if (isString(o)): return StringImpl.substr.bind(o);
 			case "substring" if (isString(o)): return StringImpl.substring.bind(o);
 			case "toString" if (isString(o)): return StringImpl.toString.bind(o);
-
+			case "length" if (isArray(o)): return ArrayImpl.get_length(o);
 			case "map" if (isArray(o)): return ArrayImpl.map.bind(o);
 			case "filter" if (isArray(o)): return ArrayImpl.filter.bind(o);
 			case "concat" if (isArray(o)): return ArrayImpl.concat.bind(o);
@@ -427,6 +426,7 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 			case "splice" if (isArray(o)): return ArrayImpl.splice.bind(o);
 		}
 
+
 		var field = handleKeywords(field);
 		return if (builtinHasAttr(o, field)) builtinGetAttr(o, field) else null;
 	}
@@ -486,10 +486,14 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 
 
 
+	static inline function unsafeFastCodeAt (s, index) {
+		return HxBuiltin.ord(python.Syntax.arrayAccess(s, index));
+	}
+
 	static inline function handleKeywords(name:String):String {
 		return if (keywords.has(name)) {
 			Internal.getPrefixed(name);
-		} else if (name.length > 2 && name.substr(0,2) == "__" && name.charAt(name.length-1) != "_") {
+		} else if (name.length > 2 && unsafeFastCodeAt(name,0) == "_".code && unsafeFastCodeAt(name,1) == "_".code && unsafeFastCodeAt(name, name.length-1) != "_".code) {
 			Internal.getPrefixed(name);
 		}
 		else name;

+ 2 - 0
std/python/_std/Reflect.hx

@@ -150,6 +150,8 @@ class Reflect {
 		return o2;
 	}
 
+
+
 	@:overload(function( f : Array<Dynamic> -> Void ) : Dynamic {})
 	public static function makeVarArgs( f : Array<Dynamic> -> Dynamic ) : Dynamic {
 		return function (v:VarArgs) {

+ 4 - 0
std/python/internal/HxOverrides.hx

@@ -27,6 +27,10 @@ class HxOverrides {
 		return Syntax.binop(a, "==", b);
 	}
 
+	static function stringOrNull (s:String):String {
+		return if (s == null) "null" else s;
+	}
+
 	static public function shift(x) {
 		return Reflect.callMethod(null, Reflect.field(x, "shift"), []);
 	}

+ 11 - 7
std/python/internal/Internal.hx

@@ -29,10 +29,12 @@ class Internal {
 	static function _getPrefixed (x:Expr):Expr {
 		return switch (x.expr) {
 			case EConst(CString(x)): macro @:pos(Context.currentPos()) $v{_prefix + x};
-			case _ : macro @:pos(Context.currentPos()) $v{_prefix} + $x;
+			case _ : macro @:pos(Context.currentPos()) (python.Syntax.binop($v{_prefix},"+",$x):String);
 		}
 	}
 
+
+
 	static function withPos(x:String):Expr {
 		return macro @:pos(Context.currentPos()) $v{x};
 	}
@@ -47,6 +49,13 @@ class Internal {
 
 	#end
 
+	macro public static function getPrefixed (x:ExprOf<String>):Expr {
+		return switch (x.expr) {
+			case EConst(CString(x)): macro @:pos(Context.currentPos()) $v{_prefix + x};
+			case _ : macro @:pos(Context.currentPos()) (python.Syntax.binop($v{_prefix},"+",$x):String);
+		}
+	}
+
 	macro public static function classRegistry ():Expr {
 		return macro (python.Syntax.pythonCode($v{_classes}) : python.lib.Dict<String, Class<Dynamic>>);
 	}
@@ -66,12 +75,7 @@ class Internal {
 		return macro @:pos(Context.currentPos()) python.Syntax.field($a{args});
 	}
 
-	macro public static function getPrefixed (x:ExprOf<String>):Expr {
-		return switch (x.expr) {
-			case EConst(CString(x)): macro @:pos(Context.currentPos()) $v{_prefix + x};
-			case _ : macro @:pos(Context.currentPos()) $v{_prefix} + $x;
-		}
-	}
+
 
 	macro public static function importAsPrefixed (o:String, x:String) {
 		return macro @:pos(Context.currentPos()) python.Syntax.importAs($v{o}, $v{_prefix + x});