ERR/E4.1b: #caller_location + Source_Location (+ namespaced default fix, comptime flush)
Finishes Phase E4. `process.exit` / `assert` now report the caller's location.
#caller_location + Source_Location:
- new `hash_caller_location` token (lexer) + a leaf `caller_location` AST node
(parser primary-expr; sema + lsp arms).
- `Source_Location :: struct { file; line; col; func }` in std.sx.
- expandCallDefaults rewrites a `#caller_location` param default to a marker
carrying the CALL site's span + source_file.
- lowerCallerLocation synthesizes the struct: file + line:col via
errors.SourceLoc.compute over the diagnostics file→source map, stamped with
the enclosing (caller) function name. inferExprType resolves it to
Source_Location. Explicitly forwarding a Source_Location through an inner
call preserves the outermost site.
namespaced default-param expansion (pre-existing crash): expandCallDefaults
bailed on field_access callees, so `mod.fn(args)` with an omitted defaulted
param passed too few args → LLVM "incorrect number of arguments". Now resolves
the namespace fd (by field / qualified name); method-on-value calls (where
`self` shifts the count) stay excluded. Prerequisite for process.exit/assert
(always called namespaced) taking `loc = #caller_location`.
comptime flush: interp.callForeign flushes the interpreter's buffered print
output before invoking any host symbol, so a comptime diagnostic emitted just
before a terminating `_exit` (process.exit at comptime) survives.
process.exit/assert take `loc: Source_Location = #caller_location`; assert
prints `ASSERTION FAILED at <file>:<line>: <msg>`. examples 250 (assert
file:line), 251 (caller-location + forwarding). The two ffi-objc *.ir
snapshots are regenerated — adding Source_Location to std.sx renumbers the
global string pool the type/field-name tables index (benign, identical IR).
This commit is contained in:
@@ -426,6 +426,15 @@ pub const Interpreter = struct {
|
||||
|
||||
fn callForeign(self: *Interpreter, func: *const inst_mod.Function, args: []const Value) InterpError!Value {
|
||||
const name = self.module.types.getString(func.name);
|
||||
|
||||
// A foreign call may not return (e.g. `process.exit` → `_exit`), which
|
||||
// would discard the interpreter's buffered `print` output (otherwise
|
||||
// flushed only after `#run` completes). Flush it first so comptime
|
||||
// diagnostics emitted just before a terminating call survive.
|
||||
if (self.output.items.len > 0) {
|
||||
_ = std.c.write(1, self.output.items.ptr, self.output.items.len);
|
||||
self.output.clearRetainingCapacity();
|
||||
}
|
||||
const symbol = (host_ffi.lookupSymbol(self.alloc, name) catch return bailDetail("comptime foreign call: dlsym error looking up symbol")) orelse {
|
||||
if (last_bail_detail == null) last_bail_detail = "comptime foreign call: symbol not found via dlsym (target-specific binding called at compile time?)";
|
||||
return error.CannotEvalComptime;
|
||||
|
||||
Reference in New Issue
Block a user