diff options
-rw-r--r-- | compiler/parser.nim | 39 | ||||
-rw-r--r-- | compiler/semstmts.nim | 16 | ||||
-rw-r--r-- | lib/core/macros.nim | 8 | ||||
-rw-r--r-- | lib/system.nim | 3 |
4 files changed, 41 insertions, 25 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim index 4974abcc3..a5428a229 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -514,7 +514,7 @@ proc parsePar(p: var TParser): PNode = optInd(p, result) if p.tok.tokType in {tkDiscard, tkInclude, tkIf, tkWhile, tkCase, tkTry, tkDefer, tkFinally, tkExcept, tkFor, tkBlock, - tkConst, tkLet, tkWhen, tkVar, + tkConst, tkLet, tkWhen, tkVar, tkFor, tkMixin}: # XXX 'bind' used to be an expression, so we exclude it here; # tests/reject/tbind2 fails otherwise. @@ -1039,7 +1039,7 @@ proc parseProcExpr(p: var TParser; isExpr: bool; kind: TNodeKind): PNode = proc isExprStart(p: TParser): bool = case p.tok.tokType - of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, + of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkFor, tkProc, tkFunc, tkIterator, tkBind, tkAddr, tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr, tkTuple, tkObject, tkType, tkWhen, tkCase, tkOut: @@ -1078,16 +1078,35 @@ proc parseTypeDescKAux(p: var TParser, kind: TNodeKind, result.addSon list parseSymbolList(p, list) +proc parseFor(p: var TParser): PNode = + #| forStmt = 'for' (identWithPragma ^+ comma) 'in' expr colcom stmt + #| forExpr = forStmt + result = newNodeP(nkForStmt, p) + getTokNoInd(p) + var a = identWithPragma(p) + addSon(result, a) + while p.tok.tokType == tkComma: + getTok(p) + optInd(p, a) + a = identWithPragma(p) + addSon(result, a) + eat(p, tkIn) + addSon(result, parseExpr(p)) + colcom(p, result) + addSon(result, parseStmt(p)) + proc parseExpr(p: var TParser): PNode = #| expr = (blockExpr #| | ifExpr #| | whenExpr #| | caseExpr + #| | forExpr #| | tryExpr) #| / simpleExpr case p.tok.tokType: of tkBlock: result = parseBlock(p) of tkIf: result = parseIfExpr(p, nkIfExpr) + of tkFor: result = parseFor(p) of tkWhen: result = parseIfExpr(p, nkWhenExpr) of tkCase: result = parseCase(p) of tkTry: result = parseTry(p, isExpr=true) @@ -1498,22 +1517,6 @@ proc parseExceptBlock(p: var TParser, kind: TNodeKind): PNode = colcom(p, result) addSon(result, parseStmt(p)) -proc parseFor(p: var TParser): PNode = - #| forStmt = 'for' (identWithPragma ^+ comma) 'in' expr colcom stmt - result = newNodeP(nkForStmt, p) - getTokNoInd(p) - var a = identWithPragma(p) - addSon(result, a) - while p.tok.tokType == tkComma: - getTok(p) - optInd(p, a) - a = identWithPragma(p) - addSon(result, a) - eat(p, tkIn) - addSon(result, parseExpr(p)) - colcom(p, result) - addSon(result, parseStmt(p)) - proc parseBlock(p: var TParser): PNode = #| blockStmt = 'block' symbol? colcom stmt #| blockExpr = 'block' symbol? colcom stmt diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 1e3265eae..a86787a8e 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -679,7 +679,7 @@ proc semForVars(c: PContext, n: PNode): PNode = addForVarDecl(c, v) inc(c.p.nestedLoopCounter) openScope(c) - n.sons[length-1] = semStmt(c, n.sons[length-1]) + n.sons[length-1] = semExprBranch(c, n.sons[length-1]) closeScope(c) dec(c.p.nestedLoopCounter) @@ -732,8 +732,18 @@ proc semFor(c: PContext, n: PNode): PNode = else: result = semForVars(c, n) # propagate any enforced VoidContext: - if n.sons[length-1].typ == enforceVoidContext: - result.typ = enforceVoidContext + let bodyType = n.sons[length-1].typ + if bodyType == enforceVoidContext or isEmptyType(bodyType): + result.typ = bodyType + else: + # if the body of a for loop is of type 'T', the + # loop's type is 'iterator (): T' + proc createForLoopExpr(c: PContext; t: PType; info: TLineInfo): PType {.nimcall.} = + result = newType(tyGenericInvocation, c.module) + addSonSkipIntLit(result, magicsys.getCompilerProc("ForLoopExpr").typ) + addSonSkipIntLit(result, t) + result = instGenericContainer(c, info, result, allowMetaTypes = false) + result.typ = createForLoopExpr(c, bodyType, result.info) closeScope(c) proc semRaise(c: PContext, n: PNode): PNode = diff --git a/lib/core/macros.nim b/lib/core/macros.nim index ed9c304fe..f2a39f43b 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -902,7 +902,7 @@ proc newIfStmt*(branches: varargs[tuple[cond, body: NimNode]]): ## result = newNimNode(nnkIfStmt) for i in branches: - result.add(newNimNode(nnkElifBranch).add(i.cond, i.body)) + result.add(newTree(nnkElifBranch, i.cond, i.body)) proc newEnum*(name: NimNode, fields: openArray[NimNode], public, pure: bool): NimNode {.compileTime.} = @@ -1227,7 +1227,7 @@ proc customPragmaNode(n: NimNode): NimNode = let recList = typDef[2][2] for identDefs in recList: for i in 0 .. identDefs.len - 3: - if identDefs[i].kind == nnkPragmaExpr and + if identDefs[i].kind == nnkPragmaExpr and identDefs[i][0].kind == nnkIdent and $identDefs[i][0] == $n[1]: return identDefs[i][1] @@ -1237,7 +1237,7 @@ macro hasCustomPragma*(n: typed, cp: typed{nkSym}): untyped = ## ## .. code-block:: nim ## template myAttr() {.pragma.} - ## type + ## type ## MyObj = object ## myField {.myAttr.}: int ## var o: MyObj @@ -1255,7 +1255,7 @@ macro getCustomPragmaVal*(n: typed, cp: typed{nkSym}): untyped = ## ## .. code-block:: nim ## template serializationKey(key: string) {.pragma.} - ## type + ## type ## MyObj = object ## myField {.serializationKey: "mf".}: int ## var o: MyObj diff --git a/lib/system.nim b/lib/system.nim index 2f95b45f0..8e6b997b6 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -4131,3 +4131,6 @@ when defined(cpp) and appType != "lib" and not defined(js) and stderr.write trace & "Error: unhandled exception: " & ex.msg & " [" & $ex.name & "]\n" quit 1 + +type + ForLoopExpr*{.compilerProc.}[T] = object ## the type of a 'for' loop expression |