first implementation of the 'func' keyword

This commit is contained in:
Andreas Rumpf 2017-09-23 23:22:53 +02:00
commit 1a61c4d46d
31 changed files with 97 additions and 84 deletions

View file

@ -95,7 +95,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
if a.kind == b.kind: if a.kind == b.kind:
case a.kind case a.kind
of nkSym: of nkSym:
const varKinds = {skVar, skTemp, skProc} const varKinds = {skVar, skTemp, skProc, skFunc}
# same symbol: aliasing: # same symbol: aliasing:
if a.sym.id == b.sym.id: result = arYes if a.sym.id == b.sym.id: result = arYes
elif a.sym.kind in varKinds or b.sym.kind in varKinds: elif a.sym.kind in varKinds or b.sym.kind in varKinds:

View file

@ -221,6 +221,8 @@ type
nkGotoState, # used for the state machine (for iterators) nkGotoState, # used for the state machine (for iterators)
nkState, # give a label to a code section (for iterators) nkState, # give a label to a code section (for iterators)
nkBreakState, # special break statement for easier code generation nkBreakState, # special break statement for easier code generation
nkFuncDef # a func
TNodeKinds* = set[TNodeKind] TNodeKinds* = set[TNodeKind]
type type
@ -534,6 +536,7 @@ type
skConst, # a constant skConst, # a constant
skResult, # special 'result' variable skResult, # special 'result' variable
skProc, # a proc skProc, # a proc
skFunc, # a func
skMethod, # a method skMethod, # a method
skIterator, # an iterator skIterator, # an iterator
skConverter, # a type converter skConverter, # a type converter
@ -552,7 +555,7 @@ type
TSymKinds* = set[TSymKind] TSymKinds* = set[TSymKind]
const const
routineKinds* = {skProc, skMethod, skIterator, routineKinds* = {skProc, skFunc, skMethod, skIterator,
skConverter, skMacro, skTemplate} skConverter, skMacro, skTemplate}
tfIncompleteStruct* = tfVarargs tfIncompleteStruct* = tfVarargs
tfUncheckedArray* = tfVarargs tfUncheckedArray* = tfVarargs
@ -931,7 +934,7 @@ type
# the poor naming choices in the standard library. # the poor naming choices in the standard library.
const const
OverloadableSyms* = {skProc, skMethod, skIterator, OverloadableSyms* = {skProc, skFunc, skMethod, skIterator,
skConverter, skModule, skTemplate, skMacro} skConverter, skModule, skTemplate, skMacro}
GenericTypes*: TTypeKinds = {tyGenericInvocation, tyGenericBody, GenericTypes*: TTypeKinds = {tyGenericInvocation, tyGenericBody,
@ -954,7 +957,7 @@ const
tyTuple, tySequence} tyTuple, tySequence}
NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence, NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence,
tyProc, tyString, tyError} tyProc, tyString, tyError}
ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, ExportableSymKinds* = {skVar, skConst, skProc, skFunc, skMethod, skType,
skIterator, skIterator,
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias} skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias}
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
@ -978,14 +981,14 @@ const
nkLiterals* = {nkCharLit..nkTripleStrLit} nkLiterals* = {nkCharLit..nkTripleStrLit}
nkLambdaKinds* = {nkLambda, nkDo} nkLambdaKinds* = {nkLambda, nkDo}
declarativeDefs* = {nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef} declarativeDefs* = {nkProcDef, nkFuncDef, nkMethodDef, nkIteratorDef, nkConverterDef}
procDefs* = nkLambdaKinds + declarativeDefs procDefs* = nkLambdaKinds + declarativeDefs
nkSymChoices* = {nkClosedSymChoice, nkOpenSymChoice} nkSymChoices* = {nkClosedSymChoice, nkOpenSymChoice}
nkStrKinds* = {nkStrLit..nkTripleStrLit} nkStrKinds* = {nkStrLit..nkTripleStrLit}
skLocalVars* = {skVar, skLet, skForVar, skParam, skResult} skLocalVars* = {skVar, skLet, skForVar, skParam, skResult}
skProcKinds* = {skProc, skTemplate, skMacro, skIterator, skProcKinds* = {skProc, skFunc, skTemplate, skMacro, skIterator,
skMethod, skConverter} skMethod, skConverter}
var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things

View file

@ -2039,7 +2039,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
else: else:
genProc(p.module, sym) genProc(p.module, sym)
putLocIntoDest(p, d, sym.loc) putLocIntoDest(p, d, sym.loc)
of skProc, skConverter, skIterator: of skProc, skConverter, skIterator, skFunc:
#if sym.kind == skIterator: #if sym.kind == skIterator:
# echo renderTree(sym.getBody, {renderIds}) # echo renderTree(sym.getBody, {renderIds})
if sfCompileTime in sym.flags: if sfCompileTime in sym.flags:
@ -2205,7 +2205,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
discard discard
of nkPragma: genPragma(p, n) of nkPragma: genPragma(p, n)
of nkPragmaBlock: expr(p, n.lastSon, d) of nkPragmaBlock: expr(p, n.lastSon, d)
of nkProcDef, nkMethodDef, nkConverterDef: of nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef:
if n.sons[genericParamsPos].kind == nkEmpty: if n.sons[genericParamsPos].kind == nkEmpty:
var prc = n.sons[namePos].sym var prc = n.sons[namePos].sym
# due to a bug/limitation in the lambda lifting, unused inner procs # due to a bug/limitation in the lambda lifting, unused inner procs

View file

@ -960,7 +960,7 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope =
res.add(t.sons[i].strVal) res.add(t.sons[i].strVal)
of nkSym: of nkSym:
var sym = t.sons[i].sym var sym = t.sons[i].sym
if sym.kind in {skProc, skIterator, skMethod}: if sym.kind in {skProc, skFunc, skIterator, skMethod}:
var a: TLoc var a: TLoc
initLocExpr(p, t.sons[i], a) initLocExpr(p, t.sons[i], a)
res.add($rdLoc(a)) res.add($rdLoc(a))

View file

@ -603,7 +603,7 @@ proc cgsym(m: BModule, name: string): Rope =
var sym = magicsys.getCompilerProc(name) var sym = magicsys.getCompilerProc(name)
if sym != nil: if sym != nil:
case sym.kind 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 skVar, skResult, skLet: genVarPrototype(m, newSymNode sym)
of skType: discard getTypeDesc(m, sym.typ) of skType: discard getTypeDesc(m, sym.typ)
else: internalError("cgsym: " & name & ": " & $sym.kind) else: internalError("cgsym: " & name & ": " & $sym.kind)

View file

@ -325,7 +325,7 @@ proc complexName(k: TSymKind, n: PNode, baseName: string): string =
## section of ``doc/docgen.txt``. ## section of ``doc/docgen.txt``.
result = baseName result = baseName
case k: case k:
of skProc: result.add(defaultParamSeparator) of skProc, skFunc: result.add(defaultParamSeparator)
of skMacro: result.add(".m" & defaultParamSeparator) of skMacro: result.add(".m" & defaultParamSeparator)
of skMethod: result.add(".e" & defaultParamSeparator) of skMethod: result.add(".e" & defaultParamSeparator)
of skIterator: result.add(".i" & defaultParamSeparator) of skIterator: result.add(".i" & defaultParamSeparator)
@ -341,7 +341,7 @@ proc isCallable(n: PNode): bool =
## Returns true if `n` contains a callable node. ## Returns true if `n` contains a callable node.
case n.kind case n.kind
of nkProcDef, nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, of nkProcDef, nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef,
nkConverterDef: result = true nkConverterDef, nkFuncDef: result = true
else: else:
result = false result = false
@ -533,6 +533,9 @@ proc generateDoc*(d: PDoc, n: PNode) =
of nkProcDef: of nkProcDef:
when useEffectSystem: documentRaises(n) when useEffectSystem: documentRaises(n)
genItem(d, n, n.sons[namePos], skProc) genItem(d, n, n.sons[namePos], skProc)
of nkFuncDef:
when useEffectSystem: documentRaises(n)
genItem(d, n, n.sons[namePos], skFunc)
of nkMethodDef: of nkMethodDef:
when useEffectSystem: documentRaises(n) when useEffectSystem: documentRaises(n)
genItem(d, n, n.sons[namePos], skMethod) genItem(d, n, n.sons[namePos], skMethod)
@ -574,6 +577,9 @@ proc generateJson*(d: PDoc, n: PNode) =
of nkProcDef: of nkProcDef:
when useEffectSystem: documentRaises(n) when useEffectSystem: documentRaises(n)
d.add genJsonItem(d, n, n.sons[namePos], skProc) 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: of nkMethodDef:
when useEffectSystem: documentRaises(n) when useEffectSystem: documentRaises(n)
d.add genJsonItem(d, n, n.sons[namePos], skMethod) 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) = proc genSection(d: PDoc, kind: TSymKind) =
const sectionNames: array[skModule..skTemplate, string] = [ const sectionNames: array[skModule..skTemplate, string] = [
"Imports", "Types", "Vars", "Lets", "Consts", "Vars", "Procs", "Methods", "Imports", "Types", "Vars", "Lets", "Consts", "Vars", "Procs", "Funcs",
"Iterators", "Converters", "Macros", "Templates" "Methods", "Iterators", "Converters", "Macros", "Templates"
] ]
if d.section[kind] == nil: return if d.section[kind] == nil: return
var title = sectionNames[kind].rope var title = sectionNames[kind].rope

View file

@ -292,7 +292,7 @@ proc useMagic(p: PProc, name: string) =
if name.len == 0: return if name.len == 0: return
var s = magicsys.getCompilerProc(name) var s = magicsys.getCompilerProc(name)
if s != nil: 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): if not p.g.generatedSyms.containsOrIncl(s.id):
let code = genProc(p, s) let code = genProc(p, s)
add(p.g.constants, code) add(p.g.constants, code)
@ -1111,7 +1111,7 @@ template isIndirect(x: PSym): bool =
({sfAddrTaken, sfGlobal} * v.flags != {} and ({sfAddrTaken, sfGlobal} * v.flags != {} and
#(mapType(v.typ) != etyObject) and #(mapType(v.typ) != etyObject) and
{sfImportc, sfVolatile, sfExportc} * v.flags == {} 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) skConst, skTemp, skLet} and p.target == targetJS)
proc genAddr(p: PProc, n: PNode, r: var TCompRes) = proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
@ -1237,7 +1237,7 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) =
else: else:
r.res = "$" & s.loc.r r.res = "$" & s.loc.r
p.declareGlobal(s.id, r.res) p.declareGlobal(s.id, r.res)
of skProc, skConverter, skMethod: of skProc, skFunc, skConverter, skMethod:
discard mangleName(s, p.target) discard mangleName(s, p.target)
if p.target == targetPHP and r.kind != resCallee: if p.target == targetPHP and r.kind != resCallee:
r.res = makeJsString($s.loc.r) r.res = makeJsString($s.loc.r)
@ -2338,7 +2338,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt, nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt,
nkFromStmt, nkTemplateDef, nkMacroDef: discard nkFromStmt, nkTemplateDef, nkMacroDef: discard
of nkPragma: genPragma(p, n) of nkPragma: genPragma(p, n)
of nkProcDef, nkMethodDef, nkConverterDef: of nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef:
var s = n.sons[namePos].sym var s = n.sons[namePos].sym
if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}: if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}:
genSym(p, n.sons[namePos], r) genSym(p, n.sons[namePos], r)

View file

@ -194,7 +194,7 @@ proc illegalCapture(s: PSym): bool {.inline.} =
s.kind == skResult s.kind == skResult
proc isInnerProc(s: PSym): bool = 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 result = s.skipGenericOwner.kind in routineKinds
proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode = proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode =
@ -371,7 +371,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
case n.kind case n.kind
of nkSym: of nkSym:
let s = n.sym 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 # this handles the case that the inner proc was declared as
# .closure but does not actually capture anything: # .closure but does not actually capture anything:
addClosureParam(c, s, n.info) addClosureParam(c, s, n.info)
@ -443,7 +444,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
discard discard
of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef: of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef:
discard discard
of nkLambdaKinds, nkIteratorDef: of nkLambdaKinds, nkIteratorDef, nkFuncDef:
if n.typ != nil: if n.typ != nil:
detectCapturedVars(n[namePos], owner, c) detectCapturedVars(n[namePos], owner, c)
else: else:
@ -730,7 +731,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
# now we know better, so patch it: # now we know better, so patch it:
n.sons[0] = x.sons[0] n.sons[0] = x.sons[0]
n.sons[1] = x.sons[1] n.sons[1] = x.sons[1]
of nkLambdaKinds, nkIteratorDef: of nkLambdaKinds, nkIteratorDef, nkFuncDef:
if n.typ != nil and n[namePos].kind == nkSym: if n.typ != nil and n[namePos].kind == nkSym:
let m = newSymNode(n[namePos].sym) let m = newSymNode(n[namePos].sym)
m.typ = n.typ m.typ = n.typ

View file

@ -144,8 +144,10 @@ type
proc getSymRepr*(s: PSym): string = proc getSymRepr*(s: PSym): string =
case s.kind case s.kind
of skProc, skMethod, skConverter, skIterator: result = getProcHeader(s) of skProc, skFunc, skMethod, skConverter, skIterator:
else: result = s.name.s result = getProcHeader(s)
else:
result = s.name.s
proc ensureNoMissingOrUnusedSymbols(scope: PScope) = proc ensureNoMissingOrUnusedSymbols(scope: PScope) =
# check if all symbols have been used and defined: # check if all symbols have been used and defined:

View file

@ -633,7 +633,7 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType;
if fn.kind == nkClosure: if fn.kind == nkClosure:
localError(n.info, "closure in spawn environment is not allowed") localError(n.info, "closure in spawn environment is not allowed")
if not (fn.kind == nkSym and fn.sym.kind in {skProc, skTemplate, skMacro, 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 # for indirect calls we pass the function pointer in the scratchObj
var argType = n[0].typ.skipTypes(abstractInst) var argType = n[0].typ.skipTypes(abstractInst)
var field = newSym(skField, getIdent"fn", owner, n.info) var field = newSym(skField, getIdent"fn", owner, n.info)

View file

@ -991,7 +991,7 @@ proc parseDoBlock(p: var TParser; info: TLineInfo): PNode =
if params.kind != nkEmpty: if params.kind != nkEmpty:
result = newProcNode(nkDo, info, result, params = params, pragmas = pragmas) 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)? #| procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)?
# either a proc type or a anonymous proc # either a proc type or a anonymous proc
let info = parLineInfo(p) let info = parLineInfo(p)
@ -1002,7 +1002,7 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
if p.tok.tokType == tkEquals and isExpr: if p.tok.tokType == tkEquals and isExpr:
getTok(p) getTok(p)
skipComment(p, result) skipComment(p, result)
result = newProcNode(nkLambda, info, parseStmt(p), result = newProcNode(kind, info, parseStmt(p),
params = params, params = params,
pragmas = pragmas) pragmas = pragmas)
else: else:
@ -1014,7 +1014,7 @@ proc parseProcExpr(p: var TParser, isExpr: bool): 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,
tkProc, 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:
result = true result = true
@ -1088,21 +1088,12 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
case p.tok.tokType: case p.tok.tokType:
of tkTuple: result = parseTuple(p, mode == pmTypeDef) 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: of tkIterator:
when false: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkLambda)
if mode in {pmTypeDesc, pmTypeDef}: if result.kind == nkLambda: result.kind = nkIteratorDef
result = parseProcExpr(p, false) else: result.kind = nkIteratorTy
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
of tkEnum: of tkEnum:
if mode == pmTypeDef: if mode == pmTypeDef:
result = parseEnum(p) result = parseEnum(p)
@ -2000,6 +1991,7 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
of tkDefer: result = parseStaticOrDefer(p, nkDefer) of tkDefer: result = parseStaticOrDefer(p, nkDefer)
of tkAsm: result = parseAsm(p) of tkAsm: result = parseAsm(p)
of tkProc: result = parseRoutine(p, nkProcDef) of tkProc: result = parseRoutine(p, nkProcDef)
of tkFunc: result = parseRoutine(p, nkFuncDef)
of tkMethod: result = parseRoutine(p, nkMethodDef) of tkMethod: result = parseRoutine(p, nkMethodDef)
of tkIterator: result = parseRoutine(p, nkIteratorDef) of tkIterator: result = parseRoutine(p, nkIteratorDef)
of tkMacro: result = parseRoutine(p, nkMacroDef) of tkMacro: result = parseRoutine(p, nkMacroDef)
@ -2056,8 +2048,8 @@ proc parseStmt(p: var TParser): PNode =
else: else:
# the case statement is only needed for better error messages: # the case statement is only needed for better error messages:
case p.tok.tokType case p.tok.tokType
of tkIf, tkWhile, tkCase, tkTry, tkFor, tkBlock, tkAsm, tkProc, tkIterator, of tkIf, tkWhile, tkCase, tkTry, tkFor, tkBlock, tkAsm, tkProc, tkFunc,
tkMacro, tkType, tkConst, tkWhen, tkVar: tkIterator, tkMacro, tkType, tkConst, tkWhen, tkVar:
parMessage(p, errComplexStmtRequiresInd) parMessage(p, errComplexStmtRequiresInd)
result = ast.emptyNode result = ast.emptyNode
else: else:

View file

@ -64,7 +64,7 @@ proc astNeeded*(s: PSym): bool =
# needs to be stored. The passes manager frees s.sons[codePos] when # needs to be stored. The passes manager frees s.sons[codePos] when
# appropriate to free the procedure body's memory. This is important # appropriate to free the procedure body's memory. This is important
# to keep memory usage down. # 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 ({sfCompilerProc, sfCompileTime} * s.flags == {}) and
(s.typ.callConv != ccInline) and (s.typ.callConv != ccInline) and
(s.ast.sons[genericParamsPos].kind == nkEmpty): (s.ast.sons[genericParamsPos].kind == nkEmpty):

View file

@ -1166,6 +1166,9 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
of nkProcDef: of nkProcDef:
if renderNoProcDefs notin g.flags: putWithSpace(g, tkProc, "proc") if renderNoProcDefs notin g.flags: putWithSpace(g, tkProc, "proc")
gproc(g, n) gproc(g, n)
of nkFuncDef:
if renderNoProcDefs notin g.flags: putWithSpace(g, tkFunc, "func")
gproc(g, n)
of nkConverterDef: of nkConverterDef:
if renderNoProcDefs notin g.flags: putWithSpace(g, tkConverter, "converter") if renderNoProcDefs notin g.flags: putWithSpace(g, tkConverter, "converter")
gproc(g, n) gproc(g, n)

View file

@ -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]) for i in countup(0, sonsLen(n) - 1): discard process(c, n.sons[i])
#var s = n.sons[namePos].sym #var s = n.sons[namePos].sym
#addInterfaceSym(w, s) #addInterfaceSym(w, s)
of nkProcDef, nkIteratorDef, nkConverterDef, of nkProcDef, nkFuncDef, nkIteratorDef, nkConverterDef,
nkTemplateDef, nkMacroDef: nkTemplateDef, nkMacroDef:
let s = n.sons[namePos].sym let s = n.sons[namePos].sym
if s == nil: internalError(n.info, "rodwrite.process") if s == nil: internalError(n.info, "rodwrite.process")

View file

@ -449,7 +449,7 @@ include semtypes, semtempl, semgnrc, semstmts, semexprs
proc addCodeForGenerics(c: PContext, n: PNode) = proc addCodeForGenerics(c: PContext, n: PNode) =
for i in countup(c.lastGenericIdx, c.generics.len - 1): for i in countup(c.lastGenericIdx, c.generics.len - 1):
var prc = c.generics[i].inst.sym 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: if prc.ast == nil or prc.ast.sons[bodyPos] == nil:
internalError(prc.info, "no code for " & prc.name.s) internalError(prc.info, "no code for " & prc.name.s)
else: else:

View file

@ -468,7 +468,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
for i in countup(0, len(a)-1): for i in countup(0, len(a)-1):
var candidate = a.sons[i].sym var candidate = a.sons[i].sym
if candidate.kind in {skProc, skMethod, skConverter, if candidate.kind in {skProc, skMethod, skConverter,
skIterator}: skFunc, skIterator}:
# it suffices that the candidate has the proper number of generic # it suffices that the candidate has the proper number of generic
# type parameters: # type parameters:
if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1: if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:

View file

@ -373,7 +373,7 @@ proc makeRangeType*(c: PContext; first, last: BiggestInt;
addSonSkipIntLit(result, intType) # basetype of range addSonSkipIntLit(result, intType) # basetype of range
proc markIndirect*(c: PContext, s: PSym) {.inline.} = 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) incl(s.flags, sfAddrTaken)
# XXX add to 'c' for global analysis # XXX add to 'c' for global analysis

View file

@ -574,7 +574,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
optImplicitStatic notin gOptions: return optImplicitStatic notin gOptions: return
if callee.magic notin ctfeWhitelist: 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 return
if n.typ != nil and typeAllowed(n.typ, skConst) != nil: 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 typeof support.
# for ``type(countup(1,3))``, see ``tests/ttoseq``. # for ``type(countup(1,3))``, see ``tests/ttoseq``.
result = semOverloadedCall(c, n, nOrig, result = semOverloadedCall(c, n, nOrig,
{skProc, skMethod, skConverter, skMacro, skTemplate, skIterator}, flags) {skProc, skFunc, skMethod, skConverter, skMacro, skTemplate, skIterator}, flags)
else: else:
result = semOverloadedCall(c, n, nOrig, result = semOverloadedCall(c, n, nOrig,
{skProc, skMethod, skConverter, skMacro, skTemplate}, flags) {skProc, skFunc, skMethod, skConverter, skMacro, skTemplate}, flags)
if result != nil: if result != nil:
if result.sons[0].kind != nkSym: if result.sons[0].kind != nkSym:
@ -1230,7 +1230,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
else: nil else: nil
if s != nil: if s != nil:
case s.kind case s.kind
of skProc, skMethod, skConverter, skIterator: of skProc, skFunc, skMethod, skConverter, skIterator:
# type parameters: partial generic specialization # type parameters: partial generic specialization
n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s) n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
result = explicitGenericInstantiation(c, n, 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 = proc semReturn(c: PContext, n: PNode): PNode =
result = n result = n
checkSonsLen(n, 1) 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): c.p.owner.kind == skIterator and c.p.owner.typ.callConv == ccClosure):
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
# transform ``return expr`` to ``result = expr; return`` # 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) var s = qualifiedLookUp(c, n, checks)
if c.matchedConcept == nil: semCaptureSym(s, c.p.owner) if c.matchedConcept == nil: semCaptureSym(s, c.p.owner)
result = semSym(c, n, s, flags) 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) #performProcvarCheck(c, n, s)
result = symChoice(c, n, s, scClosed) result = symChoice(c, n, s, scClosed)
if result.kind == nkSym: if result.kind == nkSym:
@ -2217,7 +2217,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
errorUseQualifier(c, n.info, s) errorUseQualifier(c, n.info, s)
elif s.magic == mNone: result = semDirectOp(c, n, flags) elif s.magic == mNone: result = semDirectOp(c, n, flags)
else: result = semMagic(c, n, s, 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) if s.magic == mNone: result = semDirectOp(c, n, flags)
else: result = semMagic(c, n, s, flags) else: result = semMagic(c, n, s, flags)
else: else:
@ -2330,7 +2330,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkYieldStmt: result = semYield(c, n) of nkYieldStmt: result = semYield(c, n)
of nkPragma: pragma(c, c.p.owner, n, stmtPragmas) of nkPragma: pragma(c, c.p.owner, n, stmtPragmas)
of nkIteratorDef: result = semIterator(c, n) 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 nkMethodDef: result = semMethod(c, n)
of nkConverterDef: result = semConverterDef(c, n) of nkConverterDef: result = semConverterDef(c, n)
of nkMacroDef: result = semMacroDef(c, n) of nkMacroDef: result = semMacroDef(c, n)

View file

@ -630,7 +630,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
result = newStrNodeT(lookupSymbol(s.name), n) result = newStrNodeT(lookupSymbol(s.name), n)
else: else:
result = copyTree(s.ast) result = copyTree(s.ast)
of {skProc, skMethod}: of {skProc, skFunc, skMethod}:
result = n result = n
of skType: of skType:
# XXX gensym'ed symbols can come here and cannot be resolved. This is # 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: of nkCallKinds:
if n.sons[0].kind != nkSym: return if n.sons[0].kind != nkSym: return
var s = n.sons[0].sym var s = n.sons[0].sym
if s.kind != skProc: return if s.kind != skProc and s.kind != skFunc: return
try: try:
case s.magic case s.magic
of mNone: of mNone:

View file

@ -61,7 +61,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
of skUnknown: of skUnknown:
# Introduced in this pass! Leave it as an identifier. # Introduced in this pass! Leave it as an identifier.
result = n result = n
of skProc, skMethod, skIterator, skConverter, skModule: of skProc, skFunc, skMethod, skIterator, skConverter, skModule:
result = symChoice(c, n, s, scOpen) result = symChoice(c, n, s, scOpen)
of skTemplate: of skTemplate:
if macroToExpandSym(s): if macroToExpandSym(s):
@ -243,7 +243,7 @@ proc semGenericStmt(c: PContext, n: PNode,
of skUnknown, skParam: of skUnknown, skParam:
# Leave it as an identifier. # Leave it as an identifier.
discard discard
of skProc, skMethod, skIterator, skConverter, skModule: of skProc, skFunc, skMethod, skIterator, skConverter, skModule:
result.sons[0] = sc result.sons[0] = sc
# do not check of 's.magic==mRoof' here because it might be some # do not check of 's.magic==mRoof' here because it might be some
# other '^' but after overload resolution the proper one: # 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): for j in countup(0, L-3):
addTempDecl(c, getIdentNode(a.sons[j]), skParam) addTempDecl(c, getIdentNode(a.sons[j]), skParam)
of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
nkIteratorDef, nkLambdaKinds: nkFuncDef, nkIteratorDef, nkLambdaKinds:
checkSonsLen(n, bodyPos + 1) checkSonsLen(n, bodyPos + 1)
if n.sons[namePos].kind != nkEmpty: if n.sons[namePos].kind != nkEmpty:
addTempDecl(c, getIdentNode(n.sons[0]), skProc) addTempDecl(c, getIdentNode(n.sons[0]), skProc)

View file

@ -36,7 +36,7 @@ proc rawPushProcCon(c: PContext, owner: PSym) =
c.p = x c.p = x
proc rawHandleSelf(c: PContext; owner: PSym) = 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: if c.selfName != nil and owner.kind in callableSymbols and owner.typ != nil:
let params = owner.typ.n let params = owner.typ.n
if params.len > 1: if params.len > 1:

View file

@ -387,7 +387,7 @@ proc analyse(c: var AnalysisCtx; n: PNode) =
addFactNeg(c.guards, canon(n.sons[0])) addFactNeg(c.guards, canon(n.sons[0]))
dec c.inLoop dec c.inLoop
of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef, of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
nkMacroDef, nkTemplateDef, nkConstSection, nkPragma: nkMacroDef, nkTemplateDef, nkConstSection, nkPragma, nkFuncDef:
discard discard
else: else:
analyseSons(c, n) analyseSons(c, n)

View file

@ -835,7 +835,7 @@ proc track(tracked: PEffects, n: PNode) =
setLen(tracked.locked, oldLocked) setLen(tracked.locked, oldLocked)
tracked.currLockLevel = oldLockLevel tracked.currLockLevel = oldLockLevel
of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef, of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
nkMacroDef, nkTemplateDef, nkLambda, nkDo: nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef:
discard discard
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv: of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv:
if n.len == 2: track(tracked, n.sons[1]) if n.len == 2: track(tracked, n.sons[1])
@ -937,7 +937,7 @@ proc trackProc*(s: PSym, body: PNode) =
track(t, body) track(t, body)
if not isEmptyType(s.typ.sons[0]) and if not isEmptyType(s.typ.sons[0]) and
{tfNeedsInit, tfNotNil} * s.typ.sons[0].flags != {} 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 var res = s.ast.sons[resultPos].sym # get result symbol
if res.id notin t.init: if res.id notin t.init:
message(body.info, warnProveInit, "result") message(body.info, warnProveInit, "result")
@ -979,10 +979,10 @@ proc trackProc*(s: PSym, body: PNode) =
message(s.info, warnLockLevel, message(s.info, warnLockLevel,
"declared lock level is $1, but real lock level is $2" % "declared lock level is $1, but real lock level is $2" %
[$s.typ.lockLevel, $t.maxLockLevel]) [$s.typ.lockLevel, $t.maxLockLevel])
when useWriteTracking: trackWrites(s, body) if s.kind == skFunc: trackWrites(s, body)
proc trackTopLevelStmt*(module: PSym; n: PNode) = 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}: nkTypeSection, nkConverterDef, nkMethodDef, nkIteratorDef}:
return return
var effects = newNode(nkEffectList, n.info) var effects = newNode(nkEffectList, n.info)

View file

@ -449,6 +449,8 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
a.sons[2] = semTemplBody(c, a.sons[2]) a.sons[2] = semTemplBody(c, a.sons[2])
of nkProcDef, nkLambdaKinds: of nkProcDef, nkLambdaKinds:
result = semRoutineInTemplBody(c, n, skProc) result = semRoutineInTemplBody(c, n, skProc)
of nkFuncDef:
result = semRoutineInTemplBody(c, n, skFunc)
of nkMethodDef: of nkMethodDef:
result = semRoutineInTemplBody(c, n, skMethod) result = semRoutineInTemplBody(c, n, skMethod)
of nkIteratorDef: of nkIteratorDef:

View file

@ -170,7 +170,7 @@ proc reResolveCallsWithTypedescParams(cl: var TReplTypeVars, n: PNode): PNode =
if isTypeParam(n[i]): needsFixing = true if isTypeParam(n[i]): needsFixing = true
if needsFixing: if needsFixing:
n.sons[0] = newSymNode(n.sons[0].sym.owner) 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: for i in 0 .. <n.safeLen:
n.sons[i] = reResolveCallsWithTypedescParams(cl, n[i]) n.sons[i] = reResolveCallsWithTypedescParams(cl, n[i])

View file

@ -1373,7 +1373,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
# XXX: This is very hacky. It should be moved back into liftTypeParam # XXX: This is very hacky. It should be moved back into liftTypeParam
if x.kind in {tyGenericInst, tyArray} and if x.kind in {tyGenericInst, tyArray} and
c.calleeSym != nil 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) let inst = prepareMetatypeForSigmatch(c.c, c.bindings, c.call.info, f)
return typeRel(c, inst, a) return typeRel(c, inst, a)
@ -1832,7 +1832,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
bothMetaCounter < 100: bothMetaCounter < 100:
lastBindingsLength = m.bindings.counter lastBindingsLength = m.bindings.counter
inc(bothMetaCounter) inc(bothMetaCounter)
if arg.kind in {nkProcDef, nkIteratorDef} + nkLambdaKinds: if arg.kind in {nkProcDef, nkFuncDef, nkIteratorDef} + nkLambdaKinds:
result = c.semInferredLambda(c, m.bindings, arg) result = c.semInferredLambda(c, m.bindings, arg)
elif arg.kind != nkSym: elif arg.kind != nkSym:
return nil return nil
@ -1865,7 +1865,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
else: else:
result = implicitConv(nkHiddenStdConv, f, arg, m, c) result = implicitConv(nkHiddenStdConv, f, arg, m, c)
of isInferred, isInferredConvertible: 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) result = c.semInferredLambda(c, m.bindings, arg)
elif arg.kind != nkSym: elif arg.kind != nkSym:
return nil return nil
@ -1952,7 +1952,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
z.calleeSym = m.calleeSym z.calleeSym = m.calleeSym
var best = -1 var best = -1
for i in countup(0, sonsLen(arg) - 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) copyCandidate(z, m)
z.callee = arg.sons[i].typ z.callee = arg.sons[i].typ
if tfUnresolved in z.callee.flags: continue if tfUnresolved in z.callee.flags: continue

View file

@ -121,7 +121,7 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
if s.kind == skIterator: if s.kind == skIterator:
if c.tooEarly: return n if c.tooEarly: return n
else: return liftIterSym(n, getCurrOwner(c)) 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': # top level .closure procs are still somewhat supported for 'Nake':
return makeClosure(s, nil, n.info) return makeClosure(s, nil, n.info)
#elif n.sym.kind in {skVar, skLet} and n.sym.typ.callConv == ccClosure: #elif n.sym.kind in {skVar, skLet} and n.sym.typ.callConv == ccClosure:

View file

@ -1089,7 +1089,7 @@ proc typeAllowedNode(marker: var IntSet, n: PNode, kind: TSymKind,
of nkNone..nkNilLit: of nkNone..nkNilLit:
discard discard
else: else:
if n.kind == nkRecCase and kind in {skProc, skConst}: if n.kind == nkRecCase and kind in {skProc, skFunc, skConst}:
return n[0].typ return n[0].typ
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
let it = n.sons[i] 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, proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
flags: TTypeAllowedFlags = {}): PType = 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 # if we have already checked the type, return true, because we stop the
# evaluation if something is wrong: # evaluation if something is wrong:
result = nil result = nil
@ -1116,7 +1116,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
var t = skipTypes(typ, abstractInst-{tyTypeDesc}) var t = skipTypes(typ, abstractInst-{tyTypeDesc})
case t.kind case t.kind
of tyVar: 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}) var t2 = skipTypes(t.sons[0], abstractInst-{tyTypeDesc})
case t2.kind case t2.kind
of tyVar: of tyVar:
@ -1176,7 +1176,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
result = typeAllowedAux(marker, t.sons[i], kind, flags) result = typeAllowedAux(marker, t.sons[i], kind, flags)
if result != nil: break if result != nil: break
of tyObject, tyTuple: 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 t.kind == tyObject and t.sons[0] != nil: return t
let flags = flags+{taField} let flags = flags+{taField}
for i in countup(0, sonsLen(t) - 1): for i in countup(0, sonsLen(t) - 1):

View file

@ -1289,7 +1289,7 @@ proc checkCanEval(c: PCtx; n: PNode) =
if s.kind in {skVar, skTemp, skLet, skParam, skResult} and 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: not s.isOwnedBy(c.prc.sym) and s.owner != c.module and c.mode != emRepl:
cannotEval(n) cannotEval(n)
elif s.kind in {skProc, skConverter, skMethod, elif s.kind in {skProc, skFunc, skConverter, skMethod,
skIterator} and sfForward in s.flags: skIterator} and sfForward in s.flags:
cannotEval(n) cannotEval(n)
@ -1712,7 +1712,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
case s.kind case s.kind
of skVar, skForVar, skTemp, skLet, skParam, skResult: of skVar, skForVar, skTemp, skLet, skParam, skResult:
genRdVar(c, n, dest, flags) 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: # 'skTemplate' is only allowed for 'getAst' support:
if procIsCallback(c, s): discard if procIsCallback(c, s): discard
elif sfImportc in s.flags: c.importcSym(n.info, s) elif sfImportc in s.flags: c.importcSym(n.info, s)

View file

@ -248,6 +248,8 @@ proc markWriteOrEscape(w: var W) =
for p in a.dest: for p in a.dest:
if p.kind == skParam and p.owner == w.owner: if p.kind == skParam and p.owner == w.owner:
incl(p.flags, sfWrittenTo) 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 != {}: if {rootIsResultOrParam, rootIsHeapAccess, markAsEscaping}*a.destInfo != {}:
var destIsParam = false var destIsParam = false

View file

@ -75,7 +75,8 @@ type
nnkClosure, nnkClosure,
nnkGotoState, nnkGotoState,
nnkState, nnkState,
nnkBreakState nnkBreakState,
nnkFuncDef
NimNodeKinds* = set[NimNodeKind] NimNodeKinds* = set[NimNodeKind]
NimTypeKind* = enum # some types are no longer used, see ast.nim NimTypeKind* = enum # some types are no longer used, see ast.nim
@ -103,7 +104,7 @@ type
nskUnknown, nskConditional, nskDynLib, nskParam, nskUnknown, nskConditional, nskDynLib, nskParam,
nskGenericParam, nskTemp, nskModule, nskType, nskVar, nskLet, nskGenericParam, nskTemp, nskModule, nskType, nskVar, nskLet,
nskConst, nskResult, nskConst, nskResult,
nskProc, nskMethod, nskIterator, nskProc, nskFunc, nskMethod, nskIterator,
nskConverter, nskMacro, nskTemplate, nskField, nskConverter, nskMacro, nskTemplate, nskField,
nskEnumField, nskForVar, nskLabel, nskEnumField, nskForVar, nskLabel,
nskStub nskStub
@ -843,7 +844,8 @@ proc last*(node: NimNode): NimNode {.compileTime.} = node[<node.len]
const const
RoutineNodes* = {nnkProcDef, nnkMethodDef, nnkDo, nnkLambda, nnkIteratorDef, nnkTemplateDef, nnkConverterDef} RoutineNodes* = {nnkProcDef, nnkFuncDef, nnkMethodDef, nnkDo, nnkLambda,
nnkIteratorDef, nnkTemplateDef, nnkConverterDef}
AtomicNodes* = {nnkNone..nnkNilLit} AtomicNodes* = {nnkNone..nnkNilLit}
CallNodes* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand, CallNodes* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
nnkCallStrLit, nnkHiddenCallConv} nnkCallStrLit, nnkHiddenCallConv}