summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/parser.nim39
-rw-r--r--compiler/semstmts.nim16
-rw-r--r--lib/core/macros.nim8
-rw-r--r--lib/system.nim3
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