Browse Source

Merge branch 'development' into dev_js_improvements

Conflicts:
	genjs.ml
	libs
Luca Deltodesco 12 years ago
parent
commit
bd1a344696

+ 2 - 0
.gitignore

@@ -8,6 +8,7 @@
 .*.swp
 
 
+/version.ml
 /haxe
 /haxelib*
 /haxedoc*
@@ -47,3 +48,4 @@
 /haxe.sublime*
 build.bat
 tests/unit/compile.php.hxml
+/doc/*.xml

+ 16 - 0
.travis.yml

@@ -0,0 +1,16 @@
+language: node_js
+
+before_install:
+  - sudo apt-get install python-software-properties -y # for the next command
+  - sudo add-apt-repository ppa:eyecreate/haxe -y      # add the ubuntu ppa that contains neko
+  - sudo apt-get update                                # pull info from ppa
+  - sudo apt-get install neko -y
+  - sudo apt-get install ocaml zlib1g-dev -y
+
+script:
+  - make
+  - make tools
+  - sudo make install
+  - cd tests/unit/
+  - mkdir ~/haxelib && haxelib setup ~/haxelib
+  - haxe -version

+ 24 - 11
Makefile

@@ -15,6 +15,7 @@ INSTALL_DIR=/usr
 OUTPUT=haxe
 EXTENSION=
 OCAMLOPT=ocamlopt
+OCAMLC=ocamlc
 
 CFLAGS= -g -I libs/extlib -I libs/extc -I libs/neko -I libs/javalib -I libs/ziplib -I libs/swflib -I libs/xml-light -I libs/ttflib
 
@@ -32,21 +33,33 @@ EXPORT=../../../projects/motionTools/haxe
 
 MODULES=ast type lexer common genxml parser typecore optimizer typeload \
 codegen gencommon genas3 gencpp genjs genneko genphp genswf8 \
-	genswf9 genswf genjava gencs interp typer matcher dce main
+	genswf9 genswf genjava gencs interp typer matcher dce version main
+
+ADD_REVISION=0
 
 export HAXE_STD_PATH=$(CURDIR)/std
 
+ifneq ($(ADD_REVISION),0)
+	VERSION_EXTRA="let version_extra = Some \" (git build $(shell git rev-parse --abbrev-ref HEAD) @ $(shell git describe --always)) \""
+else
+	VERSION_EXTRA="let version_extra = None"
+endif
+
 all: libs haxe
 
+version.cmx:
+	echo $(VERSION_EXTRA) > version.ml
+	$(OCAMLOPT) $(CFLAGS) -c version.ml
+
 libs:
-	make -C libs/extlib opt
-	make -C libs/extc native
-	make -C libs/neko
-	make -C libs/javalib
-	make -C libs/ziplib
-	make -C libs/swflib
-	make -C libs/xml-light xml-light.cmxa
-	make -C libs/ttflib
+	make -C libs/extlib opt OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
+	make -C libs/extc native OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
+	make -C libs/neko OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
+	make -C libs/javalib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
+	make -C libs/ziplib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
+	make -C libs/swflib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
+	make -C libs/xml-light xml-light.cmxa OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
+	make -C libs/ttflib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
 
 haxe: $(MODULES:=.cmx)
 	$(OCAMLOPT) -o $(OUTPUT) $(NATIVE_LIBS) $(LIBS) $(MODULES:=.cmx)
@@ -120,7 +133,7 @@ interp.cmx: typecore.cmx type.cmx lexer.cmx genneko.cmx common.cmx codegen.cmx a
 
 matcher.cmx: optimizer.cmx codegen.cmx typecore.cmx type.cmx typer.cmx common.cmx ast.cmx
 
-main.cmx: dce.cmx matcher.cmx typer.cmx typeload.cmx typecore.cmx type.cmx parser.cmx optimizer.cmx lexer.cmx interp.cmx genxml.cmx genswf.cmx genphp.cmx genneko.cmx genjs.cmx gencpp.cmx genas3.cmx common.cmx codegen.cmx ast.cmx gencommon.cmx genjava.cmx gencs.cmx
+main.cmx: dce.cmx matcher.cmx typer.cmx typeload.cmx typecore.cmx type.cmx parser.cmx optimizer.cmx lexer.cmx interp.cmx genxml.cmx genswf.cmx genphp.cmx genneko.cmx genjs.cmx gencpp.cmx genas3.cmx common.cmx codegen.cmx ast.cmx gencommon.cmx genjava.cmx gencs.cmx version.cmx
 
 optimizer.cmx: typecore.cmx type.cmx parser.cmx common.cmx ast.cmx
 
@@ -168,4 +181,4 @@ clean_tools:
 .mll.ml:
 	ocamllex $<
 
-.PHONY: haxe libs
+.PHONY: haxe libs version.cmx

+ 7 - 1
Makefile.win

@@ -5,6 +5,12 @@ EXTENSION=.exe
 
 OCAMLOPT=ocamlopt.opt
 
+ifneq ($(ADD_REVISION),0)
+	VERSION_EXTRA=let version_extra = Some " (git build $(shell git rev-parse --abbrev-ref HEAD) @ $(shell git describe --always)) "
+else
+	VERSION_EXTRA=let version_extra = None
+endif
+
 kill:
 	-@taskkill /F /IM haxe.exe 2>/dev/null
 
@@ -28,4 +34,4 @@ endif
 ifdef FILTER
 CC_CMD=($(OCAMLOPT) $(CFLAGS) -c $< 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1)
 CC_PARSER_CMD=($(OCAMLOPT) -pp camlp4o $(CFLAGS) -c parser.ml 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1)
-endif
+endif

+ 1 - 1
codegen.ml

@@ -735,7 +735,7 @@ let add_field_inits ctx t =
 				(cf2 :: inits, fields)
 			| _ -> (inits, cf :: fields)
 		) ([],[]) c.cl_ordered_fields in
-		c.cl_ordered_fields <- fields;
+		c.cl_ordered_fields <- (List.rev fields);
 		match inits with
 		| [] -> ()
 		| _ ->

+ 28 - 0
common.ml

@@ -881,3 +881,31 @@ let rec close_times() =
 
 ;;
 Ast.Meta.to_string_ref := fun m -> fst (MetaInfo.to_string m)
+
+(*  Taken from OCaml source typing/oprint.ml
+
+    This is a better version of string_of_float which prints without loss of precision
+    so that float_of_string (float_repres x) = x for all floats x
+*)
+let valid_float_lexeme s =
+	let l = String.length s in
+	let rec loop i =
+		if i >= l then s ^ "." else
+		match s.[i] with
+		| '0' .. '9' | '-' -> loop (i+1)
+		| _ -> s
+	in loop 0
+
+let float_repres f =
+	match classify_float f with
+	| FP_nan -> "nan"
+	| FP_infinite ->
+		if f < 0.0 then "neg_infinity" else "infinity"
+	| _ ->
+		let float_val =
+			let s1 = Printf.sprintf "%.12g" f in
+			if f = float_of_string s1 then s1 else
+			let s2 = Printf.sprintf "%.15g" f in
+			if f = float_of_string s2 then s2 else
+			Printf.sprintf "%.18g" f
+		in valid_float_lexeme float_val

+ 27 - 29
dce.ml

@@ -129,37 +129,37 @@ end
 
 let rec mark_enum dce e = if not (Meta.has Meta.Used e.e_meta) then begin
 	e.e_meta <- (Meta.Used,[],e.e_pos) :: e.e_meta;
-	PMap.iter (fun _ ef -> mark_t dce ef.ef_type) e.e_constrs;
+	PMap.iter (fun _ ef -> mark_t dce ef.ef_pos ef.ef_type) e.e_constrs;
 end
 
 and mark_abstract dce a = if not (Meta.has Meta.Used a.a_meta) then
 	a.a_meta <- (Meta.Used,[],a.a_pos) :: a.a_meta
 
 (* mark a type as kept *)
-and mark_t dce t =
+and mark_t dce p t =
 	if not (List.exists (fun t2 -> Type.fast_eq t t2) dce.t_stack) then begin
 		dce.t_stack <- t :: dce.t_stack;
 		begin match follow t with
 		| TInst({cl_kind = KTypeParameter tl} as c,pl) ->
 			if not (Meta.has Meta.Used c.cl_meta) then begin
 				c.cl_meta <- (Meta.Used,[],c.cl_pos) :: c.cl_meta;
-				List.iter (mark_t dce) tl;
+				List.iter (mark_t dce p) tl;
 			end;
-			List.iter (mark_t dce) pl
+			List.iter (mark_t dce p) pl
 		| TInst(c,pl) ->
 			mark_class dce c;
-			List.iter (mark_t dce) pl
+			List.iter (mark_t dce p) pl
 		| TFun(args,ret) ->
-			List.iter (fun (_,_,t) -> mark_t dce t) args;
-			mark_t dce ret
+			List.iter (fun (_,_,t) -> mark_t dce p t) args;
+			mark_t dce p ret
 		| TEnum(e,pl) ->
 			mark_enum dce e;
-			List.iter (mark_t dce) pl
+			List.iter (mark_t dce p) pl
 		| TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta ->
-			mark_t dce (snd (Codegen.Abstract.find_multitype_specialization a pl Ast.null_pos))
+			mark_t dce p (snd (Codegen.Abstract.find_multitype_specialization a pl p))
 		| TAbstract(a,pl) ->
 			mark_abstract dce a;
-			List.iter (mark_t dce) pl
+			List.iter (mark_t dce p) pl
 		| TLazy _ | TDynamic _ | TAnon _ | TType _ | TMono _ -> ()
 		end;
 		dce.t_stack <- List.tl dce.t_stack
@@ -249,17 +249,15 @@ and field dce c n stat =
 		let prefix = String.sub n 0 4 in
 		let pn = String.sub n 4 l in
 		let cf = find_field pn in
-		if not (Meta.has Meta.Used cf.cf_meta) then begin
-			let keep () =
-				mark_dependent_fields dce c n stat;
-				field dce c pn stat
-			in
-			(match prefix,cf.cf_kind with
-				| "get_",Var {v_read = AccCall} when "get_" ^ cf.cf_name = n -> keep()
-				| "set_",Var {v_write = AccCall} when "set_" ^ cf.cf_name = n -> keep()
-				| _ -> raise Not_found
-			);
-		end;
+		let keep () =
+			mark_dependent_fields dce c n stat;
+			field dce c pn stat
+		in
+		(match prefix,cf.cf_kind with
+			| "get_",Var {v_read = AccCall} when "get_" ^ cf.cf_name = n -> keep()
+			| "set_",Var {v_write = AccCall} when "set_" ^ cf.cf_name = n -> keep()
+			| _ -> raise Not_found
+		);
 		raise Not_found
 	with Not_found -> try
 		if c.cl_interface then begin
@@ -286,17 +284,17 @@ and field dce c n stat =
 		if dce.debug then prerr_endline ("[DCE] Field " ^ n ^ " not found on " ^ (s_type_path c.cl_path)) else ())
 
 and expr dce e =
-	mark_t dce e.etype;
+	mark_t dce e.epos e.etype;
 	match e.eexpr with
 	| TNew(c,pl,el) ->
 		mark_class dce c;
 		field dce c "new" false;
 		List.iter (expr dce) el;
-		List.iter (mark_t dce) pl;
+		List.iter (mark_t dce e.epos) pl;
 	| TVars vl ->
-		List.iter (fun (v,e) ->
-			opt (expr dce) e;
-			mark_t dce v.v_type;
+		List.iter (fun (v,e1) ->
+			opt (expr dce) e1;
+			mark_t dce e.epos v.v_type;
 		) vl;
 	| TCast(e, Some mt) ->
 		check_feature dce "typed_cast";
@@ -309,7 +307,7 @@ and expr dce e =
 		List.iter (fun (v,e) ->
 			if v.v_type != t_dynamic then check_feature dce "typed_catch";
 			expr dce e;
-			mark_t dce v.v_type;
+			mark_t dce e.epos v.v_type;
 		) vl;
 	| TCall ({eexpr = TLocal ({v_name = "__define_feature__"})},[{eexpr = TConst (TString ft)};e]) ->
 		Common.add_feature dce.com ft;
@@ -323,7 +321,7 @@ and expr dce e =
 		expr dce ef;
 		List.iter (expr dce) args;
 	| TCall ({eexpr = TConst TSuper} as e,el) ->
-		mark_t dce e.etype;
+		mark_t dce e.epos e.etype;
 		List.iter (expr dce) el;
 	| TField(e,fa) ->
 		begin match fa with
@@ -415,7 +413,7 @@ let run com main full =
 			List.iter (fun (c,cf,stat) ->
 				mark_class dce c;
 				mark_field dce c cf stat;
-				mark_t dce cf.cf_type
+				mark_t dce cf.cf_pos cf.cf_type
 			) cfl;
 			(* follow expressions to new types/fields *)
 			List.iter (fun (_,cf,_) ->

+ 6 - 1
doc/CHANGES.txt

@@ -1,4 +1,4 @@
-2013-??-??: 3.0.1
+2013-??-??: 3.1.0
 	all : allowed null-patterns in pattern matching
 	all : optimized pattern matching output
 	all : added length field to BytesBuffer, BytesOutput, BytesInput and StringBuf
@@ -12,9 +12,14 @@
 	all : allow @:fakeEnum on abstracts
 	all : allow Class.new
 	all : inlining a parameter which has side effects will not remove it even if not used
+	js : window and console are reserved words. Access them with __js__ instead of untyped.
 	js : added -D js-flatten
 	macro : allowed $v{(c:Float|Int|String)}
 	macro : resolve error line number in external files
+	flash : fixed font embedding with UTF8 chars
+
+2013-09-25: 3.0.1
+	all : minor DCE bug fix
 
 2013-05-25: 3.0.0
 	all : added haxe.ds.BalancedTree

+ 4 - 0
doc/installer.nsi

@@ -1,4 +1,8 @@
 ; Haxe/Neko Install script
+; Instructions:
+; - put haxe files in resources/haxe
+; - put neko files in resources/neko
+; - run
 
 ;--------------------------------
 

BIN
doc/osx_installer_template.zip


+ 7 - 2
genas3.ml

@@ -834,9 +834,14 @@ and gen_value ctx e =
 		gen_value ctx e1
 	| TCast (e1,None) ->
 		let s = type_str ctx e.etype e1.epos in
-		if s = "*" then
+		begin match s with
+		| "*" ->
 			gen_value ctx e1
-		else begin
+		| "Function" ->
+			spr ctx "((";
+			gen_value ctx e1;
+			print ctx ") as %s)" s;
+		| _ ->
 			print ctx "%s(" s;
 			gen_value ctx e1;
 			spr ctx ")";

+ 186 - 60
gencpp.ml

@@ -584,6 +584,7 @@ let is_internal_member member =
 	| "__Field" | "__IField" | "__Run" | "__Is" | "__GetClass" | "__GetType" | "__ToString"
 	| "__s" | "__GetPtr" | "__SetField" | "__length" | "__IsArray" | "__SetThis" | "__Internal"
 	| "__EnumParams" | "__Index" | "__Tag" | "__GetFields" | "toString" | "__HasField"
+	| "__GetRealObject"
 			-> true
    | _ -> false;;
 
@@ -2705,8 +2706,9 @@ let generate_enum_files common_ctx enum_def super_deps meta file_info =
 					", hx::TCanCast< " ^ class_name ^ " >,sStaticFields,sMemberFields,\n");
 	output_cpp ("	&__Create_" ^ class_name ^ ", &__Create,\n");
 	output_cpp ("	&super::__SGetClass(), &Create" ^ class_name ^ ", sMarkStatics\n");
-	output_cpp("#ifdef HXCPP_VISIT_ALLOCS\n    , sVisitStatic\n#endif\n);\n");
-	output_cpp ("}\n\n");
+	output_cpp("#ifdef HXCPP_VISIT_ALLOCS\n    , sVisitStatic\n#endif\n");
+	output_cpp ("#ifdef HXCPP_SCRIPTABLE\n    , 0\n#endif\n");
+	output_cpp (");\n}\n\n");
 
 	output_cpp ("void " ^ class_name ^ "::__boot()\n{\n");
 	(match meta with
@@ -3144,6 +3146,28 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
 	output_cpp "	String(null()) };\n\n";
 
 
+	let dump_member_storage = (fun field ->
+      let storage = match type_string field.cf_type with
+      | "Bool" -> "hx::fsBool"
+      | "Int" -> "hx::fsInt"
+      | "Float" -> "hx::fsFloat"
+      | "::String" -> "hx::fsString"
+      | _ -> "hx::fsObject"
+      in
+      output_cpp ("	{" ^ storage ^ ",(int)offsetof(" ^ class_name ^"," ^ (keyword_remap field.cf_name) ^")," ^
+         (str field.cf_name) ^ "},\n")
+      )
+    in
+	let stored_fields = List.filter is_data_member implemented_instance_fields in
+	output_cpp "#if HXCPP_SCRIPTABLE\n";
+   if ( (List.length stored_fields) > 0) then begin
+	   output_cpp "static hx::StorageInfo sMemberStorageInfo[] = {\n";
+	   List.iter dump_member_storage stored_fields;
+	   output_cpp "	{ hx::fsUnknown, 0, null()}\n};\n";
+   end else
+	   output_cpp "static hx::StorageInfo *sMemberStorageInfo = 0;\n";
+	output_cpp "#endif\n\n";
+
 	(* Mark static variables as used *)
 	output_cpp "static void sMarkStatics(HX_MARK_PARAMS) {\n";
 	output_cpp ("	HX_MARK_MEMBER_NAME(" ^ class_name ^ "::__mClass,\"__mClass\");\n");
@@ -3164,6 +3188,54 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
 	output_cpp "};\n\n";
 	output_cpp "#endif\n\n";
 
+   let script_type t optional = if optional then "o" else
+   match type_string t with
+   | "bool" -> "Int"
+   | "int" -> "Int"
+   | "Float" -> "Float"
+   | "::String" -> "String"
+   | "Null" -> "Void"
+   | "Void" -> "Void"
+   | _ -> "Object"
+   in
+   let script_signature t optional = match script_type t optional with
+   | "Bool" -> "b"
+   | "Int" -> "i"
+   | "Float" -> "f"
+   | "String" -> "s"
+   | "Void" -> "v"
+   | _ -> "o"
+   in
+   let script_size_type t optional = match script_type t optional with
+   | "Object" -> "void *"
+   | x -> x
+   in
+
+   let generate_script_function isStatic field scriptName callName = 
+		match follow field.cf_type  with
+		| TFun (args,return_type) ->
+         output_cpp ("\nstatic void " ^ scriptName ^ "(hx::CppiaCtx *ctx) {\n");
+         let ret = script_signature return_type false in
+         if (ret<>"v") then output_cpp ("ctx->return" ^ (script_type return_type false) ^ "(");
+         if isStatic then
+            output_cpp (class_name ^ "::" ^ callName ^ "(")
+         else
+            output_cpp ("((" ^  class_name ^ "*)ctx->getThis())->" ^  callName ^ "(");
+
+         let (signature,_,_) = List.fold_left (fun (signature,sep,size) (_,opt,t) ->
+             output_cpp (sep ^ "ctx->get" ^ (script_type t opt) ^ "(" ^ size ^ ")");
+             (signature ^ (script_signature t opt ), ",", (size^"+sizeof(" ^ (script_size_type t opt) ^ ")") ) ) (ret,"","sizeof(void*)")  args
+         in
+
+         output_cpp ")";
+         if (ret<>"v") then output_cpp (")");
+         output_cpp (";\n}\n");
+         signature;
+      | _ -> ""
+   in
+
+
+
    if (scriptable ) then begin
       let dump_script_field idx (field,f_args,return_t) =
         let args = if (class_def.cl_interface) then
@@ -3174,30 +3246,36 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
         let return_type = type_string return_t in
         let ret = if (return_type="Void") then " " else "return " in
         let name = keyword_remap field.cf_name in
-        let vtable =  "__scriptVTable[" ^ (string_of_int idx) ^ "] " in
+        let vtable =  "__scriptVTable[" ^ (string_of_int (idx+1) ) ^ "] " in
         let args_varray = (List.fold_left (fun l n -> l ^ ".Add(" ^ n ^ ")") "Array<Dynamic>()" names)  in
-        let args_comma = List.fold_left (fun l n -> l ^ "," ^ n) "" names in
+        (*let args_comma = List.fold_left (fun l n -> l ^ "," ^ n) "" names in*)
         output_cpp ("   " ^ return_type ^ " " ^ name ^ "( " ^ args ^ " ) { ");
-        if (class_def.cl_interface) then begin
+         if (class_def.cl_interface) then begin
            output_cpp (" " ^ ret ^ "mDelegate->__Field(HX_CSTRING(\"" ^ field.cf_name ^ "\"),false)");
            if (List.length names <= 5) then
               output_cpp ("->__run(" ^ (String.concat "," names) ^ ")")
            else
               output_cpp ("->__Run(" ^ args_varray ^ ")");
-           output_cpp ";return null(); }\n";
+           output_cpp ";return null(); }\n\n";
         end else begin
-           output_cpp (" if (" ^ vtable ^ ") " ^ ret);
-           if (List.length names <= 5) then
-               output_cpp("hx::ScriptableCall" ^ (string_of_int (List.length names)) ^
-                  "("^ vtable ^ ",this" ^ args_comma ^ ");")
-           else
-               output_cpp("hx::ScriptableCallMult("^ vtable ^ ",this," ^ args_varray^ "->Pointer());");
-           output_cpp (" else " ^ ret ^ class_name ^ "::" ^ name ^ "(" ^ (String.concat "," names)^ "); return null(); }\n");
+           output_cpp ("\n\tif (" ^ vtable ^ ") {\n" );
+           output_cpp ("\t\thx::CppiaCtx *__ctx = hx::CppiaCtx::getCurrent();\n" );
+           output_cpp ("\t\thx::AutoStack __as(__ctx);\n" );
+           output_cpp ("\t\t__ctx->pushObject(this);\n" );
+           List.iter (fun (name,opt, t ) ->
+              output_cpp ("\t\t__ctx->push" ^ (script_type t opt) ^ "(" ^ (keyword_remap name) ^ ");\n" );
+           ) f_args;
+           output_cpp ("\t\t" ^ ret ^ "__ctx->run" ^ (script_type return_t false) ^ "(" ^ vtable ^ ");\n" );
+           output_cpp ("\t}  else " ^ ret ^ class_name ^ "::" ^ name ^ "(" ^ (String.concat "," names)^ "); return null(); }\n\n");
         end
       in
+      let not_toString = fun (field,_,_) -> field.cf_name<>"toString" in
+      let functions = List.filter not_toString (all_virtual_functions class_def) in
+      let new_sctipt_functions = List.filter (fun (f,_,_) -> not (is_override class_def f.cf_name) ) functions in
       let sctipt_name = class_name ^ "__scriptable" in
       output_cpp ("class " ^ sctipt_name ^ " : public " ^ class_name ^ " {\n" );
       output_cpp ("   typedef "^sctipt_name ^" __ME;\n");
+      output_cpp ("   typedef "^class_name ^" super;\n");
       if (class_def.cl_interface) then
          output_cpp ("   HX_DEFINE_SCRIPTABLE_INTERFACE\n")
       else begin
@@ -3205,19 +3283,31 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
 	      if (not implement_dynamic) then
 			   output_cpp "	HX_DEFINE_SCRIPTABLE_DYNAMIC;\n";
       end;
-      let functions = all_virtual_functions class_def in
+
 	   list_iteri dump_script_field functions;
       output_cpp ("};\n\n");
 
       if (not class_def.cl_interface) then begin
-         output_cpp "static String __scriptableFunctionNames[] = {\n";
-         List.iter (fun (f,_,_) -> output_cpp ("  HX_CSTRING(\"" ^ f.cf_name ^ "\"),\n" ) ) functions;
-         output_cpp "  String(null()) };\n";
+         if (List.length new_sctipt_functions) > 0 then begin
+            let sigs = Hashtbl.create 0 in
+            List.iter (fun (f,_,_) ->
+               let s = generate_script_function false f ("__s_" ^f.cf_name) (keyword_remap f.cf_name) in
+               Hashtbl.add sigs f.cf_name s
+            ) new_sctipt_functions;
+
+            output_cpp "static hx::ScriptNamedFunction __scriptableFunctions[] = {\n";
+            List.iter (fun (f,_,_) ->
+               let s = try Hashtbl.find sigs f.cf_name with Not_found -> "v" in
+               output_cpp ("  hx::ScriptNamedFunction(\"" ^ f.cf_name ^ "\",__s_" ^ f.cf_name ^ ",\"" ^ s ^ "\"),\n" ) ) new_sctipt_functions;
+            output_cpp "  hx::ScriptNamedFunction(0,0,0) };\n";
+         end else
+            output_cpp "static hx::ScriptNamedFunction *__scriptableFunctions = 0;\n";
       end;
    end;
 
 
 
+
 	(* Initialise static in boot function ... *)
 	if (not class_def.cl_interface) then begin
 		(* Remap the specialised "extern" classes back to the generic names *)
@@ -3225,6 +3315,15 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
 			| path -> join_class_path path "." in
 
 		output_cpp ("Class " ^ class_name ^ "::__mClass;\n\n");
+      if (scriptable) then begin
+         (match class_def.cl_constructor with
+		        | Some field  ->
+                  let signature = generate_script_function false field "__script_construct_func" "__construct" in
+                  output_cpp ("hx::ScriptFunction " ^ class_name ^ "::__script_construct(__script_construct_func,\"" ^ signature ^ "\");\n");
+              | _ ->
+                  output_cpp ("hx::ScriptFunction " ^ class_name ^ "::__script_construct(0,0);\n");
+         );
+      end;
 
 		output_cpp ("void " ^ class_name ^ "::__register()\n{\n");
 		output_cpp ("	hx::Static(__mClass) = hx::RegisterClass(" ^ (str class_name_text)  ^
@@ -3232,6 +3331,7 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
 		output_cpp ("	&__CreateEmpty, &__Create,\n");
 		output_cpp ("	&super::__SGetClass(), 0, sMarkStatics\n");
 		output_cpp ("#ifdef HXCPP_VISIT_ALLOCS\n    , sVisitStatics\n#endif\n");
+		output_cpp ("#ifdef HXCPP_SCRIPTABLE\n    , sMemberStorageInfo\n#endif\n");
 		output_cpp (");\n");
       if (scriptable) then
             output_cpp ("  HX_SCRIPTABLE_REGISTER_CLASS(\""^class_name_text^"\"," ^ class_name ^ ");\n");
@@ -3248,6 +3348,7 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
 		output_cpp ("	0, 0,\n");
 		output_cpp ("	&super::__SGetClass(), 0, sMarkStatics\n");
 		output_cpp ("#ifdef HXCPP_VISIT_ALLOCS\n    , sVisitStatics\n#endif\n");
+		output_cpp ("#ifdef HXCPP_SCRIPTABLE\n    , 0\n#endif\n");
 		output_cpp (");\n");
       if (scriptable) then
          output_cpp ("  HX_SCRIPTABLE_REGISTER_INTERFACE(\""^class_name_text^"\"," ^ class_name ^ ");\n");
@@ -3316,6 +3417,8 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
 		output_h ("		static " ^ptr_name^ " __new(" ^constructor_type_args ^");\n");
 		output_h ("		static Dynamic __CreateEmpty();\n");
 		output_h ("		static Dynamic __Create(hx::DynamicArray inArgs);\n");
+      if (scriptable) then
+		   output_h ("		static hx::ScriptFunction __script_construct;\n");
 		output_h ("		~" ^ class_name ^ "();\n\n");
 		output_h ("		HX_DO_RTTI;\n");
 		if (field_integer_dynamic) then output_h "		Dynamic __IField(int inFieldID);\n";
@@ -3697,6 +3800,24 @@ let is_assign_op op =
    | _ -> false
 ;;
 
+let script_type_string haxe_type =
+	match follow haxe_type with
+	| TType ({t_path = [],"Array"},params) -> "Array"
+   | TInst ({cl_path=[],"Array"},params) ->
+      (match params with
+      | [t] ->
+         (match type_string_suff "" t with
+           | "int" -> "Array.int"
+           | "Float" -> "Array.Float"
+           | "bool" -> "Array.bool"
+           | "::String" -> "Array.String"
+           | "unsigned char" -> "Array.unsigned char"
+           | _ -> "Array.Dynamic"
+         )
+      | _ -> "Array.Dynamic"
+      )
+   | t -> type_string_suff "" t
+;;
 
 class script_writer common_ctx filename =
 	object(this)
@@ -3731,7 +3852,7 @@ class script_writer common_ctx filename =
          Buffer.add_string typeBuffer ((string_of_int (String.length name)) ^ " " ^ name ^ "\n");
          size;
       end
-	method typeText typeT = (string_of_int (this#typeId (type_string_suff "" typeT))) ^ " "
+	method typeText typeT = (string_of_int (this#typeId (script_type_string typeT))) ^ " "
 	method writeType typeT = this#write (this#typeText typeT)
 	method boolText value = if value then "1" else "0"
 	method writeBool value = this#write (if value then "1 " else "0 ")
@@ -3770,7 +3891,7 @@ class script_writer common_ctx filename =
 	| TInt i -> Printf.sprintf "i%ld " i
 	| TFloat f -> "f" ^ f ^ " "
 	| TString s -> "s" ^ (this#stringText s)
-	| TBool b -> if b then "TRUE " else "FALSE "
+	| TBool b -> if b then "true " else "false "
 	| TNull -> "NULL "
 	| TThis -> "THIS "
 	| TSuper -> "SUPER "
@@ -3786,7 +3907,7 @@ class script_writer common_ctx filename =
 	method begin_expr = this#push_indent
 	method end_expr = if not just_finished_block then this#write "\n"; this#pop_indent; just_finished_block <- true
    method func isStatic funcName ret args isInterface fieldExpression =
-       this#write ("FUNCION " ^ (this#staticText isStatic) ^ " " ^ (this#stringText funcName) ^ " ");
+       this#write ("FUNCTION " ^ (this#staticText isStatic) ^ " " ^ (this#stringText funcName) ^ " ");
        this#write ((this#typeText ret) ^ (string_of_int (List.length args)) ^ " ");
        List.iter (fun (name,opt,typ) -> this#write ( (this#stringText name) ^ (this#boolText opt) ^ " " ^ (this#typeText typ) ^ " " )) args;
        this#write "\n";
@@ -3823,29 +3944,9 @@ class script_writer common_ctx filename =
      | TBreak -> this#write "BREAK ";
      | TContinue -> this#write "CONT ";
 
-     | TBinop (op,e1,e2) when is_assign_op op->
-        let op_name = (Ast.s_binop op) ^ " " in
-        let expression = remove_parens e1 in
-        (match expression.eexpr with
-        | TField (obj, acc) ->
-           (match acc with
-           | FDynamic name -> this#write ("FNAME" ^ op_name ^ (this#stringText name) ^ "\n");
-                this#gen_expression obj;
-           | FStatic (class_def,field) -> this#write ("FSTATIC" ^ op_name^ (this#instText class_def) ^ " " ^ (this#stringText field.cf_name) ^ "\n");
-           | FInstance (_,field) when is_this obj -> this#write ("FTHIS" ^ op_name ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^ "\n");
-           | FInstance (_,field) -> this#write ("FINST" ^ op_name ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^ "\n");
-                this#gen_expression obj;
-           | FClosure (_,field)
-           | FAnon (field) -> this#write ("FNAME" ^ op_name ^ (this#stringText field.cf_name) ^ "\n");
-                this#gen_expression obj;
-           | FEnum (enum,field) -> this#write ("FENUM" ^ op_name  ^ (this#enumText enum) ^ " " ^ (this#stringText field.ef_name) ^ "\n");
-           )
-        | TArray (e1, e2) -> this#write ("ARRAYI" ^ op_name ^ (this#typeText expression.etype) ^ "\n");
-           this#gen_expression e1;
-           this#gen_expression e2;
-        | TLocal var -> this#write ("VAR" ^ op_name ^ (string_of_int var.v_id) ^ "\n");
-        | _ -> assert false
-        );
+     | TBinop (op,e1,e2) when op=OpAssign ->
+        this#write ("SET " ^ (this#typeText e1.etype) ^ " " ^ (this#typeText e2.etype) ^ "\n");
+        this#gen_expression e1;
         this#gen_expression e2;
      | TBinop (OpEq ,e1, { eexpr = TConst TNull } ) -> this#write "ISNULL\n";
         this#gen_expression e1;
@@ -3860,7 +3961,8 @@ class script_writer common_ctx filename =
         this#gen_expression e2;
      | TThrow e -> this#write "THROW\n";
         this#gen_expression e;
-     | TArrayDecl expr_list -> this#writeList "ADEF" (List.length expr_list);
+     | TArrayDecl expr_list ->
+        this#write ("ADEF " ^ (this#typeText expression.etype) ^ " " ^(string_of_int (List.length expr_list))^"\n");
         List.iter this#gen_expression expr_list;
      | TIf (e,e1,e2) ->
         (match e2 with
@@ -3874,35 +3976,43 @@ class script_writer common_ctx filename =
            this#gen_expression e1;
            this#gen_expression elze; )
      | TCall (func, arg_list) ->
+        let argN = (string_of_int (List.length arg_list)) ^ " " in
         (match (remove_parens func).eexpr with
         | TField (obj,FStatic (class_def,field) ) ->
                this#write ("CALLSTATIC " ^ (this#instText class_def) ^ " " ^ (this#stringText field.cf_name) ^
-                  (string_of_int (List.length arg_list)) ^ "\n");
+                  argN ^ "\n");
         | TField (obj,FInstance (_,field) ) when is_this obj ->
                this#write ("CALLTHIS " ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^
-                  (string_of_int (List.length arg_list)) ^ "\n");
+                  argN ^ "\n");
         | TField (obj,FInstance (_,field) ) ->
                this#write ("CALLMEMBER " ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^
-                  (string_of_int (List.length arg_list)) ^ "\n");
+                  argN ^ "\n");
                this#gen_expression obj;
-        | _ -> this#writeList "CALL " (List.length arg_list);
+        | TConst TSuper -> this#write ("CALLSUPER " ^ (this#typeText func.etype) ^ " " ^ argN ^ "\n");
+        | _ -> this#write ("CALL " ^ argN ^ "\n");
                this#gen_expression func;
         );
         List.iter this#gen_expression arg_list;
      | TField (obj, acc) ->
+        let typeText = this#typeText obj.etype in
         (match acc with
-        | FDynamic name -> this#write ("FNAME " ^ (this#stringText name) ^ "\n");
+        | FDynamic name -> this#write ("FNAME " ^ typeText ^ " " ^ (this#stringText name) ^ "\n");
              this#gen_expression obj;
         | FStatic (class_def,field) -> this#write ("FSTATIC " ^ (this#instText class_def) ^ " " ^ (this#stringText field.cf_name) );
-        | FInstance (_,field) when is_this obj -> this#write ("FTHIS " ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) );
-        | FInstance (_,field) -> this#write ("FINST " ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^ "\n");
+        | FInstance (_,field) when is_this obj -> this#write ("FTHISINST " ^ typeText ^ " " ^ (this#stringText field.cf_name) );
+        | FInstance (_,field) -> this#write ("FLINK " ^ typeText ^ " " ^ (this#stringText field.cf_name) ^ "\n");
              this#gen_expression obj;
+
+        | FClosure (_,field) when is_this obj -> this#write ("FTHISNAME " ^typeText ^ " " ^  (this#stringText field.cf_name) ^ "\n")
+        | FAnon (field) when is_this obj -> this#write ("FTHISNAME " ^typeText ^ " " ^  (this#stringText field.cf_name) ^ "\n")
+
         | FClosure (_,field)
-        | FAnon (field) -> this#write ("FNAME " ^ (this#stringText field.cf_name) ^ "\n");
+        | FAnon (field) -> this#write ("FNAME " ^typeText ^ " " ^  (this#stringText field.cf_name) ^ "\n");
              this#gen_expression obj;
+
         | FEnum (enum,field) -> this#write ("FENUM " ^ (this#enumText enum) ^ " " ^ (this#stringText field.ef_name) );
         )
-     | TArray (e1, e2) -> this#write ("ARRAYI " ^ (this#typeText expression.etype) ^ "\n");
+     | TArray (e1, e2) -> this#write ("ARRAYI " ^ (this#typeText e1.etype) ^ "\n");
         this#gen_expression e1;
         this#gen_expression e2;
      | TUnop (op, flag, e) ->
@@ -3925,14 +4035,17 @@ class script_writer common_ctx filename =
                       this#writeVar tvar;
             | Some init ->this#write "VARDECLI ";
                       this#writeVar tvar;
+                      this#write (" " ^ (this#typeText init.etype));
                       this#write "\n";
                       this#gen_expression init;
          ) var_list
-     | TNew (clazz,params,arg_list) -> this#writeList ("NEW " ^ (this#typeText (TInst(clazz,params)))) (List.length arg_list);
-         List.iter this#gen_expression arg_list;
+     | TNew (clazz,params,arg_list) ->
+        let arg_types = (String.concat " " (List.map (fun t -> this#typeText t.etype)  arg_list)) ^ "\n" in
+        this#write ("NEW " ^ (this#typeText (TInst(clazz,params))) ^ (string_of_int (List.length arg_list)) ^ " " ^ arg_types);
+        List.iter this#gen_expression arg_list;
      | TReturn optval -> (match optval with
          | None -> this#write "RETURN\n"
-         | Some value -> this#write "RETVAL\n";
+         | Some value -> this#write ("RETVAL " ^ (this#typeText value.etype) ^ "\n");
                        this#gen_expression value;
          )
      | TObjectDecl (
@@ -4002,9 +4115,12 @@ let generate_script_class common_ctx script class_def =
    List.iter (fun(c,_) -> script#instName c) class_def.cl_implements;
    script#write "\n";
    script#write ((string_of_int ( (List.length class_def.cl_ordered_fields) +
-                                  (List.length class_def.cl_ordered_statics))) ^ "\n");
+                                  (List.length class_def.cl_ordered_statics) +
+                                  (match class_def.cl_constructor with Some _ -> 1 | _ -> 0 ) ) )
+                                  ^ "\n");
+
    let generate_field isStatic field =
-      match field.cf_kind, field.cf_type with
+      match field.cf_kind, follow field.cf_type with
 	   | Var { v_read = AccInline; v_write = AccNever },_ ->
          script#write "INLINE\n";
 	   | Var v,t ->
@@ -4020,12 +4136,16 @@ let generate_script_class common_ctx script class_def =
          script#var (mode_code v.v_read) (mode_code v.v_write) isStatic field.cf_name t
 	   | Method MethDynamic, TFun(a,r) ->
          script#var "N" "N" isStatic field.cf_name (TFun(a,r))
-	   | Method _, TFun(args,ret) when field.cf_name="new" ->
+      | Method _, TFun(args,ret) when field.cf_name="new" ->
          script#func true "new" (TInst(class_def,[])) args false field.cf_expr
 	   | Method _, TFun (args,ret) ->
          script#func isStatic field.cf_name ret args class_def.cl_interface field.cf_expr
-	   | Method _, _ -> print_endline ("Unknown method type " ^ (join_class_path class_def.cl_path "." ) ^field.cf_name);
+	   | Method _, _ -> print_endline ("Unknown method type " ^ (join_class_path class_def.cl_path "." )
+                      ^ "." ^field.cf_name )
    in
+   (match class_def.cl_constructor with
+		| Some field  -> generate_field true field
+      | _ -> () );
    List.iter (generate_field false) class_def.cl_ordered_fields;
    List.iter (generate_field true) class_def.cl_ordered_statics;
    script#write "\n";
@@ -4072,6 +4192,12 @@ let generate_cppia common_ctx =
 		);
 	) common_ctx.types;
 
+	(match common_ctx.main with
+	| None -> script#write "NOMAIN\n"
+	| Some e -> script#write "MAIN\n";
+         script#gen_expression e
+   );
+
    script#close
 ;;
 

+ 2 - 2
gencs.ml

@@ -1678,7 +1678,7 @@ let configure gen =
           begin_block w;
           write w "public static void Main()";
           begin_block w;
-          (if Hashtbl.mem gen.gtypes (["cs"], "Boot") then write w "cs.Boot.init();"; newline w);
+          (if Hashtbl.mem gen.gtypes (["cs"], "Boot") then write w "global::cs.Boot.init();"; newline w);
           expr_s w { eexpr = TTypeExpr(TClassDecl cl); etype = t_dynamic; epos = Ast.null_pos };
           write w ".main();";
           end_block w;
@@ -1716,7 +1716,7 @@ let configure gen =
     if is_main then begin
       write w "public static void Main()";
       begin_block w;
-      (if Hashtbl.mem gen.gtypes (["cs"], "Boot") then write w "cs.Boot.init();"; newline w);
+      (if Hashtbl.mem gen.gtypes (["cs"], "Boot") then write w "global::cs.Boot.init();"; newline w);
       write w "main();";
       end_block w
     end;

+ 30 - 19
genjs.ml

@@ -90,12 +90,21 @@ let s_path ctx = if ctx.js_flatten then flat_path else dot_path
 let kwds =
 	let h = Hashtbl.create 0 in
 	List.iter (fun s -> Hashtbl.add h s ()) [
-		"abstract"; "as"; "boolean"; "break"; "byte"; "case"; "catch"; "char"; "class"; "continue"; "const";
-		"debugger"; "default"; "delete"; "do"; "double"; "else"; "enum"; "export"; "extends"; "false"; "final";
-		"finally"; "float"; "for"; "function"; "goto"; "if"; "implements"; "import"; "in"; "instanceof"; "int";
-		"interface"; "long"; "namespace"; "native"; "new"; "null"; "package"; "private"; "protected";
-		"public"; "return"; "short"; "static"; "super"; "switch"; "synchronized"; "this"; "throw"; "throws";
-		"transient"; "true"; "try"; "typeof"; "var"; "void"; "volatile"; "while"; "with"
+		(* JS reserved words: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Reserved_Words *)
+		"break"; "case"; "catch"; "class"; "const"; "continue"; "debugger"; "default"; "delete";
+		"do"; "else"; "enum"; "export"; "extends"; "finally"; "for"; "function"; "if"; "implements";
+		"import"; "in"; "instanceof"; "interface"; "let"; "new"; "package"; "private"; "protected";
+		"public"; "return"; "static"; "super"; "switch"; "this"; "throw"; "try"; "typeof"; "var";
+		"void"; "while"; "with"; "yield";
+	];
+	h
+
+(* Identifiers Haxe reserves to make the JS output cleaner. These can still be used in untyped code (TLocal),
+   but are escaped upon declaration. *)
+let kwds2 =
+	let h = Hashtbl.create 0 in
+	List.iter (fun s -> Hashtbl.add h s ()) [
+		"console"; "window";
 	];
 	h
 
@@ -113,6 +122,8 @@ let valid_js_ident s =
 
 let field s = if Hashtbl.mem kwds s then "[\"" ^ s ^ "\"]" else "." ^ s
 let ident s = if Hashtbl.mem kwds s then "$" ^ s else s
+let check_var_declaration v = if Hashtbl.mem kwds2 v.v_name then v.v_name <- "$" ^ v.v_name
+
 let anon_field s = if Hashtbl.mem kwds s || not (valid_js_ident s) then "'" ^ s ^ "'" else s
 let static_field s =
 	match s with
@@ -446,20 +457,13 @@ let rec gen_call ctx e el in_value =
 		concat ctx "," (gen_value ctx) el;
 		spr ctx ")"
 
-and gen_object_value ctx e = match e.eexpr with
-	| TConst (TInt _) | TConst (TFloat _) ->
-		spr ctx "(";
-		gen_value ctx e;
-		spr ctx ")"
-	| _ -> gen_value ctx e
-
 and gen_expr ctx e =
 	add_mapping ctx e;
 	match e.eexpr with
 	| TConst c -> gen_constant ctx e.epos c
 	| TLocal v -> spr ctx (ident v.v_name)
-	| TArray (e1,{ eexpr = TConst (TString s) }) when valid_js_ident s ->
-		gen_object_value ctx e1;
+	| TArray (e1,{ eexpr = TConst (TString s) }) when valid_js_ident s && (match e1.eexpr with TConst (TInt _|TFloat _) -> false | _ -> true) ->
+		gen_value ctx e1;
 		spr ctx (field s)
 	| TArray (e1,e2) ->
 		gen_value ctx e1;
@@ -496,6 +500,8 @@ and gen_expr ctx e =
 	| TEnumParameter (x,_,i) ->
 		gen_value ctx x;
 		print ctx "[%i]" (i + 2)
+	| TField ({ eexpr = TConst (TInt _ | TFloat _) } as x,f) ->
+		gen_expr ctx { e with eexpr = TField(mk (TParenthesis x) x.etype x.epos,f) }
 	| TField (x,f) ->
 		gen_value ctx x;
 		let name = field_name f in
@@ -552,6 +558,7 @@ and gen_expr ctx e =
 	| TVars vl ->
 		spr ctx "var ";
 		concat ctx ", " (fun (v,e) ->
+			check_var_declaration v;
 			spr ctx (ident v.v_name);
 			match e with
 			| None -> ()
@@ -604,6 +611,7 @@ and gen_expr ctx e =
 		spr ctx "}";
 		ctx.separator <- true
 	| TFor (v,it,e) ->
+		check_var_declaration v;
 		let handle_break = handle_break ctx e in
 		let it = ident (match it.eexpr with
 			| TLocal v -> v.v_name
@@ -628,7 +636,7 @@ and gen_expr ctx e =
 	| TTry (e,catchs) ->
 		spr ctx "try ";
 		gen_expr ctx e;
-		let vname = (match catchs with [(v,_)] -> v.v_name | _ ->
+		let vname = (match catchs with [(v,_)] -> check_var_declaration v; v.v_name | _ ->
 			let id = ctx.id_counter in
 			ctx.id_counter <- ctx.id_counter + 1;
 			"$e" ^ string_of_int id
@@ -723,7 +731,7 @@ and gen_expr ctx e =
 	| TCast (e,None) ->
 		gen_expr ctx e
 	| TCast (e1,Some t) ->
-		spr ctx "js.Boot.__cast(";
+		print ctx "%s.__cast(" (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js"],"Boot" }));
 		gen_expr ctx e1;
 		spr ctx " , ";
 		spr ctx (ctx.type_accessor t);
@@ -802,7 +810,7 @@ and gen_value ctx e =
 	| TCast (e1, None) ->
 		gen_value ctx e1
 	| TCast (e1, Some t) ->
-		spr ctx "js.Boot.__cast(";
+		print ctx "%s.__cast(" (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js"],"Boot" }));
 		gen_value ctx e1;
 		spr ctx " , ";
 		spr ctx (ctx.type_accessor t);
@@ -1261,9 +1269,12 @@ let generate com =
 		newline ctx;
 	end;
 
+	(* TODO: fix $estr *)
 	let vars = [] in
 	let vars = (if has_feature ctx "Type.resolveClass" || has_feature ctx "Type.resolveEnum" then ("$hxClasses = " ^ (if ctx.js_modern then "{}" else "$hxClasses || {}")) :: vars else vars) in
-	let vars = (if List.exists (function TEnumDecl { e_extern = false } -> true | _ -> false) com.types then "$estr = function() { return js.Boot.__string_rec(this,''); }" :: vars else vars) in
+	let vars = (if List.exists (function TEnumDecl { e_extern = false } -> true | _ -> false) com.types
+		then ("$estr = function() { return " ^ (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js"],"Boot" })) ^ ".__string_rec(this,''); }") :: vars
+		else vars) in
 	(match List.rev vars with
 	| [] -> ()
 	| vl ->

+ 3 - 3
genswf.ml

@@ -243,7 +243,7 @@ let build_class com c file =
 							| HVInt i | HVUInt i ->
 								Some (Int (Int32.to_string i))
 							| HVFloat f ->
-								Some (Float (string_of_float f))
+								Some (Float (float_repres f))
 							) in
 							match v with
 							| None -> None
@@ -542,7 +542,7 @@ let swf_ver = function
 	| 11.6 -> 19
 	| 11.7 -> 20
 	| 11.8 -> 21
-	| v -> failwith ("Invalid SWF version " ^ string_of_float v)
+	| v -> failwith ("Invalid SWF version " ^ float_repres v)
 
 let convert_header com (w,h,fps,bg) =
 	let high = (max w h) * 20 in
@@ -844,7 +844,7 @@ let build_swf9 com file swc =
 				| (Meta.Font,(EConst (String file),p) :: args,_) :: l ->
 					let file = try Common.find_file com file with Not_found -> file in
 					let ch = try open_in_bin file with _ -> error "File not found" p in
-					let ttf = TTFParser.parse ch in
+					let ttf = try TTFParser.parse ch with e -> error ("Error while parsing font " ^ file ^ " : " ^ Printexc.to_string e) p in
 					close_in ch;
 					let range_str = match args with
 						| [EConst (String str),_] -> str

+ 3 - 3
genxml.ml

@@ -353,10 +353,10 @@ let generate_type com t =
 			| l -> p "@%s(%s) " (fst (MetaInfo.to_string m)) (String.concat "," (List.map Ast.s_expr pl))
 		) ml
 	in
-	let access a =
+	let access is_read a =
 		match a, pack with
 		| AccNever, "flash" :: _ -> "null"
-		| _ -> s_access a
+		| _ -> s_access is_read a
 	in
 	let print_field stat f =
 		p "\t";
@@ -365,7 +365,7 @@ let generate_type com t =
 		(match f.cf_kind with
 		| Var v ->
 			p "var %s" f.cf_name;
-			if v.v_read <> AccNormal || v.v_write <> AccNormal then p "(%s,%s)" (access v.v_read) (access v.v_write);
+			if v.v_read <> AccNormal || v.v_write <> AccNormal then p "(%s,%s)" (access true v.v_read) (access false v.v_write);
 			p " : %s" (stype f.cf_type);
 		| Method m ->
 			let params, ret = (match follow f.cf_type with

+ 4 - 0
haxe.hxproj

@@ -128,6 +128,10 @@
     <hidden path="matcher.obj" />
     <hidden path="matcher.cmx" />
     <hidden path="matcher.cmi" />
+    <hidden path="version.obj" />
+    <hidden path="version.cmi" />
+    <hidden path="version.cmx" />
+    <hidden path="haxe.exe.manifest" />
   </hiddenPaths>
   <!-- Executed before build -->
   <preBuildCommand>make -j4 MSVC=1 FD_OUTPUT=1 -f Makefile.win kill haxe</preBuildCommand>

+ 51 - 14
interp.ml

@@ -113,8 +113,9 @@ type extern_api = {
 	get_local_using : unit -> tclass list;
 	get_local_vars : unit -> (string, Type.tvar) PMap.t;
 	get_build_fields : unit -> value;
-	get_pattern_locals : Ast.expr -> Type.t -> (string,Type.tvar) PMap.t;
+	get_pattern_locals : Ast.expr -> Type.t -> (string,Type.tvar * Ast.pos) PMap.t;
 	define_type : value -> unit;
+	define_module : string -> value list -> unit;
 	module_dependency : string -> string -> bool -> unit;
 	current_module : unit -> module_def;
 	delayed_macro : int -> (unit -> (unit -> value));
@@ -2039,6 +2040,19 @@ let z_lib =
 (* ---------------------------------------------------------------------- *)
 (* MACRO LIBRARY *)
 
+(* convert float value to haxe expression, handling inf/-inf/nan *)
+let haxe_float f p =
+    let std = (Ast.EConst (Ast.Ident "std"), p) in
+    let math = (Ast.EField (std, "Math"), p) in
+    if (f = infinity) then
+        (Ast.EField (math, "POSITIVE_INFINITY"), p)
+    else if (f = neg_infinity) then
+        (Ast.EField (math, "NEGATIVE_INFINITY"), p)
+    else if (f <> f) then
+        (Ast.EField (math, "NaN"), p)
+    else
+        (Ast.EConst (Ast.Float (float_repres f)), p)
+
 let macro_lib =
 	let error() =
 		raise Builtin_error
@@ -2060,7 +2074,7 @@ let macro_lib =
 			| VString s, VAbstract (APos p) ->
 				raise (Typecore.Fatal_error (s,p))
 			| _ -> error()
-		);		
+		);
 		"warning", Fun2 (fun msg p ->
 			match msg, p with
 			| VString s, VAbstract (APos p) ->
@@ -2154,7 +2168,7 @@ let macro_lib =
 					| VBool b -> (Ast.EConst (Ast.Ident (if b then "true" else "false")),p)
 					| VInt i -> (Ast.EConst (Ast.Int (string_of_int i)),p)
 					| VInt32 i -> (Ast.EConst (Ast.Int (Int32.to_string i)),p)
-					| VFloat f -> (Ast.EConst (Ast.Float (string_of_float f)),p)
+					| VFloat f -> haxe_float f p
 					| VAbstract (APos p) ->
 						(Ast.EObjectDecl (
 							("fileName" , (Ast.EConst (Ast.String p.Ast.pfile) , p)) ::
@@ -2355,6 +2369,10 @@ let macro_lib =
 				VNull
 			| _ -> error()
 		);
+		"local_module", Fun0 (fun() ->
+			let m = (get_ctx()).curapi.current_module() in
+			VString (Ast.s_type_path m.m_path);
+		);
 		"local_type", Fun0 (fun() ->
 			match (get_ctx()).curapi.get_local_type() with
 			| None -> VNull
@@ -2396,6 +2414,14 @@ let macro_lib =
 			(get_ctx()).curapi.define_type v;
 			VNull
 		);
+		"define_module", Fun2 (fun p v ->
+			match p, v with
+			| VString path, VArray vl ->
+				(get_ctx()).curapi.define_module path (Array.to_list vl);
+				VNull
+			| _ ->
+				error()
+		);
 		"add_class_path", Fun1 (fun v ->
 			match v with
 			| VString cp ->
@@ -2411,6 +2437,7 @@ let macro_lib =
 				let com = ccom() in
 				(match com.platform with
 				| Flash -> Genswf.add_swf_lib com file false
+				| Java -> Genjava.add_java_lib com file false
 				| _ -> failwith "Unsupported platform");
 				VNull
 			| _ ->
@@ -2454,7 +2481,7 @@ let macro_lib =
 		"pattern_locals", Fun2 (fun e t ->
 			let loc = (get_ctx()).curapi.get_pattern_locals (decode_expr e) (decode_type t) in
 			let h = Hashtbl.create 0 in
-			PMap.iter (fun n v -> Hashtbl.replace h (VString n) (encode_type v.v_type)) loc;
+			PMap.iter (fun n (v,_) -> Hashtbl.replace h (VString n) (encode_type v.v_type)) loc;
 			enc_hash h
 		);
 		"macro_context_reused", Fun1 (fun c ->
@@ -3238,7 +3265,7 @@ let rec to_string ctx n v =
 	| VInt i -> string_of_int i
 	| VInt32 i -> Int32.to_string i
 	| VFloat f ->
-		let s = string_of_float f in
+		let s = float_repres f in
 		let len = String.length s in
 		if String.unsafe_get s (len - 1) = '.' then String.sub s 0 (len - 1) else s
 	| VString s -> s
@@ -3884,7 +3911,7 @@ let rec decode_path t =
 	{
 		tpackage = List.map dec_string (dec_array (field t "pack"));
 		tname = dec_string (field t "name");
-		tparams = List.map decode_tparam (dec_array (field t "params"));
+		tparams = (match field t "params" with VNull -> [] | a -> List.map decode_tparam (dec_array a));
 		tsub = opt dec_string (field t "sub");
 	}
 
@@ -3894,18 +3921,22 @@ and decode_tparam v =
 	| 1,[e] -> TPExpr (decode_expr e)
 	| _ -> raise Invalid_expr
 
+and decode_tparams = function
+	| VNull -> []
+	| a -> List.map decode_tparam_decl (dec_array a)
+
 and decode_tparam_decl v =
 	{
 		tp_name = dec_string (field v "name");
 		tp_constraints = (match field v "constraints" with VNull -> [] | a -> List.map decode_ctype (dec_array a));
-		tp_params = (match field v "params" with VNull -> [] | a -> List.map decode_tparam_decl (dec_array a));
+		tp_params = decode_tparams (field v "params");
 	}
 
 and decode_fun v =
 	{
-		f_params = List.map decode_tparam_decl (dec_array (field v "params"));
+		f_params = decode_tparams (field v "params");
 		f_args = List.map (fun o ->
-			(dec_string (field o "name"),dec_bool (field o "opt"),opt decode_ctype (field o "type"),opt decode_expr (field o "value"))
+			(dec_string (field o "name"),(match field o "opt" with VNull -> false | v -> dec_bool v),opt decode_ctype (field o "type"),opt decode_expr (field o "value"))
 		) (dec_array (field v "args"));
 		f_type = opt decode_ctype (field v "ret");
 		f_expr = opt decode_expr (field v "expr");
@@ -3923,10 +3954,11 @@ and decode_access v =
 	| _ -> raise Invalid_expr
 
 and decode_meta_entry v =
-	MetaInfo.from_string (dec_string (field v "name")), List.map decode_expr (dec_array (field v "params")), decode_pos (field v "pos")
+	MetaInfo.from_string (dec_string (field v "name")), (match field v "params" with VNull -> [] | a -> List.map decode_expr (dec_array a)), decode_pos (field v "pos")
 
-and decode_meta_content v =
-	List.map decode_meta_entry (dec_array v)
+and decode_meta_content = function
+	| VNull -> []
+	| v -> List.map decode_meta_entry (dec_array v)
 
 and decode_field v =
 	let fkind = match decode_enum (field v "kind") with
@@ -4331,13 +4363,13 @@ let decode_type_def v =
 	let name = dec_string (field v "name") in
 	let meta = decode_meta_content (field v "meta") in
 	let pos = decode_pos (field v "pos") in
-	let isExtern = dec_bool (field v "isExtern") in
+	let isExtern = (match field v "isExtern" with VNull -> false | v -> dec_bool v) in
 	let fields = List.map decode_field (dec_array (field v "fields")) in
 	let mk fl dl =
 		{
 			d_name = name;
 			d_doc = None;
-			d_params = List.map decode_tparam_decl (dec_array (field v "params"));
+			d_params = decode_tparams (field v "params");
 			d_meta = meta;
 			d_flags = fl;
 			d_data = dl;
@@ -4385,6 +4417,11 @@ let decode_type_def v =
 	| _ ->
 		raise Invalid_expr
 	) in
+	(* if our package ends with an uppercase letter, then it's the module name *)
+	let pack,name = (match List.rev pack with
+		| last :: l when not (is_lower_ident last) -> List.rev l, last
+		| _ -> pack, name
+	) in
 	(pack, name), tdef, pos
 
 (* ---------------------------------------------------------------------- *)

+ 5 - 5
main.ml

@@ -565,7 +565,7 @@ and wait_loop boot_com host port =
 			else try
 				if m.m_extra.m_mark <= start_mark then begin
 					(match m.m_extra.m_kind with
-					| MFake -> () (* don't get classpath *)
+					| MFake | MSub -> () (* don't get classpath *)
 					| MCode -> if not (check_module_path com2 m p) then raise Not_found;
 					| MMacro when ctx.Typecore.in_macro -> if not (check_module_path com2 m p) then raise Not_found;
 					| MMacro ->
@@ -609,7 +609,7 @@ and wait_loop boot_com host port =
 							a.a_meta <- List.filter (fun (m,_,_) -> m <> Ast.Meta.ValueUsed) a.a_meta
 						| _ -> ()
 					) m.m_types;
-					Typeload.add_module ctx m p;
+					if m.m_extra.m_kind <> MSub then Typeload.add_module ctx m p;
 					PMap.iter (Hashtbl.add com2.resources) m.m_extra.m_binded_res;
 					PMap.iter (fun _ m2 -> add_modules m0 m2) m.m_extra.m_deps);
 					List.iter (Typer.call_init_macro ctx) m.m_extra.m_macro_calls
@@ -778,8 +778,8 @@ and do_connect host port args =
 
 and init ctx =
 	let usage = Printf.sprintf
-		"Haxe Compiler %d.%d.%d - (C)2005-2013 Haxe Foundation\n Usage : haxe%s -main <class> [-swf|-js|-neko|-php|-cpp|-as3] <output> [options]\n Options :"
-		(version / 100) ((version mod 100)/10) (version mod 10) (if Sys.os_type = "Win32" then ".exe" else "")
+		"Haxe Compiler %d.%d.%d %s- (C)2005-2013 Haxe Foundation\n Usage : haxe%s -main <class> [-swf|-js|-neko|-php|-cpp|-as3] <output> [options]\n Options :"
+		(version / 100) ((version mod 100)/10) (version mod 10) (match Version.version_extra with None -> "" | Some v -> v) (if Sys.os_type = "Win32" then ".exe" else "")
 	in
 	let com = ctx.com in
 	let classes = ref [([],"Std")] in
@@ -796,7 +796,7 @@ try
 	let force_typing = ref false in
 	let pre_compilation = ref [] in
 	let interp = ref false in
-	Common.define_value com Define.HaxeVer (string_of_float (float_of_int version /. 100.));
+	Common.define_value com Define.HaxeVer (float_repres (float_of_int version /. 100.));
 	Common.raw_define com (if ((version / 10) land 1 == 0) then "haxe_release" else "haxe_svn");
 	Common.raw_define com "haxe3";
 	Common.define_value com Define.Dce "std";

+ 7 - 8
matcher.ml

@@ -353,7 +353,7 @@ let to_pattern ctx e t =
 					| TFun(args,r) ->
 						unify ctx r t p;
 						List.map (fun (n,_,t) -> t) args,r
-					| _ -> error "Arguments expected" p
+					| _ -> error "No arguments expected" p
 				in
 				let rec loop2 i el tl = match el,tl with
 					| (EConst(Ident "_"),pany) :: [], t :: tl ->
@@ -411,7 +411,7 @@ let to_pattern ctx e t =
 						ignore(follow cf.cf_type);
 						let e = begin match cf.cf_expr with
 						| Some ({eexpr = TConst c | TCast({eexpr = TConst c},None)} as e) -> e
-						| _ -> print_endline "Not found"; raise Not_found
+						| _ -> raise Not_found
 						end in
 						e
 					| _ ->
@@ -442,11 +442,12 @@ let to_pattern ctx e t =
 					| _ ->
 						raise Not_found);
 			with Not_found ->
-				if not (is_lower_ident s) && s.[0] <> '`' then error "Capture variables must be lower-case" p;
 				begin match get_tuple_types t with
-					| Some _ ->
-						error "Cannot bind tuple" p
+					| Some tl ->
+						let s = String.concat "," (List.map (fun (_,_,t) -> s_type t) tl) in
+						error ("Pattern should be tuple [" ^ s ^ "]") p
 					| None ->
+						if not (is_lower_ident s) && s.[0] <> '`' then error "Capture variables must be lower-case" p;
 						let v = mk_var pctx s t p in
 						mk_pat (PVar (v,p)) v.v_type p
 				end
@@ -567,7 +568,7 @@ let to_pattern ctx e t =
 let get_pattern_locals ctx e t =
 	try
 		let _,locals,_ = to_pattern ctx e t in
-		PMap.foldi (fun n (v,_) acc -> PMap.add n v acc) locals PMap.empty
+		PMap.foldi (fun n v acc -> PMap.add n v acc) locals PMap.empty
 	with Unrecognized_pattern _ ->
 		PMap.empty
 
@@ -1067,8 +1068,6 @@ let match_expr ctx e cases def with_type p =
 	(* turn subjects to subterms and handle variable initialization where necessary *)
 	let stl = ExtList.List.mapi (fun i e ->
 		let rec loop e = match e.eexpr with
-			| TField (ef,s) when (match s with FEnum _ -> false | _ -> true) ->
-				mk_st (SField(loop ef,field_name s)) e.etype e.epos
 			| TParenthesis e | TMeta(_,e) ->
 				loop e
 			| TLocal v ->

+ 3 - 3
optimizer.ml

@@ -382,7 +382,7 @@ let rec type_inline ctx cf f ethis params tret config p force =
 
 		This could be fixed with better post process code cleanup (planed)
 	*)
-	if !cancel_inlining || (Common.platform ctx.com Js && not !force && (init <> None || !has_vars)) then
+	if !cancel_inlining then
 		None
 	else
 		let wrap e =
@@ -807,7 +807,7 @@ let rec reduce_loop ctx e =
 	let e = Type.map_expr (reduce_loop ctx) e in
 	let check_float op f1 f2 =
 		let f = op f1 f2 in
-		let fstr = string_of_float f in
+		let fstr = float_repres f in
 		if (match classify_float f with FP_nan | FP_infinite -> false | _ -> float_of_string fstr = f) then { e with eexpr = TConst (TFloat fstr) } else e
 	in
 	sanitize_expr ctx.com (match e.eexpr with
@@ -946,7 +946,7 @@ let rec reduce_loop ctx e =
 		| NegBits, TConst (TInt i) -> { e with eexpr = TConst (TInt (Int32.lognot i)) }
 		| Neg, TConst (TFloat f) ->
 			let v = 0. -. float_of_string f in
-			let vstr = string_of_float v in
+			let vstr = float_repres v in
 			if float_of_string vstr = v then
 				{ e with eexpr = TConst (TFloat vstr) }
 			else

+ 1 - 1
std/cpp/_std/sys/net/Socket.hx

@@ -157,7 +157,7 @@ class Socket {
 			socket_connect(__s, host.ip, port);
 		} catch( s : String ) {
 			if( s == "std@socket_connect" )
-				throw "Failed to connect on "+(try host.reverse() catch( e : Dynamic ) host.toString())+":"+port;
+				throw "Failed to connect on "+host.toString()+":"+port;
 			else
 				cpp.Lib.rethrow(s);
 		}

+ 42 - 29
std/haxe/Http.hx

@@ -67,8 +67,8 @@ class Http {
 	public var async : Bool;
 #end
 	var postData : String;
-	var headers : haxe.ds.StringMap<String>;
-	var params : haxe.ds.StringMap<String>;
+	var headers : List<{ header:String, value:String }>;
+	var params : List<{ param:String, value:String }>;
 
 	#if sys
 	public static var PROXY : { host : String, port : Int, auth : { user : String, pass : String } } = null;
@@ -87,8 +87,9 @@ class Http {
 	**/
 	public function new( url : String ) {
 		this.url = url;
-		headers = new haxe.ds.StringMap();
-		params = new haxe.ds.StringMap();
+		headers = new List<{ header:String, value:String }>();
+		params = new List<{ param:String, value:String }>();
+		
 		#if js
 		async = true;
 		#elseif sys
@@ -107,10 +108,16 @@ class Http {
 		This method provides a fluent interface.
 	**/
 	public function setHeader( header : String, value : String ):Http {
-		headers.set(header, value);
+		headers = Lambda.filter(headers, function(h) return h.header != header);
+		headers.push({ header:header, value:value });
 		return this;
 	}
 
+	public function addHeader( header : String, value : String ):Http {
+		headers.push({ header:header, value:value });
+		return this;
+	}
+	
 	/**
 		Sets the parameter identified as `param` to value `value`.
 
@@ -119,10 +126,16 @@ class Http {
 		This method provides a fluent interface.
 	**/
 	public function setParameter( param : String, value : String ):Http {
-		params.set(param, value);
+		params = Lambda.filter(params, function(p) return p.param != param);
+		params.push({ param:param, value:value });
 		return this;
 	}
 
+	public function addParameter( param : String, value : String ):Http {
+		params.push({ param:param, value:value });
+		return this;
+	}
+	
 	#if !flash8
 	/**
 		Sets the post data of `this` Http request to `data`.
@@ -189,12 +202,12 @@ class Http {
 		var uri = postData;
 		if( uri != null )
 			post = true;
-		else for( p in params.keys() ) {
+		else for( p in params ) {
 			if( uri == null )
 				uri = "";
 			else
 				uri += "&";
-			uri += StringTools.urlEncode(p)+"="+StringTools.urlEncode(params.get(p));
+			uri += StringTools.urlEncode(p.param)+"="+StringTools.urlEncode(p.value);
 		}
 		try {
 			if( post )
@@ -209,11 +222,11 @@ class Http {
 			onError(e.toString());
 			return;
 		}
-		if( headers.get("Content-Type") == null && post && postData == null )
+		if( !Lambda.exists(headers, function(h) return h.header == "Content-Type") && post && postData == null )
 			r.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
 
-		for( h in headers.keys() )
-			r.setRequestHeader(h,headers.get(h));
+		for( h in headers )
+			r.setRequestHeader(h.header,h.value);
 		r.send(uri);
 		if( !async )
 			onreadystatechange(null);
@@ -229,7 +242,7 @@ class Http {
 			if( e.status != 0 )
 				me.onStatus( e.status );
 		});
-		loader.addEventListener( "ioError", function(e:flash.events.IOErrorEvent) {
+		loader.addEventListener( "ioError", function(e:flash.events.IOErrorEvent){
 			me.responseData = loader.data;
 			me.onError(e.text);
 		});
@@ -240,9 +253,9 @@ class Http {
 		// headers
 		var param = false;
 		var vars = new flash.net.URLVariables();
-		for( k in params.keys() ){
+		for( p in params ){
 			param = true;
-			Reflect.setField(vars,k,params.get(k));
+			Reflect.setField(vars,p.param,p.value);
 		}
 		var small_url = url;
 		if( param && !post ){
@@ -256,8 +269,8 @@ class Http {
 		var bug = small_url.split("xxx");
 
 		var request = new flash.net.URLRequest( small_url );
-		for( k in headers.keys() )
-			request.requestHeaders.push( new flash.net.URLRequestHeader(k,headers.get(k)) );
+		for( h in headers )
+			request.requestHeaders.push( new flash.net.URLRequestHeader(h.header,h.value) );
 
 		if( postData != null ) {
 			request.data = postData;
@@ -293,12 +306,12 @@ class Http {
 		untyped ASSetPropFlags(r,"onHTTPStatus",7);
 		#end
 		untyped ASSetPropFlags(r,"onData",7);
-		for( h in headers.keys() )
-			r.addRequestHeader(h,headers.get(h));
+		for( h in headers )
+			r.addRequestHeader(h.header,h.value);
 		var param = false;
-		for( p in params.keys() ) {
+		for( p in params ) {
 			param = true;
-			Reflect.setField(r,p,params.get(p));
+			Reflect.setField(r,p.param,p.value);
 		}
 		var small_url = url;
 		if( param && !post ) {
@@ -377,16 +390,16 @@ class Http {
 			while( boundary.length < 38 )
 				boundary = "-" + boundary;
 			var b = new StringBuf();
-			for( p in params.keys() ) {
+			for( p in params ) {
 				b.add("--");
 				b.add(boundary);
 				b.add("\r\n");
 				b.add('Content-Disposition: form-data; name="');
-				b.add(p);
+				b.add(p.param);
 				b.add('"');
 				b.add("\r\n");
 				b.add("\r\n");
-				b.add(params.get(p));
+				b.add(p.value);
 				b.add("\r\n");
 			}
 			b.add("--");
@@ -401,12 +414,12 @@ class Http {
 			b.add("Content-Type: "+"application/octet-stream"+"\r\n"+"\r\n");
 			uri = b.toString();
 		} else {
-			for( p in params.keys() ) {
+			for( p in params ) {
 				if( uri == null )
 					uri = "";
 				else
 					uri += "&";
-				uri += StringTools.urlEncode(p)+"="+StringTools.urlEncode(params.get(p));
+				uri += StringTools.urlEncode(p.param)+"="+StringTools.urlEncode(p.value);
 			}
 		}
 
@@ -440,7 +453,7 @@ class Http {
 		if( postData != null )
 			b.add("Content-Length: "+postData.length+"\r\n");
 		else if( post && uri != null ) {
-			if( multipart || headers.get("Content-Type") == null ) {
+			if( multipart || !Lambda.exists(headers, function(h) return h.header == "Content-Type") ) {
 				b.add("Content-Type: ");
 				if( multipart ) {
 					b.add("multipart/form-data");
@@ -455,10 +468,10 @@ class Http {
 			else
 				b.add("Content-Length: "+uri.length+"\r\n");
 		}
-		for( h in headers.keys() ) {
-			b.add(h);
+		for( h in headers ) {
+			b.add(h.header);
 			b.add(": ");
-			b.add(headers.get(h));
+			b.add(h.value);
 			b.add("\r\n");
 		}
 		b.add("\r\n");

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

@@ -184,7 +184,7 @@ class Input {
 			bytes.push(cast readByte());
 			bytes.push(cast readByte());
 			bytes.push(cast readByte());
-			if (bigEndian)
+			if (!bigEndian)
 				bytes.reverse();
 			var sign = 1 - ((bytes[0] >> 7) << 1);
 			var exp = (((bytes[0] << 1) & 0xFF) | (bytes[1] >> 7)) - 127;
@@ -213,7 +213,7 @@ class Input {
 		bytes.push(readByte());
 		bytes.push(readByte());
 		bytes.push(readByte());
-		if (bigEndian)
+		if (!bigEndian)
 			bytes.reverse();
 
 		var sign = 1 - ((bytes[0] >> 7) << 1); // sign = bit 0

+ 12 - 12
std/haxe/io/Output.hx

@@ -133,10 +133,10 @@ class Output {
 		}
 		var exp = Math.floor(Math.log(Math.abs(x)) / LN2);
 		var sig = (Math.floor(Math.abs(x) / Math.pow(2, exp) * (2 << 22)) & 0x7FFFFF);
-		var b1 = (exp + 0x7F) >> 1 | (exp>0 ? ((x<0) ? 1<<7 : 1<<6) : ((x<0) ? 1<<7 : 0)),
-			b2 = (exp + 0x7F) << 7 & 0xFF | (sig >> 16 & 0x7F),
-			b3 = (sig >> 8) & 0xFF,
-			b4 = sig & 0xFF;
+		var b4 = (exp + 0x7F) >> 1 | (exp>0 ? ((x<0) ? 1<<7 : 1<<6) : ((x<0) ? 1<<7 : 0)),
+			b3 = (exp + 0x7F) << 7 & 0xFF | (sig >> 16 & 0x7F),
+			b2 = (sig >> 8) & 0xFF,
+			b1 = sig & 0xFF;
 		if (bigEndian)
 		{
 			writeByte(b4); writeByte(b3); writeByte(b2); writeByte(b1);
@@ -204,14 +204,14 @@ class Output {
 		var sig : Int = Math.floor(Math.abs(x) / Math.pow(2, exp) * Math.pow(2, 52));
 		var sig_h = (sig & cast 34359738367);
 		var sig_l = Math.floor((sig / Math.pow(2,32)));
-		var b1 = (exp + 0x3FF) >> 4 | (exp>0 ? ((x<0) ? 1<<7 : 1<<6) : ((x<0) ? 1<<7 : 0)),
-			b2 = (exp + 0x3FF) << 4 & 0xFF | (sig_l >> 16 & 0xF),
-			b3 = (sig_l >> 8) & 0xFF,
-			b4 = sig_l & 0xFF,
-			b5 = (sig_h >> 24) & 0xFF,
-			b6 = (sig_h >> 16) & 0xFF,
-			b7 = (sig_h >> 8) & 0xFF,
-			b8 = sig_h & 0xFF;
+		var b8 = (exp + 0x3FF) >> 4 | (exp>0 ? ((x<0) ? 1<<7 : 1<<6) : ((x<0) ? 1<<7 : 0)),
+			b7 = (exp + 0x3FF) << 4 & 0xFF | (sig_l >> 16 & 0xF),
+			b6 = (sig_l >> 8) & 0xFF,
+			b5 = sig_l & 0xFF,
+			b4 = (sig_h >> 24) & 0xFF,
+			b3 = (sig_h >> 16) & 0xFF,
+			b2 = (sig_h >> 8) & 0xFF,
+			b1 = sig_h & 0xFF;
 		if (bigEndian)
 		{
 			writeByte(b8); writeByte(b7); writeByte(b6); writeByte(b5);

+ 11 - 10
std/haxe/macro/Build.hx

@@ -68,14 +68,14 @@ class Build {
 				c;
 			case _: Context.error("Underlying type of exposing abstract must be a class", Context.currentPos());
 		}
-		function getIdentName(e) return switch(e.expr) {
-			case EConst(CIdent(s)): s;
-			case _: Context.error("Identifier expected", e.pos);
+		function getIdentNames(e) return switch(e.expr) {
+			case EConst(CIdent(s)): { field : s, newField : s };
+			case EBinop(OpArrow, { expr : EConst(CIdent(s1))}, { expr: EConst(CIdent(s2))}): { field: s1, newField : s2 };
+			case _: Context.error("Identifier or (Identifier => Identifier) expected", e.pos);
 		}
-		function toField(cf:ClassField) {
-			var name = cf.name;
+		function toField(cf:ClassField, oldName:String, newName:String) {
 			return {
-				name: name,
+				name: newName,
 				doc: cf.doc,
 				access: [AStatic, APublic, AInline],
 				pos: cf.pos,
@@ -88,7 +88,7 @@ class Build {
 							type: arg.t.toComplexType(),
 							value: null
 						});
-						var expr = macro return this.$name($a{args.map(function(arg) return macro $i{arg.name})});
+						var expr = macro return this.$oldName($a{args.map(function(arg) return macro $i{arg.name})});
 						args.unshift({name: "this", type: null, opt:false, value: null});
 						FFun({
 							args: args,
@@ -105,7 +105,8 @@ class Build {
 			}
 		}
 		for (fieldExpr in fieldExprs) {
-			var fieldName = getIdentName(fieldExpr);
+			var fieldNames = getIdentNames(fieldExpr);
+			var fieldName = fieldNames.field;
 			var cField = c.findField(fieldName, false);
 			if (cField == null) Context.error('Underlying type has no field $fieldName', fieldExpr.pos);
 			switch(cField.kind) {
@@ -113,9 +114,9 @@ class Build {
 				case _: Context.error("Only function fields can be exposed", fieldExpr.pos);
 			}
 			cField.type = map(cField.type);
-			var field = toField(cField);
+			var field = toField(cField, fieldName, fieldNames.newField);
 			fields.push(field);
 		}
 		return fields;
 	}
-}
+}

+ 13 - 0
std/haxe/macro/Context.hx

@@ -110,6 +110,13 @@ class Context {
 		}
 	}
 
+	/**
+		Returns the current module path in/on which the macro was called.
+	**/
+	public static function getLocalModule() : String {
+		return new String(load("local_module", 0)());
+	}
+	
 	/**
 		Returns the current type in/on which the macro was called.
 		
@@ -344,6 +351,12 @@ class Context {
 		load("define_type", 1)(t);
 	}
 
+	/**
+		Defines a new module with several `TypeDefinition` `types`.
+	**/
+	public static function defineModule( modulePath : String, types : Array<TypeDefinition> ) : Void {
+		load("define_module", 2)(untyped modulePath.__s,untyped types.__neko());
+	}
 
 	/**
 		Returns a syntax-level expression corresponding to typed expression `t`.

+ 7 - 7
std/haxe/macro/Expr.hx

@@ -238,7 +238,7 @@ enum ComplexType {
 typedef TypePath = {
 	var pack : Array<String>;
 	var name : String;
-	var params : Array<TypeParam>;
+	@:optional var params : Array<TypeParam>;
 	@:optional var sub : Null<String>;
 }
 
@@ -257,19 +257,19 @@ typedef Function = {
 	var args : Array<FunctionArg>;
 	var ret : Null<ComplexType>;
 	var expr : Null<Expr>;
-	var params : Array<TypeParamDecl>;
+	@:optional var params : Array<TypeParamDecl>;
 }
 
 typedef FunctionArg = {
 	var name : String;
-	var opt : Bool;
+	@:optional var opt : Bool;
 	var type : Null<ComplexType>;
 	@:optional var value : Null<Expr>;
 }
 
 typedef MetadataEntry = {
 	name : String,
-	params : Array<Expr>,
+	?params : Array<Expr>,
 	pos : Position
 }
 
@@ -304,9 +304,9 @@ typedef TypeDefinition = {
 	var pack : Array<String>;
 	var name : String;
 	var pos : Position;
-	var meta : Metadata;
-	var params : Array<TypeParamDecl>;
-	var isExtern : Bool;
+	@:optional var meta : Metadata;
+	@:optional var params : Array<TypeParamDecl>;
+	@:optional var isExtern : Bool;
 	var kind : TypeDefKind;
 	var fields : Array<Field>;
 }

+ 5 - 0
std/haxe/macro/MacroStringTools.hx

@@ -82,5 +82,10 @@ class MacroStringTools {
 		return if (pack.length == 0) name else pack.join(".") + "." +name;
 	}
 	
+	static public function toComplex( path : String ) : ComplexType {
+		var pack = path.split(".");
+		return TPath( { pack : pack, name : pack.pop(), params : [] } );
+	}
+	
 	#end
 }

+ 1 - 1
std/haxe/macro/Printer.hx

@@ -203,7 +203,7 @@ class Printer {
 		case EDisplay(e1, _): '#DISPLAY(${printExpr(e1)})';
 		case EDisplayNew(tp): '#DISPLAY(${printTypePath(tp)})';
 		case ETernary(econd, eif, eelse): '${printExpr(econd)} ? ${printExpr(eif)} : ${printExpr(eelse)}';
-		case ECheckType(e1, ct): '#CHECK_TYPE(${printExpr(e1)}, ${printComplexType(ct)})';
+		case ECheckType(e1, ct): '(${printExpr(e1)} : ${printComplexType(ct)})';
 		case EMeta(meta, e1): printMetadata(meta) + " " +printExpr(e1);
 	}
 

+ 1 - 1
std/haxe/remoting/FlashJsConnection.hx

@@ -141,7 +141,7 @@ class FlashJsConnection #if flash implements AsyncConnection implements Dynamic<
 
 	static function flashCall( flashObj : String, name : String, path : String, params : String ) : String {
 		try {
-			var fobj : Dynamic = (untyped js.Browser.document)[__data.flash]; // FIXME(bruno): Why is this necessary?
+			var fobj : Dynamic = untyped (untyped js.Browser.document)[__data.flash]; // FIXME(bruno): Why is this necessary?
 			if( fobj == null ) fobj = js.Browser.document.getElementById(flashObj);
 			if( fobj == null ) throw "Could not find flash object '"+flashObj+"'";
 			var data = null;

+ 1 - 1
std/java/vm/Gc.hx

@@ -10,6 +10,6 @@ package java.vm;
 	public static function stats() : { heap : Int, free : Int }
 	{
 		var r = java.lang.Runtime.getRuntime();
-		return { heap : r.totalMemory(), free : r.freeMemory() };
+		return { heap : cast r.totalMemory(), free : cast r.freeMemory() };
 	}
 }

+ 2 - 2
std/js/Boot.hx

@@ -41,8 +41,8 @@ class Boot {
 			var d;
 			if( __js__("typeof")(document) != "undefined" && (d = document.getElementById("haxe:trace")) != null )
 				d.innerHTML += __unhtml(msg)+"<br/>";
-			else if( __js__("typeof")(console) != "undefined" && console.log != null )
-				console.log(msg);
+			else if( __js__("typeof console") != "undefined" && __js__("console").log != null )
+				__js__("console").log(msg);
 			#end
 		}
 	}

+ 43 - 29
std/js/Scroll.hx → std/js/Error.hx

@@ -21,34 +21,48 @@
  */
 package js;
 
-import js.Browser.*;
-
-class Scroll {
-
-	public static function getTop() : Int {
-		var sy = window.pageYOffset;
-		if( untyped __js__("typeof")(sy) == 'number' )
-			return sy;
-		if( document.body ) {
-			sy = document.body.scrollTop;
-			if( sy ) return sy;
-		}
-		return document.documentElement.scrollTop;
-	}
-
-	public static function getLeft() : Int {
-		var sx = window.pageXOffset;
-		if( untyped __js__("typeof")(sx) == 'number' )
-			return sx;
-		if( document.body ) {
-			sx = document.body.scrollLeft;
-			if( sx ) return sx;
-		}
-		return document.documentElement.scrollLeft;
-	}
-
-	inline public static function set(left:Int,top:Int) {
-		window.scroll(left,top);
-	}
+@:native("Error")
+extern class Error
+{
+	var message : String;
+	var name : String;
+	var stack(default,null) : String;
 
+	function new(?message : String) : Void;
+}
+
+@:native("EvalError")
+extern class EvalError extends Error
+{
+	function new(?message : String) : Void;
+}
+
+@:native("RangeError")
+extern class RangeError extends Error
+{
+	function new(?message : String) : Void;
+}
+
+@:native("ReferenceError")
+extern class ReferenceError extends Error
+{
+	function new(?message : String) : Void;
+}
+
+@:native("SyntaxError")
+extern class SyntaxError extends Error
+{
+	function new(?message : String) : Void;
+}
+
+@:native("TypeError")
+extern class TypeError extends Error
+{
+	function new(?message : String) : Void;
+}
+
+@:native("URIError")
+extern class URIError extends Error
+{
+	function new(?message : String) : Void;
 }

+ 10 - 2
std/neko/_std/Reflect.hx

@@ -46,8 +46,16 @@
 		}
 	}
 
-	public inline static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
-		return $call(func,o,args.__neko());
+	public static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
+		var a = args.__neko();
+		// pad missing args with null's
+		var n = $nargs(func);
+		if( n > $asize(a) ) {
+			var a2 = $amake(n);
+			$ablit(a2,0,a,0,$asize(a));
+			a = a2;
+		}
+		return $call(func,o,a);
 	}
 
 	public static function fields( o : Dynamic ) : Array<String> untyped {

+ 7 - 5
std/neko/_std/Type.hx

@@ -97,13 +97,15 @@ enum ValueType {
 
 	public static function createInstance<T>( cl : Class<T>, args : Array<Dynamic> ) : T untyped {
 		var fnew = $objget(cl,$hash("new".__s));
+		var a = args.__neko();
+		// pad missing args with null's
 		var n = $nargs(fnew);
-		if( args.length < n ) {
-			args = args.copy();
-			while( args.length < n )
-				args.push(null);
+		if( n > $asize(a) ) {
+			var a2 = $amake(n);
+			$ablit(a2,0,a,0,$asize(a));
+			a = a2;
 		}
-		return $call(fnew,cl,args.__neko());
+		return $call(fnew,cl,a);
 	}
 
 	public static function createEmptyInstance<T>( cl : Class<T> ) : T untyped {

+ 1 - 1
std/neko/_std/sys/net/Socket.hx

@@ -150,7 +150,7 @@ class Socket {
 			socket_connect(__s, host.ip, port);
 		} catch( s : String ) {
 			if( s == "std@socket_connect" )
-				throw "Failed to connect on "+(try host.reverse() catch( e : Dynamic ) host.toString())+":"+port;
+				throw "Failed to connect on "+host.toString()+":"+port;
 			else
 				neko.Lib.rethrow(s);
 		}

+ 1 - 1
tests/unit/Test.hx

@@ -258,7 +258,7 @@ class Test #if swf_mark implements mt.Protect #end {
 			#if ((dce == "full") && !interp && !as3)
 			new TestDCE(),
 			#end
-			#if (java && !macro)
+			#if ( (java || neko) && !macro && !interp)
 			new TestThreads(),
 			#end
 			//new TestUnspecified(),

+ 23 - 8
type.ml

@@ -292,6 +292,7 @@ and module_kind =
 	| MCode
 	| MMacro
 	| MFake
+	| MSub
 
 and dt =
 	| DTSwitch of texpr * (texpr * dt) list * dt option
@@ -479,18 +480,18 @@ and s_type_params ctx = function
 	| [] -> ""
 	| l -> "<" ^ String.concat ", " (List.map (s_type ctx) l) ^ ">"
 
-let s_access = function
+let s_access is_read = function
 	| AccNormal -> "default"
 	| AccNo -> "null"
 	| AccNever -> "never"
 	| AccResolve -> "resolve"
-	| AccCall -> "accessor"
+	| AccCall -> if is_read then "get" else "set"
 	| AccInline	-> "inline"
 	| AccRequire (n,_) -> "require " ^ n
 
 let s_kind = function
 	| Var { v_read = AccNormal; v_write = AccNormal } -> "var"
-	| Var v -> "(" ^ s_access v.v_read ^ "," ^ s_access v.v_write ^ ")"
+	| Var v -> "(" ^ s_access true v.v_read ^ "," ^ s_access false v.v_write ^ ")"
 	| Method m ->
 		match m with
 		| MethNormal -> "method"
@@ -638,7 +639,10 @@ let rec is_nullable ?(no_lazy=false) = function
 
 	| TInst ({ cl_kind = KTypeParameter },_) -> false
 *)
-	| TAbstract (a,_) -> not (Meta.has Meta.NotNull a.a_meta)
+	| TAbstract (a,_) when Meta.has Meta.CoreType a.a_meta ->
+		not (Meta.has Meta.NotNull a.a_meta)
+	| TAbstract (a,tl) ->
+		is_nullable (apply_params a.a_types tl a.a_this)
 	| _ ->
 		true
 
@@ -895,7 +899,7 @@ let abstract_cast_stack = ref []
 let is_extern_field f =
 	match f.cf_kind with
 	| Method _ -> false
-	| Var { v_read = AccNormal | AccNo } | Var { v_write = AccNormal | AccNo } -> false
+	| Var { v_read = AccNormal | AccInline | AccNo } | Var { v_write = AccNormal | AccNo } -> false
 	| _ -> not (Meta.has Meta.IsVar f.cf_meta)
 
 let field_type f =
@@ -1273,11 +1277,22 @@ and unify_types a b tl1 tl2 =
 			type_eq EqRightDynamic t1 t2
 		with Unify_error l ->
 			let err = cannot_unify a b in
+			let allows_variance_to t (tf,cfo) = match cfo with
+				| None -> type_iseq tf t
+				| Some _ -> false
+			in
 			(try (match follow t1, follow t2 with
 				| TAbstract({a_impl = Some _} as a1,pl1),TAbstract({a_impl = Some _ } as a2,pl2) ->
-					type_eq EqStrict (apply_params a1.a_types pl1 a1.a_this) (apply_params a2.a_types pl2 a2.a_this)
-				| TAbstract({a_impl = Some _} as a,pl),t -> type_eq EqStrict (apply_params a.a_types pl a.a_this) t
-				| t,TAbstract({a_impl = Some _ } as a,pl) -> type_eq EqStrict t (apply_params a.a_types pl a.a_this)
+					let ta1 = apply_params a1.a_types pl1 a1.a_this in
+					let ta2 = apply_params a2.a_types pl2 a2.a_this in
+					type_eq EqStrict ta1 ta2;
+					if not (List.exists (allows_variance_to ta2) a1.a_to) && not (List.exists (allows_variance_to ta1) a2.a_from) then raise (Unify_error l)
+				| TAbstract({a_impl = Some _} as a,pl),t ->
+					type_eq EqStrict (apply_params a.a_types pl a.a_this) t;
+					if not (List.exists (allows_variance_to t) a.a_to) then raise (Unify_error l)
+				| t,TAbstract({a_impl = Some _ } as a,pl) ->
+					type_eq EqStrict t (apply_params a.a_types pl a.a_this);
+					if not (List.exists (allows_variance_to t) a.a_from) then raise (Unify_error l)
 				| _ -> raise (Unify_error l))
 			with Unify_error _ ->
 				error (err :: (Invariant_parameter (t1,t2)) :: l))

+ 4 - 4
typecore.ml

@@ -142,7 +142,7 @@ let type_expr_ref : (typer -> Ast.expr -> with_type -> texpr) ref = ref (fun _ _
 let type_module_type_ref : (typer -> module_type -> t list option -> pos -> texpr) ref = ref (fun _ _ _ _ -> assert false)
 let unify_min_ref : (typer -> texpr list -> t) ref = ref (fun _ _ -> assert false)
 let match_expr_ref : (typer -> Ast.expr -> (Ast.expr list * Ast.expr option * Ast.expr option) list -> Ast.expr option option -> with_type -> Ast.pos -> decision_tree) ref = ref (fun _ _ _ _ _ _ -> assert false)
-let get_pattern_locals_ref : (typer -> Ast.expr -> Type.t -> (string, tvar) PMap.t) ref = ref (fun _ _ _ -> assert false)
+let get_pattern_locals_ref : (typer -> Ast.expr -> Type.t -> (string, tvar * pos) PMap.t) ref = ref (fun _ _ _ -> assert false)
 let get_constructor_ref : (typer -> tclass -> t list -> Ast.pos -> (t * tclass_field)) ref = ref (fun _ _ _ _ -> assert false)
 let check_abstract_cast_ref : (typer -> t -> texpr -> Ast.pos -> texpr) ref = ref (fun _ _ _ _ -> assert false)
 
@@ -214,11 +214,11 @@ let unify_error_msg ctx = function
 		(match a, b with
 		| Var va, Var vb ->
 			let name, stra, strb = if va.v_read = vb.v_read then
-				"setter", s_access va.v_write, s_access vb.v_write
+				"setter", s_access false va.v_write, s_access false vb.v_write
 			else if va.v_write = vb.v_write then
-				"getter", s_access va.v_read, s_access vb.v_read
+				"getter", s_access true va.v_read, s_access true vb.v_read
 			else
-				"access", "(" ^ s_access va.v_read ^ "," ^ s_access va.v_write ^ ")", "(" ^ s_access vb.v_read ^ "," ^ s_access vb.v_write ^ ")"
+				"access", "(" ^ s_access true va.v_read ^ "," ^ s_access false va.v_write ^ ")", "(" ^ s_access true vb.v_read ^ "," ^ s_access false vb.v_write ^ ")"
 			in
 			"Inconsistent " ^ name ^ " for field " ^ f ^ " : " ^ stra ^ " should be " ^ strb
 		| _ ->

+ 92 - 8
typer.ml

@@ -166,6 +166,28 @@ let rec is_pos_infos = function
 	| _ ->
 		false
 
+let check_constraints ctx tname tpl tl map p =
+	List.iter2 (fun m (name,t) ->
+		match follow t with
+		| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
+			delay ctx PCheckConstraint (fun() ->
+				List.iter (fun ct ->
+					try
+						Type.unify (map m) (map ct)
+					with Unify_error l ->
+						display_error ctx (error_msg (Unify (Constraint_failure (tname ^ "." ^ name) :: l))) p;
+				) constr
+			);
+		| _ ->
+			()
+	) tl tpl
+
+let enum_field_type ctx en ef tl_en tl_ef p =
+	let map t = apply_params en.e_types tl_en (apply_params ef.ef_params tl_ef t) in
+	check_constraints ctx (s_type_path en.e_path) en.e_types tl_en map p;
+	check_constraints ctx ef.ef_name ef.ef_params tl_ef map p;
+	map ef.ef_type
+
 let add_constraint_checks ctx ctypes pl f tl p =
 	List.iter2 (fun m (name,t) ->
 		match follow t with
@@ -1068,7 +1090,9 @@ let rec type_ident_raise ?(imported_enums=true) ctx i p mode =
 					try
 						let ef = PMap.find i e.e_constrs in
 						let et = type_module_type ctx t None p in
-						mk (TField (et,FEnum (e,ef))) (monomorphs ef.ef_params (monomorphs e.e_types ef.ef_type)) p
+						let monos = List.map (fun _ -> mk_mono()) e.e_types in
+						let monos2 = List.map (fun _ -> mk_mono()) ef.ef_params in
+						mk (TField (et,FEnum (e,ef))) (enum_field_type ctx e ef monos monos2 p) p
 					with
 						Not_found -> loop l
 		in
@@ -2287,11 +2311,21 @@ and type_expr ctx (e,p) (with_type:with_type) =
 				| TEnum (e,pl) ->
 					(try
 						let ef = PMap.find s e.e_constrs in
-						mk (fast_enum_field e ef p) (apply_params e.e_types pl (monomorphs ef.ef_params ef.ef_type)) p
+						let monos = List.map (fun _ -> mk_mono()) ef.ef_params in
+						mk (fast_enum_field e ef p) (enum_field_type ctx e ef pl monos p) p
 					with Not_found ->
 						if ctx.untyped then raise Not_found;
 						with_type_error ctx with_type (string_error s e.e_names ("Identifier '" ^ s ^ "' is not part of enum " ^ s_type_path e.e_path)) p;
 						mk (TConst TNull) t p)
+				| TAbstract (a,pl) when has_meta Meta.FakeEnum a.a_meta ->
+					let cimpl = (match a.a_impl with None -> assert false | Some c -> c) in
+					(try
+						let cf = PMap.find s cimpl.cl_statics in
+						acc_get ctx (type_field ctx (mk (TTypeExpr (TClassDecl cimpl)) (TAnon { a_fields = PMap.add cf.cf_name cf PMap.empty; a_status = ref (Statics cimpl) }) p) s p MGet) p
+					with Not_found ->
+						if ctx.untyped then raise Not_found;
+						with_type_error ctx with_type (string_error s (List.map (fun f -> f.cf_name) cimpl.cl_ordered_statics) ("Identifier '" ^ s ^ "' is not part of enum " ^ s_type_path a.a_path)) p;
+						mk (TConst TNull) t p)
 				| _ -> raise Not_found)
 			| _ ->
 				raise Not_found)
@@ -2356,11 +2390,13 @@ and type_expr ctx (e,p) (with_type:with_type) =
 			let rec loop (l,acc) (f,e) =
 				let f,add = object_field f in
 				if PMap.mem f acc then error ("Duplicate field in object declaration : " ^ f) p;
-				if f.[0] = '$' then error "Field names starting with a dollar are not allowed" p;
 				let e = type_expr ctx e Value in
 				(match follow e.etype with TAbstract({a_path=[],"Void"},_) -> error "Fields of type Void are not allowed in structures" e.epos | _ -> ());
 				let cf = mk_field f e.etype e.epos in
-				((f,e) :: l, if add then PMap.add f cf acc else acc)
+				((f,e) :: l, if add then begin
+					if f.[0] = '$' then error "Field names starting with a dollar are not allowed" p;
+					PMap.add f cf acc
+				end else acc)
 			in
 			let fields , types = List.fold_left loop ([],PMap.empty) fl in
 			let x = ref Const in
@@ -2372,7 +2408,6 @@ and type_expr ctx (e,p) (with_type:with_type) =
 			let fl = List.map (fun (n, e) ->
 				let n,add = object_field n in
 				if PMap.mem n !fields then error ("Duplicate field in object declaration : " ^ n) p;
-				if n.[0] = '$' then error "Field names starting with a dollar are not allowed" p;
 				let e = try
 					let t = (PMap.find n a.a_fields).cf_type in
 					let e = Codegen.Abstract.check_cast ctx t (type_expr ctx e (match with_type with WithTypeResume _ -> WithTypeResume t | _ -> WithType t)) p in
@@ -2383,6 +2418,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 					type_expr ctx e Value
 				in
 				if add then begin
+					if n.[0] = '$' then error "Field names starting with a dollar are not allowed" p;
 					let cf = mk_field n e.etype e.epos in
 					fields := PMap.add n cf !fields;
 				end;
@@ -2807,6 +2843,8 @@ and type_expr ctx (e,p) (with_type:with_type) =
 				| _ -> ())
 			in
 			loop t
+		| NoValue ->
+			if name = None then display_error ctx "Unnamed lvalue functions are not supported" p
 		| _ ->
 			());
 		let ft = TFun (fun_args args,rt) in
@@ -2908,6 +2946,9 @@ and type_expr ctx (e,p) (with_type:with_type) =
 				if field_name fa = "bind" then (match follow e1.etype with
 					| TFun(args,ret) -> {e1 with etype = opt_args args ret}
 					| _ -> e)
+				else if field_name fa = "match" then (match follow e1.etype with
+					| TEnum _ as t -> {e1 with etype = tfun [t] ctx.t.tbool }
+					| _ -> e)
 				else if mode = "position" then (match extract_field fa with
 					| None -> e
 					| Some cf -> raise (Typecore.DisplayPosition [cf.cf_pos]))
@@ -2986,6 +3027,9 @@ and type_expr ctx (e,p) (with_type:with_type) =
 				let t = opt_args args ret in
 				let cf = mk_field "bind" (tfun [t] t) p in
 				PMap.add "bind" cf PMap.empty
+			| TEnum(_) as t ->
+				let cf = mk_field "match" (tfun [t] ctx.t.tbool) p in
+				PMap.add "match" cf PMap.empty
 			| _ ->
 				PMap.empty
 		in
@@ -3112,6 +3156,15 @@ and type_call ctx e el (with_type:with_type) p =
 		let e = type_expr ctx e Value in
 		ctx.com.warning (s_type (print_context()) e.etype) e.epos;
 		e
+	| (EField(e,"match"),p), [epat] ->
+		let et = type_expr ctx e Value in
+		(match follow et.etype with
+			| TEnum _ as t ->
+				let e = match_expr ctx e [[epat],None,Some (EConst(Ident "true"),p)] (Some (Some (EConst(Ident "false"),p))) (WithType ctx.t.tbool) p in
+				let locals = !get_pattern_locals_ref ctx epat t in
+				PMap.iter (fun _ (_,p) -> display_error ctx "Capture variables are not allowed" p) locals;
+				Codegen.PatternMatchConversion.to_typed_ast ctx e p
+			| _ -> def ())
 	| (EConst (Ident "__unprotect__"),_) , [(EConst (String _),_) as e] ->
 		let e = type_expr ctx e Value in
 		if Common.platform ctx.com Flash then
@@ -3660,9 +3713,40 @@ let make_macro_api ctx p =
 		);
 		Interp.define_type = (fun v ->
 			let m, tdef, pos = (try Interp.decode_type_def v with Interp.Invalid_expr -> Interp.exc (Interp.VString "Invalid type definition")) in
-			let mdep = Typeload.type_module ctx m ctx.m.curmod.m_extra.m_file [tdef,pos] pos in
-			mdep.m_extra.m_kind <- MFake;
-			add_dependency mdep ctx.m.curmod;
+			let prev = (try Some (Hashtbl.find ctx.g.modules m) with Not_found -> None) in
+			let mnew = Typeload.type_module ctx m ctx.m.curmod.m_extra.m_file [tdef,pos] pos in
+			add_dependency mnew ctx.m.curmod;
+			(* if we defined a type in an existing module, let's move the types here *)
+			(match prev with
+			| None ->
+				mnew.m_extra.m_kind <- MFake;
+			| Some mold ->
+				Hashtbl.replace ctx.g.modules mnew.m_path mold;
+				mold.m_types <- mold.m_types @ mnew.m_types;
+				mnew.m_extra.m_kind <- MSub;
+				add_dependency mold mnew;
+			);
+		);
+		Interp.define_module = (fun m types ->
+			let types = List.map (fun v ->
+				let _, tdef, pos = (try Interp.decode_type_def v with Interp.Invalid_expr -> Interp.exc (Interp.VString "Invalid type definition")) in
+				tdef, pos
+			) types in
+			let m = Ast.parse_path m in
+			let pos = (match types with [] -> Ast.null_pos | (_,p) :: _ -> p) in
+			let prev = (try Some (Hashtbl.find ctx.g.modules m) with Not_found -> None) in
+			let mnew = Typeload.type_module ctx m ctx.m.curmod.m_extra.m_file types pos in
+			add_dependency mnew ctx.m.curmod;
+			(* if we defined a type in an existing module, let's move the types here *)
+			(match prev with
+			| None ->
+				mnew.m_extra.m_kind <- MFake;
+			| Some mold ->
+				Hashtbl.replace ctx.g.modules mnew.m_path mold;
+				mold.m_types <- mold.m_types @ mnew.m_types;
+				mnew.m_extra.m_kind <- MSub;
+				add_dependency mold mnew;
+			);
 		);
 		Interp.module_dependency = (fun mpath file ismacro ->
 			let m = typing_timer ctx (fun() -> Typeload.load_module ctx (parse_path mpath) p) in