WIP: float numeric-limit accessors (NL.2) — blocked on 0091 (nan != nan); examples/docs pending
This commit is contained in:
@@ -4904,33 +4904,45 @@ pub const Lowering = struct {
|
||||
return self.lowerFieldAccessOnType(obj, obj_ty, fa.field, span);
|
||||
}
|
||||
|
||||
/// Numeric-limit accessor intercept (`<IntType>.min` / `.max`), a sibling of
|
||||
/// the `error.X` / `Struct.CONST` / pack-arity identifier-receiver intercepts
|
||||
/// in `lowerFieldAccess`. Folds an integer type's `.min`/`.max` to a comptime
|
||||
/// const of that type via the shared `TypeResolver` width logic (no second
|
||||
/// width parser) + the existing `constInt` const path. Returns null when this
|
||||
/// is not an integer-limit access, so the caller continues normal field
|
||||
/// lowering. A `.min`/`.max` on a builtin NON-numeric receiver
|
||||
/// (`bool`/`string`/`void`/`Any`/`noreturn`) is a clean diagnostic here (then
|
||||
/// a placeholder, so lowering finishes and `hasErrors()` aborts the build); a
|
||||
/// float receiver falls through (float limits are NL.2).
|
||||
/// Numeric-limit accessor intercept (`<Type>.min`/`.max`/`.epsilon`/
|
||||
/// `.min_positive`/`.true_min`/`.inf`/`.nan`), a sibling of the `error.X` /
|
||||
/// `Struct.CONST` / pack-arity identifier-receiver intercepts in
|
||||
/// `lowerFieldAccess`. Folds the limit to a comptime const of the queried
|
||||
/// type via the shared `TypeResolver` logic (no second computor) + the
|
||||
/// existing `constInt` / `constFloat` const paths:
|
||||
/// - integer `.min`/`.max` → `constInt` (NL.1, via `integerLimitFor`);
|
||||
/// - float `.min`/`.max`/`.epsilon`/`.min_positive`/`.true_min`/`.inf`/
|
||||
/// `.nan` → `constFloat` (via `floatLimitFor`).
|
||||
/// Returns null when the field is not a limit accessor, or the receiver is not
|
||||
/// a builtin type (a user struct → ordinary field lowering reports
|
||||
/// field-not-found). Two clean diagnostics (then a placeholder, so lowering
|
||||
/// finishes and `hasErrors()` aborts the build):
|
||||
/// - a FLOAT-only accessor on an integer type (`s32.epsilon`, `u8.inf`);
|
||||
/// - any accessor on a builtin NON-numeric receiver
|
||||
/// (`bool`/`string`/`void`/`Any`/`noreturn`).
|
||||
fn lowerNumericLimit(self: *Lowering, fa: *const ast.FieldAccess, span: ast.Span) ?Ref {
|
||||
const name = switch (fa.object.data) {
|
||||
.identifier => |id| id.name,
|
||||
.type_expr => |te| te.name,
|
||||
else => return null,
|
||||
};
|
||||
if (!std.mem.eql(u8, fa.field, "min") and !std.mem.eql(u8, fa.field, "max")) return null;
|
||||
if (!TypeResolver.isLimitField(fa.field)) return null;
|
||||
const ty = TypeResolver.resolveBuiltinName(name, &self.module.types) orelse return null;
|
||||
if (TypeResolver.integerLimitFor(name, fa.field)) |value| {
|
||||
return self.builder.constInt(value, ty);
|
||||
}
|
||||
// A builtin receiver that is not an integer: floats are NL.2 (fall
|
||||
// through), every other builtin (bool/string/void/Any/noreturn) has no
|
||||
// numeric limit.
|
||||
if (ty == .f32 or ty == .f64) return null;
|
||||
if (TypeResolver.floatLimitFor(name, fa.field)) |value| {
|
||||
return self.builder.constFloat(value, ty);
|
||||
}
|
||||
// The field is a limit accessor, but it does not apply to this type.
|
||||
if (self.diagnostics) |d| {
|
||||
d.addFmt(.err, span, "type '{s}' has no '.{s}' — numeric limits apply only to integer and float types", .{ name, fa.field });
|
||||
if (TypeResolver.integerWidthSign(name) != null) {
|
||||
// Integer receiver + a float-only accessor.
|
||||
d.addFmt(.err, span, "type '{s}' has no '.{s}' — '.{s}' applies only to float types (f32/f64); integer types expose only '.min'/'.max'", .{ name, fa.field, fa.field });
|
||||
} else {
|
||||
// Non-numeric builtin receiver (bool/string/void/Any/noreturn).
|
||||
d.addFmt(.err, span, "type '{s}' has no '.{s}' — numeric limits apply only to integer and float types", .{ name, fa.field });
|
||||
}
|
||||
}
|
||||
return self.emitPlaceholder(fa.field);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user