소스 검색

Vector.fill (#10687)

* Vector.fill

* Rename to createFilled

* Fix hl

* Fix php and add test

* Understandable, have a nice unspecified

* Use array_fill for php

* Move to constructor arg

* Fix no-inline

* Extern inline test
RblSb 2 년 전
부모
커밋
f76e900c1c

+ 44 - 1
std/haxe/ds/Vector.hx

@@ -61,7 +61,7 @@ abstract Vector<T>(VectorData<T>) {
 
 
 		If `length` is less than or equal to 0, the result is unspecified.
 		If `length` is less than or equal to 0, the result is unspecified.
 	**/
 	**/
-	public inline function new(length:Int) {
+	extern overload public inline function new(length:Int) {
 		#if flash10
 		#if flash10
 		this = new flash.Vector<T>(length, true);
 		this = new flash.Vector<T>(length, true);
 		#elseif neko
 		#elseif neko
@@ -86,6 +86,43 @@ abstract Vector<T>(VectorData<T>) {
 		#end
 		#end
 	}
 	}
 
 
+	/**
+		Creates a new Vector of length `length` filled with `defaultValue` elements.
+
+		Can be faster than `new Vector(length)` for iteration on some targets for non-nullable elements.
+
+		If `length` is less than or equal to 0, the result is unspecified.
+	**/
+	extern overload public inline function new(length:Int, defaultValue:T):Vector<T> {
+		#if js
+		this = [for (_ in 0...length) defaultValue];
+		#elseif python
+		this = python.Syntax.code("[{0}]*{1}", defaultValue, length);
+		#else
+
+		#if flash10
+		this = new flash.Vector<T>(length, true);
+		#elseif neko
+		this = untyped __dollar__amake(length);
+		#elseif cs
+		this = new cs.NativeArray(length);
+		#elseif java
+		this = new java.NativeArray(length);
+		#elseif cpp
+		this = NativeArray.create(length);
+		#elseif lua
+		this = untyped __lua_table__({length: length});
+		#elseif eval
+		this = new eval.Vector(length);
+		#else
+		this = [];
+		untyped this.length = length;
+		#end
+		fill(defaultValue);
+
+		#end
+	}
+
 	/**
 	/**
 		Returns the value at index `index`.
 		Returns the value at index `index`.
 
 
@@ -141,6 +178,12 @@ abstract Vector<T>(VectorData<T>) {
 		#end
 		#end
 	}
 	}
 
 
+	/**
+		Sets all `length` elements of `this` Vector to `value`.
+	**/
+	public inline function fill(value:T):Void
+		for (i in 0...length) this[i] = value;
+
 	/**
 	/**
 		Copies `length` of elements from `src` Vector, beginning at `srcPos` to
 		Copies `length` of elements from `src` Vector, beginning at `srcPos` to
 		`dest` Vector, beginning at `destPos`
 		`dest` Vector, beginning at `destPos`

+ 10 - 1
std/hl/_std/haxe/ds/Vector.hx

@@ -26,12 +26,18 @@ private typedef VectorData<T> = Array<T>
 
 
 @:coreApi
 @:coreApi
 abstract Vector<T>(VectorData<T>) {
 abstract Vector<T>(VectorData<T>) {
-	public inline function new(length:Int) {
+	extern overload public inline function new(length:Int) {
 		this = [];
 		this = [];
 		if (length > 0)
 		if (length > 0)
 			this[length - 1] = @:nullSafety(Off) cast null;
 			this[length - 1] = @:nullSafety(Off) cast null;
 	}
 	}
 
 
+	extern overload public inline function new(length:Int, defaultValue:T):Vector<T> {
+		this = [
+			for (i in 0...length) defaultValue
+		];
+	}
+
 	@:op([]) public inline function get(index:Int):T {
 	@:op([]) public inline function get(index:Int):T {
 		return this[index];
 		return this[index];
 	}
 	}
@@ -46,6 +52,9 @@ abstract Vector<T>(VectorData<T>) {
 		return this.length;
 		return this.length;
 	}
 	}
 
 
+	public inline function fill(value:T):Void
+		for (i in 0...length) this[i] = value;
+
 	public static inline function blit<T>(src:Vector<T>, srcPos:Int, dest:Vector<T>, destPos:Int, len:Int):Void {
 	public static inline function blit<T>(src:Vector<T>, srcPos:Int, dest:Vector<T>, destPos:Int, len:Int):Void {
 		(cast dest : hl.types.ArrayBase.ArrayAccess).blit(destPos, (cast src : hl.types.ArrayBase.ArrayAccess), srcPos, len);
 		(cast dest : hl.types.ArrayBase.ArrayAccess).blit(destPos, (cast src : hl.types.ArrayBase.ArrayAccess), srcPos, len);
 	}
 	}

+ 14 - 7
std/php/_std/haxe/ds/Vector.hx

@@ -28,19 +28,24 @@ private class PhpVectorData<T> {
 	public var length:Int;
 	public var length:Int;
 	public var data:NativeIndexedArray<T>;
 	public var data:NativeIndexedArray<T>;
 
 
-	public inline function new(length:Int) {
+	public inline function new(length:Int, data:NativeIndexedArray<T>) {
 		this.length = length;
 		this.length = length;
-		data = new NativeIndexedArray();
+		this.data = data;
 	}
 	}
 }
 }
 
 
 private typedef VectorData<T> = PhpVectorData<T>;
 private typedef VectorData<T> = PhpVectorData<T>;
 
 
+@:coreApi
 abstract Vector<T>(VectorData<T>) {
 abstract Vector<T>(VectorData<T>) {
 	public var length(get, never):Int;
 	public var length(get, never):Int;
 
 
-	public inline function new(length:Int) {
-		this = new VectorData(length);
+	extern overload public inline function new(length:Int) {
+		this = new VectorData(length, new NativeIndexedArray());
+	}
+
+	extern overload public inline function new(length:Int, defaultValue:T):Vector<T> {
+		this = new VectorData(length, Global.array_fill(0, length, defaultValue));
 	}
 	}
 
 
 	@:op([]) public inline function get(index:Int):T {
 	@:op([]) public inline function get(index:Int):T {
@@ -55,6 +60,9 @@ abstract Vector<T>(VectorData<T>) {
 		return this.length;
 		return this.length;
 	}
 	}
 
 
+	public inline function fill(value:T):Void
+		this.data = Global.array_fill(0, length, value);
+
 	public static function blit<T>(src:Vector<T>, srcPos:Int, dest:Vector<T>, destPos:Int, len:Int):Void {
 	public static function blit<T>(src:Vector<T>, srcPos:Int, dest:Vector<T>, destPos:Int, len:Int):Void {
 		if (src == dest) {
 		if (src == dest) {
 			if (srcPos < destPos) {
 			if (srcPos < destPos) {
@@ -99,8 +107,7 @@ abstract Vector<T>(VectorData<T>) {
 	}
 	}
 
 
 	static public inline function fromArrayCopy<T>(array:Array<T>):Vector<T> {
 	static public inline function fromArrayCopy<T>(array:Array<T>):Vector<T> {
-		var vectorData = new VectorData(array.length);
-		vectorData.data = @:privateAccess array.arr;
+		var vectorData = new VectorData(array.length, @:privateAccess array.arr);
 		return cast vectorData;
 		return cast vectorData;
 	}
 	}
 
 
@@ -127,7 +134,7 @@ abstract Vector<T>(VectorData<T>) {
 		return result;
 		return result;
 	}
 	}
 
 
-	public inline function sort<T>(f:T->T->Int):Void {
+	public inline function sort(f:T->T->Int):Void {
 		Global.usort(this.data, f);
 		Global.usort(this.data, f);
 	}
 	}
 }
 }

+ 24 - 0
tests/misc/projects/Issue10687/Main.hx

@@ -0,0 +1,24 @@
+class Main {
+	var foo = new Foo();
+	var fooExtern = new Foo();
+	var fooAb = new FooExtern();
+	var vector = new haxe.ds.Vector(1);
+	var vector2 = new haxe.ds.Vector(1, 0);
+	static function main() {}
+}
+
+class Foo {
+	public var length = Std.random(1);
+	public inline function new() {}
+}
+
+class FooExtern {
+	public var length = Std.random(1);
+	extern public inline function new() {}
+}
+
+abstract FooAb({length:Int}) {
+	extern public inline function new() {
+		this = {length: Std.random(1)};
+	}
+}

+ 2 - 0
tests/misc/projects/Issue10687/compile-fail.hxml

@@ -0,0 +1,2 @@
+--main Main
+--interp

+ 1 - 0
tests/misc/projects/Issue10687/compile-fail.hxml.stderr

@@ -0,0 +1 @@
+Main.hx:4: characters 14-29 : Extern constructor could not be inlined

+ 14 - 0
tests/unit/src/unitstd/haxe/ds/Vector.unit.hx

@@ -93,6 +93,20 @@ vec3[4] == 4;
 vec3[5] == 5;
 vec3[5] == 5;
 vec3[6] == 6;
 vec3[6] == 6;
 
 
+var vec5 = new haxe.ds.Vector(3, 5);
+vec5[0] == 5;
+vec5[1] == 5;
+vec5[2] == 5;
+vec5.fill(1);
+vec5[0] == 1;
+vec5[1] == 1;
+vec5[2] == 1;
+
+var vec5 = new haxe.ds.Vector(3, true);
+vec5[0] == true;
+vec5[1] == true;
+vec5[2] == true;
+
 var vec5 = haxe.ds.Vector.fromArrayCopy([0,1,2,3,4]);
 var vec5 = haxe.ds.Vector.fromArrayCopy([0,1,2,3,4]);
 haxe.ds.Vector.blit(vec5, 0, vec5, 1, 4);
 haxe.ds.Vector.blit(vec5, 0, vec5, 1, 4);
 vec5[0] == 0;
 vec5[0] == 0;