Merge branch 'devel' into add_cline
This commit is contained in:
commit
dcdddec674
11 changed files with 69 additions and 49 deletions
|
|
@ -1944,7 +1944,7 @@ template injectG() {.dirty.} =
|
||||||
graph.backend = newModuleList(graph)
|
graph.backend = newModuleList(graph)
|
||||||
let g = BModuleList(graph.backend)
|
let g = BModuleList(graph.backend)
|
||||||
|
|
||||||
proc setupCgen*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} =
|
proc setupCgen*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
|
||||||
injectG()
|
injectG()
|
||||||
result = newModule(g, module, graph.config)
|
result = newModule(g, module, graph.config)
|
||||||
result.idgen = idgen
|
result.idgen = idgen
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ proc generateDot*(graph: ModuleGraph; project: AbsoluteFile) =
|
||||||
rope(project.splitFile.name), b.dotGraph],
|
rope(project.splitFile.name), b.dotGraph],
|
||||||
changeFileExt(project, "dot"))
|
changeFileExt(project, "dot"))
|
||||||
|
|
||||||
proc setupDependPass*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} =
|
proc setupDependPass*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
|
||||||
var g: PGen
|
var g: PGen
|
||||||
new(g)
|
new(g)
|
||||||
g.module = module
|
g.module = module
|
||||||
|
|
|
||||||
|
|
@ -735,6 +735,8 @@ proc genLineDir(p: PProc, n: PNode) =
|
||||||
let line = toLinenumber(n.info)
|
let line = toLinenumber(n.info)
|
||||||
if line < 0:
|
if line < 0:
|
||||||
return
|
return
|
||||||
|
if optEmbedOrigSrc in p.config.globalOptions:
|
||||||
|
lineF(p, "//$1$n", [sourceLine(p.config, n.info)])
|
||||||
if optLineDir in p.options or optLineDir in p.config.options:
|
if optLineDir in p.options or optLineDir in p.config.options:
|
||||||
lineF(p, "$1", [lineDir(p.config, n.info, line)])
|
lineF(p, "$1", [lineDir(p.config, n.info, line)])
|
||||||
if hasFrameInfo(p):
|
if hasFrameInfo(p):
|
||||||
|
|
|
||||||
|
|
@ -241,14 +241,14 @@ proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) =
|
||||||
graph.compileSystemModule()
|
graph.compileSystemModule()
|
||||||
discard graph.compileModule(projectFile, {sfMainModule})
|
discard graph.compileModule(projectFile, {sfMainModule})
|
||||||
|
|
||||||
proc mySemOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} =
|
proc mySemOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
|
||||||
result = preparePContext(graph, module, idgen)
|
result = preparePContext(graph, module, idgen)
|
||||||
|
|
||||||
proc mySemClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
|
proc mySemClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
|
||||||
var c = PContext(context)
|
var c = PContext(context)
|
||||||
closePContext(graph, c, n)
|
closePContext(graph, c, n)
|
||||||
|
|
||||||
proc mySemProcess(context: PPassContext, n: PNode): PNode {.nosinks.} =
|
proc mySemProcess(context: PPassContext, n: PNode): PNode =
|
||||||
result = semWithPContext(PContext(context), n)
|
result = semWithPContext(PContext(context), n)
|
||||||
|
|
||||||
const semPass* = makePass(mySemOpen, mySemProcess, mySemClose,
|
const semPass* = makePass(mySemOpen, mySemProcess, mySemClose,
|
||||||
|
|
|
||||||
|
|
@ -666,7 +666,7 @@ proc addCodeForGenerics(c: PContext, n: PNode) =
|
||||||
n.add prc.ast
|
n.add prc.ast
|
||||||
c.lastGenericIdx = c.generics.len
|
c.lastGenericIdx = c.generics.len
|
||||||
|
|
||||||
proc preparePContext*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PContext {.nosinks.} =
|
proc preparePContext*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PContext =
|
||||||
result = newContext(graph, module)
|
result = newContext(graph, module)
|
||||||
result.idgen = idgen
|
result.idgen = idgen
|
||||||
result.enforceVoidContext = newType(tyTyped, nextTypeId(idgen), nil)
|
result.enforceVoidContext = newType(tyTyped, nextTypeId(idgen), nil)
|
||||||
|
|
@ -770,7 +770,7 @@ proc recoverContext(c: PContext) =
|
||||||
while getCurrOwner(c).kind != skModule: popOwner(c)
|
while getCurrOwner(c).kind != skModule: popOwner(c)
|
||||||
while c.p != nil and c.p.owner.kind != skModule: c.p = c.p.next
|
while c.p != nil and c.p.owner.kind != skModule: c.p = c.p.next
|
||||||
|
|
||||||
proc semWithPContext*(c: PContext, n: PNode): PNode {.nosinks.} =
|
proc semWithPContext*(c: PContext, n: PNode): PNode =
|
||||||
# no need for an expensive 'try' if we stop after the first error anyway:
|
# no need for an expensive 'try' if we stop after the first error anyway:
|
||||||
if c.config.errorMax <= 1:
|
if c.config.errorMax <= 1:
|
||||||
result = semStmtAndGenerateGenerics(c, n)
|
result = semStmtAndGenerateGenerics(c, n)
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ proc initCandidateSymbols(c: PContext, headSymbol: PNode,
|
||||||
best, alt: var TCandidate,
|
best, alt: var TCandidate,
|
||||||
o: var TOverloadIter,
|
o: var TOverloadIter,
|
||||||
diagnostics: bool): seq[tuple[s: PSym, scope: int]] =
|
diagnostics: bool): seq[tuple[s: PSym, scope: int]] =
|
||||||
|
## puts all overloads into a seq and prepares best+alt
|
||||||
result = @[]
|
result = @[]
|
||||||
var symx = initOverloadIter(o, c, headSymbol)
|
var symx = initOverloadIter(o, c, headSymbol)
|
||||||
while symx != nil:
|
while symx != nil:
|
||||||
|
|
@ -64,36 +65,35 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
errors: var CandidateErrors,
|
errors: var CandidateErrors,
|
||||||
diagnosticsFlag: bool,
|
diagnosticsFlag: bool,
|
||||||
errorsEnabled: bool, flags: TExprFlags) =
|
errorsEnabled: bool, flags: TExprFlags) =
|
||||||
|
# `matches` may find new symbols, so keep track of count
|
||||||
|
var symCount = c.currentScope.symbols.counter
|
||||||
|
|
||||||
var o: TOverloadIter
|
var o: TOverloadIter
|
||||||
var sym = initOverloadIter(o, c, headSymbol)
|
# https://github.com/nim-lang/Nim/issues/21272
|
||||||
var scope = o.lastOverloadScope
|
# prevent mutation during iteration by storing them in a seq
|
||||||
# Thanks to the lazy semchecking for operands, we need to check whether
|
# luckily `initCandidateSymbols` does just that
|
||||||
# 'initCandidate' modifies the symbol table (via semExpr).
|
var syms = initCandidateSymbols(c, headSymbol, initialBinding, filter,
|
||||||
# This can occur in cases like 'init(a, 1, (var b = new(Type2); b))'
|
best, alt, o, diagnosticsFlag)
|
||||||
let counterInitial = c.currentScope.symbols.counter
|
if len(syms) == 0:
|
||||||
var syms: seq[tuple[s: PSym, scope: int]]
|
return
|
||||||
var noSyms = true
|
# current overload being considered
|
||||||
var nextSymIndex = 0
|
var sym = syms[0].s
|
||||||
while sym != nil:
|
var scope = syms[0].scope
|
||||||
if sym.kind in filter:
|
|
||||||
# Initialise 'best' and 'alt' with the first available symbol
|
# starts at 1 because 0 is already done with setup, only needs checking
|
||||||
initCandidate(c, best, sym, initialBinding, scope, diagnosticsFlag)
|
var nextSymIndex = 1
|
||||||
initCandidate(c, alt, sym, initialBinding, scope, diagnosticsFlag)
|
var z: TCandidate # current candidate
|
||||||
best.state = csNoMatch
|
while true:
|
||||||
break
|
|
||||||
else:
|
|
||||||
sym = nextOverloadIter(o, c, headSymbol)
|
|
||||||
scope = o.lastOverloadScope
|
|
||||||
var z: TCandidate
|
|
||||||
while sym != nil:
|
|
||||||
if sym.kind notin filter:
|
|
||||||
sym = nextOverloadIter(o, c, headSymbol)
|
|
||||||
scope = o.lastOverloadScope
|
|
||||||
continue
|
|
||||||
determineType(c, sym)
|
determineType(c, sym)
|
||||||
initCandidate(c, z, sym, initialBinding, scope, diagnosticsFlag)
|
initCandidate(c, z, sym, initialBinding, scope, diagnosticsFlag)
|
||||||
if c.currentScope.symbols.counter == counterInitial or syms.len != 0:
|
|
||||||
|
# this is kinda backwards as without a check here the described
|
||||||
|
# problems in recalc would not happen, but instead it 100%
|
||||||
|
# does check forever in some cases
|
||||||
|
if c.currentScope.symbols.counter == symCount:
|
||||||
|
# may introduce new symbols with caveats described in recalc branch
|
||||||
matches(c, n, orig, z)
|
matches(c, n, orig, z)
|
||||||
|
|
||||||
if z.state == csMatch:
|
if z.state == csMatch:
|
||||||
# little hack so that iterators are preferred over everything else:
|
# little hack so that iterators are preferred over everything else:
|
||||||
if sym.kind == skIterator:
|
if sym.kind == skIterator:
|
||||||
|
|
@ -113,22 +113,36 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
firstMismatch: z.firstMismatch,
|
firstMismatch: z.firstMismatch,
|
||||||
diagnostics: z.diagnostics))
|
diagnostics: z.diagnostics))
|
||||||
else:
|
else:
|
||||||
|
# this branch feels like a ticking timebomb
|
||||||
|
# one of two bad things could happen
|
||||||
|
# 1) new symbols are discovered but the loop ends before we recalc
|
||||||
|
# 2) new symbols are discovered and resemmed forever
|
||||||
|
# not 100% sure if these are possible though as they would rely
|
||||||
|
# on somehow introducing a new overload during overload resolution
|
||||||
|
|
||||||
# Symbol table has been modified. Restart and pre-calculate all syms
|
# Symbol table has been modified. Restart and pre-calculate all syms
|
||||||
# before any further candidate init and compare. SLOW, but rare case.
|
# before any further candidate init and compare. SLOW, but rare case.
|
||||||
syms = initCandidateSymbols(c, headSymbol, initialBinding, filter,
|
syms = initCandidateSymbols(c, headSymbol, initialBinding, filter,
|
||||||
best, alt, o, diagnosticsFlag)
|
best, alt, o, diagnosticsFlag)
|
||||||
noSyms = false
|
|
||||||
if noSyms:
|
# reset counter because syms may be in a new order
|
||||||
sym = nextOverloadIter(o, c, headSymbol)
|
symCount = c.currentScope.symbols.counter
|
||||||
scope = o.lastOverloadScope
|
nextSymIndex = 0
|
||||||
elif nextSymIndex < syms.len:
|
|
||||||
# rare case: retrieve the next pre-calculated symbol
|
# just in case, should be impossible though
|
||||||
sym = syms[nextSymIndex].s
|
if syms.len == 0:
|
||||||
scope = syms[nextSymIndex].scope
|
break
|
||||||
nextSymIndex += 1
|
|
||||||
else:
|
if nextSymIndex > high(syms):
|
||||||
|
# we have reached the end
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# advance to next sym
|
||||||
|
sym = syms[nextSymIndex].s
|
||||||
|
scope = syms[nextSymIndex].scope
|
||||||
|
inc(nextSymIndex)
|
||||||
|
|
||||||
|
|
||||||
proc effectProblem(f, a: PType; result: var string; c: PContext) =
|
proc effectProblem(f, a: PType; result: var string; c: PContext) =
|
||||||
if f.kind == tyProc and a.kind == tyProc:
|
if f.kind == tyProc and a.kind == tyProc:
|
||||||
if tfThread in f.flags and tfThread notin a.flags:
|
if tfThread in f.flags and tfThread notin a.flags:
|
||||||
|
|
@ -601,7 +615,7 @@ proc tryDeref(n: PNode): PNode =
|
||||||
result.add n
|
result.add n
|
||||||
|
|
||||||
proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||||
filter: TSymKinds, flags: TExprFlags): PNode {.nosinks.} =
|
filter: TSymKinds, flags: TExprFlags): PNode =
|
||||||
var errors: CandidateErrors = @[] # if efExplain in flags: @[] else: nil
|
var errors: CandidateErrors = @[] # if efExplain in flags: @[] else: nil
|
||||||
var r = resolveOverloads(c, n, nOrig, filter, flags, errors, efExplain in flags)
|
var r = resolveOverloads(c, n, nOrig, filter, flags, errors, efExplain in flags)
|
||||||
if r.state == csMatch:
|
if r.state == csMatch:
|
||||||
|
|
|
||||||
|
|
@ -314,7 +314,7 @@ proc fillMixinScope(c: PContext) =
|
||||||
p = p.next
|
p = p.next
|
||||||
|
|
||||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
info: TLineInfo): PSym {.nosinks.} =
|
info: TLineInfo): PSym =
|
||||||
## Generates a new instance of a generic procedure.
|
## Generates a new instance of a generic procedure.
|
||||||
## The `pt` parameter is a type-unsafe mapping table used to link generic
|
## The `pt` parameter is a type-unsafe mapping table used to link generic
|
||||||
## parameters to their concrete types within the generic instance.
|
## parameters to their concrete types within the generic instance.
|
||||||
|
|
|
||||||
|
|
@ -1692,7 +1692,7 @@ proc semProcAnnotation(c: PContext, prc: PNode;
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode {.nosinks.} =
|
proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
|
||||||
## used for resolving 'auto' in lambdas based on their callsite
|
## used for resolving 'auto' in lambdas based on their callsite
|
||||||
var n = n
|
var n = n
|
||||||
let original = n[namePos].sym
|
let original = n[namePos].sym
|
||||||
|
|
|
||||||
|
|
@ -2674,7 +2674,7 @@ proc argtypeMatches*(c: PContext, f, a: PType, fromHlo = false): bool =
|
||||||
|
|
||||||
|
|
||||||
proc instTypeBoundOp*(c: PContext; dc: PSym; t: PType; info: TLineInfo;
|
proc instTypeBoundOp*(c: PContext; dc: PSym; t: PType; info: TLineInfo;
|
||||||
op: TTypeAttachedOp; col: int): PSym {.nosinks.} =
|
op: TTypeAttachedOp; col: int): PSym =
|
||||||
var m = newCandidate(c, dc.typ)
|
var m = newCandidate(c, dc.typ)
|
||||||
if col >= dc.typ.len:
|
if col >= dc.typ.len:
|
||||||
localError(c.config, info, "cannot instantiate: '" & dc.name.s & "'")
|
localError(c.config, info, "cannot instantiate: '" & dc.name.s & "'")
|
||||||
|
|
|
||||||
|
|
@ -1893,7 +1893,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
var error: string
|
var error: string
|
||||||
let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
|
let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
|
||||||
regs[rc].node.strVal, 0,
|
regs[rc].node.strVal, 0,
|
||||||
proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) {.nosinks.} =
|
proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) =
|
||||||
if error.len == 0 and msg <= errMax:
|
if error.len == 0 and msg <= errMax:
|
||||||
error = formatMsg(conf, info, msg, arg))
|
error = formatMsg(conf, info, msg, arg))
|
||||||
if error.len > 0:
|
if error.len > 0:
|
||||||
|
|
@ -1908,7 +1908,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
var error: string
|
var error: string
|
||||||
let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
|
let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
|
||||||
regs[rc].node.strVal, 0,
|
regs[rc].node.strVal, 0,
|
||||||
proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) {.nosinks.} =
|
proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) =
|
||||||
if error.len == 0 and msg <= errMax:
|
if error.len == 0 and msg <= errMax:
|
||||||
error = formatMsg(conf, info, msg, arg))
|
error = formatMsg(conf, info, msg, arg))
|
||||||
if error.len > 0:
|
if error.len > 0:
|
||||||
|
|
@ -2309,7 +2309,7 @@ proc setupGlobalCtx*(module: PSym; graph: ModuleGraph; idgen: IdGenerator) =
|
||||||
else:
|
else:
|
||||||
refresh(PCtx graph.vm, module, idgen)
|
refresh(PCtx graph.vm, module, idgen)
|
||||||
|
|
||||||
proc setupEvalGen*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} =
|
proc setupEvalGen*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
|
||||||
#var c = newEvalContext(module, emRepl)
|
#var c = newEvalContext(module, emRepl)
|
||||||
#c.features = {allowCast, allowInfiniteLoops}
|
#c.features = {allowCast, allowInfiniteLoops}
|
||||||
#pushStackFrame(c, newStackFrame())
|
#pushStackFrame(c, newStackFrame())
|
||||||
|
|
|
||||||
|
|
@ -220,6 +220,10 @@ proc waitForExit*(p: Process, timeout: int = -1): int {.rtl,
|
||||||
##
|
##
|
||||||
## On posix, if the process has exited because of a signal, 128 + signal
|
## On posix, if the process has exited because of a signal, 128 + signal
|
||||||
## number will be returned.
|
## number will be returned.
|
||||||
|
##
|
||||||
|
## .. warning:: When working with `timeout` parameters, remember that the value is
|
||||||
|
## typically expressed in milliseconds, and ensure that the correct unit of time
|
||||||
|
## is used to avoid unexpected behavior.
|
||||||
|
|
||||||
proc peekExitCode*(p: Process): int {.rtl, extern: "nosp$1", raises: [OSError], tags: [].}
|
proc peekExitCode*(p: Process): int {.rtl, extern: "nosp$1", raises: [OSError], tags: [].}
|
||||||
## Return `-1` if the process is still running. Otherwise the process' exit code.
|
## Return `-1` if the process is still running. Otherwise the process' exit code.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue