Warning: currently there's a serious bug in flx: it does not rebuild 
if the *.flx file is changed. It is supposed to do that! You will need to use 
--force
until I fix it!

Now: here is the beauty of Felix!

////////////////////////////
sthe_name : = "@" sthe_name =># "(Prefix)";
typedef fun n"@" (T:TYPE) : TYPE => cptr[T]; 
typedef ptr[T] = &T;
union cptr[T] = | nullptr | Ptr of &T;

ctor[T] cptr[T]: &T -> @T = "$1"; // safe
ctor[T] ptr[T]( px:@T) => let Ptr  ?p = px in p; // match failure if null
fun deref[T] (px:@T)=> *(px.ptr); // checked deref
fun is_nullptr[T] (px:@T)=> match px with | nullptr => true | _ => false 
endmatch;
/////////////////////////

Enforced NULL pointer checking in 9 lines of code without touching
the compiler.

The grammar production:

sthe_name : = "@" sthe_name =># "(Prefix)";

is not necessary, it just fixes the precedence of the operator:
without it also, @ is not a legal identifier so you would have to
reuse one: I initially used "^" which is reminder of Pascal.
Potential confusion with infix ^, but the resolution is similar
to * and - which also have infix and prefix forms.

The notation:

        n"@"

used in the typedef is a little secret of Felix: any string can be
used as an identifier with that notation. By the grammar we have to
define a function named "@" but it isn't a legal identifier, so we
just force it.

The typedefs introduced next: ptr, cptr, are there only because
it is necessary for ctor definition. Ctors require an identifier
as a typename. Multiple constructors can be made for any type
from the same type, but you have to make typedefs so you can name them 
differently.
This is how "complex" and "polar" are used to construct the same type (complex)
from the same argument (double * double) but give different results.

The actual cptr type is a TRICK. It depends on the representation to work.

The conversion &T -> @T is safe so the function is an identity.
The conversion @T -> &T is checked by tricking the compiler into generating a 
match failure.
Note that "let Ptr ?p = px in p" is just match px with | Ptr ?p => p | _ => 
assert 'match_failure' endmatch;"
If you screw up you get this:

Match Failure
Felix location: /Users/johnskaller/felix/./abc.flx 6[27]-6[47]
C++ location  : 
/Users/johnskaller/.felix/cache/text//Users/johnskaller/felix/./abc.cpp 68

which tells you you have a null ptr issue, but not where it is :)

// test code

var x = nullptr[int];
fun str[T] (px: @T) =>
  match px with
  | nullptr => "NULLPTR"
  | Ptr ?p => "Address " + p.address.str
  endmatch
;

println$ str x;
//println$ *x;

var a = 42;
x = Ptr (&a);

println$ str x;;

println$ *x;

const null: cptr[int] = "NULL";

println$ is_nullptr null;

--
john skaller
skal...@users.sourceforge.net





------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to