diff --git a/src/cli.bux b/src/cli.bux index 728d3c4..d97b00d 100644 --- a/src/cli.bux +++ b/src/cli.bux @@ -114,6 +114,17 @@ func Cli_Compile(source: String, sourceName: String) -> String { // --------------------------------------------------------------------------- func Cli_Build(srcPath: String, outPath: String) -> int { + // If building the standard project entry point, use full project build + // which merges stdlib and supports multi-file projects + if String_Eq(srcPath, "src/Main.bux") || String_Eq(srcPath, "src/main.bux") { + let rc: int = Cli_BuildProject("."); + if rc == 0 && !String_Eq(outPath, "build/main") { + // Rename output if custom path was requested + bux_system(String_Concat(String_Concat("mv build/main ", outPath), " 2>/dev/null || true")); + } + return rc; + } + let source: String = ReadFile(srcPath); if source == null as String || String_Eq(source, "") || !FileExists(srcPath) { Print("Error: cannot read source file: "); diff --git a/src/hir_lower.bux b/src/hir_lower.bux index 92eb4c4..9ab41b3 100644 --- a/src/hir_lower.bux +++ b/src/hir_lower.bux @@ -1221,9 +1221,9 @@ func Lcx_LowerStmt(ctx: *LowerCtx, stmt: *Stmt) -> *HirNode { // let x = Iter_Next_T(&__iter); // body // } - if iterExpr != null as *Expr && iterExpr.kind == ekIdent { + if iterExpr != null as *Expr { let collTypeExpr: *TypeExpr = iterExpr.refType; - if collTypeExpr == null as *TypeExpr { + if collTypeExpr == null as *TypeExpr && iterExpr.kind == ekIdent { // Fallback: try scope lookup (may have substituted type) let collSym: Symbol = Scope_Lookup(ctx.scope, iterExpr.strValue); collTypeExpr = collSym.refType; @@ -1309,6 +1309,7 @@ func Lcx_LowerStmt(ctx: *LowerCtx, stmt: *Stmt) -> *HirNode { // __iter = Array_Iter_T(&arr) or just copy if already Iter var iterInit: *HirNode = null as *HirNode; + var collStore: *HirNode = null as *HirNode; if isArray { let callIter: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; callIter.kind = hCall; @@ -1316,18 +1317,47 @@ func Lcx_LowerStmt(ctx: *LowerCtx, stmt: *Stmt) -> *HirNode { let addrArr: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; addrArr.kind = hUnary; addrArr.intValue = tkAmp; - let arrVar: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; - arrVar.kind = hVar; - arrVar.strValue = iterExpr.strValue; - addrArr.child1 = arrVar; + if iterExpr.kind == ekIdent { + let arrVar: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; + arrVar.kind = hVar; + arrVar.strValue = iterExpr.strValue; + addrArr.child1 = arrVar; + } else { + // Non-identifier: create temp variable for collection + ctx.varCounter = ctx.varCounter + 1; + let tmpName: String = String_Concat("__tmp_coll_", String_FromInt(ctx.varCounter)); + // Ensure Array struct instance exists and get mangled name + let arrayGenStruct: *Decl = Lcx_FindGenericStruct(ctx, "Array"); + var arrayMangledName: String = collTypeName; + if arrayGenStruct != null as *Decl { + arrayMangledName = Lcx_GenerateStructInstance(ctx, arrayGenStruct, elemTypeName, "", 1); + } + let collAlloca: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; + collAlloca.kind = hAlloca; + collAlloca.strValue = tmpName; + collAlloca.typeName = arrayMangledName; + collAlloca.typeKind = tyNamed; + collStore = bux_alloc(sizeof(HirNode)) as *HirNode; + collStore.kind = hStore; + collStore.child1 = collAlloca; + collStore.child2 = Lcx_LowerExpr(ctx, iterExpr); + let collVar: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; + collVar.kind = hVar; + collVar.strValue = tmpName; + addrArr.child1 = collVar; + } callIter.child1 = addrArr; iterInit = callIter; } else { // Already an iterator: __iter = arr - let arrVar: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; - arrVar.kind = hVar; - arrVar.strValue = iterExpr.strValue; - iterInit = arrVar; + if iterExpr.kind == ekIdent { + let arrVar: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; + arrVar.kind = hVar; + arrVar.strValue = iterExpr.strValue; + iterInit = arrVar; + } else { + iterInit = Lcx_LowerExpr(ctx, iterExpr); + } } let iterStore: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; @@ -1335,6 +1365,11 @@ func Lcx_LowerStmt(ctx: *LowerCtx, stmt: *Stmt) -> *HirNode { iterStore.child1 = iterAlloca; iterStore.child2 = iterInit; + // Chain collStore -> iterStore if temp was created + if collStore != null as *HirNode { + collStore.child3 = iterStore; + } + // condition: Iter_HasNext_T(&__iter) let condCall: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; condCall.kind = hCall; @@ -1401,7 +1436,11 @@ func Lcx_LowerStmt(ctx: *LowerCtx, stmt: *Stmt) -> *HirNode { blockNode.kind = hBlock; blockNode.line = line; blockNode.column = col; - blockNode.child1 = iterStore; + if collStore != null as *HirNode { + blockNode.child1 = collStore; + } else { + blockNode.child1 = iterStore; + } return blockNode; } } diff --git a/src/sema.bux b/src/sema.bux index 1b4bf30..6c0b828 100644 --- a/src/sema.bux +++ b/src/sema.bux @@ -579,6 +579,7 @@ func Sema_CheckExpr(sema: *Sema, expr: *Expr) -> int { if calleeType == tyFunc { if expr.child1.refType != null as *TypeExpr && expr.child1.refType.kind == tekFunc { if expr.child1.refType.funcRet != null as *TypeExpr { + expr.refType = expr.child1.refType.funcRet; return Sema_ResolveType(sema, expr.child1.refType.funcRet); } return tyVoid; @@ -589,6 +590,7 @@ func Sema_CheckExpr(sema: *Sema, expr: *Expr) -> int { let sym: Symbol = Scope_Lookup(sema.scope, expr.child1.strValue); if sym.kind == skFunc && sym.decl != null as *Decl { if sym.decl.retType != null as *TypeExpr { + expr.refType = sym.decl.retType; return Sema_ResolveType(sema, sym.decl.retType); } }