base/runtime: Add ensure and ensure_contextless

This provides an equivalent to `assert` and `assert_contextless` that
are always evaluated, ignoring `ODIN_DISABLE_ASSERT`, which is useful
for enforcing API contracts or "asserting" on conditionals with
side-effects.
This commit is contained in:
Yawning Angel
2024-12-23 14:15:59 +09:00
parent ad99d20d29
commit 3a5440e4ed

View File

@@ -964,6 +964,24 @@ assert :: proc(condition: bool, message := #caller_expression(condition), loc :=
}
}
// Evaluates the condition and aborts the program iff the condition is
// false. This routine ignores `ODIN_DISABLE_ASSERT`, and will always
// execute.
@builtin
ensure :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) {
if !condition {
@(cold)
internal :: proc(message: string, loc: Source_Code_Location) {
p := context.assertion_failure_proc
if p == nil {
p = default_assertion_failure_proc
}
p("unsatisfied ensure", message, loc)
}
internal(message, loc)
}
}
@builtin
panic :: proc(message: string, loc := #caller_location) -> ! {
p := context.assertion_failure_proc
@@ -999,6 +1017,17 @@ assert_contextless :: proc "contextless" (condition: bool, message := #caller_ex
}
}
@builtin
ensure_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) {
if !condition {
@(cold)
internal :: proc "contextless" (message: string, loc: Source_Code_Location) {
default_assertion_contextless_failure_proc("unsatisfied ensure", message, loc)
}
internal(message, loc)
}
}
@builtin
panic_contextless :: proc "contextless" (message: string, loc := #caller_location) -> ! {
default_assertion_contextless_failure_proc("panic", message, loc)