Browse Source

TestIssues mostly compiling, not yet passing

Nicolas Cannasse 9 years ago
parent
commit
1ffcbcb527

+ 89 - 27
genhl.ml

@@ -138,7 +138,8 @@ type opcode =
 	| OJNotEq of reg * reg * int
 	| OJNotEq of reg * reg * int
 	| OJAlways of int
 	| OJAlways of int
 	| OToDyn of reg * reg
 	| OToDyn of reg * reg
-	| OToFloat of reg * reg
+	| OToSFloat of reg * reg
+	| OToUFloat of reg * reg
 	| OToInt of reg * reg
 	| OToInt of reg * reg
 	| OLabel of unused
 	| OLabel of unused
 	| ONew of reg
 	| ONew of reg
@@ -284,6 +285,10 @@ type access =
 	| AEnum of field index
 	| AEnum of field index
 	| ACaptured of field index
 	| ACaptured of field index
 
 
+let is_number = function
+	| HI8 | HI16 | HI32 | HF32 | HF64 -> true
+	| _ -> false
+
 let list_iteri f l =
 let list_iteri f l =
 	let p = ref 0 in
 	let p = ref 0 in
 	List.iter (fun v -> f !p v; incr p) l
 	List.iter (fun v -> f !p v; incr p) l
@@ -536,7 +541,7 @@ let rec get_index name p =
 
 
 let rec unsigned t =
 let rec unsigned t =
 	match follow t with
 	match follow t with
-	| TAbstract ({ a_path = ["hl";"types"],("UI32"|"UI16"|"UI8") },_) -> true
+	| TAbstract ({ a_path = ["hl";"types"],("UI32"|"UI16"|"UI8") },_) | TAbstract ({ a_path = [],"UInt" },_) -> true
 	| TAbstract (a,pl) -> unsigned (Abstract.get_underlying_type a pl)
 	| TAbstract (a,pl) -> unsigned (Abstract.get_underlying_type a pl)
 	| _ -> false
 	| _ -> false
 
 
@@ -645,13 +650,21 @@ let rec to_type ctx t =
 		HAbstract (name, alloc_string ctx name)
 		HAbstract (name, alloc_string ctx name)
 	| TInst (c,pl) ->
 	| TInst (c,pl) ->
 		(match c.cl_kind with
 		(match c.cl_kind with
-		| KTypeParameter _ -> HDyn
+		| KTypeParameter tl ->
+			let rec loop = function
+				| [] -> HDyn
+				| t :: tl ->
+					match follow (apply_params c.cl_params pl t) with
+					| TInst ({cl_interface=false},_) as t -> to_type ctx t
+					| _ -> loop tl
+			in
+			loop tl
 		| _ -> class_type ctx c pl false)
 		| _ -> class_type ctx c pl false)
 	| TAbstract (a,pl) ->
 	| TAbstract (a,pl) ->
 		if Meta.has Meta.CoreType a.a_meta then
 		if Meta.has Meta.CoreType a.a_meta then
 			(match a.a_path with
 			(match a.a_path with
 			| [], "Void" -> HVoid
 			| [], "Void" -> HVoid
-			| [], "Int" -> HI32
+			| [], "Int" | [], "UInt" -> HI32
 			| [], "Float" -> HF64
 			| [], "Float" -> HF64
 			| [], "Single" -> HF32
 			| [], "Single" -> HF32
 			| [], "Bool" -> HBool
 			| [], "Bool" -> HBool
@@ -705,6 +718,16 @@ and field_type ctx f p =
 	| FDynamic _ -> t_dynamic
 	| FDynamic _ -> t_dynamic
 	| FEnum (_,f) -> f.ef_type
 	| FEnum (_,f) -> f.ef_type
 
 
+and real_type ctx e =
+	let rec loop e =
+		match e.eexpr with
+		| TField (_,f) -> field_type ctx f e.epos
+		| TLocal v -> v.v_type
+		| TParenthesis e -> loop e
+		| _ -> e.etype
+	in
+	to_type ctx (loop e)
+
 and class_type ctx c pl statics =
 and class_type ctx c pl statics =
 	let c = if c.cl_extern then resolve_class ctx c pl statics else c in
 	let c = if c.cl_extern then resolve_class ctx c pl statics else c in
 	let key_path = (if statics then fst c.cl_path, "$" ^ snd c.cl_path else c.cl_path) in
 	let key_path = (if statics then fst c.cl_path, "$" ^ snd c.cl_path else c.cl_path) in
@@ -1033,7 +1056,7 @@ and cast_to ?(force=false) ctx (r:reg) (t:ttype) p =
 		cast_to ctx tmp t p
 		cast_to ctx tmp t p
 	| (HI8 | HI16 | HI32 | HF32 | HF64), (HF32 | HF64) ->
 	| (HI8 | HI16 | HI32 | HF32 | HF64), (HF32 | HF64) ->
 		let tmp = alloc_tmp ctx t in
 		let tmp = alloc_tmp ctx t in
-		op ctx (OToFloat (tmp, r));
+		op ctx (OToSFloat (tmp, r));
 		tmp
 		tmp
 	| (HF32 | HF64), (HI8 | HI16 | HI32) ->
 	| (HF32 | HF64), (HI8 | HI16 | HI32) ->
 		let tmp = alloc_tmp ctx t in
 		let tmp = alloc_tmp ctx t in
@@ -1041,7 +1064,7 @@ and cast_to ?(force=false) ctx (r:reg) (t:ttype) p =
 		tmp
 		tmp
 	| (HI8 | HI16 | HI32), HNull ((HF32 | HF64) as t) ->
 	| (HI8 | HI16 | HI32), HNull ((HF32 | HF64) as t) ->
 		let tmp = alloc_tmp ctx t in
 		let tmp = alloc_tmp ctx t in
-		op ctx (OToFloat (tmp, r));
+		op ctx (OToSFloat (tmp, r));
 		let r = alloc_tmp ctx (HNull t) in
 		let r = alloc_tmp ctx (HNull t) in
 		op ctx (OToDyn (r,tmp));
 		op ctx (OToDyn (r,tmp));
 		r
 		r
@@ -1075,7 +1098,7 @@ and cast_to ?(force=false) ctx (r:reg) (t:ttype) p =
 		let out = alloc_tmp ctx t in
 		let out = alloc_tmp ctx t in
 		op ctx (OSafeCast (out, r));
 		op ctx (OSafeCast (out, r));
 		out
 		out
-	| HNull rt, _ when rt == t ->
+	| HNull rt, _ when t = rt ->
 		let out = alloc_tmp ctx t in
 		let out = alloc_tmp ctx t in
 		op ctx (OSafeCast (out, r));
 		op ctx (OSafeCast (out, r));
 		out
 		out
@@ -1087,6 +1110,15 @@ and cast_to ?(force=false) ctx (r:reg) (t:ttype) p =
 		let tmp = alloc_tmp ctx (HNull t) in
 		let tmp = alloc_tmp ctx (HNull t) in
 		op ctx (OToDyn (tmp, r));
 		op ctx (OToDyn (tmp, r));
 		tmp
 		tmp
+	| HNull t1, HNull t2 ->
+		let j = jump ctx (fun n -> OJNull (r,n)) in
+		let rtmp = alloc_tmp ctx t1 in
+		op ctx (OSafeCast (rtmp,r));
+		let out = cast_to ctx rtmp t p in
+		op ctx (OJAlways 1);
+		j();
+		op ctx (ONull out);
+		out
 	| HFun (args1,ret1), HFun (args2, ret2) when List.length args1 = List.length args2 ->
 	| HFun (args1,ret1), HFun (args2, ret2) when List.length args1 = List.length args2 ->
 		let fid = gen_method_wrapper ctx rt t p in
 		let fid = gen_method_wrapper ctx rt t p in
 		let fr = alloc_tmp ctx t in
 		let fr = alloc_tmp ctx t in
@@ -1342,7 +1374,12 @@ and eval_expr ctx e =
 		alloc_tmp ctx HVoid
 		alloc_tmp ctx HVoid
 	| TLocal v ->
 	| TLocal v ->
 		cast_to ctx (match captured_index ctx v with
 		cast_to ctx (match captured_index ctx v with
-		| None -> alloc_reg ctx v
+		| None ->
+			(* we need to make a copy for cases such as (a - a++) *)
+			let r = alloc_reg ctx v in
+			let r2 = alloc_tmp ctx (rtype ctx r) in
+			op ctx (OMov (r2, r));
+			r2
 		| Some idx ->
 		| Some idx ->
 			let r = alloc_tmp ctx (to_type ctx v.v_type) in
 			let r = alloc_tmp ctx (to_type ctx v.v_type) in
 			op ctx (OEnumField (r, ctx.m.mcaptreg, 0, idx));
 			op ctx (OEnumField (r, ctx.m.mcaptreg, 0, idx));
@@ -1567,9 +1604,9 @@ and eval_expr ctx e =
 			let r = eval_to ctx value et in
 			let r = eval_to ctx value et in
 			op ctx (OSetArray (arr, pos, r));
 			op ctx (OSetArray (arr, pos, r));
 			r
 			r
-		| "$ref", [v] ->
+		| "$ref", [{ eexpr = TLocal v }] ->
 			let r = alloc_tmp ctx (to_type ctx e.etype) in
 			let r = alloc_tmp ctx (to_type ctx e.etype) in
-			let rv = (match rtype ctx r with HRef t -> eval_to ctx v t | _ -> invalid()) in
+			let rv = (match rtype ctx r with HRef t -> alloc_reg ctx v | _ -> invalid()) in
 			op ctx (ORef (r,rv));
 			op ctx (ORef (r,rv));
 			r
 			r
 		| "$ttype", [v] ->
 		| "$ttype", [v] ->
@@ -1661,12 +1698,7 @@ and eval_expr ctx e =
 		| _ ->
 		| _ ->
 			error ("Unknown native call " ^ v.v_name) e.epos)
 			error ("Unknown native call " ^ v.v_name) e.epos)
 	| TCall (ec,args) ->
 	| TCall (ec,args) ->
-		let real_type = (match ec.eexpr with
-			| TField (_,f) -> field_type ctx f ec.epos
-			| TLocal v -> v.v_type
-			| _ -> ec.etype
-		) in
-		let tfun = to_type ctx real_type in
+		let tfun = real_type ctx ec in
 		let el() = eval_args ctx args tfun e.epos in
 		let el() = eval_args ctx args tfun e.epos in
 		let ret = alloc_tmp ctx (match tfun with HFun (_,r) -> r | _ -> HDyn) in
 		let ret = alloc_tmp ctx (match tfun with HFun (_,r) -> r | _ -> HDyn) in
 		let def_ret = ref None in
 		let def_ret = ref None in
@@ -1861,14 +1893,14 @@ and eval_expr ctx e =
 			binop r a b;
 			binop r a b;
 			r
 			r
 		| OpAdd | OpSub | OpMult | OpDiv | OpMod | OpShl | OpShr | OpUShr | OpAnd | OpOr | OpXor ->
 		| OpAdd | OpSub | OpMult | OpDiv | OpMod | OpShl | OpShr | OpUShr | OpAnd | OpOr | OpXor ->
-			let t = to_type ctx e.etype in
+			let t = (match to_type ctx e.etype with HNull t -> t | t -> t) in
 			let r = alloc_tmp ctx t in
 			let r = alloc_tmp ctx t in
 			let a = eval_to ctx e1 t in
 			let a = eval_to ctx e1 t in
 			let b = eval_to ctx e2 t in
 			let b = eval_to ctx e2 t in
 			binop r a b;
 			binop r a b;
 			r
 			r
 		| OpAssign ->
 		| OpAssign ->
-			let value() = eval_to ctx e2 (to_type ctx e1.etype) in
+			let value() = eval_to ctx e2 (real_type ctx e1) in
 			(match get_access ctx e1 with
 			(match get_access ctx e1 with
 			| AGlobal g ->
 			| AGlobal g ->
 				let r = value() in
 				let r = value() in
@@ -2086,8 +2118,14 @@ and eval_expr ctx e =
 		alloc_tmp ctx HVoid
 		alloc_tmp ctx HVoid
 	| TCast (v,None) ->
 	| TCast (v,None) ->
 		let t = to_type ctx e.etype in
 		let t = to_type ctx e.etype in
-		let v = eval_expr ctx v in
-		cast_to ~force:true ctx v t e.epos
+		let rv = eval_expr ctx v in
+		(match t with
+		| HF32 | HF64 when unsigned v.etype ->
+			let r = alloc_tmp ctx t in
+			op ctx (OToUFloat (r,rv));
+			r
+		| _ ->
+			cast_to ~force:true ctx rv t e.epos)
 	| TArrayDecl el ->
 	| TArrayDecl el ->
 		let r = alloc_tmp ctx (to_type ctx e.etype) in
 		let r = alloc_tmp ctx (to_type ctx e.etype) in
 		let et = (match follow e.etype with TInst (_,[t]) -> to_type ctx t | _ -> assert false) in
 		let et = (match follow e.etype with TInst (_,[t]) -> to_type ctx t | _ -> assert false) in
@@ -2295,14 +2333,26 @@ and eval_expr ctx e =
 			op ctx (OSafeCast (r,re));
 			op ctx (OSafeCast (r,re));
 		r
 		r
 and gen_assign_op ctx acc e1 f =
 and gen_assign_op ctx acc e1 f =
+	let f r =
+		match rtype ctx r with
+		| HNull t ->
+			let r2 = alloc_tmp ctx t in
+			op ctx (OSafeCast (r2,r));
+			let r3 = alloc_tmp ctx (HNull t) in
+			op ctx (OToDyn (r3,f r2));
+			r3
+		| _ ->
+			f r
+	in
 	match acc with
 	match acc with
 	| AInstanceField (eobj, findex) ->
 	| AInstanceField (eobj, findex) ->
 		let robj = eval_null_check ctx eobj in
 		let robj = eval_null_check ctx eobj in
-		let t = to_type ctx e1.etype in
+		let t = real_type ctx e1 in
 		let r = alloc_tmp ctx t in
 		let r = alloc_tmp ctx t in
 		op ctx (OField (r,robj,findex));
 		op ctx (OField (r,robj,findex));
+		let r = cast_to ctx r (to_type ctx e1.etype) e1.epos in
 		let r = f r in
 		let r = f r in
-		op ctx (OSetField (robj,findex,r));
+		op ctx (OSetField (robj,findex,cast_to ctx r t e1.epos));
 		r
 		r
 	| AStaticVar (g,t,fid) ->
 	| AStaticVar (g,t,fid) ->
 		let o = alloc_tmp ctx t in
 		let o = alloc_tmp ctx t in
@@ -2479,6 +2529,10 @@ and make_fun ?gen_content ctx fidx f cthis cparent =
 				let tmp = alloc_tmp ctx HI32 in
 				let tmp = alloc_tmp ctx HI32 in
 				op ctx (OInt (tmp, alloc_i32 ctx i));
 				op ctx (OInt (tmp, alloc_i32 ctx i));
 				op ctx (OToDyn (r, tmp));
 				op ctx (OToDyn (r, tmp));
+			| TFloat s when (match to_type ctx (follow v.v_type) with HI8 | HI16 | HI32 -> true | _ -> false) ->
+				let tmp = alloc_tmp ctx HI32 in
+				op ctx (OInt (tmp, alloc_i32 ctx (Int32.of_float (float_of_string s))));
+				op ctx (OToDyn (r, tmp));
 			| TInt i ->
 			| TInt i ->
 				let tmp = alloc_tmp ctx HF64 in
 				let tmp = alloc_tmp ctx HF64 in
 				op ctx (OFloat (tmp, alloc_float ctx (Int32.to_float i)));
 				op ctx (OFloat (tmp, alloc_float ctx (Int32.to_float i)));
@@ -3002,7 +3056,10 @@ let check code =
 				reg a (rtype b);
 				reg a (rtype b);
 				can_jump delta
 				can_jump delta
 			| OJEq (a,b,delta) | OJNotEq (a,b,delta) ->
 			| OJEq (a,b,delta) | OJNotEq (a,b,delta) ->
-				if not (safe_cast (rtype b) (rtype a)) then reg a (rtype b);
+				(match rtype a, rtype b with
+				| HObj _, HObj _ -> ()
+				| ta, tb when safe_cast tb ta -> ()
+				| _ -> reg a (rtype b));
 				can_jump delta
 				can_jump delta
 			| OJAlways d ->
 			| OJAlways d ->
 				can_jump d
 				can_jump d
@@ -3010,7 +3067,7 @@ let check code =
 				(* we can still use OToDyn on nullable if we want to turn them into dynamic *)
 				(* we can still use OToDyn on nullable if we want to turn them into dynamic *)
 				if is_dynamic (rtype a) then reg a HI32; (* don't wrap as dynamic types that can safely be cast to it *)
 				if is_dynamic (rtype a) then reg a HI32; (* don't wrap as dynamic types that can safely be cast to it *)
 				if rtype r <> HDyn then reg r (HNull (rtype a))
 				if rtype r <> HDyn then reg r (HNull (rtype a))
-			| OToFloat (a,b) ->
+			| OToSFloat (a,b) | OToUFloat (a,b) ->
 				float a;
 				float a;
 				(match rtype b with HF32 | HF64 -> () | _ -> int b);
 				(match rtype b with HF32 | HF64 -> () | _ -> int b);
 			| OToInt (a,b) ->
 			| OToInt (a,b) ->
@@ -3799,6 +3856,7 @@ let interp code =
 	and call f args =
 	and call f args =
 		let regs = Array.create (Array.length f.regs) VUndef in
 		let regs = Array.create (Array.length f.regs) VUndef in
 		let pos = ref 1 in
 		let pos = ref 1 in
+
 		stack := (f,pos) :: !stack;
 		stack := (f,pos) :: !stack;
 		let fret = (match f.ftype with
 		let fret = (match f.ftype with
 			| HFun (fargs,fret) ->
 			| HFun (fargs,fret) ->
@@ -3931,8 +3989,9 @@ let interp code =
 			| OJNotEq (a,b,i) -> if not (vcompare a b (=)) then pos := !pos + i
 			| OJNotEq (a,b,i) -> if not (vcompare a b (=)) then pos := !pos + i
 			| OJAlways i -> pos := !pos + i
 			| OJAlways i -> pos := !pos + i
 			| OToDyn (r,a) -> set r (make_dyn (get a) f.regs.(a))
 			| OToDyn (r,a) -> set r (make_dyn (get a) f.regs.(a))
-			| OToFloat (r,a) -> set r (match get a with VInt v -> VFloat (Int32.to_float v) | VFloat _ as v -> v | _ -> assert false)
-			| OToInt (r,a) -> set r (match get a with VInt _ as v -> v | VFloat v -> VInt (Int32.of_float v) | _ -> assert false)
+			| OToSFloat (r,a) -> set r (match get a with VInt v -> VFloat (Int32.to_float v) | VFloat _ as v -> v | _ -> assert false)
+			| OToUFloat (r,a) -> set r (match get a with VInt v -> VFloat (if v < 0l then Int32.to_float v +. 4294967296. else Int32.to_float v) | VFloat _ as v -> v | _ -> assert false)
+			| OToInt (r,a) -> set r (match get a with VFloat v -> VInt (Int32.of_float v) | VInt _ as v -> v | _ -> assert false)
 			| OLabel _ -> ()
 			| OLabel _ -> ()
 			| ONew r ->
 			| ONew r ->
 				set r (alloc_obj (rtype r))
 				set r (alloc_obj (rtype r))
@@ -5282,7 +5341,8 @@ let ostr o =
 	| OJNotEq (a,b,i) -> Printf.sprintf "jnoteq %d,%d,%d" a b i
 	| OJNotEq (a,b,i) -> Printf.sprintf "jnoteq %d,%d,%d" a b i
 	| OJAlways d -> Printf.sprintf "jalways %d" d
 	| OJAlways d -> Printf.sprintf "jalways %d" d
 	| OToDyn (r,a) -> Printf.sprintf "todyn %d,%d" r a
 	| OToDyn (r,a) -> Printf.sprintf "todyn %d,%d" r a
-	| OToFloat (r,a) -> Printf.sprintf "tofloat %d,%d" r a
+	| OToSFloat (r,a) -> Printf.sprintf "tosfloat %d,%d" r a
+	| OToUFloat (r,a) -> Printf.sprintf "toufloat %d,%d" r a
 	| OToInt (r,a) -> Printf.sprintf "toint %d,%d" r a
 	| OToInt (r,a) -> Printf.sprintf "toint %d,%d" r a
 	| OLabel _ -> "label"
 	| OLabel _ -> "label"
 	| ONew r -> Printf.sprintf "new %d" r
 	| ONew r -> Printf.sprintf "new %d" r
@@ -5447,6 +5507,8 @@ let generate com =
 	let all_classes = Hashtbl.create 0 in
 	let all_classes = Hashtbl.create 0 in
 	List.iter (fun t ->
 	List.iter (fun t ->
 		match t with
 		match t with
+		| TClassDecl ({ cl_path = ["hl";"types"], ("BasicIterator"|"ArrayBasic") } as c) ->
+			c.cl_extern <- true
 		| TClassDecl c ->
 		| TClassDecl c ->
 			let rec loop p f =
 			let rec loop p f =
 				match p with
 				match p with

+ 1 - 1
std/UInt.hx

@@ -20,7 +20,7 @@
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
 
 
-#if ((flash || flash9doc || cs) && !doc_gen)
+#if ((flash || flash9doc || cs || hl) && !doc_gen)
 /**
 /**
 	The unsigned Int type is only defined for Flash and C#. It's currently
 	The unsigned Int type is only defined for Flash and C#. It's currently
 	handled the same as a normal Int.
 	handled the same as a normal Int.

+ 5 - 1
std/hl/_std/Reflect.hx

@@ -123,7 +123,11 @@ class Reflect {
 	}
 	}
 
 
 	@:overload(function( f : Array<Dynamic> -> Void ) : Dynamic {})
 	@:overload(function( f : Array<Dynamic> -> Void ) : Dynamic {})
-	public static function makeVarArgs( f : Array<Dynamic> -> Dynamic ) : Dynamic {
+	@:extern public inline static function makeVarArgs( f : Array<Dynamic> -> Dynamic ) : Dynamic {
+		return _makeVarArgs(f);
+	}
+
+	static function _makeVarArgs( f : Array<Dynamic> -> Dynamic ) : Dynamic {
 		throw "TODO";
 		throw "TODO";
 		return null;
 		return null;
 	}
 	}

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

@@ -46,7 +46,7 @@ class Resource {
 	public static function getBytes( name : String ) : haxe.io.Bytes {
 	public static function getBytes( name : String ) : haxe.io.Bytes {
 		for( x in content )
 		for( x in content )
 			if( x.name.compare(0,@:privateAccess name.bytes,0,(name.length+1)<<1) == 0 )
 			if( x.name.compare(0,@:privateAccess name.bytes,0,(name.length+1)<<1) == 0 )
-				return @:privateAccess new haxe.io.Bytes(x.dataLen, x.data);
+				return @:privateAccess new haxe.io.Bytes(x.data, x.dataLen);
 		return null;
 		return null;
 	}
 	}
 
 

+ 9 - 9
std/hl/_std/haxe/io/Bytes.hx

@@ -27,13 +27,13 @@ class Bytes {
 	public var length(default,null) : Int;
 	public var length(default,null) : Int;
 	var b : hl.types.Bytes;
 	var b : hl.types.Bytes;
 
 
-	function new(length:Int,b:hl.types.Bytes) : Void {
-		this.length = length;
+	function new(b:hl.types.Bytes,length:Int) : Void {
 		this.b = b;
 		this.b = b;
+		this.length = length;
 	}
 	}
 
 
-	inline function out(pos:UInt) : Bool {
-		return pos >= (length : UInt);
+	inline function out(pos:Int) : Bool {
+		return (pos:UInt) >= (length : UInt);
 	}
 	}
 
 
 	public function get( pos : Int ) : Int {
 	public function get( pos : Int ) : Int {
@@ -57,7 +57,7 @@ class Bytes {
 
 
 	public function sub( pos : Int, len : Int ) : Bytes {
 	public function sub( pos : Int, len : Int ) : Bytes {
 		if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds;
 		if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds;
-		return new Bytes(len,b.sub(pos,len));
+		return new Bytes(b.sub(pos, len), len);
 	}
 	}
 
 
 	public function compare( other : Bytes ) : Int {
 	public function compare( other : Bytes ) : Int {
@@ -155,17 +155,17 @@ class Bytes {
 	public static function alloc( length : Int ) : Bytes {
 	public static function alloc( length : Int ) : Bytes {
 		var b = new hl.types.Bytes(length);
 		var b = new hl.types.Bytes(length);
 		b.fill(0, length, 0);
 		b.fill(0, length, 0);
-		return new Bytes(length,b);
+		return new Bytes(b,length);
 	}
 	}
 
 
 	public static function ofString( s : String ) : Bytes @:privateAccess {
 	public static function ofString( s : String ) : Bytes @:privateAccess {
 		var size = 0;
 		var size = 0;
-		var b = s.bytes.utf16ToUtf8(0,size);
-		return new Bytes(size,b);
+		var b = s.bytes.utf16ToUtf8(0, size);
+		return new Bytes(b,size);
 	}
 	}
 
 
 	public static function ofData( b : BytesData ) : Bytes {
 	public static function ofData( b : BytesData ) : Bytes {
-		return new Bytes(b.length,b.b);
+		return new Bytes(b.b,b.length);
 	}
 	}
 
 
 	public inline static function fastGet( b : BytesData, pos : Int ) : Int {
 	public inline static function fastGet( b : BytesData, pos : Int ) : Int {

+ 1 - 1
std/hl/_std/haxe/io/BytesBuffer.hx

@@ -99,7 +99,7 @@ class BytesBuffer {
 	}
 	}
 
 
 	public function getBytes() : Bytes {
 	public function getBytes() : Bytes {
-		return @:privateAccess new haxe.io.Bytes(pos, b);
+		return @:privateAccess new haxe.io.Bytes(b, pos);
 	}
 	}
 
 
 }
 }

+ 2 - 0
std/hl/types/ArrayBase.hx

@@ -94,6 +94,7 @@ class ArrayBase extends ArrayAccess {
 
 
 }
 }
 
 
+@:keep
 @:generic
 @:generic
 class BasicIterator<T> {
 class BasicIterator<T> {
 	var pos : Int;
 	var pos : Int;
@@ -109,6 +110,7 @@ class BasicIterator<T> {
 	}
 	}
 }
 }
 
 
+@:keep
 @:generic class ArrayBasic<T> extends ArrayBase {
 @:generic class ArrayBasic<T> extends ArrayBase {
 
 
 	var bytes : hl.types.BytesAccess<T>;
 	var bytes : hl.types.BytesAccess<T>;

+ 4 - 2
std/hl/types/ArrayObj.hx

@@ -11,8 +11,10 @@ class ArrayObj<T> extends ArrayBase {
 	}
 	}
 
 
 	public function concat( a : ArrayObj<T> ) : ArrayObj<T> {
 	public function concat( a : ArrayObj<T> ) : ArrayObj<T> {
-		throw "TODO";
-		return null;
+		var arr = new hl.types.NativeArray(length + a.length);
+		arr.blit(0, array, 0, length);
+		arr.blit(length, a.array, 0, a.length);
+		return alloc(cast arr);
 	}
 	}
 
 
 	override function join( sep : String ) : String {
 	override function join( sep : String ) : String {