mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-31 02:12:11 +00:00
less cascading errors for 'check' and 'ide-tools'
This commit is contained in:
20
rod/sem.nim
20
rod/sem.nim
@@ -29,9 +29,7 @@ proc considerAcc(n: PNode): PIdent =
|
||||
result = nil
|
||||
|
||||
proc isTopLevel(c: PContext): bool {.inline.} =
|
||||
# if we encountered an error, we treat as top-level so that
|
||||
# cascading errors are not that strange:
|
||||
result = c.tab.tos <= 2 or msgs.gErrorCounter > 0
|
||||
result = c.tab.tos <= 2
|
||||
|
||||
proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||
result = newSym(kind, considerAcc(n), getCurrOwner())
|
||||
@@ -166,7 +164,7 @@ proc myOpen(module: PSym, filename: string): PPassContext =
|
||||
if (c.p != nil): InternalError(module.info, "sem.myOpen")
|
||||
c.semConstExpr = semConstExpr
|
||||
c.semExpr = semExprNoFlags
|
||||
c.p = newProcCon(module)
|
||||
pushProcCon(c, module)
|
||||
pushOwner(c.module)
|
||||
openScope(c.tab) # scope for imported symbols
|
||||
SymTabAdd(c.tab, module) # a module knows itself
|
||||
@@ -179,7 +177,8 @@ proc myOpen(module: PSym, filename: string): PPassContext =
|
||||
openScope(c.tab) # scope for the module's symbols
|
||||
result = c
|
||||
|
||||
proc myOpenCached(module: PSym, filename: string, rd: PRodReader): PPassContext =
|
||||
proc myOpenCached(module: PSym, filename: string,
|
||||
rd: PRodReader): PPassContext =
|
||||
var c = PContext(myOpen(module, filename))
|
||||
c.fromCache = true
|
||||
result = c
|
||||
@@ -195,6 +194,14 @@ proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
|
||||
if result.kind != nkEmpty: addSon(a, result)
|
||||
result = a
|
||||
|
||||
proc RecoverContext(c: PContext) =
|
||||
# clean up in case of a semantic error: We clean up the stacks, etc. This is
|
||||
# faster than wrapping every stack operation in a 'try finally' block and
|
||||
# requires far less code.
|
||||
while c.tab.tos-1 > ModuleTablePos: rawCloseScope(c.tab)
|
||||
while getCurrOwner().kind != skModule: popOwner()
|
||||
while c.p != nil and c.p.owner.kind != skModule: c.p = c.p.next
|
||||
|
||||
proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||
var c = PContext(context)
|
||||
# no need for an expensive 'try' if we stop after the first error anyway:
|
||||
@@ -204,6 +211,7 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||
try:
|
||||
result = SemStmtAndGenerateGenerics(c, n)
|
||||
except ERecoverableError:
|
||||
RecoverContext(c)
|
||||
result = ast.emptyNode
|
||||
|
||||
proc myClose(context: PPassContext, n: PNode): PNode =
|
||||
@@ -216,7 +224,7 @@ proc myClose(context: PPassContext, n: PNode): PNode =
|
||||
InternalError(n.info, "n is not nil") #result := n;
|
||||
addCodeForGenerics(c, result)
|
||||
popOwner()
|
||||
c.p = nil
|
||||
popProcCon(c)
|
||||
|
||||
proc semPass(): TPass =
|
||||
initPass(result)
|
||||
|
||||
@@ -23,14 +23,15 @@ type
|
||||
Notes*: TNoteKinds
|
||||
|
||||
POptionEntry* = ref TOptionEntry
|
||||
PProcCon* = ref TProcCon
|
||||
TProcCon*{.final.} = object # procedure context; also used for top-level
|
||||
# statements
|
||||
owner*: PSym # the symbol this context belongs to
|
||||
resultSym*: PSym # the result symbol (if we are in a proc)
|
||||
nestedLoopCounter*: int # whether we are in a loop or not
|
||||
nestedBlockCounter*: int # whether we are in a block or not
|
||||
next*: PProcCon # used for stacking procedure contexts
|
||||
|
||||
PProcCon* = ref TProcCon
|
||||
PContext* = ref TContext
|
||||
TContext* = object of TPassContext # a context represents a module
|
||||
module*: PSym # the module sym belonging to the context
|
||||
@@ -58,7 +59,6 @@ var gInstTypes*: TIdTable # map PType to PType
|
||||
|
||||
proc newContext*(module: PSym, nimfile: string): PContext
|
||||
|
||||
proc newProcCon*(owner: PSym): PProcCon
|
||||
proc lastOptionEntry*(c: PContext): POptionEntry
|
||||
proc newOptionEntry*(): POptionEntry
|
||||
proc addConverter*(c: PContext, conv: PSym)
|
||||
@@ -97,10 +97,15 @@ proc PopOwner() =
|
||||
proc lastOptionEntry(c: PContext): POptionEntry =
|
||||
result = POptionEntry(c.optionStack.tail)
|
||||
|
||||
proc newProcCon(owner: PSym): PProcCon =
|
||||
proc pushProcCon*(c: PContext, owner: PSym) {.inline.} =
|
||||
if owner == nil: InternalError("owner is nil")
|
||||
new(result)
|
||||
result.owner = owner
|
||||
var x: PProcCon
|
||||
new(x)
|
||||
x.owner = owner
|
||||
x.next = c.p
|
||||
c.p = x
|
||||
|
||||
proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next
|
||||
|
||||
proc newOptionEntry(): POptionEntry =
|
||||
new(result)
|
||||
|
||||
@@ -68,13 +68,12 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
# generates an instantiated proc
|
||||
var
|
||||
oldPrc, oldMod: PSym
|
||||
oldP: PProcCon
|
||||
n: PNode
|
||||
if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
|
||||
inc(c.InstCounter)
|
||||
oldP = c.p # restore later
|
||||
# NOTE: for access of private fields within generics from a different module
|
||||
# and other identifiers we fake the current module temporarily!
|
||||
# XXX bad hack!
|
||||
oldMod = c.module
|
||||
c.module = getModule(fn)
|
||||
result = copySym(fn, false)
|
||||
@@ -105,17 +104,17 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
GenericCacheAdd(c, fn, result)
|
||||
addDecl(c, result)
|
||||
if n.sons[codePos].kind != nkEmpty:
|
||||
c.p = newProcCon(result)
|
||||
pushProcCon(c, result)
|
||||
if result.kind in {skProc, skMethod, skConverter}:
|
||||
addResult(c, result.typ.sons[0], n.info)
|
||||
addResultNode(c, n)
|
||||
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
|
||||
else:
|
||||
popProcCon(c)
|
||||
else:
|
||||
result = oldPrc
|
||||
popInfoContext()
|
||||
closeScope(c.tab) # close scope for parameters
|
||||
popOwner()
|
||||
c.p = oldP # restore
|
||||
c.module = oldMod
|
||||
dec(c.InstCounter)
|
||||
|
||||
|
||||
@@ -638,7 +638,6 @@ proc semLambda(c: PContext, n: PNode): PNode =
|
||||
checkSonsLen(n, codePos + 1)
|
||||
var s = newSym(skProc, getIdent(":anonymous"), getCurrOwner())
|
||||
s.info = n.info
|
||||
var oldP = c.p # restore later
|
||||
s.ast = n
|
||||
n.sons[namePos] = newSymNode(s)
|
||||
pushOwner(s)
|
||||
@@ -658,15 +657,15 @@ proc semLambda(c: PContext, n: PNode): PNode =
|
||||
if n.sons[codePos].kind != nkEmpty:
|
||||
if sfImportc in s.flags:
|
||||
LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
|
||||
c.p = newProcCon(s)
|
||||
pushProcCon(c, s)
|
||||
addResult(c, s.typ.sons[0], n.info)
|
||||
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
|
||||
addResultNode(c, n)
|
||||
popProcCon(c)
|
||||
else:
|
||||
LocalError(n.info, errImplOfXexpected, s.name.s)
|
||||
closeScope(c.tab) # close scope for parameters
|
||||
popOwner()
|
||||
c.p = oldP # restore
|
||||
result.typ = s.typ
|
||||
|
||||
proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
@@ -678,7 +677,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
checkSonsLen(n, codePos + 1)
|
||||
var s = semIdentDef(c, n.sons[0], kind)
|
||||
n.sons[namePos] = newSymNode(s)
|
||||
var oldP = c.p # restore later
|
||||
if sfStar in s.flags: incl(s.flags, sfInInterface)
|
||||
s.ast = n
|
||||
pushOwner(s)
|
||||
@@ -704,7 +702,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
proto = SearchForProc(c, s, c.tab.tos - 2) # -2 because we have a scope open
|
||||
# for parameters
|
||||
if proto == nil:
|
||||
if oldP.owner.kind != skModule:
|
||||
if c.p.owner.kind != skModule:
|
||||
s.typ.callConv = ccClosure
|
||||
else:
|
||||
s.typ.callConv = lastOptionEntry(c).defaultCC
|
||||
@@ -743,13 +741,14 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
if sfBorrow in s.flags:
|
||||
LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
|
||||
if n.sons[genericParamsPos].kind == nkEmpty:
|
||||
c.p = newProcCon(s)
|
||||
pushProcCon(c, s)
|
||||
if (s.typ.sons[0] != nil) and (kind != skIterator):
|
||||
addResult(c, s.typ.sons[0], n.info)
|
||||
if sfImportc notin s.flags:
|
||||
# no semantic checking for importc:
|
||||
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
|
||||
if s.typ.sons[0] != nil and kind != skIterator: addResultNode(c, n)
|
||||
popProcCon(c)
|
||||
else:
|
||||
if s.typ.sons[0] != nil and kind != skIterator:
|
||||
addDecl(c, newSym(skUnknown, getIdent("result"), nil))
|
||||
@@ -764,7 +763,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
sideEffectsCheck(c, s)
|
||||
closeScope(c.tab) # close scope for parameters
|
||||
popOwner()
|
||||
c.p = oldP # restore
|
||||
|
||||
proc semIterator(c: PContext, n: PNode): PNode =
|
||||
result = semProcAux(c, n, skIterator, iteratorPragmas)
|
||||
|
||||
Reference in New Issue
Block a user