ERR/E4.1 (slice 1): log + is_comptime + process.exit/assert (+ noreturn codegen)
Stdlib slice of Phase E4, plus the noreturn codegen fix that enables it. noreturn codegen (the enabling bug): E1.4c made `noreturn` type-system-only; this is its first backend consumer and it crashed LLVM verification. Fixed: - lower.zig: a `-> noreturn` body lowers as statements ending in `unreachable` (ensureTerminator emits unreachable; the two body-lowering sites no longer treat the last expr as a `ret`). - emit_llvm.zig: a `void`/`noreturn` call result stays unnamed (direct + foreign call sites) — LLVM rejects a named void value. - finishCatchHandler: a `noreturn` value-carrying catch body (which is not an IR terminator) closes the handler with `unreachable` instead of feeding a bad value into the merge phi. Shared by lowerCatch + lowerCatchOverChain. is_comptime(): new nullary `.is_comptime` IR op (inst/print/interp/emit_llvm) — interp evaluates true, emit_llvm emits constant false, so `if is_comptime()` dead-codes out of compiled binaries. Recognized by name in tryLowerReflectionCall + inferExprType (no std.sx decl, which would emit a spurious `declare @is_comptime` into every module). library/modules/log.sx: warn/info/debug/err — interpolate like print, write `LEVEL: <msg>` to stderr. (`error` is reserved → the level is `log.err`.) process.exit(code) -> noreturn + assert(cond, msg) in process.sx. `exit` is POSIX `_exit(2)` (immediate, no cleanup; sx print is unbuffered so nothing is lost), bound to "_exit" which also avoids a link-level clash with the sx `exit` function's own name. examples 248 (exit 0), 249 (exit 42), 250 (exit 1). #caller_location, the comptime-exit diagnostic flush, and trace.print_interpreter_frames deferred to E4.1b.
This commit is contained in:
31
examples/248-log-and-comptime.sx
Normal file
31
examples/248-log-and-comptime.sx
Normal file
@@ -0,0 +1,31 @@
|
||||
// `log.sx` leveled logging + the `is_comptime()` builtin (ERR step E4.1,
|
||||
// slice 1). `log.{warn,info,err,debug}` interpolate like `print` and write
|
||||
// `LEVEL: <msg>` to stderr. `is_comptime()` is `true` under `#run` (the
|
||||
// comptime interpreter) and folds to `false` in compiled code, so a gated
|
||||
// branch dead-codes out of the runtime binary.
|
||||
//
|
||||
// (`log.error` is spelled `log.err` — `error` is a reserved keyword. The
|
||||
// `process.exit` / `assert` part of E4.1 is blocked on `noreturn` codegen,
|
||||
// issue 0058.)
|
||||
//
|
||||
// The test runner merges stderr+stdout; the log lines (stderr) precede the
|
||||
// single stdout line. Expected exit code: 0.
|
||||
|
||||
#import "modules/std.sx";
|
||||
log :: #import "modules/log.sx";
|
||||
|
||||
probe :: () -> s32 {
|
||||
if is_comptime() { return 1; } // comptime interpreter path
|
||||
return 2; // compiled-code path
|
||||
}
|
||||
|
||||
CT :: #run probe(); // folds to 1 (run in the interpreter)
|
||||
|
||||
main :: () -> s32 {
|
||||
log.warn("disk {}% full", 91);
|
||||
log.info("user {} connected", "alice");
|
||||
log.err("bad fd {}", 7);
|
||||
log.debug("trace x={}", 42);
|
||||
print("[stdout] is_comptime runtime={} comptime={}\n", probe(), CT);
|
||||
return 0;
|
||||
}
|
||||
15
examples/249-process-exit.sx
Normal file
15
examples/249-process-exit.sx
Normal file
@@ -0,0 +1,15 @@
|
||||
// `process.exit` (ERR step E4.1): immediate process termination with an exit
|
||||
// code. No `defer` / `onfail` cleanup runs and no error-trace frames are pushed
|
||||
// — it's POSIX `_exit(2)`. Here a runtime call exits 42; the line after never
|
||||
// runs. (sx `print` writes unbuffered via `write(2)`, so the "starting" line
|
||||
// still appears despite `_exit` skipping the stdio flush.) Expected exit: 42.
|
||||
|
||||
#import "modules/std.sx";
|
||||
proc :: #import "modules/process.sx";
|
||||
|
||||
main :: () -> s32 {
|
||||
print("starting\n");
|
||||
proc.exit(42);
|
||||
print("unreachable\n");
|
||||
return 0;
|
||||
}
|
||||
15
examples/250-assert.sx
Normal file
15
examples/250-assert.sx
Normal file
@@ -0,0 +1,15 @@
|
||||
// `assert` (ERR step E4.1): a false condition prints `ASSERTION FAILED: <msg>`
|
||||
// and exits 1; a true condition is a no-op. Built on `process.exit`. (The
|
||||
// caller's `file:line` in the message rides on `#caller_location` — E4.1b.)
|
||||
// Expected exit code: 1.
|
||||
|
||||
#import "modules/std.sx";
|
||||
proc :: #import "modules/process.sx";
|
||||
|
||||
main :: () -> s32 {
|
||||
proc.assert(2 + 2 == 4, "arithmetic"); // passes → no-op
|
||||
print("first assert passed\n");
|
||||
proc.assert(2 + 2 == 5, "two plus two is not five"); // fails → abort
|
||||
print("unreachable\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user