steps to get for loops as expressions
This commit is contained in:
parent
a897371797
commit
0495e6cf3a
4 changed files with 41 additions and 25 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 =
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue