diff --git a/compiler/ast.nim b/compiler/ast.nim index 65d7bccf1e..cfcdb6ea69 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -93,6 +93,7 @@ type nkElifExpr, nkElseExpr, nkLambda, # lambda expression + nkDo, # lambda block appering as trailing proc param nkAccQuoted, # `a` as a node nkTableConstr, # a table constructor {expr: expr} @@ -644,6 +645,8 @@ proc copyTree*(src: PNode): PNode const nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit} +const nkLambdaKinds* = {nkLambda, nkDo} + proc isCallExpr*(n: PNode): bool = result = n.kind in nkCallKinds diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 0d7f6cce48..81d122859d 100755 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -7,6 +7,8 @@ # distribution, for details about the copyright. # +# included from cgen.nim + proc lenField: PRope {.inline.} = 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 nkStringToCString: convStrToCStr(p, e, d) of nkCStringToString: convCStrToStr(p, e, d) - of nkLambda: + of nkLambdaKinds: var sym = e.sons[namePos].sym genProc(p.module, sym) if sym.loc.r == nil or sym.loc.t == nil: diff --git a/compiler/evals.nim b/compiler/evals.nim index 0c67503f1d..8867387046 100755 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -1246,7 +1246,7 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = of nkPragmaBlock: result = evalAux(c, n.sons[1], flags) of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr, - nkLambda, nkContinueStmt, nkIdent: + nkLambdaKinds, nkContinueStmt, nkIdent: result = raiseCannotEval(c, n.info) of nkRefTy: result = evalAux(c, n.sons[0], flags) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 7863768ef1..a22252a30e 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -8,11 +8,12 @@ # # This include file implements lambda lifting for the transformator. +# included from transf.nim const declarativeDefs = {nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef} - procDefs = {nkLambda} + declarativeDefs + procDefs = nkLambdaKinds + declarativeDefs proc indirectAccess(a, b: PSym, info: TLineInfo): PNode = # 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) 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]'! s.ast.sons[bodyPos] = n.sons[bodyPos] else: diff --git a/compiler/lexer.nim b/compiler/lexer.nim index 0916a02d7f..278ab3b1f9 100755 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -33,8 +33,9 @@ type tkSymbol, # keywords: tkAddr, tkAnd, tkAs, tkAsm, tkAtomic, tkBind, tkBlock, tkBreak, tkCase, tkCast, - tkConst, tkContinue, tkConverter, tkDiscard, tkDistinct, tkDiv, tkElif, - tkElse, tkEnd, tkEnum, tkExcept, tkExport, tkFinally, tkFor, tkFrom, + tkConst, tkContinue, tkConverter, tkDiscard, tkDistinct, tkDiv, tkDo, + tkElif, tkElse, tkEnd, tkEnum, tkExcept, tkExport, + tkFinally, tkFor, tkFrom, tkGeneric, tkIf, tkImport, tkIn, tkInclude, tkIs, tkIsnot, tkIterator, tkLambda, tkLet, tkMacro, tkMethod, tkMod, tkNil, tkNot, tkNotin, tkObject, tkOf, tkOr, @@ -48,10 +49,12 @@ type tkBracketDotLe, tkBracketDotRi, # [. and .] tkCurlyDotLe, tkCurlyDotRi, # {. 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, tkDed, # pseudo token types used by the source renderers: - tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr + tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr, + TTokTypes* = set[TTokType] const @@ -61,8 +64,8 @@ const "tkSymbol", "addr", "and", "as", "asm", "atomic", "bind", "block", "break", "case", "cast", - "const", "continue", "converter", "discard", "distinct", "div", "elif", - "else", "end", "enum", "except", "export", + "const", "continue", "converter", "discard", "distinct", "div", "do", + "elif", "else", "end", "enum", "except", "export", "finally", "for", "from", "generic", "if", "import", "in", "include", "is", "isnot", "iterator", "lambda", "let", @@ -73,9 +76,10 @@ const "tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit", "tkFloatLit", "tkFloat32Lit", "tkFloat64Lit", "tkStrLit", "tkRStrLit", "tkTripleStrLit", "tkGStrLit", "tkGTripleStrLit", "tkCharLit", "(", - ")", "[", "]", "{", "}", "[.", ".]", "{.", ".}", "(.", ".)", ",", ";", - ":", "::", - "=", ".", "..", "tkOpr", "tkComment", "`", "[new indentation]", + ")", "[", "]", "{", "}", "[.", ".]", "{.", ".}", "(.", ".)", + ",", ";", + ":", "::", "=", "<-", "->", ".", "..", + "tkOpr", "tkComment", "`", "[new indentation]", "[same indentation]", "[dedentation]", "tkSpaces", "tkInfixOpr", "tkPrefixOpr", "tkPostfixOpr"] diff --git a/compiler/parser.nim b/compiler/parser.nim index 12184a097f..6e08cfecfc 100755 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -146,7 +146,8 @@ proc newIdentNodeP(ident: PIdent, p: TParser): PNode = proc parseExpr(p: var TParser): PNode proc parseStmt(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.} = result = tok.tokType != tkOpr or tok.ident.s[0] != '^' @@ -466,6 +467,7 @@ proc primary(p: var TParser): PNode = result = newNodeP(nkCall, p) addSon(result, a) exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result) + parseDoBlocks(p, result) of tkDot: result = newDotExpr(p, result) result = parseGStrLit(p, result) @@ -599,7 +601,7 @@ proc parseTuple(p: var TParser): PNode = optPar(p) eat(p, tkBracketRi) -proc parseParamList(p: var TParser): PNode = +proc parseParamList(p: var TParser, resTypeTok = tkColon): PNode = var a: PNode result = newNodeP(nkFormalParams, p) addSon(result, ast.emptyNode) # return type @@ -621,11 +623,33 @@ proc parseParamList(p: var TParser): PNode = optInd(p, a) optPar(p) eat(p, tkParRi) - if p.tok.tokType == tkColon: + if p.tok.tokType == resTypeTok: getTok(p) optInd(p, result) 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 = # either a proc type or a anonymous proc var @@ -634,8 +658,7 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode = info = parLineInfo(p) getTok(p) params = parseParamList(p) - if p.tok.tokType == tkCurlyDotLe: pragmas = parsePragma(p) - else: pragmas = ast.emptyNode + pragmas = optPragmas(p) if (p.tok.tokType == tkEquals) and isExpr: result = newNodeI(nkLambda, info) addSon(result, ast.emptyNode) # no name part @@ -709,9 +732,12 @@ proc parseExprStmt(p: var TParser): PNode = if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) + if p.tok.tokType == tkDo: + parseDoBlocks(p, result) + return if sonsLen(result) <= 1: result = a else: a = result - if p.tok.tokType == tkColon: + if p.tok.tokType == tkColon: # macro statement result = newNodeP(nkMacroStmt, p) result.info = a.info @@ -746,7 +772,7 @@ proc parseExprStmt(p: var TParser): PNode = addSon(b, parseStmt(p)) addSon(result, b) if b.kind == nkElse: break - + proc parseImportOrIncludeStmt(p: var TParser, kind: TNodeKind): PNode = var a: PNode result = newNodeP(kind, p) diff --git a/compiler/renderer.nim b/compiler/renderer.nim index 21cf175f57..f185b51d81 100755 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -348,7 +348,7 @@ proc lsub(n: PNode): int = of nkBind: result = lsons(n) + len("bind_") of nkBindStmt: result = lcomma(n) + len("bind_") 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: result = lcomma(n, 0, - 3) var L = sonsLen(n) @@ -785,7 +785,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = gsub(g, n.sons[0]) of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref: gsub(g, n.sons[0]) - of nkLambda: + of nkLambda, nkDo: # XXX: nkDo is rendered as regular lambda assert(n.sons[genericParamsPos].kind == nkEmpty) putWithSpace(g, tkLambda, "lambda") gsub(g, n.sons[paramsPos]) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index a90c475e27..4ae803c36b 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1279,7 +1279,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = of paSingle: result = semExpr(c, n.sons[0], flags) of nkCurly: result = semSetConstr(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 nkAddr: result = n diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index fb98e870b1..6a1c2f5294 100755 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -244,9 +244,9 @@ proc semGenericStmt(c: PContext, n: PNode, for j in countup(0, L-3): addPrelimDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c)) of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, - nkIteratorDef, nkLambda: + nkIteratorDef, nkLambdaKinds: checkSonsLen(n, bodyPos + 1) - if n.kind != nkLambda: + if n.kind notin nkLambdaKinds: addPrelimDecl(c, newSymS(skUnknown, getIdentNode(n.sons[0]), c)) openScope(c.tab) n.sons[genericParamsPos] = semGenericStmt(c, n.sons[genericParamsPos], diff --git a/compiler/semthreads.nim b/compiler/semthreads.nim index f542e04d66..1295723cf5 100755 --- a/compiler/semthreads.nim +++ b/compiler/semthreads.nim @@ -360,7 +360,7 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner = if n.sons[0].kind != nkEmpty: result = analyse(c, n.sons[0]) else: result = toVoid of nkAsmStmt, nkPragma, nkIteratorDef, nkProcDef, nkMethodDef, - nkConverterDef, nkMacroDef, nkTemplateDef, nkLambda: + nkConverterDef, nkMacroDef, nkTemplateDef, nkLambdaKinds: result = toVoid of nkExprColonExpr: result = analyse(c, n.sons[1]) diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index 398c08b8ec..d46c141fdd 100755 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -24,15 +24,17 @@ type wAddr, wAnd, wAs, wAsm, wAtomic, wBind, wBlock, wBreak, wCase, wCast, wConst, - wContinue, wConverter, wDiscard, wDistinct, wDiv, wElif, wElse, wEnd, wEnum, - wExcept, wExport, wFinally, wFor, wFrom, wGeneric, wIf, wImport, wIn, + wContinue, wConverter, wDiscard, wDistinct, wDiv, wDo, + wElif, wElse, wEnd, wEnum, wExcept, wExport, + wFinally, wFor, wFrom, wGeneric, wIf, wImport, wIn, wInclude, wIs, wIsnot, wIterator, wLambda, wLet, wMacro, wMethod, wMod, wNil, wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, wShl, wShr, wTemplate, wTry, wTuple, wType, wVar, wWhen, wWhile, wWith, wWithout, wXor, wYield, - wColon, wColonColon, wEquals, wDot, wDotDot, wStar, wMinus, + wColon, wColonColon, wEquals, wLeArraw, wRiArrow, wDot, wDotDot, + wStar, wMinus, wMagic, wThread, wFinal, wProfiler, wObjChecks, wImportCpp, wImportObjC, wImportCompilerProc, @@ -66,8 +68,9 @@ const "addr", "and", "as", "asm", "atomic", "bind", "block", "break", "case", "cast", - "const", "continue", "converter", "discard", "distinct", "div", "elif", - "else", "end", "enum", "except", "export", + "const", "continue", "converter", + "discard", "distinct", "div", "do", + "elif", "else", "end", "enum", "except", "export", "finally", "for", "from", "generic", "if", "import", "in", "include", "is", "isnot", "iterator", "lambda", "let", @@ -76,7 +79,8 @@ const "try", "tuple", "type", "var", "when", "while", "with", "without", "xor", "yield", - ":", "::", "=", ".", "..", "*", "-", + ":", "::", "=", "<-", "->", ".", "..", + "*", "-", "magic", "thread", "final", "profiler", "objchecks", "importcpp", "importobjc", diff --git a/doc/keywords.txt b/doc/keywords.txt index c5834e3a72..c4e073417d 100755 --- a/doc/keywords.txt +++ b/doc/keywords.txt @@ -1,9 +1,10 @@ addr and as asm atomic bind block break case cast const continue converter -discard distinct div +discard distinct div do elif else end enum except export -finally for from generic +finally for from +generic if import in include is isnot iterator lambda let macro method mod diff --git a/lib/core/macros.nim b/lib/core/macros.nim index a8eb0daaf0..4d13a076d9 100755 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -25,7 +25,7 @@ type nnkPrefix, nnkPostfix, nnkPar, nnkCurly, nnkCurlyExpr, nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange, nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr, - nnkElifExpr, nnkElseExpr, nnkLambda, nnkAccQuoted, + nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted, nnkTableConstr, nnkBind, nnkSymChoice, nnkHiddenStdConv, nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast, nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv, diff --git a/lib/wrappers/gtk/gtk2.nim b/lib/wrappers/gtk/gtk2.nim index 151d9ee1c9..9f455e5ba2 100755 --- a/lib/wrappers/gtk/gtk2.nim +++ b/lib/wrappers/gtk/gtk2.nim @@ -4068,7 +4068,6 @@ proc set_need_default_position*(a: gtk2.PWindow, `need_default_position`: guint) proc need_default_size*(a: gtk2.PWindow): guint proc set_need_default_size*(a: gtk2.PWindow, `need_default_size`: guint) proc position*(a: gtk2.PWindow): guint -proc set_position*(a: gtk2.PWindow, `position`: guint) proc get_type*(a: gtk2.PWindow): guint proc set_type*(a: gtk2.PWindow, `type`: guint) proc has_user_ref_count*(a: gtk2.PWindow): guint @@ -11358,10 +11357,6 @@ proc position*(a: gtk2.PWindow): guint = result = (a.Window_flag0 and bm_TGtkWindow_position) shr bp_TGtkWindow_position -proc set_position*(a: gtk2.PWindow, `position`: guint) = - a.Window_flag0 = a.Window_flag0 or - ((`position` shl bp_TGtkWindow_position) and bm_TGtkWindow_position) - proc get_type*(a: gtk2.PWindow): guint = result = (a.Window_flag0 and bm_TGtkWindow_type) shr bp_TGtkWindow_type @@ -16902,3 +16897,6 @@ proc set_has_tooltip*(widget: PWidget, b: gboolean){.cdecl, dynlib: lib, proc set_markup*(tp: PTooltip, mk: cstring){.cdecl, dynlib: lib, importc: "gtk_tooltip_set_markup".} + +proc set_visible_window*(evBox: PEventBox, v: gboolean){.cdecl, dynlib: lib, + importc: "gtk_event_box_set_visible_window".} diff --git a/tests/run/tclosure.nim b/tests/run/tclosure.nim index d7c0ec0e34..372e296d09 100755 --- a/tests/run/tclosure.nim +++ b/tests/run/tclosure.nim @@ -12,6 +12,10 @@ proc foldr(n: openarray[int], fn: proc (x, y: int): int {.closure}): int = for i in 0..n.len-1: 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 myData: array[0..4, int] = [0, 1, 2, 3, 4] @@ -24,8 +28,10 @@ proc testA() = inc(p)) testA() -for x in items(myData): + +myData.each do (x: int): write(stout, x) + #OUT 2 4 6 8 10