Error Handling
Try/catch/finally for exception handling, throw for raising errors.
Try / Catch / Finally
try / catch / finally
Handles exceptions with try/catch blocks, using end-delimited syntax just like if, while, and for.
# Basic try/catch
try
let result = 10 / 0
catch e
print("Error: " + str(e))
end
# With finally (always runs)
try
let data = read_file("config.sl")
print(data)
catch e
print("Failed: " + str(e))
finally
print("Cleanup done")
end
# Try/finally without catch
try
process_data()
finally
close_connection()
end
Catch Variable Syntax
The catch variable can be written with or without parentheses:
# Without parentheses
try
risky()
catch e
print(e)
end
# With parentheses
try
risky()
catch (e)
print(e)
end
Throwing Exceptions
throw
Raises an exception that can be caught by a surrounding try/catch block.
def divide(a: Int, b: Int) -> Int
if b == 0
throw "Division by zero"
end
a / b
end
try
let result = divide(10, 0)
catch e
print("Caught: " + str(e)) # "Caught: Division by zero"
end
End Syntax
Try/catch supports end-delimited blocks:
try
let result = risky_operation()
catch e
print("Error: " + str(e))
finally
cleanup()
end
Typed Catch
catch ClassName e
Catch specific error types by class name. Multiple catch blocks are tried in order. A bare catch without a type acts as a catch-all.
# Define error classes
class NotFoundError
message: String
new(msg: String)
this.message = msg
end
end
class ValidationError
message: String
new(msg: String)
this.message = msg
end
end
# Multiple typed catch blocks
try
throw new NotFoundError("User not found")
catch NotFoundError e
print("404: " + e.message)
catch ValidationError e
print("Invalid: " + e.message)
catch e
print("Unknown error: " + str(e))
end
Catching by Superclass
Typed catches walk the inheritance chain. A catch BaseError will also catch any subclass of BaseError.
class AppError
message: String
new(msg: String)
this.message = msg
end
end
class NotFoundError extends AppError
new(msg: String)
super(msg)
end
end
class PermissionError extends AppError
new(msg: String)
super(msg)
end
end
# Catches NotFoundError because it extends AppError
try
throw new NotFoundError("Page not found")
catch AppError e
print("App error: " + e.message)
end
Unmatched Exceptions
If no typed catch matches, the exception is re-thrown to the next outer try/catch. Add a bare catch at the end to handle all remaining exceptions.
class ErrorA {}
class ErrorB {}
try
try
throw new ErrorB()
catch ErrorA e
# Does NOT match ErrorB
print("A")
end
catch e
# ErrorB bubbles up here
print("Caught in outer: " + str(e))
end
Typed Catch Rules
- Typed catches only match class instances (strings, ints, etc. will not match)
- Catches are tried in order — put more specific types first
- A bare
catch ecatches everything (including non-instance values) - Subclasses match their parent class catches (walks the inheritance chain)
- Works with both
endand{}syntax
Nested Try/Catch
Try/catch blocks can be nested for fine-grained error handling:
try
print("Outer try")
try
throw "inner error"
catch e
print("Inner catch: " + str(e))
end
print("After inner try")
catch e
print("Outer catch: " + str(e))
end