ffi M5.A.next.4B.B: compile_error intrinsic — make-green

New reflection-builtin arm in `tryLowerReflectionCall` for
`compile_error(msg)`. Resolves the string literal at lower time,
emits a focused diagnostic at the call site's span via
`self.diagnostics.addFmt(.err, ...)`, and returns a void-typed
constant so the call expression can sit in any statement position.

Three error shapes:

- Zero args → "compile_error requires a string argument".
- Non-string-literal arg → "compile_error argument must be a
  string literal" (we need the message text at lower time;
  runtime expressions can't be reported as compile errors).
- Valid literal → the literal text is the error message verbatim.

`examples/187-compile-error.sx` flips green (the `unresolved`
diagnostic from the lock-in commit becomes the focused
`intentional compile error from #run`). 221/221.
This commit is contained in:
agra
2026-05-28 12:19:12 +03:00
parent 82f291e5af
commit 5dbe12ca57

View File

@@ -8966,6 +8966,28 @@ pub const Lowering = struct {
}
return self.builder.constBool(false);
}
if (std.mem.eql(u8, name, "compile_error")) {
// compile_error(msg) — raise a build-time diagnostic at
// the call site. The argument must be a string literal so
// the message text is available at lower time. Returns a
// void-typed const (the call site is consumed for its
// side effect, not its value).
if (self.diagnostics) |diags| {
if (c.args.len < 1) {
diags.addFmt(.err, c.callee.span, "compile_error requires a string argument", .{});
} else if (c.args[0].data == .string_literal) {
const lit = c.args[0].data.string_literal;
const msg = if (lit.is_raw)
lit.raw
else
unescape.unescapeString(self.alloc, lit.raw) catch lit.raw;
diags.addFmt(.err, c.callee.span, "{s}", .{msg});
} else {
diags.addFmt(.err, c.callee.span, "compile_error argument must be a string literal", .{});
}
}
return self.builder.constInt(0, .void);
}
if (std.mem.eql(u8, name, "field_name")) {
// field_name(T, i) → field_name_get instruction
if (c.args.len < 2) return self.builder.constString(self.module.types.internString(""));