diff options
31 files changed, 97 insertions, 84 deletions
diff --git a/compiler/aliases.nim b/compiler/aliases.nim index 0c836bb24..c0371e159 100644 --- a/compiler/aliases.nim +++ b/compiler/aliases.nim @@ -95,7 +95,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult = if a.kind == b.kind: case a.kind of nkSym: - const varKinds = {skVar, skTemp, skProc} + const varKinds = {skVar, skTemp, skProc, skFunc} # same symbol: aliasing: if a.sym.id == b.sym.id: result = arYes elif a.sym.kind in varKinds or b.sym.kind in varKinds: diff --git a/compiler/ast.nim b/compiler/ast.nim index 6e87959bf..79e1105e1 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -221,6 +221,8 @@ type nkGotoState, # used for the state machine (for iterators) nkState, # give a label to a code section (for iterators) nkBreakState, # special break statement for easier code generation + nkFuncDef # a func + TNodeKinds* = set[TNodeKind] type @@ -534,6 +536,7 @@ type skConst, # a constant skResult, # special 'result' variable skProc, # a proc + skFunc, # a func skMethod, # a method skIterator, # an iterator skConverter, # a type converter @@ -552,7 +555,7 @@ type TSymKinds* = set[TSymKind] const - routineKinds* = {skProc, skMethod, skIterator, + routineKinds* = {skProc, skFunc, skMethod, skIterator, skConverter, skMacro, skTemplate} tfIncompleteStruct* = tfVarargs tfUncheckedArray* = tfVarargs @@ -931,7 +934,7 @@ type # the poor naming choices in the standard library. const - OverloadableSyms* = {skProc, skMethod, skIterator, + OverloadableSyms* = {skProc, skFunc, skMethod, skIterator, skConverter, skModule, skTemplate, skMacro} GenericTypes*: TTypeKinds = {tyGenericInvocation, tyGenericBody, @@ -954,7 +957,7 @@ const tyTuple, tySequence} NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence, tyProc, tyString, tyError} - ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, + ExportableSymKinds* = {skVar, skConst, skProc, skFunc, skMethod, skType, skIterator, skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias} PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, @@ -978,14 +981,14 @@ const nkLiterals* = {nkCharLit..nkTripleStrLit} nkLambdaKinds* = {nkLambda, nkDo} - declarativeDefs* = {nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef} + declarativeDefs* = {nkProcDef, nkFuncDef, nkMethodDef, nkIteratorDef, nkConverterDef} procDefs* = nkLambdaKinds + declarativeDefs nkSymChoices* = {nkClosedSymChoice, nkOpenSymChoice} nkStrKinds* = {nkStrLit..nkTripleStrLit} skLocalVars* = {skVar, skLet, skForVar, skParam, skResult} - skProcKinds* = {skProc, skTemplate, skMacro, skIterator, + skProcKinds* = {skProc, skFunc, skTemplate, skMacro, skIterator, skMethod, skConverter} var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 25681c330..88944aea6 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2039,7 +2039,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = else: genProc(p.module, sym) putLocIntoDest(p, d, sym.loc) - of skProc, skConverter, skIterator: + of skProc, skConverter, skIterator, skFunc: #if sym.kind == skIterator: # echo renderTree(sym.getBody, {renderIds}) if sfCompileTime in sym.flags: @@ -2205,7 +2205,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = discard of nkPragma: genPragma(p, n) of nkPragmaBlock: expr(p, n.lastSon, d) - of nkProcDef, nkMethodDef, nkConverterDef: + of nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef: if n.sons[genericParamsPos].kind == nkEmpty: var prc = n.sons[namePos].sym # due to a bug/limitation in the lambda lifting, unused inner procs diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 74ffb4603..eb32e7dd0 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -960,7 +960,7 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope = res.add(t.sons[i].strVal) of nkSym: var sym = t.sons[i].sym - if sym.kind in {skProc, skIterator, skMethod}: + if sym.kind in {skProc, skFunc, skIterator, skMethod}: var a: TLoc initLocExpr(p, t.sons[i], a) res.add($rdLoc(a)) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index d0add6bcc..6970d09c3 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -603,7 +603,7 @@ proc cgsym(m: BModule, name: string): Rope = var sym = magicsys.getCompilerProc(name) if sym != nil: case sym.kind - of skProc, skMethod, skConverter, skIterator: genProc(m, sym) + of skProc, skFunc, skMethod, skConverter, skIterator: genProc(m, sym) of skVar, skResult, skLet: genVarPrototype(m, newSymNode sym) of skType: discard getTypeDesc(m, sym.typ) else: internalError("cgsym: " & name & ": " & $sym.kind) diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 3f4f7b164..8c50a4f1d 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -325,7 +325,7 @@ proc complexName(k: TSymKind, n: PNode, baseName: string): string = ## section of ``doc/docgen.txt``. result = baseName case k: - of skProc: result.add(defaultParamSeparator) + of skProc, skFunc: result.add(defaultParamSeparator) of skMacro: result.add(".m" & defaultParamSeparator) of skMethod: result.add(".e" & defaultParamSeparator) of skIterator: result.add(".i" & defaultParamSeparator) @@ -341,7 +341,7 @@ proc isCallable(n: PNode): bool = ## Returns true if `n` contains a callable node. case n.kind of nkProcDef, nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, - nkConverterDef: result = true + nkConverterDef, nkFuncDef: result = true else: result = false @@ -533,6 +533,9 @@ proc generateDoc*(d: PDoc, n: PNode) = of nkProcDef: when useEffectSystem: documentRaises(n) genItem(d, n, n.sons[namePos], skProc) + of nkFuncDef: + when useEffectSystem: documentRaises(n) + genItem(d, n, n.sons[namePos], skFunc) of nkMethodDef: when useEffectSystem: documentRaises(n) genItem(d, n, n.sons[namePos], skMethod) @@ -574,6 +577,9 @@ proc generateJson*(d: PDoc, n: PNode) = of nkProcDef: when useEffectSystem: documentRaises(n) d.add genJsonItem(d, n, n.sons[namePos], skProc) + of nkFuncDef: + when useEffectSystem: documentRaises(n) + d.add genJsonItem(d, n, n.sons[namePos], skFunc) of nkMethodDef: when useEffectSystem: documentRaises(n) d.add genJsonItem(d, n, n.sons[namePos], skMethod) @@ -604,8 +610,8 @@ proc generateJson*(d: PDoc, n: PNode) = proc genSection(d: PDoc, kind: TSymKind) = const sectionNames: array[skModule..skTemplate, string] = [ - "Imports", "Types", "Vars", "Lets", "Consts", "Vars", "Procs", "Methods", - "Iterators", "Converters", "Macros", "Templates" + "Imports", "Types", "Vars", "Lets", "Consts", "Vars", "Procs", "Funcs", + "Methods", "Iterators", "Converters", "Macros", "Templates" ] if d.section[kind] == nil: return var title = sectionNames[kind].rope diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 73e6a9948..bffe196df 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -292,7 +292,7 @@ proc useMagic(p: PProc, name: string) = if name.len == 0: return var s = magicsys.getCompilerProc(name) if s != nil: - internalAssert s.kind in {skProc, skMethod, skConverter} + internalAssert s.kind in {skProc, skFunc, skMethod, skConverter} if not p.g.generatedSyms.containsOrIncl(s.id): let code = genProc(p, s) add(p.g.constants, code) @@ -1111,7 +1111,7 @@ template isIndirect(x: PSym): bool = ({sfAddrTaken, sfGlobal} * v.flags != {} and #(mapType(v.typ) != etyObject) and {sfImportc, sfVolatile, sfExportc} * v.flags == {} and - v.kind notin {skProc, skConverter, skMethod, skIterator, + v.kind notin {skProc, skFunc, skConverter, skMethod, skIterator, skConst, skTemp, skLet} and p.target == targetJS) proc genAddr(p: PProc, n: PNode, r: var TCompRes) = @@ -1237,7 +1237,7 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) = else: r.res = "$" & s.loc.r p.declareGlobal(s.id, r.res) - of skProc, skConverter, skMethod: + of skProc, skFunc, skConverter, skMethod: discard mangleName(s, p.target) if p.target == targetPHP and r.kind != resCallee: r.res = makeJsString($s.loc.r) @@ -2338,7 +2338,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt, nkFromStmt, nkTemplateDef, nkMacroDef: discard of nkPragma: genPragma(p, n) - of nkProcDef, nkMethodDef, nkConverterDef: + of nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef: var s = n.sons[namePos].sym if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}: genSym(p, n.sons[namePos], r) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 986d8c716..e64e0a898 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -194,7 +194,7 @@ proc illegalCapture(s: PSym): bool {.inline.} = s.kind == skResult proc isInnerProc(s: PSym): bool = - if s.kind in {skProc, skMethod, skConverter, skIterator} and s.magic == mNone: + if s.kind in {skProc, skFunc, skMethod, skConverter, skIterator} and s.magic == mNone: result = s.skipGenericOwner.kind in routineKinds proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode = @@ -371,7 +371,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = case n.kind of nkSym: let s = n.sym - if s.kind in {skProc, skMethod, skConverter, skIterator} and s.typ != nil and s.typ.callConv == ccClosure: + if s.kind in {skProc, skFunc, skMethod, skConverter, skIterator} and + s.typ != nil and s.typ.callConv == ccClosure: # this handles the case that the inner proc was declared as # .closure but does not actually capture anything: addClosureParam(c, s, n.info) @@ -443,7 +444,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = discard of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef: discard - of nkLambdaKinds, nkIteratorDef: + of nkLambdaKinds, nkIteratorDef, nkFuncDef: if n.typ != nil: detectCapturedVars(n[namePos], owner, c) else: @@ -730,7 +731,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass; # now we know better, so patch it: n.sons[0] = x.sons[0] n.sons[1] = x.sons[1] - of nkLambdaKinds, nkIteratorDef: + of nkLambdaKinds, nkIteratorDef, nkFuncDef: if n.typ != nil and n[namePos].kind == nkSym: let m = newSymNode(n[namePos].sym) m.typ = n.typ diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 5a5dfc46a..eddfeea56 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -144,8 +144,10 @@ type proc getSymRepr*(s: PSym): string = case s.kind - of skProc, skMethod, skConverter, skIterator: result = getProcHeader(s) - else: result = s.name.s + of skProc, skFunc, skMethod, skConverter, skIterator: + result = getProcHeader(s) + else: + result = s.name.s proc ensureNoMissingOrUnusedSymbols(scope: PScope) = # check if all symbols have been used and defined: diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index ce76b63a4..033472c07 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -633,7 +633,7 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType; if fn.kind == nkClosure: localError(n.info, "closure in spawn environment is not allowed") if not (fn.kind == nkSym and fn.sym.kind in {skProc, skTemplate, skMacro, - skMethod, skConverter}): + skFunc, skMethod, skConverter}): # for indirect calls we pass the function pointer in the scratchObj var argType = n[0].typ.skipTypes(abstractInst) var field = newSym(skField, getIdent"fn", owner, n.info) diff --git a/compiler/parser.nim b/compiler/parser.nim index 253716247..06ecf900e 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -991,7 +991,7 @@ proc parseDoBlock(p: var TParser; info: TLineInfo): PNode = if params.kind != nkEmpty: result = newProcNode(nkDo, info, result, params = params, pragmas = pragmas) -proc parseProcExpr(p: var TParser, isExpr: bool): PNode = +proc parseProcExpr(p: var TParser; isExpr: bool; kind: TNodeKind): PNode = #| procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)? # either a proc type or a anonymous proc let info = parLineInfo(p) @@ -1002,7 +1002,7 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode = if p.tok.tokType == tkEquals and isExpr: getTok(p) skipComment(p, result) - result = newProcNode(nkLambda, info, parseStmt(p), + result = newProcNode(kind, info, parseStmt(p), params = params, pragmas = pragmas) else: @@ -1014,7 +1014,7 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode = proc isExprStart(p: TParser): bool = case p.tok.tokType of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, - tkProc, tkIterator, tkBind, tkAddr, + tkProc, tkFunc, tkIterator, tkBind, tkAddr, tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr, tkTuple, tkObject, tkType, tkWhen, tkCase, tkOut: result = true @@ -1088,21 +1088,12 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode = case p.tok.tokType: of tkTuple: result = parseTuple(p, mode == pmTypeDef) - of tkProc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}) + of tkProc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkLambda) + of tkFunc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkFuncDef) of tkIterator: - when false: - if mode in {pmTypeDesc, pmTypeDef}: - result = parseProcExpr(p, false) - result.kind = nkIteratorTy - else: - # no anon iterators for now: - parMessage(p, errExprExpected, p.tok) - getTok(p) # we must consume a token here to prevend endless loops! - result = ast.emptyNode - else: - result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}) - if result.kind == nkLambda: result.kind = nkIteratorDef - else: result.kind = nkIteratorTy + result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkLambda) + if result.kind == nkLambda: result.kind = nkIteratorDef + else: result.kind = nkIteratorTy of tkEnum: if mode == pmTypeDef: result = parseEnum(p) @@ -2000,6 +1991,7 @@ proc complexOrSimpleStmt(p: var TParser): PNode = of tkDefer: result = parseStaticOrDefer(p, nkDefer) of tkAsm: result = parseAsm(p) of tkProc: result = parseRoutine(p, nkProcDef) + of tkFunc: result = parseRoutine(p, nkFuncDef) of tkMethod: result = parseRoutine(p, nkMethodDef) of tkIterator: result = parseRoutine(p, nkIteratorDef) of tkMacro: result = parseRoutine(p, nkMacroDef) @@ -2056,8 +2048,8 @@ proc parseStmt(p: var TParser): PNode = else: # the case statement is only needed for better error messages: case p.tok.tokType - of tkIf, tkWhile, tkCase, tkTry, tkFor, tkBlock, tkAsm, tkProc, tkIterator, - tkMacro, tkType, tkConst, tkWhen, tkVar: + of tkIf, tkWhile, tkCase, tkTry, tkFor, tkBlock, tkAsm, tkProc, tkFunc, + tkIterator, tkMacro, tkType, tkConst, tkWhen, tkVar: parMessage(p, errComplexStmtRequiresInd) result = ast.emptyNode else: diff --git a/compiler/passes.nim b/compiler/passes.nim index bf6ce1a0a..6efd50385 100644 --- a/compiler/passes.nim +++ b/compiler/passes.nim @@ -64,7 +64,7 @@ proc astNeeded*(s: PSym): bool = # needs to be stored. The passes manager frees s.sons[codePos] when # appropriate to free the procedure body's memory. This is important # to keep memory usage down. - if (s.kind in {skMethod, skProc}) and + if (s.kind in {skMethod, skProc, skFunc}) and ({sfCompilerProc, sfCompileTime} * s.flags == {}) and (s.typ.callConv != ccInline) and (s.ast.sons[genericParamsPos].kind == nkEmpty): diff --git a/compiler/renderer.nim b/compiler/renderer.nim index 220693f68..c52161a55 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -1166,6 +1166,9 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = of nkProcDef: if renderNoProcDefs notin g.flags: putWithSpace(g, tkProc, "proc") gproc(g, n) + of nkFuncDef: + if renderNoProcDefs notin g.flags: putWithSpace(g, tkFunc, "func") + gproc(g, n) of nkConverterDef: if renderNoProcDefs notin g.flags: putWithSpace(g, tkConverter, "converter") gproc(g, n) @@ -1324,7 +1327,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = if p.typ == nil or tfImplicitTypeParam notin p.typ.flags: return true return false - + if n.hasExplicitParams: put(g, tkBracketLe, "[") gsemicolon(g, n) diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim index 9a8fafd86..fb50c6473 100644 --- a/compiler/rodwrite.nim +++ b/compiler/rodwrite.nim @@ -580,7 +580,7 @@ proc process(c: PPassContext, n: PNode): PNode = for i in countup(0, sonsLen(n) - 1): discard process(c, n.sons[i]) #var s = n.sons[namePos].sym #addInterfaceSym(w, s) - of nkProcDef, nkIteratorDef, nkConverterDef, + of nkProcDef, nkFuncDef, nkIteratorDef, nkConverterDef, nkTemplateDef, nkMacroDef: let s = n.sons[namePos].sym if s == nil: internalError(n.info, "rodwrite.process") diff --git a/compiler/sem.nim b/compiler/sem.nim index cd0df0de0..21fd0b383 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -449,7 +449,7 @@ include semtypes, semtempl, semgnrc, semstmts, semexprs proc addCodeForGenerics(c: PContext, n: PNode) = for i in countup(c.lastGenericIdx, c.generics.len - 1): var prc = c.generics[i].inst.sym - if prc.kind in {skProc, skMethod, skConverter} and prc.magic == mNone: + if prc.kind in {skProc, skFunc, skMethod, skConverter} and prc.magic == mNone: if prc.ast == nil or prc.ast.sons[bodyPos] == nil: internalError(prc.info, "no code for " & prc.name.s) else: diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 5984e25e0..9492e63f4 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -468,7 +468,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = for i in countup(0, len(a)-1): var candidate = a.sons[i].sym if candidate.kind in {skProc, skMethod, skConverter, - skIterator}: + skFunc, skIterator}: # it suffices that the candidate has the proper number of generic # type parameters: if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1: diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 97212d2cd..a3f0f715b 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -373,7 +373,7 @@ proc makeRangeType*(c: PContext; first, last: BiggestInt; addSonSkipIntLit(result, intType) # basetype of range proc markIndirect*(c: PContext, s: PSym) {.inline.} = - if s.kind in {skProc, skConverter, skMethod, skIterator}: + if s.kind in {skProc, skFunc, skConverter, skMethod, skIterator}: incl(s.flags, sfAddrTaken) # XXX add to 'c' for global analysis diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 9930e127e..315efa440 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -574,7 +574,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode = optImplicitStatic notin gOptions: return if callee.magic notin ctfeWhitelist: return - if callee.kind notin {skProc, skConverter} or callee.isGenericRoutine: + if callee.kind notin {skProc, skFunc, skConverter} or callee.isGenericRoutine: return if n.typ != nil and typeAllowed(n.typ, skConst) != nil: return @@ -616,10 +616,10 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode, # for typeof support. # for ``type(countup(1,3))``, see ``tests/ttoseq``. result = semOverloadedCall(c, n, nOrig, - {skProc, skMethod, skConverter, skMacro, skTemplate, skIterator}, flags) + {skProc, skFunc, skMethod, skConverter, skMacro, skTemplate, skIterator}, flags) else: result = semOverloadedCall(c, n, nOrig, - {skProc, skMethod, skConverter, skMacro, skTemplate}, flags) + {skProc, skFunc, skMethod, skConverter, skMacro, skTemplate}, flags) if result != nil: if result.sons[0].kind != nkSym: @@ -1230,7 +1230,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode = else: nil if s != nil: case s.kind - of skProc, skMethod, skConverter, skIterator: + of skProc, skFunc, skMethod, skConverter, skIterator: # type parameters: partial generic specialization n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s) result = explicitGenericInstantiation(c, n, s) @@ -1398,7 +1398,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode = proc semReturn(c: PContext, n: PNode): PNode = result = n checkSonsLen(n, 1) - if c.p.owner.kind in {skConverter, skMethod, skProc, skMacro} or ( + if c.p.owner.kind in {skConverter, skMethod, skProc, skFunc, skMacro} or ( c.p.owner.kind == skIterator and c.p.owner.typ.callConv == ccClosure): if n.sons[0].kind != nkEmpty: # transform ``return expr`` to ``result = expr; return`` @@ -2122,7 +2122,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = var s = qualifiedLookUp(c, n, checks) if c.matchedConcept == nil: semCaptureSym(s, c.p.owner) result = semSym(c, n, s, flags) - if s.kind in {skProc, skMethod, skConverter, skIterator}: + if s.kind in {skProc, skFunc, skMethod, skConverter, skIterator}: #performProcvarCheck(c, n, s) result = symChoice(c, n, s, scClosed) if result.kind == nkSym: @@ -2217,7 +2217,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = errorUseQualifier(c, n.info, s) elif s.magic == mNone: result = semDirectOp(c, n, flags) else: result = semMagic(c, n, s, flags) - of skProc, skMethod, skConverter, skIterator: + of skProc, skFunc, skMethod, skConverter, skIterator: if s.magic == mNone: result = semDirectOp(c, n, flags) else: result = semMagic(c, n, s, flags) else: @@ -2330,7 +2330,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = of nkYieldStmt: result = semYield(c, n) of nkPragma: pragma(c, c.p.owner, n, stmtPragmas) of nkIteratorDef: result = semIterator(c, n) - of nkProcDef: result = semProc(c, n) + of nkProcDef, nkFuncDef: result = semProc(c, n) of nkMethodDef: result = semMethod(c, n) of nkConverterDef: result = semConverterDef(c, n) of nkMacroDef: result = semMacroDef(c, n) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 9733564e7..d961a47a3 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -630,7 +630,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode = result = newStrNodeT(lookupSymbol(s.name), n) else: result = copyTree(s.ast) - of {skProc, skMethod}: + of {skProc, skFunc, skMethod}: result = n of skType: # XXX gensym'ed symbols can come here and cannot be resolved. This is @@ -654,7 +654,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode = of nkCallKinds: if n.sons[0].kind != nkSym: return var s = n.sons[0].sym - if s.kind != skProc: return + if s.kind != skProc and s.kind != skFunc: return try: case s.magic of mNone: diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index e3d078432..3cdb68df6 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -61,7 +61,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym, of skUnknown: # Introduced in this pass! Leave it as an identifier. result = n - of skProc, skMethod, skIterator, skConverter, skModule: + of skProc, skFunc, skMethod, skIterator, skConverter, skModule: result = symChoice(c, n, s, scOpen) of skTemplate: if macroToExpandSym(s): @@ -243,7 +243,7 @@ proc semGenericStmt(c: PContext, n: PNode, of skUnknown, skParam: # Leave it as an identifier. discard - of skProc, skMethod, skIterator, skConverter, skModule: + of skProc, skFunc, skMethod, skIterator, skConverter, skModule: result.sons[0] = sc # do not check of 's.magic==mRoof' here because it might be some # other '^' but after overload resolution the proper one: @@ -437,7 +437,7 @@ proc semGenericStmt(c: PContext, n: PNode, for j in countup(0, L-3): addTempDecl(c, getIdentNode(a.sons[j]), skParam) of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, - nkIteratorDef, nkLambdaKinds: + nkFuncDef, nkIteratorDef, nkLambdaKinds: checkSonsLen(n, bodyPos + 1) if n.sons[namePos].kind != nkEmpty: addTempDecl(c, getIdentNode(n.sons[0]), skProc) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index a28d322b1..6abb34e90 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -36,7 +36,7 @@ proc rawPushProcCon(c: PContext, owner: PSym) = c.p = x proc rawHandleSelf(c: PContext; owner: PSym) = - const callableSymbols = {skProc, skMethod, skConverter, skIterator, skMacro} + const callableSymbols = {skProc, skFunc, skMethod, skConverter, skIterator, skMacro} if c.selfName != nil and owner.kind in callableSymbols and owner.typ != nil: let params = owner.typ.n if params.len > 1: diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim index 90c1a315a..2581f5728 100644 --- a/compiler/semparallel.nim +++ b/compiler/semparallel.nim @@ -387,7 +387,7 @@ proc analyse(c: var AnalysisCtx; n: PNode) = addFactNeg(c.guards, canon(n.sons[0])) dec c.inLoop of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef, - nkMacroDef, nkTemplateDef, nkConstSection, nkPragma: + nkMacroDef, nkTemplateDef, nkConstSection, nkPragma, nkFuncDef: discard else: analyseSons(c, n) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index e24c5fd29..e1a3939fc 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -835,7 +835,7 @@ proc track(tracked: PEffects, n: PNode) = setLen(tracked.locked, oldLocked) tracked.currLockLevel = oldLockLevel of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef, - nkMacroDef, nkTemplateDef, nkLambda, nkDo: + nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef: discard of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv: if n.len == 2: track(tracked, n.sons[1]) @@ -937,7 +937,7 @@ proc trackProc*(s: PSym, body: PNode) = track(t, body) if not isEmptyType(s.typ.sons[0]) and {tfNeedsInit, tfNotNil} * s.typ.sons[0].flags != {} and - s.kind in {skProc, skConverter, skMethod}: + s.kind in {skProc, skFunc, skConverter, skMethod}: var res = s.ast.sons[resultPos].sym # get result symbol if res.id notin t.init: message(body.info, warnProveInit, "result") @@ -979,10 +979,10 @@ proc trackProc*(s: PSym, body: PNode) = message(s.info, warnLockLevel, "declared lock level is $1, but real lock level is $2" % [$s.typ.lockLevel, $t.maxLockLevel]) - when useWriteTracking: trackWrites(s, body) + if s.kind == skFunc: trackWrites(s, body) proc trackTopLevelStmt*(module: PSym; n: PNode) = - if n.kind in {nkPragma, nkMacroDef, nkTemplateDef, nkProcDef, + if n.kind in {nkPragma, nkMacroDef, nkTemplateDef, nkProcDef, nkFuncDef, nkTypeSection, nkConverterDef, nkMethodDef, nkIteratorDef}: return var effects = newNode(nkEffectList, n.info) diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 8ad8a6288..be8567c9c 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -449,6 +449,8 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode = a.sons[2] = semTemplBody(c, a.sons[2]) of nkProcDef, nkLambdaKinds: result = semRoutineInTemplBody(c, n, skProc) + of nkFuncDef: + result = semRoutineInTemplBody(c, n, skFunc) of nkMethodDef: result = semRoutineInTemplBody(c, n, skMethod) of nkIteratorDef: diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index b4a61deb7..a3953d87e 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -170,7 +170,7 @@ proc reResolveCallsWithTypedescParams(cl: var TReplTypeVars, n: PNode): PNode = if isTypeParam(n[i]): needsFixing = true if needsFixing: n.sons[0] = newSymNode(n.sons[0].sym.owner) - return cl.c.semOverloadedCall(cl.c, n, n, {skProc}, {}) + return cl.c.semOverloadedCall(cl.c, n, n, {skProc, skFunc}, {}) for i in 0 .. <n.safeLen: n.sons[i] = reResolveCallsWithTypedescParams(cl, n[i]) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 41596f05c..cde9d70ac 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1373,7 +1373,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, # XXX: This is very hacky. It should be moved back into liftTypeParam if x.kind in {tyGenericInst, tyArray} and c.calleeSym != nil and - c.calleeSym.kind == skProc: + c.calleeSym.kind in {skProc, skFunc}: let inst = prepareMetatypeForSigmatch(c.c, c.bindings, c.call.info, f) return typeRel(c, inst, a) @@ -1832,7 +1832,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType, bothMetaCounter < 100: lastBindingsLength = m.bindings.counter inc(bothMetaCounter) - if arg.kind in {nkProcDef, nkIteratorDef} + nkLambdaKinds: + if arg.kind in {nkProcDef, nkFuncDef, nkIteratorDef} + nkLambdaKinds: result = c.semInferredLambda(c, m.bindings, arg) elif arg.kind != nkSym: return nil @@ -1865,7 +1865,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType, else: result = implicitConv(nkHiddenStdConv, f, arg, m, c) of isInferred, isInferredConvertible: - if arg.kind in {nkProcDef, nkIteratorDef} + nkLambdaKinds: + if arg.kind in {nkProcDef, nkFuncDef, nkIteratorDef} + nkLambdaKinds: result = c.semInferredLambda(c, m.bindings, arg) elif arg.kind != nkSym: return nil @@ -1952,7 +1952,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType, z.calleeSym = m.calleeSym var best = -1 for i in countup(0, sonsLen(arg) - 1): - if arg.sons[i].sym.kind in {skProc, skMethod, skConverter, skIterator}: + if arg.sons[i].sym.kind in {skProc, skFunc, skMethod, skConverter, skIterator}: copyCandidate(z, m) z.callee = arg.sons[i].typ if tfUnresolved in z.callee.flags: continue diff --git a/compiler/transf.nim b/compiler/transf.nim index 41959b018..f1ee49a54 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -121,7 +121,7 @@ proc transformSymAux(c: PTransf, n: PNode): PNode = if s.kind == skIterator: if c.tooEarly: return n else: return liftIterSym(n, getCurrOwner(c)) - elif s.kind in {skProc, skConverter, skMethod} and not c.tooEarly: + elif s.kind in {skProc, skFunc, skConverter, skMethod} and not c.tooEarly: # top level .closure procs are still somewhat supported for 'Nake': return makeClosure(s, nil, n.info) #elif n.sym.kind in {skVar, skLet} and n.sym.typ.callConv == ccClosure: diff --git a/compiler/types.nim b/compiler/types.nim index dc7cd52db..a1581dac1 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1089,7 +1089,7 @@ proc typeAllowedNode(marker: var IntSet, n: PNode, kind: TSymKind, of nkNone..nkNilLit: discard else: - if n.kind == nkRecCase and kind in {skProc, skConst}: + if n.kind == nkRecCase and kind in {skProc, skFunc, skConst}: return n[0].typ for i in countup(0, sonsLen(n) - 1): let it = n.sons[i] @@ -1107,7 +1107,7 @@ proc matchType*(a: PType, pattern: openArray[tuple[k:TTypeKind, i:int]], proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, flags: TTypeAllowedFlags = {}): PType = - assert(kind in {skVar, skLet, skConst, skProc, skParam, skResult}) + assert(kind in {skVar, skLet, skConst, skProc, skFunc, skParam, skResult}) # if we have already checked the type, return true, because we stop the # evaluation if something is wrong: result = nil @@ -1116,7 +1116,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, var t = skipTypes(typ, abstractInst-{tyTypeDesc}) case t.kind of tyVar: - if kind in {skProc, skConst}: return t + if kind in {skProc, skFunc, skConst}: return t var t2 = skipTypes(t.sons[0], abstractInst-{tyTypeDesc}) case t2.kind of tyVar: @@ -1176,7 +1176,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, result = typeAllowedAux(marker, t.sons[i], kind, flags) if result != nil: break of tyObject, tyTuple: - if kind in {skProc, skConst} and + if kind in {skProc, skFunc, skConst} and t.kind == tyObject and t.sons[0] != nil: return t let flags = flags+{taField} for i in countup(0, sonsLen(t) - 1): diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 3d291d8a2..6f9d70495 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1289,7 +1289,7 @@ proc checkCanEval(c: PCtx; n: PNode) = if s.kind in {skVar, skTemp, skLet, skParam, skResult} and not s.isOwnedBy(c.prc.sym) and s.owner != c.module and c.mode != emRepl: cannotEval(n) - elif s.kind in {skProc, skConverter, skMethod, + elif s.kind in {skProc, skFunc, skConverter, skMethod, skIterator} and sfForward in s.flags: cannotEval(n) @@ -1712,7 +1712,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = case s.kind of skVar, skForVar, skTemp, skLet, skParam, skResult: genRdVar(c, n, dest, flags) - of skProc, skConverter, skMacro, skTemplate, skMethod, skIterator: + of skProc, skFunc, skConverter, skMacro, skTemplate, skMethod, skIterator: # 'skTemplate' is only allowed for 'getAst' support: if procIsCallback(c, s): discard elif sfImportc in s.flags: c.importcSym(n.info, s) diff --git a/compiler/writetracking.nim b/compiler/writetracking.nim index 443e8ddf1..fe71e5b31 100644 --- a/compiler/writetracking.nim +++ b/compiler/writetracking.nim @@ -248,6 +248,8 @@ proc markWriteOrEscape(w: var W) = for p in a.dest: if p.kind == skParam and p.owner == w.owner: incl(p.flags, sfWrittenTo) + if w.owner.kind == skFunc and p.typ.kind != tyVar: + localError(a.info, "write access to non-var parameter: " & p.name.s) if {rootIsResultOrParam, rootIsHeapAccess, markAsEscaping}*a.destInfo != {}: var destIsParam = false diff --git a/lib/core/macros.nim b/lib/core/macros.nim index e88002c7b..28b3dd7ab 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -75,7 +75,8 @@ type nnkClosure, nnkGotoState, nnkState, - nnkBreakState + nnkBreakState, + nnkFuncDef NimNodeKinds* = set[NimNodeKind] NimTypeKind* = enum # some types are no longer used, see ast.nim @@ -103,7 +104,7 @@ type nskUnknown, nskConditional, nskDynLib, nskParam, nskGenericParam, nskTemp, nskModule, nskType, nskVar, nskLet, nskConst, nskResult, - nskProc, nskMethod, nskIterator, + nskProc, nskFunc, nskMethod, nskIterator, nskConverter, nskMacro, nskTemplate, nskField, nskEnumField, nskForVar, nskLabel, nskStub @@ -843,7 +844,8 @@ proc last*(node: NimNode): NimNode {.compileTime.} = node[<node.len] const - RoutineNodes* = {nnkProcDef, nnkMethodDef, nnkDo, nnkLambda, nnkIteratorDef, nnkTemplateDef, nnkConverterDef} + RoutineNodes* = {nnkProcDef, nnkFuncDef, nnkMethodDef, nnkDo, nnkLambda, + nnkIteratorDef, nnkTemplateDef, nnkConverterDef} AtomicNodes* = {nnkNone..nnkNilLit} CallNodes* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand, nnkCallStrLit, nnkHiddenCallConv} |