steps to get for loops as expressions

This commit is contained in:
Andreas Rumpf
2018-02-28 20:30:17 +01:00
parent a897371797
commit 0495e6cf3a
4 changed files with 41 additions and 25 deletions

View File

@@ -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

View File

@@ -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 =

View File

@@ -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

View File

@@ -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