Skip to content

Commit

Permalink
[cs] Added support for accessing a Pointer's underlying type's fields
Browse files Browse the repository at this point in the history
  • Loading branch information
waneck committed Nov 5, 2014
1 parent 4316d33 commit b1e92a6
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 13 deletions.
7 changes: 7 additions & 0 deletions gencommon.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions gencs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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") },[])
Expand Down Expand Up @@ -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") }, _ )
Expand Down Expand Up @@ -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 ->
Expand Down
33 changes: 21 additions & 12 deletions std/cs/Pointer.hx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
...
});
Expand Down Expand Up @@ -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>
Expand All @@ -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 changes: 61 additions & 0 deletions tests/unit/src/unit/TestCSharp.hx
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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;
}
}
21 changes: 20 additions & 1 deletion type.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 }

0 comments on commit b1e92a6

Please sign in to comment.