Prechádzať zdrojové kódy

[cs] Added support for accessing a Pointer's underlying type's fields

Cauê Waneck 11 rokov pred
rodič
commit
b1e92a6c5c
5 zmenil súbory, kde vykonal 126 pridanie a 13 odobranie
  1. 7 0
      gencommon.ml
  2. 17 0
      gencs.ml
  3. 21 12
      std/cs/Pointer.hx
  4. 61 0
      tests/unit/src/unit/TestCSharp.hx
  5. 20 1
      type.ml

+ 7 - 0
gencommon.ml

@@ -1343,6 +1343,13 @@ let field_access gen (t:t) (field:string) : (tfield_access) =
 		underlying type.
 	*)
 
+	(* let pointers to values be accessed as the underlying values *)
+	let t = match gen.greal_type t with
+		| TAbstract({ a_path = ["cs"],"Pointer" },[t]) ->
+			t
+		| _ -> t
+	in
+
 	match follow t with
 		| TInst(cl, params) ->
 			let orig_cl = cl in

+ 17 - 0
gencs.ml

@@ -748,6 +748,13 @@ let configure gen =
 
 	let write_field w name = write w (change_field name) in
 
+	let ptr =
+		if Common.defined gen.gcon Define.Unsafe then
+			get_abstract (get_type gen (["cs"],"Pointer"))
+		else
+			null_abstract
+	in
+
 	gen.gfollow#add ~name:"follow_basic" (fun t -> match t with
 			| TEnum ({ e_path = ([], "Bool") }, [])
 			| TAbstract ({ a_path = ([], "Bool") },[])
@@ -781,6 +788,8 @@ let configure gen =
 			| TAbstract ({ a_path = [],"Single" },[]) -> Some t
 			| TType (({ t_path = [],"Null" } as tdef),[t2]) ->
 					Some (TType(tdef,[follow (gen.gfollow#run_f t2)]))
+			| TAbstract({ a_path = ["cs"],"PointerAccess" },[t]) ->
+					Some (TAbstract(ptr,[t]))
 			| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 					Some (gen.gfollow#run_f ( Abstract.get_underlying_type a pl) )
 			| TAbstract( { a_path = ([], "EnumValue") }, _	)
@@ -1232,6 +1241,14 @@ let configure gen =
 					);
 					write w ".";
 					write_field w (field_name s)
+				| TField (e, s) when is_pointer gen e.etype ->
+					(* take off the extra cast if possible *)
+					let e = match e.eexpr with
+						| TCast(e1,_) when Gencommon.CastDetect.type_iseq gen e.etype e1.etype ->
+							e1
+						| _ -> e
+					in
+					expr_s w e; write w "->"; write_field w (field_name s)
 				| TField (e, s) ->
 					expr_s w e; write w "."; write_field w (field_name s)
 				| TTypeExpr mt ->

+ 21 - 12
std/cs/Pointer.hx

@@ -33,9 +33,9 @@ import cs.StdTypes.Int64;
 			...
 		}
 	Haxe code:
-		var pSrc:cs.Pointer<Int>;
-		cs.Lib.fixed(pSrc = cast src,
-		{
+		var src:NativeArray<Int>;
+		cs.Lib.fixed({
+			var pSrc:cs.Pointer<Int> = cs.Lib.pointerOfArray(src);
 			...
 		});
 
@@ -72,6 +72,20 @@ import cs.StdTypes.Int64;
 	@:op(A<=B) public static function ltep<T>(lhs:Pointer<T>, rhs:Pointer<T>):Bool;
 
 	@:op(~A) public static function bnegp<T>(t:Pointer<T>):Pointer<T>;
+	@:op(A++) public static function prepp<T>(t:Pointer<T>):Pointer<T>;
+	@:op(A--) public static function prenn<T>(t:Pointer<T>):Pointer<T>;
+	@:op(++A) public static function postpp<T>(t:Pointer<T>):Pointer<T>;
+	@:op(--A) public static function postnn<T>(t:Pointer<T>):Pointer<T>;
+
+	/**
+		Returns a `cs.PointerAccess` type, which in turn allows the underlying Pointer's
+		fields to be accessed.
+	 **/
+	// @:analyzer(no_simplification)
+	public var acc(get,never):PointerAccess<T>;
+
+	// @:analyzer(no_simplification)
+	@:extern inline private function get_acc():PointerAccess<T> return (cast this : PointerAccess<T>);
 
 	// backwards compatibility
 	inline public function add(i:Int):Pointer<T>
@@ -84,13 +98,8 @@ import cs.StdTypes.Int64;
 	@:arrayAccess public static function getp<T>(p:Pointer<T>, at:Int64):T;
 	@:arrayAccess public static function setp<T>(p:Pointer<T>, at:Int64, val:T):T;
 }
-//
-// @:native('cs.Pointer') extern class PointerData<T> /*extends Int,*/ implements ArrayAccess<T>
-// {
-// 	static function op_Addition<T>(p:Pointer<T>, i:Int):Pointer<T>;
-// 	public inline function add(i:Int):Pointer<T>
-// 	{
-// 		return op_Addition(this,i);
-// 	}
-// }
+
+@:forward abstract PointerAccess<T>(T)
+{
+}
 #end

+ 61 - 0
tests/unit/src/unit/TestCSharp.hx

@@ -64,6 +64,55 @@ class TestCSharp extends Test
 		test2(other,-2);
 		eq(other[0][0],-2);
 	}
+
+	@:unsafe function testPointerAccess()
+	{
+		var struct = new SomeStruct(10,20);
+		eq(10,struct.int);
+		eq(20.0,struct.float);
+
+		var addr = cs.Lib.addressOf(struct);
+		eq(10,addr.acc.int);
+		eq(20.0,addr.acc.float);
+		addr.acc.int = 22;
+		eq(22,addr.acc.int);
+		eq(22,struct.int);
+
+		addr.acc.float = 42.42;
+		eq(42.42,addr.acc.float);
+		eq(42.42,struct.float);
+
+		var arr = new cs.NativeArray<SomeStruct>(10);
+		cs.Lib.fixed({
+			var arrptr = cs.Lib.pointerOfArray(arr);
+			for (i in 0...10)
+			{
+				(arrptr + i).acc.int = i;
+				(arrptr + i).acc.float = i + i / 10;
+			}
+			var ptr = arrptr;
+			for (i in 0...10)
+			{
+				eq(arr[i].int,i);
+				eq(arr[i].float,i + i / 10);
+
+				eq((arrptr + i).acc.int, i);
+				eq((arrptr + i).acc.float, i + i / 10);
+
+				ptr.acc.int = i *2;
+				ptr.acc.float = (i + i / 10) * 2;
+				ptr++;
+			}
+			for (i in 0...10)
+			{
+				eq(arr[i].int,i*2);
+				eq(arr[i].float,(i + i / 10)*2);
+
+				eq((arrptr + i).acc.int, i*2);
+				eq((arrptr + i).acc.float, (i + i / 10)*2);
+			}
+		});
+	}
 #end
 
 	function testTypes()
@@ -456,3 +505,15 @@ private class TestMyClass extends haxe.test.MyClass
 		return Std.int(super.get_SomeProp2() / 2);
 	}
 }
+
+@:struct @:nativeGen private class SomeStruct
+{
+	public var int:Int;
+	public var float:Float;
+
+	public function new(i,f)
+	{
+		this.int = i;
+		this.float = f;
+	}
+}

+ 20 - 1
type.ml

@@ -419,6 +419,25 @@ let null_class =
 
 let null_field = mk_field "" t_dynamic Ast.null_pos
 
+let null_abstract = {
+	a_path = ([],"");
+	a_module = null_module;
+	a_pos = null_pos;
+	a_private = true;
+	a_doc = None;
+	a_meta = [];
+	a_params = [];
+	a_ops = [];
+	a_unops = [];
+	a_impl = None;
+	a_this = t_dynamic;
+	a_from = [];
+	a_from_field = [];
+	a_to = [];
+	a_to_field = [];
+	a_array = [];
+}
+
 let add_dependency m mdep =
 	if m != null_module && m != mdep then m.m_extra.m_deps <- PMap.add mdep.m_id mdep m.m_extra.m_deps
 
@@ -1905,4 +1924,4 @@ let map_expr_type f ft fv e =
 	| TCast (e1,t) ->
 		{ e with eexpr = TCast (f e1,t); etype = ft e.etype }
 	| TMeta (m,e1) ->
-		{e with eexpr = TMeta(m, f e1); etype = ft e.etype }
+		{e with eexpr = TMeta(m, f e1); etype = ft e.etype }