fix(bootstrap): resolve lir lower crashes and struct-copy bugs

- Fix lirValToC crash on lvkInt in hStore raw C emission
- Add hAlloca handling to lowerExpr (returns &name, avoids unhandled fallback)
- Fix nested comment syntax in unhandled expr fallback
- Rewrite buildLval to handle hIndexPtr and nested hFieldPtr/hArrowField
  so assignments like arr[i].field = val emit direct C lvalues
- Make &&/|| temporaries unique (__and_tmp_N/__or_tmp_N) to avoid
  duplicate declarations in the same function
- Selfhost null-deref fix in sema.bux (unchained nested conditions)
This commit is contained in:
2026-06-06 21:46:25 +03:00
parent 9416c486b2
commit 3ae8c60ebb
6 changed files with 194 additions and 32 deletions
+25 -3
View File
@@ -539,9 +539,31 @@ proc lowerExpr(ctx: var LowerCtx, expr: Expr): HirNode =
return hirUnary(expr.exprUnaryOp, operand, typ, loc)
of ekBinary:
let left = ctx.lowerExpr(expr.exprBinaryLeft)
let right = ctx.lowerExpr(expr.exprBinaryRight)
return hirBinary(expr.exprBinaryOp, left, right, typ, loc)
case expr.exprBinaryOp
of tkAmpAmp:
# Short-circuit &&: use if-then-else to avoid evaluating right when left is false
let tmp = hirAlloca("__and_tmp_" & $ctx.varCounter, makeBool(), loc)
inc ctx.varCounter
let left = ctx.lowerExpr(expr.exprBinaryLeft)
let thenBlock = hirBlock(@[hirStore(tmp, ctx.lowerExpr(expr.exprBinaryRight), loc)], nil, makeVoid(), loc)
let falseTok = Token(kind: tkBoolLiteral, text: "false", loc: loc)
let elseBlock = hirBlock(@[hirStore(tmp, hirLit(falseTok, makeBool(), loc), loc)], nil, makeVoid(), loc)
let ifNode = hirIf(left, thenBlock, elseBlock, loc)
return hirBlock(@[tmp, ifNode], hirLoad(tmp, makeBool(), loc), makeBool(), loc)
of tkPipePipe:
# Short-circuit ||: use if-then-else to avoid evaluating right when left is true
let tmp = hirAlloca("__or_tmp_" & $ctx.varCounter, makeBool(), loc)
inc ctx.varCounter
let left = ctx.lowerExpr(expr.exprBinaryLeft)
let trueTok = Token(kind: tkBoolLiteral, text: "true", loc: loc)
let thenBlock = hirBlock(@[hirStore(tmp, hirLit(trueTok, makeBool(), loc), loc)], nil, makeVoid(), loc)
let elseBlock = hirBlock(@[hirStore(tmp, ctx.lowerExpr(expr.exprBinaryRight), loc)], nil, makeVoid(), loc)
let ifNode = hirIf(left, thenBlock, elseBlock, loc)
return hirBlock(@[tmp, ifNode], hirLoad(tmp, makeBool(), loc), makeBool(), loc)
else:
let left = ctx.lowerExpr(expr.exprBinaryLeft)
let right = ctx.lowerExpr(expr.exprBinaryRight)
return hirBinary(expr.exprBinaryOp, left, right, typ, loc)
of ekCall:
# Method call desugaring: obj.method(args) → Type_method(obj, args)