Exception handling with Nasal: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
m (Syntax highlight and remove (extraneous) heading)
m (Use Nasal highlighter)
 
Line 4: Line 4:
<tt>die()</tt> aborts a function with an error message (this can be compared to the throw() mechanism in C++).
<tt>die()</tt> aborts a function with an error message (this can be compared to the throw() mechanism in C++).


<syntaxhighlight lang="php">
<syntaxhighlight lang="nasal">
var divide = func(a, b) {
var divide = func(a, b) {
     if (b == 0)
     if (b == 0)
Line 14: Line 14:
die() is also used internally by built-in extension functions or Nasal core functions. <tt>getprop("/4me")</tt>, for example, dies with an error message ''"name must begin with alpha or '_'"''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to <tt>getprop()</tt>? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The <tt>call()</tt> function can catch <tt>die()</tt> exceptions:
die() is also used internally by built-in extension functions or Nasal core functions. <tt>getprop("/4me")</tt>, for example, dies with an error message ''"name must begin with alpha or '_'"''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to <tt>getprop()</tt>? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The <tt>call()</tt> function can catch <tt>die()</tt> exceptions:


<syntaxhighlight lang="php">
<syntaxhighlight lang="nasal">
var value = getprop(property);                                    # dies if 'property' is invalid
var value = getprop(property);                                    # dies if 'property' is invalid
var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues
var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues
Line 21: Line 21:
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the <tt>call()</tt> function catches the exception and sets the 'err' vector instead. That vector remains empty on success.
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the <tt>call()</tt> function catches the exception and sets the 'err' vector instead. That vector remains empty on success.


<syntaxhighlight lang="php">
<syntaxhighlight lang="nasal">
if (size(err))
if (size(err))
     print("ERROR: bad property ", property, " (", err[0], ")");  # err[0] contains the die() message
     print("ERROR: bad property ", property, " (", err[0], ")");  # err[0] contains the die() message
Line 32: Line 32:
<tt>die()</tt> doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.
<tt>die()</tt> doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.


<syntaxhighlight lang="php">
<syntaxhighlight lang="nasal">
var Error = {                                                            # exception class
var Error = {                                                            # exception class
     new: func(msg, number) {
     new: func(msg, number) {

Latest revision as of 21:07, 10 November 2013


die() aborts a function with an error message (this can be compared to the throw() mechanism in C++).

var divide = func(a, b) {
    if (b == 0)
        die("division by zero");
    return a / b;     # this line won't be reached if b == 0
}

die() is also used internally by built-in extension functions or Nasal core functions. getprop("/4me"), for example, dies with an error message "name must begin with alpha or '_'". Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to getprop()? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The call() function can catch die() exceptions:

var value = getprop(property);                                    # dies if 'property' is invalid
var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues

The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the call() function catches the exception and sets the 'err' vector instead. That vector remains empty on success.

if (size(err))
    print("ERROR: bad property ", property, " (", err[0], ")");   # err[0] contains the die() message
else
    print("value of ", property, " is ", value);

The first argument of call() is a function object, the second a vector of function arguments (or nil), and the third a vector where the function will return a possible error. For more information on the call() function see the Nasal library documentation.

die() doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.

var Error = {                                                             # exception class
    new: func(msg, number) {
        return { parents: [Error], message: msg, number: number };
    },
};

var A = func(a) {
    if (a < 0)
        die(Error.new("negative argument to A", a));                      # throw Error
    return "A received " ~ a;
}

var B = func(val) {
    var result = A(val);
    print("B finished");      # this line is not reached if A threw an exception
    return result;
}

var value = call(B, [-4], var err = []);                                  # try B(-4)

if (size(err)) {                                                          # catch (...)
    print("ERROR: ", err[0].message, "; bad value was ", err[0].number);
    die(err[0]);                                                          # re-throw
} else {
    print("SUCCESS: ", value);
}