`do' keyword in the grammar for lambda blocks

This commit is contained in:
Zahary Karadjov 2012-02-10 14:50:06 +02:00
commit 560a3bad28
14 changed files with 83 additions and 36 deletions

View file

@ -93,6 +93,7 @@ type
nkElifExpr, nkElifExpr,
nkElseExpr, nkElseExpr,
nkLambda, # lambda expression nkLambda, # lambda expression
nkDo, # lambda block appering as trailing proc param
nkAccQuoted, # `a` as a node nkAccQuoted, # `a` as a node
nkTableConstr, # a table constructor {expr: expr} nkTableConstr, # a table constructor {expr: expr}
@ -644,6 +645,8 @@ proc copyTree*(src: PNode): PNode
const nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, const nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
nkCallStrLit} nkCallStrLit}
const nkLambdaKinds* = {nkLambda, nkDo}
proc isCallExpr*(n: PNode): bool = proc isCallExpr*(n: PNode): bool =
result = n.kind in nkCallKinds result = n.kind in nkCallKinds

View file

@ -7,6 +7,8 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
# included from cgen.nim
proc lenField: PRope {.inline.} = proc lenField: PRope {.inline.} =
result = toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len") result = toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len")
@ -1723,7 +1725,7 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
of nkChckRange: genRangeChck(p, e, d, "chckRange") of nkChckRange: genRangeChck(p, e, d, "chckRange")
of nkStringToCString: convStrToCStr(p, e, d) of nkStringToCString: convStrToCStr(p, e, d)
of nkCStringToString: convCStrToStr(p, e, d) of nkCStringToString: convCStrToStr(p, e, d)
of nkLambda: of nkLambdaKinds:
var sym = e.sons[namePos].sym var sym = e.sons[namePos].sym
genProc(p.module, sym) genProc(p.module, sym)
if sym.loc.r == nil or sym.loc.t == nil: if sym.loc.r == nil or sym.loc.t == nil:

View file

@ -1246,7 +1246,7 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
of nkPragmaBlock: of nkPragmaBlock:
result = evalAux(c, n.sons[1], flags) result = evalAux(c, n.sons[1], flags)
of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr, of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr,
nkLambda, nkContinueStmt, nkIdent: nkLambdaKinds, nkContinueStmt, nkIdent:
result = raiseCannotEval(c, n.info) result = raiseCannotEval(c, n.info)
of nkRefTy: of nkRefTy:
result = evalAux(c, n.sons[0], flags) result = evalAux(c, n.sons[0], flags)

View file

@ -8,11 +8,12 @@
# #
# This include file implements lambda lifting for the transformator. # This include file implements lambda lifting for the transformator.
# included from transf.nim
const const
declarativeDefs = {nkProcDef, nkMethodDef, nkIteratorDef, declarativeDefs = {nkProcDef, nkMethodDef, nkIteratorDef,
nkConverterDef} nkConverterDef}
procDefs = {nkLambda} + declarativeDefs procDefs = nkLambdaKinds + declarativeDefs
proc indirectAccess(a, b: PSym, info: TLineInfo): PNode = proc indirectAccess(a, b: PSym, info: TLineInfo): PNode =
# returns a[].b as a node # returns a[].b as a node
@ -169,7 +170,7 @@ proc createEnvStmt(c: PTransf, varList: TCapture, env: PSym): PTransNode =
IdNodeTablePut(c.transCon.mapping, v, fieldAccess) IdNodeTablePut(c.transCon.mapping, v, fieldAccess)
proc transformProcFin(c: PTransf, n: PNode, s: PSym): PTransNode = proc transformProcFin(c: PTransf, n: PNode, s: PSym): PTransNode =
if n.kind == nkLambda: if n.kind in nkLambdaKinds:
# for lambdas we transformed 'n.sons[bodyPos]', but not 'ast.n[bodyPos]'! # for lambdas we transformed 'n.sons[bodyPos]', but not 'ast.n[bodyPos]'!
s.ast.sons[bodyPos] = n.sons[bodyPos] s.ast.sons[bodyPos] = n.sons[bodyPos]
else: else:

View file

@ -33,8 +33,9 @@ type
tkSymbol, # keywords: tkSymbol, # keywords:
tkAddr, tkAnd, tkAs, tkAsm, tkAtomic, tkAddr, tkAnd, tkAs, tkAsm, tkAtomic,
tkBind, tkBlock, tkBreak, tkCase, tkCast, tkBind, tkBlock, tkBreak, tkCase, tkCast,
tkConst, tkContinue, tkConverter, tkDiscard, tkDistinct, tkDiv, tkElif, tkConst, tkContinue, tkConverter, tkDiscard, tkDistinct, tkDiv, tkDo,
tkElse, tkEnd, tkEnum, tkExcept, tkExport, tkFinally, tkFor, tkFrom, tkElif, tkElse, tkEnd, tkEnum, tkExcept, tkExport,
tkFinally, tkFor, tkFrom,
tkGeneric, tkIf, tkImport, tkIn, tkInclude, tkIs, tkIsnot, tkIterator, tkGeneric, tkIf, tkImport, tkIn, tkInclude, tkIs, tkIsnot, tkIterator,
tkLambda, tkLet, tkLambda, tkLet,
tkMacro, tkMethod, tkMod, tkNil, tkNot, tkNotin, tkObject, tkOf, tkOr, tkMacro, tkMethod, tkMod, tkNil, tkNot, tkNotin, tkObject, tkOf, tkOr,
@ -48,10 +49,12 @@ type
tkBracketDotLe, tkBracketDotRi, # [. and .] tkBracketDotLe, tkBracketDotRi, # [. and .]
tkCurlyDotLe, tkCurlyDotRi, # {. and .} tkCurlyDotLe, tkCurlyDotRi, # {. and .}
tkParDotLe, tkParDotRi, # (. and .) tkParDotLe, tkParDotRi, # (. and .)
tkComma, tkSemiColon, tkColon, tkColonColon, tkEquals, tkDot, tkDotDot, tkComma, tkSemiColon,
tkColon, tkColonColon, tkEquals, tkLeArrow, tkRiArrow, tkDot, tkDotDot,
tkOpr, tkComment, tkAccent, tkInd, tkSad, tkOpr, tkComment, tkAccent, tkInd, tkSad,
tkDed, # pseudo token types used by the source renderers: tkDed, # pseudo token types used by the source renderers:
tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr,
TTokTypes* = set[TTokType] TTokTypes* = set[TTokType]
const const
@ -61,8 +64,8 @@ const
"tkSymbol", "tkSymbol",
"addr", "and", "as", "asm", "atomic", "addr", "and", "as", "asm", "atomic",
"bind", "block", "break", "case", "cast", "bind", "block", "break", "case", "cast",
"const", "continue", "converter", "discard", "distinct", "div", "elif", "const", "continue", "converter", "discard", "distinct", "div", "do",
"else", "end", "enum", "except", "export", "elif", "else", "end", "enum", "except", "export",
"finally", "for", "from", "generic", "if", "finally", "for", "from", "generic", "if",
"import", "in", "include", "is", "isnot", "iterator", "import", "in", "include", "is", "isnot", "iterator",
"lambda", "let", "lambda", "let",
@ -73,9 +76,10 @@ const
"tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit", "tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit",
"tkFloatLit", "tkFloat32Lit", "tkFloat64Lit", "tkStrLit", "tkRStrLit", "tkFloatLit", "tkFloat32Lit", "tkFloat64Lit", "tkStrLit", "tkRStrLit",
"tkTripleStrLit", "tkGStrLit", "tkGTripleStrLit", "tkCharLit", "(", "tkTripleStrLit", "tkGStrLit", "tkGTripleStrLit", "tkCharLit", "(",
")", "[", "]", "{", "}", "[.", ".]", "{.", ".}", "(.", ".)", ",", ";", ")", "[", "]", "{", "}", "[.", ".]", "{.", ".}", "(.", ".)",
":", "::", ",", ";",
"=", ".", "..", "tkOpr", "tkComment", "`", "[new indentation]", ":", "::", "=", "<-", "->", ".", "..",
"tkOpr", "tkComment", "`", "[new indentation]",
"[same indentation]", "[dedentation]", "tkSpaces", "tkInfixOpr", "[same indentation]", "[dedentation]", "tkSpaces", "tkInfixOpr",
"tkPrefixOpr", "tkPostfixOpr"] "tkPrefixOpr", "tkPostfixOpr"]

View file

@ -146,7 +146,8 @@ proc newIdentNodeP(ident: PIdent, p: TParser): PNode =
proc parseExpr(p: var TParser): PNode proc parseExpr(p: var TParser): PNode
proc parseStmt(p: var TParser): PNode proc parseStmt(p: var TParser): PNode
proc parseTypeDesc(p: var TParser): PNode proc parseTypeDesc(p: var TParser): PNode
proc parseParamList(p: var TParser): PNode proc parseDoBlocks(p: var TParser, call: PNode)
proc parseParamList(p: var TParser, resTypeTok = tkColon): PNode
proc IsLeftAssociative(tok: TToken): bool {.inline.} = proc IsLeftAssociative(tok: TToken): bool {.inline.} =
result = tok.tokType != tkOpr or tok.ident.s[0] != '^' result = tok.tokType != tkOpr or tok.ident.s[0] != '^'
@ -466,6 +467,7 @@ proc primary(p: var TParser): PNode =
result = newNodeP(nkCall, p) result = newNodeP(nkCall, p)
addSon(result, a) addSon(result, a)
exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result) exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result)
parseDoBlocks(p, result)
of tkDot: of tkDot:
result = newDotExpr(p, result) result = newDotExpr(p, result)
result = parseGStrLit(p, result) result = parseGStrLit(p, result)
@ -599,7 +601,7 @@ proc parseTuple(p: var TParser): PNode =
optPar(p) optPar(p)
eat(p, tkBracketRi) eat(p, tkBracketRi)
proc parseParamList(p: var TParser): PNode = proc parseParamList(p: var TParser, resTypeTok = tkColon): PNode =
var a: PNode var a: PNode
result = newNodeP(nkFormalParams, p) result = newNodeP(nkFormalParams, p)
addSon(result, ast.emptyNode) # return type addSon(result, ast.emptyNode) # return type
@ -621,11 +623,33 @@ proc parseParamList(p: var TParser): PNode =
optInd(p, a) optInd(p, a)
optPar(p) optPar(p)
eat(p, tkParRi) eat(p, tkParRi)
if p.tok.tokType == tkColon: if p.tok.tokType == resTypeTok:
getTok(p) getTok(p)
optInd(p, result) optInd(p, result)
result.sons[0] = parseTypeDesc(p) result.sons[0] = parseTypeDesc(p)
proc optPragmas(p: var TParser): PNode =
if p.tok.tokType == tkCurlyDotLe: result = parsePragma(p)
else: result = ast.emptyNode
proc parseDoBlock(p: var TParser): PNode =
var info = parLineInfo(p)
getTok(p)
var params = parseParamList(p, tkRiArrow)
var pragmas = optPragmas(p)
eat(p, tkColon)
result = newNodeI(nkDo, info)
addSon(result, ast.emptyNode) # no name part
addSon(result, ast.emptyNode) # no generic parameters
addSon(result, params)
addSon(result, pragmas)
skipComment(p, result)
addSon(result, parseStmt(p))
proc parseDoBlocks(p: var TParser, call: PNode) =
while p.tok.tokType == tkDo:
addSon(call, parseDoBlock(p))
proc parseProcExpr(p: var TParser, isExpr: bool): PNode = proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
# either a proc type or a anonymous proc # either a proc type or a anonymous proc
var var
@ -634,8 +658,7 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
info = parLineInfo(p) info = parLineInfo(p)
getTok(p) getTok(p)
params = parseParamList(p) params = parseParamList(p)
if p.tok.tokType == tkCurlyDotLe: pragmas = parsePragma(p) pragmas = optPragmas(p)
else: pragmas = ast.emptyNode
if (p.tok.tokType == tkEquals) and isExpr: if (p.tok.tokType == tkEquals) and isExpr:
result = newNodeI(nkLambda, info) result = newNodeI(nkLambda, info)
addSon(result, ast.emptyNode) # no name part addSon(result, ast.emptyNode) # no name part
@ -709,9 +732,12 @@ proc parseExprStmt(p: var TParser): PNode =
if p.tok.tokType != tkComma: break if p.tok.tokType != tkComma: break
getTok(p) getTok(p)
optInd(p, a) optInd(p, a)
if p.tok.tokType == tkDo:
parseDoBlocks(p, result)
return
if sonsLen(result) <= 1: result = a if sonsLen(result) <= 1: result = a
else: a = result else: a = result
if p.tok.tokType == tkColon: if p.tok.tokType == tkColon:
# macro statement # macro statement
result = newNodeP(nkMacroStmt, p) result = newNodeP(nkMacroStmt, p)
result.info = a.info result.info = a.info
@ -746,7 +772,7 @@ proc parseExprStmt(p: var TParser): PNode =
addSon(b, parseStmt(p)) addSon(b, parseStmt(p))
addSon(result, b) addSon(result, b)
if b.kind == nkElse: break if b.kind == nkElse: break
proc parseImportOrIncludeStmt(p: var TParser, kind: TNodeKind): PNode = proc parseImportOrIncludeStmt(p: var TParser, kind: TNodeKind): PNode =
var a: PNode var a: PNode
result = newNodeP(kind, p) result = newNodeP(kind, p)

View file

@ -348,7 +348,7 @@ proc lsub(n: PNode): int =
of nkBind: result = lsons(n) + len("bind_") of nkBind: result = lsons(n) + len("bind_")
of nkBindStmt: result = lcomma(n) + len("bind_") of nkBindStmt: result = lcomma(n) + len("bind_")
of nkCheckedFieldExpr: result = lsub(n.sons[0]) of nkCheckedFieldExpr: result = lsub(n.sons[0])
of nkLambda: result = lsons(n) + len("lambda__=_") of nkLambda, nkDo: result = lsons(n) + len("lambda__=_") # XXX: render nkDo
of nkConstDef, nkIdentDefs: of nkConstDef, nkIdentDefs:
result = lcomma(n, 0, - 3) result = lcomma(n, 0, - 3)
var L = sonsLen(n) var L = sonsLen(n)
@ -785,7 +785,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
gsub(g, n.sons[0]) gsub(g, n.sons[0])
of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref: of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref:
gsub(g, n.sons[0]) gsub(g, n.sons[0])
of nkLambda: of nkLambda, nkDo: # XXX: nkDo is rendered as regular lambda
assert(n.sons[genericParamsPos].kind == nkEmpty) assert(n.sons[genericParamsPos].kind == nkEmpty)
putWithSpace(g, tkLambda, "lambda") putWithSpace(g, tkLambda, "lambda")
gsub(g, n.sons[paramsPos]) gsub(g, n.sons[paramsPos])

View file

@ -1279,7 +1279,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of paSingle: result = semExpr(c, n.sons[0], flags) of paSingle: result = semExpr(c, n.sons[0], flags)
of nkCurly: result = semSetConstr(c, n) of nkCurly: result = semSetConstr(c, n)
of nkBracket: result = semArrayConstr(c, n) of nkBracket: result = semArrayConstr(c, n)
of nkLambda: result = semLambda(c, n) of nkLambdaKinds: result = semLambda(c, n)
of nkDerefExpr: result = semDeref(c, n) of nkDerefExpr: result = semDeref(c, n)
of nkAddr: of nkAddr:
result = n result = n

View file

@ -244,9 +244,9 @@ proc semGenericStmt(c: PContext, n: PNode,
for j in countup(0, L-3): for j in countup(0, L-3):
addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c)) addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c))
of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
nkIteratorDef, nkLambda: nkIteratorDef, nkLambdaKinds:
checkSonsLen(n, bodyPos + 1) checkSonsLen(n, bodyPos + 1)
if n.kind != nkLambda: if n.kind notin nkLambdaKinds:
addPrelimDecl(c, newSymS(skUnknown, getIdentNode(n.sons[0]), c)) addPrelimDecl(c, newSymS(skUnknown, getIdentNode(n.sons[0]), c))
openScope(c.tab) openScope(c.tab)
n.sons[genericParamsPos] = semGenericStmt(c, n.sons[genericParamsPos], n.sons[genericParamsPos] = semGenericStmt(c, n.sons[genericParamsPos],

View file

@ -360,7 +360,7 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
if n.sons[0].kind != nkEmpty: result = analyse(c, n.sons[0]) if n.sons[0].kind != nkEmpty: result = analyse(c, n.sons[0])
else: result = toVoid else: result = toVoid
of nkAsmStmt, nkPragma, nkIteratorDef, nkProcDef, nkMethodDef, of nkAsmStmt, nkPragma, nkIteratorDef, nkProcDef, nkMethodDef,
nkConverterDef, nkMacroDef, nkTemplateDef, nkLambda: nkConverterDef, nkMacroDef, nkTemplateDef, nkLambdaKinds:
result = toVoid result = toVoid
of nkExprColonExpr: of nkExprColonExpr:
result = analyse(c, n.sons[1]) result = analyse(c, n.sons[1])

View file

@ -24,15 +24,17 @@ type
wAddr, wAnd, wAs, wAsm, wAtomic, wAddr, wAnd, wAs, wAsm, wAtomic,
wBind, wBlock, wBreak, wCase, wCast, wConst, wBind, wBlock, wBreak, wCase, wCast, wConst,
wContinue, wConverter, wDiscard, wDistinct, wDiv, wElif, wElse, wEnd, wEnum, wContinue, wConverter, wDiscard, wDistinct, wDiv, wDo,
wExcept, wExport, wFinally, wFor, wFrom, wGeneric, wIf, wImport, wIn, wElif, wElse, wEnd, wEnum, wExcept, wExport,
wFinally, wFor, wFrom, wGeneric, wIf, wImport, wIn,
wInclude, wIs, wIsnot, wIterator, wLambda, wLet, wInclude, wIs, wIsnot, wIterator, wLambda, wLet,
wMacro, wMethod, wMod, wNil, wMacro, wMethod, wMod, wNil,
wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn,
wShl, wShr, wTemplate, wTry, wTuple, wType, wVar, wWhen, wWhile, wWith, wShl, wShr, wTemplate, wTry, wTuple, wType, wVar, wWhen, wWhile, wWith,
wWithout, wXor, wYield, wWithout, wXor, wYield,
wColon, wColonColon, wEquals, wDot, wDotDot, wStar, wMinus, wColon, wColonColon, wEquals, wLeArraw, wRiArrow, wDot, wDotDot,
wStar, wMinus,
wMagic, wThread, wFinal, wProfiler, wObjChecks, wMagic, wThread, wFinal, wProfiler, wObjChecks,
wImportCpp, wImportObjC, wImportCpp, wImportObjC,
wImportCompilerProc, wImportCompilerProc,
@ -66,8 +68,9 @@ const
"addr", "and", "as", "asm", "atomic", "addr", "and", "as", "asm", "atomic",
"bind", "block", "break", "case", "cast", "bind", "block", "break", "case", "cast",
"const", "continue", "converter", "discard", "distinct", "div", "elif", "const", "continue", "converter",
"else", "end", "enum", "except", "export", "discard", "distinct", "div", "do",
"elif", "else", "end", "enum", "except", "export",
"finally", "for", "from", "generic", "if", "finally", "for", "from", "generic", "if",
"import", "in", "include", "is", "isnot", "iterator", "import", "in", "include", "is", "isnot", "iterator",
"lambda", "let", "lambda", "let",
@ -76,7 +79,8 @@ const
"try", "tuple", "type", "var", "when", "while", "with", "without", "xor", "try", "tuple", "type", "var", "when", "while", "with", "without", "xor",
"yield", "yield",
":", "::", "=", ".", "..", "*", "-", ":", "::", "=", "<-", "->", ".", "..",
"*", "-",
"magic", "thread", "final", "profiler", "objchecks", "magic", "thread", "final", "profiler", "objchecks",
"importcpp", "importobjc", "importcpp", "importobjc",

View file

@ -1,9 +1,10 @@
addr and as asm atomic addr and as asm atomic
bind block break bind block break
case cast const continue converter case cast const continue converter
discard distinct div discard distinct div do
elif else end enum except export elif else end enum except export
finally for from generic finally for from
generic
if import in include is isnot iterator if import in include is isnot iterator
lambda let lambda let
macro method mod macro method mod

View file

@ -25,7 +25,7 @@ type
nnkPrefix, nnkPostfix, nnkPar, nnkCurly, nnkCurlyExpr, nnkPrefix, nnkPostfix, nnkPar, nnkCurly, nnkCurlyExpr,
nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange, nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr, nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
nnkElifExpr, nnkElseExpr, nnkLambda, nnkAccQuoted, nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted,
nnkTableConstr, nnkBind, nnkSymChoice, nnkHiddenStdConv, nnkTableConstr, nnkBind, nnkSymChoice, nnkHiddenStdConv,
nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast, nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast,
nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv, nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv,

View file

@ -12,6 +12,10 @@ proc foldr(n: openarray[int], fn: proc (x, y: int): int {.closure}): int =
for i in 0..n.len-1: for i in 0..n.len-1:
result = fn(result, n[i]) result = fn(result, n[i])
proc each(n: openarray[int], fn: proc(x: int) {.closure.}) =
for i in 0..n.len-1:
fn(n[i])
var var
myData: array[0..4, int] = [0, 1, 2, 3, 4] myData: array[0..4, int] = [0, 1, 2, 3, 4]
@ -24,8 +28,10 @@ proc testA() =
inc(p)) inc(p))
testA() testA()
for x in items(myData):
myData.each do (x: int):
write(stout, x) write(stout, x)
#OUT 2 4 6 8 10 #OUT 2 4 6 8 10