Browse Source

adjusted Vector specification

Simon Krajewski 12 years ago
parent
commit
45aaac23f2
7 changed files with 72 additions and 37 deletions
  1. 2 1
      codegen.ml
  2. 1 1
      optimizer.ml
  3. 1 1
      std/haxe/EnumFlags.hx
  4. 42 19
      std/haxe/Vector.hx
  5. 15 11
      tests/unit/unitstd/haxe/Vector.unit.hx
  6. 2 2
      typeload.ml
  7. 9 2
      typer.ml

+ 2 - 1
codegen.ml

@@ -1310,7 +1310,8 @@ let handle_abstract_casts ctx e =
 		in
 		(match cf.cf_expr with
 		| Some { eexpr = TFunction fd } when cf.cf_kind = Method MethInline ->
-			(match Optimizer.type_inline ctx cf fd ethis args t (Some (a.a_types <> [], apply_params a.a_types pl)) p true with
+			let config = if has_meta ":impl" cf.cf_meta then (Some (a.a_types <> [], apply_params a.a_types pl)) else None in
+			(match Optimizer.type_inline ctx cf fd ethis args t config p true with
 				| Some e -> e
 				| None ->
 					def())

+ 1 - 1
optimizer.ml

@@ -394,7 +394,7 @@ let rec type_inline ctx cf f ethis params tret config p force =
 			let unify_func () = unify_raise ctx mt (TFun (List.map (fun e -> "",false,e.etype) params,tret)) p in
 			(match follow ethis.etype with
 			| TAnon a -> (match !(a.a_status) with
-				| Statics {cl_kind = KAbstractImpl a } ->
+				| Statics {cl_kind = KAbstractImpl a } when has_meta ":impl" cf.cf_meta ->
 					(* TODO: we might have to unify something here *)
 					()
 				| _ -> unify_func())

+ 1 - 1
std/haxe/EnumFlags.hx

@@ -81,7 +81,7 @@ abstract EnumFlags(Int)<T:EnumValue> {
 		have any impact on speed).
 	**/
 	@:from public inline static function ofInt<T:EnumValue>( i : Int ) : EnumFlags<T> {
-		return new EnumFlags(i);
+		return new EnumFlags<T>(i);
 	}
 
 	/**

+ 42 - 19
std/haxe/Vector.hx

@@ -20,13 +20,8 @@
  * DEALINGS IN THE SOFTWARE.
  */
 package haxe;
-
-/**
-	A Vector is a storage of fixed size. It can be faster than Array on some
-	targets, and is never slower.
-**/
 	
-typedef VImpl<T> = #if flash9
+private typedef VectorData<T> = #if flash9
 	flash.Vector<T>
 #elseif neko
 	neko.NativeArray<T>
@@ -34,7 +29,11 @@ typedef VImpl<T> = #if flash9
 	Array<T>
 #end
 
-abstract Vector(VImpl<T>)<T> {
+/**
+	A Vector is a storage of fixed size. It can be faster than Array on some
+	targets, and is never slower.
+**/
+abstract Vector(VectorData<T>)<T> {
 	/**
 		Creates a new Vector of length [length].
 		
@@ -44,11 +43,9 @@ abstract Vector(VImpl<T>)<T> {
 			targets
 			- null for other types on static targets
 			
-		If [length] is less than or equal to 0, an exception is thrown.
+		If [length] is less than or equal to 0, the result is unspecified.
 	**/
 	public inline function new(length:Int) {
-		if (length <= 0)
-			throw "Invalid length, must be >= 1";
 		#if flash9
 			this = new flash.Vector<T>(length, true);
 		#elseif neko
@@ -66,14 +63,11 @@ abstract Vector(VImpl<T>)<T> {
 	/**
 		Returns the value at index [index].
 		
-		If [index] is negative or exceeds [this].length, null is returned.
+		If [index] is negative or exceeds [this].length, the result is
+		unspecified.
 	**/
     public inline function get(index:Int):Null<T> {
-		#if (flash9 || cpp || js || java)
-		return index < 0 || index >= this.length ? null : this[index];
-		#else
 		return this[index];
-		#end
 	}
 	
 	/**
@@ -97,11 +91,40 @@ abstract Vector(VImpl<T>)<T> {
 		#end
 	}
 	
-	@:from static public inline function fromArray(arr:Array<T>) {
+	/**
+		Extracts the data of [this] Vector.
+		
+		This returns the internal representation type.
+	**/
+	public inline function toData():VectorData<T>
+		return cast this
+		
+	/**
+		Initializes a new Vector from [data].
+		
+		Since [data] is the internal representation of Vector, this is a no-op.
+		
+		If [data] is null, the corresponding Vector is also [null].
+	**/
+	static public inline function fromData<T>(data:VectorData<T>):Vector<T>
+		return cast data
+	
+	/**
+		Creates a new Vector by copying the elements of [array].
+		
+		This always creates a copy, even on platforms where the internal
+		representation is Array.
+		
+		The elements are not copied and retain their identity, so
+		a[i] == Vector.fromArrayCopy(a).get(i) is true for any valid i.
+		
+		If [array] is null, the result is unspecified.
+	**/
+	static public inline function fromArrayCopy<T>(array:Array<T>):Vector<T> {
 		// TODO: Optimize this for flash (and others?)
-		var vec = new Vector<T>(arr.length);
-		for (i in 0...arr.length)
-			vec.set(i, arr[i]);
+		var vec = new Vector<T>(array.length);
+		for (i in 0...array.length)
+			vec.set(i, array[i]);
 		return vec;
 	}
 }

+ 15 - 11
tests/unit/unitstd/haxe/Vector.unit.hx

@@ -13,28 +13,24 @@ vec.get(0) == vNullInt;
 vec.get(1) == 2;
 vec.get(2) == vNullInt;
 
-// out of bounds
-vec.get( -1) == null;
-vec.get(4) == null;
-
 // float init
 var vec = new haxe.Vector<Float>(3);
-vec.get( -1) == null;
 vec.get(0) == vNullFloat;
 vec.get(1) == vNullFloat;
 vec.get(2) == vNullFloat;
-vec.get(3) == null;
 
 // bool init
 var vec = new haxe.Vector<Bool>(3);
-vec.get( -1) == null;
 vec.get(0) == vNullBool;
 vec.get(1) == vNullBool;
 vec.get(2) == vNullBool;
-vec.get(3) == null;
 
 // fromArray
-var vec:haxe.Vector<String> = ["1", "2", "3"];
+var arr = ["1", "2", "3"];
+var vec:haxe.Vector<String> = haxe.Vector.fromArrayCopy(arr);
+#if (!flash && !neko)
+arr != vec.toData();
+#end
 vec.length() == 3;
 vec.get(0) == "1";
 vec.get(1) == "2";
@@ -42,5 +38,13 @@ vec.get(2) == "3";
 
 // objects
 var tpl = new haxe.Template("foo");
-var vec:haxe.Vector<haxe.Template> = [tpl];
-tpl == vec.get(0);
+var vec:haxe.Vector<haxe.Template> = haxe.Vector.fromArrayCopy([tpl]);
+tpl == vec.get(0);
+
+// toData + fromData
+var vec:haxe.Vector<String> = haxe.Vector.fromArrayCopy(["1", "2", "3"]);
+var data = vec.toData();
+var vec2 = haxe.Vector.fromData(data);
+vec2.get(0) == "1";
+vec2.get(1) == "2";
+vec2.get(2) == "3";

+ 2 - 2
typeload.ml

@@ -140,11 +140,11 @@ let make_module ctx mpath file tdecls loadp =
 							| Some e -> Some (EBlock [init p;e;ret p],p)
 							)
 						} in
-						{ f with cff_name = "_new"; cff_access = AStatic :: f.cff_access; cff_kind = FFun fu }
+						{ f with cff_name = "_new"; cff_access = AStatic :: f.cff_access; cff_kind = FFun fu; cff_meta = (":impl",[],p) :: f.cff_meta }
 					| FFun fu when not stat ->
 						if has_meta ":from" f.cff_meta then error "@:from cast functions must be static" f.cff_pos;
 						let fu = { fu with f_args = ("this",false,Some this_t,None) :: fu.f_args } in
-						{ f with cff_kind = FFun fu; cff_access = AStatic :: f.cff_access }
+						{ f with cff_kind = FFun fu; cff_access = AStatic :: f.cff_access; cff_meta = (":impl",[],p) :: f.cff_meta }
 					| _ ->
 						f
 				) fields in

+ 9 - 2
typer.ml

@@ -571,7 +571,7 @@ let make_call ctx e params t p =
 			| _ -> false
 		) in
 		let config = match cl with
-			| Some ({cl_kind = KAbstractImpl _ }) ->
+			| Some ({cl_kind = KAbstractImpl _ }) when has_meta ":impl" f.cf_meta ->
 				(match if fname = "_new" then t else follow (List.hd params).etype with
 					| TAbstract(a,pl) ->
 						Some (a.a_types <> [], apply_params a.a_types pl)
@@ -904,7 +904,14 @@ let rec type_ident_raise ?(imported_enums=true) ctx i p mode =
 
 and type_field ctx e i p mode =
 	let no_field() =
-		if not ctx.untyped then display_error ctx (s_type (print_context()) e.etype ^ " has no field " ^ i) p;
+		let t = match follow e.etype with
+			| TAnon a -> (match !(a.a_status) with
+				| Statics {cl_kind = KAbstractImpl a} -> TAbstract(a,[])
+				| _ -> e.etype)
+			| TInst({cl_kind = KAbstractImpl a},_) -> TAbstract(a,[])
+			| _ -> e.etype
+		in
+		if not ctx.untyped then display_error ctx (s_type (print_context()) t ^ " has no field " ^ i) p;
 		AKExpr (mk (TField (e,FDynamic i)) (mk_mono()) p)
 	in
 	match follow e.etype with