Browse Source

Merge pull request #2924 from Simn/genpy

Python support
Nicolas Cannasse 11 years ago
parent
commit
b1353516c2
100 changed files with 8406 additions and 28 deletions
  1. 3 0
      .gitignore
  2. 2 0
      .travis.yml
  3. 4 2
      Makefile
  4. 17 0
      common.ml
  5. 2 0
      extra/ImportAll.hx
  6. 4 0
      extra/all.hxml
  7. 1889 0
      genpy.ml
  8. 14 5
      main.ml
  9. 2 2
      std/DateTools.hx
  10. 1 1
      std/List.hx
  11. 22 0
      std/StringTools.hx
  12. 19 0
      std/haxe/CallStack.hx
  13. 4 2
      std/haxe/Int32.hx
  14. 2 0
      std/haxe/Int64.hx
  15. 11 0
      std/haxe/Log.hx
  16. 35 0
      std/haxe/Resource.hx
  17. 12 12
      std/haxe/Serializer.hx
  18. 1 1
      std/haxe/Timer.hx
  19. 7 0
      std/haxe/ds/Vector.hx
  20. 15 0
      std/haxe/io/Bytes.hx
  21. 3 0
      std/haxe/io/BytesBuffer.hx
  22. 2 0
      std/haxe/io/BytesData.hx
  23. 3 0
      std/haxe/io/BytesInput.hx
  24. 3 0
      std/haxe/io/BytesOutput.hx
  25. 3 3
      std/haxe/io/Input.hx
  26. 2 0
      std/haxe/unit/TestRunner.hx
  27. 452 0
      std/python/Boot.hx
  28. 15 0
      std/python/HaxeIterable.hx
  29. 38 0
      std/python/HaxeIterator.hx
  30. 23 0
      std/python/KwArgs.hx
  31. 68 0
      std/python/Lib.hx
  32. 17 0
      std/python/NativeArrayTools.hx
  33. 20 0
      std/python/NativeIterable.hx
  34. 19 0
      std/python/NativeIterator.hx
  35. 32 0
      std/python/NativeStringTools.hx
  36. 136 0
      std/python/Syntax.hx
  37. 16 0
      std/python/VarArgs.hx
  38. 141 0
      std/python/_std/Array.hx
  39. 148 0
      std/python/_std/Date.hx
  40. 257 0
      std/python/_std/EReg.hx
  41. 320 0
      std/python/_std/Math.hx
  42. 160 0
      std/python/_std/Reflect.hx
  43. 215 0
      std/python/_std/Std.hx
  44. 206 0
      std/python/_std/String.hx
  45. 116 0
      std/python/_std/StringBuf.hx
  46. 137 0
      std/python/_std/Sys.hx
  47. 282 0
      std/python/_std/Type.hx
  48. 335 0
      std/python/_std/Xml.hx
  49. 43 0
      std/python/_std/haxe/Json.hx
  50. 59 0
      std/python/_std/haxe/ds/IntMap.hx
  51. 56 0
      std/python/_std/haxe/ds/ObjectMap.hx
  52. 67 0
      std/python/_std/haxe/ds/StringMap.hx
  53. 80 0
      std/python/_std/sys/FileSystem.hx
  54. 89 0
      std/python/_std/sys/io/File.hx
  55. 105 0
      std/python/_std/sys/io/FileInput.hx
  56. 95 0
      std/python/_std/sys/io/FileOutput.hx
  57. 38 0
      std/python/_std/sys/io/Process.hx
  58. 64 0
      std/python/_std/sys/net/Host.hx
  59. 268 0
      std/python/_std/sys/net/Socket.hx
  60. 7 0
      std/python/internal/AnonObject.hx
  61. 168 0
      std/python/internal/ArrayImpl.hx
  62. 23 0
      std/python/internal/EnumImpl.hx
  63. 12 0
      std/python/internal/HxException.hx
  64. 58 0
      std/python/internal/HxOverrides.hx
  65. 206 0
      std/python/internal/Internal.hx
  66. 99 0
      std/python/internal/StringImpl.hx
  67. 14 0
      std/python/io/FileBytesInput.hx
  68. 12 0
      std/python/io/FileBytesOutput.hx
  69. 13 0
      std/python/io/FileTextInput.hx
  70. 12 0
      std/python/io/FileTextOutput.hx
  71. 14 0
      std/python/io/IFileInput.hx
  72. 12 0
      std/python/io/IFileOutput.hx
  73. 43 0
      std/python/io/IInput.hx
  74. 44 0
      std/python/io/IOutput.hx
  75. 61 0
      std/python/io/IoTools.hx
  76. 44 0
      std/python/io/NativeBytesInput.hx
  77. 30 0
      std/python/io/NativeBytesOutput.hx
  78. 65 0
      std/python/io/NativeInput.hx
  79. 46 0
      std/python/io/NativeOutput.hx
  80. 42 0
      std/python/io/NativeTextInput.hx
  81. 29 0
      std/python/io/NativeTextOutput.hx
  82. 149 0
      std/python/lib/Builtin.hx
  83. 23 0
      std/python/lib/ByteArray.hx
  84. 16 0
      std/python/lib/Bytes.hx
  85. 53 0
      std/python/lib/Codecs.hx
  86. 93 0
      std/python/lib/Dict.hx
  87. 355 0
      std/python/lib/Exceptions.hx
  88. 6 0
      std/python/lib/FileDescriptor.hx
  89. 6 0
      std/python/lib/FileObject.hx
  90. 10 0
      std/python/lib/FuncTools.hx
  91. 19 0
      std/python/lib/Glob.hx
  92. 20 0
      std/python/lib/Inspect.hx
  93. 26 0
      std/python/lib/Json.hx
  94. 24 0
      std/python/lib/Math.hx
  95. 15 0
      std/python/lib/Msvcrt.hx
  96. 77 0
      std/python/lib/Os.hx
  97. 15 0
      std/python/lib/PPrint.hx
  98. 14 0
      std/python/lib/Random.hx
  99. 189 0
      std/python/lib/Re.hx
  100. 43 0
      std/python/lib/Set.hx

+ 3 - 0
.gitignore

@@ -57,5 +57,8 @@ build.bat
 tests/unit/compile.php.hxml
 tests/unit/compile.php.hxml
 /extra/*.xml
 /extra/*.xml
 tests/optimization/testopt.js
 tests/optimization/testopt.js
+tests/unit/unit.py
+tests/unit/unit.py.res1.txt
+tests/unit/unit.py.res2.bin
 *.cmo
 *.cmo
 tests/sys/bin/
 tests/sys/bin/

+ 2 - 0
.travis.yml

@@ -16,6 +16,7 @@ env:
     - TARGET=as3
     - TARGET=as3
     - TARGET=java
     - TARGET=java
     - TARGET=cs
     - TARGET=cs
+    - TARGET=python
     - TARGET=flash8
     - TARGET=flash8
     - TARGET=polygonal-ds
     - TARGET=polygonal-ds
     - TARGET=flambe
     - TARGET=flambe
@@ -24,6 +25,7 @@ env:
     - TARGET=openfl-samples
     - TARGET=openfl-samples
     - TARGET=flixel-demos
     - TARGET=flixel-demos
     - TARGET=neko-sys
     - TARGET=neko-sys
+    - TARGET=python-sys
     - TARGET=bytecode
     - TARGET=bytecode
 
 
 matrix:
 matrix:

+ 4 - 2
Makefile

@@ -47,7 +47,7 @@ RELDIR=../../..
 
 
 MODULES=ast type lexer common genxml parser typecore optimizer typeload \
 MODULES=ast type lexer common genxml parser typecore optimizer typeload \
 	codegen gencommon genas3 gencpp genjs genneko genphp genswf8 \
 	codegen gencommon genas3 gencpp genjs genneko genphp genswf8 \
-	genswf9 genswf genjava gencs interp dce filters typer matcher version main
+	genswf9 genswf genjava gencs genpy interp dce filters typer matcher version main
 
 
 ADD_REVISION=0
 ADD_REVISION=0
 
 
@@ -138,6 +138,8 @@ genneko.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EX
 
 
 genphp.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 genphp.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
+genpy.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
+
 genswf.$(MODULE_EXT): type.$(MODULE_EXT) genswf9.$(MODULE_EXT) genswf8.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 genswf.$(MODULE_EXT): type.$(MODULE_EXT) genswf9.$(MODULE_EXT) genswf8.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
 genswf8.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 genswf8.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
@@ -150,7 +152,7 @@ interp.$(MODULE_EXT): typecore.$(MODULE_EXT) type.$(MODULE_EXT) lexer.$(MODULE_E
 
 
 matcher.$(MODULE_EXT): optimizer.$(MODULE_EXT) codegen.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) typer.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 matcher.$(MODULE_EXT): optimizer.$(MODULE_EXT) codegen.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) typer.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-main.$(MODULE_EXT): filters.$(MODULE_EXT) matcher.$(MODULE_EXT) typer.$(MODULE_EXT) typeload.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) optimizer.$(MODULE_EXT) lexer.$(MODULE_EXT) interp.$(MODULE_EXT) genxml.$(MODULE_EXT) genswf.$(MODULE_EXT) genphp.$(MODULE_EXT) genneko.$(MODULE_EXT) genjs.$(MODULE_EXT) gencpp.$(MODULE_EXT) genas3.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) gencommon.$(MODULE_EXT) genjava.$(MODULE_EXT) gencs.$(MODULE_EXT) version.$(MODULE_EXT)
+main.$(MODULE_EXT): filters.$(MODULE_EXT) matcher.$(MODULE_EXT) typer.$(MODULE_EXT) typeload.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) optimizer.$(MODULE_EXT) lexer.$(MODULE_EXT) interp.$(MODULE_EXT) genxml.$(MODULE_EXT) genswf.$(MODULE_EXT) genphp.$(MODULE_EXT) genneko.$(MODULE_EXT) genjs.$(MODULE_EXT) gencpp.$(MODULE_EXT) genas3.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) gencommon.$(MODULE_EXT) genjava.$(MODULE_EXT) gencs.$(MODULE_EXT) genpy.$(MODULE_EXT) version.$(MODULE_EXT)
 
 
 optimizer.$(MODULE_EXT): typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 optimizer.$(MODULE_EXT): typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 

+ 17 - 0
common.ml

@@ -57,6 +57,7 @@ type platform =
 	| Cpp
 	| Cpp
 	| Cs
 	| Cs
 	| Java
 	| Java
+	| Python
 
 
 (**
 (**
 	The capture policy tells which handling we make of captured locals
 	The capture policy tells which handling we make of captured locals
@@ -635,6 +636,21 @@ let get_config com =
 			pf_can_skip_non_nullable_argument = true;
 			pf_can_skip_non_nullable_argument = true;
 			pf_ignore_unsafe_cast = false;
 			pf_ignore_unsafe_cast = false;
 		}
 		}
+	| Python ->
+		{
+			pf_static = false;
+			pf_sys = true;
+			pf_locals_scope = false;
+			pf_captured_scope = false;
+			pf_unique_locals = false;
+			pf_capture_policy = CPLoopVars;
+			pf_pad_nulls = false;
+			pf_add_final_return = false;
+			pf_overload = false;
+			pf_pattern_matching = false;
+			pf_can_skip_non_nullable_argument = true;
+			pf_ignore_unsafe_cast = true;
+		}
 
 
 let memory_marker = [|Unix.time()|]
 let memory_marker = [|Unix.time()|]
 
 
@@ -749,6 +765,7 @@ let platform_name = function
 	| Cpp -> "cpp"
 	| Cpp -> "cpp"
 	| Cs -> "cs"
 	| Cs -> "cs"
 	| Java -> "java"
 	| Java -> "java"
+	| Python -> "python"
 
 
 let flash_versions = List.map (fun v ->
 let flash_versions = List.map (fun v ->
 	let maj = int_of_float v in
 	let maj = int_of_float v in

+ 2 - 0
extra/ImportAll.hx

@@ -52,6 +52,8 @@ class ImportAll {
 			if( !Context.defined("java") ) return;
 			if( !Context.defined("java") ) return;
 		case "cs":
 		case "cs":
 			if( !Context.defined("cs") ) return;
 			if( !Context.defined("cs") ) return;
+		case "python":
+			if( !Context.defined("python") ) return;
 		case "tools":
 		case "tools":
 			return;
 			return;
 		case "build-tool":
 		case "build-tool":

+ 4 - 0
extra/all.hxml

@@ -47,6 +47,10 @@
 -xml cs.xml
 -xml cs.xml
 -D xmldoc
 -D xmldoc
 
 
+--next
+-python all_python
+-xml python.xml
+
 --next
 --next
 
 
 -xml cross.xml
 -xml cross.xml

+ 1889 - 0
genpy.ml

@@ -0,0 +1,1889 @@
+(*
+ * Copyright (C)2005-2014 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.
+ *)
+
+open Ast
+open Type
+open Common
+
+module Utils = struct
+	let class_of_module_type mt = match mt with
+		| TClassDecl c -> c
+		| _ -> failwith ("Not a class: " ^ (s_type_path (t_infos mt).mt_path))
+
+	let find_type com path =
+		try
+			List.find (fun mt -> match mt with
+				| TAbstractDecl _ -> false
+				| _ -> (t_infos mt).mt_path = path
+			) com.types
+		with Not_found ->
+			error (Printf.sprintf "Could not find type %s\n" (s_type_path path)) null_pos
+
+	let mk_static_field c cf p =
+			let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
+			let ethis = mk (TTypeExpr (TClassDecl c)) ta p in
+			let t = monomorphs cf.cf_params cf.cf_type in
+			mk (TField (ethis,(FStatic (c,cf)))) t p
+
+	let mk_static_call c cf el p =
+		let ef = mk_static_field c cf p in
+		let tr = match follow ef.etype with
+			| TFun(args,tr) -> tr
+			| _ -> assert false
+		in
+		mk (TCall(ef,el)) tr p
+
+	let resolve_static_field c n =
+		try
+			PMap.find n c.cl_statics
+		with Not_found ->
+			failwith (Printf.sprintf "Class %s has no field %s" (s_type_path c.cl_path) n)
+
+	let mk_static_field_2 c n p =
+		mk_static_field c (resolve_static_field c n) p
+
+	let mk_static_call_2 c n el p =
+		mk_static_call c (resolve_static_field c n) el p
+end
+
+module KeywordHandler = struct
+	let kwds =
+		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"
+		];
+		h
+
+	let handle_keywords s =
+		let l = String.length s in
+		if Hashtbl.mem kwds s then
+			"_hx_" ^ s
+		(*
+			handle special __ underscore behaviour (creates private fields for objects) for fields but only if the field doesn't
+			end with at least one underscores like __iter__ because these are special fields
+		*)
+		else if l > 2 && String.sub s 0 2 = "__" && String.sub s (l - 1) 1 <> "_" then
+			"_hx_" ^ s
+		else s
+end
+
+module Transformer = struct
+	type adjusted_expr = {
+		a_expr : texpr;
+		a_blocks : texpr list;
+		a_next_id : unit -> string;
+		a_is_value : bool;
+	}
+
+	let como = ref None
+	let t_bool = ref t_dynamic
+	let t_void = ref t_dynamic
+	let t_string= ref t_dynamic
+	let c_reflect = ref null_class
+
+	let init com =
+		como := Some com;
+		t_bool := com.basic.tbool;
+		t_void := com.basic.tvoid;
+		t_string := com.basic.tstring;
+		c_reflect := 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
+
+
+	let new_counter () =
+		let n = ref (-1) in
+		(fun () ->
+			incr n;
+			Printf.sprintf "_hx_local_%i" !n
+		)
+
+	let to_expr ae =
+		match ae.a_blocks with
+			| [] ->
+				ae.a_expr
+			| el ->
+				match ae.a_expr.eexpr with
+					| TBlock el2 ->
+						{ ae.a_expr with eexpr = TBlock (el @ el2) }
+					| _ ->
+						{ ae.a_expr with eexpr = TBlock (el @ [ae.a_expr])}
+
+	let lift_expr ?(is_value = false) ?(next_id = None) ?(blocks = []) e =
+		let next_id = match next_id with
+			| None ->
+				new_counter()
+			| Some f ->
+				f
+		in
+		{
+			a_expr = e;
+			a_blocks = blocks;
+			a_next_id = next_id;
+			a_is_value = is_value
+		}
+
+	let lift_expr1 is_value next_id blocks e =
+		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 = [] }
+
+	let create_non_local n pos =
+		let s = "nonlocal " ^ (KeywordHandler.handle_keywords n) in
+		(* TODO: this is a hack... *)
+		let id = mk (TLocal (to_tvar "python_Syntax.pythonCode" t_dynamic ) ) !t_void pos in
+		let id2 = mk (TLocal( to_tvar s t_dynamic )) !t_void pos in
+		mk (TCall(id, [id2])) t_dynamic pos
+
+	let to_tlocal_expr ?(capture = false) n t p =
+		mk (TLocal (to_tvar ~capture:capture n t)) t p
+
+	let check_unification e t = match follow e.etype,follow t with
+		| TAnon an1, TAnon an2 ->
+			PMap.iter (fun s cf ->
+				if not (PMap.mem s an1.a_fields) then an1.a_fields <- PMap.add s cf an1.a_fields
+			) an2.a_fields;
+			e
+		| _ ->
+			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
+
+	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
+
+	let dynamic_field_read_write next_id e1 s op e2 =
+		let id = next_id() in
+		let temp_var = to_tvar id e1.etype in
+		let temp_var_def = mk (TVar(temp_var,Some e1)) e1.etype e1.epos in
+		let temp_local = mk (TLocal temp_var) e1.etype e1.epos in
+		let e_field = dynamic_field_read temp_local s in
+		let e_op = mk (TBinop(op,e_field,e2)) e_field.etype e_field.epos in
+		let e_set_field = dynamic_field_write temp_local s e_op in
+		mk (TBlock [
+			temp_var_def;
+			e_set_field;
+		]) e_set_field.etype e_set_field.epos
+
+	let add_non_locals_to_func e = match e.eexpr with
+		| TFunction tf ->
+			let cur = ref PMap.empty in
+			let save () =
+				let prev = !cur in
+				(fun () ->
+					cur := prev
+				)
+			in
+			let declare v =
+				cur := PMap.add v.v_id v !cur;
+			in
+			List.iter (fun (v,_) -> declare v) tf.tf_args;
+			let non_locals = Hashtbl.create 0 in
+			let rec it e = match e.eexpr with
+				| TVar(v,e1) ->
+					begin match e1 with
+						| Some e ->
+							maybe_continue e
+						| None ->
+							()
+					end;
+					declare v;
+				| TTry(e1,catches) ->
+					it e1;
+					List.iter (fun (v,e) ->
+						let restore = save() in
+						declare v;
+						it e;
+						restore()
+					) catches;
+				| TBinop( (OpAssign | OpAssignOp(_)), { eexpr = TLocal v }, e2) ->
+					if not (PMap.mem v.v_id !cur) then
+						Hashtbl.add non_locals v.v_id v;
+					maybe_continue e2;
+				| TFunction _ ->
+					()
+				| _ ->
+					Type.iter it e
+			and maybe_continue e = match e.eexpr with
+				| TFunction _ ->
+					()
+				| _ ->
+					it e
+			in
+			it tf.tf_expr;
+			let el = Hashtbl.fold (fun k v acc ->
+				(create_non_local v.v_name e.epos) :: acc
+			) non_locals [] in
+			let el = tf.tf_expr :: el in
+			let tf = { tf with tf_expr = { tf.tf_expr with eexpr = TBlock(List.rev el)}} in
+			{e with eexpr = TFunction tf}
+		| _ ->
+			assert false
+
+	let rec transform_function tf ae is_value =
+		let p = tf.tf_expr.epos in
+		let assigns = List.fold_left (fun acc (v,value) -> match value with
+			| None ->
+				acc
+			| Some ct ->
+				let a_local = mk (TLocal v) v.v_type p in
+				let a_null = mk (TConst TNull) v.v_type p in
+				let a_cmp = mk (TBinop(OpEq,a_local,a_null)) !t_bool p in
+				let a_value = mk (TConst(ct)) v.v_type p in
+				let a_assign = mk (TBinop(OpAssign,a_local,a_value)) v.v_type p in
+				let a_if = mk (TIf(a_cmp,a_assign,None)) !t_void p in
+				a_if :: acc
+		) [] tf.tf_args in
+		let body = match assigns with
+			| [] ->
+				tf.tf_expr
+			| _ ->
+				let eb = mk (TBlock (List.rev assigns)) t_dynamic p in
+				Type.concat eb tf.tf_expr
+		in
+		let e1 = to_expr (transform_expr ~next_id:(Some ae.a_next_id) body) in
+		let fn = mk (TFunction({
+			tf_expr = e1;
+			tf_args = tf.tf_args;
+			tf_type = tf.tf_type;
+		})) ae.a_expr.etype p in
+		let fn = add_non_locals_to_func fn in
+		if is_value then begin
+			let new_name = ae.a_next_id() in
+			let new_var = alloc_var new_name tf.tf_type in
+			let new_local = mk (TLocal new_var) fn.etype p in
+			let def = mk (TVar(new_var,Some fn)) fn.etype p in
+			lift_expr1 false ae.a_next_id [def] new_local
+		end else
+			lift_expr fn
+
+	and transform_var_expr ae eo v =
+		let b,new_expr = match eo with
+			| None ->
+				[],None
+			| Some e1 ->
+				let f = transform_expr1 true ae.a_next_id [] e1 in
+				let b = f.a_blocks in
+				b,Some(f.a_expr)
+		in
+		let e = mk (TVar(v,new_expr)) ae.a_expr.etype ae.a_expr.epos in
+		lift_expr ~next_id:(Some ae.a_next_id) ~blocks:b e
+
+	and transform_expr ?(is_value = false) ?(next_id = None) ?(blocks = []) (e : texpr) : adjusted_expr =
+		transform1 (lift_expr ~is_value ~next_id ~blocks e)
+
+	and transform_expr1 is_value next_id blocks e =
+		transform_expr ~is_value ~next_id:(Some next_id) ~blocks e
+
+	and transform_exprs_to_block el tb is_value p next_id =
+		match el with
+			| [e] ->
+				transform_expr ~is_value ~next_id:(Some next_id) e
+			| _ ->
+				let res = DynArray.create () in
+				List.iter (fun e ->
+					let ae = transform_expr ~is_value ~next_id:(Some next_id) e in
+					List.iter (DynArray.add res) ae.a_blocks;
+					DynArray.add res ae.a_expr
+				) el;
+				lift_expr (mk (TBlock (DynArray.to_list res)) tb p)
+
+	and transform_switch ae is_value e1 cases edef =
+		let case_functions = ref [] in
+		let case_to_if (el,e) eelse =
+			let val_reversed = List.rev el in
+			let mk_eq e = mk (TBinop(OpEq,e1,e)) !t_bool (punion e1.epos e.epos) in
+			let cond = match val_reversed with
+				| [] ->
+					assert false
+				| [e] ->
+					mk_eq e
+				| e :: el ->
+					List.fold_left (fun eelse e -> mk (TBinop(OpBoolOr,eelse,mk_eq e)) !t_bool (punion eelse.epos e.epos)) (mk_eq e) el
+			in
+			let eif = if is_value then begin
+				let name = ae.a_next_id() in
+				let func = exprs_to_func [e] name ae in
+				case_functions := !case_functions @ func.a_blocks;
+				let call = func.a_expr in
+				mk (TIf(cond,call,eelse)) ae.a_expr.etype ae.a_expr.epos
+			end else
+				mk (TIf(cond,e,eelse)) ae.a_expr.etype e.epos
+			in
+			eif
+		in
+		let rev_cases = List.rev cases in
+		let edef = Some (match edef with
+			| None ->
+				mk (TBlock []) ae.a_expr.etype ae.a_expr.epos
+			| Some e ->
+				e)
+		in
+		let res = match rev_cases,edef with
+			| [],Some edef ->
+				edef
+			| [],None ->
+				(* I don't think that can happen? *)
+				assert false
+			| [case],_ ->
+				case_to_if case edef
+			| case :: cases,_ ->
+				List.fold_left (fun acc case -> case_to_if case (Some acc)) (case_to_if case edef) cases
+		in
+		let res = if is_value then
+			mk (TBlock ((List.rev (res :: !case_functions)))) res.etype res.epos
+		else
+			res
+		in
+		forward_transform res ae
+
+	and transform_op_assign_op ae e1 op one is_value post =
+		let e1_ = transform_expr e1 ~is_value:true ~next_id:(Some ae.a_next_id) in
+		let handle_as_local temp_local =
+			let ex = ae.a_expr in
+			let res_var = alloc_var (ae.a_next_id()) ex.etype in
+			let res_local = {ex with eexpr = TLocal res_var} in
+			let plus = {ex with eexpr = TBinop(op,temp_local,one)} in
+			let var_expr = {ex with eexpr = TVar(res_var,Some temp_local)} in
+			let assign_expr = {ex with eexpr = TBinop(OpAssign,e1_.a_expr,plus)} in
+			let blocks = if post then
+				[var_expr;assign_expr;res_local]
+			else
+				[assign_expr;temp_local]
+			in
+			(* TODO: block is ignored in the else case? *)
+			let block = e1_.a_blocks @ blocks in
+			if is_value then begin
+				let f = exprs_to_func block (ae.a_next_id()) ae in
+				lift_expr f.a_expr ~is_value:true ~next_id:(Some ae.a_next_id) ~blocks:f.a_blocks
+			end else begin
+				let block = e1_.a_blocks @ [assign_expr] in
+				transform_exprs_to_block block ex.etype false ex.epos ae.a_next_id
+			end
+		in
+		match e1_.a_expr.eexpr with
+			| TArray({eexpr = TLocal _},{eexpr = TLocal _})
+			| TField({eexpr = TLocal _},_)
+			| TLocal _ ->
+				handle_as_local e1_.a_expr
+			| TArray(e1,e2) ->
+				let id = ae.a_next_id() in
+				let temp_var_l = alloc_var id e1.etype in
+				let temp_local_l = {e1 with eexpr = TLocal temp_var_l} in
+				let temp_var_l = {e1 with eexpr = TVar(temp_var_l,Some e1)} in
+
+				let id = ae.a_next_id() in
+				let temp_var_r = alloc_var id e2.etype in
+				let temp_local_r = {e2 with eexpr = TLocal temp_var_r} in
+				let temp_var_r = {e2 with eexpr = TVar(temp_var_r,Some e2)} in
+
+				let id = ae.a_next_id() in
+				let temp_var = alloc_var id e1_.a_expr.etype in
+				let temp_local = {e1_.a_expr with eexpr = TLocal temp_var} in
+				let temp_var_expr = {e1_.a_expr with eexpr = TArray(temp_local_l,temp_local_r)} in
+				let temp_var = {e1_.a_expr with eexpr = TVar(temp_var,Some temp_var_expr)} in
+
+				let plus = {ae.a_expr with eexpr = TBinop(op,temp_local,one)} in
+				let assign_expr = {ae.a_expr with eexpr = TBinop(OpAssign,temp_var_expr,plus)} in
+				let block = e1_.a_blocks @ [temp_var_l;temp_var_r;temp_var;assign_expr;if post then temp_local else temp_var_expr] in
+				if is_value then begin
+					let f = exprs_to_func block (ae.a_next_id()) ae in
+					lift_expr f.a_expr ~is_value:true ~next_id:(Some ae.a_next_id) ~blocks:f.a_blocks
+				end else
+					transform_exprs_to_block block ae.a_expr.etype false ae.a_expr.epos ae.a_next_id
+			| TField(e1,fa) ->
+				let temp_var_l = alloc_var (ae.a_next_id()) e1.etype in
+				let temp_local_l = {e1 with eexpr = TLocal temp_var_l} in
+				let temp_var_l = {e1 with eexpr = TVar(temp_var_l,Some e1)} in
+
+				let temp_var = alloc_var (ae.a_next_id()) e1_.a_expr.etype in
+				let temp_local = {e1_.a_expr with eexpr = TLocal temp_var} in
+				let temp_var_expr = {e1_.a_expr with eexpr = TField(temp_local_l,fa)} in
+				let temp_var = {e1_.a_expr with eexpr = TVar(temp_var,Some temp_var_expr)} in
+
+				let plus = {ae.a_expr with eexpr = TBinop(op,temp_local,one)} in
+				let assign_expr = {ae.a_expr with eexpr = TBinop(OpAssign,temp_var_expr,plus)} in
+				let block = e1_.a_blocks @ [temp_var_l;temp_var;assign_expr;if post then temp_local else temp_var_expr] in
+				if is_value then begin
+					let f = exprs_to_func block (ae.a_next_id()) ae in
+					lift_expr f.a_expr ~is_value:true ~next_id:(Some ae.a_next_id) ~blocks:f.a_blocks
+				end else
+					transform_exprs_to_block block ae.a_expr.etype false ae.a_expr.epos ae.a_next_id
+			| _ ->
+				debug_expr e1_.a_expr;
+				assert false
+
+	and var_to_treturn_expr ?(capture = false) n t p =
+		let x = mk (TLocal (to_tvar ~capture:capture n t)) t p in
+		mk (TReturn (Some x)) t p
+
+	and exprs_to_func exprs name base =
+		let convert_return_expr (expr:texpr) =
+			match expr.eexpr with
+			| TWhile(_,_,_) ->
+				let ret = { expr with eexpr = TReturn (None) } in
+				[expr; ret]
+			| TFunction(f) ->
+				let ret = var_to_treturn_expr name f.tf_type f.tf_expr.epos in
+				[expr;ret]
+			| TBinop(OpAssign, l, r) ->
+				let r = { l with eexpr = TReturn(Some l) } in
+				[expr; r]
+			| x ->
+				let ret_expr = { expr with eexpr = TReturn( Some(expr) )} in
+				[ret_expr]
+		in
+		let def =
+			(let ex = match exprs with
+			| [] -> assert false
+			| [x] ->
+				(let exs = convert_return_expr x in
+				match exs with
+				| [] -> assert false
+				| [x] -> x
+				| x ->
+					match List.rev x with
+					| x::xs ->
+						mk (TBlock exs) x.etype base.a_expr.epos
+					| _ -> assert false)
+
+			| x ->
+				match List.rev x with
+				| x::xs ->
+					(let ret = x in
+					let tail = List.rev xs in
+					let block = tail @ (convert_return_expr ret) in
+					match List.rev block with
+					| x::_ ->
+						mk (TBlock block) x.etype base.a_expr.epos
+					| _ -> assert false)
+				| _ -> assert false
+			in
+			let f1 = { tf_args = []; tf_type = TFun([],ex.etype); tf_expr = ex} in
+			let fexpr = mk (TFunction f1) ex.etype ex.epos in
+			let fvar = to_tvar name fexpr.etype in
+			let f = add_non_locals_to_func fexpr in
+			let assign = { ex with eexpr = TVar(fvar, Some(f))} in
+			let call_expr = (mk (TLocal fvar) fexpr.etype ex.epos ) in
+			let substitute = mk (TCall(call_expr, [])) ex.etype ex.epos in
+			lift_expr ~blocks:[assign] substitute)
+		in
+		match exprs with
+		| [{ eexpr = TFunction({ tf_args = []} as f) } as x] ->
+			let l = to_tlocal_expr name f.tf_type f.tf_expr.epos in
+			let substitute = mk (TCall(l, [])) f.tf_type f.tf_expr.epos in
+			lift_expr ~blocks:[x] substitute
+		| _ -> def
+
+	and transform_call is_value e params ae =
+		let trans is_value blocks e = transform_expr1 is_value ae.a_next_id blocks e in
+		let trans1 e params =
+			let e = trans true [] e in
+			let blocks = e.a_blocks @ (List.flatten (List.map (fun (p) -> p.a_blocks) params)) in
+			let params = List.map (fun (p) -> p.a_expr) params in
+			let e = { ae.a_expr with eexpr = TCall(e.a_expr, params) } in
+			lift_expr ~blocks:blocks e
+		in
+		match e, params with
+		(* the foreach block should not be handled as a value *)
+		| ({ eexpr = TField(_, FStatic({cl_path = ["python";],"Syntax"},{ cf_name = "_foreach" }))} as e, [e1;e2;e3]) ->
+			trans1 e [trans true [] e1; trans true [] e2; trans false [] e3]
+		| (e, params) ->
+			trans1 e (List.map (trans true []) params)
+
+
+	and transform1 ae : adjusted_expr =
+
+		let trans is_value blocks e = transform_expr1 is_value ae.a_next_id blocks e in
+		let lift is_value blocks e = lift_expr1 is_value ae.a_next_id blocks e in
+		let a_expr = ae.a_expr in
+		match ae.a_is_value,ae.a_expr.eexpr with
+		| (is_value,TBlock [x]) ->
+			trans is_value [] x
+		| (_,TBlock []) ->
+			lift_expr (mk (TConst TNull) ae.a_expr.etype ae.a_expr.epos)
+		| (false,TBlock el) ->
+			transform_exprs_to_block el ae.a_expr.etype false ae.a_expr.epos ae.a_next_id
+		| (true,TBlock el) ->
+			let name = ae.a_next_id() in
+			let block,tr = match List.rev el with
+				| e :: el ->
+					List.rev ((mk (TReturn (Some e)) t_dynamic e.epos) :: el),e.etype
+				| [] ->
+					assert false
+			in
+			let my_block = transform_exprs_to_block block tr false ae.a_expr.epos ae.a_next_id in
+			let fn = mk (TFunction {
+				tf_args = [];
+				tf_type = tr;
+				tf_expr = my_block.a_expr;
+			}) ae.a_expr.etype ae.a_expr.epos in
+			let t_var = alloc_var name ae.a_expr.etype in
+			let f = add_non_locals_to_func fn in
+			let fn_assign = mk (TVar (t_var,Some f)) ae.a_expr.etype ae.a_expr.epos in
+			let ev = mk (TLocal t_var) ae.a_expr.etype ae.a_expr.epos in
+			let substitute = mk (TCall(ev,[])) ae.a_expr.etype ae.a_expr.epos in
+			lift_expr ~blocks:[fn_assign] substitute
+		| (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
+			let inc = {e1 with eexpr = TBinop(op,ve,one)} in
+			let inc_assign = {e1 with eexpr = TBinop(OpAssign,ve,inc)} in
+			let var_assign = {e1 with eexpr = TVar(v,Some ve)} in
+			if post_fix = Postfix then
+				lift true [var_assign] inc_assign
+			else
+				lift true [inc_assign] var_assign
+		| (_,TVar(v,eo)) ->
+			transform_var_expr ae eo v
+		| (_,TFor(v,e1,e2)) ->
+			let a1 = trans true [] e1 in
+			let a2 = to_expr (trans false [] e2) in
+
+			let name = (ae.a_next_id ()) in
+			let t_var = alloc_var name e1.etype in
+
+			let mk_local v p = { eexpr = TLocal v; etype = v.v_type; epos = p } in
+
+			let ev = mk_local t_var e1.epos in
+			let ehasnext = mk (TField(ev,quick_field e1.etype "hasNext")) (tfun [] (!t_bool) ) e1.epos in
+			let ehasnext = mk (TCall(ehasnext,[])) ehasnext.etype ehasnext.epos in
+
+			let enext = mk (TField(ev,quick_field e1.etype "next")) (tfun [] v.v_type) e1.epos in
+			let enext = mk (TCall(enext,[])) v.v_type e1.epos in
+
+			let var_assign = mk (TVar (v,Some enext)) v.v_type a_expr.epos in
+
+			let ebody = Type.concat var_assign (a2) in
+
+			let var_decl = mk (TVar (t_var,Some a1.a_expr)) (!t_void) e1.epos in
+			let twhile = mk (TWhile((mk (TParenthesis ehasnext) ehasnext.etype ehasnext.epos),ebody,NormalWhile)) (!t_void) e1.epos in
+
+			let blocks = a1.a_blocks @ [var_decl] in
+
+			lift_expr ~blocks: blocks twhile
+		| (_,TReturn None) ->
+			ae
+		| (_,TReturn (Some ({eexpr = TFunction f} as ef))) ->
+			let n = ae.a_next_id() in
+			let e1 = to_expr (trans false [] f.tf_expr) in
+			let f = mk (TFunction {
+				tf_args = f.tf_args;
+				tf_type = f.tf_type;
+				tf_expr = e1;
+			}) ef.etype ef.epos in
+			let f1 = add_non_locals_to_func f in
+			let var_n = alloc_var n ef.etype in
+			let f1_assign = mk (TVar(var_n,Some f1)) !t_void f1.epos in
+			let var_local = mk (TLocal var_n) ef.etype f1.epos in
+			let er = mk (TReturn (Some var_local)) t_dynamic  ae.a_expr.epos in
+			lift true [f1_assign] er
+
+		| (_,TReturn Some(x)) ->
+			let x1 = trans true [] x in
+			(match x1.a_blocks with
+				| [] ->
+					lift true [] { ae.a_expr with eexpr = TReturn(Some x1.a_expr) }
+				| blocks ->
+					let f = exprs_to_func (blocks @ [x1.a_expr]) (ae.a_next_id()) ae in
+					lift true f.a_blocks {a_expr with eexpr = TReturn (Some f.a_expr)})
+		| (_, TParenthesis(e1)) ->
+			let e1 = trans true [] e1 in
+			let p = { ae.a_expr with eexpr = TParenthesis(e1.a_expr)} in
+			lift true e1.a_blocks p
+		| (true, TIf(econd, eif, eelse)) ->
+			(let econd1 = trans true [] econd in
+			let eif1 = trans true [] eif in
+			let eelse1 = match eelse with
+				| Some x -> Some(trans true [] x)
+				| None -> None
+			in
+			let blocks = [] in
+			let eif2, blocks =
+				match eif1.a_blocks with
+				| [] -> eif1.a_expr, blocks
+				| x ->
+					let regular =
+						let fname = eif1.a_next_id () in
+						let f = exprs_to_func (List.append eif1.a_blocks [eif1.a_expr]) fname ae in
+						f.a_expr, List.append blocks f.a_blocks
+					in
+					match eif1.a_blocks with
+					| [{ eexpr = TVar(_, Some({ eexpr = TFunction(_)}))} as b] ->
+						eif1.a_expr, List.append blocks [b]
+					| _ -> regular
+			in
+			let eelse2, blocks =
+				match eelse1 with
+				| None -> None, blocks
+				| Some({ a_blocks = []} as x) -> Some(x.a_expr), blocks
+				| Some({ a_blocks = b} as eelse1) ->
+					let regular =
+						let fname = eelse1.a_next_id () in
+						let f = exprs_to_func (List.append eelse1.a_blocks [eelse1.a_expr]) fname ae in
+						Some(f.a_expr), List.append blocks f.a_blocks
+					in
+					match b with
+					| [{ eexpr = TVar(_, Some({ eexpr = TFunction(f)}))} as b] ->
+						Some(eelse1.a_expr), List.append blocks [b]
+					| _ -> regular
+			in
+			let blocks = List.append econd1.a_blocks blocks in
+			let new_if = { ae.a_expr with eexpr = TIf(econd1.a_expr, eif2, eelse2) } in
+			match blocks with
+			| [] ->
+				let meta = Meta.Custom(":ternaryIf"), [], ae.a_expr.epos in
+				let ternary = { ae.a_expr with eexpr = TMeta(meta, new_if) } in
+				lift_expr ~blocks:blocks ternary
+			| b ->
+				let f = exprs_to_func (List.append blocks [new_if]) (ae.a_next_id ()) ae in
+				lift_expr ~blocks:f.a_blocks f.a_expr)
+		| (false, TIf(econd, eif, eelse)) ->
+			let econd = trans true [] econd in
+			let eif = to_expr (trans false [] eif) in
+			let eelse = match eelse with
+			| Some(x) -> Some(to_expr (trans false [] x))
+			| None -> None
+			in
+			let new_if = { ae.a_expr with eexpr = TIf(econd.a_expr, eif, eelse) } in
+			lift false econd.a_blocks new_if
+		| (false, TWhile(econd, e1, NormalWhile)) ->
+			let econd1 = trans true [] econd in
+			let e11 = to_expr (trans false [] e1) in
+			let new_while = mk (TWhile(econd1.a_expr,e11,NormalWhile)) a_expr.etype a_expr.epos in
+			lift false econd1.a_blocks new_while
+		| (true, TWhile(econd, ebody, NormalWhile)) ->
+			let econd = trans true [] econd in
+			let ebody = to_expr (trans false [] ebody) in
+			let ewhile = { ae.a_expr with eexpr = TWhile(econd.a_expr, ebody, NormalWhile) } in
+			let eval = { ae.a_expr with eexpr = TConst(TNull) } in
+			let f = exprs_to_func (List.append econd.a_blocks [ewhile; eval]) (ae.a_next_id ()) ae in
+			lift true f.a_blocks f.a_expr
+		| (false, TWhile(econd, ebody, DoWhile)) ->
+			let not_expr = { econd with eexpr = TUnop(Not, Prefix, econd) } in
+			let break_expr = mk TBreak !t_void econd.epos in
+			let if_expr = mk (TIf(not_expr, break_expr, None)) (!t_void) econd.epos in
+			let new_e = match ebody.eexpr with
+				| TBlock(exprs) -> { econd with eexpr = TBlock( List.append exprs [if_expr]) }
+				| _ -> { econd with eexpr = TBlock( List.append [ebody] [if_expr]) }
+			in
+			let true_expr = mk (TConst(TBool(true))) econd.etype ae.a_expr.epos in
+			let new_expr = { ae.a_expr with eexpr = TWhile( true_expr, new_e, NormalWhile) } in
+			forward_transform new_expr ae
+
+		| (is_value, TSwitch(e, cases, edef)) ->
+			transform_switch ae is_value e cases edef
+
+		(* anon field access on optional params *)
+		| (is_value, TField(e,FAnon cf)) when Meta.has Meta.Optional cf.cf_meta ->
+			let e = dynamic_field_read e cf.cf_name in
+			transform_expr ~is_value:is_value e
+		| (is_value, TBinop(OpAssign,{eexpr = TField(e1,FAnon cf)},e2)) when Meta.has Meta.Optional cf.cf_meta ->
+			let e = dynamic_field_write e1 cf.cf_name e2 in
+			transform_expr ~is_value:is_value e
+		| (is_value, TBinop(OpAssignOp op,{eexpr = TField(e1,FAnon cf)},e2)) when Meta.has Meta.Optional cf.cf_meta ->
+			let e = dynamic_field_read_write ae.a_next_id e1 cf.cf_name op e2 in
+			transform_expr ~is_value:is_value e
+		(* TODO we need to deal with Increment, Decrement too!
+
+		| (_, TUnop( (Increment | Decrement) as unop, op,{eexpr = TField(e1,FAnon cf)})) when Meta.has Meta.Optional cf.cf_meta  ->
+			let  = dynamic_field_read e cf.cf_name in
+
+			let e = dynamic_field_read_write_unop ae.a_next_id e1 cf.cf_name unop op in
+			Printf.printf "dyn read write\n";
+			transform_expr e
+		*)
+		(*
+			anon field access with non optional members like iterator, length, split must be handled too, we need to Reflect on them too when it's a runtime method
+		*)
+		| (is_value, TUnop( (Increment | Decrement) as unop, op, e)) ->
+			let one = { ae.a_expr with eexpr = TConst(TInt(Int32.of_int(1)))} in
+			let is_postfix = match op with
+			| Postfix -> true
+			| Prefix -> false in
+			let op = match unop with
+			| Increment -> OpAdd
+			| Decrement -> OpSub
+			| _ -> assert false in
+			transform_op_assign_op ae e op one is_value is_postfix
+		| (_, TUnop(op, Prefix, e)) ->
+			let e1 = trans true [] e in
+			let r = { a_expr with eexpr = TUnop(op, Prefix, e1.a_expr) } in
+			lift_expr ~blocks:e1.a_blocks r
+
+		| (is_value, TField(e,FDynamic s)) ->
+			let e = dynamic_field_read e s in
+			transform_expr ~is_value:is_value e
+		| (is_value, TBinop(OpAssign,{eexpr = TField(e1,FDynamic s)},e2)) ->
+			let e = dynamic_field_write e1 s e2 in
+			transform_expr ~is_value:is_value e
+		| (is_value, TBinop(OpAssignOp op,{eexpr = TField(e1,FDynamic s)},e2)) ->
+			let e = dynamic_field_read_write ae.a_next_id e1 s op e2 in
+			transform_expr ~is_value:is_value e
+		| (is_value, TField(e1, FClosure(Some {cl_path = [],("String" | "list")},cf))) ->
+			let e = dynamic_field_read e1 cf.cf_name in
+			transform_expr ~is_value:is_value e
+		| (is_value, TBinop(OpAssign, left, right))->
+			(let left = trans true [] left in
+			let right = trans true [] right in
+			let r = { a_expr with eexpr = TBinop(OpAssign, left.a_expr, right.a_expr)} in
+			if is_value then
+				(let blocks = List.concat [left.a_blocks; right.a_blocks; [r]] in
+				let f = exprs_to_func blocks (ae.a_next_id ()) ae in
+				lift true f.a_blocks f.a_expr)
+			else
+				lift false (List.append left.a_blocks right.a_blocks) r)
+		| (is_value, TBinop(OpAssignOp(x), left, right)) ->
+			let right = trans true [] right in
+			let v = right.a_expr in
+			let res = transform_op_assign_op ae left x v is_value false in
+			lift true (List.append right.a_blocks res.a_blocks) res.a_expr
+		| (_, TBinop(op, left, right))->
+			(let left = trans true [] left in
+			let right = trans true [] right in
+			let r = { a_expr with eexpr = TBinop(op, left.a_expr, right.a_expr)} in
+			lift false (List.append left.a_blocks right.a_blocks) r)
+
+		| (true, TThrow(x)) ->
+			let block = TBlock([a_expr; { a_expr with eexpr = TConst(TNull) }]) in
+			let r = { a_expr with eexpr = block } in
+			forward_transform r ae
+		| (false, TThrow(x)) ->
+			let x = trans true [] x in
+			let r = { a_expr with eexpr = TThrow(x.a_expr)} in
+			lift false x.a_blocks r
+		| (_, TNew(c, tp, params)) ->
+			let params = List.map (trans true []) params in
+			let blocks = List.flatten (List.map (fun (p) -> p.a_blocks) params) in
+			let params = List.map (fun (p) -> p.a_expr) params in
+			let e = { a_expr with eexpr = TNew(c, tp, params) } in
+			lift false blocks e
+		| (is_value, TCall(e,params)) ->
+			transform_call is_value e params ae
+		| (_, TArray(e1, e2)) ->
+			let e1 = trans true [] e1 in
+			let e2 = trans true [] e2 in
+			let r = { a_expr with eexpr = TArray(e1.a_expr, e2.a_expr)} in
+			let blocks = List.append e1.a_blocks e2.a_blocks in
+			lift_expr ~blocks:blocks r
+		| (false, TTry(etry, catches)) ->
+			let etry = trans false [] etry in
+			let catches = List.map (fun(v,e) -> v, trans false [] e) catches in
+			let blocks = List.flatten (List.map (fun (_,e) -> e.a_blocks) catches) in
+			let catches = List.map (fun(v,e) -> v, e.a_expr) catches in
+			let r = { a_expr with eexpr = TTry(etry.a_expr, catches)} in
+			let blocks = List.append etry.a_blocks blocks in
+			lift false blocks r
+		| (true, TTry(etry, catches)) ->
+
+			let id = ae.a_next_id () in
+			let temp_var = to_tvar id a_expr.etype in
+			let temp_var_def = { a_expr with eexpr = TVar(temp_var, None) } in
+			let temp_local = { a_expr with eexpr = TLocal(temp_var)} in
+			let mk_temp_assign right = { a_expr with eexpr = TBinop(OpAssign, temp_local, right)} in
+			let etry = mk_temp_assign etry in
+			let catches = List.map (fun (v,e)-> v, mk_temp_assign e) catches in
+			let new_try = { a_expr with eexpr = TTry(etry, catches)} in
+			let block = [temp_var_def; new_try; temp_local] in
+			let new_block = { a_expr with eexpr = TBlock(block)} in
+			forward_transform new_block ae
+		| (_, TObjectDecl(fields)) ->
+			let fields = List.map (fun (name,ex) -> name, trans true [] ex) fields in
+			let blocks = List.flatten (List.map (fun (_,ex) -> ex.a_blocks) fields) in
+			let fields = List.map (fun (name,ex) -> name, ex.a_expr) fields in
+			let r = { a_expr with eexpr = (TObjectDecl(fields) )} in
+			lift_expr ~blocks r
+		| (_, TArrayDecl(values)) ->
+			let values = List.map (trans true []) values in
+			let blocks = List.flatten (List.map (fun (v) -> v.a_blocks) values) in
+			let exprs = List.map (fun (v) -> v.a_expr) values in
+			let r = { a_expr with eexpr = TArrayDecl exprs } in
+			lift_expr ~blocks:blocks r
+		| (is_value, TCast(e1,Some mt)) ->
+			let e = Codegen.default_cast ~vtmp:(ae.a_next_id()) (match !como with Some com -> com | None -> assert false) e1 mt ae.a_expr.etype ae.a_expr.epos in
+			transform_expr ~is_value:is_value e
+		| (is_value, TCast(e,None)) ->
+			let e = trans is_value [] e in
+			let r = { a_expr with eexpr = TCast(e.a_expr, None)} in
+			lift_expr ~blocks:e.a_blocks r
+		| (_, TField(e,f)) ->
+			let e = trans true [] e in
+			let r = { a_expr with eexpr = TField(e.a_expr, f) } in
+			lift_expr ~blocks:e.a_blocks r
+		| (is_value, TMeta(m, e)) ->
+			let e = trans is_value [] e in
+			let r = { a_expr with eexpr = TMeta(m, e.a_expr); etype = e.a_expr.etype } in
+			lift_expr ~blocks:e.a_blocks r
+		| ( _, TPatMatch _ ) -> assert false
+		| ( _, TLocal _ ) -> lift_expr a_expr
+
+		| ( _, TConst _ ) -> lift_expr a_expr
+		| ( _, TTypeExpr _ ) -> lift_expr a_expr
+		| ( _, TEnumParameter _ ) -> lift_expr a_expr
+		| ( _, TUnop _ ) -> assert false
+		| ( true, TWhile(econd, ebody, DoWhile) ) ->
+			let new_expr = trans false [] a_expr in
+			let f = exprs_to_func (new_expr.a_blocks @ [new_expr.a_expr]) (ae.a_next_id()) ae in
+			lift_expr ~is_value:true ~blocks:f.a_blocks f.a_expr
+
+		| ( _, TBreak ) | ( _, TContinue ) ->
+			lift_expr a_expr
+
+	and transform e =
+		to_expr (transform1 (lift_expr e))
+
+	and forward_transform e base =
+		transform1 (lift_expr1 base.a_is_value base.a_next_id base.a_blocks e)
+
+	let transform_to_value e =
+		to_expr (transform1 (lift_expr e ~is_value:true))
+
+end
+
+module Printer = struct
+
+	type print_context = {
+		pc_indent : string;
+		pc_next_anon_func : unit -> string;
+		pc_debug : bool;
+	}
+
+	let create_context =
+		let n = ref (-1) in
+		(fun indent debug -> {
+				pc_indent = indent;
+				pc_next_anon_func = (fun () -> incr n; Printf.sprintf "anon_%i" !n);
+				pc_debug = debug;
+			}
+		)
+
+	let tabs = ref ""
+
+	let opt o f s = match o with
+		| None -> ""
+		| Some v -> s ^ (f v)
+
+	(* TODO: both of these are crazy *)
+
+	let is_type p t =
+		(fun r ->
+			let x = t_infos r in
+			(String.concat "." (fst x.mt_path)) = p && (snd x.mt_path) = t
+		)
+
+	let is_type1 p s =
+		(fun t -> match follow t with
+			| TInst(c,_) -> (is_type p s)(TClassDecl c)
+			| TAbstract(a,_) -> (is_type p s)(TAbstractDecl a)
+			| TEnum(en,_) -> (is_type p s)(TEnumDecl en)
+			| _ -> false
+		)
+
+	let is_underlying_string t = match follow t with
+		| TAbstract(a,tl) -> (is_type1 "" "String")(Codegen.Abstract.get_underlying_type a tl)
+		| _ -> false
+
+	let handle_keywords s =
+		KeywordHandler.handle_keywords s
+
+	let print_unop = function
+		| Increment | Decrement -> assert false
+		| Not -> "not "
+		| Neg -> "-";
+		| NegBits -> "~"
+
+	let print_binop = function
+		| OpAdd -> "+"
+		| OpSub -> "-"
+		| OpMult -> "*"
+		| OpDiv -> "/"
+		| OpAssign -> "="
+		| OpEq -> "=="
+		| OpNotEq -> "!="
+		| OpGt -> ">"
+		| OpGte -> ">="
+		| OpLt -> "<"
+		| OpLte -> "<="
+		| OpAnd -> "&"
+		| OpOr -> "|"
+		| OpXor -> "^"
+		| OpBoolAnd -> "and"
+		| OpBoolOr -> "or"
+		| OpShl -> "<<"
+		| OpShr -> ">>"
+		| OpUShr -> ">>"
+		| OpMod -> "%"
+		| OpInterval | OpArrow | OpAssignOp _ -> assert false
+
+	let print_string s =
+		Printf.sprintf "\"%s\"" (Ast.s_escape s)
+
+	let print_constant = function
+		| TThis -> "self"
+		| TNull -> "None"
+		| TBool(true) -> "True"
+		| TBool(false) -> "False"
+		| TString(s) -> print_string s
+		| TInt(i) -> Int32.to_string i
+		| TFloat s -> s
+		| TSuper -> "super"
+
+	let print_base_type tp =
+		try
+			begin match Meta.get Meta.Native tp.mt_meta with
+				| _,[EConst(String s),_],_ -> s
+				| _ -> raise Not_found
+			end
+		with Not_found ->
+			let pack,name = tp.mt_path in
+			(String.concat "_" pack) ^ (if pack = [] then name else "_" ^ name)
+
+	let print_module_type mt = print_base_type (t_infos mt)
+
+	let print_metadata (name,_,_) =
+		Printf.sprintf "@%s" name
+
+	let print_args args =
+		let had_value = ref false in
+		let sl = List.map (fun (v,cto) ->
+			let name = handle_keywords v.v_name in
+			let arg_string = match follow v.v_type with
+				| TAbstract({a_path = ["python"],"KwArgs"},_) -> "**" ^ name
+				| TAbstract({a_path = ["python"],"VarArgs"},_) -> "*" ^ name
+				| _ -> name
+			in
+			let arg_value = match cto with
+				| None when !had_value -> " = None"
+				| None -> ""
+				| Some ct ->
+					had_value := true;
+					Printf.sprintf " = %s" (print_constant ct)
+			in
+			Printf.sprintf "%s%s" arg_string arg_value
+		) args in
+		String.concat "," sl
+
+	let rec print_op_assign_right pctx e =
+		match e.eexpr with
+			| TIf({eexpr = TParenthesis econd},eif,Some eelse)
+			| 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
+
+	and print_var pctx v eo =
+		match eo with
+			| Some {eexpr = TFunction tf} ->
+				print_function pctx tf (Some v.v_name)
+			| _ ->
+				let s_init = match eo with
+					| None -> "None"
+					| Some e -> print_op_assign_right pctx e
+				in
+				Printf.sprintf "%s = %s" (handle_keywords v.v_name) s_init
+
+	and print_function pctx tf name =
+		let s_name = match name with
+			| None -> pctx.pc_next_anon_func()
+			| Some s -> handle_keywords s
+		in
+		let s_args = print_args tf.tf_args in
+		let s_expr = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} tf.tf_expr in
+		Printf.sprintf "def %s(%s):\n%s\t%s" s_name s_args pctx.pc_indent s_expr
+
+	and print_expr pctx e =
+		let indent = pctx.pc_indent in
+		let print_expr_indented e = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e in
+		match e.eexpr with
+			| TConst ct ->
+				print_constant ct
+			| TTypeExpr mt ->
+				print_module_type mt
+			| TLocal v ->
+				handle_keywords v.v_name
+			| TEnumParameter(e1,_,index) ->
+				Printf.sprintf "%s.params[%i]" (print_expr pctx e1) index
+			| TArray(e1,e2) ->
+				Printf.sprintf "HxOverrides.arrayGet(%s, %s)" (print_expr pctx e1) (print_expr pctx e2)
+			| TBinop(OpAssign,{eexpr = TArray(e1,e2)},e3) ->
+				Printf.sprintf "HxOverrides.arraySet(%s,%s,%s)" (print_expr pctx e1) (print_expr pctx e2) (print_expr pctx 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)
+			| 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 "_hx_c.Std._hx_is(%s, _hx_builtin.str)" (print_expr pctx e1)
+							| "boolean" -> Printf.sprintf "_hx_c.Std._hx_is(%s, _hx_builtin.bool)" (print_expr pctx e1)
+							| "number" -> Printf.sprintf "_hx_c.Std._hx_is(%s, _hx_builtin.float)" (print_expr pctx e1)
+							| _ -> assert false
+						end
+					| _ ->
+						assert false
+				end
+			| TBinop(OpEq,e1,({eexpr = TConst TNull} as e2)) ->
+				Printf.sprintf "(%s is %s)" (print_expr pctx e1) (print_expr pctx e2)
+			| TBinop(OpNotEq,e1,({eexpr = TConst TNull} as e2)) ->
+				Printf.sprintf "(%s is not %s)" (print_expr pctx e1) (print_expr pctx e2)
+			| TBinop(OpMod,e1,e2) when (is_type1 "" "Int")(e1.etype) && (is_type1 "" "Int")(e2.etype) ->
+				Printf.sprintf "(%s %% %s)" (print_expr pctx e1) (print_expr pctx e2)
+			| TBinop(OpMod,e1,e2) ->
+				Printf.sprintf "HxOverrides.modf(%s, %s)" (print_expr pctx e1) (print_expr pctx e2)
+			| 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)
+				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);
+			| TBinop(op,e1,e2) ->
+				Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (print_binop op) (print_expr pctx e2)
+			| TField(e1,fa) ->
+				print_field pctx e1 fa false
+			| TParenthesis e1 ->
+				Printf.sprintf "(%s)" (print_expr pctx e1)
+			| TObjectDecl fl ->
+				let fl2 = ref fl in
+				begin match follow e.etype with
+					| TAnon an ->
+						PMap.iter (fun s cf ->
+							if not (List.mem_assoc s fl) then fl2 := (s,null cf.cf_type cf.cf_pos) :: !fl2
+						) an.a_fields
+					| _ ->
+						()
+				end;
+				Printf.sprintf "_hx_c._hx_AnonObject(%s)" (print_exprs_named pctx ", " !fl2)
+			| TArrayDecl el ->
+				Printf.sprintf "[%s]" (print_exprs pctx ", " el)
+			| TCall(e1,el) ->
+				print_call pctx e1 el
+			| TNew(c,_,el) ->
+				let id = print_base_type (t_infos (TClassDecl c)) in
+				Printf.sprintf "%s(%s)" id (print_exprs pctx ", " el)
+			| TUnop(Not,Prefix,e1) ->
+				Printf.sprintf "(%s%s)" (print_unop Not) (print_expr pctx e1)
+			| TUnop(op,Prefix,e1) ->
+				Printf.sprintf "%s%s" (print_unop op) (print_expr pctx e1)
+			| TFunction tf ->
+				print_function pctx tf None
+			| TVar (v,eo) ->
+				print_var pctx v eo
+			| TBlock [] ->
+				Printf.sprintf "pass\n%s" indent
+			| TBlock [{ eexpr = TBlock _} as b] ->
+				print_expr pctx b
+			| TBlock el ->
+				let old = !tabs in
+				tabs := pctx.pc_indent;
+				let s = print_block_exprs pctx ("\n" ^ !tabs) pctx.pc_debug el in
+				tabs := old;
+				Printf.sprintf "%s\n" s
+			| TIf(econd,eif,(Some {eexpr = TIf _} as eelse)) ->
+				print_if_else pctx econd eif eelse true
+			| TIf(econd,eif,eelse) ->
+				print_if_else pctx econd eif eelse false
+			| TWhile(econd,e1,NormalWhile) ->
+				Printf.sprintf "while %s:\n%s\t%s" (print_expr pctx econd) indent (print_expr_indented e1)
+			| TWhile(econd,e1,DoWhile) ->
+				error "Currently not supported" e.epos
+			| TTry(e1,catches) ->
+				print_try pctx e1 catches
+			| TReturn eo ->
+				Printf.sprintf "return%s" (opt eo (print_op_assign_right pctx) " ")
+			| TBreak ->
+				"break"
+			| TContinue ->
+				"continue"
+			| TThrow e1 ->
+				Printf.sprintf "raise _HxException(%s)" (print_expr pctx e1)
+			| TCast(e1,None) ->
+				print_expr pctx e1
+			| TMeta((Meta.Custom ":ternaryIf",_,_),{eexpr = TIf(econd,eif,Some eelse)}) ->
+				Printf.sprintf "%s if %s else %s" (print_expr pctx eif) (print_expr pctx econd) (print_expr pctx eelse)
+			| TMeta(_,e1) ->
+				print_expr pctx e1
+			| TPatMatch _ | TSwitch _ | TCast(_, Some _) | TFor _ | TUnop(_,Postfix,_) ->
+				assert false
+
+	and print_if_else pctx econd eif eelse as_elif =
+		let econd1 = match econd.eexpr with
+			| TParenthesis e -> e
+			| _ -> econd
+		in
+		let if_str = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} eif in
+		let indent = pctx.pc_indent in
+		let else_str = if as_elif then
+			opt eelse (print_expr pctx) "el"
+		else
+			opt eelse (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent}) (Printf.sprintf "else:\n%s\t" indent)
+		in
+		Printf.sprintf "if %s:\n%s\t%s\n%s%s" (print_expr pctx econd1) indent if_str indent else_str
+
+	and print_field pctx e1 fa is_assign =
+		let obj = match e1.eexpr with
+			| TConst TSuper -> "super()"
+			| _ -> print_expr pctx e1
+		in
+		let name = field_name fa in
+		let is_extern = (match fa with
+		| FInstance(c,_) -> c.cl_extern
+		| FStatic(c,_) -> c.cl_extern
+		| _ -> false)
+		in
+		let do_default () =
+			Printf.sprintf "%s.%s" obj (if is_extern then name else (handle_keywords name))
+		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 "_hx_builtin.len(%s)" (print_expr pctx e1)
+			| FInstance(c,{cf_name = "length"}) when (is_type "" "String")(TClassDecl c) ->
+				Printf.sprintf "_hx_builtin.len(%s)" (print_expr pctx e1)
+			| FStatic(c,{cf_name = "fromCharCode"}) when (is_type "" "String")(TClassDecl c) ->
+				Printf.sprintf "HxString.fromCharCode"
+			| FInstance _ | FStatic _ ->
+				do_default ()
+			| FAnon cf when name = "iterator" && not is_assign ->
+				begin match follow cf.cf_type with
+					| TFun([],_) ->
+						Printf.sprintf "_hx_functools.partial(HxOverrides.iterator, %s)" obj
+					| _ ->
+						do_default()
+				end
+			| FAnon cf when name = "shift" && not is_assign ->
+				begin match follow cf.cf_type with
+					| TFun([],_) ->
+						Printf.sprintf "_hx_functools.partial(HxOverrides.shift, %s)" obj
+					| _ ->
+						do_default()
+				end
+			| _ ->
+				do_default()
+
+	and print_try pctx e1 catches =
+		let print_catch pctx i (v,e) =
+			let indent = pctx.pc_indent in
+			let handle_base_type bt =
+				let t = print_base_type bt in
+				let res = if t = "String" then
+					Printf.sprintf "if _hx_builtin.isinstance(_hx_e1, str):\n%s\t%s = _hx_e1\n%s\t%s" indent v.v_name indent (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e)
+				else
+					Printf.sprintf "if _hx_builtin.isinstance(_hx_e1, %s):\n%s\t%s = _hx_e1\n%s\t%s" t indent v.v_name indent (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e)
+				in
+				if i > 0 then
+					indent ^ "el" ^ res
+				else
+					res
+			in
+			match follow v.v_type with
+				| TDynamic _ ->
+					Printf.sprintf "%sif True:\n%s\t%s = _hx_e1\n%s\t%s" (if i > 0 then indent ^ "el" else "") indent v.v_name indent (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e)
+				| TInst(c,_) ->
+					handle_base_type (t_infos (TClassDecl c))
+				| TEnum(en,_) ->
+					handle_base_type (t_infos (TEnumDecl en))
+				| _ ->
+					assert false
+		in
+		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 isinstance(_hx_e, _HxException) else _hx_e\n%s\t" indent indent in
+		let catch_str = String.concat (Printf.sprintf "\n%s\n" indent) (ExtList.List.mapi (fun i catch -> print_catch {pctx with pc_indent = "\t" ^ pctx.pc_indent} i catch) catches) in
+		let except_end = Printf.sprintf "\n%s\telse:\n%s\t\traise _hx_e" indent indent in
+		Printf.sprintf "%s%s%s%s" try_str except catch_str except_end
+
+	and print_call2 pctx e1 el =
+		let id = print_expr pctx e1 in
+		match id,el with
+			| "super",_ ->
+				let s_el = print_exprs pctx ", " el in
+				Printf.sprintf "super().__init__(%s)" s_el
+			| ("python_Syntax.pythonCode"),[e1] ->
+				begin match e1.eexpr with
+					| TConst (TString s) -> s
+					| e -> print_expr pctx e1
+				end
+			| "python_Syntax._callNamedUntyped",el ->
+				let res,fields = match List.rev el with
+					| {eexpr = TObjectDecl fields} :: el ->
+						List.rev el,fields
+					| _ ->
+						assert false
+				in
+				begin match res with
+					| e1 :: [] ->
+						Printf.sprintf "%s(%s)" (print_expr pctx e1) (print_params_named pctx ", " fields)
+					| e1 :: el ->
+						Printf.sprintf "%s(%s, %s)" (print_expr pctx e1) (print_exprs pctx ", " el) (print_params_named pctx ", " fields)
+					| [] ->
+						Printf.sprintf "%s(%s)" (print_expr pctx e1) (print_params_named pctx ", " fields)
+				end
+			| "python_Syntax.varArgs",[e1] ->
+				"*" ^ (print_expr pctx e1)
+			| "python_Syntax.call" ,e1 :: [{eexpr = TArrayDecl el}]->
+				Printf.sprintf "%s(%s)" (print_expr pctx e1) (print_exprs pctx ", " el)
+			| "python_Syntax.field",[e1;{eexpr = TConst(TString id)}] ->
+				Printf.sprintf "%s.%s" (print_expr pctx e1) id
+			| "python_Syntax.tuple", [{eexpr = TArrayDecl el}] ->
+				Printf.sprintf "(%s)" (print_exprs pctx ", " el)
+			| "python_Syntax._arrayAccess", e1 :: {eexpr = TArrayDecl el} :: etrail ->
+				let trailing_colon = match etrail with
+					| [{eexpr = TConst(TBool(true))}] -> true
+					| _ -> false
+				in
+				Printf.sprintf "%s[%s%s]" (print_expr pctx e1) (print_exprs pctx ":" el) (if trailing_colon then ":" else "")
+			| "python_Syntax.isIn",[e1;e2] ->
+				Printf.sprintf "%s in %s" (print_expr pctx e1) (print_expr pctx e2)
+			| "python_Syntax.delete",[e1] ->
+				Printf.sprintf "del %s" (print_expr pctx e1)
+			| "python_Syntax.binop",[e0;{eexpr = TConst(TString id)};e2] ->
+				Printf.sprintf "(%s %s %s)" (print_expr pctx e0) id (print_expr pctx e2)
+			| "python_Syntax.assign",[e0;e1] ->
+				Printf.sprintf "%s = %s" (print_expr pctx e0) (print_expr pctx e1)
+			| "python_Syntax.arraySet",[e1;e2;e3] ->
+				Printf.sprintf "%s[%s] = %s" (print_expr pctx e1) (print_expr pctx e2) (print_expr pctx e3)
+			| "python_Syntax._newInstance", e1 :: [{eexpr = TArrayDecl el}] ->
+				Printf.sprintf "%s(%s)" (print_expr pctx e1) (print_exprs pctx ", " el)
+			| "python_Syntax.opPow", [e1;e2] ->
+				Printf.sprintf "(%s ** %s)" (print_expr pctx e1) (print_expr pctx e2)
+ 			| "python_Syntax._foreach",[e1;e2;e3] ->
+				let pctx = {pctx with pc_indent = "\t" ^ pctx.pc_indent} in
+				let i = pctx.pc_indent in
+				Printf.sprintf "for %s in %s:\n%s%s" (print_expr pctx e1) (print_expr pctx e2) i (print_expr pctx e3)
+(* 			| "__new_named__",e1::el ->
+				Printf.sprintf "new %s(%s)" (print_expr pctx e1) (print_exprs pctx ", " el) *)
+(* 			| "__python_kwargs__",[e1] ->
+				"**" ^ (print_expr pctx e1) *)
+(* 			| "__named_arg__",[{eexpr = TConst (TString name)};e2] ->
+				Printf.sprintf "%s=%s" name (print_expr pctx e2) *)
+(* 			| "__assert__",el ->
+				Printf.sprintf "assert(%s)" (print_exprs pctx ", " el) *)
+(* 			| "__call_global__",{eexpr = TConst(TString s)} :: el ->
+				Printf.sprintf "%s(%s)" s (print_exprs pctx ", " el) *)
+(* 			| "__is__",[e1;e2] ->
+				Printf.sprintf "%s is %s" (print_expr pctx e1) (print_expr pctx e2) *)
+(* 			| "__as__",[e1;e2] ->
+				Printf.sprintf "%s as %s" (print_expr pctx e1) (print_expr pctx e2) *)
+(* 			| "__int_parse__",[e1] ->
+				Printf.sprintf "int.parse(%s)" (print_expr pctx e1) *)
+(* 			| "__double_parse__",[e1] ->
+				Printf.sprintf "double.parse(%s)" (print_expr pctx e1) *)
+(* 			| "__instanceof__",[e1;e2] ->
+				Printf.sprintf "_hx_c.Std._hx_is%s,%s" (print_expr pctx e1) (print_expr pctx e2) *)
+(* 			| "__strict_eq__",[e2;e3] ->
+				let e2 = match e2.eexpr with
+					| TBinop(OpOr,a,_) -> a
+					| _ -> e2
+				in
+				print_expr pctx {e1 with eexpr = TBinop(OpEq,e2,e3)} *)
+			| _,el ->
+				Printf.sprintf "%s(%s)" id (print_call_args pctx e1 el)
+
+	and print_call pctx e1 el =
+		match e1.eexpr, el with
+			| TField(e1,((FAnon {cf_name = "iterator"}) | FDynamic ("iterator"))), [] ->
+				Printf.sprintf "HxOverrides.iterator(%s)" (print_expr pctx e1)
+			| TField(e1,((FAnon {cf_name = ("toUpperCase" | "toLowerCase" as s)}) | FDynamic ("toUpperCase" | "toLowerCase" as s))), [] ->
+				Printf.sprintf "HxOverrides.%s(%s)" s (print_expr pctx e1)
+			| _,_ ->
+				print_call2 pctx e1 el
+
+	and print_call_args pctx e1 el =
+		let print_arg pctx i x =
+			let prefix = match e1.eexpr, follow x.etype with
+				(* the should not apply for the instance methods of the abstract itself *)
+				| TField(_, FStatic({cl_path = ["python"; "_KwArgs"],"KwArgs_Impl_"},f)), _ when i == 0 && Meta.has Meta.Impl f.cf_meta -> ""
+				| TField(_, FStatic({cl_path = ["python"; "_VarArgs"],"VarArgs_Impl_"},f)), _ when i == 0 && Meta.has Meta.Impl f.cf_meta -> ""
+				| _, TAbstract({a_path = ["python"],"KwArgs"},_) -> "**"
+				| _, TAbstract({a_path = ["python"],"VarArgs"},_) -> "*"
+				| _, _ -> ""
+			in
+			prefix ^ (print_expr pctx x)
+		in
+		String.concat "," (ExtList.List.mapi (print_arg pctx) el)
+
+	and print_exprs pctx sep el =
+		String.concat sep (List.map (print_expr pctx) el)
+
+	and print_block_exprs pctx sep print_debug_comment el =
+		if print_debug_comment then begin
+			let el = List.fold_left (fun acc e ->
+				let line = Lexer.get_error_line e.epos in
+				(print_expr pctx e) :: (Printf.sprintf "# %s:%i" e.epos.pfile line) :: acc
+			) [] el in
+			String.concat sep (List.rev el)
+		end else
+			print_exprs pctx sep el
+
+	and print_exprs_named pctx sep fl =
+		let args = String.concat sep (List.map (fun (s,e) -> Printf.sprintf "'%s': %s" (handle_keywords s) (print_expr pctx e)) fl) in
+		Printf.sprintf "{%s}" args
+	and print_params_named pctx sep fl =
+		let args = String.concat sep (List.map (fun (s,e) -> Printf.sprintf "%s= %s" (handle_keywords s) (print_expr pctx e)) fl) in
+		Printf.sprintf "%s" args
+	let handle_keywords s =
+		KeywordHandler.handle_keywords s
+end
+
+module Generator = struct
+	type context = {
+		com : Common.context;
+		buf : Buffer.t;
+		packages : (string,int) Hashtbl.t;
+		mutable static_inits : (unit -> unit) list;
+		mutable class_inits : (unit -> unit) list;
+		mutable indent_count : int;
+		transform_time : float;
+		print_time : float;
+	}
+
+	type class_field_infos = {
+		cfd_fields : string list;
+		cfd_props : string list;
+		cfd_methods : string list;
+	}
+
+	let mk_context com = {
+		com = com;
+		buf = Buffer.create 16000;
+		packages = Hashtbl.create 0;
+		static_inits = [];
+		class_inits = [];
+		indent_count = 0;
+		transform_time = 0.;
+		print_time = 0.;
+	}
+
+	(* Transformer interface *)
+
+	let transform_expr e =
+		let e = Codegen.UnificationCallback.run Transformer.check_unification e in
+		Transformer.transform e
+
+	let transform_to_value e =
+		let e = Codegen.UnificationCallback.run Transformer.check_unification e in
+		Transformer.transform_to_value e
+
+	(* Printer interface *)
+
+	let get_path mt =
+		Printer.print_base_type mt
+
+	let tfunc_str f pctx name =
+		Printer.print_function pctx f name
+
+	let texpr_str e pctx =
+		Printer.print_expr pctx e
+
+	let handle_keywords s =
+		Printer.handle_keywords s
+
+	(* Helper *)
+
+	let get_full_name mt =
+		(* TODO: haxe source is crazy *)
+		s_type_path mt.mt_path
+
+	let collect_class_field_data cfl =
+		let fields = DynArray.create () in
+		let props = DynArray.create () in
+		let methods = DynArray.create () in
+		List.iter (fun cf ->
+			match cf.cf_kind with
+				| Var({v_read = AccResolve}) ->
+					()
+				| Var({v_read = AccCall}) ->
+					if Meta.has Meta.IsVar cf.cf_meta then
+						DynArray.add fields cf.cf_name
+					else
+						DynArray.add props cf.cf_name
+				| Var _ ->
+					DynArray.add fields cf.cf_name
+				| _ ->
+					DynArray.add methods cf.cf_name
+		) cfl;
+		{
+			cfd_fields = DynArray.to_list fields;
+			cfd_props = DynArray.to_list props;
+			cfd_methods = DynArray.to_list methods;
+		}
+
+	let collect_class_statics_data cfl =
+		let fields = DynArray.create () in
+		List.iter (fun cf ->
+			if not (is_extern_field cf) then
+				DynArray.add fields cf.cf_name
+		) cfl;
+		DynArray.to_list fields
+
+	let filter_py_metas metas =
+		List.filter (fun (n,_,_) -> match n with Meta.Custom ":python" -> true | _ -> false) metas
+
+	let get_members_with_init_expr c =
+		List.filter (fun cf -> match cf.cf_kind with
+			| Var _ when is_extern_field cf -> false
+			| Var _ when cf.cf_expr = None -> true
+			| _ -> false
+		) c.cl_ordered_fields
+
+	(* Printing *)
+
+	let spr ctx s =
+		Buffer.add_string ctx.buf s
+
+	let spr_line ctx s =
+		Buffer.add_string ctx.buf s;
+		Buffer.add_string ctx.buf "\n"
+
+	let print ctx =
+		Printf.kprintf (fun s -> begin
+			Buffer.add_string ctx.buf s
+		end)
+
+	let newline ctx =
+		spr ctx "\n"
+
+
+	(* Generating functions *)
+
+	let gen_pre_code_meta ctx metadata =
+		try
+			begin match Meta.get (Meta.Custom ":preCode") metadata with
+				| _,[(EConst(String s)),_],_ -> spr ctx s
+				| _ -> raise Not_found
+			end
+		with Not_found ->
+			()
+
+	let gen_py_metas ctx metas indent =
+		List.iter (fun (n,el,_) ->
+			match el with
+				| [EConst(String s),_] ->
+					print ctx "%s@%s\n" indent s
+				| _ ->
+					assert false
+		) metas
+
+	let gen_expr ctx e field indent =
+		let pctx = Printer.create_context ("\t" ^ indent) ctx.com.debug in
+		let e = match e.eexpr with
+			| TFunction(f) ->
+				{e with eexpr = TBlock [e]}
+			| _ ->
+				e
+		in
+		let expr2 = transform_to_value e in
+		let name = "_hx_init_" ^ (String.concat "_" (ExtString.String.nsplit field ".")) in
+		let maybe_split_expr expr2 = match expr2.eexpr with
+			| TBlock es when es <> [] && field <> "" ->
+				begin match List.rev es with
+					| e_last :: el ->
+						let new_last = {e_last with eexpr = TReturn (Some e_last)} in
+						let new_block = {expr2 with eexpr = TBlock (List.rev (new_last :: el))} in
+						let v_name = alloc_var name (tfun [] e_last.etype) in
+						let f_name = mk (TLocal v_name) v_name.v_type e_last.epos in
+						let call_f = mk (TCall(f_name,[])) e_last.etype e_last.epos in
+						Some new_block,call_f
+					| _ ->
+						assert false
+				end
+			| _ ->
+				None,expr2
+		in
+		let r = maybe_split_expr expr2 in
+		match r with
+			| Some e1,e2 ->
+				let expr_string_1 = texpr_str e1 pctx in
+				let expr_string_2 = texpr_str e2 pctx in
+				print ctx "%sdef %s():\n\t%s" indent name expr_string_1;
+				print ctx "%s%s = %s" indent field expr_string_2;
+			| None,e2 ->
+				let expr_string_2 = texpr_str e2 pctx in
+				if field = "" then
+					spr ctx expr_string_2
+				else
+					print ctx "%s%s = %s" indent field expr_string_2
+
+	let gen_func_expr ctx e c name metas extra_args indent stat =
+		let pctx = Printer.create_context indent ctx.com.debug in
+		let e = match e.eexpr with
+			| TFunction(f) ->
+				let args = List.map (fun s ->
+					alloc_var s t_dynamic,None
+				) extra_args in
+				{e with eexpr = TFunction {f with tf_args = args @ f.tf_args}}
+			| _ ->
+				e
+		in
+		let expr1 = transform_expr e in
+		let field_name = if stat then
+			Printf.sprintf "%s_statics_%s" (snd c.cl_path) name
+		else
+			name
+		in
+		let expr_string = match expr1.eexpr with
+			| TFunction f ->
+				tfunc_str f pctx (Some field_name)
+			| _ ->
+				Printf.sprintf "%s = %s" field_name (texpr_str expr1 pctx)
+		in
+		gen_py_metas ctx metas indent;
+		spr ctx indent;
+		spr ctx expr_string;
+		if stat then begin
+			print ctx "%s.%s = %s" (get_path (t_infos (TClassDecl c))) name field_name
+		end
+
+	let gen_class_constructor ctx c cf =
+		let member_inits = get_members_with_init_expr c in
+		newline ctx;
+		let py_metas = filter_py_metas cf.cf_meta in
+		begin match member_inits,cf.cf_expr with
+			| _,Some ({eexpr = TFunction f} as ef) ->
+				let ethis = mk (TConst TThis) (TInst(c,List.map snd c.cl_types)) cf.cf_pos in
+				let member_data = List.map (fun cf ->
+					let ef = mk (TField(ethis,FInstance(c, cf))) cf.cf_type cf.cf_pos in
+					mk (TBinop(OpAssign,ef,null ef.etype ef.epos)) ef.etype ef.epos
+				) member_inits in
+				let e = {f.tf_expr with eexpr = TBlock (member_data @ [f.tf_expr])} in
+				cf.cf_expr <- Some {ef with eexpr = TFunction {f with tf_expr = e}};
+			| _ ->
+				(* TODO: is this correct? *)
+				()
+		end;
+		gen_func_expr ctx (match cf.cf_expr with None -> assert false | Some e -> e) c "__init__" py_metas ["self"] "\t" false;
+		newline ctx
+
+	let gen_class_field ctx c p cf =
+		let field = handle_keywords cf.cf_name in
+		begin match cf.cf_expr with
+			| None ->
+				()(* print ctx "\t# var %s" field *)
+			| Some e ->
+				begin match cf.cf_kind with
+					| Method _ ->
+						let py_metas = filter_py_metas cf.cf_meta in
+						gen_func_expr ctx e c field py_metas ["self"] "\t" false;
+
+					| _ ->
+						gen_expr ctx e (Printf.sprintf "# var %s" field) "\t";
+				newline ctx;
+				end
+		end
+
+	let gen_static_field ctx c p cf =
+		let p = get_path (t_infos (TClassDecl c)) in
+		let field = handle_keywords cf.cf_name in
+		match cf.cf_expr with
+			| None ->
+				print ctx "%s.%s = None;\n" p field
+			| Some e ->
+				match cf.cf_kind with
+					| Method _ ->
+						let py_metas = filter_py_metas cf.cf_meta in
+						gen_func_expr ctx e c field py_metas [] "" true;
+						newline ctx
+					| _ ->
+						(let f = fun () ->
+							gen_expr ctx e (Printf.sprintf "%s.%s" p field) "";
+							newline ctx
+						in
+						ctx.static_inits <- f :: ctx.static_inits;)
+
+	let gen_class_data ctx c cfd p_super p_interfaces p p_name =
+		let field_str = String.concat "," (List.map (fun s -> "\"" ^ s ^ "\"") cfd.cfd_fields) in
+		let props_str = String.concat "," (List.map (fun s -> "\"" ^ s ^ "\"") cfd.cfd_props) in
+		let method_str = String.concat "," (List.map (fun s -> "\"" ^ s ^ "\"") cfd.cfd_methods) in
+		let statics_str =
+			let statics = collect_class_statics_data c.cl_ordered_statics in
+			String.concat "," (List.map (fun s -> "\"" ^ s ^ "\"") statics)
+		in
+
+		print ctx "%s._hx_class = %s\n" p p;
+		print ctx "%s._hx_class_name = \"%s\"\n" p p_name;
+		print ctx "_hx_classes[\"%s\"] = %s\n" p_name p;
+		print ctx "_hx_c.%s = %s\n" p p;
+		print ctx "%s._hx_fields = [%s]\n" p field_str;
+		print ctx "%s._hx_props = [%s]\n" p props_str;
+		print ctx "%s._hx_methods = [%s]\n" p method_str;
+		(* TODO: It seems strange to have a separation for member fields but a plain _hx_statics for static ones *)
+		print ctx "%s._hx_statics = [%s]\n" p statics_str;
+		print ctx "%s._hx_interfaces = [%s]\n" p (String.concat "," p_interfaces);
+		match p_super with
+			| None ->
+				()
+			| Some ps ->
+				print ctx "%s._hx_super = %s\n" p ps
+
+	let gen_class_empty_constructor ctx p cfl =
+		let s_name = p ^ "_hx_empty_init" in
+		print ctx "def %s (_hx_o):\n" s_name;
+		let found_fields = ref false in
+		List.iter (fun cf -> match cf.cf_kind with
+				| Var ({v_read = AccResolve | AccCall}) ->
+					()
+				| Var _ ->
+					found_fields := true;
+					print ctx "\t_hx_o.%s = None\n" (handle_keywords cf.cf_name)
+				| _ ->
+					()
+		) cfl;
+		if not !found_fields then
+			spr ctx "\tpass\n";
+		print ctx "%s._hx_empty_init = %s\n" p s_name
+
+	let gen_class_statics ctx c p =
+		List.iter (fun cf -> gen_static_field ctx c p cf) c.cl_ordered_statics
+
+
+	let gen_class_init ctx c =
+		match c.cl_init with
+			| None ->
+				()
+			| Some e ->
+				let f = fun () ->
+					let e = transform_expr e in
+					spr_line ctx (texpr_str e (Printer.create_context "" ctx.com.debug));
+				in
+				ctx.class_inits <- f :: ctx.class_inits
+
+	let gen_class ctx c =
+		gen_pre_code_meta ctx c.cl_meta;
+		(* print ctx "# print %s.%s\n" (s_type_path c.cl_module.m_path) (snd c.cl_path); *)
+		if not c.cl_extern then begin
+			let mt = (t_infos (TClassDecl c)) in
+			let p = get_path mt in
+			let p_name = get_full_name mt in
+			newline ctx;
+			print ctx "class %s" p;
+			let p_super = match c.cl_super with
+				| None ->
+					None
+				| Some (csup,_) ->
+					let p = get_path (t_infos (TClassDecl csup)) in
+					print ctx "(%s)" p;
+					Some p
+			in
+			let p_interfaces = List.map (fun (c,tl) ->
+				get_path (t_infos (TClassDecl c))
+			) c.cl_implements in
+			spr ctx ":";
+			spr ctx "\n";
+			begin match c.cl_constructor with
+				| Some cf -> gen_class_constructor ctx c cf;
+				| None -> ()
+			end;
+			List.iter (fun cf -> gen_class_field ctx c p cf) c.cl_ordered_fields;
+			let x = collect_class_field_data c.cl_ordered_fields in
+			let use_pass = match x.cfd_methods with
+				| [] -> c.cl_constructor = None
+				| _ -> c.cl_interface
+			in
+			if use_pass then spr_line ctx "\tpass\n";
+
+			gen_class_data ctx c x p_super p_interfaces p p_name;
+			gen_class_empty_constructor ctx p c.cl_ordered_fields;
+			gen_class_statics ctx c p;
+		end;
+		gen_class_init ctx c
+
+
+    let gen_enum_metadata ctx en p =
+        let meta = Codegen.build_metadata ctx.com (TEnumDecl en) in
+        match meta with
+            | None ->
+                ()
+            | Some e ->
+            	print ctx "%s.__meta__ = " p;
+                gen_expr ctx e "" "";
+                newline ctx
+
+	let gen_enum ctx en =
+		let mt = (t_infos (TEnumDecl en)) in
+		let p = get_path mt in
+		let p_name = get_full_name mt in
+		newline ctx;
+		print ctx "class %s(_hx_c.Enum):\n" p;
+		spr ctx "\tdef __init__(self, t, i, p):\n";
+		print ctx "\t\tsuper(%s,self).__init__(t, i, p)\n" p;
+		let enum_constructs = PMap.foldi (fun k ef acc ->
+			let f = handle_keywords ef.ef_name in
+			begin match follow ef.ef_type with
+				| TFun(args,_) ->
+					let print_args args =
+						let had_optional = ref false in
+						let sl = List.map (fun (n,o,_) ->
+							let name = handle_keywords n in
+							let arg_value = if !had_optional then
+								"= None"
+							else if o then begin
+								had_optional := true;
+								" = None"
+							end else
+								""
+							in
+							Printf.sprintf "%s%s" name arg_value
+						) args in
+						String.concat "," sl
+					in
+					let param_str = print_args args in
+					let args_str = String.concat "," (List.map (fun (n,_,_) -> handle_keywords n) args) in
+					print ctx "def _%s_statics_%s (%s):\n" p f param_str;
+					print ctx "\treturn %s(\"%s\", %i, [%s])\n" p ef.ef_name ef.ef_index args_str;
+					print ctx "%s.%s = _%s_statics_%s\n" p f p f;
+				| _ ->
+					(* TODO: haxe source has api.quoteString for ef.ef_name *)
+					print ctx "%s.%s = %s(\"%s\", %i, list())\n" p f p ef.ef_name ef.ef_index
+			end;
+			newline ctx;
+			ef :: acc
+		) en.e_constrs [] in
+		let fix = match enum_constructs with [] -> "" | _ -> "\"" 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 enum_constructs_str = fix ^ (String.concat ("\",\"") (List.map (fun ef -> ef.ef_name) enum_constructs)) ^ fix in
+		print ctx "%s._hx_constructs = [%s]\n" p enum_constructs_str;
+		print ctx "%s._hx_class = %s\n" p p;
+		print ctx "%s._hx_class_name = \"%s\"\n" p p_name;
+		print ctx "_hx_classes[\"%s\"] = %s\n" p_name p;
+		print ctx "_hx_c.%s = %s\n" p p;
+		gen_enum_metadata ctx en p
+
+	let gen_abstract ctx a =
+		gen_pre_code_meta ctx a.a_meta;
+		(* print ctx "# print %s.%s\n" (s_type_path a.a_module.m_path) (snd a.a_path); *)
+		newline ctx;
+		let mt = (t_infos (TAbstractDecl a)) in
+		let p = get_path mt in
+		let p_name = get_full_name mt in
+		print ctx "class %s" p;
+		spr ctx ":";
+		begin match a.a_impl with
+			| Some c ->
+				List.iter (fun cf ->
+					if cf.cf_name = "_new" then
+						gen_class_constructor ctx c cf
+					else
+						gen_class_field ctx c p cf
+				) c.cl_ordered_statics;
+			| None ->
+				spr_line ctx "\n\tpass\n";
+		end;
+
+		print ctx "%s._hx_class = %s\n" p p;
+		print ctx "%s._hx_class_name = \"%s\"\n" p p_name;
+		print ctx "_hx_classes[\"%s\"] = %s\n" p_name p;
+		print ctx "_hx_c.%s = %s\n" p p
+
+	let gen_type ctx mt = match mt with
+		| TClassDecl c -> gen_class ctx c
+		| TEnumDecl en -> gen_enum ctx en
+		| TAbstractDecl {a_path = [],"UInt"} -> ()
+		| TAbstractDecl a when Meta.has Meta.CoreType a.a_meta -> gen_abstract ctx a
+		| _ -> ()
+
+	(* Generator parts *)
+
+	let gen_resources ctx =
+		if Hashtbl.length ctx.com.resources > 0 then begin
+			spr ctx "def _hx_resources__():\n\treturn {";
+			let first = ref true in
+			Hashtbl.iter (fun k v ->
+				let prefix = if !first then begin
+					first := false;
+					"";
+				end else
+					","
+				in
+				print ctx "%s'%s': open('%%s.%%s'%%(__file__,'%s'),'rb').read()" prefix k k;
+				Std.output_file (ctx.com.file ^ "." ^ k) v
+			) ctx.com.resources;
+			spr ctx "}\n"
+		end
+
+	let gen_types ctx =
+		let used_paths = Hashtbl.create 0 in
+		let find_type path =
+			Hashtbl.add used_paths path true;
+			Utils.find_type ctx.com path
+		in
+		gen_type ctx (find_type (["python"],"Boot"));
+		gen_type ctx (find_type ([],"Enum"));
+		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
+		) ctx.com.types
+
+	let gen_static_inits ctx =
+		List.iter (fun f -> f()) (List.rev ctx.static_inits)
+
+	let gen_class_inits ctx =
+		List.iter (fun f -> f()) (List.rev ctx.class_inits)
+
+	let gen_main ctx =
+		match ctx.com.main with
+			| None ->
+				()
+			| Some e ->
+				gen_expr ctx e "" ""
+
+	(* Entry point *)
+
+	let run com =
+		Transformer.init com;
+		let ctx = mk_context com in
+		gen_resources ctx;
+		gen_types ctx;
+		gen_class_inits ctx;
+		gen_static_inits ctx;
+		gen_main ctx;
+
+		mkdir_from_path com.file;
+		let ch = open_out_bin com.file in
+		output_string ch (Buffer.contents ctx.buf);
+		close_out ch
+end
+
+let generate com =
+	Generator.run com

+ 14 - 5
main.ml

@@ -1004,6 +1004,9 @@ try
 			cp_libs := "hxjava" :: !cp_libs;
 			cp_libs := "hxjava" :: !cp_libs;
 			set_platform Java dir;
 			set_platform Java dir;
 		),"<directory> : generate Java code into target directory");
 		),"<directory> : generate Java code into target directory");
+		("-python",Arg.String (fun dir ->
+			set_platform Python dir;
+		),"<directory> : generate Python code into target directory");
 		("-xml",Arg.String (fun file ->
 		("-xml",Arg.String (fun file ->
 			Parser.use_doc := true;
 			Parser.use_doc := true;
 			xml_out := Some file
 			xml_out := Some file
@@ -1345,13 +1348,16 @@ try
 			Gencs.before_generate com;
 			Gencs.before_generate com;
 			add_std "cs"; "cs"
 			add_std "cs"; "cs"
 		| Java ->
 		| Java ->
-      let old_flush = ctx.flush in
-      ctx.flush <- (fun () ->
-        List.iter (fun (_,_,close,_,_) -> close()) com.java_libs;
-        old_flush()
-      );
+			let old_flush = ctx.flush in
+			ctx.flush <- (fun () ->
+				List.iter (fun (_,_,close,_,_) -> close()) com.java_libs;
+				old_flush()
+			);
 			Genjava.before_generate com;
 			Genjava.before_generate com;
 			add_std "java"; "java"
 			add_std "java"; "java"
+		| Python ->
+			add_std "python";
+			"python"
 	) in
 	) in
 	(* if we are at the last compilation step, allow all packages accesses - in case of macros or opening another project file *)
 	(* if we are at the last compilation step, allow all packages accesses - in case of macros or opening another project file *)
 	if com.display <> DMNone && not ctx.has_next then com.package_rules <- PMap.foldi (fun p r acc -> match r with Forbidden -> acc | _ -> PMap.add p r acc) com.package_rules PMap.empty;
 	if com.display <> DMNone && not ctx.has_next then com.package_rules <- PMap.foldi (fun p r acc -> match r with Forbidden -> acc | _ -> PMap.add p r acc) com.package_rules PMap.empty;
@@ -1443,6 +1449,9 @@ try
 		| Java ->
 		| Java ->
 			Common.log com ("Generating Java in : " ^ com.file);
 			Common.log com ("Generating Java in : " ^ com.file);
 			Genjava.generate com;
 			Genjava.generate com;
+		| Python ->
+			Common.log com ("Generating python in : " ^ com.file);
+			Genpy.generate com;
 		);
 		);
 	end;
 	end;
 	Sys.catch_break false;
 	Sys.catch_break false;

+ 2 - 2
std/DateTools.hx

@@ -200,12 +200,12 @@ class DateTools {
 		return o.ms + 1000.0 * (o.seconds + 60.0 * (o.minutes + 60.0 * (o.hours + 24.0 * o.days)));
 		return o.ms + 1000.0 * (o.seconds + 60.0 * (o.minutes + 60.0 * (o.hours + 24.0 * o.days)));
 	}
 	}
 
 
-	#if (js || flash || php || cpp)
+	#if (js || flash || php || cpp || python)
 	/**
 	/**
 		Retrieve Unix timestamp value from Date components. Takes same argument sequence as the Date constructor.
 		Retrieve Unix timestamp value from Date components. Takes same argument sequence as the Date constructor.
 	**/
 	**/
 	public static #if (js || flash || php) inline #end function makeUtc(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ):Float {
 	public static #if (js || flash || php) inline #end function makeUtc(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ):Float {
-	    #if (js || flash)
+	    #if (js || flash || python)
 		   return untyped Date.UTC(year, month, day, hour, min, sec);
 		   return untyped Date.UTC(year, month, day, hour, min, sec);
 		#elseif php
 		#elseif php
 		   return untyped __call__("gmmktime", hour, min, sec, month + 1, day, year) * 1000;
 		   return untyped __call__("gmmktime", hour, min, sec, month + 1, day, year) * 1000;

+ 1 - 1
std/List.hx

@@ -159,7 +159,7 @@ class List<T> {
 		Returns an iterator on the elements of the list.
 		Returns an iterator on the elements of the list.
 	**/
 	**/
 	public function iterator() : Iterator<T> {
 	public function iterator() : Iterator<T> {
-		#if (java || cs)
+		#if (java || cs || python)
 		var h = h;
 		var h = h;
 		return cast {
 		return cast {
 			hasNext : function() {
 			hasNext : function() {

+ 22 - 0
std/StringTools.hx

@@ -50,6 +50,9 @@ class StringTools {
 			catch (e:Dynamic) throw e;
 			catch (e:Dynamic) throw e;
 		#elseif cs
 		#elseif cs
 			return cs.system.Uri.EscapeUriString(s);
 			return cs.system.Uri.EscapeUriString(s);
+		#elseif python
+			python.Syntax.pythonCode("from urllib.parse import quote");
+			return quote(s);
 		#else
 		#else
 			return null;
 			return null;
 		#end
 		#end
@@ -75,6 +78,9 @@ class StringTools {
 			catch (e:Dynamic) throw e;
 			catch (e:Dynamic) throw e;
 		#elseif cs
 		#elseif cs
 			return cs.system.Uri.UnescapeDataString(s);
 			return cs.system.Uri.UnescapeDataString(s);
+		#elseif python
+			python.Syntax.pythonCode("from urllib.parse import unquote");
+			return unquote(s);
 		#else
 		#else
 			return null;
 			return null;
 		#end
 		#end
@@ -163,6 +169,9 @@ class StringTools {
 		`s`, the result is false.
 		`s`, the result is false.
 	**/
 	**/
 	public static function isSpace( s : String, pos : Int ) : Bool {
 	public static function isSpace( s : String, pos : Int ) : Bool {
+		#if python
+		if (s.length == 0 || pos < 0 || pos >= s.length) return false;
+		#end
 		var c = s.charCodeAt( pos );
 		var c = s.charCodeAt( pos );
 		return (c > 8 && c < 14) || c == 32;
 		return (c > 8 && c < 14) || c == 32;
 	}
 	}
@@ -323,9 +332,18 @@ class StringTools {
 				n >>>= 4;
 				n >>>= 4;
 			} while( n > 0 );
 			} while( n > 0 );
 		#end
 		#end
+		#if python
+		if (digits != null && s.length < digits) {
+			var diff = digits - s.length;
+			for (_ in 0...diff) {
+				s = "0" + s;
+			}
+		}
+		#else
 		if( digits != null )
 		if( digits != null )
 			while( s.length < digits )
 			while( s.length < digits )
 				s = "0"+s;
 				s = "0"+s;
+		#end
 		return s;
 		return s;
 	}
 	}
 
 
@@ -358,6 +376,8 @@ class StringTools {
 			#else
 			#else
 		return (untyped s).charCodeAt(index);
 		return (untyped s).charCodeAt(index);
 			#end
 			#end
+		#elseif python
+		return if (index >= s.length) -1 else untyped(ord(untyped s[index]));
 		#else
 		#else
 		return s.cca(index);
 		return s.cca(index);
 		#end
 		#end
@@ -379,6 +399,8 @@ class StringTools {
 		return c == -1;
 		return c == -1;
 		#elseif java
 		#elseif java
 		return c == -1;
 		return c == -1;
+		#elseif python
+		return c == -1;
 		#else
 		#else
 		return false;
 		return false;
 		#end
 		#end

+ 19 - 0
std/haxe/CallStack.hx

@@ -101,6 +101,14 @@ class CallStack {
 			return stack;
 			return stack;
 		#elseif cs
 		#elseif cs
 			return makeStack(new cs.system.diagnostics.StackTrace(1, true));
 			return makeStack(new cs.system.diagnostics.StackTrace(1, true));
+		#elseif python
+			var stack = [];
+			var infos = python.lib.Traceback.extract_stack();
+			infos.pop();
+			infos.reverse();
+			for (elem in infos)
+				stack.push(FilePos(null, elem._1, elem._2));
+			return stack;
 		#else
 		#else
 			return []; // Unsupported
 			return []; // Unsupported
 		#end
 		#end
@@ -159,6 +167,17 @@ class CallStack {
 			return stack;
 			return stack;
 		#elseif cs
 		#elseif cs
 			return makeStack(new cs.system.diagnostics.StackTrace(cs.internal.Exceptions.exception, true));
 			return makeStack(new cs.system.diagnostics.StackTrace(cs.internal.Exceptions.exception, true));
+		#elseif python
+			var stack = [];
+			var exc = python.lib.Sys.exc_info();
+			if (exc._3 != null)
+			{
+				var infos = python.lib.Traceback.extract_tb(exc._3);
+				infos.reverse();
+				for (elem in infos)
+					stack.push(FilePos(null, elem._1, elem._2));
+			}
+			return stack;
 		#else
 		#else
 			return []; // Unsupported
 			return []; // Unsupported
 		#end
 		#end

+ 4 - 2
std/haxe/Int32.hx

@@ -67,7 +67,7 @@ abstract Int32(Int) from Int to Int {
 
 
 	@:op(A - B) public static function floatSub(a:Float, b:Int32):Float;
 	@:op(A - B) public static function floatSub(a:Float, b:Int32):Float;
 
 
-	#if (as3 || flash8 || js || php)
+	#if (as3 || flash8 || js || php || python)
 
 
 	@:op(A * B) private static function mul(a:Int32, b:Int32):Int32
 	@:op(A * B) private static function mul(a:Int32, b:Int32):Int32
 		return clamp( a * (b & 0xFFFF) + clamp( a * (b >>> 16) << 16 ) );
 		return clamp( a * (b & 0xFFFF) + clamp( a * (b >>> 16) << 16 ) );
@@ -148,7 +148,7 @@ abstract Int32(Int) from Int to Int {
 	@:op(A >>> B) private static function ushrInt(a:Int32, b:Int):Int32;
 	@:op(A >>> B) private static function ushrInt(a:Int32, b:Int):Int32;
 	@:op(A >>> B) private static function intUshr(a:Int, b:Int32):Int32;
 	@:op(A >>> B) private static function intUshr(a:Int, b:Int32):Int32;
 
 
-	#if php
+	#if (php || python)
 
 
 	// PHP may be 64-bit, so shifts must be clamped
 	// PHP may be 64-bit, so shifts must be clamped
 	@:op(A << B) private static inline function shl(a:Int32, b:Int32):Int32
 	@:op(A << B) private static inline function shl(a:Int32, b:Int32):Int32
@@ -191,6 +191,8 @@ abstract Int32(Int) from Int to Int {
 		#elseif php
 		#elseif php
 		// we might be on 64-bit php, so sign extend from 32-bit
 		// we might be on 64-bit php, so sign extend from 32-bit
 		return (x << extraBits) >> extraBits;
 		return (x << extraBits) >> extraBits;
+		#elseif python
+		return (x + python.Syntax.opPow(2, 31)) % python.Syntax.opPow(2, 32) - python.Syntax.opPow(2, 31);
 		#else
 		#else
 		return (x);
 		return (x);
 		#end
 		#end

+ 2 - 0
std/haxe/Int64.hx

@@ -61,6 +61,8 @@ class Int64 {
 			return i | 0;
 			return i | 0;
 		#elseif php
 		#elseif php
 			return i32php(i); // handle overflow of 32-bit integers correctly
 			return i32php(i); // handle overflow of 32-bit integers correctly
+		#elseif python
+			return (i + python.Syntax.opPow(2, 31)) % python.Syntax.opPow(2, 32) - python.Syntax.opPow(2, 31);
 		#else
 		#else
 			return i;
 			return i;
 		#end
 		#end

+ 11 - 0
std/haxe/Log.hx

@@ -94,6 +94,17 @@ class Log {
 			#elseif java
 			#elseif java
 			untyped __java__("java.lang.System.out.println(str)");
 			untyped __java__("java.lang.System.out.println(str)");
 			#end
 			#end
+		#elseif (python)
+			var str:String = null;
+			if (infos != null) {
+				str = infos.fileName + ":" + Std.string(infos.lineNumber) + ": " + v;
+				if (infos.customParams != null) {
+					str += "," + infos.customParams.join(",");
+				}
+			} else {
+				str = v;
+			}
+			python.Lib.println(str);
 		#end
 		#end
 	}
 	}
 
 

+ 35 - 0
std/haxe/Resource.hx

@@ -20,6 +20,10 @@
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
 package haxe;
 package haxe;
+#if python
+import haxe.io.Bytes;
+import haxe.io.BytesData;
+#end
 
 
 /**
 /**
 	Resource can be used to access resources that were added through the
 	Resource can be used to access resources that were added through the
@@ -34,6 +38,8 @@ class Resource {
 
 
 	#if (java || cs)
 	#if (java || cs)
 	@:keep static var content : Array<String>;
 	@:keep static var content : Array<String>;
+	#elseif python
+	static var content : python.lib.Dict<String, BytesData>;
 	#else
 	#else
 	static var content : Array<{ name : String, data : String, str : String }>;
 	static var content : Array<{ name : String, data : String, str : String }>;
 	#end
 	#end
@@ -67,6 +73,9 @@ class Resource {
 		#if (java || cs)
 		#if (java || cs)
 		for ( x in content )
 		for ( x in content )
 			names.push(x);
 			names.push(x);
+		#elseif python
+		for ( k in content.keys().iter())
+			names.push(k);
 		#else
 		#else
 		for ( x in content )
 		for ( x in content )
 			names.push(x.name);
 			names.push(x.name);
@@ -92,6 +101,18 @@ class Resource {
 		if (str != null)
 		if (str != null)
 			return new cs.io.NativeInput(str).readAll().toString();
 			return new cs.io.NativeInput(str).readAll().toString();
 		return null;
 		return null;
+		#elseif python
+        #if embed_resources
+		for( k in content.keys().iter() )
+			if( k == name ) {
+				var b : haxe.io.Bytes = haxe.crypto.Base64.decode(content.get(k, null));
+				return b.toString();
+
+			}
+		return null;
+        #else
+        return content.hasKey(name) ? Bytes.ofData(content.get(name,null)).toString() : null;
+        #end
 		#else
 		#else
 		for( x in content )
 		for( x in content )
 			if( x.name == name ) {
 			if( x.name == name ) {
@@ -126,6 +147,18 @@ class Resource {
 		if (str != null)
 		if (str != null)
 			return new cs.io.NativeInput(str).readAll();
 			return new cs.io.NativeInput(str).readAll();
 		return null;
 		return null;
+		#elseif python
+        #if embed_resources
+		for( k in content.keys().iter() )
+			if( k == name ) {
+				var b : haxe.io.Bytes = haxe.crypto.Base64.decode(content.get(k, null));
+				return b;
+
+			}
+        #else
+        return Bytes.ofData(content.get(name,null));
+        #end
+		return null;
 		#else
 		#else
 		for( x in content )
 		for( x in content )
 			if( x.name == name ) {
 			if( x.name == name ) {
@@ -150,6 +183,8 @@ class Resource {
 		null;
 		null;
 		#elseif (java || cs)
 		#elseif (java || cs)
 		//do nothing
 		//do nothing
+		#elseif python
+		content = untyped _hx_resources__();
 		#else
 		#else
 		content = untyped __resources__();
 		content = untyped __resources__();
 		#end
 		#end

+ 12 - 12
std/haxe/Serializer.hx

@@ -252,14 +252,14 @@ class Serializer {
 			}
 			}
 			if( useCache && serializeRef(v) )
 			if( useCache && serializeRef(v) )
 				return;
 				return;
-			switch( #if (neko || cs) Type.getClassName(c) #else c #end ) {
-			case #if (neko || cs) "Array" #else cast Array #end:
+			switch( #if (neko || cs || python) Type.getClassName(c) #else c #end ) {
+			case #if (neko || cs || python) "Array" #else cast Array #end:
 				var ucount = 0;
 				var ucount = 0;
 				buf.add("a");
 				buf.add("a");
-				#if flash9
+				#if (flash9 || python)
 				var v : Array<Dynamic> = v;
 				var v : Array<Dynamic> = v;
 				#end
 				#end
-				var l = #if (neko || flash9 || php || cs || java) v.length #elseif cpp v.__length() #else v[untyped "length"] #end;
+				var l = #if (neko || flash9 || php || cs || java || python) v.length #elseif cpp v.__length() #else v[untyped "length"] #end;
 				for( i in 0...l ) {
 				for( i in 0...l ) {
 					if( v[i] == null )
 					if( v[i] == null )
 						ucount++;
 						ucount++;
@@ -285,17 +285,17 @@ class Serializer {
 					}
 					}
 				}
 				}
 				buf.add("h");
 				buf.add("h");
-			case #if (neko || cs) "List" #else cast List #end:
+			case #if (neko || cs || python) "List" #else cast List #end:
 				buf.add("l");
 				buf.add("l");
 				var v : List<Dynamic> = v;
 				var v : List<Dynamic> = v;
 				for( i in v )
 				for( i in v )
 					serialize(i);
 					serialize(i);
 				buf.add("h");
 				buf.add("h");
-			case #if (neko || cs) "Date" #else cast Date #end:
+			case #if (neko || cs || python) "Date" #else cast Date #end:
 				var d : Date = v;
 				var d : Date = v;
 				buf.add("v");
 				buf.add("v");
 				buf.add(d.toString());
 				buf.add(d.toString());
-			case #if (neko || cs) "haxe.ds.StringMap" #else cast haxe.ds.StringMap #end:
+			case #if (neko || cs || python) "haxe.ds.StringMap" #else cast haxe.ds.StringMap #end:
 				buf.add("b");
 				buf.add("b");
 				var v : haxe.ds.StringMap<Dynamic> = v;
 				var v : haxe.ds.StringMap<Dynamic> = v;
 				for( k in v.keys() ) {
 				for( k in v.keys() ) {
@@ -303,7 +303,7 @@ class Serializer {
 					serialize(v.get(k));
 					serialize(v.get(k));
 				}
 				}
 				buf.add("h");
 				buf.add("h");
-			case #if (neko || cs) "haxe.ds.IntMap" #else cast haxe.ds.IntMap #end:
+			case #if (neko || cs || python) "haxe.ds.IntMap" #else cast haxe.ds.IntMap #end:
 				buf.add("q");
 				buf.add("q");
 				var v : haxe.ds.IntMap<Dynamic> = v;
 				var v : haxe.ds.IntMap<Dynamic> = v;
 				for( k in v.keys() ) {
 				for( k in v.keys() ) {
@@ -312,7 +312,7 @@ class Serializer {
 					serialize(v.get(k));
 					serialize(v.get(k));
 				}
 				}
 				buf.add("h");
 				buf.add("h");
-			case #if (neko || cs) "haxe.ds.ObjectMap" #else cast haxe.ds.ObjectMap #end:
+			case #if (neko || cs || python) "haxe.ds.ObjectMap" #else cast haxe.ds.ObjectMap #end:
 				buf.add("M");
 				buf.add("M");
 				var v : haxe.ds.ObjectMap<Dynamic,Dynamic> = v;
 				var v : haxe.ds.ObjectMap<Dynamic,Dynamic> = v;
 				for ( k in v.keys() ) {
 				for ( k in v.keys() ) {
@@ -327,7 +327,7 @@ class Serializer {
 					serialize(v.get(k));
 					serialize(v.get(k));
 				}
 				}
 				buf.add("h");
 				buf.add("h");
-			case #if (neko || cs) "haxe.io.Bytes" #else cast haxe.io.Bytes #end:
+			case #if (neko || cs || python) "haxe.io.Bytes" #else cast haxe.io.Bytes #end:
 				var v : haxe.io.Bytes = v;
 				var v : haxe.io.Bytes = v;
 				#if neko
 				#if neko
 				var chars = new String(base_encode(v.getData(),untyped BASE64.__s));
 				var chars = new String(base_encode(v.getData(),untyped BASE64.__s));
@@ -365,7 +365,7 @@ class Serializer {
 				buf.add(chars);
 				buf.add(chars);
 			default:
 			default:
 				if( useCache ) cache.pop();
 				if( useCache ) cache.pop();
-				if( #if flash9 try v.hxSerialize != null catch( e : Dynamic ) false #elseif (cs || java) Reflect.hasField(v, "hxSerialize") #else v.hxSerialize != null #end  ) {
+				if( #if flash9 try v.hxSerialize != null catch( e : Dynamic ) false #elseif (cs || java || python) Reflect.hasField(v, "hxSerialize") #else v.hxSerialize != null #end  ) {
 					buf.add("C");
 					buf.add("C");
 					serializeString(Type.getClassName(c));
 					serializeString(Type.getClassName(c));
 					if( useCache ) cache.push(v);
 					if( useCache ) cache.push(v);
@@ -456,7 +456,7 @@ class Serializer {
 				for( i in 0...l )
 				for( i in 0...l )
 					serialize(untyped __field__(v, __php__("params"), i));
 					serialize(untyped __field__(v, __php__("params"), i));
 			}
 			}
-			#elseif (java || cs)
+			#elseif (java || cs || python)
 			if( useEnumIndex ) {
 			if( useEnumIndex ) {
 				buf.add(":");
 				buf.add(":");
 				buf.add(Type.enumIndex(v));
 				buf.add(Type.enumIndex(v));

+ 1 - 1
std/haxe/Timer.hx

@@ -36,7 +36,7 @@ package haxe;
 	the child class.
 	the child class.
 **/
 **/
 class Timer {
 class Timer {
-	#if (flash || js || java)
+	#if (flash || js || java || python)
 
 
 	#if (flash || js)
 	#if (flash || js)
 		private var id : Null<Int>;
 		private var id : Null<Int>;

+ 7 - 0
std/haxe/ds/Vector.hx

@@ -66,6 +66,11 @@ abstract Vector<T>(VectorData<T>) {
 			this = new java.NativeArray(length);
 			this = new java.NativeArray(length);
 		#elseif cpp
 		#elseif cpp
 			this = untyped (new Array<T>()).__SetSizeExact(length);
 			this = untyped (new Array<T>()).__SetSizeExact(length);
+		#elseif python
+			this = new Array();
+			for (i in 0...length) {
+				this[i] = null;
+			}
 		#else
 		#else
 			this = [];
 			this = [];
 			untyped this.length = length;
 			untyped this.length = length;
@@ -112,6 +117,8 @@ abstract Vector<T>(VectorData<T>) {
 			return this.Length;
 			return this.Length;
 		#elseif java
 		#elseif java
 			return this.length;
 			return this.length;
+		#elseif python
+			return this.length;
 		#else
 		#else
 			return untyped this.length;
 			return untyped this.length;
 		#end
 		#end

+ 15 - 0
std/haxe/io/Bytes.hx

@@ -49,6 +49,8 @@ class Bytes {
 		return untyped b[pos];
 		return untyped b[pos];
 		#elseif java
 		#elseif java
 		return untyped b[pos] & 0xFF;
 		return untyped b[pos] & 0xFF;
+		#elseif python
+		return python.Syntax.arrayAccess(b, pos);
 		#else
 		#else
 		return b[pos];
 		return b[pos];
 		#end
 		#end
@@ -67,6 +69,8 @@ class Bytes {
 		b[pos] = cast v;
 		b[pos] = cast v;
 		#elseif cs
 		#elseif cs
 		b[pos] = cast v;
 		b[pos] = cast v;
+		#elseif python
+		python.Syntax.arraySet(b, pos, v & 0xFF);
 		#else
 		#else
 		b[pos] = v & 0xFF;
 		b[pos] = v & 0xFF;
 		#end
 		#end
@@ -87,6 +91,8 @@ class Bytes {
 		java.lang.System.arraycopy(src.b, srcpos, b, pos, len);
 		java.lang.System.arraycopy(src.b, srcpos, b, pos, len);
 		#elseif cs
 		#elseif cs
 		cs.system.Array.Copy(src.b, srcpos, b, pos, len);
 		cs.system.Array.Copy(src.b, srcpos, b, pos, len);
+		#elseif python
+		python.Syntax.pythonCode("self.b[pos:pos+len] = src.b[srcpos:srcpos+len]");
 		#elseif cpp
 		#elseif cpp
 		b.blit(pos, src.b, srcpos, len);
 		b.blit(pos, src.b, srcpos, len);
 		#else
 		#else
@@ -145,6 +151,8 @@ class Bytes {
 		var newarr = new cs.NativeArray(len);
 		var newarr = new cs.NativeArray(len);
 		cs.system.Array.Copy(b, pos, newarr, 0, len);
 		cs.system.Array.Copy(b, pos, newarr, 0, len);
 		return new Bytes(len, newarr);
 		return new Bytes(len, newarr);
+		#elseif python
+		return new Bytes(len, python.Syntax.arrayAccess(b, pos, pos+len) );
 		#else
 		#else
 		return new Bytes(len,b.slice(pos,pos+len));
 		return new Bytes(len,b.slice(pos,pos+len));
 		#end
 		#end
@@ -371,6 +379,8 @@ class Bytes {
 		return new Bytes(length, new cs.NativeArray(length));
 		return new Bytes(length, new cs.NativeArray(length));
 		#elseif java
 		#elseif java
 		return new Bytes(length, new java.NativeArray(length));
 		return new Bytes(length, new java.NativeArray(length));
+		#elseif python
+		return new Bytes(length, python.lib.Builtin.bytearray(length));
 		#else
 		#else
 		var a = new Array();
 		var a = new Array();
 		for( i in 0...length )
 		for( i in 0...length )
@@ -403,6 +413,11 @@ class Bytes {
 			return new Bytes(b.length, b);
 			return new Bytes(b.length, b);
 		}
 		}
 		catch (e:Dynamic) throw e;
 		catch (e:Dynamic) throw e;
+
+		#elseif python
+			var b:BytesData = python.lib.Builtin.bytearray(s, "UTF-8");
+			return new Bytes(b.length, b);
+
 		#else
 		#else
 		var a = new Array();
 		var a = new Array();
 		// utf16-decode and utf8-encode
 		// utf16-decode and utf8-encode

+ 3 - 0
std/haxe/io/BytesBuffer.hx

@@ -185,6 +185,9 @@ class BytesBuffer {
 		#elseif java
 		#elseif java
 		var buf = b.toByteArray();
 		var buf = b.toByteArray();
 		var bytes = new Bytes(buf.length, buf);
 		var bytes = new Bytes(buf.length, buf);
+		#elseif python
+		var buf = python.lib.Builtin.bytearray(b);
+		var bytes = new Bytes(buf.length, buf);
 		#else
 		#else
 		var bytes = new Bytes(b.length,b);
 		var bytes = new Bytes(b.length,b);
 		#end
 		#end

+ 2 - 0
std/haxe/io/BytesData.hx

@@ -34,6 +34,8 @@ package haxe.io;
 	typedef BytesData = java.NativeArray<java.StdTypes.Int8>;
 	typedef BytesData = java.NativeArray<java.StdTypes.Int8>;
 #elseif cs
 #elseif cs
 	typedef BytesData = cs.NativeArray<cs.StdTypes.UInt8>;
 	typedef BytesData = cs.NativeArray<cs.StdTypes.UInt8>;
+#elseif python
+	typedef BytesData = python.lib.ByteArray;
 #else
 #else
 	typedef BytesData = Array<Int>;
 	typedef BytesData = Array<Int>;
 #end
 #end

+ 3 - 0
std/haxe/io/BytesInput.hx

@@ -55,6 +55,9 @@ class BytesInput extends Input {
 		this.len = len;
 		this.len = len;
 		this.totlen = len;
 		this.totlen = len;
 		#end
 		#end
+		#if python
+		bigEndian = false;
+		#end
 	}
 	}
 
 
 	inline function get_position() : Int {
 	inline function get_position() : Int {

+ 3 - 0
std/haxe/io/BytesOutput.hx

@@ -39,6 +39,9 @@ class BytesOutput extends Output {
 		#else
 		#else
 		b = new BytesBuffer();
 		b = new BytesBuffer();
 		#end
 		#end
+		#if python
+		bigEndian = false;
+		#end
 	}
 	}
 
 
 	inline function get_length() : Int {
 	inline function get_length() : Int {

+ 3 - 3
std/haxe/io/Input.hx

@@ -203,7 +203,7 @@ class Input {
 		#elseif php
 		#elseif php
 			var a = untyped __call__('unpack', 'd', readString(8));
 			var a = untyped __call__('unpack', 'd', readString(8));
 			return a[1];
 			return a[1];
-		#elseif (flash || js)
+		#elseif (flash || js || python)
 		var bytes = [];
 		var bytes = [];
 		bytes.push(readByte());
 		bytes.push(readByte());
 		bytes.push(readByte());
 		bytes.push(readByte());
@@ -312,7 +312,7 @@ class Input {
 		var ch2 = readByte();
 		var ch2 = readByte();
 		var ch3 = readByte();
 		var ch3 = readByte();
 		var ch4 = readByte();
 		var ch4 = readByte();
-#if php
+#if (php || python)
         // php will overflow integers.  Convert them back to signed 32-bit ints.
         // php will overflow integers.  Convert them back to signed 32-bit ints.
         var n = bigEndian ? ch4 | (ch3 << 8) | (ch2 << 16) | (ch1 << 24) : ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24);
         var n = bigEndian ? ch4 | (ch3 << 8) | (ch2 << 16) | (ch1 << 24) : ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24);
         if (n & 0x80000000 != 0)
         if (n & 0x80000000 != 0)
@@ -344,7 +344,7 @@ class Input {
 	static var _double_of_bytes = cpp.Lib.load("std","double_of_bytes",2);
 	static var _double_of_bytes = cpp.Lib.load("std","double_of_bytes",2);
 #end
 #end
 
 
-#if (flash || js)
+#if (flash || js || python)
 	function getDoubleSig(bytes:Array<Int>)
 	function getDoubleSig(bytes:Array<Int>)
     {
     {
         return (((bytes[1]&0xF) << 16) | (bytes[2] << 8) | bytes[3] ) * 4294967296. +
         return (((bytes[1]&0xF) << 16) | (bytes[2] << 8) | bytes[3] ) * 4294967296. +

+ 2 - 0
std/haxe/unit/TestRunner.hx

@@ -84,6 +84,8 @@ class TestRunner {
 		#elseif java
 		#elseif java
 			var str:String = v;
 			var str:String = v;
 			untyped __java__("java.lang.System.out.print(str)");
 			untyped __java__("java.lang.System.out.print(str)");
+		#elseif python
+			python.Lib.print(v);
 		#end
 		#end
 	}
 	}
 
 

+ 452 - 0
std/python/Boot.hx

@@ -0,0 +1,452 @@
+package python;
+
+import python.internal.ArrayImpl;
+import python.internal.Internal;
+import python.internal.StringImpl;
+import python.internal.EnumImpl;
+import python.internal.HxOverrides;
+import python.internal.HxException;
+import python.internal.AnonObject;
+
+import python.Syntax;
+
+private extern class Set<T> {
+	public inline function has (v:T):Bool {
+		return python.Syntax.isIn(v, this);
+	}
+}
+
+
+@:preCode("
+import builtins as _hx_builtin
+import functools as _hx_functools
+import math as _hx_math
+
+_hx_classes = dict()
+
+class _hx_AnonObject(object):
+	def __init__(self, fields):
+		self.__dict__ = fields
+
+_hx_c = _hx_AnonObject({})
+
+_hx_c._hx_AnonObject = _hx_AnonObject
+")
+@:keep class Boot {
+
+	static function __init__ () {
+		Internal.importAsPrefixed("inspect", "boot_inspect");
+		Boot.inspect = Internal.pythonCodePrefixed("boot_inspect");
+		Boot.math = Internal.pythonCodePrefixed("math");
+		Boot.builtin = Internal.pythonCodePrefixed("builtin");
+	}
+
+	static inline function mathRound (v:Float) {
+		return math.floor(v + 0.5);
+	}
+
+	inline static function mkSet <T>(a:Array<T>):Set<T> return Syntax.callField(builtin, "set", a);
+
+	static var keywords:Set<String> = mkSet(
+	[
+		"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"
+	]);
+
+	inline static function arrayJoin <T>(x:Array<T>, sep:String):String {
+		return Syntax.field(sep, "join")(x.map(python.Boot.toString));
+	}
+
+	inline static function isInstance(o:Dynamic, x:Dynamic):Bool {
+		return Syntax.callField(builtin, "isinstance", o, x);
+	}
+
+	inline static function builtinStr(o:Dynamic):String {
+		return Syntax.callField(builtin, "str", o);
+	}
+
+	inline static function builtinHasAttr(o:Dynamic, x:String):Bool {
+		return Syntax.callField(builtin, "hasattr", o, x);
+	}
+
+	inline static function builtinGetAttr(o:Dynamic, x:String):Dynamic {
+		return Syntax.callField(builtin, "getattr", o, x);
+	}
+
+	inline static function isPyBool(o:Dynamic):Bool {
+		return isInstance(o, Syntax.field(builtin, "bool"));
+	}
+
+	inline static function isPyInt(o:Dynamic):Bool {
+		return isInstance(o, Syntax.field(builtin, "int"));
+	}
+
+	inline static function isPyFloat(o:Dynamic):Bool {
+		return isInstance(o, Syntax.field(builtin, "float"));
+	}
+
+	inline static function builtinLen(o:Dynamic):Int {
+		return Syntax.callField(builtin, "len", o);
+	}
+
+	inline static function builtinInt(o:Dynamic):Int {
+		return Syntax.callField(builtin, "int", o);
+	}
+
+	inline static function builtinCallable(o:Dynamic):Bool {
+		return Syntax.callField(builtin, "callable", o);
+	}
+
+	inline static function inspectGetMembers(o:Dynamic, f:String->Bool):Void {
+		Syntax.callField(inspect, "getmembers", o, f);
+	}
+
+	inline static function inspectIsClass(o:Dynamic):Bool {
+		return Syntax.callField(inspect, "isclass", o);
+	}
+
+	inline static function inspectIsFunction(o:Dynamic):Bool {
+		return Syntax.callField(inspect, "isclass", o);
+	}
+
+	inline static function inspectIsMethod(o:Dynamic):Bool {
+		return Syntax.callField(inspect, "isclass", o);
+	}
+
+	static var builtin:Dynamic;
+	static var inspect:Dynamic;
+	static var math:Dynamic;
+
+	static inline function isClass(o:Dynamic) : Bool {
+		return o != null && (o == String || inspectIsClass(o));
+	}
+
+	static inline function isAnonObject (o:Dynamic) {
+		return isInstance(o, AnonObject);
+	}
+
+	private static function _add_dynamic(a:Dynamic,b:Dynamic):Dynamic {
+		if (isInstance(a, String) || isInstance(b, String)) {
+			return toString1(a,"") + toString1(b,"");
+		}
+		return Syntax.binop(a, "+", b);
+	}
+
+	static function toString (o:Dynamic) {
+		return toString1(o, "");
+	}
+
+	private static function toString1(o:Dynamic,s:String):String {
+
+		if (s == null) s = "";
+		if( o == null ) return "null";
+
+		if( s.length >= 5 ) return "<...>"; // too much deep recursion
+
+		if (isInstance(o, String)) return o;
+
+		if (isPyBool(o)) {
+			if ((o:Bool)) return "true" else return "false";
+		}
+		if (isPyInt(o)) {
+			return builtinStr(o);
+		}
+		// 1.0 should be printed as 1
+		if (isPyFloat(o)) {
+			try {
+				if (o == builtinInt(o)) {
+					return builtinStr(mathRound(o));
+				} else {
+					return builtinStr(o);
+				}
+			} catch (e:Dynamic) {
+				return builtinStr(o);
+			}
+		}
+
+		if (inspectIsFunction(o) || inspectIsMethod(o)) return "<function>";
+
+		if (isInstance(o, Array))
+		{
+			var o1:Array<Dynamic> = o;
+			var l = o1.length;
+
+			var st = "[";
+			s += "\t";
+			for( i in 0...l ) {
+				var prefix = "";
+				if (i > 0) {
+					prefix = ",";
+				}
+				st += prefix + toString1(o1[i],s);
+			}
+			st += "]";
+			return st;
+		}
+		try {
+			if (builtinHasAttr(o, "toString")) {
+				return o.toString();
+			}
+		} catch (e:Dynamic) {
+
+		}
+
+		if (builtinHasAttr(o, "__class__"))
+		{
+
+			if (isInstance(o, AnonObject))
+			{
+				var toStr = null;
+				try
+				{
+					var fields = fields(o);
+					var fieldsStr = [for (f in fields) '$f : ${toString1(field(o,f), s+"\t")}'];
+					toStr = "{ " + arrayJoin(fieldsStr, ", ") + " }";
+				}
+				catch (e:Dynamic) {
+					return "{ ... }";
+				}
+
+				if (toStr == null)
+				{
+					return "{ ... }";
+				}
+				else
+				{
+					return toStr;
+				}
+
+			}
+			if (isInstance(o, Enum)) {
+
+				var o:EnumImpl = o;
+
+				var l = builtinLen(o.params);
+				var hasParams = l > 0;
+				if (hasParams) {
+					var paramsStr = "";
+					for (i in 0...l) {
+						var prefix = "";
+						if (i > 0) {
+							prefix = ",";
+						}
+						paramsStr += prefix + toString1(o.params[i],s);
+					}
+					return o.tag + "(" + paramsStr + ")";
+				} else {
+					return o.tag;
+				}
+			}
+
+
+			if (Internal.hasClassName(o) && 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 toStr = Internal.fieldClassName(o) + "( " + arrayJoin(fieldsStr, ", ") + " )";
+				return toStr;
+			}
+
+			if (Internal.hasClassName(o) && Syntax.field(Syntax.field(o, "__class__"), "__name__") == "type") {
+
+				var fields = getClassFields(o);
+				var fieldsStr = [for (f in fields) '$f : ${toString1(field(o,f), s+"\t")}'];
+
+				var toStr = "#" + Internal.fieldClassName(o) + "( " + arrayJoin(fieldsStr, ", ") + " )";
+				return toStr;
+			}
+			if (o == String) {
+				return "#String";
+			}
+
+			if (o == Array) {
+				return "#Array";
+			}
+
+			if (builtinCallable(o)) {
+				return "function";
+			}
+			try {
+				if (builtinHasAttr(o, "__repr__")) {
+					return Syntax.callField(o, "__repr__");
+				}
+			} catch (e:Dynamic) {}
+
+			if (builtinHasAttr(o, "__str__")) {
+				return Syntax.callField(o, "__str__", []);
+			}
+
+			if (builtinHasAttr(o, "__name__")) {
+				return Syntax.field(o, "__name__");
+			}
+			return "???";
+		} else {
+			try {
+				inspectGetMembers(o, function (_) return true);
+				return builtinStr(o);
+			} catch (e:Dynamic) {
+				return "???";
+			}
+		}
+	}
+
+	static function fields (o:Dynamic) {
+		var a = [];
+		if (o != null) {
+			if (Internal.hasFields(o)) {
+				var fields:Array<String> = Internal.fieldFields(o);
+				return fields.copy();
+			}
+			if (isInstance(o, AnonObject)) {
+
+				var d:Dynamic = Syntax.field(o, "__dict__");
+				var keys = d.keys();
+				var handler = unhandleKeywords;
+
+				Syntax.pythonCode("for k in keys:");
+				Syntax.pythonCode("	a.append(handler(k))");
+			}
+			else if (builtinHasAttr(o, "__dict__")) {
+				var a = [];
+				var d:Dynamic = Syntax.field(o, "__dict__");
+				var keys1  = d.keys();
+				Syntax.pythonCode("for k in keys1:");
+				Syntax.pythonCode("	a.append(k)");
+
+			}
+		}
+		return a;
+	}
+
+	static inline function isString (o:Dynamic):Bool {
+		return isInstance(o, String);
+	}
+
+	static inline function isArray (o:Dynamic):Bool {
+		return isInstance(o, Array);
+	}
+
+	static function field( o : Dynamic, field : String ) : Dynamic {
+		if (field == null) return null;
+
+		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);
+			case "charCodeAt" if (isString(o)): return StringImpl.charCodeAt.bind(o);
+			case "indexOf" if (isString(o)): return StringImpl.indexOf.bind(o);
+			case "lastIndexOf" if (isString(o)): return StringImpl.lastIndexOf.bind(o);
+			case "split" if (isString(o)): return StringImpl.split.bind(o);
+			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 "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);
+			case "copy" if (isArray(o)): return function () return ArrayImpl.copy(o);
+			case "iterator" if (isArray(o)): return ArrayImpl.iterator.bind(o);
+			case "insert" if (isArray(o)): return ArrayImpl.insert.bind(o);
+			case "join" if (isArray(o)): return function (sep) return ArrayImpl.join(o, sep);
+			case "toString" if (isArray(o)): return ArrayImpl.toString.bind(o);
+			case "pop" if (isArray(o)): return ArrayImpl.pop.bind(o);
+			case "push" if (isArray(o)): return ArrayImpl.push.bind(o);
+			case "unshift" if (isArray(o)): return ArrayImpl.unshift.bind(o);
+			case "indexOf" if (isArray(o)): return ArrayImpl.indexOf.bind(o);
+			case "lastIndexOf" if (isArray(o)): return ArrayImpl.lastIndexOf.bind(o);
+			case "remove" if (isArray(o)): return ArrayImpl.remove.bind(o);
+			case "reverse" if (isArray(o)): return ArrayImpl.reverse.bind(o);
+			case "shift" if (isArray(o)): return ArrayImpl.shift.bind(o);
+			case "slice" if (isArray(o)): return ArrayImpl.slice.bind(o);
+			case "sort" if (isArray(o)): return ArrayImpl.sort.bind(o);
+			case "splice" if (isArray(o)): return ArrayImpl.splice.bind(o);
+		}
+
+		var field = handleKeywords(field);
+		return if (builtinHasAttr(o, field)) builtinGetAttr(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 sc = getSuperClass(c);
+
+		if (sc == null) {
+			return f;
+		} else {
+			var scArr = getInstanceFields(sc);
+			var scMap = [for (f in scArr) f => f];
+			var res = [];
+			for (f1 in f) {
+				if (!scMap.exists(f1)) {
+					scArr.push(f1);
+				}
+			}
+
+			return scArr;
+		}
+	}
+
+	static function getSuperClass( c : Class<Dynamic> ) : Class<Dynamic> {
+		if( c == null )
+			return null;
+
+		try {
+			if (Internal.hasSuper(c)) {
+				return Internal.fieldSuper(c);
+			}
+			return null;
+		} catch (e:Dynamic) {
+
+		}
+		return null;
+
+	}
+
+	static function getClassFields( c : Class<Dynamic> ) : Array<String> {
+		if (Internal.hasStatics(c)) {
+			var x:Array<String> = Internal.fieldStatics(c);
+			return x.copy();
+		} else {
+			return [];
+		}
+	}
+
+
+
+	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) != "_") {
+			Internal.getPrefixed(name);
+		}
+		else name;
+	}
+
+	static var prefixLength = Internal.prefix().length;
+
+	static function unhandleKeywords(name:String):String {
+		if (name.substr(0,prefixLength) == Internal.prefix()) {
+			var real = name.substr(prefixLength);
+			if (keywords.has(real)) return real;
+		}
+		return name;
+	}
+
+}

+ 15 - 0
std/python/HaxeIterable.hx

@@ -0,0 +1,15 @@
+package python;
+
+
+import python.NativeIterable.NativeIterableRaw;
+
+class HaxeIterable<T> {
+
+	var x : NativeIterableRaw<T>;
+
+	public inline function new (x:NativeIterableRaw<T>) {
+		this.x = x;
+	}
+
+	public inline function iterator ():HaxeIterator<T> return new HaxeIterator(x.__iter__());
+}

+ 38 - 0
std/python/HaxeIterator.hx

@@ -0,0 +1,38 @@
+package python;
+
+import python.lib.Exceptions.StopIteration;
+import python.NativeIterator;
+
+
+class HaxeIterator<T>
+{
+	var it :NativeIteratorRaw<T>;
+	var x:Null<T> = null;
+	var has = false;
+	var checked = false;
+
+	public function new (it:NativeIteratorRaw<T>) {
+		this.it = it;
+	}
+
+	public inline function next ():T {
+		checked = false;
+		return x;
+	}
+
+	public function hasNext ():Bool {
+		if (checked) {
+			return has;
+		} else {
+			try {
+				x = it.__next__();
+				has = true;
+			} catch (s:StopIteration) {
+				has = false;
+				x = null;
+			}
+			checked = true;
+			return has;
+		}
+	}
+}

+ 23 - 0
std/python/KwArgs.hx

@@ -0,0 +1,23 @@
+
+package python;
+
+import python.lib.Dict;
+
+abstract KwArgs (Dict<String, Dynamic>)
+{
+	inline function new (d:Dict<String, Dynamic>) this = d;
+
+	@:to inline function toDict ():Dict<String, Dynamic>
+	{
+		return this;
+	}
+	@:from static inline function fromDict (d:Dict<String, Dynamic>):KwArgs
+	{
+		return new KwArgs(d);
+	}
+
+	public function get <V>(key:String, def:V):V
+	{
+		return this.get(key, def);
+	}
+}

+ 68 - 0
std/python/Lib.hx

@@ -0,0 +1,68 @@
+package python;
+
+import python.lib.Dict;
+import python.NativeStringTools;
+
+typedef PySys = python.lib.Sys;
+
+class Lib {
+
+	public static function print(v:Dynamic):Void {
+		var str = Std.string(v);
+
+		PySys.stdout.buffer.write( NativeStringTools.encode(str, "utf-8"));
+		PySys.stdout.flush();
+	}
+
+	public static function println(v:Dynamic):Void {
+		var str = Std.string(v);
+
+		PySys.stdout.buffer.write( NativeStringTools.encode('$str\n', "utf-8"));
+		PySys.stdout.flush();
+	}
+
+	public static function dictToAnon (v:Dict<String, Dynamic>):Dynamic
+	{
+		var o = {};
+		Syntax.assign(Syntax.field(o, "__dict__"), v);
+		return o;
+	}
+
+	@:access(python.Boot) public static function anonToDict (o:{}):Dynamic
+	{
+		return if (python.Boot.isAnonObject(o))
+		{
+			Syntax.field(o, "__dict__");
+		}
+		else null;
+
+	}
+
+	public static function toPythonIterable <T>(it:Iterable<T>):python.NativeIterable<T> {
+		return {
+			__iter__ : function () {
+				var it1 = it.iterator();
+				var self:NativeIterator<T> = null;
+				self = new NativeIterator({
+					__next__ : function ():T {
+					if (it1.hasNext()) {
+						return it1.next();
+					} else {
+						throw new python.lib.Exceptions.StopIteration();
+					}
+				},
+				__iter__ : function () return self
+				});
+				return self;
+			}
+		}
+	}
+
+	public static inline function toHaxeIterable <T>(it:NativeIterable<T>):HaxeIterable<T> {
+		return new HaxeIterable(it);
+	}
+
+	public static inline function toHaxeIterator <T>(it:NativeIterator<T>):HaxeIterator<T> {
+		return new HaxeIterator(it);
+	}
+}

+ 17 - 0
std/python/NativeArrayTools.hx

@@ -0,0 +1,17 @@
+package python;
+
+class NativeArrayTools {
+
+	public static inline function extend <T>(a:Array<T>, x:Array<T>):Void {
+		python.Syntax.field(a, "extend")(x);
+	}
+
+	public static inline function append <T>(a:Array<T>, x:T):Void {
+		python.Syntax.field(a, "append")(x);
+	}
+
+	public static inline function contains <T>(a:Array<T>, x:T):Bool {
+		return python.Syntax.isIn(x,a);
+	}
+
+}

+ 20 - 0
std/python/NativeIterable.hx

@@ -0,0 +1,20 @@
+
+package python;
+
+import python.HaxeIterable;
+import python.NativeIterator;
+
+abstract NativeIterable <T>(NativeIterableRaw<T>) to NativeIterableRaw<T> from NativeIterableRaw<T> {
+	@:to public static inline function toHaxeIterable <T>(p:NativeIterableRaw<T>):HaxeIterable<T> return new HaxeIterable(p);
+
+	//@:from public static inline function fromArray <T>(p:Array<T>):PyIterable<T> return cast p;
+
+	public inline function iterator <T>() return toHaxeIterable().iterator();
+
+	public function getNativeIterable <T>():NativeIterableRaw<T> return this;
+	public function getNativeIterator <T>():NativeIteratorRaw<T> return this.__iter__();
+
+}
+typedef NativeIterableRaw<T> = {
+	function __iter__():NativeIterator<T>;
+}

+ 19 - 0
std/python/NativeIterator.hx

@@ -0,0 +1,19 @@
+
+package python;
+
+import python.NativeIterable.NativeIterableRaw;
+
+abstract NativeIterator <T>(NativeIteratorRaw<T>) to NativeIteratorRaw<T> to NativeIterable<T> {
+	public inline function new (p:NativeIteratorRaw<T>) this = p;
+
+	@:to public static inline function toHaxeIterator <T>(p:NativeIteratorRaw<T>):HaxeIterator<T> return new HaxeIterator(p);
+	@:to public static inline function toNativeIterable <T>(p:NativeIteratorRaw<T>):NativeIterable<T> return p;
+
+	public function getNativeIteratorRaw <T>():NativeIteratorRaw<T> return this;
+}
+
+typedef NativeIteratorRaw<T> = {
+	> NativeIterableRaw<T>,
+	function __next__ ():T;
+	//function __iter__ ():NativeIterator<T>;
+}

+ 32 - 0
std/python/NativeStringTools.hx

@@ -0,0 +1,32 @@
+
+package python;
+
+import python.lib.Bytes;
+import python.lib.Tuple;
+
+class NativeStringTools {
+
+	public static function format (s:String, args:Array<Dynamic>):String
+	{
+		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 {
+		return (python.Syntax.callField(s, "encode", encoding, errors):Bytes);
+	}
+
+	public static inline function contains(s:String, e:String):Bool {
+		return python.Syntax.isIn(e,s);
+	}
+
+	public static inline function strip(s:String, ?chars:String):String
+	{
+		return python.Syntax.field(s, "strip")(chars);
+	}
+
+	public static inline function rpartition (s:String, sep:String):Tup3<String, String, String>
+	{
+		return python.Syntax.field(s, "rpartition")(sep);
+	}
+
+}

+ 136 - 0
std/python/Syntax.hx

@@ -0,0 +1,136 @@
+package python;
+
+#if macro
+import haxe.macro.Expr;
+import haxe.macro.Context;
+import haxe.macro.ExprTools;
+#end
+
+extern class Syntax {
+
+	#if macro
+	static var self = macro python.Syntax;
+	#end
+
+	@:noUsing macro public static function importModule (module:String):haxe.macro.Expr {
+		return macro ($self.pythonCode($v{"import " + module}):Void);
+	}
+
+	@:noUsing macro public static function importAs (module:String, className : String):haxe.macro.Expr
+	{
+		var n = className.split(".").join("_");
+		var e = "import " + module + " as " + n;
+		var e1 = "_hx_c."+n+" = "+n;
+
+		return macro ({
+			$self.pythonCode($v{e});
+			$self.pythonCode($v{e1});
+		}:Void);
+	}
+
+	@:noUsing
+	macro public static function newInstance (c:Expr, params:Array<Expr>):haxe.macro.Expr {
+		return macro $self._newInstance($c, $a{params});
+	}
+
+	static function _newInstance(c:Dynamic, args:Array<Dynamic>):Dynamic { return null; }
+
+	@:noUsing
+	public static function isIn(a:Dynamic, b:Dynamic):Bool { return false; }
+
+	@:noUsing
+	public static function delete(a:Dynamic):Void { }
+
+	@:noUsing
+	public static function binop(a:Dynamic, op:String, b:Dynamic):Dynamic { return null; }
+
+	@:noUsing
+	public static function assign(a:Dynamic, b:Dynamic):Void { }
+
+	@:noUsing
+	public static function pythonCode<T>(b:String):T { return null; };
+
+	@:noUsing
+	macro public static function arrayAccess(x:Expr, rest:Array<Expr>):ExprOf<Dynamic> {
+		return macro $self._arrayAccess($x, $a{rest});
+	}
+
+	@:noUsing
+	macro public static function arrayAccessWithTrailingColon(x:Expr, rest:Array<Expr>):ExprOf<Dynamic> {
+		return macro $self._arrayAccess($x, $a{rest}, true);
+	}
+
+	static function _arrayAccess(a:Dynamic, args:Array<Dynamic>, ?trailingColon:Bool = false):Dynamic { return null; }
+
+	@:noUsing
+	public static function arraySet(a:Dynamic, i:Dynamic, v:Dynamic):Dynamic { return null; }
+
+
+	static function _foreach(id:Dynamic, it:Dynamic, block:Dynamic):Dynamic { return null; }
+
+
+	@:noUsing
+	macro public static function foreach <T>(v:Expr, it:Expr, b:Expr):haxe.macro.Expr
+	{
+		var id = switch (v.expr) {
+			case EConst(CIdent(x)):x;
+			case _ : Context.error("unexpected " + ExprTools.toString(v) + ": const ident expected", v.pos);
+		}
+		var iter = try {
+			Context.typeof(macro $it.__iter__());
+			macro $it.__iter__().getNativeIteratorRaw();
+		} catch (e:Dynamic) {
+			macro $it.getNativeIteratorRaw();
+		};
+
+
+		return macro {
+			// the first 2 expressions are only used to create a typing context for the foreach construct
+			// TODO how can we get rid of them, so that they are not generated?
+			var $id = null;
+			if (false) $v = $iter.__next__();
+			$self._foreach($v, $it, $b);
+		}
+	}
+
+	@:noUsing macro public static function importFromAs (from:String, module:String, className : String):haxe.macro.Expr {
+
+		var n = className.split(".").join("_");
+
+		var e = "from " + from + " import " + module + " as " + n;
+		var e1 = "_hx_c."+n+" = " + n;
+		return macro ({
+			$self.pythonCode($v{e});
+			$self.pythonCode($v{e1});
+		}:Void);
+	}
+
+	@:noUsing
+	macro public static function callField(o:Expr, field:ExprOf<String>, params:Array<Expr>):haxe.macro.Expr {
+		return macro @:pos(o.pos) $self.call($self.field($o, $field), $a{params});
+	}
+
+	static function call(e:Dynamic, args:Array<Dynamic>):Dynamic { return null; }
+
+	@:noUsing
+	public static function field (o:Dynamic, field:String):Dynamic { return null; }
+
+	@:noUsing
+	macro public static function tuple(args:Array<Expr>):Dynamic {
+		var args = macro $a{args};
+		return macro $self._tuple($args);
+	}
+
+	static function _tuple(args:Array<Dynamic>):Dynamic { return null; }
+
+	@:noUsing
+	public static function varArgs(args:Array<Dynamic>):Dynamic { return null; }
+
+	macro public static function callNamedUntyped (e:Expr, args:Expr):Expr {
+		return macro @:pos(e.pos) $self._callNamedUntyped($e, $args);
+	}
+
+	static function _callNamedUntyped(e:Dynamic, args:Dynamic):Dynamic { return null; }
+
+	public static function opPow(a:Int, b:Int):Int { return 0; }
+}

+ 16 - 0
std/python/VarArgs.hx

@@ -0,0 +1,16 @@
+
+package python;
+
+abstract VarArgs (Array<Dynamic>)
+{
+	inline function new (d:Array<Dynamic>) this = d;
+
+	@:to inline function toArray ():Array<Dynamic>
+	{
+		return this;
+	}
+	@:from static inline function fromArray (d:Array<Dynamic>):VarArgs
+	{
+		return new VarArgs(d);
+	}
+}

+ 141 - 0
std/python/_std/Array.hx

@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+#if !macro
+import python.internal.ArrayImpl;
+import python.NativeIterator;
+#end
+
+@:native("list")
+@:coreApi
+extern class Array<T> implements ArrayAccess<T> extends ArrayImpl {
+
+	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);
+	}
+
+	public inline function copy() : Array<T> {
+		return ArrayImpl.copy(this);
+	}
+
+	@:runtime public inline function iterator() : Iterator<T> {
+		return ArrayImpl.iterator(this);
+	}
+
+	public inline function insert( pos : Int, x : T ) : Void {
+		return ArrayImpl.insert(this, pos, x);
+	}
+
+
+	@:runtime public inline function join( sep : String ) : String {
+		return ArrayImpl.join(this, sep);
+	}
+
+	public inline function toString() : String {
+		return ArrayImpl.toString(this);
+	}
+
+	@:runtime public inline function pop() : Null<T> {
+		return ArrayImpl.pop(this);
+	}
+
+	@:runtime public inline function push(x:T) : Int {
+		return ArrayImpl.push(this,x);
+	}
+
+	public inline function unshift(x : T) : Void {
+		return ArrayImpl.unshift(this,x);
+	}
+
+	public inline function indexOf(x : T, ?fromIndex:Int) : Int {
+		return ArrayImpl.indexOf(this,x, fromIndex);
+	}
+
+	public inline function lastIndexOf(x : T, ?fromIndex:Int) : Int {
+		return ArrayImpl.lastIndexOf(this,x, fromIndex);
+	}
+
+	public inline function remove(x : T) : Bool {
+		return ArrayImpl.remove(this,x);
+
+	}
+
+	public inline function reverse() : Void {
+		return ArrayImpl.reverse(this);
+	}
+
+	@:runtime public inline function shift() : Null<T> {
+		return ArrayImpl.shift(this);
+	}
+
+	public inline function slice( pos : Int, ?end : Int ) : Array<T> {
+		return ArrayImpl.slice(this, pos, end);
+	}
+
+	public inline function sort(f:T->T->Int) : Void {
+		return ArrayImpl.sort(this, f);
+	}
+
+	public inline function splice( pos : Int, len : Int ) : Array<T> {
+		return ArrayImpl.splice(this, pos, len);
+	}
+
+	public inline function map<S>( f : T -> S ) : Array<S> {
+		return ArrayImpl.map(this, f);
+	}
+
+	public inline function filter( f : T -> Bool ) : Array<T> {
+		return ArrayImpl.filter(this,f);
+	}
+
+
+
+	@:keep private inline function __get(idx:Int):T
+	{
+		return ArrayImpl.__get(this, idx);
+	}
+
+	@:keep private inline function __set(idx:Int, val:T):T
+	{
+		return ArrayImpl.__set(this, idx,val);
+	}
+
+	@:keep private inline function __unsafe_get(idx:Int):T
+	{
+		return ArrayImpl.__unsafe_get(this, idx);
+	}
+
+	@:keep private inline function __unsafe_set(idx:Int, val:T):T
+	{
+		return ArrayImpl.__unsafe_set(this, idx,val);
+	}
+
+	@:noCompletion private function __iter__ ():NativeIterator<T>;
+}

+ 148 - 0
std/python/_std/Date.hx

@@ -0,0 +1,148 @@
+
+
+
+/*
+ * 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;
+
+import python.lib.datetime.DateTime;
+import python.lib.datetime.TimeDelta;
+import python.Syntax;
+
+@:coreApi class Date
+{
+	// since January 1, 1970, 00:00:00 GMT
+	//static var BASE = new DateTime(1970, 1, 1);
+
+	private var date:DateTime;
+
+	public function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void
+	{
+		if (year < DateTime.min.year) year = DateTime.min.year;
+		if (day == 0) day = 1;
+		date = new DateTime(year, month+1, day, hour, min, sec, 0, python.lib.datetime.Timezone.utc);
+	}
+
+	public inline function getTime() : Float
+	{
+		return datetimeTimestamp(date);
+	}
+
+	public inline function getHours() : Int
+	{
+		return date.hour;
+	}
+
+	public inline function getMinutes() : Int
+	{
+		return date.minute;
+	}
+
+	public inline function getSeconds() : Int
+	{
+		return date.second;
+	}
+
+	public inline function getFullYear() : Int
+	{
+		return date.year;
+	}
+
+	public inline function getMonth() : Int
+	{
+		return date.month-1;
+	}
+
+	public inline function getDate() : Int
+	{
+		return date.day;
+	}
+
+	public inline function getDay() : Int
+	{
+		return date.isoweekday();
+	}
+
+	public function toString():String
+	{
+		inline function st (x) return Std.string(x);
+
+		var m = getMonth()+1;
+		var d = getDate();
+		var h = getHours();
+		var mi = getMinutes();
+		var s = getSeconds();
+		return st(getFullYear())
+			+"-"+(if( m < 10 ) "0"+st(m) else ""+st(m))
+			+"-"+(if( d < 10 ) "0"+st(d) else ""+st(d))
+			+" "+(if( h < 10 ) "0"+st(h) else ""+st(h))
+			+":"+(if( mi < 10 ) "0"+st(mi) else ""+st(mi))
+			+":"+(if( s < 10 ) "0"+st(s) else ""+st(s));
+	}
+
+	static public function now() : Date
+	{
+		var d = new Date(1970, 0, 1, 0, 0, 0);
+		d.date = DateTime.now();
+		return d;
+	}
+
+	static public function fromTime( t : Float ) : Date
+	{
+		var d = new Date(1970, 0, 1, 0, 0, 0);
+		d.date = DateTime.fromtimestamp(t/1000.0, python.lib.datetime.Timezone.utc);
+		return d;
+	}
+
+	static function UTC( year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Float
+	{
+		var dt = new DateTime(year, month+1, day, hour, min, sec, 0, python.lib.datetime.Timezone.utc);
+		return datetimeTimestamp(dt);
+	}
+
+	static function datetimeTimestamp(dt:DateTime):Float {
+		var dt2 = new DateTime(1970, 1, 1, 0, 0, 0, 0, python.lib.datetime.Timezone.utc);
+		var timedelta = new TimeDelta(0, 1);
+		return Syntax.binop(Syntax.binop(dt, "-", dt2) * 1000, "/", timedelta);
+	}
+
+	static public function fromString( s : String ) : Date
+	{
+		switch( s.length )
+		{
+			case 8: // hh:mm:ss
+				var k = s.split(":");
+				var d : Date = new Date(0, 0, 0, Std.parseInt(k[0]), Std.parseInt(k[1]), Std.parseInt(k[2]));
+				return d;
+			case 10: // YYYY-MM-DD
+				var k = s.split("-");
+				return new Date(Std.parseInt(k[0]),Std.parseInt(k[1]) - 1,Std.parseInt(k[2]),0,0,0);
+			case 19: // YYYY-MM-DD hh:mm:ss
+				var k = s.split(" ");
+				var y = k[0].split("-");
+				var t = k[1].split(":");
+				return new Date(Std.parseInt(y[0]),Std.parseInt(y[1]) - 1,Std.parseInt(y[2]),Std.parseInt(t[0]),Std.parseInt(t[1]),Std.parseInt(t[2]));
+			default:
+				throw "Invalid date format : " + s;
+		}
+	}
+}

+ 257 - 0
std/python/_std/EReg.hx

@@ -0,0 +1,257 @@
+import python.lib.Builtin;
+import python.lib.Re;
+import python.lib.Re.MatchObject;
+import python.lib.Re.Pattern;
+
+@:coreApi
+class EReg {
+
+	/**
+		Creates a new regular expression with pattern `r` and modifiers `opt`.
+
+		This is equivalent to the shorthand syntax `~/r/opt`
+
+		If `r` or `opt` are null, the result is unspecified.
+	**/
+
+	var pattern:Regex;
+	var matchObj:MatchObject;
+	var global:Bool;
+
+	public function new( r : String, opt : String ) {
+		global = false;
+		var options = 0;
+		for (i in 0...opt.length) {
+			var c = StringTools.fastCodeAt(opt, i);
+			if (c == "m".code) options |= Re.M;
+			if (c == "i".code) options |= Re.I;
+			if (c == "s".code) options |= Re.S;
+			if (c == "u".code) options |= Re.U;
+			if (c == "g".code) global = true;
+		}
+		pattern = Re.compile(r, options);
+	}
+
+	/**
+		Tells if `this` regular expression matches String `s`.
+
+		This method modifies the internal state.
+
+		If `s` is `null`, the result is unspecified.
+	**/
+	public inline function match( s : String ) : Bool {
+		matchObj = Re.search(pattern, s);
+		return matchObj != null;
+	}
+
+	/**
+		Returns the matched sub-group `n` of `this` EReg.
+
+		This method should only be called after `this.match` or
+		`this.matchSub`, and then operates on the String of that operation.
+
+		The index `n` corresponds to the n-th set of parentheses in the pattern
+		of `this` EReg. If no such sub-group exists, an exception is thrown.
+
+		If `n` equals 0, the whole matched substring is returned.
+	**/
+	public inline function matched( n : Int ) : String {
+		return matchObj.group(n);
+	}
+
+	/**
+		Returns the part to the left of the last matched substring.
+
+		If the most recent call to `this.match` or `this.matchSub` did not
+		match anything, the result is unspecified.
+
+		If the global g modifier was in place for the matching, only the
+		substring to the left of the leftmost match is returned.
+
+		The result does not include the matched part.
+	**/
+	public inline function matchedLeft() : String {
+		return matchObj.string.substr(0, matchObj.start());
+	}
+
+	/**
+		Returns the part to the right of the last matched substring.
+
+		If the most recent call to `this.match` or `this.matchSub` did not
+		match anything, the result is unspecified.
+
+		If the global g modifier was in place for the matching, only the
+		substring to the right of the leftmost match is returned.
+
+		The result does not include the matched part.
+	**/
+	public inline function matchedRight() : String {
+		return matchObj.string.substr(matchObj.end());
+	}
+
+	/**
+		Returns the position and length of the last matched substring, within
+		the String which was last used as argument to `this.match` or
+		`this.matchSub`.
+
+		If the most recent call to `this.match` or `this.matchSub` did not
+		match anything, the result is unspecified.
+
+		If the global g modifier was in place for the matching, the position and
+		length of the leftmost substring is returned.
+	**/
+	public inline function matchedPos() : { pos : Int, len : Int } {
+		return { pos : matchObj.start(), len : matchObj.end() - matchObj.start() };
+	}
+
+	/**
+		Tells if `this` regular expression matches a substring of String `s`.
+
+		This function expects `pos` and `len` to describe a valid substring of
+		`s`, or else the result is unspecified. To get more robust behavior,
+		`this.matchSub(s.substr(pos,len))` can be used instead.
+
+		This method modifies the internal state.
+
+		If `s` is null, the result is unspecified.
+	**/
+	public function matchSub( s : String, pos : Int, ?len : Int):Bool {
+		if (len != null) {
+			matchObj = pattern.search(s, pos, pos+len);
+		} else {
+			matchObj = pattern.search(s, pos);
+		}
+
+		return this.matchObj != null;
+
+	}
+
+	/**
+		Splits String `s` at all substrings `this` EReg matches.
+
+		If a match is found at the start of `s`, the result contains a leading
+		empty String "" entry.
+
+		If a match is found at the end of `s`, the result contains a trailing
+		empty String "" entry.
+
+		If two matching substrings appear next to each other, the result
+		contains the empty String "" between them.
+
+		By default, this method splits `s` into two parts at the first matched
+		substring. If the global g modifier is in place, `s` is split at each
+		matched substring.
+
+		If `s` is null, the result is unspecified.
+	**/
+	public function split( s : String ) : Array<String> {
+		return if (global) {
+			var ret = [];
+			var lastEnd = 0;
+
+			for (x in Re.finditer(pattern, s)) {
+
+				ret.push(s.substring(lastEnd, x.start() ));
+				lastEnd = x.end();
+			}
+			ret.push(s.substr(lastEnd));
+			return ret;
+		} else {
+			this.match(s);
+			if (matchObj == null) {
+
+				return [s];
+			} else {
+				return [ s.substring(0, matchObj.start()), s.substr(matchObj.end()) ];
+			}
+
+		}
+	}
+
+	/**
+		Replaces the first substring of `s` which `this` EReg matches with `by`.
+
+		If `this` EReg does not match any substring, the result is `s`.
+
+		By default, this method replaces only the first matched substring. If
+		the global g modifier is in place, all matched substrings are replaced.
+
+		If `by` contains `$1` to `$9`, the digit corresponds to number of a
+		matched sub-group and its value is used instead. If no such sub-group
+		exists, the replacement is unspecified. The string `$$` becomes `$`.
+
+		If `s` or `by` are null, the result is unspecified.
+	**/
+	public function replace( s : String, by : String ) : String
+	{
+		var by = by.split("$$").join("_hx_#repl#__");
+		function replace (x:MatchObject) {
+			var res = by;
+			var g = x.groups();
+			for (i in 0...g.length) {
+
+				res = res.split("$"+Builtin.str(i+1)).join(g[i]);
+			}
+			res = res.split("_hx_#repl#__").join("$");
+			return res;
+		}
+		return Re.sub(pattern, replace, s, global ? 0 : 1 );
+	}
+
+	/**
+		For each occurence of the pattern in the string `s`, the function `f` is called and
+		can return the string that needs to be replaced. All occurences are matched anyway,
+		and setting the `g` flag might cause some incorrect behavior on some platforms.
+	**/
+	public function map( s : String, f : EReg -> String ) : String {
+
+		var buf = new StringBuf();
+		var pos = 0;
+		var right = s;
+
+		var cur = this;
+		while( pos < s.length ) {
+
+			if (matchObj == null) {
+				matchObj = Re.search(pattern, s);
+			} else {
+				matchObj = matchObj.re.search(s, pos);
+			}
+
+			if( matchObj == null )
+				break;
+
+
+
+			var pos1 = matchObj.end();
+
+			var curPos = cur.matchedPos();
+
+
+			buf.add(cur.matchedLeft().substr(pos));
+			buf.add(f(cur));
+
+			right = cur.matchedRight();
+
+
+
+			if (!global) {
+				buf.add(right);
+				return buf.toString();
+			}
+
+			if (curPos.len == 0) {
+				buf.add(s.charAt(pos1));
+				right = right.substr(1);
+				pos = pos1+1;
+			} else {
+				pos = pos1;
+			}
+
+
+		}
+		buf.add(right);
+		return buf.toString();
+
+	}
+}

+ 320 - 0
std/python/_std/Math.hx

@@ -0,0 +1,320 @@
+
+package;
+
+import python.lib.Builtin;
+
+/*
+ * 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.
+ */
+/**
+	This class defines mathematical functions and constants.
+**/
+@:native("_hx_math")
+@:coreApi
+extern class Math
+{
+	static var PI(default,null) : Float;
+
+	/**
+		A special Float constant which denotes negative infinity.
+
+		For example, this is the result of -1.0 / 0.0.
+
+		Operations with NEGATIVE_INFINITY as an operand may result in
+		Operations with NEGATIVE_INFINITY as an operand may result in
+		NEGATIVE_INFINITY, POSITIVE_INFINITY or NaN. For detailed information,
+		see ...
+
+		If this constant is converted to an Int, e.g. through Std.int(), the
+		result is unspecified.
+	**/
+	static var NEGATIVE_INFINITY(default, null) : Float;
+
+	/**
+		A special Float constant which denotes negative infinity.
+
+		For example, this is the result of 1.0 / 0.0.
+
+		Operations with POSITIVE_INFINITY as an operand may result in
+		NEGATIVE_INFINITY, POSITIVE_INFINITY or NaN. For detailed information,
+		see ...
+
+		If this constant is converted to an Int, e.g. through Std.int(), the
+		result is unspecified.
+	**/
+	static var POSITIVE_INFINITY(default,null) : Float;
+
+	/**
+		A special Float constant which denotes an invalid number.
+
+		NaN stands for "Not a Number". It occurs when a mathematically incorrect
+		operation is executed, such as taking the square root of a negative
+		number: Math.sqrt(-1).
+
+		All further operations with NaN as an operand will result in NaN.
+
+		If this constant is converted to an Int, e.g. through Std.int(), the
+		result is unspecified.
+
+		In order to test if a value is NaN, you should use Math.isNaN() function.
+
+		(Php) In PHP versions prior to 5.3.1 VC 9 there may be unexpected
+		results when performing arithmetic operations with NaN on Windows, see:
+			https://bugs.php.net/bug.php?id=42143
+	**/
+	static var NaN(default, null) : Float;
+
+	/**
+		Returns the absolute value of `v`.
+
+		If `v` is positive or 0, the result is unchanged. Otherwise the result
+		is -`v`.
+
+		If `v` is NEGATIVE_INFINITY or POSITIVE_INFINITY, the result is
+		POSITIVE_INFINITY.
+
+		If `v` is NaN, the result is NaN.
+	**/
+	public static inline function abs(v:Float):Float
+	{
+		return (Math:Dynamic).fabs(v);
+	}
+
+	/**
+		Returns the smaller of values `a` and `b`.
+
+		If `a` or `b` are NaN, the result is NaN.
+
+		If `a` or `b` are NEGATIVE_INFINITY, the result is NEGATIVE_INFINITY.
+
+		If `a` and `b` are POSITIVE_INFINITY, the result is POSITIVE_INFINITY.
+	**/
+
+	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);
+	}
+
+	/**
+		Returns the greater of values `a` and `b`.
+
+		If `a` or `b` are NaN, the result is NaN.
+
+		If `a` or `b` are POSITIVE_INFINITY, the result is POSITIVE_INFINITY.
+
+		If `a` and `b` are NEGATIVE_INFINITY, the result is NEGATIVE_INFINITY.
+	**/
+	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);
+	}
+
+	/**
+		Returns the trigonometric sine of `v`.
+
+		The unit of `v` is radians.
+
+		If `v` is NaN or infinite, the result is NaN.
+	**/
+	public static inline function sin(v:Float):Float {
+		return if (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY) NaN else python.lib.Math.sin(v);
+	}
+
+	/**
+		Returns the trigonometric cosine of `v`.
+
+		The unit of `v` is radians.
+
+		If `v` is NaN or infinite, the result is NaN.
+	**/
+	public static inline function cos(v:Float):Float {
+		return if (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY) NaN else python.lib.Math.cos(v);
+	}
+
+
+	static function tan(v:Float):Float {
+		return if (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY) NaN else python.lib.Math.tan(v);
+	}
+	static function asin(v:Float):Float {
+		return if (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY) NaN else python.lib.Math.asin(v);
+	}
+	static function acos(v:Float):Float {
+		return if (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY) NaN else python.lib.Math.acos(v);
+	}
+	static function atan(v:Float):Float {
+		return if (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY) NaN else python.lib.Math.atan(v);
+	}
+	static function atan2(y:Float, x:Float):Float {
+		return if (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY) NaN else python.lib.Math.atan2(v);
+	}
+
+	/**
+		Returns Euler's number, raised to the power of `v`.
+
+		exp(1.0) is approximately 2.718281828459.
+
+		If `v` is POSITIVE_INFINITY, the result is POSITIVE_INFINITY.
+
+		If `v` is NEGATIVE_INFINITY, the result is 0.0.
+
+		If `v` is NaN, the result is NaN.
+	**/
+	public static inline function exp(v:Float):Float
+	{
+		if (v == NEGATIVE_INFINITY) {
+			return 0.0;
+		} else if (v == POSITIVE_INFINITY) {
+			return POSITIVE_INFINITY;
+		} else {
+			return (Math:Dynamic).exp(v);
+		}
+	}
+
+	/**
+		Returns the natural logarithm of `v`.
+
+		If `v` is negative (including NEGATIVE_INFINITY) or NaN, the result is
+		NaN.
+
+		If `v` is POSITIVE_INFINITY, the result is POSITIVE_INFINITY.
+
+		If `v` is 0.0, the result is NEGATIVE_INFINITY.
+
+		This is the inverse operation of exp, i.e. log(exp(v)) == v always
+		holds.
+	**/
+	public static inline function log(v:Float):Float {
+		return if (v == 0.0) NEGATIVE_INFINITY else if (v < 0.0) NaN else python.lib.Math.log(v);
+	}
+
+	// TODO
+	// http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Math.html#pow(double, double) <-- wtf?
+	static function pow(v:Float, exp:Float):Float;
+
+	/**
+		Returns the square root of `v`.
+
+		If `v` is negative (including NEGATIVE_INFINITY) or NaN, the result is
+		NaN.
+
+		If `v` is POSITIVE_INFINITY, the result is POSITIVE_INFINITY.
+
+		If `v` is 0.0, the result is 0.0.
+	**/
+	public static inline function sqrt(v:Float):Float
+	{
+		return if (v < 0) NaN else python.lib.Math.sqrt(v);
+	}
+
+	/**
+		Rounds `v` to the nearest Int value.
+
+		If v is outside of the signed Int32 range, or is NaN, NEGATIVE_INFINITY or POSITIVE_INFINITY, the result is unspecified.
+
+		TODO: need spec
+	**/
+	public static inline function round(v:Float):Int {
+		return Math.floor(v + 0.5);
+	}
+
+	/**
+		Returns the largest Int value that is not greater than `v`.
+
+		If v is outside of the signed Int32 range, or is NaN, NEGATIVE_INFINITY or POSITIVE_INFINITY, the result is unspecified.
+
+		TODO: need spec
+	**/
+	static function floor(v:Float):Int;
+
+	/**
+		Returns the smallest Int value that is not less than `v`.
+
+		If v is outside of the signed Int32 range, or is NaN, NEGATIVE_INFINITY or POSITIVE_INFINITY, the result is unspecified.
+
+		TODO: need spec
+	**/
+	static function ceil(v:Float):Int;
+
+	/**
+		Returns a pseudo-random number which is greater than or equal to 0.0,
+		and less than 1.0.
+	**/
+	inline static function random() : Float {
+		return python.lib.Random.random();
+	}
+
+
+
+	static inline function ffloor( v : Float ) : Float
+	{
+		if (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY) return v;
+		if (isNaN(v)) return NaN;
+		return floor(v);
+	}
+
+	static inline function fceil( v : Float ) : Float
+	{
+		if (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY) return v;
+		if (isNaN(v)) return NaN;
+		return ceil(v);
+	}
+
+	static inline function fround( v : Float ) : Float
+	{
+		if (v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY) return v;
+		if (isNaN(v)) return NaN;
+		return round(v);
+	}
+
+
+
+
+	/**
+		Tells if `f` is a finite number.
+
+		If `f` is POSITIVE_INFINITY, NEGATIVE_INFINITY or NaN, the result is
+		false.
+
+		Otherwise the result is true.
+	**/
+	static inline function isFinite( f : Float ) : Bool return f != POSITIVE_INFINITY && f != NEGATIVE_INFINITY && !isNaN(f);
+
+	/**
+		Tells if `f` is not a valid number.
+
+		If `f` is NaN, the result is true.
+
+		Otherwise the result is false. In particular, both POSITIVE_INFINITY and
+		NEGATIVE_INFINITY are not considered NaN.
+	**/
+	static inline function isNaN( f : Float ) : Bool {
+
+		return python.lib.Math.isnan(f);
+	}
+
+	static function __init__():Void {
+		python.Syntax.importAs("math", "_hx_math");
+		NEGATIVE_INFINITY = Builtin.float('-inf');
+		POSITIVE_INFINITY = Builtin.float('inf');
+		NaN = Builtin.float("nan");
+		PI = python.lib.Math.pi;
+	}
+
+}

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

@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+import python.internal.AnonObject;
+import python.internal.StringImpl;
+import python.internal.ArrayImpl;
+
+import python.lib.Builtin;
+import python.lib.Inspect;
+import python.Syntax;
+import python.VarArgs;
+
+@:access(python.Boot)
+@:coreApi
+class Reflect {
+
+
+	static inline function handleKeywords(name:String):String {
+		return python.Boot.handleKeywords(name);
+	}
+
+	static function unhandleKeywords(name:String):String {
+		return python.Boot.unhandleKeywords(name);
+	}
+
+	public static function hasField( o : Dynamic, field : String ) : Bool
+	{
+		var field = handleKeywords(field);
+		return Builtin.hasattr(o, field);
+	}
+
+	static inline function isString (o:Dynamic):Bool {
+		return Builtin.isinstance(o, String);
+	}
+	static inline function isArray (o:Dynamic):Bool {
+		return Builtin.isinstance(o, Array);
+	}
+	@:access(python.Boot)
+	@:keep public static function field( o : Dynamic, field : String ) : Dynamic
+	{
+		return python.Boot.field(o, field);
+	}
+
+	@:keep public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void
+	{
+		var field = handleKeywords(field);
+		return Builtin.setattr(o,field,value);
+	}
+
+	public static function getProperty( o : Dynamic, field : String ) : Dynamic
+	{
+		var field = handleKeywords(field);
+		var tmp = null;
+		if (o == null) {
+			return null;
+		} else {
+			tmp = Reflect.field(o, "get_" + field);
+			if (tmp != null && Builtin.callable(tmp)) {
+				return tmp();
+			} else {
+				return Reflect.field(o, field);
+			}
+		}
+	}
+
+	public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void {
+
+		var field = handleKeywords(field);
+
+		return if (Builtin.hasattr(o,"set_"+field)) {
+			var tmp = Builtin.getattr(o,"set_"+field);
+			tmp(value);
+		}
+		else Builtin.setattr(o,field, value);
+	}
+
+	public static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic
+	{
+		var args:VarArgs = args;
+		return if (Builtin.callable(func)) func(python.Syntax.varArgs(args)) else null;
+	}
+
+	public static inline function fields( o : Dynamic ) : Array<String>
+	{
+		return python.Boot.fields(o);
+	}
+
+	public static function isFunction( f : Dynamic ) : Bool
+	{
+		return Inspect.isfunction(f) || Inspect.ismethod(f);
+	}
+
+	public static function compare<T>( a : T, b : T ) : Int {
+		if (a == null && b == null) return 0;
+		return
+			if (a == null) 1 else if (b == null) -1
+			else ( a == b ) ? 0 : (((cast a) > (cast b)) ? 1 : -1);
+	}
+
+	public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool {
+		if( f1 == f2 )
+			return true;
+		if( !isFunction(f1) || !isFunction(f2) )
+			return false;
+
+		return false;
+	}
+
+	public static function isObject( v : Dynamic ) : Bool {
+
+		return switch (Type.typeof(v)) {
+			case TObject, TClass(_): true;
+			case _ : false;
+		}
+	}
+
+	public static function isEnumValue( v : Dynamic ) : Bool {
+		return v != Enum && Builtin.isinstance(v, cast Enum);
+	}
+
+	public static function deleteField( o : Dynamic, field : String ) : Bool {
+		if( !hasField(o,field) ) return false;
+		Syntax.callField(o, "__delattr__", field);
+		return true;
+	}
+
+	public static function copy<T>( o : T ) : T {
+		var o2 : Dynamic = {};
+		for( f in Reflect.fields(o) )
+			Reflect.setField(o2,f,Reflect.field(o,f));
+		return o2;
+	}
+
+	@:overload(function( f : Array<Dynamic> -> Void ) : Dynamic {})
+	public static function makeVarArgs( f : Array<Dynamic> -> Dynamic ) : Dynamic {
+		return function (v:VarArgs) {
+			return f(v);
+		}
+	}
+
+}

+ 215 - 0
std/python/_std/Std.hx

@@ -0,0 +1,215 @@
+/*
+ * 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;
+
+import python.internal.Internal;
+import python.lib.Builtin;
+import python.lib.Inspect;
+import python.Boot;
+import python.Syntax;
+
+@:keepInit
+@:coreApi class Std {
+
+	public static inline function instance<T:{}, S:T>( value : T, c : Class<S> ) : S {
+		try {
+			return Builtin.isinstance(value,c) ? cast value : null;
+		} catch (e:Dynamic) {
+			return null;
+		}
+	}
+
+	@:access(python.Boot.getSuperClass)
+	public static function is( v : Dynamic, t : Dynamic ) : Bool {
+
+		if (v == null && t == null) {
+			return false;
+		}
+		if (t == null) {
+
+			return false;
+		}
+		if (t == Dynamic) {
+			return true;
+		}
+		var isBool = Builtin.isinstance(v, Builtin.bool);
+
+		if (t == Bool && isBool) {
+			return true;
+		}
+		if (!isBool && t != Bool && t == Int && Builtin.isinstance(v, Builtin.int )) {
+			return true;
+		}
+		var vIsFloat = Builtin.isinstance(v, Builtin.float);
+
+		if (!isBool && vIsFloat && t == Int && Math.isFinite(v) && v == Std.int(v) && v <= 2147483647 && v >= -2147483648) {
+			return true;
+		}
+
+
+		if (!isBool &&  t == Float && ( Builtin.isinstance(v, python.Syntax.pythonCode("(float,int)")))) {
+			return true;
+		}
+
+		if ( t == Builtin.str) {
+			return Builtin.isinstance(v, String);
+		}
+		if (t == Enum && Inspect.isclass(v) && Internal.hasConstructs(v)) return true;
+
+		if (t == Enum) return false;
+
+
+		if (t == Class && !Builtin.isinstance(v, Enum) && Inspect.isclass(v) && Internal.hasClassName(v) && !Internal.hasConstructs(v)) return true;
+
+		if (t == Class) return false;
+
+		if (try Builtin.isinstance(v, t) catch (e:Dynamic) false) {
+			return true;
+		}
+
+		if (Inspect.isclass(t)) {
+
+			function loop (intf)
+			{
+				var f:Array<Dynamic> = if (Internal.hasInterfaces(intf)) Internal.fieldInterfaces(intf) else [];
+				if (f != null) {
+					for (i in f) {
+						if ( i == t) {
+							return true;
+						} else {
+							var l = loop(i);
+							if (l) {
+								return true;
+							}
+						}
+					}
+					return false;
+				} else {
+					return false;
+				}
+			}
+			var currentClass = Syntax.field(v, "__class__");
+			while(currentClass != null) {
+				if (loop(currentClass)) {
+					return true;
+				}
+				currentClass = python.Boot.getSuperClass(currentClass);
+			}
+			return false;
+		} else {
+			return false;
+		}
+	}
+
+	@:access(python.Boot)
+	@:keep
+	public static function string( s : Dynamic ) : String
+	{
+		return python.Boot.toString(s);
+	}
+
+	public static inline function int( x : Float ) : Int
+	{
+		try {
+			return Builtin.int(x);
+		} catch (e:Dynamic) {
+			return null;
+		}
+	}
+
+	public static function parseInt( x : String ) : Null<Int> {
+		if (x == null) return null;
+		try {
+			return Builtin.int(x);
+		} catch (e:Dynamic) {
+			try {
+				var prefix = x.substr(0,2).toLowerCase();
+
+				if (prefix == "0x") {
+					return Builtin.int(x,16);
+				}
+				throw "fail";
+			} catch (e:Dynamic) {
+
+				var r = int(parseFloat(x));
+
+				if (r == null) {
+					var r1 = shortenPossibleNumber(x);
+					if (r1 != x) {
+						return parseInt(r1);
+					} else {
+						return null;
+					}
+				}
+				return r;
+			}
+		}
+	}
+
+	static function shortenPossibleNumber (x:String):String
+	{
+		var r = "";
+		for (i in 0...x.length) {
+			var c = x.charAt(i);
+			switch (c.charCodeAt(0)) {
+				case "0".code
+				| "1".code
+				| "2".code
+				| "3".code
+				| "4".code
+				| "5".code
+				| "6".code
+				| "7".code
+				| "8".code
+				| "9".code
+				| ".".code : r += c;
+				case _ : break;
+			}
+		}
+		return r;
+	}
+
+	public static function parseFloat( x : String ) : Float
+	{
+		try {
+			return Builtin.float(x);
+		} catch (e:Dynamic) {
+
+			if (x != null) {
+				var r1 = shortenPossibleNumber(x);
+				if (r1 != x) {
+					return parseFloat(r1);
+				}
+			}
+			return Math.NaN;
+		}
+	}
+
+	public static inline function random( x : Int ) : Int {
+		if (x <= 0) {
+			return 0;
+		} else {
+			return int(Math.random()*x);
+		}
+	}
+}

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

@@ -0,0 +1,206 @@
+package;
+/*
+ * 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.
+ */
+/**
+	The basic String class.
+
+	A haxe String is immutable, it is not possible to modify individual
+	characters. No method of this class changes the state of [this] String.
+
+	Strings can be constructed using the string literal syntax "string value".
+
+	String can be concatenated by using the + operator. If an operand is not a
+	String, it is passed through Std.string() first.
+**/
+#if !macro
+import python.internal.StringImpl;
+#end
+@: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.
+	**/
+	function new(string:String) : Void;
+
+	/**
+		Returns a String where all characters of [this] String are upper case.
+
+		Affects the characters [a-z]. Other characters remain unchanged.
+	**/
+	@:runtime public inline function toUpperCase() : String {
+		return StringImpl.toUpperCase(this);
+	}
+
+	/**
+		Returns a String where all characters of [this] String are lower case.
+
+		Affects the characters [A-Z]. Other characters remain unchanged.
+	**/
+	@:runtime public inline function toLowerCase() : String {
+		return StringImpl.toLowerCase(this);
+	}
+
+	/**
+		Returns the character at position [index] of [this] String.
+
+		If [index] is negative or exceeds [this].length, the empty String ""
+		is returned.
+	**/
+	inline public function charAt(index : Int) : String
+	{
+		return StringImpl.charAt(this, index);
+	}
+
+	/**
+		Returns the character code at position [index] of [this] String.
+
+		If [index] is negative or exceeds [this].length, null is returned.
+
+		To obtain the character code of a single character, "x".code can be used
+		instead to inline the character code at compile time. Note that this
+		only works on String literals of length 1.
+	**/
+	inline public function charCodeAt( index : Int) : Null<Int>
+	{
+		return StringImpl.charCodeAt(this, index);
+	}
+
+	/**
+		Returns the position of the leftmost occurence of [str] within [this]
+		String.
+
+		If [startIndex] is given, the search is performed within the substring
+		of [this] String starting from [startIndex]. Otherwise the search is
+		performed within [this] String. In either case, the returned position
+		is relative to the beginning of [this] String.
+
+		If [str] cannot be found, -1 is returned.
+	**/
+	inline function indexOf( str : String, ?startIndex : Int ) : Int {
+		return StringImpl.indexOf(this, str, startIndex);
+	}
+
+	/**
+		Returns the position of the rightmost occurence of [str] within [this]
+		String.
+
+		If [startIndex] is given, the search is performed within the substring
+		of [this] String from 0 to [startIndex]. Otherwise the search is
+		performed within [this] String. In either case, the returned position
+		is relative to the beginning of [this] String.
+
+		If [str] cannot be found, -1 is returned.
+	**/
+	inline function lastIndexOf( str : String, ?startIndex : Int ) : Int {
+		return StringImpl.lastIndexOf(this, str, startIndex);
+	}
+
+	/**
+		Splits [this] String at each occurence of [delimiter].
+
+		If [delimiter] is the empty String "", [this] String is split into an
+		Array of [this].length elements, where the elements correspond to the
+		characters of [this] String.
+
+		If [delimiter] is not found within [this] String, the result is an Array
+		with one element, which equals [this] String.
+
+		If [delimiter] is null, the result is unspecified.
+
+		Otherwise, [this] String is split into parts at each occurence of
+		[delimiter]. If [this] String starts (or ends) with [delimiter}, the
+		result Array contains a leading (or trailing) empty String "" element.
+		Two subsequent delimiters also result in an empty String "" element.
+	**/
+	inline function split( delimiter : String ) : Array<String> {
+		return StringImpl.split(this, delimiter);
+	}
+
+	/**
+		Returns [len] characters of [this] String, starting at position [pos].
+
+		If [len] is omitted, all characters from position [pos] to the end of
+		[this] String are included.
+
+		If [pos] is negative, its value is calculated from the end of [this]
+		String by [this].length + [pos]. If this yields a negative value, 0 is
+		used instead.
+
+		If the calculated position + [len] exceeds [this].length, the characters
+		from that position to the end of [this] String are returned.
+
+		If [len] is negative, the result is unspecified.
+	**/
+	inline public function substr( pos : Int, ?len : Int ) : String
+	{
+		return StringImpl.substr(this, pos, len);
+	}
+
+	/**
+		Returns the part of [this] String from [startIndex] to [endIndex].
+
+		If [startIndex] or [endIndex] are negative, 0 is used instead.
+
+		If [startIndex] exceeds [endIndex], they are swapped.
+
+		If the (possibly swapped) [endIndex] is omitted or exceeds
+		[this].length, [this].length is used instead.
+
+		If the (possibly swapped) [startIndex] exceeds [this].length, the empty
+		String "" is returned.
+	**/
+	inline function substring( startIndex : Int, ?endIndex : Int ) : String {
+		return StringImpl.substring(this, startIndex, endIndex);
+	}
+
+	/**
+		Returns the String itself.
+	**/
+	inline function toString() : String return StringImpl.toString(this);
+
+	/**
+		Returns the String corresponding to the character code [code].
+
+		If [code] is negative or has another invalid value, the result is
+		unspecified.
+	**/
+	public static function fromCharCode( code : Int ) : String {
+		return StringImpl.fromCharCode(code);
+	}
+
+	@:keep static function __init__ ():Void {
+		python.Syntax.importFromAs("builtins", "str", "String");
+	}
+
+
+}

+ 116 - 0
std/python/_std/StringBuf.hx

@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+import python.lib.Builtin;
+import python.lib.io.IOBase.SeekSet;
+import python.lib.io.StringIO;
+
+
+/**
+	A String buffer is an efficient way to build a big string by appending small
+	elements together.
+
+	Its cross-platform implementation uses String concatenation internally, but
+	StringBuf may be optimized for different targets.
+
+	Unlike String, an instance of StringBuf is not immutable in the sense that
+	it can be passed as argument to functions which modify it by appending more
+	values. However, the internal buffer cannot be modified.
+**/
+
+@:coreApi
+class StringBuf {
+
+	/**
+		Creates a new StringBuf instance.
+
+		This may involve initialization of the internal buffer.
+	**/
+
+	private var b : StringIO;
+
+	public inline function new():Void {
+		this.b = new StringIO();
+	}
+
+	public var length(get, never):Int;
+
+	public function get_length ():Int {
+		var pos = b.tell();
+		b.seek(0, SeekSet.SeekEnd);
+		var len = b.tell();
+		b.seek(pos, SeekSet.SeekSet);
+		return len;
+	}
+
+	/**
+		Appends the representation of [x] to [this] StringBuf.
+
+		The exact representation of [x] may vary per platform. To get more
+		consistent behavior, this function should be called with
+		Std.string(x).
+
+		If [x] is null, the String "null" is appended.
+	**/
+	public inline function add<T>( x : T ) : Void {
+		add1(Std.string(x));
+	}
+
+	inline function add1(s:String):Void {
+		b.write(s);
+	}
+
+	/**
+		Appends the character identified by [c] to [this] StringBuf.
+
+		If [c] is negative or has another invalid value, the result is
+		unspecified.
+	**/
+	public inline function addChar( c : Int ) : Void {
+		add1(String.fromCharCode(c));
+	}
+
+	/**
+		Appends a substring of [s] to [this] StringBuf.
+
+		This function expects [pos] and [len] to describe a valid substring of
+		[s], or else the result is unspecified. To get more robust behavior,
+		[this].add(s.substr(pos,len)) can be used instead.
+
+		If [s] or [pos] are null, the result is unspecified.
+
+		If [len] is omitted or null, the substring ranges from [pos] to the end
+		of [s].
+	**/
+	public inline function addSub( s : String, pos : Int, ?len : Int) : Void {
+		add1((len == null ? s.substr(pos) : s.substr(pos, len)));
+	}
+
+	/**
+		Returns the content of [this] StringBuf as String.
+
+		The buffer is not emptied by this operation.
+	**/
+	public inline function toString() : String {
+		return b.getvalue();
+	}
+}

+ 137 - 0
std/python/_std/Sys.hx

@@ -0,0 +1,137 @@
+import python.lib.Time;
+import python.lib.Os;
+import sys.io.FileInput;
+import sys.io.FileOutput;
+
+@:coreApi
+class Sys {
+
+	static var environ:haxe.ds.StringMap<String> = {
+		environ = new haxe.ds.StringMap();
+
+		var env = Os.environ;
+
+		for (key in env.keys()) {
+			environ.set(key, env.get(key, null));
+		}
+		environ;
+	}
+
+	public static function time():Float {
+		return Time.time();
+	}
+
+	public static function exit(code:Int):Void {
+		python.lib.Sys.exit(code);
+	}
+
+	public static function print(v:Dynamic):Void {
+		python.Lib.print(v);
+	}
+
+	public static function println(v:Dynamic):Void {
+		python.Lib.println(v);
+	}
+
+	public static function args() : Array<String> {
+		var argv = python.lib.Sys.argv;
+		return argv.slice(1);
+	}
+
+	public static function getEnv( s : String ) : String {
+		return environ.get(s);
+	}
+
+	public static function putEnv( s : String, v : String ) : Void {
+		python.lib.Os.putenv(s, v);
+		environ.set(s, v);
+	}
+
+	public static function environment() : haxe.ds.StringMap<String> {
+		return environ;
+	}
+
+	public static function sleep( seconds : Float ) : Void {
+		python.lib.Time.sleep(seconds);
+	}
+
+	public static function setTimeLocale( loc : String ) : Bool {
+		return false;
+	}
+
+	public static function getCwd() : String {
+		return python.lib.Os.getcwd();
+	}
+
+	public static function setCwd( s : String ) : Void {
+		python.lib.Os.chdir(s);
+	}
+
+	public static function systemName() : String {
+		return switch (python.lib.Sys.platform) {
+			case x if (StringTools.startsWith(x, "linux")):
+				"Linux";
+			case "darwin": "Mac";
+			case "win32" | "cygwin" : "Windows";
+			case _ :
+				throw "not supported platform";
+		}
+	}
+
+	public static function command( cmd : String, ?args : Array<String> ) : Int {
+		var args = args == null ? [cmd] : [cmd].concat(args);
+		return python.lib.Subprocess.call(args);
+	}
+
+	public static function cpuTime() : Float {
+		return python.lib.Time.clock();
+	}
+
+	public static function executablePath() : String {
+		return python.lib.Sys.argv[0];
+	}
+
+	public static function getChar( echo : Bool ) : Int {
+
+		var ch = switch (systemName()) {
+			case "Linux" | "Mac":
+				var fd = python.lib.Sys.stdin.fileno();
+				var old = python.lib.Termios.tcgetattr(fd);
+
+				var restore = python.lib.Termios.tcsetattr.bind(fd, python.lib.Termios.TCSADRAIN, old);
+
+				try {
+					python.lib.Tty.setraw(fd);
+					var x = python.lib.Sys.stdin.read(1);
+					restore();
+					x.charCodeAt(0);
+				} catch (e:Dynamic) {
+					restore();
+					throw e;
+				}
+
+			case "Windows":
+				python.lib.Msvcrt.getch().decode("utf-8").charCodeAt(0);
+			case x :
+				throw "platform " + x + " not supported";
+		}
+		if (echo) {
+			python.Lib.print(String.fromCharCode(ch));
+		}
+		return ch;
+	}
+
+	public static function stdin() : haxe.io.Input {
+		return python.io.IoTools.createFileInputFromText(python.lib.Sys.stdin);
+	}
+
+	public static function stdout() : haxe.io.Output {
+		return python.io.IoTools.createFileOutputFromText(python.lib.Sys.stdout);
+	}
+
+	public static function stderr() : haxe.io.Output {
+		return python.io.IoTools.createFileOutputFromText(python.lib.Sys.stderr);
+	}
+
+
+}

+ 282 - 0
std/python/_std/Type.hx

@@ -0,0 +1,282 @@
+import python.internal.AnonObject;
+import python.internal.EnumImpl;
+import python.internal.Internal;
+import python.lib.Builtin;
+import python.Syntax;
+
+/*
+ * 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.
+ */
+enum ValueType {
+	TNull;
+	TInt;
+	TFloat;
+	TBool;
+	TObject;
+	TFunction;
+	TClass( c : Class<Dynamic> );
+	TEnum( e : Enum<Dynamic> );
+	TUnknown;
+}
+
+@:access(python.Boot)
+@:coreApi class Type {
+
+	public static function getClass<T>( o : T ) : Class<T> {
+
+		if( o == null )
+			return null;
+
+		if (python.Boot.isClass(o)) return null;
+
+		if (python.Boot.isAnonObject(o)) return null;
+
+		if (Internal.hasClass(o)) {
+			return Internal.fieldClass(o);
+		}
+		if (Builtin.hasattr(o, "__class__")) {
+			return Syntax.field(o, "__class__");
+		} else {
+			return null;
+		}
+	}
+
+	public static function getEnum( o : EnumValue ) : Enum<Dynamic> {
+		if( o == null )
+			return null;
+		return Syntax.field(o, "__class__");
+	}
+
+	public static function getSuperClass( c : Class<Dynamic> ) : Class<Dynamic> {
+		return python.Boot.getSuperClass(c);
+
+	}
+
+	public static function getClassName( c : Class<Dynamic> ) : String {
+		if (Internal.hasClassName(c)) {
+			return Internal.fieldClassName(c);
+		} else {
+			// it's not a haxe class
+			if (c == Array) return "Array";
+			if (c == Math) return "Math";
+			if (c == String) return "String";
+
+			try {
+				var s :String = Syntax.field(c, "__name__");
+			} catch (e:Dynamic) {}
+		}
+		var res = null;
+
+		return res;
+	}
+
+	public static function getEnumName( e : Enum<Dynamic> ) : String {
+		return Internal.fieldClassName(e);
+	}
+
+	public static function resolveClass( name : String ) : Class<Dynamic>
+	{
+		if (name == "Array") return Array;
+		if (name == "Math") return Math;
+		if (name == "String") return String;
+
+		var cl : Class<Dynamic> = Internal.classRegistry().get(name, null);
+		// ensure that this is a class
+		if( cl == null || !python.Boot.isClass(cl) )
+			return null;
+		return cl;
+	}
+
+	public static function resolveEnum( name : String ) : Enum<Dynamic> {
+		if (name == "Bool") return cast Bool;
+		var o = resolveClass(name);
+		return if (Internal.hasConstructs(o)) cast o else null;
+	}
+
+	public static function createInstance<T>( cl : Class<T>, args : Array<Dynamic> ) : T
+	{
+		var l = args.length;
+		switch( l )
+		{
+			case 0:
+				return Syntax.newInstance(cl);
+			case 1:
+				return Syntax.newInstance(cl,args[0]);
+			case 2:
+				return Syntax.newInstance(cl,args[0],args[1]);
+			case 3:
+				return Syntax.newInstance(cl,args[0],args[1],args[2]);
+			case 4:
+				return Syntax.newInstance(cl,args[0],args[1],args[2],args[3]);
+			case 5:
+				return Syntax.newInstance(cl,args[0],args[1],args[2],args[3],args[4]);
+			case 6:
+				return Syntax.newInstance(cl,args[0],args[1],args[2],args[3],args[4],args[5]);
+			case 7:
+				return Syntax.newInstance(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
+			case 8:
+				return Syntax.newInstance(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
+			default:
+				throw "Too many arguments";
+		}
+		return null;
+	}
+
+	public static function createEmptyInstance<T>( cl : Class<T> ) : T
+	{
+		var i = Syntax.callField(cl, "__new__", cl);
+
+		function callInit (cl) {
+			var sc = getSuperClass(cl);
+			if (sc != null) {
+				callInit(sc);
+			}
+			if (Internal.hasEmptyInit(cl)) {
+				Internal.callEmptyInit(cl, i);
+			}
+		}
+		callInit(cl);
+
+		return i;
+	}
+
+	public static function createEnum<T>( e : Enum<T>, constr : String, ?params : Array<Dynamic> ) : T
+	{
+		var f = Reflect.field(e,constr);
+		if( f == null ) throw "No such constructor "+constr;
+		if( Reflect.isFunction(f) ) {
+			if( params == null ) throw "Constructor "+constr+" need parameters";
+
+			return Reflect.callMethod(e,f,params);
+		}
+		if( params != null && params.length != 0 )
+			throw "Constructor "+constr+" does not need parameters";
+		return f;
+	}
+
+	public static function createEnumIndex<T>( e : Enum<T>, index : Int, ?params : Array<Dynamic> ) : T {
+
+		var c : String = Internal.fieldConstructs(e)[index];
+		if( c == null ) throw index+" is not a valid enum constructor index";
+		return createEnum(e,c,params);
+	}
+
+	public static inline function getInstanceFields( c : Class<Dynamic> ) : Array<String> {
+		return python.Boot.getInstanceFields(c);
+	}
+
+	public static inline function getClassFields( c : Class<Dynamic> ) : Array<String> {
+		return python.Boot.getClassFields(c);
+	}
+
+	public static function getEnumConstructs( e : Enum<Dynamic> ) : Array<String> {
+		if (Builtin.hasattr(e, Internal.constructsVal())) {
+			var x:Array<String> = Internal.fieldConstructs(e);
+			return x.copy();
+		} else {
+			return [];
+		}
+	}
+
+
+
+	public static function typeof( v : Dynamic ) : ValueType {
+		if (v == null) {
+			return TNull;
+		} else if (Builtin.isinstance(v, Builtin.bool )) {
+			return TBool;
+		} else if (Builtin.isinstance(v, Builtin.int)) {
+			return TInt;
+		} else if (Builtin.isinstance(v, Builtin.float)) {
+			return TFloat;
+		} else if (Builtin.isinstance(v, String)) {
+			return TClass(String);
+		} else if (Builtin.isinstance(v, Array)) {
+			return TClass(Array);
+		} else if (Builtin.isinstance(v, AnonObject) || python.lib.Inspect.isclass(v)) {
+			return TObject;
+		}
+		else if (Builtin.isinstance(v, Enum)) {
+			return TEnum(Syntax.field(v, "__class__"));
+		}
+		else if (Builtin.isinstance(v, Builtin.type) || Internal.hasClass(v)) {
+			return TClass(Syntax.field(v, "__class__"));
+		} else if (Builtin.callable(v)) {
+			return TFunction;
+		} else {
+			return TUnknown;
+		}
+	}
+
+	static inline function asEnumImpl (x:Dynamic):EnumImpl {
+		return (cast x:EnumImpl);
+	}
+
+	public static function enumEq<T>( a : T, b : T ) : Bool {
+		if( a == b )
+			return true;
+		try {
+			if (b == null && a != b) return false;
+			if( asEnumImpl(a).tag != asEnumImpl(b).tag )
+				return false;
+			var p1 = asEnumImpl(a).params;
+			var p2 = asEnumImpl(b).params;
+			if (p1.length != p2.length) return false;
+
+			for( i in 0...p1.length )
+				if( !enumEq(p1[i],p2[i]) )
+					return false;
+
+			if( Internal.fieldClass(a) != Internal.fieldClass(b))
+				return false;
+		} catch( e : Dynamic ) {
+			return false;
+		}
+		return true;
+	}
+
+	public static inline function enumConstructor( e : EnumValue ) : String {
+		return asEnumImpl(e).tag;
+	}
+
+	public static inline function enumParameters( e : EnumValue ) : Array<Dynamic> {
+		return asEnumImpl(e).params;
+	}
+
+	public static inline function enumIndex( e : EnumValue ) : Int {
+		return asEnumImpl(e).index;
+	}
+
+	public static function allEnums<T>( e : Enum<T> ) : Array<T>
+	{
+			var ctors = getEnumConstructs(e);
+			var ret = [];
+			for (ctor in ctors)
+			{
+					var v = Reflect.field(e, ctor);
+					if (Std.is(v, e))
+							ret.push(v);
+			}
+
+			return ret;
+	}
+
+}

+ 335 - 0
std/python/_std/Xml.hx

@@ -0,0 +1,335 @@
+/*
+ * 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.
+ */
+enum XmlType {
+}
+
+@:coreApi class Xml {
+
+	public static var Element(default,null) : XmlType;
+	public static var PCData(default,null) : XmlType;
+	public static var CData(default,null) : XmlType;
+	public static var Comment(default,null) : XmlType;
+	public static var DocType(default,null) : XmlType;
+	public static var ProcessingInstruction(default,null) : XmlType;
+	public static var Document(default,null) : XmlType;
+
+	public var nodeType(default,null) : XmlType;
+	public var nodeName(get,set) : String;
+	public var nodeValue(get,set) : String;
+	public var parent(get,null) : Xml;
+
+	var _nodeName : String;
+	var _nodeValue : String;
+	var _attributes : haxe.ds.StringMap<String>;
+	var _children : Array<Xml>;
+	var _parent : Xml;
+
+	public static function parse( str : String ) : Xml {
+		return haxe.xml.Parser.parse(str);
+	}
+
+	private function new() : Void {
+	}
+
+	public static function createElement( name : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.Element;
+		r._children = new Array();
+		r._attributes = new haxe.ds.StringMap();
+		r.set_nodeName( name );
+		return r;
+	}
+
+	public static function createPCData( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.PCData;
+		r.set_nodeValue( data );
+		return r;
+	}
+
+	public static function createCData( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.CData;
+		r.set_nodeValue( data );
+		return r;
+	}
+
+	public static function createComment( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.Comment;
+		r.set_nodeValue( data );
+		return r;
+	}
+
+	public static function createDocType( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.DocType;
+		r.set_nodeValue( data );
+		return r;
+	}
+
+	public static function createProcessingInstruction( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.ProcessingInstruction;
+		r.set_nodeValue( data );
+		return r;
+	}
+
+	public static function createDocument() : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.Document;
+		r._children = new Array();
+		return r;
+	}
+
+	private function get_nodeName() : String {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		return _nodeName;
+	}
+
+	private function set_nodeName( n : String ) : String {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		return _nodeName = n;
+	}
+
+	private function get_nodeValue() : String {
+		if( nodeType == Xml.Element || nodeType == Xml.Document )
+			throw "bad nodeType";
+		return _nodeValue;
+	}
+
+	private function set_nodeValue( v : String ) : String {
+		if( nodeType == Xml.Element || nodeType == Xml.Document )
+			throw "bad nodeType";
+		return _nodeValue = v;
+	}
+
+	private function get_parent() : Xml {
+		return _parent;
+	}
+
+	public function get( att : String ) : String {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		return _attributes.get( att );
+	}
+
+	public function set( att : String, value : String ) : Void {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		_attributes.set( att, value );
+	}
+
+	public function remove( att : String ) : Void{
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		_attributes.remove( att );
+	}
+
+	public function exists( att : String ) : Bool {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		return _attributes.exists( att );
+	}
+
+	public function attributes() : Iterator<String> {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		return _attributes.keys();
+	}
+
+	public function iterator() : Iterator<Xml> {
+		if( _children == null ) throw "bad nodetype";
+		var cur = 0;
+		var x = this._children;
+		return {
+
+			hasNext : function(){
+				return cur < x.length;
+			},
+			next : function(){
+				return x[cur++];
+			}
+		}
+	}
+
+	public function elements() : Iterator<Xml> {
+		if( _children == null ) throw "bad nodetype";
+		var cur = 0;
+		var x = this._children;
+		return {
+
+			hasNext : function() {
+				var k = cur;
+				var l = x.length;
+				while( k < l ) {
+					if( x[k].nodeType == Xml.Element )
+						break;
+					k += 1;
+				}
+				cur = k;
+				return k < l;
+			},
+			next : function() {
+				var k = cur;
+				var l = x.length;
+				while( k < l ) {
+					var n = x[k];
+					k += 1;
+					if( n.nodeType == Xml.Element ) {
+						cur = k;
+						return n;
+					}
+				}
+				return null;
+			}
+		}
+	}
+
+	public function elementsNamed( name : String ) : Iterator<Xml> {
+		if( _children == null ) throw "bad nodetype";
+		var cur = 0;
+		var x = this._children;
+		return {
+
+			hasNext : function() {
+				var k = cur;
+				var l = x.length;
+				while( k < l ) {
+					var n = x[k];
+					if( n.nodeType == Xml.Element && n._nodeName == name )
+						break;
+					k++;
+				}
+				cur = k;
+				return k < l;
+			},
+			next : function() {
+				var k = cur;
+				var l = x.length;
+				while( k < l ) {
+					var n = x[k];
+					k++;
+					if( n.nodeType == Xml.Element && n._nodeName == name ) {
+						cur = k;
+						return n;
+					}
+				}
+				return null;
+			}
+		}
+	}
+
+	public function firstChild() : Xml {
+		if( _children == null ) throw "bad nodetype";
+		return _children[0];
+	}
+
+	public function firstElement() : Xml {
+		if( _children == null ) throw "bad nodetype";
+		var cur = 0;
+		var l = _children.length;
+		while( cur < l ) {
+			var n = _children[cur];
+			if( n.nodeType == Xml.Element )
+				return n;
+			cur++;
+		}
+		return null;
+	}
+
+	public function addChild( x : Xml ) : Void {
+		if( _children == null ) throw "bad nodetype";
+		if( x._parent != null ) x._parent._children.remove(x);
+		x._parent = this;
+		_children.push( x );
+	}
+
+	public function removeChild( x : Xml ) : Bool {
+		if( _children == null ) throw "bad nodetype";
+		var b = _children.remove( x );
+		if( b )
+			x._parent = null;
+		return b;
+	}
+
+	public function insertChild( x : Xml, pos : Int ) : Void {
+		if( _children == null ) throw "bad nodetype";
+		if( x._parent != null ) x._parent._children.remove(x);
+		x._parent = this;
+		_children.insert( pos, x );
+	}
+
+	public function toString() : String {
+		if( nodeType == Xml.PCData )
+			return StringTools.htmlEscape(_nodeValue);
+		if( nodeType == Xml.CData )
+			return "<![CDATA["+_nodeValue+"]]>";
+		if( nodeType == Xml.Comment )
+			return "<!--"+_nodeValue+"-->";
+		if( nodeType == Xml.DocType )
+			return "<!DOCTYPE "+_nodeValue+">";
+		if( nodeType == Xml.ProcessingInstruction )
+			return "<?"+_nodeValue+"?>";
+		var s = new StringBuf();
+
+		if( nodeType == Xml.Element ) {
+			s.add("<");
+			s.add(_nodeName);
+			for( k in _attributes.keys() ){
+				s.add(" ");
+				s.add(k);
+				s.add("=\"");
+				s.add(_attributes.get(k));
+				s.add("\"");
+			}
+			if( _children.length == 0 ) {
+				s.add("/>");
+				return s.toString();
+			}
+			s.add(">");
+		}
+
+		for( x in iterator() )
+			s.add(x.toString());
+
+		if( nodeType == Xml.Element ) {
+			s.add("</");
+			s.add(_nodeName);
+			s.add(">");
+		}
+		return s.toString();
+	}
+
+	static function __init__() : Void {
+		Xml.Element = cast "element";
+		Xml.PCData = cast "pcdata";
+		Xml.CData = cast "cdata";
+		Xml.Comment = cast "comment";
+		Xml.DocType = cast "doctype";
+		Xml.ProcessingInstruction = cast "processingInstruction";
+		Xml.Document = cast "document";
+	}
+
+}

+ 43 - 0
std/python/_std/haxe/Json.hx

@@ -0,0 +1,43 @@
+/*
+ * 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 haxe;
+
+import python.Syntax;
+
+class Json {
+
+	public static inline function parse( text : String ) : Dynamic {
+		return python.lib.Json.loads(text, null, null, python.Lib.dictToAnon);
+	}
+
+	public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space : String ) : String {
+
+		return haxe.format.JsonPrinter.print(value, replacer, space);
+		/*
+		function def (o:Dynamic) {
+			trace(o);
+			return python.Lib.anonToDict(o);
+		}
+		return python.lib.Json.dumps(value, false, false, true, true, null, null, null, def);
+		*/
+	}
+}

+ 59 - 0
std/python/_std/haxe/ds/IntMap.hx

@@ -0,0 +1,59 @@
+package haxe.ds;
+
+import python.lib.Dict;
+import python.Syntax;
+
+class IntMap<T> implements Map.IMap<Int, T> {
+	private var h : Dict<Int, T>;
+
+	public function new() : Void {
+		h = new Dict();
+	}
+
+	public function set( key : Int, value : T ) : Void {
+		h.set(key, value);
+	}
+
+	public inline function get( key : Int ) : Null<T> {
+		return h.get(key, null);
+	}
+
+	public inline function exists( key : Int ) : Bool {
+		return h.hasKey(key);
+	}
+
+	public function remove( key : Int ) : Bool
+	{
+		if(!h.hasKey(key)) return false;
+		Syntax.delete(Syntax.arrayAccess(h, key));
+		return true;
+	}
+
+	public function keys() : Iterator<Int> {
+		return h.keys().iter();
+	}
+
+	public function iterator() : Iterator<T> {
+		var iter = keys();
+		var ref = h;
+		return {
+			hasNext : function() { return iter.hasNext(); },
+			next : function() { var i = iter.next(); return ref.get(i, null); }
+		};
+	}
+
+	public function toString() : String {
+		var s = new StringBuf();
+		s.add("{");
+		var it = keys();
+		for( i in it ) {
+			s.add(i);
+			s.add(" => ");
+			s.add(Std.string(get(i)));
+			if( it.hasNext() )
+				s.add(", ");
+		}
+		s.add("}");
+		return s.toString();
+	}
+}

+ 56 - 0
std/python/_std/haxe/ds/ObjectMap.hx

@@ -0,0 +1,56 @@
+package haxe.ds;
+
+import python.lib.Builtin;
+import python.lib.Dict;
+
+class ObjectMap<K:{},V> implements Map.IMap<K, V> {
+
+	var h : Dict<K,V>;
+
+
+	public function new() : Void {
+		h = new Dict();
+	}
+
+	public function set(key:K, value:V):Void {
+		h.set(key, value);
+	}
+
+	public inline function get(key:K):Null<V> {
+		return h.get(key, null);
+	}
+
+	public inline function exists(key:K):Bool {
+		return h.hasKey(key);
+	}
+
+	public function remove( key : K ) : Bool
+	{
+		var r = h.hasKey(key);
+		if (r) h.remove(key);
+		return r;
+	}
+
+	public function keys() : Iterator<K> {
+		return h.keys().iter();
+	}
+
+	public function iterator() : Iterator<V> {
+		return h.values().iter();
+	}
+
+	public function toString() : String {
+		var s = new StringBuf();
+		s.add("{");
+		var it = keys();
+		for( i in it ) {
+			s.add(Std.string(i));
+			s.add(" => ");
+			s.add(Std.string(get(i)));
+			if( it.hasNext() )
+				s.add(", ");
+		}
+		s.add("}");
+		return s.toString();
+	}
+}

+ 67 - 0
std/python/_std/haxe/ds/StringMap.hx

@@ -0,0 +1,67 @@
+package haxe.ds;
+
+
+import python.Syntax;
+import python.lib.Dict;
+
+class StringMap<T> implements Map.IMap<String, T> {
+	private var h : Dict<String,T>;
+
+	public function new() : Void {
+		h = new Dict();
+	}
+
+	public inline function set( key : String, value : T ) : Void {
+		h.set("$"+key, value);
+	}
+
+	public inline function get( key : String ) : Null<T> {
+		return h.get("$"+key, null);
+
+	}
+
+	public inline function exists( key : String ) : Bool {
+		return h.hasKey("$" + key);
+	}
+
+	public function remove( key : String ) : Bool {
+		var key = "$"+key;
+		var has = h.hasKey(key);
+		if (has) h.remove(key);
+		return has;
+	}
+
+	public function keys() : Iterator<String> {
+		var a = [];
+		Syntax.foreach(key, h, {
+			a.push( key.substr(1));
+		});
+		return a.iterator();
+	}
+
+	public function iterator() : Iterator<T> {
+		var iter = keys();
+		var ref = h;
+		return {
+			hasNext : function() { return iter.hasNext(); },
+			next : function() { var i = iter.next(); return ref.get("$"+i, null); }
+		};
+	}
+
+	public function toString() : String {
+
+		var s = new StringBuf();
+
+		s.add("{");
+		var it = keys();
+		for( i in it ) {
+			s.add(i);
+			s.add(" => ");
+			s.add(Std.string(get(i)));
+			if( it.hasNext() )
+				s.add(", ");
+		}
+		s.add("}");
+		return s.toString();
+	}
+}

+ 80 - 0
std/python/_std/sys/FileSystem.hx

@@ -0,0 +1,80 @@
+/*
+ * 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 sys;
+
+import python.lib.Os;
+import python.lib.os.Path;
+
+@:coreApi
+class FileSystem {
+
+	public static function exists( path : String ) : Bool {
+		return Path.exists(path);
+	}
+
+	public static function stat( path : String ) : sys.FileStat {
+		var s = Os.stat(path);
+		return {
+			gid : s.st_gid,
+			uid : s.st_uid,
+			atime : Date.fromTime(s.st_atime),
+			mtime : Date.fromTime(s.st_mtime),
+			ctime : Date.fromTime(s.st_ctime),
+			size : s.st_size,
+			dev : s.st_dev,
+			ino : s.st_ino,
+			nlink : s.st_nlink,
+			rdev : s.st_rdev,
+			mode : s.st_mode
+		}
+	}
+
+	public static function rename( path : String, newPath : String ) : Void {
+		Os.rename(path, newPath);
+	}
+
+	public static function fullPath( relPath : String ) : String {
+		return Path.abspath(relPath);
+	}
+
+	public static function isDirectory( path : String ) : Bool
+	{
+		return Path.isdir(path);
+	}
+
+	public static function createDirectory( path : String ) : Void {
+		Os.makedirs(path, 511, true);
+	}
+
+	public static function deleteFile( path : String ) : Void {
+		Os.remove(path);
+	}
+
+	public static function deleteDirectory( path : String ) : Void {
+		Os.rmdir(path);
+	}
+
+	public static function readDirectory( path : String ) : Array<String> {
+		return Os.listdir(path);
+	}
+
+}

+ 89 - 0
std/python/_std/sys/io/File.hx

@@ -0,0 +1,89 @@
+/*
+ * 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 sys.io;
+
+import python.io.IoTools;
+import sys.io.FileInput;
+
+/**
+	API for reading and writing to files.
+
+	See `sys.FileSystem` for the complementary file system API.
+**/
+@:coreApi
+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 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, "");
+		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 size = f.read(-1);
+		var b = haxe.io.Bytes.ofData(size);
+		f.close();
+		return b;
+	}
+
+	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);
+		f.write(bytes.getData());
+		f.close();
+	}
+
+	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 : "");
+
+		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 : "");
+
+		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 : "");
+
+		return if (binary) IoTools.createFileOutputFromBytes(cast f) else IoTools.createFileOutputFromText(cast f);
+	}
+
+	public static function copy( srcPath : String, dstPath : String ) : Void
+	{
+		return python.lib.ShUtil.copy(srcPath, dstPath);
+	}
+}

+ 105 - 0
std/python/_std/sys/io/FileInput.hx

@@ -0,0 +1,105 @@
+
+package sys.io;
+
+import haxe.io.Bytes;
+import haxe.io.Input;
+import python.io.IFileInput;
+
+
+
+class FileInput extends Input
+{
+	var impl:IFileInput;
+
+
+
+	public function new (impl:IFileInput) {
+		this.impl = impl;
+	}
+
+	override public function set_bigEndian(b:Bool) {
+		return impl.bigEndian = b;
+	}
+
+	public function seek( p : Int, pos : FileSeek ) : Void {
+		return impl.seek(p, pos);
+	}
+	public function tell() : Int {
+		return impl.tell();
+	}
+	public function eof() : Bool {
+		return impl.eof();
+	}
+
+	override public function readByte() : Int {
+		return impl.readByte();
+	}
+
+	override public function readBytes( s : Bytes, pos : Int, len : Int ) : Int {
+		return impl.readBytes(s, pos, len);
+	}
+
+	override public function close():Void {
+		impl.close();
+	}
+
+	override public function readAll( ?bufsize : Int ) : Bytes {
+		return impl.readAll(bufsize);
+	}
+
+	override public function readFullBytes( s : Bytes, pos : Int, len : Int ):Void {
+		impl.readFullBytes(s, pos, len);
+	}
+
+	override public function read( nbytes : Int ) : Bytes {
+		return impl.read(nbytes);
+	}
+
+	override public function readUntil( end : Int ) : String {
+		return impl.readUntil(end);
+	}
+
+	override public function readLine() : String {
+		return impl.readLine();
+	}
+
+	override public function readFloat() : Float {
+		return impl.readFloat();
+	}
+
+	override public function readDouble() : Float {
+		return impl.readDouble();
+	}
+
+	override public function readInt8():Int {
+		return impl.readInt8();
+	}
+
+	override public function readInt16():Int {
+		return impl.readInt16();
+	}
+
+	override public function readUInt16():Int {
+		return impl.readUInt16();
+	}
+
+	override public function readInt24():Int {
+		return impl.readInt24();
+	}
+
+	override public function readUInt24():Int {
+		return impl.readUInt24();
+	}
+
+	override public function readInt32():Int {
+		return impl.readInt32();
+	}
+
+	override public function readString( len : Int ) : String {
+		return impl.readString(len);
+	}
+
+
+
+
+}

+ 95 - 0
std/python/_std/sys/io/FileOutput.hx

@@ -0,0 +1,95 @@
+package sys.io;
+
+import haxe.io.Bytes;
+import haxe.io.Input;
+import haxe.io.Output;
+import python.io.IFileOutput;
+
+class FileOutput extends Output {
+
+	var impl:IFileOutput;
+
+	public function new (impl:IFileOutput) {
+		this.impl = impl;
+	}
+
+	public function seek( p : Int, pos : FileSeek ) : Void {
+		return impl.seek(p, pos);
+	}
+
+	public function tell() : Int {
+		return impl.tell();
+	}
+
+	override public function set_bigEndian(b:Bool) {
+		return impl.bigEndian = b;
+	}
+
+	override public function writeByte( c : Int ) : Void {
+		impl.writeByte(c);
+	}
+
+	override public function writeBytes( s : Bytes, pos : Int, len : Int ):Int {
+		return impl.writeBytes(s,pos,len);
+	}
+
+	override public function flush():Void {
+		impl.flush();
+	}
+
+	override public function close():Void {
+		impl.close();
+	}
+
+	override public function write( s : Bytes ) : Void {
+		impl.write(s);
+	}
+
+	override public function writeFullBytes( s : Bytes, pos : Int, len : Int ):Void {
+		impl.writeFullBytes(s,pos,len);
+	}
+
+	override public function writeFloat( x : Float ):Void {
+		impl.writeFloat(x);
+	}
+
+	override public function writeDouble( x : Float ):Void {
+		impl.writeDouble(x);
+	}
+
+	override public function writeInt8( x : Int ):Void {
+		impl.writeInt8(x);
+	}
+
+	override public function writeInt16( x : Int ):Void {
+		impl.writeInt16(x);
+	}
+
+	override public function writeUInt16( x : Int ):Void {
+		impl.writeUInt16(x);
+	}
+
+	override public function writeInt24( x : Int ):Void {
+		impl.writeInt24(x);
+	}
+
+	override public function writeUInt24( x : Int ):Void {
+		impl.writeUInt24(x);
+	}
+
+	override public function writeInt32( x : Int ):Void {
+		impl.writeInt32(x);
+	}
+
+	override public function prepare( nbytes : Int ):Void {
+		impl.prepare(nbytes);
+	}
+
+	override public function writeInput( i : Input, ?bufsize : Int ):Void {
+		impl.writeInput(i,bufsize);
+	}
+
+	override public function writeString( s : String ):Void {
+		impl.writeString(s);
+	}
+}

+ 38 - 0
std/python/_std/sys/io/Process.hx

@@ -0,0 +1,38 @@
+
+package sys.io;
+
+import python.lib.Subprocess;
+import python.lib.subprocess.Popen;
+
+class Process {
+
+	public var stdout(default,null) : haxe.io.Input;
+	public var stderr(default,null) : haxe.io.Input;
+	public var stdin(default,null) : haxe.io.Output;
+
+	var p:Popen;
+
+	public function new( cmd : String, args : Array<String> ) : Void {
+
+		p = Popen.create([cmd].concat(args), { stdin : Subprocess.PIPE, stdout: Subprocess.PIPE, stderr : Subprocess.PIPE });
+
+
+		this.stdout = new FileInput (cast p.stdout);
+		this.stderr = new FileInput (cast p.stderr);
+		this.stdin =  new FileOutput(cast p.stdin);
+	}
+
+	public function getPid() : Int {
+		return p.pid;
+	}
+	public function exitCode() : Int {
+		return p.returncode;
+	}
+	public function close() : Void {
+		p.terminate();
+	}
+	public function kill() : Void {
+		p.kill();
+	}
+
+}

+ 64 - 0
std/python/_std/sys/net/Host.hx

@@ -0,0 +1,64 @@
+/*
+ * 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 sys.net;
+
+/**
+	A given IP host name.
+**/
+class Host {
+
+	/**
+		The actual IP corresponding to the host.
+	**/
+	public var ip(default,null) : Int;
+
+	/**
+		Creates a new Host : the name can be an IP in the form "127.0.0.1" or an host name such as "google.com", in which case
+		the corresponding IP address is resolved using DNS. An exception occur if the host name could not be found.
+	**/
+    var name:String;
+	public function new( name : String ) : Void {
+        this.name = name;
+    }
+
+	/**
+		Returns the IP representation of the host
+	**/
+	public function toString() : String {
+        return name;
+    }
+
+	/**
+		Perform a reverse-DNS query to resolve a host name from an IP.
+	**/
+	public function reverse() : String {
+        return "";
+    }
+
+	/**
+		Returns the local computer host name
+	**/
+	public static function localhost() : String {
+        return "";
+    }
+
+}

+ 268 - 0
std/python/_std/sys/net/Socket.hx

@@ -0,0 +1,268 @@
+/*
+* 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 sys.net;
+
+import haxe.io.Error;
+import haxe.io.Bytes;
+import haxe.io.BytesData;
+import python.lib.Exceptions;
+import python.lib.Tuple;
+import python.lib.net.Socket in PSocket;
+import python.lib.net.Socket.Select in Select;
+import python.lib.net.Address in PAddress;
+
+private class SocketInput extends haxe.io.Input {
+
+    var __s : PSocket;
+
+    public function new(s) {
+        __s = s;
+    }
+
+    public override function readByte() : Int {
+        var r:BytesData;
+        try {
+            r = __s.recv(1,0);
+        } catch( e : BlockingIOError ) {
+                throw Blocked;
+        }
+        if( r.length == 0 )
+            throw new haxe.io.Eof();
+        return python.Syntax.pythonCode("r[0]");
+    }
+
+    public override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int {
+        var r;
+        var data = buf.getData();
+        try {
+            r = __s.recv(len,0);
+            for (i in pos...(pos+r.length)){
+                data.set(i,r[i-pos]);
+            }
+        } catch( e : BlockingIOError ) {
+                throw Blocked;
+        }
+        if( r.length == 0 )
+            throw new haxe.io.Eof();
+        return r.length;
+    }
+
+    public override function close() {
+        super.close();
+        if( __s != null ) __s.close();
+    }
+
+}
+
+private class SocketOutput extends haxe.io.Output {
+
+    var __s : PSocket;
+
+    public function new(s) {
+        __s = s;
+    }
+
+    public override function writeByte( c : Int ) {
+        try {
+            __s.send(python.Syntax.pythonCode('bytes([c])'),0);
+        } catch( e : BlockingIOError ) {
+                throw Blocked;
+        }
+    }
+
+    public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int {
+        return try {
+            var data    = buf.getData();
+            var payload = python.Syntax.pythonCode("data[pos:pos+len]");
+            var r = __s.send(payload,0);
+            return r;
+        } catch( e : BlockingIOError ) {
+                throw Blocked;
+        }
+    }
+
+    public override function close() {
+        super.close();
+        if( __s != null ) __s.close();
+    }
+}
+
+/**
+    A TCP socket class : allow you to both connect to a given server and exchange messages or start your own server and wait for connections.
+**/
+@:coreApi class Socket {
+
+
+    var __s:PSocket;
+    /**
+        The stream on which you can read available data. By default the stream is blocking until the requested data is available,
+        use [setBlocking(false)] or [setTimeout] to prevent infinite waiting.
+    **/
+    public var input(default,null) : haxe.io.Input;
+
+    /**
+        The stream on which you can send data. Please note that in case the output buffer you will block while writing the data, use [setBlocking(false)] or [setTimeout] to prevent that.
+    **/
+    public var output(default,null) : haxe.io.Output;
+
+    /**
+        A custom value that can be associated with the socket. Can be used to retreive your custom infos after a [select].
+    ***/
+    public var custom : Dynamic;
+
+    /**
+        Creates a new unconnected socket.
+    **/
+    public function new() : Void {
+        //var __s = new PSocket();
+        //input = new SocketInput(__s);
+        //output = new SocketOutput(__s);
+    }
+
+    function __init() : Void  {
+        __s = new PSocket();
+        input = new SocketInput(__s);
+        output = new SocketOutput(__s);
+    }
+
+    /**
+        Closes the socket : make sure to properly close all your sockets or you will crash when you run out of file descriptors.
+    **/
+    public function close() : Void {
+        __s.close();
+    }
+
+    /**
+        Read the whole data available on the socket.
+    **/
+    public function read() : String {
+        return "";
+    }
+
+    /**
+        Write the whole data to the socket output.
+    **/
+    public function write( content : String ) : Void {
+
+    }
+
+    /**
+        Connect to the given server host/port. Throw an exception in case we couldn't sucessfully connect.
+    **/
+    public function connect( host : Host, port : Int ) : Void {
+        __init();
+        var host_str = host.toString();
+        __s.connect(python.Syntax.pythonCode("(host_str,port)"));
+    }
+
+    /**
+        Allow the socket to listen for incoming questions. The parameter tells how many pending connections we can have until they get refused. Use [accept()] to accept incoming connections.
+    **/
+    public function listen( connections : Int ) : Void {
+        __s.listen(connections);
+    }
+
+    /**
+        Shutdown the socket, either for reading or writing.
+    **/
+    public function shutdown( read : Bool, write : Bool ) : Void
+        __s.shutdown( (read && write) ? PSocket.SHUT_RDWR : read ?  PSocket.SHUT_RD : PSocket.SHUT_WR  );
+
+    /**
+        Bind the socket to the given host/port so it can afterwards listen for connections there.
+    **/
+    public function bind( host : Host, port : Int ) : Void {
+        __init();
+        var host_str = host.toString();
+        __s.bind(python.Syntax.pythonCode("(host_str,port)"));
+    }
+
+    /**
+        Accept a new connected client. This will return a connected socket on which you can read/write some data.
+    **/
+    public function accept() : Socket {
+        var tp2:Tup2<PSocket,PAddress> = __s.accept();
+        var s = new Socket();
+        s.__s = tp2._1;
+        s.input = new SocketInput(s.__s);
+        s.output = new SocketOutput(s.__s);
+        return s;
+    }
+
+    /**
+        Return the informations about the other side of a connected socket.
+    **/
+    public function peer() : { host : Host, port : Int } {
+        var pn = __s.getpeername();
+        return { host:new Host( pn._1 ), port:pn._2}
+    }
+
+    /**
+        Return the informations about our side of a connected socket.
+    **/
+    public function host() : { host : Host, port : Int } {
+        var pn = __s.getsockname();
+        return { host:new Host( pn._1 ), port:pn._2};
+    }
+
+    /**
+        Gives a timeout after which blocking socket operations (such as reading and writing) will abort and throw an exception.
+    **/
+    public function setTimeout( timeout : Float ) : Void {
+        __s.settimeout(timeout);
+    }
+
+    /**
+        Block until some data is available for read on the socket.
+    **/
+    public function waitForRead() : Void {
+
+    }
+
+    /**
+        Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediatly by throwing a haxe.io.Error.Blocking value.
+    **/
+    public function setBlocking( b : Bool ) : Void {
+        __s.setblocking(b);
+    }
+
+    /**
+        Allows the socket to immediatly send the data when written to its output : this will cause less ping but might increase the number of packets / data size, especially when doing a lot of small writes.
+    **/
+    public function setFastSend( b : Bool ) : Void {}
+
+    @:keep function fileno():Int return __s.fileno();
+
+    /**
+        Wait until one of the sockets groups is ready for the given operation :
+        [read] contains sockets on which we want to wait for available data to be read,
+        [write] contains sockets on which we want to wait until we are allowed to write some data to their output buffers,
+        [others] contains sockets on which we want to wait for exceptional conditions.
+        [select] will block until one of the condition is met, in which case it will return the sockets for which the condition was true.
+        In case a [timeout] (in seconds) is specified, select might wait at worse until the timeout expires.
+    **/
+    public static function select(read : Array<Socket>, write : Array<Socket>, others : Array<Socket>, ?timeout : Float) : { read: Array<Socket>,write: Array<Socket>,others: Array<Socket> } {
+        var t3 = Select.select(read,write,others,timeout);
+        return {read:t3._1,write:t3._2,others:t3._3};
+    }
+
+}

+ 7 - 0
std/python/internal/AnonObject.hx

@@ -0,0 +1,7 @@
+
+package python.internal;
+
+@:native("_hx_AnonObject")
+extern class AnonObject {
+
+}

+ 168 - 0
std/python/internal/ArrayImpl.hx

@@ -0,0 +1,168 @@
+/*
+ * 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;
+
+import python.lib.FuncTools;
+//import python.lib.Builtin;
+
+private abstract Builtin(Dynamic) {}
+
+@:allow(Array)
+@:keep
+class ArrayImpl {
+
+	static inline function builtin():Builtin return Internal.builtin();
+
+	public static inline function get_length <T>(x:Array<T>):Int return Syntax.callField(builtin(), "len", x);
+
+	public static inline function concat<T>( a1:Array<T>, a2 : Array<T>) : Array<T> {
+		return Syntax.binop(a1, "+", a2);
+	}
+
+	public static inline function copy<T>(x:Array<T>) : Array<T> {
+		return Syntax.field(builtin(), "list")(x);
+	}
+
+	public static inline function iterator<T>(x:Array<T>) : Iterator<T> {
+		return new HaxeIterator(Syntax.callField(x, "__iter__"));
+	}
+
+	public static function indexOf<T>(a:Array<T>, x : T, ?fromIndex:Int) : Int {
+		var l =
+			if (fromIndex == null) 0
+			else if (fromIndex < 0) a.length + fromIndex
+			else fromIndex;
+		if (l < 0) l = 0;
+		for (i in l...a.length) {
+			if (a[i] == x) return i;
+		}
+		return -1;
+	}
+
+	public static function lastIndexOf<T>(a:Array<T>, x : T, ?fromIndex:Int) : Int {
+		var l =
+			if (fromIndex == null) a.length
+			else if (fromIndex < 0) a.length + fromIndex + 1
+			else fromIndex+1;
+		if (l > a.length) l = a.length;
+		while (--l > -1) {
+			if (a[l] == x) return l;
+		}
+		return -1;
+	}
+
+	@:access(python.Boot)
+	public static inline function join<T>(x:Array<T>, sep : String ) : String {
+		return Syntax.field(sep, "join")(x.map(python.Boot.toString));
+	}
+
+	public static inline function toString<T>(x:Array<T>) : String {
+		return "[" + join(x, ",") + "]";
+	}
+
+	public static inline function pop<T>(x:Array<T>) : Null<T> {
+		return if (x.length == 0) null else Syntax.callField(x, "pop");
+	}
+
+	public static inline function push<T>(x:Array<T>, e:T) : Int {
+		Syntax.callField(x, "append", e);
+		return get_length(x);
+	}
+
+	public static inline function unshift<T>(x:Array<T>,e : T) : Void {
+		return x.insert(0,e);
+	}
+
+	public static function remove<T>(x:Array<T>,e : T) : Bool {
+		try {
+			Syntax.callField(x, "remove", e);
+			return true;
+		} catch (e:Dynamic) {
+			return false;
+		}
+	}
+
+	public static inline function shift<T>(x:Array<T>) : Null<T> {
+		if (x.length == 0) return null;
+		return Syntax.callField(x, "pop", 0);
+	}
+
+	public static inline function slice<T>(x:Array<T>, pos : Int, ?end : Int ) : Array<T> {
+		return Syntax.arrayAccess(x, pos, end);
+	}
+
+	public static inline function sort<T>(x:Array<T>, f:T->T->Int) : Void {
+		Syntax.callNamedUntyped(Syntax.field(x, "sort"), { key : python.lib.FuncTools.cmp_to_key(f) });
+	}
+
+	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;
+		var res = Syntax.arrayAccess(x, pos, pos+len);
+		Syntax.delete((Syntax.arrayAccess(x, pos, pos+len)));
+		return res;
+	}
+
+	public static inline function map<S,T>(x:Array<T>, f : T -> S ) : Array<S> {
+		return Syntax.field(builtin(), "list")(Syntax.field(builtin(), "map")(f, x));
+	}
+
+	public static inline function filter<T>(x:Array<T>, f : T -> Bool ) : Array<T> {
+		return Syntax.field(builtin(), "list")(Syntax.field(builtin(), "filter")(f, x));
+	}
+
+	public static inline function insert<T>(a:Array<T>, pos : Int, x : T ) : Void {
+		Syntax.callField(a, "insert", pos, x);
+	}
+
+	public static inline function reverse<T>(a:Array<T>) : Void {
+		Syntax.callField(a, "reverse");
+	}
+
+	private static inline function __get<T>(x:Array<T>, idx:Int):T {
+		return if (idx < x.length && idx > -1) Syntax.arrayAccess(x, idx) else null;
+	}
+
+	private static inline function __set<T>(x:Array<T>, idx:Int, v:T):T {
+		var l = x.length;
+		while (l < idx) {
+			x.push(null);
+			l+=1;
+		}
+		if (l == idx) {
+			x.push(v);
+		} else {
+			Syntax.assign(Syntax.arrayAccess(x, idx), v);
+		}
+		return v;
+	}
+
+	private static inline function __unsafe_get<T>(x:Array<T>,idx:Int):T {
+		return Syntax.arrayAccess(x, idx);
+	}
+
+	private static inline function __unsafe_set<T>(x:Array<T>,idx:Int, val:T):T {
+		Syntax.assign(Syntax.arrayAccess(x, idx), val);
+		return val;
+	}
+}

+ 23 - 0
std/python/internal/EnumImpl.hx

@@ -0,0 +1,23 @@
+package python.internal;
+
+@:keep
+@:native("Enum")
+class EnumImpl {
+	public var tag:String;
+	public var index:Int;
+	public var params:Array<Dynamic>;
+
+	public function new(tag, index, params) {
+		this.tag = tag;
+		this.index = index;
+		this.params = params;
+	}
+
+	function __str__() {
+		return if (params == null) {
+			tag;
+		} else {
+			tag + "(" + params.join(",") + ")";
+		}
+	}
+}

+ 12 - 0
std/python/internal/HxException.hx

@@ -0,0 +1,12 @@
+package python.internal;
+
+@:keep
+@:native("_HxException")
+class HxException extends python.lib.Exceptions.Exception {
+	public var val:Dynamic;
+	public function new(val) {
+		var message = Std.string(val);
+		super(message);
+		this.val = val;
+	}
+}

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

@@ -0,0 +1,58 @@
+package python.internal;
+
+import python.Syntax;
+
+import python.Syntax.pythonCode in py;
+
+@:keep
+@:native("HxOverrides")
+@:access(python.internal.ArrayImpl)
+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
+
+	static public function iterator(x) {
+		if (Std.is(x, Array)) {
+			return (x:Array<Dynamic>).iterator();
+		}
+		return Reflect.callMethod(null, Reflect.field(x, "iterator"), []);
+	}
+
+	static public function shift(x) {
+		return Reflect.callMethod(null, Reflect.field(x, "shift"), []);
+	}
+	static public function toUpperCase(x) {
+		return Reflect.callMethod(null, Reflect.field(x, "toUpperCase"), []);
+	}
+
+	static public function toLowerCase(x) {
+		return Reflect.callMethod(null, Reflect.field(x, "toLowerCase"), []);
+	}
+
+	static public function rshift(val:Int, n:Int) {
+		return Syntax.binop(Syntax.binop(val, "%", Syntax.pythonCode("0x100000000")), ">>", n);
+	}
+
+	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)");
+	}
+
+	static public function arrayGet<T>(a:Dynamic, i:Int):Dynamic {
+		if (Std.is(a, Array)) {
+			return ArrayImpl.__get(a, i);
+		} else {
+			return Syntax.arrayAccess(a, i);
+		}
+	}
+
+	static public function arraySet(a:Dynamic, i:Int, v:Dynamic) {
+		if (Std.is(a, Array)) {
+			return ArrayImpl.__set(a, i, v);
+		} else {
+			Syntax.assign(Syntax.arrayAccess(a, i), v);
+			return v;
+		}
+	}
+
+}

+ 206 - 0
std/python/internal/Internal.hx

@@ -0,0 +1,206 @@
+package python.internal;
+#if macro
+import haxe.macro.Context;
+import haxe.macro.Expr;
+#end
+
+class Internal {
+
+	#if macro
+
+	static var _prefix = "_hx_";
+
+	static var _builtin = _prefix + "builtin";
+
+	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";
+	static var _statics = _prefix + "statics";
+	static var _interfaces = _prefix + "interfaces";
+	static var _emptyInit = _prefix + "empty_init";
+	static var _constructs = _prefix + "constructs";
+
+	static var _classes = _prefix + "classes";
+
+	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;
+		}
+	}
+
+	static function withPos(x:String):Expr {
+		return macro @:pos(Context.currentPos()) $v{x};
+	}
+
+	static function fieldWithPos(o:Expr, x:String):Expr {
+		return macro @:pos(Context.currentPos()) python.Syntax.field($o, $v{x});
+	}
+
+	static function has (o:Expr, field:String):Expr {
+		return macro python.Syntax.pythonCode($v{_builtin}).hasattr($o, $v{field});
+	}
+
+	#end
+
+	macro public static function builtin ():Expr {
+		return macro (python.Syntax.pythonCode($v{_builtin}):Dynamic);
+	}
+
+	macro public static function classRegistry ():Expr {
+		return macro (python.Syntax.pythonCode($v{_classes}) : python.lib.Dict<String, Class<Dynamic>>);
+	}
+
+	macro public static function callFieldPrefixed (o:Expr, x:String, params:Array<Expr>):Expr {
+		var args = [o,macro @:pos(Context.currentPos()) $v{_prefix + x}].concat(params);
+		return macro @:pos(Context.currentPos()) python.Syntax.callField($a{args});
+	}
+
+	macro public static function fieldPrefixed (o:Expr, x:String):Expr {
+		var args = [o,macro @:pos(Context.currentPos()) $v{_prefix + x}];
+		return macro @:pos(Context.currentPos()) python.Syntax.field($a{args});
+	}
+
+	macro public static function hasAttrPrefixed (o:Expr, x:String):Expr {
+		var args = [o,macro @:pos(Context.currentPos()) $v{_prefix + x}];
+		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});
+	}
+
+	macro public static function prefix ():Expr {
+		return macro @:pos(Context.currentPos()) $v{_prefix};
+	}
+
+	macro public static function pythonCodePrefixed (x:String):Expr {
+		return macro python.Syntax.pythonCode($v{_prefix + x});
+	}
+
+	macro public static function hasClassName (o:Expr):Expr {
+		return has(o, _className);
+	}
+
+	macro public static function hasInterfaces (o:Expr):Expr {
+		return has(o, _interfaces);
+	}
+
+	macro public static function hasClass (o:Expr):Expr {
+		return has(o, _class);
+	}
+
+	macro public static function hasConstructs (o:Expr):Expr {
+		return has(o, _constructs);
+	}
+
+	macro public static function hasEmptyInit (o:Expr):Expr {
+		return has(o, _emptyInit);
+	}
+
+	macro public static function hasFields (o:Expr):Expr {
+		return has(o, _fields);
+	}
+
+	macro public static function hasSuper (o:Expr):Expr {
+		return has(o, _super);
+	}
+
+	macro public static function hasStatics (o:Expr):Expr {
+		return has(o, _statics);
+	}
+
+	macro public static function classNameVal ():Expr {
+		return withPos(_className);
+	}
+
+	macro public static function methodsVal ():Expr {
+		return withPos(_methods);
+	}
+
+	macro public static function classVal():Expr {
+		return withPos(_className);
+	}
+
+	macro public static function propsVal():Expr {
+		return withPos(_props);
+	}
+
+	macro public static function superVal():Expr {
+		return withPos(_super);
+	}
+
+	macro public static function interfacesVal():Expr {
+		return withPos(_interfaces);
+	}
+
+	macro public static function fieldsVal():Expr {
+		return withPos(_fields);
+	}
+
+	macro public static function staticsVal():Expr {
+		return withPos(_statics);
+	}
+
+	macro public static function constructsVal():Expr {
+		return withPos(_constructs);
+	}
+
+	macro public static function emptyInitVal():Expr {
+		return withPos(_emptyInit);
+	}
+
+	macro public static function fieldClassName (o:Expr):Expr {
+		return fieldWithPos(o, _className);
+	}
+
+	macro public static function fieldInterfaces (o:Expr):Expr {
+		return fieldWithPos(o, _interfaces);
+	}
+
+	macro public static function fieldClass (o:Expr):Expr {
+		return fieldWithPos(o, _class);
+	}
+
+	macro public static function fieldSuper (o:Expr):Expr {
+		return fieldWithPos(o, _super);
+	}
+
+	macro public static function fieldStatics (o:Expr):Expr {
+		return fieldWithPos(o, _statics);
+	}
+
+	macro public static function fieldMethods (o:Expr):Expr {
+		return fieldWithPos(o, _methods);
+	}
+
+	macro public static function fieldFields (o:Expr):Expr {
+		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 fieldEmptyInit (o:Expr):Expr {
+		return fieldWithPos(o, _emptyInit);
+	}
+
+	macro public static function callEmptyInit (o:Expr, instance:Expr):Expr {
+		return macro @:pos(Context.currentPos()) python.Syntax.callField($o, $v{_emptyInit}, $instance);
+	}
+}

+ 99 - 0
std/python/internal/StringImpl.hx

@@ -0,0 +1,99 @@
+package python.internal;
+
+import python.internal.Internal;
+
+
+@:keep
+@:native("HxString")
+class StringImpl {
+
+	static inline function builtin ():Dynamic return Internal.builtin();
+
+	public static function split (s:String, d:String) {
+		return if (d == "") Syntax.field(builtin(), "list")(s) else Syntax.callField(s, "split", d);
+	}
+
+	public static function charCodeAt(s:String, index:Int) {
+		return
+			if (s == null || s.length == 0 || index < 0 || index >= s.length) null
+			else Syntax.callField(builtin(), "ord", Syntax.arrayAccess(s, index));
+	}
+
+	public static inline function charAt(s:String, index:Int) {
+		return if (index < 0 || index >= s.length) "" else Syntax.arrayAccess(s,index);
+	}
+
+	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 ? Syntax.callField(builtin(), "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;
+			} else {
+				return i;
+			}
+		}
+	}
+
+	public static function toUpperCase (s:String) {
+		return Syntax.callField(s, "upper");
+	}
+
+	public static function toLowerCase (s:String) {
+		return Syntax.callField(s, "lower");
+	}
+	public static 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);
+	}
+
+	public static function toString (s:String) {
+		return s;
+	}
+
+	public static function get_length (s:String) {
+		return Syntax.field(builtin(), "len")(s);
+	}
+
+	public static inline function fromCharCode( code : Int ) : String {
+		#if doc_gen
+		return "";
+		#else
+		var c = code;
+		return Syntax.callField('', "join",
+			Syntax.callField(builtin(), "map", Syntax.field(builtin(), "chr"), [c])); // TODO: check cast
+		#end
+	}
+
+	public static function substring( s:String, startIndex : Int, ?endIndex : Int ) : String {
+		if (startIndex < 0) startIndex = 0;
+		if (endIndex == null) {
+			return Syntax.arrayAccessWithTrailingColon(s, startIndex);
+		} else {
+			if (endIndex < 0) endIndex = 0;
+			if (endIndex < startIndex) {
+
+				return Syntax.arrayAccess(s, endIndex, startIndex);
+			} else {
+
+				return Syntax.arrayAccess(s, startIndex, endIndex);
+			}
+		}
+	}
+
+	public static function substr( s:String, startIndex : Int, ?len : Int ) : String {
+		if (len == null) {
+			return Syntax.arrayAccessWithTrailingColon(s, startIndex);
+		} else {
+			if (len == 0) return "";
+			return Syntax.arrayAccess(s, startIndex, startIndex+len);
+		}
+
+	}
+}

+ 14 - 0
std/python/io/FileBytesInput.hx

@@ -0,0 +1,14 @@
+
+package python.io;
+
+import python.io.NativeBytesInput;
+import python.io.NativeTextInput;
+import python.lib.io.RawIOBase;
+import python.lib.io.IOBase.SeekSet;
+import python.lib.io.TextIOBase;
+
+class FileBytesInput extends NativeBytesInput implements IFileInput {
+	public function new (stream:RawIOBase) {
+		super(stream);
+	}
+}

+ 12 - 0
std/python/io/FileBytesOutput.hx

@@ -0,0 +1,12 @@
+
+package python.io;
+
+import python.io.IFileOutput;
+import python.io.NativeBytesOutput;
+import python.lib.io.RawIOBase;
+
+class FileBytesOutput extends NativeBytesOutput implements IFileOutput {
+	public function new (stream:RawIOBase) {
+		super(stream);
+	}
+}

+ 13 - 0
std/python/io/FileTextInput.hx

@@ -0,0 +1,13 @@
+package python.io;
+
+import python.io.NativeBytesInput;
+import python.io.NativeTextInput;
+import python.lib.io.RawIOBase;
+import python.lib.io.IOBase.SeekSet;
+import python.lib.io.TextIOBase;
+
+class FileTextInput extends NativeTextInput implements IFileInput {
+	public function new (stream:TextIOBase) {
+		super(stream);
+	}
+}

+ 12 - 0
std/python/io/FileTextOutput.hx

@@ -0,0 +1,12 @@
+
+package python.io;
+
+import python.io.IFileOutput;
+import python.io.NativeBytesOutput;
+import python.lib.io.TextIOBase;
+
+class FileTextOutput extends NativeTextOutput implements IFileOutput {
+	public function new (stream:TextIOBase) {
+		super(stream);
+	}
+}

+ 14 - 0
std/python/io/IFileInput.hx

@@ -0,0 +1,14 @@
+
+package python.io;
+
+import python.io.IInput;
+import sys.io.FileSeek;
+
+
+
+interface IFileInput extends IInput {
+	public function seek( p : Int, pos : FileSeek ) : Void;
+
+	public function tell() : Int;
+	public function eof() : Bool;
+}

+ 12 - 0
std/python/io/IFileOutput.hx

@@ -0,0 +1,12 @@
+
+package python.io;
+
+import python.io.IOutput;
+import sys.io.FileSeek;
+
+interface IFileOutput extends IOutput {
+
+	public function seek( p : Int, pos : FileSeek ) : Void;
+	public function tell() : Int;
+
+}

+ 43 - 0
std/python/io/IInput.hx

@@ -0,0 +1,43 @@
+
+package python.io;
+
+import haxe.io.Bytes;
+
+interface IInput
+{
+	public var bigEndian(default,set) : Bool;
+
+	public function readByte() : Int;
+
+	public function readBytes( s : Bytes, pos : Int, len : Int ) : Int;
+
+	public function close():Void;
+
+	public function readAll( ?bufsize : Int ) : Bytes;
+
+	public function readFullBytes( s : Bytes, pos : Int, len : Int ):Void;
+
+	public function read( nbytes : Int ) : Bytes;
+
+	public function readUntil( end : Int ) : String;
+
+	public function readLine() : String;
+
+	public function readFloat() : Float;
+
+	public function readDouble() : Float;
+
+	public function readInt8():Int;
+
+	public function readInt16():Int;
+
+	public function readUInt16():Int;
+
+	public function readInt24():Int;
+
+	public function readUInt24():Int;
+
+	public function readInt32():Int;
+
+	public function readString( len : Int ) : String;
+}

+ 44 - 0
std/python/io/IOutput.hx

@@ -0,0 +1,44 @@
+
+package python.io;
+
+import haxe.io.Bytes;
+import haxe.io.Input;
+
+interface IOutput {
+
+	public var bigEndian(default, set) : Bool;
+
+	public function writeByte( c : Int ) : Void;
+
+	public function writeBytes( s : Bytes, pos : Int, len : Int ):Int;
+
+	public function flush():Void;
+
+	public function close():Void;
+
+	public function write( s : Bytes ) : Void;
+
+	public function writeFullBytes( s : Bytes, pos : Int, len : Int ):Void;
+
+	public function writeFloat( x : Float ):Void;
+
+	public function writeDouble( x : Float ):Void;
+
+	public function writeInt8( x : Int ):Void;
+
+	public function writeInt16( x : Int ):Void;
+
+	public function writeUInt16( x : Int ):Void;
+
+	public function writeInt24( x : Int ):Void;
+
+	public function writeUInt24( x : Int ):Void;
+
+	public function writeInt32( x : Int ):Void;
+
+	public function prepare( nbytes : Int ):Void;
+
+	public function writeInput( i : Input, ?bufsize : Int ):Void;
+
+	public function writeString( s : String ):Void;
+}

+ 61 - 0
std/python/io/IoTools.hx

@@ -0,0 +1,61 @@
+
+package python.io;
+
+import python.io.FileBytesInput;
+import python.io.FileTextInput;
+import python.io.FileTextOutput;
+import python.io.FileBytesOutput;
+import python.lib.io.RawIOBase;
+import python.lib.io.TextIOBase;
+import sys.io.FileInput;
+import sys.io.FileOutput;
+
+import python.lib.io.IOBase.SeekSet;
+
+
+class IoTools {
+
+	public static function createFileInputFromText (t:TextIOBase) {
+		return new FileInput(new FileTextInput(t));
+	}
+
+	public static function createFileInputFromBytes (t:RawIOBase) {
+		return new FileInput(new FileBytesInput(t));
+	}
+
+	public static function createFileOutputFromText (t:TextIOBase) {
+		return new FileOutput(new FileTextOutput(t));
+	}
+
+	public static function createFileOutputFromBytes (t:RawIOBase) {
+		return new FileOutput(new FileBytesOutput(t));
+	}
+
+	public static function seekInTextMode (stream:TextIOBase, tell:Void->Int , p : Int, pos : sys.io.FileSeek)
+	{
+ 		var pos = switch (pos) {
+ 			case SeekBegin:
+ 				SeekSet.SeekSet;
+ 			case SeekCur:
+ 				p = tell() + p;
+ 				SeekSet.SeekSet;
+ 			case SeekEnd :
+ 				stream.seek(0, SeekSet.SeekEnd);
+ 				p = tell() + p;
+ 				SeekSet.SeekSet;
+ 		}
+ 		stream.seek(p, pos);
+	}
+
+	public static function seekInBinaryMode (stream:RawIOBase, p : Int, pos : sys.io.FileSeek)
+	{
+ 		var pos = switch(pos)
+		{
+			case SeekBegin: SeekSet.SeekSet;
+			case SeekCur: SeekSet.SeekCur;
+			case SeekEnd: SeekSet.SeekEnd;
+		};
+		stream.seek(p, pos);
+	}
+
+}

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

@@ -0,0 +1,44 @@
+
+package python.io;
+
+import haxe.io.Eof;
+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;
+
+
+class NativeBytesInput extends NativeInput<RawIOBase> implements IInput {
+
+
+	public function new (stream:RawIOBase) {
+		super(stream);
+
+	}
+
+	override public function readByte():Int
+	{
+
+		var ret = stream.read(1);
+
+		if (ret.length == 0) throwEof();
+
+		return ret.get(0);
+	}
+
+	public function seek( p : Int, pos : sys.io.FileSeek ) : Void
+	{
+		wasEof = false;
+		return IoTools.seekInBinaryMode(stream, p, pos);
+	}
+
+	override function readinto (b:ByteArray):Int {
+		return stream.readinto(b);
+	}
+
+
+}

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

@@ -0,0 +1,30 @@
+
+package python.io;
+
+import haxe.io.Output;
+
+import python.lib.Builtin;
+import python.lib.io.IOBase;
+import python.lib.io.RawIOBase;
+
+class NativeBytesOutput extends NativeOutput<RawIOBase>{
+
+	public function new (stream:RawIOBase) {
+		super(stream);
+	}
+
+	public function seek( p : Int, pos : sys.io.FileSeek ) : Void
+	{
+		return IoTools.seekInBinaryMode(stream, p, pos);
+	}
+
+	override public function prepare(nbytes:Int):Void
+	{
+		stream.truncate(nbytes);
+	}
+
+	override public function writeByte(c:Int):Void
+	{
+		stream.write(Builtin.bytearray([c]));
+	}
+}

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

@@ -0,0 +1,65 @@
+
+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;
+
+class NativeInput<T:IOBase> extends Input{
+
+	var stream:T;
+	var wasEof:Bool;
+
+	function new (s:T) {
+		this.stream = s;
+		wasEof = false;
+		if (!stream.readable()) throw "Write-only stream";
+	}
+
+	public var canSeek(get_canSeek, null):Bool;
+
+	private function get_canSeek():Bool
+	{
+		return stream.seekable();
+	}
+
+	override public function close():Void
+	{
+		stream.close();
+	}
+
+	public function tell() : Int
+	{
+		return stream.tell();
+	}
+
+	function throwEof() {
+		wasEof = true;
+		throw new Eof();
+	}
+
+	public function eof() {
+		return wasEof;
+	}
+
+	function readinto (b:ByteArray):Int {
+		throw "abstract method, should be overriden";
+	}
+
+	override public function readBytes(s:haxe.io.Bytes, pos:Int, len:Int):Int
+	{
+		if( pos < 0 || len < 0 || pos + len > s.length )
+			throw haxe.io.Error.OutsideBounds;
+
+		stream.seek(pos, python.lib.io.IOBase.SeekSet.SeekCur);
+		var ba = Builtin.bytearray(len);
+		var ret = readinto(ba);
+		s.blit(pos, haxe.io.Bytes.ofData(ba) ,0,len);
+		if (ret == 0)
+			throwEof();
+		return ret;
+	}
+}

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

@@ -0,0 +1,46 @@
+
+package python.io;
+
+import haxe.io.Output;
+
+import python.lib.Builtin;
+import python.lib.io.IOBase;
+import python.lib.io.RawIOBase;
+
+class NativeOutput<T:IOBase> extends Output {
+
+	var stream:T;
+
+	public var canSeek(get_canSeek, null):Bool;
+
+	public function new (stream:T) {
+		this.stream = stream;
+		if (!stream.writable()) throw "Read only stream";
+	}
+
+	override public function close():Void
+	{
+		stream.close();
+	}
+
+	private function get_canSeek():Bool
+	{
+		return stream.seekable();
+	}
+
+	override public function prepare(nbytes:Int):Void
+	{
+		stream.truncate(nbytes);
+	}
+
+	override public function flush():Void
+	{
+		stream.flush();
+	}
+
+
+	public function tell() : Int
+	{
+		return stream.tell();
+	}
+}

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

@@ -0,0 +1,42 @@
+
+package python.io;
+
+import haxe.io.Eof;
+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;
+import python.lib.io.TextIOBase;
+
+
+class NativeTextInput extends NativeInput<TextIOBase> implements IInput {
+
+	public function new (stream:TextIOBase) {
+		super(stream);
+	}
+
+	override public function readByte():Int
+	{
+		var ret = stream.read(1);
+
+		if (ret.length == 0) throwEof();
+
+		return ret.charCodeAt(0);
+	}
+
+	public function seek( p : Int, pos : sys.io.FileSeek ) : Void
+	{
+		wasEof = false;
+		IoTools.seekInTextMode(stream, tell, p, pos);
+	}
+
+	override function readinto (b:ByteArray):Int {
+		return stream.buffer.readinto(b);
+	}
+
+}

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

@@ -0,0 +1,29 @@
+
+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;
+
+class NativeTextOutput extends NativeOutput<TextIOBase> {
+
+	public function new (stream:TextIOBase) {
+		super(stream);
+		if (!stream.writable()) throw "Read only stream";
+	}
+
+	public function seek( p : Int, pos : sys.io.FileSeek ) : Void
+	{
+		IoTools.seekInTextMode(stream, tell, p, pos);
+	}
+
+	override public function writeByte(c:Int):Void
+	{
+		stream.write(String.fromCharCode(c));
+	}
+
+}

+ 149 - 0
std/python/lib/Builtin.hx

@@ -0,0 +1,149 @@
+
+package python.lib;
+
+
+import python.lib.io.IOBase;
+import python.lib.Dict;
+import python.NativeIterable;
+import python.NativeIterator;
+
+@:native("_hx_builtin")
+extern class Builtin {
+
+
+
+	@:overload(function (f:Int):Int {})
+	public static function abs(x:Float):Float;
+	public static function all(i:Iterable<Bool>):Bool;
+	public static function any(i:Iterable<Bool>):Bool;
+
+	public static function bool(x:Dynamic):Bool;
+
+	public static function issubclass(x:Class<Dynamic>, from:Class<Dynamic>):Bool;
+	public static function callable(x:Dynamic):Bool;
+
+
+
+
+	@:overload(function (obj:Dynamic, f:Tuple<Dynamic>):Bool {})
+	public static function isinstance(obj:Dynamic, cl:Dynamic):Bool;
+
+	public static function hasattr(obj:Dynamic, attr:String):Bool;
+	public static function getattr(obj:Dynamic, attr:String):Dynamic;
+
+	@:overload(function (f:Set<Dynamic>):Int {})
+	@:overload(function (f:StringBuf):Int {})
+	@:overload(function (f:Array<Dynamic>):Int {})
+	@:overload(function (f:Dict<Dynamic, Dynamic>):Int {})
+	@:overload(function (f:Bytes):Int {})
+	@:overload(function (f:DictView<Dynamic>):Int {})
+	@:overload(function (f:ByteArray):Int {})
+	@:overload(function (f:Tuple<Dynamic>):Int {})
+	public static function len(x:String):Int;
+
+	public static function open(file:String, mode:String, ?buffering:Int = -1, ?encoding:String = null, ?errors : String, ?newline:String, ?closefd:Bool, ?opener:String->Int->FileDescriptor):IOBase;
+
+	//public static function divmod():Void;
+	//public static function input():Void;
+
+	//public static function staticmethod():Void;
+	//public static function enumerate():Void;
+	@:overload(function (x:Dynamic, base:Int):Int {})
+	public static function int(x:Dynamic):Int;
+	//public static function ord():Void;
+	public static inline function str(o:Dynamic):String {
+		return python.Syntax.field(Builtin, "str")(o);
+	}
+	//public static function eval():Void;
+
+	//public static function pow():Void;
+	//public static function sum():Void;
+	//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 super():Void;
+	//public static function bin():Void;
+	//public static function file():Void;
+	public static function iter<X>(d:DictView<X>):NativeIterator<X>;
+	//public static function property():Void;
+
+
+
+	@:overload(function <X>():Tuple<X> {})
+	public static function tuple<X>(a:Array<X>):Tuple<X>;
+
+
+
+
+	//public static function range():Void;
+
+	public static function type():Void;
+	@:overload(function (it:Array<Int>):python.lib.ByteArray {})
+	@:overload(function (it:NativeIterable<Int>):python.lib.ByteArray {})
+	@:overload(function (size:Int):python.lib.ByteArray {})
+	public static function bytearray(source:String,encoding:String,?errors:Dynamic):python.lib.ByteArray;
+	public static function float(x:Dynamic):Float;
+
+	@:overload(function <T>(f:Array<T>):Array<T> {})
+	@:overload(function (f:String):Array<String> {})
+	@:overload(function <G>(f:Tuple<G>):Array<G> {})
+	public static function list<T>(i:NativeIterable<T>):Array<T>;
+
+	@:overload(function <A>(f:A->Bool, i:NativeIterable<A>):NativeIterator<A> {})
+	public static function filter<A>(f:A->Bool, i:Array<A>):NativeIterator<A>;
+	//public static function raw_input():Void;
+	//public static function unichr():Void;
+
+	//public static function format():Void;
+	//public static function locals():Void;
+	//public static function reduce():Void;
+	//public static function unicode():Void;
+	public static function chr(c:Int):String;
+	//public static function frozenset():Void;
+	//public static function long():Void;
+	//public static function reload():Void;
+	//public static function vars():Void;
+	//public static function classmethod():Void;
+
+	public static function map<A,B>(fn:A->B, it:NativeIterable<A>):NativeIterator<B>;
+	//public static function repr():Void;
+	//public static function xrange():Void;
+	//public static function cmp():Void;
+	//public static function globals():Void;
+	@:overload(function (a1:Float, a2:Float, ?a3:Float, ?a4:Float, ?a5:Float, ?a6:Float, ?a7:Float, ?a8:Float, ?a9:Float):Float {})
+	public static function max(a1:Int, a2:Int, ?a3:Int, ?a4:Int, ?a5:Int, ?a6:Int, ?a7:Int, ?a8:Int, ?a9:Int):Int;
+	//public static function reversed():Void;
+	//public static function zip():Void;
+	//public static function compile():Void;
+
+	//public static function memoryview():Void;
+	public static function round(f:Float):Int;
+	//public static function __import__():Void;
+	//public static function complex():Void;
+	//public static function hash():Void;
+	@:overload(function (a1:Float, a2:Float, ?a3:Float, ?a4:Float, ?a5:Float, ?a6:Float, ?a7:Float, ?a8:Float, ?a9:Float):Float {})
+	public static function min(a1:Int, a2:Int, ?a3:Int, ?a4:Int, ?a5:Int, ?a6:Int, ?a7:Int, ?a8:Int, ?a9:Int):Int;
+	//public static function set():Void;
+	//public static function apply():Void;
+	public static function delattr(o:Dynamic, attr:String):Void;
+	//public static function help():Void;
+	//public static function next():Void;
+	public static function setattr(o:Dynamic, attr:String, val:Dynamic):Void;
+	//public static function buffer():Void;
+	//public static function dict():Void;
+	//public static function hex():Void;
+	//public static function object():Void;
+	//public static function slice():Void;
+	//public static function coerce():Void;
+	//public static function dir():Void;
+	public static function id(x:{}):Int;
+	//public static function oct():Void;
+	//public static function sorted():Void;
+	//public static function intern():Void;
+
+
+}

+ 23 - 0
std/python/lib/ByteArray.hx

@@ -0,0 +1,23 @@
+package python.lib;
+
+import python.lib.Builtin;
+import python.Syntax;
+
+extern class ByteArray implements ArrayAccess<Int> {
+	public var length(get, null):Int;
+	public inline function get_length ():Int {
+		return Builtin.len(this);
+	}
+
+	public inline function get(i:Int):Int {
+		return Syntax.arrayAccess(this, i);
+	}
+
+	public inline function set(i:Int,v:Int):Void {
+        this.__setitem__(i,v);
+    }
+
+    public function __setitem__(i:Int,v:Int):Void;
+
+	public function decode(encoding:String="utf-8", errors:String="strict"):String;
+}

+ 16 - 0
std/python/lib/Bytes.hx

@@ -0,0 +1,16 @@
+
+package python.lib;
+
+import python.lib.ByteArray;
+
+extern class Bytes extends ByteArray {
+
+	//public function decode(encoding:String="utf-8", errors:String="strict"):String;
+
+	static function __init__ ():Void
+	{
+		Syntax.importFromAs("builtins", "bytes", "python.lib.Bytes");
+	}
+
+
+}

+ 53 - 0
std/python/lib/Codecs.hx

@@ -0,0 +1,53 @@
+
+package python.lib;
+
+import python.lib.io.IOBase;
+import python.lib.io.RawIOBase;
+import python.lib.io.TextIOBase;
+import python.lib.Bytes;
+import python.lib.FileObject;
+import python.lib.Tuple.Tup2;
+
+extern interface Codec {
+	public function encode(input:Dynamic, ?errors:String = "strict"):Tup2<String, Int>;
+	public function decode(input:Dynamic, ?errors:String = "strict"):Tup2<Bytes, Int>;
+}
+
+extern interface StreamReader extends Codec {
+	public function read(?size:Int, ?chars:Int, ?firstline:Bool):String;
+	public function readline(?size:Int, ?keepsend:Bool = false):String;
+	public function readlines(?sizehint:Int, ?keepsend:Bool = false):Array<String>;
+	public function reset():Void;
+
+}
+
+extern interface StreamWriter extends Codec {
+	public function write(object:Dynamic):Void;
+	public function writelines(list:Array<String>):Void;
+	public function reset():Void;
+}
+
+extern class StreamReaderWriterText implements StreamReader implements StreamWriter  {
+	public function read(?size:Int, ?chars:Int, ?firstline:Bool):String;
+	public function readline(?size:Int, ?keepsend:Bool = false):String;
+	public function readlines(?sizehint:Int, ?keepsend:Bool = false):Array<String>;
+	public function reset():Void;
+
+	public function write(object:Dynamic):Void;
+	public function writelines(list:Array<String>):Void;
+
+	public function close():Void;
+
+	public function encode(input:Dynamic, ?errors:String = "strict"):Tup2<String, Int>;
+	public function decode(input:Dynamic, ?errors:String = "strict"):Tup2<Bytes, Int>;
+}
+
+
+extern class Codecs {
+
+	public static function open(filename:String, mode:String, ?encoding:String, ?errors:String, ?buffering:Bool):StreamReaderWriterText;
+
+	static function __init__ ():Void {
+		Syntax.importAs("codecs", "python.lib.Codecs");
+	}
+}

+ 93 - 0
std/python/lib/Dict.hx

@@ -0,0 +1,93 @@
+
+package python.lib;
+
+import python.lib.Builtin;
+import python.lib.Tuple;
+import python.NativeIterator;
+import python.Syntax;
+
+
+extern class DictView<T> {
+	public inline function iter ():NativeIterator<T>
+	{
+		return Builtin.iter(this);
+	}
+	public inline function length ():Int
+	{
+		return Builtin.len(this);
+	}
+
+	public inline function iterator ():Iterator<T>
+	{
+		return iter();
+	}
+}
+
+extern class Dict <K, V>
+{
+	public function new ():Void;
+
+	public inline function length ():Int
+	{
+		return python.lib.Builtin.len(this);
+	}
+
+	public inline function hasKey (k:K):Bool {
+		return DictImpl.hasKey(this,k);
+	}
+
+	public function clear ():Void;
+	public function copy ():Dict<K,V>;
+	public function get (key:K, def:V):V;
+
+	public function update (d:Dict<K,V>):Void;
+
+	public function keys ():DictView<K>;
+	public function values ():DictView<V>;
+	public function items ():DictView<Tup2<K,V>>;
+
+	public static inline function fromObject (x:{}):Dict<String,Dynamic> {
+		return DictImpl.fromObject(x);
+	}
+	public inline function set (key:K, val:V):Void {
+		DictImpl.set(this, key, val);
+	}
+
+	public inline function remove (key:K):Void
+	{
+		DictImpl.remove(this, key);
+	}
+
+	public inline function iterator ():Iterator<V>
+	{
+		return values().iter();
+	}
+	public function __iter__():NativeIterator<K>;
+
+	static function __init__ ():Void
+	{
+		Syntax.importFromAs("builtins", "dict", "python.lib.Dict");
+	}
+
+}
+
+class DictImpl {
+	public static inline function fromObject (x:{}) {
+		var d = new Dict();
+		for (f in Reflect.fields(x)) {
+			d.set(f, Reflect.field(x,f));
+		}
+		return d;
+	}
+	public static inline function hasKey <X>(d:Dict<X, Dynamic>, key:X) {
+		return Syntax.isIn(key, d);
+	}
+
+	public static inline function remove <X>(d:Dict<X, Dynamic>, key:X) {
+		Syntax.delete(python.Syntax.arrayAccess(d, key));
+	}
+
+	public static inline function set <K,V>(d:Dict<K, V>, key:K, val:V) {
+		Syntax.arraySet(d, key, val);
+	}
+}

+ 355 - 0
std/python/lib/Exceptions.hx

@@ -0,0 +1,355 @@
+
+package python.lib;
+
+
+@:native("BaseException")
+extern class BaseException
+{
+	public function new (msg:String):Void;
+}
+
+
+
+@:native("BufferError")
+extern class BufferError extends BaseException
+{
+
+}
+
+@:native("GeneratorExit")
+extern class GeneratorExit extends BaseException
+{
+
+}
+
+@:native("KeyboardInterrupt")
+extern class KeyboardInterrupt extends BaseException
+{
+
+}
+
+@:native("Exception")
+extern class Exception extends BaseException
+{
+
+}
+
+@:native("SyntaxError")
+extern class SyntaxError extends Exception
+{
+
+}
+
+@:native("StopIteration")
+extern class StopIteration extends Exception
+{
+	public function new (?message:String);
+}
+
+@:native("RuntimeError")
+extern class RuntimeError extends Exception
+{
+
+}
+
+@:native("NotImplementedError")
+extern class NotImplementedError extends RuntimeError
+{
+
+}
+
+@:native("IndentationError")
+extern class IndentationError extends SyntaxError
+{
+
+}
+
+@:native("EnvironmentError")
+extern class EnvironmentError extends Exception
+{
+
+}
+
+@:native("OSError")
+extern class OSError extends EnvironmentError
+{
+
+}
+
+@:native("BlockingIOError")
+extern class BlockingIOError extends OSError
+{
+
+}
+
+@:native("ChildProcessError")
+extern class ChildProcessError extends OSError
+{
+
+}
+
+@:native("ConnectionError")
+extern class ConnectionError extends OSError
+{
+
+}
+
+@:native("BrokenPipeError")
+extern class BrokenPipeError extends ConnectionError
+{
+
+}
+
+@:native("ConnectionAbortedError")
+extern class ConnectionAbortedError extends ConnectionError
+{
+
+}
+@:native("ConnectionRefusedError")
+extern class ConnectionRefusedError extends ConnectionError
+{
+
+}
+@:native("ConnectionResetError")
+extern class ConnectionResetError extends ConnectionError
+{
+
+}
+
+@:native("FileExistsError")
+extern class FileExistsError extends OSError
+{
+
+}
+@:native("FileNotFoundError")
+extern class FileNotFoundError extends OSError
+{
+
+}
+@:native("InterruptedError")
+extern class InterruptedError extends OSError
+{
+
+}
+@:native("IsADirectoryError")
+extern class IsADirectoryError extends OSError
+{
+
+}
+@:native("NotADirectoryError")
+extern class NotADirectoryError extends OSError
+{
+
+}
+@:native("PermissionError")
+extern class PermissionError extends OSError
+{
+
+}
+@:native("ProcessLookupError")
+extern class ProcessLookupError extends OSError
+{
+
+}
+@:native("TimeoutError")
+extern class TimeoutError extends OSError
+{
+
+}
+
+
+@:native("NameError")
+extern class NameError extends Exception
+{
+
+}
+
+@:native("UnboundLocalError")
+extern class UnboundLocalError extends NameError
+{
+
+}
+
+@:native("MemoryError")
+extern class MemoryError extends Exception
+{
+
+}
+
+@:native("AssertionError")
+extern class AssertionError extends Exception
+{
+
+}
+
+@:native("AttributeError")
+extern class AttributeError extends Exception
+{
+
+}
+
+@:native("EOFError")
+extern class EOFError extends Exception
+{
+
+}
+
+@:native("ArithmeticError")
+extern class ArithmeticError extends Exception
+{
+
+}
+
+
+
+@:native("FloatingPointError")
+extern class FloatingPointError extends ArithmeticError
+{
+
+}
+
+@:native("OverflowError")
+extern class OverflowError extends ArithmeticError
+{
+
+}
+
+
+@:native("ZeroDivisionError")
+extern class ZeroDivisionError extends ArithmeticError
+{
+
+}
+
+
+
+@:native("ImportError")
+extern class ImportError extends Exception
+{
+
+}
+
+@:native("LookupError")
+extern class LookupError extends Exception
+{
+
+}
+
+@:native("IndexError")
+extern class IndexError extends LookupError
+{
+
+}
+
+@:native("KeyError")
+extern class KeyError extends LookupError
+{
+
+}
+
+@:native("IOError")
+extern class IOError extends EnvironmentError
+{
+
+}
+
+@:native("VMSError")
+extern class VMSError extends OSError
+{
+
+}
+
+@:native("WindowsError")
+extern class WindowsError extends OSError
+{
+
+}
+
+
+
+
+
+
+@:native("ValueError")
+extern class ValueError extends Exception
+{
+
+}
+
+@:native("UnicodeError")
+extern class UnicodeError extends ValueError
+{
+
+}
+@:native("UnicodeDecodeError")
+extern class UnicodeDecodeError extends UnicodeError
+{
+
+}
+@:native("UnicodeEncodeError")
+extern class UnicodeEncodeError extends UnicodeError
+{
+
+}
+@:native("UnicodeTranslateError")
+extern class UnicodeTranslateError extends UnicodeError
+{
+
+}
+
+@:native("Warning")
+extern class Warning extends Exception
+{
+
+}
+
+@:native("DeprecationWarning")
+extern class DeprecationWarning extends Warning
+{
+
+}
+@:native("PendingDeprecationWarning")
+extern class PendingDeprecationWarning extends Warning
+{
+
+}
+@:native("RuntimeWarning")
+extern class RuntimeWarning extends Warning
+{
+
+}
+@:native("SyntaxWarning")
+extern class SyntaxWarning extends Warning
+{
+
+}
+@:native("UserWarning")
+extern class UserWarning extends Warning
+{
+
+}
+@:native("FutureWarning")
+extern class FutureWarning extends Warning
+{
+
+}
+@:native("ImportWarning")
+extern class ImportWarning extends Warning
+{
+
+}
+@:native("UnicodeWarning")
+extern class UnicodeWarning extends Warning
+{
+
+}
+@:native("BytesWarning")
+extern class BytesWarning extends Warning
+{
+
+}
+@:native("ResourceWarning")
+extern class ResourceWarning extends Warning
+{
+
+}

+ 6 - 0
std/python/lib/FileDescriptor.hx

@@ -0,0 +1,6 @@
+
+package python.lib;
+
+extern class FileDescriptor {
+
+}

+ 6 - 0
std/python/lib/FileObject.hx

@@ -0,0 +1,6 @@
+
+package python.lib;
+
+import python.lib.io.IOBase;
+
+typedef FileObject = IOBase;

+ 10 - 0
std/python/lib/FuncTools.hx

@@ -0,0 +1,10 @@
+
+package python.lib;
+
+
+@:native("_hx_functools")
+extern class FuncTools {
+
+	public static function cmp_to_key<A>(f:A->A->Int):Dynamic;
+
+}

+ 19 - 0
std/python/lib/Glob.hx

@@ -0,0 +1,19 @@
+
+package python.lib;
+
+
+import python.NativeIterator;
+
+extern class Glob {
+
+	public static function glob (pathname:String):Array<String>;
+	public static function iglob (pathname:String):NativeIterator<String>;
+
+
+
+	static function __init__ ():Void
+	{
+		Syntax.importAs("glob", "python.lib.Glob");
+	}
+
+}

+ 20 - 0
std/python/lib/Inspect.hx

@@ -0,0 +1,20 @@
+
+package python.lib;
+
+import python.Syntax;
+
+extern class Inspect {
+
+	static function __init__ ():Void
+	{
+		python.Syntax.importAs("inspect", "python.lib.Inspect");
+	}
+
+	static function getmembers (value:Dynamic, ?filter:Dynamic->Bool):Bool;
+	static function ismethod (value:Dynamic):Bool;
+	static function isclass (value:Dynamic):Bool;
+
+	static function isfunction(value:Dynamic):Bool;
+
+
+}

+ 26 - 0
std/python/lib/Json.hx

@@ -0,0 +1,26 @@
+
+package python.lib;
+
+import python.KwArgs;
+import python.lib.Dict;
+import python.lib.Tuple.Tup2;
+
+extern class Json {
+
+
+	public static function loads (
+		s:String,
+		encoding:Null<String> = null,
+		cls : Null<Dynamic> = null,
+		object_hook:Null<Dict<String, Dynamic>->Dynamic> = null
+		):Dict<String, Dynamic>;
+	public static function dumps (x:Dynamic, skipkeys:Bool=false, ensure_ascii:Bool=true, check_circular:Bool=true,
+		allow_nan:Bool=true,
+		cls:Null<Dynamic> = null, indent:Null<String> = null,
+		separators:Null<Tup2<String,String>>, /*default*/def:Null<Dynamic->String> = null, sort_keys:Bool=false, kw:KwArgs = null):String;
+
+	static function __init__ ():Void
+	{
+		python.Syntax.importAs("json", "python.lib.Json");
+	}
+}

+ 24 - 0
std/python/lib/Math.hx

@@ -0,0 +1,24 @@
+package python.lib;
+
+extern class Math {
+
+	public static function isnan (f:Float):Bool;
+
+	public static var pi:Float;
+
+	public static function sqrt(f:Float):Float;
+	public static function log(f:Float):Float;
+	public static function cos(f:Float):Float;
+	public static function sin(f:Float):Float;
+	public static function tan(f:Float):Float;
+	static function asin(v:Float):Float;
+	static function acos(v:Float):Float;
+	static function atan(v:Float):Float;
+	static function atan2(y:Float, x:Float):Float;
+
+	static function __init__():Void {
+		python.Syntax.importAs("math", "python.lib.Math");
+
+	}
+
+}

+ 15 - 0
std/python/lib/Msvcrt.hx

@@ -0,0 +1,15 @@
+
+package python.lib;
+
+extern class Msvcrt {
+
+	public static function getch ():python.lib.Bytes;
+
+	static function __init__ ():Void
+	{
+		try {
+			python.Syntax.importAs("msvcrt", "python.lib.Msvcrt");
+		} catch (e:Dynamic) {}
+	}
+
+}

+ 77 - 0
std/python/lib/Os.hx

@@ -0,0 +1,77 @@
+
+package python.lib;
+
+
+import python.lib.Exceptions.OSError;
+import python.lib.Tuple;
+
+extern class Stat {
+	public var st_mode:Int;
+	public var st_ino:Int;
+	public var st_dev:Int;
+	public var st_nlink:Int;
+	public var st_uid:Int;
+	public var st_gid:Int;
+	public var st_size:Int;
+	public var st_atime:Int;
+	public var st_mtime:Int;
+	public var st_ctime:Int;
+
+	@:optional public var st_blocks:Int;
+	@:optional public var st_blksize:Int;
+	@:optional public var st_rdev:Int;
+	@:optional public var st_flags:Int;
+
+	@:optional public var st_gen:Int;
+	@:optional public var st_birthtime:Int;
+
+	@:optional public var st_rsize:Int;
+	@:optional public var st_creator:Int;
+	@:optional public var st_type:Int;
+}
+
+extern class Os {
+
+	public static var environ : Dict<String, String>;
+
+	public static function putenv (name:String, value:String):Void;
+
+	public static function chdir (path:String):Void;
+
+	public static function unlink (path:String):Void;
+	public static function remove (path:String):Void;
+
+	public static function getcwd():String;
+
+	public static function getcwdb():Bytes;
+
+	public static function removedirs (path:String):Void;
+
+	public static function rename (src:String, dest:String):Void;
+
+	public static function renames (oldName:String, newName:String):Void;
+
+	public static function rmdir (path:String):Void;
+
+
+	public static function stat (path:String):Stat;
+
+	public static function fchdir (fd:FileDescriptor):Void;
+
+	public static function listdir (path:String = "."):Array<String>;
+
+	public static function walk (top:String, topdown:Bool = true, onerror:OSError->Void = null, followlinks:Bool = false):Tup3<String, Array<String>, Array<String>>;
+
+	public static var sep(default, null) : String;
+	public static var pathsep(default, null):String;
+
+	public static function makedirs (path:String, mode : Int = 511 /* Oktal 777 */, exist_ok:Bool = false):Void;
+
+	public static function mkdir (path:String, mode : Int = 511 /* Oktal 777 */):Void;
+
+	static function __init__ ():Void
+	{
+		python.Syntax.importAs("os", "python.lib.Os");
+	}
+
+}

+ 15 - 0
std/python/lib/PPrint.hx

@@ -0,0 +1,15 @@
+
+package python.lib;
+
+extern class PPrint {
+
+
+	public static function pprint (x:Dynamic):Void;
+
+	public static function pformat(object:Dynamic, indent:Int=1, width:Int=80, depth:Int=null):String;
+
+	static function __init__ ():Void {
+		python.Syntax.importAs("pprint", "python.lib.PPrint");
+	}
+
+}

+ 14 - 0
std/python/lib/Random.hx

@@ -0,0 +1,14 @@
+
+package python.lib;
+
+
+
+extern class Random {
+
+	public static function random ():Float;
+
+	static function __init__ ():Void {
+		Syntax.importAs("random", "python.lib.Random");
+	}
+
+}

+ 189 - 0
std/python/lib/Re.hx

@@ -0,0 +1,189 @@
+
+package python.lib;
+
+import python.lib.Tuple;
+
+
+private abstract Choice <A,B>(Dynamic) {
+	@:from public static inline function fromA <A,B>(x:A):Choice<A,B> return cast x;
+	@:from public static inline function fromB <A,B>(x:B):Choice<A,B> return cast x;
+}
+
+typedef TODO = Dynamic;
+
+typedef Pattern = Choice<String, Regex>;
+
+typedef Repl = Choice<String, MatchObject->String>;
+
+
+
+
+extern class MatchObject
+{
+
+	public var pos(default, null):Int;
+	public var endpos(default, null):Int;
+	public var lastindex(default, null):Int;
+	public var lastgroup(default, null):Int;
+	public var re(default, null):Regex;
+	public var string(default, null):String;
+
+	public function expand(template:String):String;
+
+	@:overload(function (x:String):String {})
+	public function group(?i:Int = 0):String;
+
+	public function groups(defaultVal:String = null):Tuple<String>;
+	public function groupdict(defaultVal:Dict<String, String> = null):Dict<String, String>;
+
+	@:overload(function (x:String):Int {})
+	public function start (?i:Int = 0):Int;
+
+	@:overload(function (x:String):Int {})
+	public function end (?i:Int = 0):Int;
+
+	public function span (?i:Int):Tup2<Int, Int>;
+
+
+	public inline function groupById(s:String):String {
+		return group(s);
+	}
+
+	public inline function startById(s:String):Int {
+		return start(s);
+	}
+
+	public inline function endById(s:String):Int {
+		return end(s);
+	}
+
+}
+
+private class RegexHelper {
+	public static function findallDynamic(r:Regex, string:String, ?pos:Int, ?endpos:Int):Array<Dynamic>
+	{
+		if (endpos == null) {
+			if (pos == null) {
+				return python.Syntax.field(r, "findall")(string);
+			} else {
+				return python.Syntax.field(r, "findall")(string, pos);
+			}
+		} else {
+			return python.Syntax.field(r, "findall")(string, pos, endpos);
+		}
+
+	}
+}
+
+extern class Regex
+{
+	public function search(string:String, pos:Int = 0, ?endpos:Int):Null<MatchObject>;
+	public function match(string:String, pos:Int = 0, ?endpos:Int):Null<MatchObject>;
+
+	public function split(string:String, maxsplit:Int=0):Array<String>;
+
+	public inline function findallString(string:String, ?pos:Int, ?endpos:Int):Array<String>
+	{
+		return cast this.findallDynamic(string, pos, endpos);
+	}
+
+
+	public inline function findallDynamic(string:String, ?pos:Int, ?endpos:Int):Array<Dynamic>
+	{
+		return RegexHelper.findallDynamic(this, string, pos, endpos);
+	}
+
+	public inline function findallTuple(string:String, ?pos:Int, ?endpos:Int):Array<Tuple<String>> {
+
+		return cast this.findallDynamic(string, pos, endpos);
+	}
+
+	public inline function findallArray(string:String, ?pos:Int, ?endpos:Int):Array<Array<String>>
+	{
+		return findallTuple(string, pos, endpos).map(function (t) return t.toArray());
+	}
+
+	public function finditer(string:String, ?pos:Int, ?endpos:Int):NativeIterator<MatchObject>;
+
+	public function sub(repl:Repl, string:String, count:Int=0):String;
+	public function subn(repl:Repl, string:String, count:Int=0):String;
+
+	public var flags(default, null):Int;
+	public var groups(default, null):Int;
+	public var groupindex(default, null):Dict<String, Int>;
+	public var pattern(default, null):String;
+}
+
+
+
+extern class Re
+{
+
+	public static var A:Int;
+	public static var ASCII:Int;
+	public static var DEBUG:Int;
+	public static var I:Int;
+	public static var IGNORECASE:Int;
+
+	public static var L:Int;
+	public static var LOCALE:Int;
+
+	public static var M:Int;
+	public static var MULTILINE:Int;
+
+	public static var S:Int;
+	public static var DOTALL:Int;
+
+	public static var X:Int;
+	public static var VERBOSE:Int;
+
+	public static var U:Int;
+	public static var UNICODE:Int;
+
+
+
+	public static function compile (pattern:String, ?flags:Int = 0):Regex;
+
+	public static function match (pattern:Pattern, string:String, flags:Int = 0):Null<MatchObject>;
+
+	public static function search (pattern:Pattern, string:String, flags:Int = 0):Null<MatchObject>;
+
+	public static function split(pattern:Pattern, string:String, maxsplit:Int=0, flags:Int=0):Array<String>;
+
+	public static inline function findallDynamic(pattern:Pattern, string:String, flags:Int=0):Array<Dynamic>
+	{
+		return python.Syntax.field(pattern, "findall")(string, flags);
+	}
+
+
+	public static inline function findallString(pattern:Pattern, string:String,	flags:Int=0):Array<String>
+	{
+		return python.Syntax.field(pattern, "findall")(string, flags);
+	}
+
+	public static inline function findallTuple(pattern:Pattern, string:String, flags:Int=0):Array<Tuple<String>>
+	{
+		return python.Syntax.field(pattern, "findall")(string, flags);
+	}
+
+	public static inline function findallArray(pattern:Pattern, string:String, flags:Int=0):Array<Array<String>>
+	{
+		return findallTuple(pattern, string,flags).map(function (t) return t.toArray());
+	}
+
+	public static function finditer(pattern:Pattern, string:String,   flags:Int=0):NativeIterator<MatchObject>;
+
+
+	@:overload(function (pattern:Pattern, repl:String, string:String,  ?count:Int=0, ?flags:Int=0):String {})
+	public static function sub(pattern:Pattern, repl:MatchObject->String, string:String,  ?count:Int=0, ?flags:Int=0):String;
+
+	public static function subn(pattern:Pattern, repl:Repl, string:String, count:Int=0, flags:Int=0):String;
+
+	public static function escape(string:String):TODO;
+
+	public static function purge():Void;
+
+	static function __init__ ():Void {
+		python.Syntax.importAs("re", "python.lib.Re");
+	}
+}

+ 43 - 0
std/python/lib/Set.hx

@@ -0,0 +1,43 @@
+
+package python.lib;
+
+import python.NativeIterator;
+import python.NativeIterable;
+
+extern class Set <T>
+{
+	@:overload(function (?array:Array<T>):Void {})
+	public function new (?iterable:NativeIterable<T>):Void;
+
+	public inline function length ():Int
+	{
+		return python.lib.Builtin.len(this);
+	}
+
+	public inline function has (v:T):Bool
+	{
+		return python.Syntax.isIn(v, this);
+	}
+
+
+	public inline function minus (other:Set<T>):Set<T>
+	{
+		return python.Syntax.binop(this, "-", other);
+	}
+	public inline function plus (other:Set<T>):Set<T>
+	{
+		return python.Syntax.binop(this, "+", other);
+	}
+
+	static function __init__ ():Void
+	{
+		Syntax.importFromAs("builtins", "set", "python.lib.Set");
+	}
+
+	function __iter__ ():NativeIterator<T>;
+
+	public inline function iterator ():NativeIterator<T>
+	{
+		return __iter__();
+	}
+}

Some files were not shown because too many files changed in this diff