Просмотр исходного кода

more hl TestSpecification support

Nicolas Cannasse 9 лет назад
Родитель
Сommit
53d1cd8b23

+ 23 - 6
genhl.ml

@@ -238,6 +238,7 @@ type method_context = {
 }
 
 type array_impl = {
+	aall : tclass;
 	abase : tclass;
 	adyn : tclass;
 	aobj : tclass;
@@ -672,7 +673,7 @@ and resolve_class ctx c pl statics =
 	in
 	match c.cl_path, pl with
 	| ([],"Array"), [t] ->
-		if statics then ctx.array_impl.abase else array_class ctx (to_type ctx t)
+		if statics then ctx.array_impl.aall else array_class ctx (to_type ctx t)
 	| ([],"Array"), [] ->
 		assert false
 	| _, _ when c.cl_extern ->
@@ -859,7 +860,7 @@ and alloc_global ctx name t =
 
 and class_global ctx c =
 	let static = c != ctx.base_class in
-	let c = if is_array_type (HObj { null_proto with pname = s_type_path c.cl_path }) then ctx.array_impl.abase else c in
+	let c = if is_array_type (HObj { null_proto with pname = s_type_path c.cl_path }) then ctx.array_impl.aall else c in
 	let c = resolve_class ctx c (List.map snd c.cl_params) static in
 	let t = class_type ctx c [] static in
 	alloc_global ctx ("$" ^ s_type_path c.cl_path) t, t
@@ -1292,6 +1293,7 @@ and make_string ctx s p =
 and make_module_type ctx t =
 	let r = alloc_tmp ctx HType in
 	let t = (match t with
+	| TClassDecl { cl_path = [],"Array" } -> TInst (ctx.array_impl.aall,[])
 	| TClassDecl c -> TInst (c,List.map (fun _ -> t_dynamic) c.cl_params)
 	| TEnumDecl e -> TEnum (e,List.map (fun _ -> t_dynamic) e.e_params)
 	| TAbstractDecl a -> TAbstract (a,List.map (fun _ -> t_dynamic) a.a_params)
@@ -1888,12 +1890,12 @@ and eval_expr ctx e =
 				op ctx (OMov (l, r));
 				r
 			| AArray (ra,(at,vt),ridx) ->
-				let v = cast_to ctx (value()) vt e.epos in
+				let v = cast_to ctx (value()) at e.epos in
 				(* bounds check against length *)
 				(match at with
 				| HDyn ->
 					(* call setDyn() *)
-					op ctx (OCallMethod (alloc_tmp ctx HVoid,1,[ra;ridx;cast_to ctx v HDyn e.epos]));
+					op ctx (OCallMethod (alloc_tmp ctx HVoid,1,[ra;ridx;cast_to ctx v (if is_dynamic at then at else HDyn) e.epos]));
 				| _ ->
 					let len = alloc_tmp ctx HI32 in
 					op ctx (OField (len,ra,0)); (* length *)
@@ -1908,7 +1910,7 @@ and eval_expr ctx e =
 					| _ ->
 						let arr = alloc_tmp ctx HArray in
 						op ctx (OField (arr,ra,1));
-						op ctx (OSetArray (arr,ridx,v))
+						op ctx (OSetArray (arr,ridx,cast_to ctx v (if is_dynamic at then at else HDyn) e.epos))
 				);
 				v
 			| ADynamic (ethis,f) ->
@@ -2251,6 +2253,11 @@ and eval_expr ctx e =
 		result
 	| TTypeExpr t ->
 		(match t with
+		| TClassDecl { cl_path = [],"Array" } ->
+			let g, t = class_global ctx ctx.array_impl.aall in
+			let r = alloc_tmp ctx t in
+			op ctx (OGetGlobal (r, g));
+			r
 		| TClassDecl c ->
 			let g, t = class_global ctx c in
 			let r = alloc_tmp ctx t in
@@ -3302,7 +3309,7 @@ let rec is_compatible v t =
 	| VType _, HType -> true
 	| VArray _, HArray -> true
 	| VDynObj _, HDynObj -> true
-	| VVirtual v, HVirtual _ -> tsame (HVirtual v.vtype) t
+	| VVirtual v, HVirtual _ -> safe_cast (HVirtual v.vtype) t
 	| VRef (_,_,t1), HRef t2 -> tsame t1 t2
 	| VAbstract _, HAbstract _ -> true
 	| VEnum _, HEnum _ -> true
@@ -4481,6 +4488,10 @@ let interp code =
 				(function
 				| [VType t] -> VType (match t with HObj { psuper = Some o } -> HObj o | _ -> HVoid)
 				| _ -> assert false)
+			| "type_args_count" ->
+				(function
+				| [VType t] -> to_int (match t with HFun (args,_) -> List.length args | _ -> 0)
+				| _ -> assert false)
 			| "type_get_global" ->
 				(function
 				| [VType t] ->
@@ -4752,6 +4763,11 @@ let interp code =
 				(function
 				| [VClosure (f,_)] -> VClosure (f,None)
 				| _ -> assert false)
+			| "get_closure_value" ->
+				(function
+				| [VClosure (_,None)] -> VNull
+				| [VClosure (_,Some v)] -> v
+				| _ -> assert false)
 			| "bytes_find" ->
 				(function
 				| [VBytes src; VInt pos; VInt len; VBytes chk; VInt cpos; VInt clen; ] ->
@@ -5406,6 +5422,7 @@ let generate com =
 		cfids = new_lookup();
 		defined_funs = Hashtbl.create 0;
 		array_impl = {
+			aall = get_class "ArrayAccess";
 			abase = get_class "ArrayBase";
 			adyn = get_class "ArrayDyn";
 			aobj = get_class "ArrayObj";

+ 7 - 0
std/hl/_std/Reflect.hx

@@ -58,6 +58,13 @@ class Reflect {
 	public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array<Dynamic> ) : Dynamic {
 		var args : hl.types.ArrayDyn = cast args;
 		var count = args.length;
+
+		var ft = hl.types.Type.getDynamic(func);
+		if( ft.kind != HFun )
+			throw "Invalid function " + func;
+		if( o != null && hl.types.Api.getClosureValue(func) == null && count == ft.getArgsCount() )
+			o = null;
+
 		var nargs = o == null ? count : count + 1;
 		var a = new hl.types.NativeArray<Dynamic>(nargs);
 		if( o == null ) {

+ 78 - 0
std/hl/_std/haxe/ds/Vector.hx

@@ -0,0 +1,78 @@
+/*
+ * Copyright (C)2005-2016 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;
+
+private typedef VectorData<T> = Array<T>
+
+abstract Vector<T>(VectorData<T>) {
+
+	public inline function new(length:Int) {
+		this = [];
+		if( length > 0 ) this[length-1] = cast null;
+	}
+
+	@:op([]) public inline function get(index:Int):T {
+		return this[index];
+	}
+
+	@:op([]) public inline function set(index:Int, val:T):T {
+		return this[index] = val;
+	}
+
+	public var length(get, never):Int;
+
+	inline function get_length():Int {
+		return this.length;
+	}
+
+	public static inline function blit<T>(src:Vector<T>, srcPos:Int, dest:Vector<T>, destPos:Int, len:Int):Void	{
+		for (i in 0...len)
+			dest[destPos + i] = src[srcPos + i];
+	}
+
+	public inline function toArray():Array<T> {
+		return this.copy();
+	}
+
+	public inline function toData():VectorData<T>
+		return this;
+
+	static public inline function fromData<T>(data:VectorData<T>):Vector<T>
+		return cast data;
+
+	static public inline function fromArrayCopy<T>(array:Array<T>):Vector<T> {
+		return cast array.copy();
+	}
+
+	public inline function copy<T>():Vector<T> {
+		return cast this.copy();
+	}
+
+	public inline function join<T>(sep:String):String {
+		return this.join(sep);
+	}
+
+	public inline function sort<T>(f:T->T->Int):Void {
+		this.sort(f);
+	}
+
+}

+ 2 - 0
std/hl/_std/haxe/io/BytesBuffer.hx

@@ -84,11 +84,13 @@ class BytesBuffer {
 	public inline function addFloat( v : Float ) : Void {
 		if( pos + 4 > size ) __expand(0);
 		b.setF32(pos, v);
+		pos += 4;
 	}
 
 	public inline function addDouble( v : Float ) : Void {
 		if( pos + 8 > size ) __expand(0);
 		b.setF64(pos, v);
+		pos += 8;
 	}
 
 	public inline function addBytes( src : Bytes, pos : Int, len : Int ) : Void {

+ 1 - 0
std/hl/types/Api.hx

@@ -7,6 +7,7 @@ extern class Api {
 	@:hlNative("std","has_field") static function hasField( obj : Dynamic, hash : Int ) : Bool;
 	@:hlNative("std","delete_field") static function deleteField( obj : Dynamic, hash : Int ) : Bool;
 	@:hlNative("std","call_method") static function callMethod( f : haxe.Constraints.Function, args : NativeArray<Dynamic> ) : Dynamic;
+	@:hlNative("std","get_closure_value") static function getClosureValue( f : haxe.Constraints.Function ) : Dynamic;
 	@:hlNative("std","no_closure") static function noClosure( f : haxe.Constraints.Function ) : haxe.Constraints.Function;
 	@:hlNative("std", "safe_cast") static function safeCast( v : Dynamic, t : Type ) : Dynamic;
 

+ 89 - 20
std/hl/types/ArrayBase.hx

@@ -120,8 +120,13 @@ class BasicIterator<T> {
 	}
 
 	public function concat( a : ArrayBasic<T> ) : ArrayBasic<T> {
-		throw "TODO";
-		return null;
+		var ac = new ArrayBasic<T>();
+		ac.length = ac.size = length + a.length;
+		ac.bytes = new Bytes(ac.length << bytes.sizeBits);
+		var offset = length << bytes.sizeBits;
+		(ac.bytes:Bytes).blit(0, this.bytes, 0, offset);
+		(ac.bytes:Bytes).blit(offset, a.bytes, 0, a.length << bytes.sizeBits);
+		return ac;
 	}
 
 	override function join( sep : String ) : String {
@@ -151,17 +156,46 @@ class BasicIterator<T> {
 	}
 
 	override function reverse() : Void {
-		throw "TODO";
+		for( i in 0...length >> 1 ) {
+			var k = length - 1 - i;
+			var tmp = bytes[i];
+			bytes[i] = bytes[k];
+			bytes[k] = tmp;
+		}
 	}
 
 	public function shift() : Null<T> {
-		throw "TODO";
-		return null;
+		if( length == 0 )
+			return null;
+		var v = bytes[0];
+		length--;
+		(bytes:Bytes).blit(0, bytes, 1 << bytes.sizeBits, length << bytes.sizeBits);
+		return v;
 	}
 
 	public function slice( pos : Int, ?end : Int ) : ArrayBasic<T> {
-		throw "TODO";
-		return null;
+		if( pos < 0 ) {
+			pos = this.length + pos;
+			if( pos < 0 )
+				pos = 0;
+		}
+		var pend : Int;
+		if( end == null )
+			pend = this.length;
+		else {
+			pend = end;
+			if( pend < 0 )
+				pend += this.length;
+			if( pend > this.length )
+				pend = this.length;
+		}
+		var len = pend - pos;
+		if( len < 0 )
+			return new ArrayBasic<T>();
+		var a = new ArrayBasic<T>();
+		a.length = a.size = len;
+		a.bytes = (bytes:Bytes).sub(pos << bytes.sizeBits, len << bytes.sizeBits);
+		return a;
 	}
 
 	public function sort( f : T -> T -> Int ) : Void {
@@ -185,11 +219,19 @@ class BasicIterator<T> {
 	}
 
 	public function unshift( x : T ) : Void {
-		throw "TODO";
+		if( length == size ) __expand(length) else length++;
+		(bytes:Bytes).blit(1<<bytes.sizeBits, bytes, 0, (length - 1) << bytes.sizeBits);
+		bytes[0] = x;
 	}
 
 	public function insert( pos : Int, x : T ) : Void {
-		throw "TODO";
+		if( pos < 0 ) {
+			pos = length + pos;
+			if( pos < 0 ) pos = 0;
+		} else if( pos > length ) pos = length;
+		if( length == size ) __expand(length) else length++;
+		(bytes:Bytes).blit((pos + 1)<<bytes.sizeBits, bytes, pos<<bytes.sizeBits, (length - pos - 1) << bytes.sizeBits);
+		bytes[pos] = x;
 	}
 
 	public function remove( x : T ) : Bool {
@@ -202,34 +244,59 @@ class BasicIterator<T> {
 	}
 
 	public function indexOf( x : T, ?fromIndex:Int ) : Int {
-		for( i in (fromIndex == null ? 0 : fromIndex)...length )
+		var idx : Int = fromIndex == null ? 0 : fromIndex;
+		if( idx < 0 ) {
+			idx += length;
+			if( idx < 0 ) idx = 0;
+		}
+		for( i in idx...length )
 			if( bytes[i] == x )
 				return i;
 		return -1;
 	}
 
 	public function lastIndexOf( x : T, ?fromIndex:Int ) : Int {
-		throw "TODO";
+		var len = length;
+		var i:Int = fromIndex != null ? fromIndex : len - 1;
+		if( i >= len )
+			i = len - 1;
+		else if( i  < 0 )
+			i += len;
+		while( i >= 0 ) {
+			if( bytes[i] == x )
+				return i;
+			i--;
+		}
 		return -1;
 	}
 
 	public function copy() : ArrayBasic<T> {
-		throw "TODO";
-		return null;
+		var a = new ArrayBasic<T>();
+		a.length = a.size = length;
+		a.bytes = new Bytes(length << bytes.sizeBits);
+		(a.bytes:Bytes).blit(0, bytes, 0, length << bytes.sizeBits);
+		return a;
 	}
 
 	public function iterator() : Iterator<T> {
 		return new BasicIterator(this);
 	}
 
-	public function map<S>( f : T -> S ) : ArrayDyn {
-		throw "TODO";
-		return null;
+	public function map<S>( f : T -> S ) : ArrayDyn @:privateAccess {
+		var a = new ArrayObj();
+		if( length > 0 ) a.__expand(length - 1);
+		for( i in 0...length )
+			a.array[i] = f(bytes[i]);
+		return ArrayDyn.alloc(a,true);
 	}
 
-	public function filter( f : Int -> Bool ) : ArrayBasic<T> {
-		throw "TODO";
-		return null;
+	public function filter( f : T -> Bool ) : ArrayBasic<T> {
+		var a = new ArrayBasic<T>();
+		for( i in 0...length ) {
+			var v = bytes[i];
+			if( f(v) ) a.push(v);
+		}
+		return a;
 	}
 
 	override function getDyn( pos : Int ) : Dynamic {
@@ -266,7 +333,9 @@ class BasicIterator<T> {
 			var next = (size * 3) >> 1;
 			if( next < newlen ) next = newlen;
 			var bytes2 = new hl.types.Bytes(next << bytes.sizeBits);
-			bytes2.blit(0,bytes,0,length << bytes.sizeBits);
+			var bsize = length << bytes.sizeBits;
+			bytes2.blit(0, bytes, 0, bsize);
+			bytes2.fill(bsize, (next << bytes.sizeBits) - bsize, 0);
 			bytes = bytes2;
 			size = next;
 		}

+ 68 - 12
std/hl/types/ArrayObj.hx

@@ -44,17 +44,44 @@ class ArrayObj<T> extends ArrayBase {
 	}
 
 	override function reverse() : Void {
-		throw "TODO";
+		for( i in 0...length >> 1 ) {
+			var k = length - 1 - i;
+			var tmp = array[i];
+			array[i] = array[k];
+			array[k] = tmp;
+		}
 	}
 
 	public function shift() : Null<T> {
-		throw "TODO";
-		return null;
+		if( length == 0 )
+			return null;
+		length--;
+		var v = array[0];
+		array.blit(0, array, 1, length);
+		array[length] = null;
+		return v;
 	}
 
 	public function slice( pos : Int, ?end : Int ) : ArrayObj<T> {
-		throw "TODO";
-		return null;
+		if( pos < 0 ) {
+			pos = this.length + pos;
+			if( pos < 0 )
+				pos = 0;
+		}
+		var pend : Int;
+		if( end == null )
+			pend = this.length;
+		else {
+			pend = end;
+			if( pend < 0 )
+				pend += this.length;
+			if( pend > this.length )
+				pend = this.length;
+		}
+		var len = pend - pos;
+		if( len < 0 )
+			return new ArrayObj();
+		return alloc(array.sub(pos,len));
 	}
 
 	public function sort( f : T -> T -> Int ) : Void {
@@ -97,11 +124,19 @@ class ArrayObj<T> extends ArrayBase {
 	}
 
 	public function unshift( x : T ) : Void {
-		throw "TODO";
+		if( length == array.length ) __expand(length) else length++;
+		array.blit(1, array, 0, length - 1);
+		array[0] = x;
 	}
 
 	public function insert( pos : Int, x : T ) : Void {
-		throw "TODO";
+		if( pos < 0 ) {
+			pos = length + pos;
+			if( pos < 0 ) pos = 0;
+		} else if( pos > length ) pos = length;
+		if( length == array.length ) __expand(length) else length++;
+		array.blit(pos + 1, array, pos, length - pos - 1);
+		array[pos] = x;
 	}
 
 	public function remove( x : T ) : Bool {
@@ -115,6 +150,10 @@ class ArrayObj<T> extends ArrayBase {
 
 	public function indexOf( x : T, ?fromIndex:Int ) : Int {
 		var i : Int = fromIndex;
+		if( i < 0 ) {
+			i += length;
+			if( i < 0 ) i = 0;
+		}
 		var length = length;
 		var array = array;
 		while( i < length ) {
@@ -126,7 +165,17 @@ class ArrayObj<T> extends ArrayBase {
 	}
 
 	public function lastIndexOf( x : T, ?fromIndex:Int ) : Int {
-		throw "TODO";
+		var len = length;
+		var i:Int = fromIndex != null ? fromIndex : len - 1;
+		if( i >= len )
+			i = len - 1;
+		else if( i  < 0 )
+			i += len;
+		while( i >= 0 ) {
+			if( array[i] == x )
+				return i;
+			i--;
+		}
 		return -1;
 	}
 
@@ -143,13 +192,20 @@ class ArrayObj<T> extends ArrayBase {
 	}
 
 	public function map<S>( f : T -> S ) : ArrayDyn {
-		throw "TODO";
-		return null;
+		var a = new ArrayObj();
+		if( length > 0 ) a.__expand(length - 1);
+		for( i in 0...length )
+			a.array[i] = f(array[i]);
+		return ArrayDyn.alloc(a,true);
 	}
 
 	public function filter( f : T -> Bool ) : ArrayObj<T> {
-		throw "TODO";
-		return null;
+		var a = new ArrayObj();
+		for( i in 0...length ) {
+			var v = array[i];
+			if( f(v) ) a.push(v);
+		}
+		return a;
 	}
 
 	// called by compiler when accessing the array outside of its bounds, might trigger resize

+ 4 - 0
std/hl/types/Type.hx

@@ -60,6 +60,10 @@ abstract TypeKind(Int) {
 		return null;
 	}
 
+	@:hlNative("std","type_args_count") public function getArgsCount() : Int {
+		return 0;
+	}
+
 	@:hlNative("std","type_super") public function getSuper() : Type {
 		return null;
 	}

+ 3 - 0
tests/unit/src/unitstd/EReg.unit.hx

@@ -87,6 +87,7 @@ pos.len == 2;
 ~/a/g.replace("bab", "z") == "bzb";
 ~/a/g.replace("baba", "z") == "bzbz";
 
+#if !hl
 // replace + $
 ~/href="(.*?)"/.replace('lead href="foo" trail',"$1") == "lead foo trail";
 //~/href="(.*?)"/.replace('lead href="foo" trail',"$2") == "lead $2 trail";
@@ -95,6 +96,8 @@ pos.len == 2;
 ~/href="(.*?)"/g.replace('lead href="foo" href="bar" trail',"$1") == "lead foo bar trail";
 ~/href="(.*?)"/g.replace('lead href="foo" href="bar" trail',"$$$1$$") == "lead $foo$ $bar$ trail";
 //~/href="(.*?)"/g.replace('lead href="foo" href="bar" trail',"$$$2$$") == "lead $$2$ $$2$ trail";
+#end
+
 ~/a(b)c/g.replace("abcabc", "$1") == "bb";
 
 // map