fix(selfhost): collection-based for-in with Std::Array + monomorphization fixes

- Fix Fmt_Format name conflict between lib/Fmt.bux and src/fmt.bux
  by renaming selfhost formatter function to Fmt_FormatSource.

- Fix collection-based for-in loops to handle already-monomorphized
  types like Array_int and Iter_string (typeArgCount=0 cases).

- Fix ekSizeOf and ekCast in HIR lowering to apply Lcx_SubstituteType
  during generic monomorphization, so sizeof(T) and *T casts emit
  correct concrete types in C output.

- Fix sema to infer stmt.refStmtType from initializer expression
  when no explicit type annotation is given, ensuring C backend
  emits correct pointer types for let data = ... as *T.
This commit is contained in:
2026-06-10 01:15:21 +03:00
parent 632fa1535c
commit 499b389ba8
3 changed files with 59 additions and 11 deletions
+2 -2
View File
@@ -73,7 +73,7 @@ func Fmt_CountBraceDelta(line: String) -> int {
return delta;
}
func Fmt_Format(source: String) -> String {
func Fmt_FormatSource(source: String) -> String {
let sb: StringBuilder = StringBuilder_NewCap(8192);
var indent: int = 0;
var i: uint = 0;
@@ -130,7 +130,7 @@ func Fmt_Format(source: String) -> String {
func Fmt_FormatFile(path: String) -> bool {
let source: String = bux_read_file(path);
if source == null as String || String_Eq(source, "") { return false; }
let formatted: String = Fmt_Format(source);
let formatted: String = Fmt_FormatSource(source);
if String_Eq(formatted, "") { return false; }
return bux_write_file(path, formatted);
}
+45 -6
View File
@@ -2,6 +2,8 @@
// Transforms the typed AST into a lower-level IR suitable for code generation.
module HirLower {
extern func bux_str_slice(s: String, start: uint, len: uint) -> String;
extern func bux_strlen(s: String) -> uint;
// ---------------------------------------------------------------------------
// Lowering context
@@ -619,8 +621,13 @@ func Lcx_LowerExpr(ctx: *LowerCtx, expr: *Expr) -> *HirNode {
if kind == ekSizeOf {
n.kind = hSizeOf;
if expr.refType != null as *TypeExpr {
let substTe: *TypeExpr = Lcx_SubstituteType(ctx, expr.refType);
if substTe != null as *TypeExpr {
n.typeName = substTe.typeName;
} else {
n.typeName = expr.refType.typeName;
}
}
return n;
}
@@ -704,13 +711,15 @@ func Lcx_LowerExpr(ctx: *LowerCtx, expr: *Expr) -> *HirNode {
n.kind = hCast;
n.child1 = Lcx_LowerExpr(ctx, expr.child1);
if expr.refType != null as *TypeExpr {
let resolvedKind: int = Lcx_ResolveTypeKind(expr.refType);
let substTe: *TypeExpr = Lcx_SubstituteType(ctx, expr.refType);
if substTe == null as *TypeExpr { substTe = expr.refType; }
let resolvedKind: int = Lcx_ResolveTypeKind(substTe);
n.typeKind = resolvedKind;
// For pointer types, construct "PointeeType*"
if expr.refType.kind == tekPointer && expr.refType.pointerPointee != null as *TypeExpr {
n.typeName = String_Concat(expr.refType.pointerPointee.typeName, "*");
} else if !String_Eq(expr.refType.typeName, "") {
n.typeName = expr.refType.typeName;
if substTe.kind == tekPointer && substTe.pointerPointee != null as *TypeExpr {
n.typeName = String_Concat(substTe.pointerPointee.typeName, "*");
} else if !String_Eq(substTe.typeName, "") {
n.typeName = substTe.typeName;
}
}
return n;
@@ -1082,10 +1091,40 @@ func Lcx_LowerStmt(ctx: *LowerCtx, stmt: *Stmt) -> *HirNode {
elemTypeKind = Lcx_ResolveTypeKindFromName(elemTypeName);
}
if !String_Eq(elemTypeName, "") {
// Handle already-monomorphized types like Array_int, Iter_string
var isArray: bool = String_Eq(collTypeName, "Array");
var isIter: bool = String_Eq(collTypeName, "Iter");
if String_Eq(elemTypeName, "") {
// Manual prefix check for "Array_"
var isArrayPrefix: bool = false;
var isIterPrefix: bool = false;
let collName: String = collTypeName;
if collName[0] as int == 65 && collName[1] as int == 114 && collName[2] as int == 114 && collName[3] as int == 97 && collName[4] as int == 121 && collName[5] as int == 95 {
isArrayPrefix = true;
}
if collName[0] as int == 73 && collName[1] as int == 116 && collName[2] as int == 101 && collName[3] as int == 114 && collName[4] as int == 95 {
isIterPrefix = true;
}
if isArrayPrefix {
isArray = true;
let prefixLen: uint = 6; // len("Array_")
let totalLen: uint = bux_strlen(collTypeName);
if totalLen > prefixLen {
elemTypeName = bux_str_slice(collTypeName, prefixLen, totalLen - prefixLen);
elemTypeKind = Lcx_ResolveTypeKindFromName(elemTypeName);
}
} else if isIterPrefix {
isIter = true;
let prefixLen: uint = 5; // len("Iter_")
let totalLen: uint = bux_strlen(collTypeName);
if totalLen > prefixLen {
elemTypeName = bux_str_slice(collTypeName, prefixLen, totalLen - prefixLen);
elemTypeKind = Lcx_ResolveTypeKindFromName(elemTypeName);
}
}
}
if !String_Eq(elemTypeName, "") {
if isArray || isIter {
let iterVarName: String = String_Concat("__iter_", varName);
let iterTypeName: String = Lcx_MangleName("Iter", elemTypeName, "", 1);
+9
View File
@@ -756,6 +756,15 @@ func Sema_CheckStmt(sema: *Sema, stmt: *Stmt) {
} else {
sym.typeName = stmt.refStmtType.typeName;
}
} else if stmt.child1 != null as *Expr && stmt.child1.refType != null as *TypeExpr {
// Infer type from initializer expression
sym.refType = stmt.child1.refType;
stmt.refStmtType = stmt.child1.refType;
if stmt.child1.refType.kind == tekPointer && stmt.child1.refType.pointerPointee != null as *TypeExpr {
sym.typeName = String_Concat(stmt.child1.refType.pointerPointee.typeName, "*");
} else {
sym.typeName = stmt.child1.refType.typeName;
}
}
sym.isMutable = stmt.boolValue;
sym.isPublic = false;