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

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

View file

@ -29,9 +29,7 @@ proc considerAcc(n: PNode): PIdent =
result = nil result = nil
proc isTopLevel(c: PContext): bool {.inline.} = proc isTopLevel(c: PContext): bool {.inline.} =
# if we encountered an error, we treat as top-level so that result = c.tab.tos <= 2
# cascading errors are not that strange:
result = c.tab.tos <= 2 or msgs.gErrorCounter > 0
proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
result = newSym(kind, considerAcc(n), getCurrOwner()) 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") if (c.p != nil): InternalError(module.info, "sem.myOpen")
c.semConstExpr = semConstExpr c.semConstExpr = semConstExpr
c.semExpr = semExprNoFlags c.semExpr = semExprNoFlags
c.p = newProcCon(module) pushProcCon(c, module)
pushOwner(c.module) pushOwner(c.module)
openScope(c.tab) # scope for imported symbols openScope(c.tab) # scope for imported symbols
SymTabAdd(c.tab, module) # a module knows itself 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 openScope(c.tab) # scope for the module's symbols
result = c 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)) var c = PContext(myOpen(module, filename))
c.fromCache = true c.fromCache = true
result = c result = c
@ -195,6 +194,14 @@ proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
if result.kind != nkEmpty: addSon(a, result) if result.kind != nkEmpty: addSon(a, result)
result = a 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 = proc myProcess(context: PPassContext, n: PNode): PNode =
var c = PContext(context) var c = PContext(context)
# 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:
@ -204,6 +211,7 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
try: try:
result = SemStmtAndGenerateGenerics(c, n) result = SemStmtAndGenerateGenerics(c, n)
except ERecoverableError: except ERecoverableError:
RecoverContext(c)
result = ast.emptyNode result = ast.emptyNode
proc myClose(context: PPassContext, n: PNode): PNode = 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; InternalError(n.info, "n is not nil") #result := n;
addCodeForGenerics(c, result) addCodeForGenerics(c, result)
popOwner() popOwner()
c.p = nil popProcCon(c)
proc semPass(): TPass = proc semPass(): TPass =
initPass(result) initPass(result)

View file

@ -23,14 +23,15 @@ type
Notes*: TNoteKinds Notes*: TNoteKinds
POptionEntry* = ref TOptionEntry POptionEntry* = ref TOptionEntry
PProcCon* = ref TProcCon
TProcCon*{.final.} = object # procedure context; also used for top-level TProcCon*{.final.} = object # procedure context; also used for top-level
# statements # statements
owner*: PSym # the symbol this context belongs to owner*: PSym # the symbol this context belongs to
resultSym*: PSym # the result symbol (if we are in a proc) resultSym*: PSym # the result symbol (if we are in a proc)
nestedLoopCounter*: int # whether we are in a loop or not nestedLoopCounter*: int # whether we are in a loop or not
nestedBlockCounter*: int # whether we are in a block 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 PContext* = ref TContext
TContext* = object of TPassContext # a context represents a module TContext* = object of TPassContext # a context represents a module
module*: PSym # the module sym belonging to the context 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 newContext*(module: PSym, nimfile: string): PContext
proc newProcCon*(owner: PSym): PProcCon
proc lastOptionEntry*(c: PContext): POptionEntry proc lastOptionEntry*(c: PContext): POptionEntry
proc newOptionEntry*(): POptionEntry proc newOptionEntry*(): POptionEntry
proc addConverter*(c: PContext, conv: PSym) proc addConverter*(c: PContext, conv: PSym)
@ -97,10 +97,15 @@ proc PopOwner() =
proc lastOptionEntry(c: PContext): POptionEntry = proc lastOptionEntry(c: PContext): POptionEntry =
result = POptionEntry(c.optionStack.tail) result = POptionEntry(c.optionStack.tail)
proc newProcCon(owner: PSym): PProcCon = proc pushProcCon*(c: PContext, owner: PSym) {.inline.} =
if owner == nil: InternalError("owner is nil") if owner == nil: InternalError("owner is nil")
new(result) var x: PProcCon
result.owner = owner 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 = proc newOptionEntry(): POptionEntry =
new(result) new(result)

View file

@ -68,13 +68,12 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
# generates an instantiated proc # generates an instantiated proc
var var
oldPrc, oldMod: PSym oldPrc, oldMod: PSym
oldP: PProcCon
n: PNode n: PNode
if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep") if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
inc(c.InstCounter) inc(c.InstCounter)
oldP = c.p # restore later
# NOTE: for access of private fields within generics from a different module # NOTE: for access of private fields within generics from a different module
# and other identifiers we fake the current module temporarily! # and other identifiers we fake the current module temporarily!
# XXX bad hack!
oldMod = c.module oldMod = c.module
c.module = getModule(fn) c.module = getModule(fn)
result = copySym(fn, false) result = copySym(fn, false)
@ -105,17 +104,17 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
GenericCacheAdd(c, fn, result) GenericCacheAdd(c, fn, result)
addDecl(c, result) addDecl(c, result)
if n.sons[codePos].kind != nkEmpty: if n.sons[codePos].kind != nkEmpty:
c.p = newProcCon(result) pushProcCon(c, result)
if result.kind in {skProc, skMethod, skConverter}: if result.kind in {skProc, skMethod, skConverter}:
addResult(c, result.typ.sons[0], n.info) addResult(c, result.typ.sons[0], n.info)
addResultNode(c, n) addResultNode(c, n)
n.sons[codePos] = semStmtScope(c, n.sons[codePos]) n.sons[codePos] = semStmtScope(c, n.sons[codePos])
popProcCon(c)
else: else:
result = oldPrc result = oldPrc
popInfoContext() popInfoContext()
closeScope(c.tab) # close scope for parameters closeScope(c.tab) # close scope for parameters
popOwner() popOwner()
c.p = oldP # restore
c.module = oldMod c.module = oldMod
dec(c.InstCounter) dec(c.InstCounter)

View file

@ -638,7 +638,6 @@ proc semLambda(c: PContext, n: PNode): PNode =
checkSonsLen(n, codePos + 1) checkSonsLen(n, codePos + 1)
var s = newSym(skProc, getIdent(":anonymous"), getCurrOwner()) var s = newSym(skProc, getIdent(":anonymous"), getCurrOwner())
s.info = n.info s.info = n.info
var oldP = c.p # restore later
s.ast = n s.ast = n
n.sons[namePos] = newSymNode(s) n.sons[namePos] = newSymNode(s)
pushOwner(s) pushOwner(s)
@ -658,15 +657,15 @@ proc semLambda(c: PContext, n: PNode): PNode =
if n.sons[codePos].kind != nkEmpty: if n.sons[codePos].kind != nkEmpty:
if sfImportc in s.flags: if sfImportc in s.flags:
LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s) LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
c.p = newProcCon(s) pushProcCon(c, s)
addResult(c, s.typ.sons[0], n.info) addResult(c, s.typ.sons[0], n.info)
n.sons[codePos] = semStmtScope(c, n.sons[codePos]) n.sons[codePos] = semStmtScope(c, n.sons[codePos])
addResultNode(c, n) addResultNode(c, n)
popProcCon(c)
else: else:
LocalError(n.info, errImplOfXexpected, s.name.s) LocalError(n.info, errImplOfXexpected, s.name.s)
closeScope(c.tab) # close scope for parameters closeScope(c.tab) # close scope for parameters
popOwner() popOwner()
c.p = oldP # restore
result.typ = s.typ result.typ = s.typ
proc semProcAux(c: PContext, n: PNode, kind: TSymKind, proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
@ -678,7 +677,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
checkSonsLen(n, codePos + 1) checkSonsLen(n, codePos + 1)
var s = semIdentDef(c, n.sons[0], kind) var s = semIdentDef(c, n.sons[0], kind)
n.sons[namePos] = newSymNode(s) n.sons[namePos] = newSymNode(s)
var oldP = c.p # restore later
if sfStar in s.flags: incl(s.flags, sfInInterface) if sfStar in s.flags: incl(s.flags, sfInInterface)
s.ast = n s.ast = n
pushOwner(s) 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 proto = SearchForProc(c, s, c.tab.tos - 2) # -2 because we have a scope open
# for parameters # for parameters
if proto == nil: if proto == nil:
if oldP.owner.kind != skModule: if c.p.owner.kind != skModule:
s.typ.callConv = ccClosure s.typ.callConv = ccClosure
else: else:
s.typ.callConv = lastOptionEntry(c).defaultCC s.typ.callConv = lastOptionEntry(c).defaultCC
@ -743,13 +741,14 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if sfBorrow in s.flags: if sfBorrow in s.flags:
LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s) LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
if n.sons[genericParamsPos].kind == nkEmpty: if n.sons[genericParamsPos].kind == nkEmpty:
c.p = newProcCon(s) pushProcCon(c, s)
if (s.typ.sons[0] != nil) and (kind != skIterator): if (s.typ.sons[0] != nil) and (kind != skIterator):
addResult(c, s.typ.sons[0], n.info) addResult(c, s.typ.sons[0], n.info)
if sfImportc notin s.flags: if sfImportc notin s.flags:
# no semantic checking for importc: # no semantic checking for importc:
n.sons[codePos] = semStmtScope(c, n.sons[codePos]) n.sons[codePos] = semStmtScope(c, n.sons[codePos])
if s.typ.sons[0] != nil and kind != skIterator: addResultNode(c, n) if s.typ.sons[0] != nil and kind != skIterator: addResultNode(c, n)
popProcCon(c)
else: else:
if s.typ.sons[0] != nil and kind != skIterator: if s.typ.sons[0] != nil and kind != skIterator:
addDecl(c, newSym(skUnknown, getIdent("result"), nil)) addDecl(c, newSym(skUnknown, getIdent("result"), nil))
@ -764,7 +763,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
sideEffectsCheck(c, s) sideEffectsCheck(c, s)
closeScope(c.tab) # close scope for parameters closeScope(c.tab) # close scope for parameters
popOwner() popOwner()
c.p = oldP # restore
proc semIterator(c: PContext, n: PNode): PNode = proc semIterator(c: PContext, n: PNode): PNode =
result = semProcAux(c, n, skIterator, iteratorPragmas) result = semProcAux(c, n, skIterator, iteratorPragmas)