So here is an example.
The FAIL function is very general and
will probably go in the library.
//////
gen FAIL[ret,exn] : exn -> any = "(throw $1,*(?1*)0)";
//////
Unfortunately, you have to give the type "ret" which is the
type of the C++ expression. Felix compiler actually knows this
type from context. However it doesn't know what to do with it
since FAIL is a just an ordinary library binding. The compiler
fools itself into believing the type is that determined by context,
but to get the C++ right you have to specify it anyhow.
Note the function return type is "any". This tells Felix that
the function never returns.
Now here is use in a function:
////////////////////
noinline fun fred (var x: int) =
{
var y = match x with
| 1 => 2
| _ => FAIL[int] "message"
endmatch
;
return y;
}
proc check(x:int)
{
try
var z = fred(x);
println$ z;
catch a:string =>
println$ "FAIL " + a;
endtry
}
check 1;
check 2;
////////////////// RESULT: ////////
2
FAIL message
////////////////////////
Please note the function "fred" is marked noinline.
This is essential in general (although in this case
it works inline or not).
Now a similar example, this time with a procedural
throw:
////////////////////////
noinline fun fred2 (var x: int) =
{
match x with
| 1 => println "ONE";
| _ => FAIL[void] "message";
endmatch
;
return "OK";
}
proc check2(x:int)
{
try
var z = fred2(x);
println$ z;
catch a:string =>
println$ "FAIL " + a;
endtry
}
check2 1;
check2 2;
////////////////////////////////////RESULT
ONE
OK
FAIL message
/////////////////////////////
If you take out the "noinline" then in this case we get instead:
////////////////
ONE
OK
Exception type string : message
/////////////////
The last diagnostic is because the exception is catch in flx_run
in the try block surrounding the scheduler. That's because after
inlining the function fred2, we're probably throwing out of a
continuation -> resume()
method call invoked by the driver, rather than the try/catch block.
It's likely this kind of code will just crash in normal circumstances
because attempting to perform a service call or invoke a procedural
closure, or return, is all implemented by returning "this". The code
expects to be inside a "resume()" method, with no intervening
stack. [However C/C++ will do a return and clean up the stack,
which is why it works in some cases, even if the stack
isn't empty]
The effect of all this is:
the FAIL function is a fully general way of aborting in case of an error,
however such uses of C++ throw does NOT imply a try/catch will work
in all cases it would in C++.
--
john skaller
[email protected]
http://felix-lang.org
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Felix-language mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/felix-language