Browse Source

Merge branch 'development' into genpy

Conflicts:
	.travis.yml
Simon Krajewski 11 năm trước cách đây
mục cha
commit
90b4419a48

+ 1 - 1
Makefile.win

@@ -12,7 +12,7 @@ else
 endif
 
 kill:
-	-@taskkill /F /IM haxe.exe 2>/dev/null
+	-@taskkill /F /IM haxe.exe
 
 # allow Ocaml/Mingw as well
 NATIVE_LIBS += -I "c:/program files/mingw/lib/"

+ 9 - 7
README.md

@@ -23,7 +23,7 @@ You can try Haxe directly from your browser at [try.haxe.org](http://try.haxe.or
 
 For more information about Haxe, head to the [offical Haxe website](http://haxe.org).
 
-## License 
+## License
 
 The Haxe project has several licenses, covering different parts of the projects.
 
@@ -35,13 +35,15 @@ For the complete Haxe licenses, please see http://haxe.org/doc/license or [extra
 
 ## Installing Haxe
 
-The latest stable release is [Haxe v3.1.1](http://haxe.org/download). Pre-built binaries are available for your platform:
+The latest stable release is [Haxe v3.1.2](http://haxe.org/download). Pre-built binaries are available for your platform:
+
+ * **[Windows installer](http://haxe.org/file/haxe-3.1.2-win.exe)**
+ * **[Windows binaries](http://haxe.org/file/haxe-3.1.2-win.zip)**
+ * **[OSX installer](http://haxe.org/file/haxe-3.1.2-osx-installer.pkg)**
+ * **[OSX binaries](http://haxe.org/file/haxe-3.1.2-osx.tar.gz)**
+ * **[Linux 32-bit binaries](http://haxe.org/file/haxe-3.1.2-linux32.tar.gz)**
+ * **[Linux 64-bit binaries](http://haxe.org/file/haxe-3.1.2-linux64.tar.gz)**
 
- * **[Windows installer](http://haxe.org/file/haxe-3.1.1-win.exe)**
- * **[OSX installer](http://haxe.org/file/haxe-3.1.1-osx-installer.pkg)**
- * **[Linux 32-bit binaries](http://haxe.org/file/haxe-3.1.1-linux32.tar.gz)**
- * **[Linux 64-bit binaries](http://haxe.org/file/haxe-3.1.1-linux64.tar.gz)**
- 
 Automated development builds are available from [build.haxe.org](http://build.haxe.org).
 
 ## Building from source

+ 1 - 1
ast.ml

@@ -53,7 +53,7 @@ module Meta = struct
 		| Debug
 		| Decl
 		| DefParam
-    | Delegate
+		| Delegate
 		| Depend
 		| Deprecated
 		| DynamicObject

+ 20 - 15
codegen.ml

@@ -47,15 +47,6 @@ let binop op a b t p =
 let index com e index t p =
 	mk (TArray (e,mk (TConst (TInt (Int32.of_int index))) com.basic.tint p)) t p
 
-let concat e1 e2 =
-	let e = (match e1.eexpr, e2.eexpr with
-		| TBlock el1, TBlock el2 -> TBlock (el1@el2)
-		| TBlock el, _ -> TBlock (el @ [e2])
-		| _, TBlock el -> TBlock (e1 :: el)
-		| _ , _ -> TBlock [e1;e2]
-	) in
-	mk e e2.etype (punion e1.epos e2.epos)
-
 let type_constant com c p =
 	let t = com.basic in
 	match c with
@@ -398,7 +389,7 @@ let rec build_generic ctx c p tl =
 					| _ -> assert false)
 				| _ -> Some(cs,pl)
 		);
-		Typeload.add_constructor ctx cg p;
+		Typeload.add_constructor ctx cg false p;
 		cg.cl_kind <- KGenericInstance (c,tl);
 		cg.cl_interface <- c.cl_interface;
 		cg.cl_constructor <- (match cg.cl_constructor, c.cl_constructor, c.cl_super with
@@ -514,14 +505,28 @@ let build_metadata com t =
 (* -------------------------------------------------------------------------- *)
 (* MACRO TYPE *)
 
-let get_macro_path e args p =
+let get_macro_path ctx e args p =
 	let rec loop e =
 		match fst e with
 		| EField (e,f) -> f :: loop e
 		| EConst (Ident i) -> [i]
 		| _ -> error "Invalid macro call" p
 	in
-	(match loop e with
+	let path = match e with
+		| (EConst(Ident i)),_ ->
+			let path = try
+				if not (PMap.mem i ctx.curclass.cl_statics) then raise Not_found;
+				ctx.curclass.cl_path
+			with Not_found -> try
+				(t_infos (fst (PMap.find i ctx.m.module_globals))).mt_path
+			with Not_found ->
+				error "Invalid macro call" p
+			in
+			i :: (snd path) :: (fst path)
+		| _ ->
+			loop e
+	in
+	(match path with
 	| meth :: cl :: path -> (List.rev path,cl), meth, args
 	| _ -> error "Invalid macro call" p)
 
@@ -529,7 +534,7 @@ let build_macro_type ctx pl p =
 	let path, field, args = (match pl with
 		| [TInst ({ cl_kind = KExpr (ECall (e,args),_) },_)]
 		| [TInst ({ cl_kind = KExpr (EArrayDecl [ECall (e,args),_],_) },_)] ->
-			get_macro_path e args p
+			get_macro_path ctx e args p
 		| _ ->
 			error "MacroType requires a single expression call parameter" p
 	) in
@@ -543,7 +548,7 @@ let build_macro_type ctx pl p =
 
 let build_macro_build ctx c pl cfl p =
 	let path, field, args = match Meta.get Meta.GenericBuild c.cl_meta with
-		| _,[ECall(e,args),_],_ -> get_macro_path e args p
+		| _,[ECall(e,args),_],_ -> get_macro_path ctx e args p
 		| _ -> error "genericBuild requires a single expression call parameter" p
 	in
 	let old = ctx.ret,ctx.g.get_build_infos in
@@ -1615,4 +1620,4 @@ module UnificationCallback = struct
 				etf
 			| _ ->
 				check (Type.map_expr (run f) e)
-end;;
+end;;

+ 15 - 2
extra/CHANGES.txt

@@ -1,15 +1,28 @@
-2014-??-??: 3.1.2
+2014-03-29: 3.1.2
 
 	Bugfixes:
 
-	all : properly disallowed usage of super as value
 	all : disallowed spaces between >>, >>>, >>= and >>>=
+	all : fix branching issue when switching on Dynamic values with only one case
+	all : added missing abstract cast call when checking for equality
+	all : fixed member fields initializations on parent classes that have no constructor
+	all : fixed toString usage of abstracts which are argument to Std.string
+	flash : avoid rare FP 12 PPAPI JIT crash
 	cpp : fixed bug in side-effect handler which caused incorrect behavior of while loops
+	js : fixed missing print function for enum values with DCE
+	macro : make sure member field initializations are respected
 
 	General improvements and optimizations:
 
 	all : cached file exist checks to speed up compilations with a lot of class paths
+	all : improved completion related to super class fields
 	all : allowed iterating on abstract which have get_length and @:arrayAccess fields
+	js : improved Type.allEnums implementation to avoid issues with obfuscation
+
+	Standard Library:
+
+	all : added haxe.io.Bytes.readDouble/Float
+	all : added haxe.io.BytesBuffer.addString/Float/Double
 
 2014-03-15: 3.1.1
 

+ 2 - 2
extra/release-checklist.txt

@@ -1,8 +1,8 @@
-- Make sure CHANGES.txt has a proper date set.
+- Make sure CHANGES.txt has a proper date set!
 - Make sure `version` in main.ml has the correct value.
 - Merge development branch into master.
 - Wait for Travis to greenlight master.
-- Tag master.
+- Tag master as MAJOR.MINOR.PATCH.
 - Wait for builds.haxe.org to build master.
 - If required, tell Caue to fix builds.haxe.org.
 - Get https://github.com/waneck/hxbuilds/tree/master/release-helper

+ 4 - 4
filters.ml

@@ -120,7 +120,7 @@ let handle_side_effects com gen_temp e =
 			let e_break = mk TBreak t_dynamic p in
 			let e_not = mk (TUnop(Not,Prefix,Codegen.mk_parent e1)) e1.etype e1.epos in
 			let e_if = mk (TIf(e_not,e_break,None)) com.basic.tvoid p in
-			let e_block = if flag = NormalWhile then Codegen.concat e_if e2 else Codegen.concat e2 e_if in
+			let e_block = if flag = NormalWhile then Type.concat e_if e2 else Type.concat e2 e_if in
 			let e_true = mk (TConst (TBool true)) com.basic.tbool p in
 			let e = mk (TWhile(Codegen.mk_parent e_true,e_block,NormalWhile)) e.etype p in
 			loop e
@@ -493,13 +493,13 @@ let captured_vars com e =
 			let vtmp = mk_var v used in
 			let it = wrap used it in
 			let expr = wrap used expr in
-			mk (TFor (vtmp,it,Codegen.concat (mk_init v vtmp e.epos) expr)) e.etype e.epos
+			mk (TFor (vtmp,it,Type.concat (mk_init v vtmp e.epos) expr)) e.etype e.epos
 		| TTry (expr,catchs) ->
 			let catchs = List.map (fun (v,e) ->
 				let e = wrap used e in
 				try
 					let vtmp = mk_var v used in
-					vtmp, Codegen.concat (mk_init v vtmp e.epos) e
+					vtmp, Type.concat (mk_init v vtmp e.epos) e
 				with Not_found ->
 					v, e
 			) catchs in
@@ -547,7 +547,7 @@ let captured_vars com e =
 			let fargs = List.map (fun (v,o) ->
 				if PMap.mem v.v_id used then
 					let vtmp = mk_var v used in
-					fexpr := Codegen.concat (mk_init v vtmp e.epos) !fexpr;
+					fexpr := Type.concat (mk_init v vtmp e.epos) !fexpr;
 					vtmp, o
 				else
 					v, o

+ 2 - 0
genas3.ml

@@ -417,9 +417,11 @@ let rec gen_call ctx e el r =
 		spr ctx " is ";
 		gen_value ctx e2;
 	| TLocal { v_name = "__in__" } , [e1;e2] ->
+		spr ctx "(";
 		gen_value ctx e1;
 		spr ctx " in ";
 		gen_value ctx e2;
+		spr ctx ")"
 	| TLocal { v_name = "__as__" }, [e1;e2] ->
 		gen_value ctx e1;
 		spr ctx " as ";

+ 9 - 9
gencommon.ml

@@ -2056,7 +2056,7 @@ struct
                           { e with eexpr = TBlock( (add_fn hd) :: tl ) }
                         | _ ->
                           { e with eexpr = TBlock( funs @ (hd :: tl) ) })
-                      | _ -> Codegen.concat { e with eexpr = TBlock(funs) } e
+                      | _ -> Type.concat { e with eexpr = TBlock(funs) } e
                     in
                     let tf_expr = add_fn (mk_block tf.tf_expr) in
                     { e with eexpr = TFunction({ tf with tf_expr = tf_expr }) }
@@ -2645,7 +2645,7 @@ struct
                   | [] ->
                     match catchall with
                       | Some (v,s) ->
-                        Codegen.concat { eexpr = TVar(v, Some(catchall_local)); etype = gen.gcon.basic.tvoid; epos = pos } s
+                        Type.concat { eexpr = TVar(v, Some(catchall_local)); etype = gen.gcon.basic.tvoid; epos = pos } s
                       | None ->
                         mk_block (rethrow_expr temp_local)
                 in
@@ -3430,7 +3430,7 @@ struct
         *)
         let real_get_args = gen.gexpr_filters#run_f { eexpr = TBlock(get_args); etype = basic.tvoid; epos = pos } in
 
-        let func_expr = Codegen.concat real_get_args tf_expr in
+        let func_expr = Type.concat real_get_args tf_expr in
 
         (* set invoke function *)
         (* todo properly abstract how naming for invoke is made *)
@@ -5133,7 +5133,7 @@ struct
     let block = if flag = Ast.NormalWhile then
       { e1 with eexpr = TIf(cond, e1, Some({ e1 with eexpr = TBreak; etype = basic.tvoid })) }
     else
-      Codegen.concat e1 { e1 with
+      Type.concat e1 { e1 with
         eexpr = TIf({
           eexpr = TUnop(Ast.Not, Ast.Prefix, mk_paren cond);
           etype = basic.tbool;
@@ -9043,7 +9043,7 @@ struct
               {
                 eexpr = TWhile(
                   { eexpr = TCall(mk_access gen temp "hasNext" in_expr.epos, []); etype = basic.tbool; epos = in_expr.epos },
-                  Codegen.concat ({
+                  Type.concat ({
                     eexpr = TVar(var, Some({ eexpr = TCall(mk_access gen temp "next" in_expr.epos, []); etype = var.v_type; epos = in_expr.epos }));
                     etype = basic.tvoid;
                     epos = in_expr.epos
@@ -9720,7 +9720,7 @@ struct
       (fun (expr,kind) ->
         match kind with
           | Normal when has_fallback expr -> expr
-          | Normal -> Codegen.concat expr (mk_sbreak expr.epos)
+          | Normal -> Type.concat expr (mk_sbreak expr.epos)
           | BreaksLoop | BreaksFunction -> expr
       )
     else
@@ -9759,7 +9759,7 @@ struct
         | TFunction tf ->
           let changed, kind = process_expr tf.tf_expr in
           let changed = if handle_not_final_returns && not (is_void tf.tf_type) && kind <> BreaksFunction then
-            Codegen.concat changed { eexpr = TReturn( Some (null tf.tf_type expr.epos) ); etype = basic.tvoid; epos = expr.epos }
+            Type.concat changed { eexpr = TReturn( Some (null tf.tf_type expr.epos) ); etype = basic.tvoid; epos = expr.epos }
           else
             changed
           in
@@ -9977,7 +9977,7 @@ struct
                   { tf.tf_expr with eexpr = TBlock((if !found then { super with eexpr = TCall(e1,args) } else super) :: !block @ tl) }
                 | _ -> assert false)
               with | Not_found ->
-                Codegen.concat { tf.tf_expr with eexpr = TBlock(!block); etype = basic.tvoid } tf.tf_expr
+                Type.concat { tf.tf_expr with eexpr = TBlock(!block); etype = basic.tvoid } tf.tf_expr
             in
 
             args := fun_args tf_args;
@@ -10541,7 +10541,7 @@ struct
                 f.cf_expr <- Some({ e with
                   eexpr = TFunction({ tf with
                     tf_args = List.rev new_args;
-                    tf_expr = Codegen.concat { eexpr = TBlock(List.map (fun (v,ve) -> { eexpr = TVar(v,ve); etype = gen.gcon.basic.tvoid; epos = e.epos }) vardecl); etype = gen.gcon.basic.tvoid; epos = e.epos } tf.tf_expr
+                    tf_expr = Type.concat { eexpr = TBlock(List.map (fun (v,ve) -> { eexpr = TVar(v,ve); etype = gen.gcon.basic.tvoid; epos = e.epos }) vardecl); etype = gen.gcon.basic.tvoid; epos = e.epos } tf.tf_expr
                   });
                 });
                 f

+ 1 - 0
gencpp.ml

@@ -4603,6 +4603,7 @@ let generate_source common_ctx =
 		let cmd = ref "haxelib run hxcpp Build.xml haxe" in
 		if (common_ctx.debug) then cmd := !cmd ^ " -Ddebug";
       cmd := !cmd ^ !cmd_defines;
+      cmd := List.fold_left (fun cmd path -> cmd ^ " -I" ^ (escape_command path) ) !cmd common_ctx.class_path;
       print_endline !cmd;
 		if common_ctx.run_command !cmd <> 0 then failwith "Build failed";
 		Sys.chdir old_dir;

+ 1 - 1
gencs.ml

@@ -2589,7 +2589,7 @@ let configure gen =
         let exc_field = mk_static_field_access_infer exc_cl "exception" e.epos [] in
         let esetstack = mk (TBinop(Ast.OpAssign, exc_field, mk_local v e.epos)) v.v_type e.epos in
 
-        Codegen.concat esetstack e;
+        Type.concat esetstack e;
       )
   );
 

+ 2 - 2
genjava.ml

@@ -486,8 +486,8 @@ struct
             Some conds, hashed_exprs
           | _ -> assert false
       ) (None,[]) el in
-      let e = if has_default then Codegen.concat execute_def_set e else e in
-      let e = if !has_conflict then Codegen.concat e { e with eexpr = TBreak; etype = basic.tvoid } else e in
+      let e = if has_default then Type.concat execute_def_set e else e in
+      let e = if !has_conflict then Type.concat e { e with eexpr = TBreak; etype = basic.tvoid } else e in
       let e = {
         eexpr = TIf(get conds, e, None);
         etype = basic.tvoid;

+ 1 - 1
genjs.ml

@@ -287,7 +287,7 @@ let fun_block ctx f p =
 	let e = List.fold_left (fun e (a,c) ->
 		match c with
 		| None | Some TNull -> e
-		| Some c -> Codegen.concat (Codegen.set_default ctx.com a c p) e
+		| Some c -> Type.concat (Codegen.set_default ctx.com a c p) e
 	) f.tf_expr f.tf_args in
 	e
 

+ 1 - 1
genphp.ml

@@ -509,7 +509,7 @@ let fun_block ctx f p =
 	let e = List.fold_left (fun e (v,c) ->
 		match c with
 		| None | Some TNull -> e
-		| Some c -> Codegen.concat (Codegen.set_default ctx.com v c p) e
+		| Some c -> Type.concat (Codegen.set_default ctx.com v c p) e
 	) e f.tf_args in
 	if ctx.com.debug then begin
 		Codegen.stack_block ctx.stack ctx.curclass ctx.curmethod e

+ 1 - 1
genpy.ml

@@ -229,7 +229,7 @@ module Transformer = struct
 				tf.tf_expr
 			| _ ->
 				let eb = mk (TBlock (List.rev assigns)) t_dynamic p in
-				Codegen.concat eb tf.tf_expr
+				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({

+ 5 - 3
main.ml

@@ -56,6 +56,8 @@ let prompt = ref false
 let start_time = ref (get_time())
 let global_cache = ref None
 
+let path_sep = if Sys.os_type = "Unix" then "/" else "\\"
+
 let get_real_path p =
 	try
 		Extc.get_real_path p
@@ -1285,13 +1287,13 @@ try
 		com.main_class <- None;
 		let real = get_real_path (!Parser.resume_display).Ast.pfile in
 		(* try to fix issue on windows when get_real_path fails (8.3 DOS names disabled) *)
-		let real = (match List.rev (ExtString.String.nsplit real "\\") with
-		| file :: path when String.length file > 0 && file.[0] >= 'a' && file.[1] <= 'z' -> file.[0] <- char_of_int (int_of_char file.[0] - int_of_char 'a' + int_of_char 'A'); String.concat "\\" (List.rev (file :: path))
+		let real = (match List.rev (ExtString.String.nsplit real path_sep) with
+		| file :: path when String.length file > 0 && file.[0] >= 'a' && file.[1] <= 'z' -> file.[0] <- char_of_int (int_of_char file.[0] - int_of_char 'a' + int_of_char 'A'); String.concat path_sep (List.rev (file :: path))
 		| _ -> real) in
 		classes := lookup_classes com real;
 		if !classes = [] then begin
 			if not (Sys.file_exists real) then failwith "Display file does not exist";
-			(match List.rev (ExtString.String.nsplit real "\\") with
+			(match List.rev (ExtString.String.nsplit real path_sep) with
 			| file :: _ when file.[0] >= 'a' && file.[1] <= 'z' -> failwith ("Display file '" ^ file ^ "' should not start with a lowercase letter")
 			| _ -> ());
 			failwith "Display file was not found in class path";

+ 6 - 0
matcher.ml

@@ -343,6 +343,12 @@ let to_pattern ctx e t =
 			unify ctx e.etype t p;
 			let c = match e.eexpr with TConst c -> c | _ -> assert false in
 			mk_con_pat (CConst c) [] t p
+		| EMeta((Meta.Macro,[],_),(ECall (e1,args),_)) ->
+			let path, field, args = Codegen.get_macro_path ctx e1 args p in
+			begin match ctx.g.do_macro ctx MExpr path field args p with
+				| Some e ->	loop pctx e t
+				| None -> error "Macro failure" p
+			end
 		| EField _ ->
 			let e = type_expr ctx e (WithType t) in
 			let e = match Optimizer.make_constant_expression ctx ~concat_strings:true e with Some e -> e | None -> e in

+ 1 - 1
std/flash/_std/haxe/ds/IntMap.hx

@@ -42,7 +42,7 @@ package haxe.ds;
 	}
 
 	public function remove( key : Int ) : Bool {
-		if( untyped !h.hasOwnProperty(key) ) return false;
+		if( !exists(key) ) return false;
 		untyped __delete__(h,key);
 		return true;
 	}

+ 1 - 1
std/flash/_std/haxe/ds/StringMap.hx

@@ -43,7 +43,7 @@ package haxe.ds;
 
 	public function remove( key : String ) : Bool {
 		key = "$"+key;
-		if( untyped !h.hasOwnProperty(key) ) return false;
+		if( untyped !__in__(key,h) ) return false;
 		untyped __delete__(h,key);
 		return true;
 	}

+ 83 - 0
std/flash/_std/haxe/ds/UnsafeStringMap.hx

@@ -0,0 +1,83 @@
+/*
+ * 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.ds;
+
+/**
+	This is similar to `StringMap` excepts that it does not sanitize the keys.
+	As a result, it will be faster to access the map for reading, but it might fail
+	with some reserved keys such as `constructor` or `prototype`.
+**/
+class UnsafeStringMap<T> implements Map.IMap<String,T> {
+
+	private var h : flash.utils.Dictionary;
+
+	public function new() : Void {
+		h = new flash.utils.Dictionary();
+	}
+
+	public inline function set( key : String, value : T ) : Void {
+		untyped h[key] = value;
+	}
+
+	public inline function get( key : String ) : Null<T> {
+		return untyped h[key];
+	}
+
+	public inline function exists( key : String ) : Bool {
+		return untyped __in__(key,h);
+	}
+
+	public function remove( key : String ) : Bool {
+		if( untyped !h.hasOwnProperty(key) ) return false;
+		untyped __delete__(h,key);
+		return true;
+	}
+
+	public function keys() : Iterator<String> {
+		return untyped (__keys__(h)).iterator();
+	}
+
+	public function iterator() : Iterator<T> {
+		return untyped {
+			ref : h,
+			it : __keys__(h).iterator(),
+			hasNext : function() { return __this__.it.hasNext(); },
+			next : function() { var i : Dynamic = __this__.it.next(); return __this__.ref[i]; }
+		};
+	}
+
+	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();
+	}
+
+}

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

@@ -185,6 +185,30 @@ class Bytes {
 		#end
 	}
 
+	public function readDouble( pos : Int ) : Float {
+		#if neko
+		return untyped Input._double_of_bytes(sub(pos,8).b,false);
+		#elseif flash9
+		b.position = pos;
+		return b.readDouble();
+		#else
+		var b = new haxe.io.BytesInput(this,pos,8);
+		return b.readDouble();
+		#end
+	}
+
+	public function readFloat( pos : Int ) : Float {
+		#if neko
+		return untyped Input._float_of_bytes(sub(pos,4).b,false);
+		#elseif flash9
+		b.position = pos;
+		return b.readFloat();
+		#else
+		var b = new haxe.io.BytesInput(this,pos,4);
+		return b.readFloat();
+		#end
+	}
+
 	public function readString( pos : Int, len : Int ) : String {
 		#if !neko
 		if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds;

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

@@ -109,6 +109,40 @@ class BytesBuffer {
 		#end
 	}
 
+	public inline function addString( v : String ) {
+		#if neko
+		untyped StringBuf.__add(b, v.__s);
+		#elseif flash9
+		b.writeUTFBytes(v);
+		#else
+		add(Bytes.ofString(v));
+		#end
+	}
+
+	public inline function addFloat( v : Float ) {
+		#if neko
+		untyped StringBuf.__add(b, Output._float_bytes(v, false));
+		#elseif flash9
+		b.writeFloat(v);
+		#else
+		var b = new BytesOutput();
+		b.writeFloat(v);
+		add(b.getBytes());
+		#end
+	}
+	
+	public inline function addDouble( v : Float ) {
+		#if neko
+		untyped StringBuf.__add(b, Output._double_bytes(v, false));
+		#elseif flash9
+		b.writeDouble(v);
+		#else
+		var b = new BytesOutput();
+		b.writeDouble(v);
+		add(b.getBytes());
+		#end
+	}
+	
 	public inline function addBytes( src : Bytes, pos : Int, len : Int ) {
 		#if !neko
 		if( pos < 0 || len < 0 || pos + len > src.length ) throw Error.OutsideBounds;

+ 1 - 5
std/haxe/zip/Reader.hx

@@ -195,8 +195,7 @@ class Reader {
 	public static function unzip( f : Entry ) {
 		if( !f.compressed )
 			return f.data;
-		#if neko
-		var c = new neko.zip.Uncompress(-15);
+		var c = new haxe.zip.Uncompress(-15);
 		var s = haxe.io.Bytes.alloc(f.fileSize);
 		var r = c.execute(f.data,0,s,0);
 		c.close();
@@ -205,9 +204,6 @@ class Reader {
 		f.compressed = false;
 		f.dataSize = f.fileSize;
 		f.data = s;
-		#else
-		throw "No uncompress support";
-		#end
 		return f.data;
 	}
 

+ 1 - 1
std/python/_std/Sys.hx

@@ -7,7 +7,7 @@ class Sys {
 	static var environ:haxe.ds.StringMap<String>;
 
 	public static function time():Float {
-		return Time.time()/1000;
+		return Time.time();
 	}
 
 	public static function exit(code:Int):Void {

+ 28 - 1
tests/RunTravis.hx

@@ -32,6 +32,18 @@ class RunTravis {
 		Sys.exit(exitCode);
 	}
 
+	static function getHaxelibPath(libName:String) {
+		var proc = new sys.io.Process("haxelib", ["path", libName]);
+		var result = proc.stdout.readLine();
+		proc.close();
+		return result;
+	}
+
+	static function changeDirectory(path:String) {
+		Sys.println('Changing directory to $path');
+		Sys.setCwd(path);
+	}
+
 	static function setupFlashPlayerDebugger():Void {
 		Sys.putEnv("DISPLAY", ":99.0");
 		runCommand("sh", ["-e", "/etc/init.d/xvfb", "start"]);
@@ -83,7 +95,6 @@ class RunTravis {
 			case "macro", null:
 				runCommand("haxe", ["compile-macro.hxml"]);
 
-
 				//generate documentation
 				runCommand("haxelib", ["git", "hxparse", "https://github.com/Simn/hxparse", "development", "src"], true);
 				runCommand("haxelib", ["git", "hxtemplo", "https://github.com/Simn/hxtemplo", "master", "src"], true);
@@ -181,6 +192,22 @@ class RunTravis {
 
 				runCommand("haxe", ["compile-as3.hxml", "-D", "fdb"]);
 				runFlash("unit9_as3.swf");
+			//case "openfl":
+				//runCommand("haxelib", ["install", "munit"]);
+				//runCommand("haxelib", ["install", "openfl"]);
+				//runCommand("haxelib", ["git", "openfl-validation", "https://github.com/openfl/openfl-validation"]);
+			case "polygonal-ds":
+				runCommand("haxelib", ["git", "polygonal-ds", "https://github.com/Simn/ds"]);
+				runCommand("haxelib", ["git", "polygonal-core", "https://github.com/polygonal/core", "master", "src"]);
+				runCommand("haxelib", ["git", "polygonal-printf", "https://github.com/polygonal/printf", "master", "src"]);
+				changeDirectory(getHaxelibPath("polygonal-ds"));
+				runCommand("haxe", ["-cp", "src", "-cp", "test", "-lib", "polygonal-core", "-lib", "polygonal-printf", "-main", "UnitTest", "-js", "unit.js"]);
+				runCommand("node", ["unit.js"]);
+			//case "flambe":
+				//runCommand("haxelib", ["git", "flambe", "https://github.com/aduros/flambe", "master", "src"]);
+				//runCommand("haxelib", ["git", "flambe-server", "https://github.com/aduros/flambe-server", "master", "src"]);
+				//changeDirectory(haxe.io.Path.join([getHaxelibPath("flambe"), "..", "tests", "unit"]));
+				//runCommand("sh", ["run-tests"]);
 			case target:
 				throw "unknown target: " + target;
 		}

+ 36 - 0
tests/unit/issues/Issue2698.hx

@@ -0,0 +1,36 @@
+package unit.issues;
+import unit.Test;
+
+private abstract IntString(String) {
+    @:from static function fromInt(i:Int):IntString return cast Std.string(i);
+    @:to function toInt():Int return Std.parseInt(this);
+}
+
+class Issue2698 extends Test {
+	function test() {
+		var a:IntString = 1;
+		var b:Int = 1;
+		var c:IntString = 2;
+		var d:Int = 2;
+		
+		t(a == a);
+		t(a == b);
+		f(a == c);
+		f(a == d);
+		
+		t(b == a);
+		t(b == b);
+		f(b == c);
+		f(b == d);
+		
+		f(c == a);
+		f(c == b);
+		t(c == c);
+		t(c == d);
+		
+		f(d == a);
+		f(d == b);
+		t(d == c);
+		t(d == d);
+	}
+}

+ 17 - 0
tests/unit/issues/Issue2722.hx

@@ -0,0 +1,17 @@
+package unit.issues;
+import unit.Test;
+
+private class Test1 {
+	public var x:Int = 42;
+}
+
+private class Test2 extends Test1 {
+	public function new() { }
+}
+
+class Issue2722 extends Test {
+	function test() {
+		var test2 = new Test2();
+		eq(42, test2.x);
+	}
+}

+ 3 - 0
tests/unit/unitstd/Sys.unit.hx

@@ -0,0 +1,3 @@
+#if sys
+(Sys.time() > 1395990000.00) == true;
+#end

+ 9 - 0
type.ml

@@ -600,6 +600,15 @@ let rec has_mono t = match t with
 	| TLazy r ->
 		has_mono (!r())
 
+let concat e1 e2 =
+	let e = (match e1.eexpr, e2.eexpr with
+		| TBlock el1, TBlock el2 -> TBlock (el1@el2)
+		| TBlock el, _ -> TBlock (el @ [e2])
+		| _, TBlock el -> TBlock (e1 :: el)
+		| _ , _ -> TBlock [e1;e2]
+	) in
+	mk e e2.etype (punion e1.epos e2.epos)
+
 (* ======= Field utility ======= *)
 
 let field_name f =

+ 44 - 11
typeload.ml

@@ -992,7 +992,7 @@ let check_extends ctx c t p = match follow t with
 		end
 	| _ -> error "Should extend by using a class" p
 
-let rec add_constructor ctx c p =
+let rec add_constructor ctx c force_constructor p =
 	match c.cl_constructor, c.cl_super with
 	| None, Some ({ cl_constructor = Some cfsup } as csup,cparams) when not c.cl_extern ->
 		let cf = {
@@ -1046,6 +1046,18 @@ let rec add_constructor ctx c p =
 		cf.cf_type <- TLazy r;
 		c.cl_constructor <- Some cf;
 		delay ctx PForce (fun() -> ignore((!r)()));
+	| None,_ when force_constructor ->
+		let constr = mk (TFunction {
+			tf_args = [];
+			tf_type = ctx.t.tvoid;
+			tf_expr = mk (TBlock []) ctx.t.tvoid p;
+		}) (tfun [] ctx.t.tvoid) p in
+		let cf = mk_field "new" constr.etype p in
+		cf.cf_expr <- Some constr;
+		cf.cf_type <- constr.etype;
+		cf.cf_meta <- [Meta.CompilerGenerated,[],p];
+		cf.cf_kind <- Method MethNormal;
+		c.cl_constructor <- Some cf;
 	| _ ->
 		(* nothing to do *)
 		()
@@ -1219,16 +1231,34 @@ let type_function ctx args ret fmode f do_display p =
 	in
 	let has_super_constr() =
 		match ctx.curclass.cl_super with
-		| None -> false
-		| Some (csup,_) ->
-			try ignore(get_constructor (fun f->f.cf_type) csup); true with Not_found -> false
+		| None ->
+			None
+		| Some (csup,tl) ->
+			try
+				let _,cf = get_constructor (fun f->f.cf_type) csup in
+				Some (Meta.has Meta.CompilerGenerated cf.cf_meta,TInst(csup,tl))
+			with Not_found ->
+				None
+	in
+	let e = if fmode <> FunConstructor then
+		e
+	else match has_super_constr() with
+		| Some (was_forced,t_super) ->
+			(try
+				loop e;
+				if was_forced then
+					let e_super = mk (TConst TSuper) t_super e.epos in
+					let e_super_call = mk (TCall(e_super,[])) ctx.t.tvoid e.epos in
+					concat e_super_call e
+				else begin
+					display_error ctx "Missing super constructor call" p;
+					e
+				end
+			with
+				Exit -> e);
+		| None ->
+			e
 	in
-	if fmode = FunConstructor && has_super_constr() then
-		(try
-			loop e;
-			display_error ctx "Missing super constructor call" p
-		with
-			Exit -> ());
 	locals();
 	let e = match ctx.curfun, ctx.vthis with
 		| (FunMember|FunConstructor), Some v ->
@@ -1568,6 +1598,8 @@ let init_class ctx c p context_init herits fields =
 		end
 	in
 
+	let force_constructor = ref false in
+
 	let bind_var ctx cf e stat inline =
 		let p = cf.cf_pos in
 		if not stat && has_field cf.cf_name c.cl_super then error ("Redefinition of variable " ^ cf.cf_name ^ " in subclass is not allowed") p;
@@ -1640,6 +1672,7 @@ let init_class ctx c p context_init herits fields =
 				end;
 				t
 			) "bind_var" in
+			if not stat then force_constructor := true;
 			bind_type ctx cf r (snd e) false
 	in
 
@@ -2082,7 +2115,7 @@ let init_class ctx c p context_init herits fields =
 		make sure a default contructor with same access as super one will be added to the class structure at some point.
 	*)
 	(* add_constructor does not deal with overloads correctly *)
-	if not ctx.com.config.pf_overload then add_constructor ctx c p;
+	if not ctx.com.config.pf_overload then add_constructor ctx c !force_constructor p;
 	(* check overloaded constructors *)
 	(if ctx.com.config.pf_overload then match c.cl_constructor with
 	| Some ctor ->

+ 12 - 5
typer.ml

@@ -730,10 +730,14 @@ let rec acc_get ctx g p =
 	| AKNo f -> error ("Field " ^ f ^ " cannot be accessed for reading") p
 	| AKExpr e -> e
 	| AKSet _ | AKAccess _ -> assert false
-	| AKUsing (et,_,_,e) ->
+	| AKUsing (et,_,cf,e) ->
 		(* build a closure with first parameter applied *)
 		(match follow et.etype with
 		| TFun (_ :: args,ret) ->
+			begin match follow e.etype,cf.cf_kind with
+				| TAbstract _,Method MethInline -> error "Cannot create closure on abstract inline method" e.epos
+				| _ -> ()
+			end;
 			let tcallb = TFun (args,ret) in
 			let twrap = TFun ([("_e",false,e.etype)],tcallb) in
 			(* arguments might not have names in case of variable fields of function types, so we generate one (issue #2495) *)
@@ -1726,12 +1730,15 @@ let rec type_binop ctx op e1 e2 is_assign_op p =
 		mk_op e1 e2 !result
 	| OpEq
 	| OpNotEq ->
-		(try
+		let e1,e2 = try
 			unify_raise ctx e1.etype e2.etype p;
 			(* we only have to check one type here, because unification fails if one is Void and the other is not *)
-			(match follow e2.etype with TAbstract({a_path=[],"Void"},_) -> error "Cannot compare Void" p | _ -> ())
-		with
-			Error (Unify _,_) -> unify ctx e2.etype e1.etype p);
+			(match follow e2.etype with TAbstract({a_path=[],"Void"},_) -> error "Cannot compare Void" p | _ -> ());
+			Codegen.Abstract.check_cast ctx e2.etype e1 p,e2
+		with Error (Unify _,_) ->
+			unify ctx e2.etype e1.etype p;
+			e1,Codegen.Abstract.check_cast ctx e1.etype e2 p
+		in
 		mk_op e1 e2 ctx.t.tbool
 	| OpGt
 	| OpGte