diff --git a/apps/boko-framework/src/Boko.bux b/apps/boko-framework/src/Boko.bux index 77371cb..7afe4bd 100644 --- a/apps/boko-framework/src/Boko.bux +++ b/apps/boko-framework/src/Boko.bux @@ -242,8 +242,7 @@ func Query_Parse(queryString: String) -> StringMap { } let pairCount: uint = String_SplitCount(queryString, "&"); - var i: uint = 0; - while i < pairCount { + for i in 0..pairCount { let pair: String = String_SplitPart(queryString, "&", i); let eqPos: String = String_Find(pair, "="); var key: String = pair; @@ -258,7 +257,6 @@ func Query_Parse(queryString: String) -> StringMap { } } StringMap_Set(&map, key, value); - i = i + 1; } return map; } @@ -317,8 +315,7 @@ func Request_Parse(raw: String) -> Request { } // Parse headers - var i: uint = 1; - while i < lineCount { + for i in 1..lineCount { let line: String = String_SplitPart(headerBlock, "\r\n", i); let colonPos: String = String_Find(line, ": "); if !String_IsNull(colonPos) { @@ -332,7 +329,6 @@ func Request_Parse(raw: String) -> Request { } StringMap_Set(&req.headers, key, value); } - i = i + 1; } return req; @@ -349,8 +345,7 @@ func Path_Match(pattern: String, path: String, req: *Request) -> bool { req.pathParams = StringMap_New(8); - var i: uint = 0; - while i < patParts { + for i in 0..patParts { let patPart: String = String_SplitPart(pattern, "/", i); let pathPart: String = String_SplitPart(path, "/", i); @@ -361,7 +356,6 @@ func Path_Match(pattern: String, path: String, req: *Request) -> bool { } else { if !String_Eq(patPart, pathPart) { return false; } } - i = i + 1; } return true; @@ -462,10 +456,8 @@ func App_Run(app: *App) { PrintLine(""); // Spawn workers - var i: int = 0; - while i < app.threadCount - 1 { + for i in 0..(app.threadCount - 1) { spawn App_Worker(fd); - i = i + 1; } // Main thread is the last worker diff --git a/bootstrap/hir_lower.nim b/bootstrap/hir_lower.nim index 73760e4..7f62e41 100644 --- a/bootstrap/hir_lower.nim +++ b/bootstrap/hir_lower.nim @@ -481,7 +481,15 @@ proc resolveExprType(ctx: var LowerCtx, expr: Expr): Type = return makeSlice(makeUnknown()) of ekRange: let loType = ctx.resolveExprType(expr.exprRangeLo) - return makeRange(loType) + let hiType = ctx.resolveExprType(expr.exprRangeHi) + if loType == hiType: + return makeRange(loType) + elif loType.isAssignableTo(hiType): + return makeRange(hiType) + elif hiType.isAssignableTo(loType): + return makeRange(loType) + else: + return makeRange(loType) of ekTuple: var elems: seq[Type] = @[] for e in expr.exprTupleElements: @@ -1377,7 +1385,8 @@ proc lowerStmt(ctx: var LowerCtx, stmt: Stmt): HirNode = let inclusive = iterExpr.exprRangeInclusive # Determine loop variable type from range bounds - let varType = ctx.resolveExprType(iterExpr.exprRangeLo) + let rangeType = ctx.resolveExprType(iterExpr) + let varType = if rangeType.inner.len > 0: rangeType.inner[0] else: ctx.resolveExprType(iterExpr.exprRangeLo) # Create: var i = lo; while i < hi { body; i = i + 1; } let initStmt = hirAlloca(varName, varType, loc) diff --git a/bootstrap/sema.nim b/bootstrap/sema.nim index b4a04ee..1473c73 100644 --- a/bootstrap/sema.nim +++ b/bootstrap/sema.nim @@ -1007,9 +1007,16 @@ proc checkExpr(sema: var Sema, expr: Expr, scope: Scope): Type = of ekRange: let lo = sema.checkExpr(expr.exprRangeLo, scope) let hi = sema.checkExpr(expr.exprRangeHi, scope) - if lo != hi: + var rangeType: Type = lo + if lo == hi: + rangeType = lo + elif lo.isAssignableTo(hi): + rangeType = hi + elif hi.isAssignableTo(lo): + rangeType = lo + else: sema.emitError(expr.loc, "range bounds must have same type") - return makeRange(lo) + return makeRange(rangeType) of ekCall: if expr.exprCallCallee == nil: sema.emitError(expr.loc, "internal error: nil callee in call expression")