Error Handling

An overview of error handling and debugging in Stof.

Errors in Stof can occur for various reasons. One example is attempting to call a function that doesn't exist. Another might be giving unexpected arguments that cannot be coerced into the right types or forgetting to provide required arguments.

It is also common to throw custom errors from within Stof according to how you expect your interfaces to be used.

Errors can be caught with the try-catch statement to be handled properly or continued up the stack. The catch block can optionally take an error parameter, with one of three available error types:

  • str - error message only.

  • (str, str) - error type, then error message respectfully.

  • map - an entry for "type: str", "message: str", and "stack: vec", providing a function stack to where the error occurred (the actual function that threw being the last in the vector).

The "throw" function is located in the Standard Library and the Try-Catch statement can be referenced in the Stof Language Reference page.

Library Error

#[main]
fn main() {
    try { // using a "try-catch" block here prevents this function from erroring
        let x = Number.ab(-4); // Should be Number.abs(-4)
    } catch (error: (str, str)) {  // only error message if type is "str" instead
        pln(error);
    }
}
> stof run example.stof
(["NumberLibError(\"NotFound\")", "ab is not a function in the Number Library"])

Throw Custom Error

#[main]
fn main() {
    try {
        throw("CustomError", "you messed up something");
    } catch (error: (str, str)) {
        pln(error);
    }
}
> stof run example.stof
(["CustomError", "you messed up something"])

Debugging

The "trace" & "callstack" functions can be found in the Standard Library.

When an error is thrown in Stof and not handled, it will be printed to the console with its stack information (if using the CLI).

However, it is often nice to programmatically trace the call stack when debugging.

#[main]
fn main() {
    self.first();
}

fn first() {
    trace("getting to first");
    
    let stack = callstack();
    assertEq(stack.first().name(), "main");
    assertEq(stack.last().name(), "first");
}
> stof run example.stof
trace main @ root ...
trace first @ root ...
getting to first

Last updated