fix(selfhost): block scoping for if/while/loop/match bodies

- Create child scope in Sema_CheckBlock for every block, matching
  bootstrap sema.nim behavior (newScope for ekBlock).
- Fixes "var scoping bug in selfhost sema" where variables declared
  with var inside if/while blocks shared parent function scope, causing
  duplicate-definition errors between sibling if/else blocks, and C
  scoping mismatch between user variables and compiled output.
- Remove stale workaround comments from lib/Json.bux (let instead of
  var inside if blocks — no longer needed).
- Update sema.bux TODO comment for type table.
This commit is contained in:
2026-06-09 15:56:16 +03:00
parent 64bd41067a
commit 3ed5891de2
2 changed files with 8 additions and 9 deletions
-2
View File
@@ -89,7 +89,6 @@ func Json_ArrayGet(v: JsonValue, index: uint) -> JsonValue {
func Json_ArrayPush(self: *JsonValue, val: JsonValue) { func Json_ArrayPush(self: *JsonValue, val: JsonValue) {
if self.tag != JsonTagArray { return; } if self.tag != JsonTagArray { return; }
if self.arrLen >= self.arrCap { if self.arrLen >= self.arrCap {
// Compute new capacity (avoid var scoping bug in selfhost sema)
let arrNewCap: uint = self.arrCap; let arrNewCap: uint = self.arrCap;
if arrNewCap == 0 { if arrNewCap == 0 {
self.arrCap = 4; self.arrCap = 4;
@@ -145,7 +144,6 @@ func Json_ObjectSet(self: *JsonValue, key: String, val: JsonValue) {
i = i + 1; i = i + 1;
} }
if self.objLen >= self.objCap { if self.objLen >= self.objCap {
// Compute new capacity (avoid var scoping bug in selfhost sema)
let objNewCap: uint = self.objCap; let objNewCap: uint = self.objCap;
if objNewCap == 0 { if objNewCap == 0 {
self.objCap = 4; self.objCap = 4;
+8 -7
View File
@@ -134,10 +134,9 @@ func Sema_ResolveType(sema: *Sema, te: *TypeExpr) -> int {
if String_Eq(name, "float64") { return tyFloat64; } if String_Eq(name, "float64") { return tyFloat64; }
if String_Eq(name, "float") { return tyFloat64; } if String_Eq(name, "float") { return tyFloat64; }
// Check type table for user-defined types (StringMap not yet supported) // Type resolution uses scope-based lookup via Sema_CollectGlobals
// TODO: re-enable when StringMap generic is available // TODO: add StringMap-based type table for faster named-type validation
// if sema.typeTable != null as *void { ... } return tyNamed;
return tyNamed; // assume named type
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -177,14 +176,16 @@ func Sema_TypeName(kind: int) -> String {
func Sema_CheckBlock(sema: *Sema, block: *Block) { func Sema_CheckBlock(sema: *Sema, block: *Block) {
if block == null as *Block { return; } if block == null as *Block { return; }
// Use current scope directly — only function bodies create new scopes. // Create child scope for block (matching Nim bootstrap behavior)
// This matches Nim bootstrap behavior and fixes variable visibility var blockScope: Scope = Scope_NewChild(sema.scope);
// in nested blocks (if/while bodies). let prevScope: *Scope = sema.scope;
sema.scope = &blockScope;
var stmt: *Stmt = block.firstStmt; var stmt: *Stmt = block.firstStmt;
while stmt != null as *Stmt { while stmt != null as *Stmt {
Sema_CheckStmt(sema, stmt); Sema_CheckStmt(sema, stmt);
stmt = stmt.nextStmt; stmt = stmt.nextStmt;
} }
sema.scope = prevScope;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------