Errors

Unlike other programming languages, FOL does not have exceptions (Rust neither). It has only two types of errors:

  • braking errors
  • recoverable errors

Breaking errors cause a program to fail abruptly. A program cannot revert to its normal state if an unrecoverable error occurs. It cannot retry the failed operation or undo the error. An example of an unrecoverable error is trying to access a location beyond the end of an array.

Recoverable error are errors that can be corrected. A program can retry the failed operation or specify an alternate course of action when it encounters a recoverable error. Recoverable errors do not cause a program to fail abruptly. An example of a recoverable error is when a file is not found.

There are two keywords reserved and associated to two types of errors: report for a recoverable error and panic for the braking error.

Breaking error

panic keyword allows a program to terminate immediately and provide feedback to the caller of the program. It should be used when a program reaches an unrecoverable state. This most commonly occurs when a bug of some kind has been detected and it’s not clear to the programmer how to handle the error.

pro main(): int = {
    panic "Hello";
    .echo("End of main");                                                       //unreachable statement
}

In the above example, the program will terminate immediately when it encounters the panic keyword.
Output:

main.fol:3
routine 'main' panicked at 'Hello'
-------

Trying to acces an out of bound element of array:

pro main(): int = {
    var a: arr[int, 3] = [10,20,30];
    a[10];                                                                      //invokes a panic since index 10 cannot be reached
}

Output:

main.fol:4
routine 'main' panicked at 'index out of bounds: the len is 3 but the index is 10'
-------
a[10];
   ^-------- index out of bounds: the len is 3 but the index is 10

A program can invoke panic if business rules are violated, for example: if the value assigned to the variable is odd it throws an error:

pro main(): int = {
   var no = 13; 
   //try with odd and even
   if (no % 2 == 0) {
      .echo("Thank you , number is even");
   } else {
      panic "NOT_AN_EVEN"; 
   }
   .echo("End of main");
}

Output:

main.fol:9
routine 'main' panicked at 'NOT_AN_EVEN'
-------

Recoverable error

report can be used to handle recoverable errors. As discussed here, FOL uses two variables result nd error in return of each subprogram. As name implies, result represents the type of the value that will be returned in a success case, and error represents the type of the error err[] that will be returned in a failure case.

When we use the keyword report, the error is returned to the subprogram’s error variable and the subprogram qutis executing (the subprogram, not the program).

use file: mod[std] = { std::fs::File }

pro main(): int = {
    pro[] fileReader(path: str): str = {
        var aFile = file.readfile(path)
        if ( check(aFile) ) {
            report "File could not be opened" + file                        // report will not break the program, but will return the error here, and the subprogram will stop
        } else {
            return file.to_string()                                         // this will be executed only if file was oopened without error
        }
    }
}

Form this point on, the error is concatinated up to the main function. This is known as propagating the error and gives more control to the calling code, where there might be more information or logic that dictates how the error should be handled than what you have available in the context of your code.

use file: mod[std] = { std::fs::File }

pro main(): int = {
    var f = file.open("main.jpg");                                           // main.jpg doesn't exist
    if (check(f)) {
        report "File could not be opened" + file                             // report will not break the program
    } else {
        .echo("File was open sucessfulley")                                  // this will be executed only if file was oopened without error
    }
}
By default, all errors are either conctinated up with report, or exited with panic.

A simplier way to hande errors is through pipes