mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
first implementation of the 'func' keyword
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user