Errors and Cleanup
Catch a failure
Section titled “Catch a failure”Nubo uses catch name { ... } directly. There is no try keyword.
fn fail() void { panic("Cannot load account")}
catch err { fail()}
if !isNil(err) { println(err.message) println(string(err))}The block runs immediately. Its binding is an Error on failure and nil on success. panic accepts a message string; creating an Error does not throw it.
Built-in Error and SourceLocation
Section titled “Built-in Error and SourceLocation”These types are global; no import or repeated declaration is needed.
| Type | Fields |
|---|---|
SourceLocation | file: string, line: int, column: int, columnEnd: int |
Error | message: string, base: Error?, metaData: SourceLocation?, stackTrace: []SourceLocation |
let location = SourceLocation("main.nubo", 10, 3, 12)let cause = Error("Database unavailable")let problem = Error("Cannot load account", base: cause, metaData: location)
problem.stackTrace.push(location)
println(typecheck(Error, problem))println(string(problem))Omitted location columns default to zero. Error construction supplies a fresh trace list, and copies a supplied list. Formatting includes source locations, frames, and causes, with circular-cause protection. Caught runtime errors populate available metadata automatically.
Deferred cleanup
Section titled “Deferred cleanup”import io from "@std/io"
fn writeGreeting() void { let file = io.open("greeting.txt", "w")
defer fn() void { file.close() }()
file.write("Hello, Nubo")}
writeGreeting()Deferred calls run in reverse registration order when their owning interpreter scope unwinds, including error paths. defer takes a call, not a function declaration alone.
A spawned worker’s failure is asynchronous: a catch around the launch is not a wait for that worker. Use explicit communication to report completion and results.