Parcourir la source

[python] major work on improving generated python code cleanliness

- remove @:keeps, use feature-based keeping
- rework reflection info generation based on features
- introduce soft-keywords for builtin globals and use them instead of importing "builtins" (closes #3952)
- general cleanup and unused code removal
Dan Korostelev il y a 10 ans
Parent
commit
8d01ba9dd8

+ 212 - 97
genpy.ml

@@ -70,8 +70,16 @@ module KeywordHandler = struct
 		let h = Hashtbl.create 0 in
 		List.iter (fun s -> Hashtbl.add h s ()) [
 			"and"; "as"; "assert"; "break"; "class"; "continue"; "def"; "del"; "elif"; "else"; "except"; "exec"; "finally"; "for";
-			"from"; "global"; "if"; "import"; "in"; "is"; "lambda"; "not"; "or"; "pass"; "print";" raise"; "return"; "try"; "while";
-			"with"; "yield"; "float"; "None"; "list"; "True"; "False"
+			"from"; "global"; "if"; "import"; "in"; "is"; "lambda"; "not"; "or"; "pass"; " raise"; "return"; "try"; "while";
+			"with"; "yield"; "None"; "True"; "False";
+		];
+		h
+
+	let kwds2 =
+		let h = Hashtbl.create 0 in
+		List.iter (fun s -> Hashtbl.add h s ()) [
+			"len"; "int"; "float"; "list"; "bool"; "str"; "isinstance"; "print"; "min"; "max";
+			"hasattr"; "getattr"; "setattr"; "callable"; "type"; "ord"; "chr"; "iter"; "map"; "filter"
 		];
 		h
 
@@ -86,6 +94,9 @@ module KeywordHandler = struct
 		else if l > 2 && String.sub s 0 2 = "__" && String.sub s (l - 1) 1 <> "_" then
 			"_hx_" ^ s
 		else s
+
+	let check_var_declaration v =
+		if Hashtbl.mem kwds2 v.v_name then v.v_name <- "_hx_" ^ v.v_name
 end
 
 module Transformer = struct
@@ -101,7 +112,7 @@ module Transformer = struct
 	let t_void = ref t_dynamic
 	let t_string = ref t_dynamic
 	let t_int = ref t_dynamic
-	let c_reflect = ref null_class
+	let c_reflect = ref (fun () -> null_class)
 
 	let init com =
 		como := Some com;
@@ -109,13 +120,24 @@ module Transformer = struct
 		t_void := com.basic.tvoid;
 		t_string := com.basic.tstring;
 		t_int := com.basic.tint;
-		c_reflect := Utils.class_of_module_type (Utils.find_type com ([],"Reflect"))
+		c_reflect := fun () -> Utils.class_of_module_type (Utils.find_type com ([],"Reflect"))
 
 	and debug_expr e =
 		let s_type = Type.s_type (print_context()) in
 		let s = Type.s_expr_pretty "\t" s_type e in
 		Printf.printf "%s\n" s
 
+	and debug_expr_with_type e =
+		let s_type = Type.s_type (print_context()) in
+		let es = Type.s_expr_pretty "\t" s_type e in
+		let t = s_type e.etype in
+		Printf.printf "%s : %s\n" es t
+
+	and debug_type t =
+		let s_type = Type.s_type (print_context()) in
+		let t = s_type t in
+		Printf.printf "%s\n" t
+
 	let new_counter () =
 		let n = ref (-1) in
 		(fun () ->
@@ -152,7 +174,8 @@ module Transformer = struct
 		lift_expr ~is_value:is_value ~next_id:(Some next_id) ~blocks:blocks e
 
 	let to_tvar ?(capture = false) n t =
-		{ v_name = n; v_type = t; v_id = 0; v_capture = capture; v_extra = None; v_meta = [] }
+		alloc_var n t
+		(* { v_name = n; v_type = t; v_id = 0; v_capture = capture; v_extra = None; v_meta = [] } *)
 
 	let create_non_local n pos =
 		let s = "nonlocal " ^ (KeywordHandler.handle_keywords n) in
@@ -174,10 +197,10 @@ module Transformer = struct
 			e
 
 	let dynamic_field_read e s =
-		Utils.mk_static_call_2 !c_reflect "field" [e;mk (TConst (TString s)) !t_string e.epos] e.epos
+		Utils.mk_static_call_2 ((!c_reflect)()) "field" [e;mk (TConst (TString s)) !t_string e.epos] e.epos
 
 	let dynamic_field_write e1 s e2 =
-		Utils.mk_static_call_2 !c_reflect "setField" [e1;mk (TConst (TString s)) !t_string e1.epos;e2] e1.epos
+		Utils.mk_static_call_2 ((!c_reflect)()) "setField" [e1;mk (TConst (TString s)) !t_string e1.epos;e2] e1.epos
 
 	let dynamic_field_read_write next_id e1 s op e2 =
 		let id = next_id() in
@@ -310,11 +333,11 @@ module Transformer = struct
 				let size = List.length el in
 				let res = DynArray.create () in
 				ExtList.List.iteri (fun i e ->
-					(* this removes Builtin.len(x) calls which are reproduced by the inlined return
+					(* this removes len(x) calls which are reproduced by the inlined return
 					   of Array.push even if the value is not used *)
 					let is_removable_statement e = (not is_value || i < size-1) &&
 						match e.eexpr with
-						| TCall({ eexpr = TField(_, FStatic({cl_path = ["python";"internal"],"HxBuiltin"},{ cf_name = "len" }))}, [_]) -> true
+						| TField(_, FInstance({cl_path = [],"list"},_,{ cf_name = "length" })) -> true
 						| _ -> false
 					in
 					if not (is_removable_statement e) then
@@ -612,7 +635,9 @@ module Transformer = struct
 		| (is_value,TFunction(f)) ->
 			transform_function f ae is_value
 		| (_,TVar(v,None)) ->
+
 			transform_var_expr ae None v
+
  		| (false, TVar(v,Some({ eexpr = TUnop((Increment | Decrement as unop),post_fix,({eexpr = TLocal _ | TField({eexpr = TConst TThis},_)} as ve))} as e1))) ->
 			let one = {e1 with eexpr = TConst (TInt (Int32.of_int 1))} in
 			let op = if unop = Increment then OpAdd else OpSub in
@@ -941,14 +966,20 @@ module Printer = struct
 		pc_indent : string;
 		pc_next_anon_func : unit -> string;
 		pc_debug : bool;
+		pc_com : Common.context;
 	}
 
+	let has_feature pctx = Common.has_feature pctx.pc_com
+
+	let add_feature pctx = Common.add_feature pctx.pc_com
+
 	let create_context =
 		let n = ref (-1) in
-		(fun indent debug -> {
+		(fun indent com debug -> {
 				pc_indent = indent;
 				pc_next_anon_func = (fun () -> incr n; Printf.sprintf "anon_%i" !n);
 				pc_debug = debug;
+				pc_com = com;
 			}
 		)
 
@@ -1047,6 +1078,12 @@ module Printer = struct
 	let print_metadata (name,_,_) =
 		Printf.sprintf "@%s" name
 
+	let rec remove_outer_parens e = match e.eexpr with
+		| TParenthesis(e) -> remove_outer_parens e
+		| TMeta((Meta.Custom ":ternaryIf",_,_),_) -> e
+		| TMeta(_,e) -> remove_outer_parens e
+		| _ -> e
+
 	let print_args args p =
 		let had_value = ref false in
 		let had_var_args = ref false in
@@ -1080,7 +1117,7 @@ module Printer = struct
 			| TIf(econd,eif,Some eelse) ->
 				Printf.sprintf "%s if %s else %s" (print_expr pctx eif) (print_expr pctx econd) (print_expr pctx eelse)
 			| _ ->
-				print_expr pctx e
+				print_expr pctx (remove_outer_parens e)
 
 	and print_var pctx v eo =
 		match eo with
@@ -1111,11 +1148,11 @@ module Printer = struct
 			match e2.eexpr with
 			| TConst TInt index ->
 				if Int32.to_int index >= 0 then
-					Printf.sprintf "(%s[%s] if %s < python_lib_Builtin.len(%s) else None)" s1 s2 s2 s1
+					Printf.sprintf "(%s[%s] if %s < len(%s) else None)" s1 s2 s2 s1
 				else
 					"None"
 			| TLocal _ ->
-				Printf.sprintf "(%s[%s] if %s >= 0 and %s < python_lib_Builtin.len(%s) else None)" s1 s2 s2 s2 s1
+				Printf.sprintf "(%s[%s] if %s >= 0 and %s < len(%s) else None)" s1 s2 s2 s2 s1
 			| _ ->
 				default
 		in
@@ -1132,7 +1169,7 @@ module Printer = struct
 				print_constant ct
 			| TTypeExpr mt ->
 				print_module_type mt
-			| TLocal v ->
+			| (TLocal v | TParenthesis({ eexpr = (TLocal v) })) ->
 				handle_keywords v.v_name
 			| TEnumParameter(e1,_,index) ->
 				Printf.sprintf "%s.params[%i]" (print_expr pctx e1) index
@@ -1147,20 +1184,20 @@ module Printer = struct
 			| TBinop(OpAssign,{eexpr = TArray({etype = t} as e1,e2)},e3) when is_anon_or_dynamic t ->
 				Printf.sprintf "HxOverrides.arraySet(%s,%s,%s)" (print_expr pctx e1) (print_expr pctx e2) (print_expr pctx e3)
 			| TBinop(OpAssign,{eexpr = TArray(e1,e2)},e3) ->
-				Printf.sprintf "%s[%s] = %s" (print_expr pctx e1) (print_expr pctx e2) (print_expr pctx e3)
+				Printf.sprintf "%s[%s] = %s" (print_expr pctx e1) (print_expr pctx e2) (print_expr pctx (remove_outer_parens e3) )
 			| TBinop(OpAssign,{eexpr = TField(ef1,fa)},e2) ->
 				Printf.sprintf "%s = %s" (print_field pctx ef1 fa true) (print_op_assign_right pctx e2)
 			| TBinop(OpAssign,e1,e2) ->
-				Printf.sprintf "%s = %s" (print_expr pctx e1) (print_expr pctx e2)
+				Printf.sprintf "%s = %s" (print_expr pctx e1) (print_expr pctx (remove_outer_parens e2))
 			| TBinop(op,e1,({eexpr = TBinop(_,_,_)} as e2)) ->
 				print_expr pctx { e with eexpr = TBinop(op, e1, { e2 with eexpr = TParenthesis(e2) })}
 			| TBinop(OpEq,{eexpr = TCall({eexpr = TLocal {v_name = "__typeof__"}},[e1])},e2) ->
 				begin match e2.eexpr with
 					| TConst(TString s) ->
 						begin match s with
-							| "string" -> Printf.sprintf "Std._hx_is(%s, python_lib_Builtin.str)" (print_expr pctx e1)
-							| "boolean" -> Printf.sprintf "Std._hx_is(%s, python_lib_Builtin.bool)" (print_expr pctx e1)
-							| "number" -> Printf.sprintf "Std._hx_is(%s, python_lib_Builtin.float)" (print_expr pctx e1)
+							| "string" -> Printf.sprintf "Std._hx_is(%s, str)" (print_expr pctx e1)
+							| "boolean" -> Printf.sprintf "Std._hx_is(%s, bool)" (print_expr pctx e1)
+							| "number" -> Printf.sprintf "Std._hx_is(%s, float)" (print_expr pctx e1)
 							| _ -> assert false
 						end
 					| _ ->
@@ -1233,14 +1270,25 @@ module Printer = struct
 					match ex.eexpr, ex.etype with
 						| e, _ when is_safe_string ex -> print_expr pctx ex
 						| TBinop(OpAdd, e1, e2), x when (is_type1 "" "String")(x) -> Printf.sprintf "(%s + %s)" (safe_string e1) (safe_string e2)
+						| (TLocal(_)),x when (is_type1 "" "String")(x) ->
+							(*
+								we could add this pattern too, but is it sideeffect free??
+								| TField({ eexpr = TLocal(_)},_)
+							*)
+							let s = (print_expr pctx ex) in
+							Printf.sprintf "(\"null\" if %s is None else %s)" s s
 						| _,x when (is_type1 "" "String")(x) -> Printf.sprintf "HxOverrides.stringOrNull(%s)" (print_expr pctx ex)
-						| _,_ -> Printf.sprintf "Std.string(%s)" (print_expr pctx ex)
+						| _,_ ->
+							if has_feature pctx "Std.string" then
+								Printf.sprintf "Std.string(%s)" (print_expr pctx ex)
+							else
+								Printf.sprintf "str(%s)" (print_expr pctx ex)
 				in
 				let e1_str = safe_string e1 in
 				let e2_str = safe_string e2 in
 				Printf.sprintf "(%s + %s)" e1_str e2_str
 			| TBinop(OpAdd,e1,e2) when (match follow e.etype with TDynamic _ -> true | _ -> false) ->
-				Printf.sprintf "python_Boot._add_dynamic(%s,%s)" (print_expr pctx e1) (print_expr pctx e2);
+				Printf.sprintf "python_Boot._add_dynamic(%s,%s)" (print_expr pctx e1) (print_expr pctx e2)
 			| TBinop(op,e1,e2) ->
 				Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (print_binop op) (print_expr pctx e2)
 			| TField(e1,fa) ->
@@ -1272,6 +1320,7 @@ module Printer = struct
 			| TFunction tf ->
 				print_function pctx tf None e.epos
 			| TVar (v,eo) ->
+				KeywordHandler.check_var_declaration v;
 				print_var pctx v eo
 			| TBlock [] ->
 				Printf.sprintf "pass"
@@ -1358,12 +1407,14 @@ module Printer = struct
 		in
 		match fa with
 			(* we need to get rid of these cases in the transformer, how is this handled in js *)
-			| FInstance(c,_,{cf_name = "length" | "get_length"}) when (is_type "" "list")(TClassDecl c) ->
-				Printf.sprintf "python_lib_Builtin.len(%s)" (print_expr pctx e1)
+			| FInstance(c,_,{cf_name = "length"}) when (is_type "" "list")(TClassDecl c) ->
+				Printf.sprintf "len(%s)" (print_expr pctx e1)
 			| FInstance(c,_,{cf_name = "length"}) when (is_type "" "String")(TClassDecl c) ->
-				Printf.sprintf "python_lib_Builtin.len(%s)" (print_expr pctx e1)
+				Printf.sprintf "len(%s)" (print_expr pctx e1)
 			| FStatic(c,{cf_name = "fromCharCode"}) when (is_type "" "String")(TClassDecl c) ->
 				Printf.sprintf "HxString.fromCharCode"
+			| FStatic({cl_path = ["python";"internal"],"UBuiltins"},{cf_name = s}) ->
+				s
 			| FInstance _ | FStatic _ ->
 				do_default ()
 			| FAnon cf when is_assign && call_override(name) ->
@@ -1386,6 +1437,7 @@ module Printer = struct
 			| _ -> false
 		end in
 		let print_catch pctx i (v,e) =
+			KeywordHandler.check_var_declaration v;
 			let is_empty_expr = begin match e.eexpr with
 				| TBlock [] -> true
 				| _ -> false
@@ -1396,13 +1448,13 @@ module Printer = struct
 			let handle_base_type bt =
 				let t = print_base_type bt in
 				let print_type_check t_str =
-					Printf.sprintf "if python_lib_Builtin.isinstance(_hx_e1, %s):\n%s\t%s\t%s" t_str indent assign (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e)
+					Printf.sprintf "if isinstance(_hx_e1, %s):\n%s\t%s\t%s" t_str indent assign (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e)
 				in
 				let res = match t with
-				| "String" -> print_type_check "python_lib_Builtin.str"
-				| "Bool" -> print_type_check "python_lib_Builtin.bool"
-				| "Int" -> print_type_check "python_lib_Builtin.int"
-				| "Float" -> print_type_check "python_lib_Builtin.float"
+				| "String" -> print_type_check "str"
+				| "Bool" -> print_type_check "bool"
+				| "Int" -> print_type_check "int"
+				| "Float" -> print_type_check "float"
 				| t -> print_type_check t
 				in
 				if i > 0 then
@@ -1430,7 +1482,7 @@ module Printer = struct
 		let indent = pctx.pc_indent in
 		let print_expr_indented e = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e in
 		let try_str = Printf.sprintf "try:\n%s\t%s\n%s" indent (print_expr_indented e1) indent in
-		let except = Printf.sprintf "except Exception as _hx_e:\n%s\t_hx_e1 = _hx_e.val if python_lib_Builtin.isinstance(_hx_e, _HxException) else _hx_e\n%s\t" indent indent in
+		let except = Printf.sprintf "except Exception as _hx_e:\n%s\t_hx_e1 = _hx_e.val if isinstance(_hx_e, _HxException) else _hx_e\n%s\t" indent indent in
 		let catch_str = String.concat (Printf.sprintf "\n") (ExtList.List.mapi (fun i catch -> print_catch {pctx with pc_indent = "\t" ^ pctx.pc_indent} i catch) catches) in
 		let except_end = if not has_catch_all then Printf.sprintf "\n%s\telse:\n%s\t\traise _hx_e" indent indent else "" in
 		Printf.sprintf "%s%s%s%s" try_str except catch_str except_end
@@ -1438,6 +1490,8 @@ module Printer = struct
 	and print_call2 pctx e1 el =
 		let id = print_expr pctx e1 in
 		match id,el with
+			| "__define_feature__",[_;e] ->
+				print_expr pctx e
 			| "super",_ ->
 				let s_el = print_exprs pctx ", " el in
 				Printf.sprintf "super().__init__(%s)" s_el
@@ -1525,6 +1579,12 @@ module Printer = struct
 
 	and print_call pctx e1 el =
 		match e1.eexpr, el with
+			| TLocal { v_name = "`trace" }, [e;infos] ->
+				if has_feature pctx "haxe.Log.trace" then begin
+					"haxe_Log.trace(" ^ (print_expr pctx e) ^ "," ^ (print_expr pctx infos) ^ ")"
+				end else begin
+					"print(str(" ^ (print_expr pctx e) ^ "))"
+				end
 			| TField(e1,((FAnon {cf_name = (("join" | "push" | "map" | "filter") as s)}) | FDynamic (("join" | "push" | "map" | "filter") as s))), [x] ->
 				Printf.sprintf "HxOverrides.%s(%s, %s)" s (print_expr pctx e1) (print_expr pctx x)
 			| TField(e1,((FAnon {cf_name = (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s)}) | FDynamic (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s))), [] ->
@@ -1595,6 +1655,9 @@ module Generator = struct
 		print_time : float;
 	}
 
+	let has_feature ctx = Common.has_feature ctx.com
+	let add_feature ctx = Common.add_feature ctx.com
+
 	type class_field_infos = {
 		cfd_fields : string list;
 		cfd_props : string list;
@@ -1732,7 +1795,7 @@ module Generator = struct
 		) metas
 
 	let gen_expr ctx e field indent =
-		let pctx = Printer.create_context ("\t" ^ indent) ctx.com.debug in
+		let pctx = Printer.create_context ("\t" ^ indent) ctx.com ctx.com.debug in
 		let e = match e.eexpr with
 			| TFunction(f) ->
 				{e with eexpr = TBlock [e]}
@@ -1773,7 +1836,7 @@ module Generator = struct
 					print ctx "%s%s = %s" indent field expr_string_2
 
 	let gen_func_expr ctx e c name metas extra_args indent stat p =
-		let pctx = Printer.create_context indent ctx.com.debug in
+		let pctx = Printer.create_context indent ctx.com ctx.com.debug in
 		let e = match e.eexpr with
 			| TFunction(f) ->
 				let args = List.map (fun s ->
@@ -1837,51 +1900,27 @@ module Generator = struct
 				end
 		end
 
-	let gen_class_register ctx c cfd p_super p_interfaces p p_name =
-		print ctx "@_hx_classes.registerClass(\"%s\"" p_name;
-
-		let add_names_arg lst arg_name =
-			match lst with
-			| [] -> ()
-			| l ->
-				let s = String.concat "," (List.map (fun s -> "\"" ^ s ^ "\"") l) in
-				print ctx ", %s=[%s]" arg_name s
-		in
-
-		add_names_arg cfd.cfd_fields "fields";
-		add_names_arg cfd.cfd_props "props";
-		add_names_arg cfd.cfd_methods "methods";
-		(* TODO: It seems strange to have a separation for member fields but a plain _hx_statics for static ones *)
-		add_names_arg (collect_class_statics_data c.cl_ordered_statics) "statics";
-
-		(match p_interfaces with
-		| [] -> ()
-		| l -> print ctx ", interfaces=[%s]" (String.concat "," p_interfaces)
-		);
-
-		(match p_super with
-		| None -> ()
-		| Some ps -> print ctx ", superClass=%s" ps);
-
-		print ctx ")\n"
-
 	let gen_class_empty_constructor ctx p cfl =
-		newline ctx;
-		newline ctx;
-		print ctx "\t@staticmethod\n\tdef _hx_empty_init(_hx_o):";
-		let found_fields = ref false in
-		List.iter (fun cf -> match cf.cf_kind with
-				| Var ({v_read = AccResolve | AccCall}) ->
-					()
-				| Var _ ->
-					found_fields := true;
-					newline ctx;
-					print ctx "\t\t_hx_o.%s = None" (handle_keywords cf.cf_name)
-				| _ ->
-					()
-		) cfl;
-		if not !found_fields then
-			spr ctx "\t\tpass"
+		if has_feature ctx "Type.createEmptyInstance" then begin
+			newline ctx;
+			newline ctx;
+			print ctx "\t@staticmethod\n\tdef _hx_empty_init(_hx_o):";
+			let found_fields = ref false in
+			List.iter (fun cf -> match cf.cf_kind with
+					| Var ({v_read = AccResolve | AccCall}) ->
+						()
+					| Var _ ->
+						found_fields := true;
+						newline ctx;
+						print ctx "\t\t_hx_o.%s = None" (handle_keywords cf.cf_name)
+					| _ ->
+						()
+			) cfl;
+			if not !found_fields then
+				spr ctx "\t\tpass"
+		end else begin
+			newline ctx
+		end
 
 	let gen_class_statics ctx c p =
 		let methods, other = List.partition (fun cf ->
@@ -1926,10 +1965,14 @@ module Generator = struct
 			| None ->
 				()
 			| Some e ->
-				let f = fun () ->
+				let is_math = c.cl_path = ([], "Math") in
+				let math_feature = has_feature ctx "Math" in
+				let f = if is_math && not math_feature then
+					fun () -> ()
+				else fun () ->
 					let e = transform_expr e in
 					newline ctx;
-					spr ctx (texpr_str e (Printer.create_context "" ctx.com.debug));
+					spr ctx (texpr_str e (Printer.create_context "" ctx.com ctx.com.debug));
 				in
 				ctx.class_inits <- f :: ctx.class_inits
 
@@ -1990,6 +2033,7 @@ module Generator = struct
 		if not c.cl_extern then begin
 			newline ctx;
 			newline ctx;
+			let is_nativegen = Meta.has Meta.NativeGen c.cl_meta in
 			let mt = (t_infos (TClassDecl c)) in
 			let p = get_path mt in
 			let p_name = get_full_name mt in
@@ -2005,11 +2049,40 @@ module Generator = struct
 			) c.cl_implements in
 
 			newline ctx;
-			if not (Meta.has Meta.NativeGen c.cl_meta) then
-				gen_class_register ctx c x p_super p_interfaces p p_name;
 			print ctx "class %s" p;
 			(match p_super with Some p -> print ctx "(%s)" p | _ -> ());
-			spr ctx ":";
+			spr ctx ":\n";
+
+			if not is_nativegen then begin
+				if has_feature ctx "python._hx_class_name" then print ctx "\t_hx_class_name = \"%s\"\n" p_name;
+
+				let print_field names field quote =
+					if has_feature ctx ("python." ^ field) then try
+						let q s = if quote then "\"" ^ s ^ "\"" else s in
+						let s = match names with
+							| [] when (match c.cl_super with Some _ -> false | _ -> true) ->
+								(* always overwrite parent's class fields *)
+								raise Exit
+							| _ ->
+								"[" ^ (String.concat ", " (List.map q names)) ^ "]"
+						in
+						print ctx "\t%s = %s\n" field s
+					with Exit -> ()
+				in
+
+				print_field x.cfd_fields "_hx_fields" true;
+				print_field x.cfd_methods "_hx_methods" true;
+				(* TODO: It seems strange to have a separation for member fields but a plain _hx_statics for static ones *)
+				print_field (collect_class_statics_data c.cl_ordered_statics) "_hx_statics" true;
+				print_field (p_interfaces) "_hx_interfaces" false;
+
+				if has_feature ctx "python._hx_super" then (match p_super with
+					| None -> ()
+					| Some ps -> print ctx "\t_hx_super = %s\n" ps
+				);
+
+			end;
+
 			begin match c.cl_constructor with
 				| Some cf -> gen_class_constructor ctx c cf;
 				| None -> ()
@@ -2024,7 +2097,7 @@ module Generator = struct
 					false
 				| _ ->
 					gen_class_empty_constructor ctx p c.cl_ordered_fields;
-					true
+					has_feature ctx "Type.createEmptyInstance"
 			in
 
 			let use_pass = (not has_inner_static) && (not has_empty_constructor) && match x.cfd_methods with
@@ -2034,6 +2107,11 @@ module Generator = struct
 			if use_pass then begin
 				newline ctx;
 				spr ctx "\tpass";
+			end;
+
+			if not is_nativegen then begin
+				if has_feature ctx "python._hx_class" then print ctx "\n%s._hx_class = %s" p p;
+				if has_feature ctx "python._hx_classes" then print ctx "\n_hx_classes[\"%s\"] = %s" p_name p;
 			end
 		end;
 		gen_class_init ctx c
@@ -2056,14 +2134,19 @@ module Generator = struct
 		let enum_constructs = PMap.foldi (fun k ef acc -> ef :: acc) en.e_constrs [] in
 		let enum_constructs = List.sort (fun a b -> if a.ef_index < b.ef_index then -1 else if a.ef_index > b.ef_index then 1 else 0) enum_constructs in
 
-		let fix = match enum_constructs with [] -> "" | _ -> "\"" in
-		let enum_constructs_str = fix ^ (String.concat ("\",\"") (List.map (fun ef -> ef.ef_name) enum_constructs)) ^ fix in
-
 		newline ctx;
 		newline ctx;
-		print ctx "@_hx_classes.registerEnum(\"%s\", [%s])\n" p_name enum_constructs_str;
 		print ctx "class %s(Enum):\n" p;
-		spr ctx "\tdef __init__(self, t, i, p):\n";
+
+		if has_feature ctx "python._hx_class_name" then print ctx "\t_hx_class_name = \"%s\"\n" p_name;
+		if has_feature ctx "python._hx_constructs" then begin
+			let fix = match enum_constructs with [] -> "" | _ -> "\"" in
+			let enum_constructs_str = fix ^ (String.concat ("\", \"") (List.map (fun ef -> ef.ef_name) enum_constructs)) ^ fix in
+			print ctx "\t_hx_constructs = [%s]" enum_constructs_str;
+		end;
+
+
+		spr ctx "\n\tdef __init__(self, t, i, p):\n";
 		print ctx "\t\tsuper(%s,self).__init__(t, i, p)" p;
 
 		let const_constructors,param_constructors = List.partition (fun ef ->
@@ -2108,6 +2191,9 @@ module Generator = struct
 			print ctx "%s.%s = %s(\"%s\", %i, list())" p f p ef.ef_name ef.ef_index
 		) const_constructors;
 
+		if has_feature ctx "python._hx_class" then print ctx "\n%s._hx_class = %s" p p;
+		if has_feature ctx "python._hx_classes" then print ctx "\n_hx_classes[\"%s\"] = %s" p_name p;
+
 		gen_enum_metadata ctx en p
 
 	let gen_abstract ctx a =
@@ -2119,10 +2205,11 @@ module Generator = struct
 		let mt = (t_infos (TAbstractDecl a)) in
 		let p = get_path mt in
 		let p_name = get_full_name mt in
-		print ctx "@_hx_classes.registerAbstract(\"%s\")\n" p_name;
-		print ctx "class %s" p;
-		spr ctx ":";
-		match a.a_impl with
+		print ctx "class %s:\n" p;
+
+		if has_feature ctx "python._hx_class_name" then print ctx "\t_hx_class_name = \"%s\"\n" p_name;
+
+		(match a.a_impl with
 		| Some c ->
 			List.iter (fun cf ->
 				if cf.cf_name = "_new" then
@@ -2131,12 +2218,25 @@ module Generator = struct
 					gen_class_field ctx c p cf
 			) c.cl_ordered_statics
 		| None ->
-			spr ctx "\n\tpass"
+			spr ctx "\n\tpass");
+
+		if has_feature ctx "python._hx_class" then print ctx "\n%s._hx_class = %s" p p;
+		if has_feature ctx "python._hx_classes" then print ctx "\n_hx_classes[\"%s\"] = %s" p_name p
+
 
 	let gen_type ctx mt = match mt with
 		| TClassDecl c -> gen_class ctx c
 		| TEnumDecl en when not en.e_extern -> gen_enum ctx en
 		| TAbstractDecl {a_path = [],"UInt"} -> ()
+		| TAbstractDecl {a_path = [],"Enum"} -> ()
+		| TAbstractDecl {a_path = [],"EnumValue"} when not (has_feature ctx "has_enum") -> ()
+		| TAbstractDecl {a_path = [],"Void"} -> ()
+		| TAbstractDecl {a_path = [],"Int"} when not (has_feature ctx "Int.*") -> ()
+		| TAbstractDecl {a_path = [],"Float"} when not (has_feature ctx "Float.*") -> ()
+		| TAbstractDecl {a_path = [],"Class"} when not (has_feature ctx "Class.*") -> ()
+		| TAbstractDecl {a_path = [],"Dynamic"} when not (has_feature ctx "Dynamic.*") -> ()
+		| TAbstractDecl {a_path = [],"Bool"} when not (has_feature ctx "Bool.*") -> ()
+
 		| TAbstractDecl a when Meta.has Meta.CoreType a.a_meta -> gen_abstract ctx a
 		| _ -> ()
 
@@ -2186,11 +2286,25 @@ module Generator = struct
 			Hashtbl.add used_paths path true;
 			Utils.find_type ctx.com path
 		in
-		gen_type ctx (find_type ([],"_hx_ClassRegistry"));
-		gen_type ctx (find_type ([],"_hx_AnonObject"));
-		gen_type ctx (find_type (["python"],"Boot"));
-		gen_type ctx (find_type ([],"Enum"));
-		gen_type ctx (find_type ([],"HxOverrides"));
+		let need_anon_for_trace = (has_feature ctx "has_anon_trace") && (has_feature ctx "haxe.Log.trace") in
+		if (has_feature ctx "has_anon") || (has_feature ctx "_hx_AnonObject") || need_anon_for_trace then begin
+			let with_body = (has_feature ctx "has_anon") || need_anon_for_trace in
+			spr ctx "\n\nclass _hx_AnonObject:\n";
+			if with_body then begin
+				spr ctx "\tdef __init__(self,fields):\n";
+				spr ctx "\t\tself.__dict__ = fields"
+			end else
+				spr ctx "\tpass";
+			Hashtbl.add used_paths ([],"_hx_AnonObject") true;
+		end;
+		if has_feature ctx "python._hx_classes" then
+			spr ctx "\n\n_hx_classes = {}";
+		if has_feature ctx "Boot.*" then
+			gen_type ctx (find_type (["python"],"Boot"));
+		if has_feature ctx "has_enum" || has_feature ctx "Enum.*" then
+			gen_type ctx (find_type ([],"Enum"));
+		if has_feature ctx "HxOverrides.*" then
+			gen_type ctx (find_type ([],"HxOverrides"));
 		List.iter (fun mt ->
 			if not (Hashtbl.mem used_paths (t_infos mt).mt_path) then
 				gen_type ctx mt
@@ -2218,6 +2332,7 @@ module Generator = struct
 		gen_imports ctx;
 		gen_resources ctx;
 		gen_types ctx;
+		newline ctx;
 		gen_class_inits ctx;
 		gen_static_inits ctx;
 		gen_main ctx;

+ 1 - 1
std/StringTools.hx

@@ -396,7 +396,7 @@ class StringTools {
 		#elseif js
 		return (untyped s).charCodeAt(index);
 		#elseif python
-		return if (index >= s.length) -1 else python.lib.Builtin.ord(python.Syntax.arrayAccess(s, index));
+		return if (index >= s.length) -1 else python.internal.UBuiltins.ord(python.Syntax.arrayAccess(s, index));
 		#else
 		return untyped s.cca(index);
 		#end

+ 63 - 124
std/python/Boot.hx

@@ -28,113 +28,43 @@ import python.internal.EnumImpl;
 import python.internal.HxOverrides;
 import python.internal.HxException;
 import python.internal.AnonObject;
-import python.lib.Builtin;
+import python.internal.UBuiltins;
 import python.lib.Inspect;
 import python.lib.Set;
 
 import python.Syntax;
 
-typedef HxClassBase = {
-    _hx_class:Dynamic,
-    _hx_class_name:String
-}
-
-private typedef HxAbstract = {
-    >HxClassBase,
-}
-
-private typedef HxEnum = {
-    >HxClassBase,
-    _hx_constructs:Array<String>
-}
-
-private typedef HxClass = {
-    >HxClassBase,
-    _hx_fields:Array<String>,
-    _hx_props:Array<String>,
-    _hx_methods:Array<String>,
-    _hx_statics:Array<String>,
-    _hx_interfaces:Array<HxClassBase>,
-    _hx_super:HxClass
-}
-
-@:keep
-@:nativeGen
-@:native("_hx_ClassRegistry")
-private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
-    function _register(cls:HxClassBase, name:String):Void {
-        cls._hx_class = cls;
-        cls._hx_class_name = name;
-        set(name, cls);
-    }
-
-    function registerAbstract(name:String):HxAbstract->HxAbstract {
-        function wrapper(cls:HxAbstract):HxAbstract {
-            _register(cls, name);
-            return cls;
-        }
-        return wrapper;
-    }
-
-    function registerEnum(name:String, constructs:Array<String>):HxEnum->HxEnum {
-        function wrapper(cls:HxEnum):HxEnum {
-            _register(cls, name);
-            cls._hx_constructs = constructs;
-            return cls;
-        }
-        return wrapper;
-    }
-
-    function registerClass(name:String, ?fields:Array<String>, ?props:Array<String>, ?methods:Array<String>, ?statics:Array<String>, ?interfaces:Array<HxClassBase>, ?superClass:HxClass):HxClass->HxClass {
-        if (fields == null) fields = [];
-        if (props == null) props = [];
-        if (methods == null) methods = [];
-        if (statics == null) statics = [];
-        if (interfaces == null) interfaces = [];
-        function wrapper(cls:HxClass):HxClass {
-            _register(cls, name);
-            cls._hx_fields = fields;
-            cls._hx_props = props;
-            cls._hx_methods = methods;
-            cls._hx_statics = statics;
-            cls._hx_interfaces = interfaces;
-            if (superClass != null)
-                cls._hx_super = superClass;
-            return cls;
-        }
-        return wrapper;
-    }
-}
-
-@:preCode("_hx_classes = _hx_ClassRegistry()")
-@:keep class Boot {
+class Boot {
 
 	static var keywords:Set<String> = new Set(
 	[
-		"and",      "del",      "from",     "not",      "while",
-		"as",       "elif",     "global",   "or",       "with",
-		"assert",   "else",     "if",       "pass",     "yield",
-		"break",    "except",   "import",   "print",    "float",
-		"class",    "exec",     "in",       "raise",
-		"continue", "finally",  "is",       "return",
-		"def",      "for",      "lambda",   "try",
-		"None",     "list",     "True",     "False"
+		"and",      "del",      "from",     "not",      "with",
+		"as",       "elif",     "global",   "or",       "yield",
+		"assert",   "else",     "if",       "pass",     "None",
+		"break",    "except",   "import",   "raise",    "True",
+		"class",    "exec",     "in",       "return",   "False",
+		"continue", "finally",  "is",       "try",
+		"def",      "for",      "lambda",   "while",
 	]);
 
 	inline static function arrayJoin <T>(x:Array<T>, sep:String):String {
 		return Syntax.field(sep, "join")(Syntax.pythonCode("[{0}(x1,'') for x1 in {1}]", python.Boot.toString1, x));
 	}
 
+	inline static function safeJoin (x:Array<String>, sep:String):String {
+		return Syntax.field(sep, "join")(Syntax.pythonCode("[x1 for x1 in {0}]", x));
+	}
+
 	inline static function isPyBool(o:Dynamic):Bool {
-		return Builtin.isinstance(o, Builtin.bool);
+		return UBuiltins.isinstance(o, UBuiltins.bool);
 	}
 
 	inline static function isPyInt(o:Dynamic):Bool {
-		return Builtin.isinstance(o, Builtin.int);
+		return UBuiltins.isinstance(o, UBuiltins.int);
 	}
 
 	inline static function isPyFloat(o:Dynamic):Bool {
-		return Builtin.isinstance(o, Builtin.float);
+		return UBuiltins.isinstance(o, UBuiltins.float);
 	}
 
 	static inline function isClass(o:Dynamic) : Bool {
@@ -142,11 +72,14 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 	}
 
 	static inline function isAnonObject(o:Dynamic) {
-		return Builtin.isinstance(o, AnonObject);
+		return UBuiltins.isinstance(o, AnonObject);
 	}
 
-	private static function _add_dynamic(a:Dynamic,b:Dynamic):Dynamic {
-		if (Builtin.isinstance(a, String) || Builtin.isinstance(b, String)) {
+	@:ifFeature("add_dynamic") private static function _add_dynamic(a:Dynamic,b:Dynamic):Dynamic {
+		if (UBuiltins.isinstance(a, String) && UBuiltins.isinstance(b, String)) {
+			return Syntax.binop(a, "+", b);
+		}
+		if (UBuiltins.isinstance(a, String) || UBuiltins.isinstance(b, String)) {
 			return Syntax.binop(toString1(a,""), "+", toString1(b,""));
 		}
 		return Syntax.binop(a, "+", b);
@@ -169,24 +102,25 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 			if ((o:Bool)) return "true" else return "false";
 		}
 		if (isPyInt(o)) {
-			return Builtin.str(o);
+			return UBuiltins.str(o);
 		}
 		// 1.0 should be printed as 1
 		if (isPyFloat(o)) {
 			try {
-				if ( (o:Float) == Builtin.int(o)) {
-					return Builtin.str(Math.round(o));
+				if ( (o:Float) == UBuiltins.int(o)) {
+					return UBuiltins.str(Math.round(o));
 				} else {
-					return Builtin.str(o);
+					return UBuiltins.str(o);
 				}
 			} catch (e:Dynamic) {
-				return Builtin.str(o);
+				return UBuiltins.str(o);
 			}
 		}
 
 		if (isArray(o))
 		{
 			var o1:Array<Dynamic> = o;
+
 			var l = o1.length;
 
 			var st = "[";
@@ -203,14 +137,14 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 		}
 
 		try {
-			if (Builtin.hasattr(o, "toString"))
+			if (UBuiltins.hasattr(o, "toString"))
 				return Syntax.callField(o, "toString");
 		} catch (e:Dynamic) {
 		}
 
 		if (Inspect.isfunction(o) || Inspect.ismethod(o)) return "<function>";
 
-		if (Builtin.hasattr(o, "__class__"))
+		if (UBuiltins.hasattr(o, "__class__"))
 		{
 
 			if (isAnonObject(o))
@@ -219,8 +153,8 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 				try
 				{
 					var fields = fields(o);
-					var fieldsStr = [for (f in fields) '$f : ${toString1(field(o,f), s+"\t")}'];
-					toStr = "{ " + arrayJoin(fieldsStr, ", ") + " }";
+					var fieldsStr = [for (f in fields) '$f : ${toString1(simpleField(o,f), s+"\t")}'];
+					toStr = "{ " + safeJoin(fieldsStr, ", ") + " }";
 				}
 				catch (e:Dynamic) {
 					return "{ ... }";
@@ -236,11 +170,11 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 				}
 
 			}
-			if (Builtin.isinstance(o, Enum)) {
+			if (UBuiltins.isinstance(o, Enum)) {
 
-				var o:EnumImpl = o;
+				var o:EnumImpl = (o:EnumImpl);
 
-				var l = Builtin.len(o.params);
+				var l = UBuiltins.len(o.params);
 				var hasParams = l > 0;
 				if (hasParams) {
 					var paramsStr = "";
@@ -260,14 +194,14 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 			if (Internal.hasClassName(o)) {
 				if (Syntax.field(Syntax.field(o, "__class__"), "__name__") != "type") {
 					var fields = getInstanceFields(o);
-					var fieldsStr = [for (f in fields) '$f : ${toString1(field(o,f), s+"\t")}'];
+					var fieldsStr = [for (f in fields) '$f : ${toString1(simpleField(o,f), s+"\t")}'];
 
-					var toStr = Internal.fieldClassName(o) + "( " + arrayJoin(fieldsStr, ", ") + " )";
+					var toStr = (Internal.fieldClassName(o):String) + "( " + safeJoin(fieldsStr, ", ") + " )";
 					return toStr;
 				} else {
 					var fields = getClassFields(o);
-					var fieldsStr = [for (f in fields) '$f : ${toString1(field(o,f), s+"\t")}'];
-					var toStr = "#" + Internal.fieldClassName(o) + "( " + arrayJoin(fieldsStr, ", ") + " )";
+					var fieldsStr = [for (f in fields) '$f : ${toString1(simpleField(o,f), s+"\t")}'];
+					var toStr = "#" + (Internal.fieldClassName(o):String) + "( " + safeJoin(fieldsStr, ", ") + " )";
 					return toStr;
 				}
 			}
@@ -280,25 +214,25 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 				return "#Array";
 			}
 
-			if (Builtin.callable(o)) {
+			if (UBuiltins.callable(o)) {
 				return "function";
 			}
 			try {
-				if (Builtin.hasattr(o, "__repr__")) {
+				if (UBuiltins.hasattr(o, "__repr__")) {
 					return Syntax.callField(o, "__repr__");
 				}
 			} catch (e:Dynamic) {}
 
-			if (Builtin.hasattr(o, "__str__")) {
+			if (UBuiltins.hasattr(o, "__str__")) {
 				return Syntax.callField(o, "__str__", []);
 			}
 
-			if (Builtin.hasattr(o, "__name__")) {
+			if (UBuiltins.hasattr(o, "__name__")) {
 				return Syntax.field(o, "__name__");
 			}
 			return "???";
 		} else {
-			return Builtin.str(o);
+			return UBuiltins.str(o);
 		}
 	}
 
@@ -323,7 +257,7 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 				Syntax.pythonCode("for k in keys:");
 				Syntax.pythonCode("	a.append(handler(k))");
 			}
-			else if (Builtin.hasattr(o, "__dict__")) {
+			else if (UBuiltins.hasattr(o, "__dict__")) {
 				var a = [];
 				var d = Syntax.field(o, "__dict__");
 				var keys1  = Syntax.callField(d, "keys");
@@ -336,11 +270,18 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 	}
 
 	static inline function isString (o:Dynamic):Bool {
-		return Builtin.isinstance(o, Builtin.str);
+		return UBuiltins.isinstance(o, UBuiltins.str);
 	}
 
 	static inline function isArray (o:Dynamic):Bool {
-		return Builtin.isinstance(o, Builtin.list);
+		return UBuiltins.isinstance(o, UBuiltins.list);
+	}
+
+	static function simpleField( o : Dynamic, field : String ) : Dynamic {
+		if (field == null) return null;
+
+		var field = handleKeywords(field);
+		return if (UBuiltins.hasattr(o, field)) UBuiltins.getattr(o, field) else null;
 	}
 
 	static function field( o : Dynamic, field : String ) : Dynamic {
@@ -382,29 +323,27 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 
 
 		var field = handleKeywords(field);
-		return if (Builtin.hasattr(o, field)) Builtin.getattr(o, field) else null;
+		return if (UBuiltins.hasattr(o, field)) UBuiltins.getattr(o, field) else null;
 	}
 
 
 	static function getInstanceFields( c : Class<Dynamic> ) : Array<String> {
-		var f = if (Internal.hasFields(c)) {
-			var x:Array<String> = Internal.fieldFields(c);
-			var x2:Array<String> = Internal.fieldMethods(c);
-			x.concat(x2);
-		} else {
-			[];
-		}
+		var f = if (Internal.hasFields(c)) Internal.fieldFields(c) else [];
+		if (Internal.hasMethods(c))
+			f = f.concat(Internal.fieldMethods(c));
 
 		var sc = getSuperClass(c);
 
 		if (sc == null) {
 			return f;
 		} else {
+
 			var scArr = getInstanceFields(sc);
-			var scMap = [for (f in scArr) f => f];
+			var scMap = new Set(scArr);
+			//var scMap = [for (f in scArr) f => f];
 			var res = [];
 			for (f1 in f) {
-				if (!scMap.exists(f1)) {
+				if (!scMap.has(f1)) {
 					scArr.push(f1);
 				}
 			}
@@ -441,7 +380,7 @@ private class ClassRegistry extends python.lib.Dict<String, HxClassBase> {
 
 
 	static inline function unsafeFastCodeAt (s, index) {
-		return Builtin.ord(python.Syntax.arrayAccess(s, index));
+		return UBuiltins.ord(python.Syntax.arrayAccess(s, index));
 	}
 
 	static inline function handleKeywords(name:String):String {

+ 4 - 2
std/python/Lib.hx

@@ -54,8 +54,9 @@ class Lib {
 	/**
 	 	Returns a flat copy of the underlying Dictionary of `o`.
 	**/
+	@:access(python.Boot.isAnonObject)
 	public static function anonToDict (o:{}):Dict<String, Dynamic> {
-		return if (python.lib.Builtin.isinstance(o, AnonObject))
+		return if (Boot.isAnonObject(o))
 		{
 			(Syntax.field(o, "__dict__"):Dict<String,Dynamic>).copy();
 		}
@@ -67,8 +68,9 @@ class Lib {
 	 	Returns the underlying Dictionary of the anonymous object `o`.
 	 	Modifications to this dictionary are reflected in the anonymous Object too.
 	**/
+	@:access(python.Boot.isAnonObject)
 	public static function anonAsDict (o:{}):Dict<String, Dynamic> {
-		return if (python.lib.Builtin.isinstance(o, AnonObject))
+		return if (Boot.isAnonObject(o))
 		{
 			(Syntax.field(o, "__dict__"):Dict<String,Dynamic>);
 		}

+ 1 - 1
std/python/NativeIterable.hx

@@ -45,5 +45,5 @@ abstract NativeIterable<T>(NativeIterableRaw<T>) to NativeIterableRaw<T> from Na
     Native python iterable protocol.
 **/
 typedef NativeIterableRaw<T> = {
-	function __iter__():NativeIterator<T>;
+	private function __iter__():NativeIterator<T>;
 }

+ 1 - 1
std/python/NativeStringTools.hx

@@ -31,7 +31,7 @@ class NativeStringTools {
 		return python.Syntax.field(s, "format")(python.Syntax.varArgs(args));
 	}
 
-	@:keep public static inline function encode(s:String, encoding:String="utf-8", errors:String="strict"):Bytes {
+	public static inline function encode(s:String, encoding:String="utf-8", errors:String="strict"):Bytes {
 		return (python.Syntax.callField(s, "encode", encoding, errors):Bytes);
 	}
 

+ 1 - 1
std/python/VarArgs.hx

@@ -21,7 +21,7 @@
  */
 package python;
 
-import python.lib.Builtin.list;
+import python.internal.UBuiltins.list;
 
 /**
 	This type represents python `*args` feature, supporting

+ 1 - 4
std/python/_std/Array.hx

@@ -26,16 +26,13 @@ import python.NativeIterator;
 
 @:native("list")
 @:coreApi
-extern class Array<T> implements ArrayAccess<T> extends ArrayImpl {
+extern class Array<T> implements ArrayAccess<T> {
 
 	public var length(default,null) : Int;
 
-	private inline function get_length ():Int return ArrayImpl.get_length(this);
-
 
 	public function new() : Void;
 
-
 	public inline function concat( a : Array<T>) : Array<T> {
 
 		return ArrayImpl.concat(this, a);

+ 2 - 2
std/python/_std/EReg.hx

@@ -19,7 +19,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
-import python.lib.Builtin;
+import python.internal.UBuiltins;
 import python.lib.Re;
 import python.lib.Re.MatchObject;
 import python.lib.Re.Pattern;
@@ -210,7 +210,7 @@ class EReg {
 			var g = x.groups();
 			for (i in 0...g.length) {
 
-				res = res.split("$"+Builtin.str(i+1)).join(g[i]);
+				res = res.split("$"+UBuiltins.str(i+1)).join(g[i]);
 			}
 			res = res.split("_hx_#repl#__").join("$");
 			return res;

+ 6 - 6
std/python/_std/Math.hx

@@ -19,7 +19,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
-import python.lib.Builtin;
+import python.internal.UBuiltins;
 
 @:pythonImport("math")
 @:coreApi
@@ -39,12 +39,12 @@ extern class Math
 	}
 
 	public static inline function min(a:Float, b:Float):Float {
-		return if (isNaN(a)) a else if (isNaN(b)) b else Builtin.min(a,b);
+		return if (isNaN(a)) a else if (isNaN(b)) b else UBuiltins.min(a,b);
 	}
 
 	public static inline function max(a:Float, b:Float):Float
 	{
-		return if (isNaN(a)) a else if (isNaN(b)) b else Builtin.max(a,b);
+		return if (isNaN(a)) a else if (isNaN(b)) b else UBuiltins.max(a,b);
 	}
 
 	public static inline function sin(v:Float):Float {
@@ -132,9 +132,9 @@ extern class Math
 	}
 
 	static function __init__():Void {
-		NEGATIVE_INFINITY = Builtin.float('-inf');
-		POSITIVE_INFINITY = Builtin.float('inf');
-		NaN = Builtin.float("nan");
+		NEGATIVE_INFINITY = UBuiltins.float('-inf');
+		POSITIVE_INFINITY = UBuiltins.float('inf');
+		NaN = UBuiltins.float("nan");
 		PI = python.lib.Math.pi;
 	}
 

+ 14 - 13
std/python/_std/Reflect.hx

@@ -23,8 +23,8 @@
 import python.internal.AnonObject;
 import python.internal.StringImpl;
 import python.internal.ArrayImpl;
+import python.internal.UBuiltins;
 
-import python.lib.Builtin;
 import python.lib.Inspect;
 import python.Syntax;
 import python.VarArgs;
@@ -35,17 +35,18 @@ import python.Boot.handleKeywords;
 class Reflect {
 
 	public static inline function hasField( o : Dynamic, field : String ) : Bool {
-		return Builtin.hasattr(o, handleKeywords(field));
+		return UBuiltins.hasattr(o, handleKeywords(field));
 	}
 
-	@:keep
-	public static inline function field( o : Dynamic, field : String ) : Dynamic {
+
+	@:ifFeature("dynamic_read", "anon_optional_read")
+	public static function field( o : Dynamic, field : String ) : Dynamic {
 		return python.Boot.field(o, field);
 	}
 
-	@:keep
+	@:ifFeature("dynamic_write", "anon_optional_write")
 	public static inline function setField( o : Dynamic, field : String, value : Dynamic ) : Void {
-		Builtin.setattr(o, handleKeywords(field), value);
+		UBuiltins.setattr(o, handleKeywords(field), value);
 	}
 
 	public static function getProperty( o : Dynamic, field : String ) : Dynamic
@@ -55,7 +56,7 @@ class Reflect {
 
 		field = handleKeywords(field);
 		var tmp = Reflect.field(o, "get_" + field);
-		if (tmp != null && Builtin.callable(tmp))
+		if (tmp != null && UBuiltins.callable(tmp))
 			return tmp();
 		else
 			return Reflect.field(o, field);
@@ -64,15 +65,15 @@ class Reflect {
 	public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void {
 
 		var field = handleKeywords(field);
-		if (Builtin.hasattr(o, "set_" + field))
-			Builtin.getattr(o, "set_" + field)(value);
+		if (UBuiltins.hasattr(o, "set_" + field))
+			UBuiltins.getattr(o, "set_" + field)(value);
 		else
-			Builtin.setattr(o, field, value);
+			UBuiltins.setattr(o, field, value);
 	}
 
 	public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array<Dynamic> ) : Dynamic
 	{
-		return if (Builtin.callable(func)) func(python.Syntax.varArgs(args)) else null;
+		return if (UBuiltins.callable(func)) func(python.Syntax.varArgs(args)) else null;
 	}
 
 	public static inline function fields( o : Dynamic ) : Array<String>
@@ -82,7 +83,7 @@ class Reflect {
 
 	public static function isFunction( f : Dynamic ) : Bool
 	{
-		return Inspect.isfunction(f) || Inspect.ismethod(f) || Builtin.hasattr(f, "func_code");
+		return Inspect.isfunction(f) || Inspect.ismethod(f) || UBuiltins.hasattr(f, "func_code");
 	}
 
 	public static function compare<T>( a : T, b : T ) : Int {
@@ -109,7 +110,7 @@ class Reflect {
 	}
 
 	public static function isEnumValue( v : Dynamic ) : Bool {
-		return v != Enum && Builtin.isinstance(v, cast Enum);
+		return v != Enum && UBuiltins.isinstance(v, cast Enum);
 	}
 
 	public static function deleteField( o : Dynamic, field : String ) : Bool {

+ 14 - 15
std/python/_std/Std.hx

@@ -23,7 +23,7 @@
 package;
 
 import python.internal.Internal;
-import python.lib.Builtin;
+import python.internal.UBuiltins;
 import python.lib.Inspect;
 import python.Boot;
 import python.Syntax;
@@ -33,7 +33,7 @@ import python.Syntax;
 
 	public static inline function instance<T:{}, S:T>( value : T, c : Class<S> ) : S {
 		try {
-			return Builtin.isinstance(value,c) ? cast value : null;
+			return UBuiltins.isinstance(value,c) ? cast value : null;
 		} catch (e:Dynamic) {
 			return null;
 		}
@@ -57,27 +57,27 @@ import python.Syntax;
 		if (isMetaType(t,Dynamic)) {
 			return true;
 		}
-		var isBool = Builtin.isinstance(v, Builtin.bool);
+		var isBool = UBuiltins.isinstance(v, UBuiltins.bool);
 
 		if (isMetaType(t, Bool) && isBool) {
 			return true;
 		}
-		if (!isBool && !isMetaType(t, Bool) && isMetaType(t,Int) && Builtin.isinstance(v, Builtin.int )) {
+		if (!isBool && !isMetaType(t, Bool) && isMetaType(t,Int) && UBuiltins.isinstance(v, UBuiltins.int )) {
 			return true;
 		}
-		var vIsFloat = Builtin.isinstance(v, Builtin.float);
+		var vIsFloat = UBuiltins.isinstance(v, UBuiltins.float);
 
 		if (!isBool && vIsFloat && isMetaType(t,Int) && Math.isFinite(v) && v == Std.int(v) && v <= 2147483647 && v >= -2147483648) {
 			return true;
 		}
 
 
-		if (!isBool &&  isMetaType(t,Float) && ( Builtin.isinstance(v, python.Syntax.pythonCode("(float,int)")))) {
+		if (!isBool &&  isMetaType(t,Float) && ( UBuiltins.isinstance(v, python.Syntax.tuple(UBuiltins.float, UBuiltins.int)))) {
 			return true;
 		}
 
-		if ( isMetaType(t, Builtin.str)) {
-			return Builtin.isinstance(v, String);
+		if ( isMetaType(t, UBuiltins.str)) {
+			return UBuiltins.isinstance(v, String);
 		}
 		var isEnumType = isMetaType(t,Enum);
 		if (isEnumType && Inspect.isclass(v) && Internal.hasConstructs(v)) return true;
@@ -85,11 +85,11 @@ import python.Syntax;
 		if (isEnumType) return false;
 
 		var isClassType = isMetaType(t,Class);
-		if (isClassType && !Builtin.isinstance(v, Enum) && Inspect.isclass(v) && Internal.hasClassName(v) && !Internal.hasConstructs(v)) return true;
+		if (isClassType && !UBuiltins.isinstance(v, Enum) && Inspect.isclass(v) && Internal.hasClassName(v) && !Internal.hasConstructs(v)) return true;
 
 		if (isClassType) return false;
 
-		if (try Builtin.isinstance(v, t) catch (e:Dynamic) false) {
+		if (try UBuiltins.isinstance(v, t) catch (e:Dynamic) false) {
 			return true;
 		}
 
@@ -128,7 +128,6 @@ import python.Syntax;
 	}
 
 	@:access(python.Boot)
-	@:keep
 	public static function string( s : Dynamic ) : String
 	{
 		return python.Boot.toString(s);
@@ -137,7 +136,7 @@ import python.Syntax;
 	public static inline function int( x : Float ) : Int
 	{
 		try {
-			return Builtin.int(x);
+			return UBuiltins.int(x);
 		} catch (e:Dynamic) {
 			return null;
 		}
@@ -146,13 +145,13 @@ import python.Syntax;
 	public static function parseInt( x : String ) : Null<Int> {
 		if (x == null) return null;
 		try {
-			return Builtin.int(x);
+			return UBuiltins.int(x);
 		} catch (e:Dynamic) {
 			try {
 				var prefix = x.substr(0,2).toLowerCase();
 
 				if (prefix == "0x") {
-					return Builtin.int(x,16);
+					return UBuiltins.int(x,16);
 				}
 				throw "fail";
 			} catch (e:Dynamic) {
@@ -198,7 +197,7 @@ import python.Syntax;
 	public static function parseFloat( x : String ) : Float
 	{
 		try {
-			return Builtin.float(x);
+			return UBuiltins.float(x);
 		} catch (e:Dynamic) {
 
 			if (x != null) {

+ 0 - 6
std/python/_std/String.hx

@@ -36,17 +36,11 @@ import python.internal.StringImpl;
 @:pythonImport("builtins", "str")
 @:coreApi
 extern class String {
-
-
 	/**
 		The number of characters in [this] String.
 	**/
 	var length(default,null) : Int;
 
-	private inline function get_length ():Int {
-		return StringImpl.get_length(this);
-	}
-
 	/**
 		Creates a copy from a given String.
 	**/

+ 1 - 2
std/python/_std/StringBuf.hx

@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2005-2012 Haxe Foundation
+ * Copyright (C)2005-2015 Haxe Foundation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -20,7 +20,6 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-import python.lib.Builtin;
 import python.lib.io.IOBase.SeekSet;
 import python.lib.io.StringIO;
 

+ 12 - 12
std/python/_std/Type.hx

@@ -23,7 +23,7 @@
 import python.internal.AnonObject;
 import python.internal.EnumImpl;
 import python.internal.Internal;
-import python.lib.Builtin;
+import python.internal.UBuiltins;
 import python.Syntax;
 
 enum ValueType {
@@ -53,7 +53,7 @@ enum ValueType {
 		if (Internal.hasClass(o)) {
 			return Internal.fieldClass(o);
 		}
-		if (Builtin.hasattr(o, "__class__")) {
+		if (UBuiltins.hasattr(o, "__class__")) {
 			return Syntax.field(o, "__class__");
 		} else {
 			return null;
@@ -188,7 +188,7 @@ enum ValueType {
 	}
 
 	public static function getEnumConstructs( e : Enum<Dynamic> ) : Array<String> {
-		if (Builtin.hasattr(e, Internal.constructsVal())) {
+		if (UBuiltins.hasattr(e, Internal.constructsVal())) {
 			var x:Array<String> = Internal.fieldConstructs(e);
 			return x.copy();
 		} else {
@@ -201,25 +201,25 @@ enum ValueType {
 	public static function typeof( v : Dynamic ) : ValueType {
 		if (v == null) {
 			return TNull;
-		} else if (Builtin.isinstance(v, Builtin.bool )) {
+		} else if (UBuiltins.isinstance(v, UBuiltins.bool )) {
 			return TBool;
-		} else if (Builtin.isinstance(v, Builtin.int)) {
+		} else if (UBuiltins.isinstance(v, UBuiltins.int)) {
 			return TInt;
-		} else if (Builtin.isinstance(v, Builtin.float)) {
+		} else if (UBuiltins.isinstance(v, UBuiltins.float)) {
 			return TFloat;
-		} else if (Builtin.isinstance(v, String)) {
+		} else if (UBuiltins.isinstance(v, String)) {
 			return TClass(String);
-		} else if (Builtin.isinstance(v, Array)) {
+		} else if (UBuiltins.isinstance(v, Array)) {
 			return TClass(Array);
-		} else if (Builtin.isinstance(v, AnonObject) || python.lib.Inspect.isclass(v)) {
+		} else if (UBuiltins.isinstance(v, AnonObject) || python.lib.Inspect.isclass(v)) {
 			return TObject;
 		}
-		else if (Builtin.isinstance(v, Enum)) {
+		else if (UBuiltins.isinstance(v, Enum)) {
 			return TEnum(Syntax.field(v, "__class__"));
 		}
-		else if (Builtin.isinstance(v, Builtin.type) || Internal.hasClass(v)) {
+		else if (UBuiltins.isinstance(v, UBuiltins.type) || Internal.hasClass(v)) {
 			return TClass(Syntax.field(v, "__class__"));
-		} else if (Builtin.callable(v)) {
+		} else if (UBuiltins.callable(v)) {
 			return TFunction;
 		} else {
 			return TUnknown;

+ 1 - 1
std/python/_std/haxe/Resource.hx

@@ -34,7 +34,7 @@ import haxe.io.BytesData;
 	}
 
 	public static inline function listNames() : Array<String> {
-		return python.lib.Builtin.list(getContent().keys());
+		return python.internal.UBuiltins.list(getContent().keys());
 	}
 
 	public static function getString( name : String ) : String {

+ 2 - 3
std/python/_std/haxe/ds/ObjectMap.hx

@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2005-2012 Haxe Foundation
+ * Copyright (C)2005-2015 Haxe Foundation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -21,7 +21,6 @@
  */
 package haxe.ds;
 
-import python.lib.Builtin;
 import python.lib.Dict;
 
 class ObjectMap<K:{},V> implements haxe.Constraints.IMap<K, V> {
@@ -74,4 +73,4 @@ class ObjectMap<K:{},V> implements haxe.Constraints.IMap<K, V> {
 		s.add("}");
 		return s.toString();
 	}
-}
+}

+ 7 - 7
std/python/_std/sys/io/File.hx

@@ -34,20 +34,20 @@ class File {
 
 	public static function getContent( path : String ) : String
 	{
-		var f:python.lib.io.TextIOBase = cast python.lib.Builtin.open(path, "r", -1, "utf-8", null, "");
+		var f:python.lib.io.TextIOBase = cast python.lib.Builtins.open(path, "r", -1, "utf-8", null, "");
 		var content = f.read(-1);
 		f.close();
 		return content;
 	}
 
 	public static function saveContent( path : String, content : String ) : Void {
-		var f:python.lib.io.TextIOBase = cast python.lib.Builtin.open(path, "w", -1, "utf-8", null, "");
+		var f:python.lib.io.TextIOBase = cast python.lib.Builtins.open(path, "w", -1, "utf-8", null, "");
 		f.write(content);
 		f.close();
 	}
 
 	public static function getBytes( path : String ) : haxe.io.Bytes {
-		var f:python.lib.io.RawIOBase = cast python.lib.Builtin.open(path, "rb", -1);
+		var f:python.lib.io.RawIOBase = cast python.lib.Builtins.open(path, "rb", -1);
 		var size = f.read(-1);
 		var b = haxe.io.Bytes.ofData(size);
 		f.close();
@@ -55,7 +55,7 @@ class File {
 	}
 
 	public static function saveBytes( path : String, bytes : haxe.io.Bytes ) : Void {
-		var f:python.lib.io.RawIOBase = cast python.lib.Builtin.open(path, "wb", -1);
+		var f:python.lib.io.RawIOBase = cast python.lib.Builtins.open(path, "wb", -1);
 		f.write(bytes.getData());
 		f.close();
 	}
@@ -63,21 +63,21 @@ class File {
 	public static function read( path : String, binary : Bool = true ) : FileInput {
 		var mode = if (binary) "rb" else "r";
 
-		var f = python.lib.Builtin.open(path, mode, -1, null, null, binary ? null : "");
+		var f = python.lib.Builtins.open(path, mode, -1, null, null, binary ? null : "");
 
 		return if (binary) IoTools.createFileInputFromBytes(cast f) else IoTools.createFileInputFromText(cast f);
 	}
 
 	public static function write( path : String, binary : Bool = true ) : FileOutput {
 		var mode = if (binary) "wb" else "w";
-		var f = python.lib.Builtin.open(path, mode, -1, null, null, binary ? null : "");
+		var f = python.lib.Builtins.open(path, mode, -1, null, null, binary ? null : "");
 
 		return if (binary) IoTools.createFileOutputFromBytes(cast f) else IoTools.createFileOutputFromText(cast f);
 	}
 
 	public static function append( path : String, binary : Bool = true ) : FileOutput {
 		var mode = if (binary) "ab" else "a";
-		var f = python.lib.Builtin.open(path, mode, -1, null, null, binary ? null : "");
+		var f = python.lib.Builtins.open(path, mode, -1, null, null, binary ? null : "");
 
 		return if (binary) IoTools.createFileOutputFromBytes(cast f) else IoTools.createFileOutputFromText(cast f);
 	}

+ 2 - 8
std/python/internal/AnonObject.hx

@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2005-2012 Haxe Foundation
+ * Copyright (C)2005-2015 Haxe Foundation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -21,13 +21,7 @@
  */
 package python.internal;
 
-import python.Syntax;
-
-@:keep
-@:nativeGen
 @:native("_hx_AnonObject")
 class AnonObject {
-    public function new(fields) {
-        Syntax.assign(Internal.fieldDict(this), fields);
-    }
+	public function new(fields:python.lib.Dict<String, Dynamic>) {}
 }

+ 27 - 9
std/python/internal/ArrayImpl.hx

@@ -23,26 +23,29 @@
 package python.internal;
 
 import python.lib.Functools;
-import python.lib.Builtin;
 
 @:allow(Array)
-@:keep
 class ArrayImpl {
 
-	public static inline function get_length <T>(x:Array<T>):Int return Builtin.len(x);
+	@:ifFeature("dynamic_read.length", "anon_optional_read.length")
+	public static inline function get_length <T>(x:Array<T>):Int return UBuiltins.len(x);
 
+	@:ifFeature("dynamic_read.concat", "anon_optional_read.concat")
 	public static inline function concat<T>(a1:Array<T>, a2 : Array<T>) : Array<T> {
 		return Syntax.binop(a1, "+", a2);
 	}
 
+	@:ifFeature("dynamic_read.copy", "anon_optional_read.copy")
 	public static inline function copy<T>(x:Array<T>) : Array<T> {
-		return Builtin.list(x);
+		return UBuiltins.list(x);
 	}
 
+	@:ifFeature("dynamic_read.iterator", "anon_optional_read.iterator")
 	public static inline function iterator<T>(x:Array<T>) : Iterator<T> {
 		return new HaxeIterator(Syntax.callField(x, "__iter__"));
 	}
 
+	@:ifFeature("dynamic_read.indexOf", "anon_optional_read.indexOf")
 	public static function indexOf<T>(a:Array<T>, x : T, ?fromIndex:Int) : Int {
 		var len = a.length;
 		var l =
@@ -56,6 +59,7 @@ class ArrayImpl {
 		return -1;
 	}
 
+	@:ifFeature("dynamic_read.lastIndexOf", "anon_optional_read.lastIndexOf")
 	public static function lastIndexOf<T>(a:Array<T>, x : T, ?fromIndex:Int) : Int {
 		var len = a.length;
 		var l =
@@ -70,27 +74,33 @@ class ArrayImpl {
 	}
 
 	@:access(python.Boot)
+	@:ifFeature("dynamic_read.join", "anon_optional_read.join")
 	public static inline function join<T>(x:Array<T>, sep : String ) : String {
 		return Boot.arrayJoin(x, sep);
 	}
 
+	@:ifFeature("dynamic_read.toString", "anon_optional_read.toString")
 	public static inline function toString<T>(x:Array<T>) : String {
 		return "[" + join(x, ",") + "]";
 	}
 
+	@:ifFeature("dynamic_read.pop", "anon_optional_read.pop")
 	public static inline function pop<T>(x:Array<T>) : Null<T> {
 		return if (x.length == 0) null else Syntax.callField(x, "pop");
 	}
 
+	@:ifFeature("dynamic_read.push", "anon_optional_read.push")
 	public static inline function push<T>(x:Array<T>, e:T) : Int {
 		Syntax.callField(x, "append", e);
-		return get_length(x);
+		return x.length;
 	}
 
+	@:ifFeature("dynamic_read.unshift", "anon_optional_read.unshift")
 	public static inline function unshift<T>(x:Array<T>,e : T) : Void {
 		x.insert(0,e);
 	}
 
+	@:ifFeature("dynamic_read.remove", "anon_optional_read.remove")
 	public static function remove<T>(x:Array<T>,e : T) : Bool {
 		try {
 			Syntax.callField(x, "remove", e);
@@ -100,19 +110,22 @@ class ArrayImpl {
 		}
 	}
 
+	@:ifFeature("dynamic_read.shift", "anon_optional_read.shift")
 	public static inline function shift<T>(x:Array<T>) : Null<T> {
 		if (x.length == 0) return null;
 		return Syntax.callField(x, "pop", 0);
 	}
 
+	@:ifFeature("dynamic_read.slice", "anon_optional_read.slice")
 	public static inline function slice<T>(x:Array<T>, pos : Int, ?end : Int ) : Array<T> {
 		return Syntax.arrayAccess(x, pos, end);
 	}
-
+	@:ifFeature("dynamic_read.sort", "anon_optional_read.sort")
 	public static inline function sort<T>(x:Array<T>, f:T->T->Int) : Void {
 		Syntax.callNamedUntyped(Syntax.field(x, "sort"), { key : Functools.cmp_to_key(f) });
 	}
 
+	@:ifFeature("dynamic_read.splice", "anon_optional_read.splice")
 	public static inline function splice<T>(x:Array<T>, pos : Int, len : Int ) : Array<T> {
 		if (pos < 0) pos = x.length+pos;
 		if (pos < 0) pos = 0;
@@ -121,26 +134,31 @@ class ArrayImpl {
 		return res;
 	}
 
+	@:ifFeature("dynamic_read.map", "anon_optional_read.map")
 	public static inline function map<S,T>(x:Array<T>, f : T -> S) : Array<S> {
-		return Builtin.list(Builtin.map(f, cast x));
+		return UBuiltins.list(UBuiltins.map(f, cast x));
 	}
 
+	@:ifFeature("dynamic_read.filter", "anon_optional_read.filter")
 	public static inline function filter<T>(x:Array<T>, f : T -> Bool) : Array<T> {
-		return Builtin.list(Builtin.filter(f, cast x));
+		return UBuiltins.list(UBuiltins.filter(f, cast x));
 	}
 
+	@:ifFeature("dynamic_read.insert", "anon_optional_read.insert")
 	public static inline function insert<T>(a:Array<T>, pos : Int, x : T ) : Void {
 		Syntax.callField(a, "insert", pos, x);
 	}
-
+	@:ifFeature("dynamic_read.reverse", "anon_optional_read.reverse")
 	public static inline function reverse<T>(a:Array<T>) : Void {
 		Syntax.callField(a, "reverse");
 	}
 
+	@:ifFeature("array_read")
 	private static inline function _get<T>(x:Array<T>, idx:Int):T {
 		return if (idx > -1 && idx < x.length) unsafeGet(x, idx) else null;
 	}
 
+	@:ifFeature("array_write")
 	private static inline function _set<T>(x:Array<T>, idx:Int, v:T):T {
 		var l = x.length;
 		while (l < idx) {

+ 8 - 1
std/python/internal/EnumImpl.hx

@@ -21,19 +21,26 @@
  */
 package python.internal;
 
-@:keep
+@:ifFeature("has_enum", "Enum.*")
 @:native("Enum")
 class EnumImpl {
+	@:ifFeature("has_enum", "Enum.*")
 	public var tag:String;
+
+	@:ifFeature("has_enum", "Enum.*")
 	public var index:Int;
+
+	@:ifFeature("has_enum", "Enum.*")
 	public var params:Array<Dynamic>;
 
+	@:ifFeature("has_enum", "Enum.*")
 	public function new(tag, index, params) {
 		this.tag = tag;
 		this.index = index;
 		this.params = params;
 	}
 
+	@:ifFeature("has_enum", "Enum.*")
 	function __str__() {
 		return if (params == null) {
 			tag;

+ 5 - 3
std/python/internal/HxException.hx

@@ -21,13 +21,15 @@
  */
 package python.internal;
 
-@:keep
+@:ifFeature("has_throw")
 @:native("_HxException")
 class HxException extends python.lib.Exceptions.Exception {
+	@:ifFeature("has_throw")
 	public var val:Dynamic;
+	@:ifFeature("has_throw")
 	public function new(val) {
-		var message = Std.string(val);
+		var message = UBuiltins.str(val);
 		super(message);
 		this.val = val;
 	}
-}
+}

+ 15 - 3
std/python/internal/HxOverrides.hx

@@ -25,7 +25,6 @@ import python.Syntax;
 
 import python.Syntax.pythonCode in py;
 
-@:keep
 @:noDoc
 @:native("HxOverrides")
 @:access(python.internal.ArrayImpl)
@@ -35,24 +34,26 @@ class HxOverrides {
 	// this two cases iterator and shift are like all methods in String and Array and are already handled in Reflect
 	// we need to modify the transformer to call Reflect directly
 
+	@:ifFeature("dynamic_read.iterator", "anon_optional_read.iterator")
 	static public function iterator(x) {
 		if (Boot.isArray(x)) {
 			return (x:Array<Dynamic>).iterator();
 		}
 		return Syntax.callField(x, "iterator");
 	}
-
+	@:ifFeature("dynamic_binop_==", "dynamic_binop_!=")
 	static function eq( a:Dynamic, b:Dynamic ) : Bool {
 		if (Boot.isArray(a) || Boot.isArray(b)) {
 			return Syntax.pythonCode('a is b');
 		}
 		return Syntax.binop(a, "==", b);
 	}
-
+	@:ifFeature("unsafe_string_concat")
 	static function stringOrNull (s:String):String {
 		return if (s == null) "null" else s;
 	}
 
+	@:ifFeature("dynamic_read.shift", "anon_optional_read.shift")
 	static public function shift(x) {
 		if (Boot.isArray(x)) {
 			return (x:Array<Dynamic>).shift();
@@ -60,6 +61,7 @@ class HxOverrides {
 		return Syntax.callField(x, "shift");
 	}
 
+	@:ifFeature("dynamic_read.pop", "anon_optional_read.pop")
 	static public function pop(x) {
 		if (Boot.isArray(x)) {
 			return (x:Array<Dynamic>).pop();
@@ -67,6 +69,7 @@ class HxOverrides {
 		return Syntax.callField(x, "pop");
 	}
 
+	@:ifFeature("dynamic_read.push", "anon_optional_read.push")
 	static public function push(x, e) {
 		if (Boot.isArray(x)) {
 			return (x:Array<Dynamic>).push(e);
@@ -74,6 +77,7 @@ class HxOverrides {
 		return Syntax.callField(x, "push", e);
 	}
 
+	@:ifFeature("dynamic_read.join", "anon_optional_read.join")
 	static public function join(x, sep) {
 		if (Boot.isArray(x)) {
 			return (x:Array<Dynamic>).join(sep);
@@ -81,6 +85,7 @@ class HxOverrides {
 		return Syntax.callField(x, "join", sep);
 	}
 
+	@:ifFeature("dynamic_read.filter", "anon_optional_read.filter")
 	static public function filter(x, f) {
 		if (Boot.isArray(x)) {
 			return (x:Array<Dynamic>).filter(f);
@@ -88,6 +93,7 @@ class HxOverrides {
 		return Syntax.callField(x, "filter", f);
 	}
 
+	@:ifFeature("dynamic_read.map", "anon_optional_read.map")
 	static public function map(x, f) {
 		if (Boot.isArray(x)) {
 			return (x:Array<Dynamic>).map(f);
@@ -95,6 +101,7 @@ class HxOverrides {
 		return Syntax.callField(x, "map", f);
 	}
 
+	@:ifFeature("dynamic_read.toUpperCase", "anon_optional_read.toUpperCase")
 	static public function toUpperCase(x) {
 		if (Boot.isString(x)) {
 			return (x:String).toUpperCase();
@@ -102,6 +109,7 @@ class HxOverrides {
 		return Syntax.callField(x, "toUpperCase");
 	}
 
+	@:ifFeature("dynamic_read.toLowerCase", "anon_optional_read.toLowerCase")
 	static public function toLowerCase(x) {
 		if (Boot.isString(x)) {
 			return (x:String).toLowerCase();
@@ -109,14 +117,17 @@ class HxOverrides {
 		return Syntax.callField(x, "toLowerCase");
 	}
 
+	@:ifFeature("binop_>>>")
 	static public function rshift(val:Int, n:Int) {
 		return Syntax.binop(Syntax.binop(val, "%", Syntax.pythonCode("0x100000000")), ">>", n);
 	}
 
+	@:ifFeature("binop_%")
 	static public function modf(a:Float, b:Float) {
 		return Syntax.pythonCode("float('nan') if (b == 0.0) else a % b if a > 0 else -(-a % b)");
 	}
 
+	@:ifFeature("dynamic_array_read")
 	static public function arrayGet<T>(a:Dynamic, i:Int):Dynamic {
 		if (Boot.isArray(a)) {
 			return ArrayImpl._get(a, i);
@@ -125,6 +136,7 @@ class HxOverrides {
 		}
 	}
 
+	@:ifFeature("dynamic_array_write")
 	static public function arraySet(a:Dynamic, i:Int, v:Dynamic) {
 		if (Boot.isArray(a)) {
 			return ArrayImpl._set(a, i, v);

+ 8 - 13
std/python/internal/Internal.hx

@@ -35,7 +35,6 @@ class Internal {
 
 	static var _className = _prefix + "class_name";
 	static var _class = _prefix + "class";
-	static var _props = _prefix + "props";
 	static var _fields = _prefix + "fields";
 	static var _super = _prefix + "super";
 	static var _methods = _prefix + "methods";
@@ -62,11 +61,11 @@ class Internal {
 	}
 
 	static function fieldWithPos(o:Expr, x:String):Expr {
-		return macro @:pos(Context.currentPos()) python.Syntax.field($o, $v{x});
+		return macro @:pos(Context.currentPos()) (untyped __define_feature__($v{"python." + x}, python.Syntax.field($o, $v{x})));
 	}
 
 	static function has (o:Expr, field:String):Expr {
-		return macro python.lib.Builtin.hasattr($o, $v{field});
+		return macro (untyped __define_feature__($v{"python." + field}, python.internal.UBuiltins.hasattr($o, $v{field})) : Bool);
 	}
 
 	#end
@@ -79,7 +78,7 @@ class Internal {
 	}
 
 	macro public static function classRegistry ():Expr {
-		return macro (python.Syntax.pythonCode($v{_classes}) : python.lib.Dict<String, Class<Dynamic>>);
+		return macro (untyped __define_feature__($v{"python." + _classes}, python.Syntax.pythonCode($v{_classes})) : python.lib.Dict<String, Class<Dynamic>>);
 	}
 
 	macro public static function callFieldPrefixed (o:Expr, x:String, params:Array<Expr>):Expr {
@@ -131,6 +130,10 @@ class Internal {
 		return has(o, _emptyInit);
 	}
 
+	macro public static function hasMethods (o:Expr):Expr {
+		return has(o, _methods);
+	}
+
 	macro public static function hasFields (o:Expr):Expr {
 		return has(o, _fields);
 	}
@@ -155,10 +158,6 @@ class Internal {
 		return withPos(_className);
 	}
 
-	macro public static function propsVal():Expr {
-		return withPos(_props);
-	}
-
 	macro public static function superVal():Expr {
 		return withPos(_super);
 	}
@@ -211,16 +210,12 @@ class Internal {
 		return fieldWithPos(o, _fields);
 	}
 
-	macro public static function fieldProps (o:Expr):Expr {
-		return fieldWithPos(o, _props);
-	}
-
 	macro public static function fieldConstructs (o:Expr):Expr {
 		return fieldWithPos(o, _constructs);
 	}
 
 	macro public static function fieldDict (o:Expr):Expr {
-		return fieldWithPos(o, _dict);
+		return macro @:pos(Context.currentPos()) python.Syntax.field($o, $v{_dict});
 	}
 
 	macro public static function fieldEmptyInit (o:Expr):Expr {

+ 17 - 13
std/python/internal/StringImpl.hx

@@ -22,33 +22,35 @@
 package python.internal;
 
 import python.internal.Internal;
-import python.lib.Builtin;
 
-@:keep
 @:native("HxString")
 class StringImpl {
 
+	@:ifFeature("dynamic_read.split", "anon_optional_read.split")
 	public static inline function split (s:String, d:String) {
-		return if (d == "") Builtin.list(s) else Syntax.callField(s, "split", d);
+		return if (d == "") UBuiltins.list(s) else Syntax.callField(s, "split", d);
 	}
 
+	@:ifFeature("dynamic_read.charCodeAt", "anon_optional_read.charCodeAt")
 	public static function charCodeAt(s:String, index:Int) {
 		return
 			if (s == null || s.length == 0 || index < 0 || index >= s.length) null
-			else Builtin.ord(Syntax.arrayAccess(s, index));
+			else UBuiltins.ord(Syntax.arrayAccess(s, index));
 	}
 
+	@:ifFeature("dynamic_read.charAt", "anon_optional_read.charAt")
 	public static inline function charAt(s:String, index:Int) {
 		return if (index < 0 || index >= s.length) "" else Syntax.arrayAccess(s,index);
 	}
 
+	@:ifFeature("dynamic_read.lastIndexOf", "anon_optional_read.lastIndexOf")
 	public static inline function lastIndexOf(s:String, str:String, ?startIndex:Int):Int {
 		if (startIndex == null) {
 			return Syntax.callField(s, "rfind", str, 0, s.length);
 		} else {
 
 			var i = Syntax.callField(s, "rfind", str, 0, startIndex+1);
-			var startLeft = i == -1 ? Builtin.max(0, startIndex + 1 - str.length) : i + 1;
+			var startLeft = i == -1 ? UBuiltins.max(0, startIndex + 1 - str.length) : i + 1;
 			var check = Syntax.callField(s,"find", str, startLeft, s.length);
 			if (check > i && check <= startIndex) {
 				return check;
@@ -58,36 +60,38 @@ class StringImpl {
 		}
 	}
 
+	@:ifFeature("dynamic_read.toUpperCase", "anon_optional_read.toUpperCase")
 	public static inline function toUpperCase (s:String) {
 		return Syntax.callField(s, "upper");
 	}
-
+	@:ifFeature("dynamic_read.toLowerCase", "anon_optional_read.toLowerCase")
 	public static inline function toLowerCase (s:String) {
 		return Syntax.callField(s, "lower");
 	}
+	@:ifFeature("dynamic_read.indexOf", "anon_optional_read.indexOf")
 	public static inline function indexOf (s:String, str:String, ?startIndex:Int) {
 		if (startIndex == null)
 			return Syntax.callField(s, "find", str);
 		else
 			return Syntax.callField(s, "find", str, startIndex);
 	}
-
+	@:ifFeature("dynamic_read.toString", "anon_optional_read.toString")
 	public static inline function toString (s:String) {
 		return s;
 	}
-
+	@:ifFeature("dynamic_read.length", "anon_optional_read.length")
 	public static inline function get_length (s:String) {
-		return Builtin.len(s);
+		return UBuiltins.len(s);
 	}
-
+	@:ifFeature("dynamic_read.fromCharCode", "anon_optional_read.fromCharCode")
 	public static inline function fromCharCode( code : Int ) : String {
 		#if doc_gen
 		return "";
 		#else
-		return Syntax.callField('', "join", Builtin.map(Builtin.chr, cast [code])); // TODO: check cast
+		return Syntax.callField('', "join", UBuiltins.map(UBuiltins.chr, cast [code])); // TODO: check cast
 		#end
 	}
-
+	@:ifFeature("dynamic_read.substring", "anon_optional_read.substring")
 	public static function substring( s:String, startIndex : Int, ?endIndex : Int ) : String {
 		if (startIndex < 0) startIndex = 0;
 		if (endIndex == null) {
@@ -103,7 +107,7 @@ class StringImpl {
 			}
 		}
 	}
-
+	@:ifFeature("dynamic_read.substr", "anon_optional_read.substr")
 	public static function substr( s:String, startIndex : Int, ?len : Int ) : String {
 		if (len == null) {
 			return Syntax.arrayAccessWithTrailingColon(s, startIndex);

+ 48 - 0
std/python/internal/UBuiltins.hx

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C)2005-2012 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package python.internal;
+
+/**
+    This class provides unqualified access to python builtins that are safe to use in haxe/python code.
+    Fields listed here must be synchronized with genpy's KeywordHandler.kwds2 list to be properly escaped.
+**/
+extern class UBuiltins {
+    static function len(x:Dynamic):Int;
+    static function isinstance(o:Dynamic, c:Dynamic):Bool;
+    static function str(o:Dynamic):String;
+    static function bool(o:Dynamic):Bool;
+    static function float(o:Dynamic):Float;
+    static function int(o:Dynamic, ?base:Int):Int;
+    static function list<T>(o:Dynamic):Array<T>;
+    static function min<T>(a:T, b:T):T;
+    static function max<T>(a:T, b:T):T;
+    static function hasattr(o:Dynamic, a:String):Bool;
+    static function getattr(o:Dynamic, a:String):Dynamic;
+    static function setattr(o:Dynamic, a:String, v:Dynamic):Void;
+    static function callable(x:Dynamic):Bool;
+    static function type(o:Dynamic):Dynamic;
+    static function ord(s:String):Int;
+    static function chr(c:Int):String;
+    static function map<T,S>(f:T->S, a:Array<T>):Array<S>;
+    static function filter<T>(f:T->Bool, a:Array<T>):Array<T>;
+    static function iter<T>(o:python.NativeIterable<T>):python.NativeIterator<T>;
+}

+ 0 - 1
std/python/io/NativeBytesInput.hx

@@ -26,7 +26,6 @@ import haxe.io.Input;
 
 import python.io.IInput;
 import python.io.IoTools;
-import python.lib.Builtin;
 import python.lib.Bytearray;
 import python.lib.io.RawIOBase;
 import python.lib.io.IOBase.SeekSet;

+ 0 - 1
std/python/io/NativeBytesOutput.hx

@@ -23,7 +23,6 @@ package python.io;
 
 import haxe.io.Output;
 
-import python.lib.Builtin;
 import python.lib.Bytearray;
 import python.lib.io.IOBase;
 import python.lib.io.RawIOBase;

+ 0 - 1
std/python/io/NativeInput.hx

@@ -23,7 +23,6 @@ package python.io;
 
 import haxe.io.Eof;
 import haxe.io.Input;
-import python.lib.Builtin;
 import python.lib.Bytearray;
 import python.lib.io.IOBase;
 import python.lib.io.RawIOBase;

+ 0 - 1
std/python/io/NativeOutput.hx

@@ -23,7 +23,6 @@ package python.io;
 
 import haxe.io.Output;
 
-import python.lib.Builtin;
 import python.lib.io.IOBase;
 import python.lib.io.RawIOBase;
 

+ 0 - 1
std/python/io/NativeTextInput.hx

@@ -27,7 +27,6 @@ import haxe.io.Input;
 import python.io.IInput;
 import python.io.IoTools;
 import python.io.NativeInput;
-import python.lib.Builtin;
 import python.lib.Bytearray;
 import python.lib.io.RawIOBase;
 import python.lib.io.IOBase.SeekSet;

+ 0 - 1
std/python/io/NativeTextOutput.hx

@@ -24,7 +24,6 @@ package python.io;
 import haxe.io.Output;
 
 import python.io.IoTools;
-import python.lib.Builtin;
 import python.lib.io.IOBase;
 import python.lib.io.RawIOBase;
 import python.lib.io.TextIOBase;

+ 3 - 5
std/python/lib/Builtin.hx → std/python/lib/Builtins.hx

@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2005-2012 Haxe Foundation
+ * Copyright (C)2005-2015 Haxe Foundation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,7 +29,7 @@ import python.NativeIterable;
 import python.NativeIterator;
 
 @:pythonImport("builtins")
-extern class Builtin {
+extern class Builtins {
 
 
 
@@ -80,9 +80,7 @@ extern class Builtin {
 	//public static function basestring():Void;
 	//public static function execfile():Void;
 
-	public static inline function print(o:Dynamic):Void {
-		python.Syntax.field(Builtin, "print")(o);
-	}
+	public static function print(o:Dynamic):Void;
 
 	//public static function super():Void;
 	//public static function bin():Void;

+ 4 - 5
std/python/lib/Bytearray.hx

@@ -21,21 +21,20 @@
  */
 package python.lib;
 
-import python.lib.Builtin;
 import python.Syntax;
 
 @:pythonImport("builtins", "bytearray")
 extern class Bytearray implements ArrayAccess<Int> {
 
-	public var length(get, null):Int;
+	public var length(get,never):Int;
 
 	@:overload(function (it:Array<Int>):Void {})
 	@:overload(function (it:NativeIterable<Int>):Void {})
 	@:overload(function (size:Int):Void {})
 	public function new (source:String,encoding:String,?errors:Dynamic):Void;
 
-	public inline function get_length ():Int {
-		return Builtin.len(this);
+	inline function get_length ():Int {
+		return python.internal.UBuiltins.len(this);
 	}
 
 	public inline function get(i:Int):Int {
@@ -49,4 +48,4 @@ extern class Bytearray implements ArrayAccess<Int> {
     public function __setitem__(i:Int,v:Int):Void;
 
 	public function decode(encoding:String="utf-8", errors:String="strict"):String;
-}
+}

+ 6 - 5
std/python/lib/Dict.hx

@@ -21,20 +21,21 @@
  */
 package python.lib;
 
-import python.lib.Builtin;
+import python.internal.UBuiltins;
 import python.lib.Tuple;
 import python.NativeIterator;
 import python.Syntax;
 
 
 extern class DictView<T> {
+	private function __iter__():NativeIterator<T>;
 	public inline function iter ():NativeIterator<T>
 	{
-		return Builtin.iter(this);
+		return UBuiltins.iter(this);
 	}
 	public inline function length ():Int
 	{
-		return Builtin.len(this);
+		return UBuiltins.len(this);
 	}
 
 	public inline function iterator ():Iterator<T>
@@ -50,7 +51,7 @@ extern class Dict <K, V>
 
 	public inline function length ():Int
 	{
-		return python.lib.Builtin.len(this);
+		return UBuiltins.len(this);
 	}
 
 	public inline function hasKey (k:K):Bool {
@@ -81,7 +82,7 @@ extern class Dict <K, V>
 	{
 		return values().iter();
 	}
-	public function __iter__():NativeIterator<K>;
+	private function __iter__():NativeIterator<K>;
 }
 
 class DictImpl {

+ 1 - 1
std/python/lib/Set.hx

@@ -32,7 +32,7 @@ extern class Set <T>
 
 	public inline function length ():Int
 	{
-		return python.lib.Builtin.len(this);
+		return python.internal.UBuiltins.len(this);
 	}
 
 	public inline function has (v:T):Bool

+ 4 - 4
std/python/lib/Tuple.hx

@@ -21,7 +21,7 @@
  */
 package python.lib;
 
-import python.lib.Builtin;
+import python.internal.UBuiltins;
 import python.Syntax;
 
 @:pythonImport("builtins", "tuple")
@@ -30,15 +30,15 @@ extern class Tuple<X> implements ArrayAccess<X> {
 	@:overload(function ():Void {})
 	public function new (a:Array<X>):Void;
 
-	public var length(get_length, null):Int;
+	public var length(get_length,never):Int;
 
 	inline function get_length():Int {
-		return Builtin.len(this);
+		return UBuiltins.len(this);
 	}
 
 	public inline function toArray ():Array<X>
 	{
-		return Builtin.list(this);
+		return UBuiltins.list(this);
 	}
 
 }

+ 1 - 1
typer.ml

@@ -3842,7 +3842,7 @@ and type_call ctx e el (with_type:with_type) p =
 		else
 		let params = (match el with [] -> [] | _ -> ["customParams",(EArrayDecl el , p)]) in
 		let infos = mk_infos ctx p params in
-		if platform ctx.com Js && el = [] && has_dce ctx.com then
+		if (platform ctx.com Js || platform ctx.com Python) && el = [] && has_dce ctx.com then
 			let e = type_expr ctx e Value in
 			let infos = type_expr ctx infos Value in
 			let e = match follow e.etype with