lang: const-aggregate comptime folds (PLAN-CONST-AGG step 3)

An array const's '.len' and 'K[<const idx>]' element reads, and a
struct const's field ('LIT.r'), fold as compile-time integer leaves —
usable in array dimensions and other constants' initializers. All
source-aware (the SELECTED author's elements, folded in the author's
context with the cyclic-definition frame); a const out-of-range index
diagnoses at fold time, never wraps.

- evalConstIntExpr gains the three ctx hooks (lookupConstAggLen /
  lookupConstArrayElem / lookupConstStructField) + an index_expr arm;
  all five ctx implementations extended (stateless tiers fold null).
- Array consts dual-register in module_const_map (value = the literal
  node) so the folders see elements; bare reads still hit the GLOBAL
  arm first, so no double emission.
- Untyped consts whose RHS is a const-aggregate leaf ('L :: K.len',
  'E :: K[1]', 'R :: LIT.r') register in a pass 2b AFTER aggregates,
  gated on the receiver naming a const aggregate — a namespaced member
  ('F :: m.PI_ISH') is never mis-typed by the count placeholder.

Examples: 0179 (folds in dims + const exprs), 1163 (OOB diagnostic).
This commit is contained in:
agra
2026-06-11 12:44:43 +03:00
parent 7f3bd69bd9
commit c23b76c7d6
14 changed files with 224 additions and 2 deletions

View File

@@ -111,6 +111,15 @@ pub const SourceConstCtx = struct {
pub fn nameIsFloatTyped(self: SourceConstCtx, name: []const u8) bool {
return self.lowering.sourceConstIsFloatTyped(name, self.frame);
}
pub fn lookupConstAggLen(self: SourceConstCtx, name: []const u8) ?i64 {
return self.lowering.foldConstAggLen(name);
}
pub fn lookupConstArrayElem(self: SourceConstCtx, name: []const u8, idx: i64, span: ?ast.Span) ?i64 {
return self.lowering.foldConstArrayElem(name, idx, span, self.frame);
}
pub fn lookupConstStructField(self: SourceConstCtx, name: []const u8, field: []const u8) ?i64 {
return self.lowering.foldConstStructField(name, field, self.frame);
}
};
// ── Scope ───────────────────────────────────────────────────────────────
@@ -773,6 +782,16 @@ pub const Lowering = struct {
return self.sourceConstIsFloatTyped(name, null);
}
pub fn lookupConstAggLen(self: *Lowering, name: []const u8) ?i64 {
return self.foldConstAggLen(name);
}
pub fn lookupConstArrayElem(self: *Lowering, name: []const u8, idx: i64, span: ?ast.Span) ?i64 {
return self.foldConstArrayElem(name, idx, span, null);
}
pub fn lookupConstStructField(self: *Lowering, name: []const u8, field: []const u8) ?i64 {
return self.foldConstStructField(name, field, null);
}
/// Resolve a type node, checking type_bindings first for generic type params.
pub fn resolveTypeWithBindings(self: *Lowering, node: *const Node) TypeId {
// Pack-index in a type position: `$<pack>[<lit>]` resolves to the
@@ -1524,6 +1543,9 @@ pub const Lowering = struct {
pub const selectModuleConst = lower_comptime.selectModuleConst;
pub const GlobalAuthor = lower_comptime.GlobalAuthor;
pub const selectGlobalAuthor = lower_comptime.selectGlobalAuthor;
pub const foldConstAggLen = lower_comptime.foldConstAggLen;
pub const foldConstArrayElem = lower_comptime.foldConstArrayElem;
pub const foldConstStructField = lower_comptime.foldConstStructField;
pub const resolveGlobalRef = lower_comptime.resolveGlobalRef;
pub const sourceModuleConst = lower_comptime.sourceModuleConst;
pub const pinConstAuthorSource = lower_comptime.pinConstAuthorSource;