steps to get for loops as expressions

This commit is contained in:
Andreas Rumpf 2018-02-28 20:30:17 +01:00
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) optInd(p, result)
if p.tok.tokType in {tkDiscard, tkInclude, tkIf, tkWhile, tkCase, if p.tok.tokType in {tkDiscard, tkInclude, tkIf, tkWhile, tkCase,
tkTry, tkDefer, tkFinally, tkExcept, tkFor, tkBlock, tkTry, tkDefer, tkFinally, tkExcept, tkFor, tkBlock,
tkConst, tkLet, tkWhen, tkVar, tkConst, tkLet, tkWhen, tkVar, tkFor,
tkMixin}: tkMixin}:
# XXX 'bind' used to be an expression, so we exclude it here; # XXX 'bind' used to be an expression, so we exclude it here;
# tests/reject/tbind2 fails otherwise. # tests/reject/tbind2 fails otherwise.
@ -1039,7 +1039,7 @@ proc parseProcExpr(p: var TParser; isExpr: bool; kind: TNodeKind): PNode =
proc isExprStart(p: TParser): bool = proc isExprStart(p: TParser): bool =
case p.tok.tokType 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, tkProc, tkFunc, tkIterator, tkBind, tkAddr,
tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr, tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr,
tkTuple, tkObject, tkType, tkWhen, tkCase, tkOut: tkTuple, tkObject, tkType, tkWhen, tkCase, tkOut:
@ -1078,16 +1078,35 @@ proc parseTypeDescKAux(p: var TParser, kind: TNodeKind,
result.addSon list result.addSon list
parseSymbolList(p, 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 = proc parseExpr(p: var TParser): PNode =
#| expr = (blockExpr #| expr = (blockExpr
#| | ifExpr #| | ifExpr
#| | whenExpr #| | whenExpr
#| | caseExpr #| | caseExpr
#| | forExpr
#| | tryExpr) #| | tryExpr)
#| / simpleExpr #| / simpleExpr
case p.tok.tokType: case p.tok.tokType:
of tkBlock: result = parseBlock(p) of tkBlock: result = parseBlock(p)
of tkIf: result = parseIfExpr(p, nkIfExpr) of tkIf: result = parseIfExpr(p, nkIfExpr)
of tkFor: result = parseFor(p)
of tkWhen: result = parseIfExpr(p, nkWhenExpr) of tkWhen: result = parseIfExpr(p, nkWhenExpr)
of tkCase: result = parseCase(p) of tkCase: result = parseCase(p)
of tkTry: result = parseTry(p, isExpr=true) of tkTry: result = parseTry(p, isExpr=true)
@ -1498,22 +1517,6 @@ proc parseExceptBlock(p: var TParser, kind: TNodeKind): PNode =
colcom(p, result) colcom(p, result)
addSon(result, parseStmt(p)) 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 = proc parseBlock(p: var TParser): PNode =
#| blockStmt = 'block' symbol? colcom stmt #| blockStmt = 'block' symbol? colcom stmt
#| blockExpr = '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) addForVarDecl(c, v)
inc(c.p.nestedLoopCounter) inc(c.p.nestedLoopCounter)
openScope(c) openScope(c)
n.sons[length-1] = semStmt(c, n.sons[length-1]) n.sons[length-1] = semExprBranch(c, n.sons[length-1])
closeScope(c) closeScope(c)
dec(c.p.nestedLoopCounter) dec(c.p.nestedLoopCounter)
@ -732,8 +732,18 @@ proc semFor(c: PContext, n: PNode): PNode =
else: else:
result = semForVars(c, n) result = semForVars(c, n)
# propagate any enforced VoidContext: # propagate any enforced VoidContext:
if n.sons[length-1].typ == enforceVoidContext: let bodyType = n.sons[length-1].typ
result.typ = enforceVoidContext 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) closeScope(c)
proc semRaise(c: PContext, n: PNode): PNode = proc semRaise(c: PContext, n: PNode): PNode =

View file

@ -902,7 +902,7 @@ proc newIfStmt*(branches: varargs[tuple[cond, body: NimNode]]):
## ##
result = newNimNode(nnkIfStmt) result = newNimNode(nnkIfStmt)
for i in branches: 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], proc newEnum*(name: NimNode, fields: openArray[NimNode],
public, pure: bool): NimNode {.compileTime.} = public, pure: bool): NimNode {.compileTime.} =
@ -1227,7 +1227,7 @@ proc customPragmaNode(n: NimNode): NimNode =
let recList = typDef[2][2] let recList = typDef[2][2]
for identDefs in recList: for identDefs in recList:
for i in 0 .. identDefs.len - 3: 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]: identDefs[i][0].kind == nnkIdent and $identDefs[i][0] == $n[1]:
return identDefs[i][1] return identDefs[i][1]
@ -1237,7 +1237,7 @@ macro hasCustomPragma*(n: typed, cp: typed{nkSym}): untyped =
## ##
## .. code-block:: nim ## .. code-block:: nim
## template myAttr() {.pragma.} ## template myAttr() {.pragma.}
## type ## type
## MyObj = object ## MyObj = object
## myField {.myAttr.}: int ## myField {.myAttr.}: int
## var o: MyObj ## var o: MyObj
@ -1255,7 +1255,7 @@ macro getCustomPragmaVal*(n: typed, cp: typed{nkSym}): untyped =
## ##
## .. code-block:: nim ## .. code-block:: nim
## template serializationKey(key: string) {.pragma.} ## template serializationKey(key: string) {.pragma.}
## type ## type
## MyObj = object ## MyObj = object
## myField {.serializationKey: "mf".}: int ## myField {.serializationKey: "mf".}: int
## var o: MyObj ## 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 & stderr.write trace & "Error: unhandled exception: " & ex.msg &
" [" & $ex.name & "]\n" " [" & $ex.name & "]\n"
quit 1 quit 1
type
ForLoopExpr*{.compilerProc.}[T] = object ## the type of a 'for' loop expression