&TA pointer can be created by addressing a variable using the notation:
&vPointers can be dereferenced using the usual syntax:
*pand there is the usual arrow notation:
p->xwhich means the same as
(*p).x
Only variables, not values, are addressable. Pointers are used to implement assignment. You have seen many examples of assignment:
var v : T; v = e;What you didn't know was that the assignment operator is just syntactic sugar for the procedure call:
set(&v,e);This procedure is defined automatically for structs, unions, and function and procedure closures, that is, for Felix types; but you can define it manually for abstract types including primitives. The usual definition is:
type T = "T"; proc _set: &T * t = "*$1=$2;"If you don't define a set method for a primitive type, Felix assumes the C++ assignment operator as above. WARNING: This is wrong in principle, since Felix cannot check such a function exists, if it doesn't, you will get an error at C++ compilation time instead of Felix compilation time. Be warned!
Note that all Felix primitives must be C++ assignable and implicitly default constructible, since in the generated code all values and variables are first declared without an initialiser and then assigned to.
It is important to note that in Felix, you can take the address of any variable, and safely pass the pointer around, without fear it will dangle: this includes pointers to function and procedure local variables.
This all works because Felix uses a garbage collector, but you should note that because the frame containing an object must be kept alive if there is a pointer into it, returning a pointer to a function local variable may prevent other local variables in the same frame from being destroyed.
1: include "std"; 2: 3: fun pone (): &int = 4: { 5: var x : int = 1; 6: return &x; 7: } 8: 9: var p1 = pone(); 10: print (*p1); endl; 11: *p1 = 2; 12: 13: print (*p1); endl; 14: