less cascading errors for 'check' and 'ide-tools'

This commit is contained in:
Araq
2011-04-03 22:18:22 +02:00
parent 94f4256811
commit 623fd8a8ab
4 changed files with 33 additions and 23 deletions

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)