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.
30 lines
1.4 KiB
Plaintext
30 lines
1.4 KiB
Plaintext
#import "std.sx";
|
|
|
|
// =====================================================================
|
|
// log.sx — plain leveled logging (ERR step E4.1), orthogonal to the
|
|
// error channel. Each entry is written to stderr as `LEVEL: <msg>\n`,
|
|
// where <msg> is the formatted `fmt` + args (same `{}` interpolation as
|
|
// `print`). Sink is stderr (fd 2) so log output stays out of a program's
|
|
// stdout data stream.
|
|
//
|
|
// Note: PLAN-ERR §log sketches a `LEVEL ts msg` line with an ISO-8601
|
|
// UTC timestamp. The timestamp is deferred — it needs a clock binding
|
|
// and would make golden tests time-dependent; the level + message are
|
|
// the load-bearing parts. Add `ts` once a pinnable clock lands.
|
|
// =====================================================================
|
|
|
|
libc :: #library "c";
|
|
|
|
write :: (fd: s32, buf: [*]u8, count: usize) -> isize #foreign libc;
|
|
|
|
// Prefix the level, append a newline, write the whole line to stderr.
|
|
emit :: (level: string, msg: string) {
|
|
line := concat(concat(level, msg), "\n");
|
|
write(2, line.ptr, xx line.len);
|
|
}
|
|
|
|
warn :: ($fmt: string, ..$args) { #insert build_format(fmt); #insert "emit(\"WARN: \", result);"; }
|
|
info :: ($fmt: string, ..$args) { #insert build_format(fmt); #insert "emit(\"INFO: \", result);"; }
|
|
debug :: ($fmt: string, ..$args) { #insert build_format(fmt); #insert "emit(\"DEBUG: \", result);"; }
|
|
err :: ($fmt: string, ..$args) { #insert build_format(fmt); #insert "emit(\"ERROR: \", result);"; }
|