diff options
author | Araq <rumpf_a@web.de> | 2012-07-29 02:45:50 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-07-29 02:45:50 +0200 |
commit | 087b8621d32b65dde4a39952c0a53bbf5cc57414 (patch) | |
tree | 6833af36f7e394ba80ffcbac5cb41f6e898da77a | |
parent | 48e95fe9f9ce1a412e7fddc8293a2b1db7f46bbd (diff) | |
download | Nim-087b8621d32b65dde4a39952c0a53bbf5cc57414.tar.gz |
improvements for idetools; system.compiles improved
-rwxr-xr-x | compiler/lookups.nim | 7 | ||||
-rwxr-xr-x | compiler/msgs.nim | 3 | ||||
-rwxr-xr-x | compiler/sem.nim | 3 | ||||
-rwxr-xr-x | compiler/semdata.nim | 32 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 14 | ||||
-rwxr-xr-x | compiler/suggest.nim | 73 | ||||
-rwxr-xr-x | todo.txt | 1 |
7 files changed, 101 insertions, 32 deletions
diff --git a/compiler/lookups.nim b/compiler/lookups.nim index b26ac808e..0ad1c7f01 100755 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -58,9 +58,14 @@ proc CloseScope*(tab: var TSymTab) = if tab.tos > len(tab.stack): InternalError("CloseScope") var it: TTabIter var s = InitTabIter(it, tab.stack[tab.tos-1]) + var missingImpls = 0 while s != nil: if sfForward in s.flags: - LocalError(s.info, errImplOfXexpected, getSymRepr(s)) + # too many 'implementation of X' errors are annoying + # and slow 'suggest' down: + if missingImpls == 0: + LocalError(s.info, errImplOfXexpected, getSymRepr(s)) + inc missingImpls elif {sfUsed, sfExported} * s.flags == {} and optHints in s.options: # BUGFIX: check options in s! if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam}: diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 034fd38d8..edcb66274 100755 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -483,6 +483,9 @@ proc UnknownLineInfo*(): TLineInfo = var msgContext: seq[TLineInfo] = @[] +proc getInfoContextLen*(): int = return msgContext.len +proc setInfoContextLen*(L: int) = setLen(msgContext, L) + proc pushInfoContext*(info: TLineInfo) = msgContext.add(info) diff --git a/compiler/sem.nim b/compiler/sem.nim index 63e401108..904adf955 100755 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -198,11 +198,14 @@ proc myProcess(context: PPassContext, n: PNode): PNode = if msgs.gErrorMax <= 1: result = SemStmtAndGenerateGenerics(c, n) else: + let oldContextLen = msgs.getInfoContextLen() try: result = SemStmtAndGenerateGenerics(c, n) except ERecoverableError: RecoverContext(c) result = ast.emptyNode + msgs.setInfoContextLen(oldContextLen) + if gCmd == cmdIdeTools: findSuggest(c, n) proc checkThreads(c: PContext) = if not needsGlobalAnalysis(): return diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 76ceafecf..fb5b8075a 100755 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -78,11 +78,41 @@ type var gGenericsCache: PGenericsCache # save for modularity -proc newGenericsCache: PGenericsCache = +proc newGenericsCache*(): PGenericsCache = new(result) initIdTable(result.InstTypes) result.generics = @[] +proc tempContext*(c: PContext): PContext = + ## generates a temporary context so that side-effects can be rolled-back; + ## necessary for ``system.compiles``. + new(result) + result.module = c.module + result.p = c.p + # don't use the old cache: + result.generics = newGenericsCache() + result.friendModule = c.friendModule + result.InstCounter = c.InstCounter + result.threadEntries = @[] + # hrm, 'tab' is expensive to copy ... so we don't. We open a new scope + # instead to be able to undo scope changes. Not entirely correct for + # explicit 'global' vars though: + #shallowCopy(result.tab, c.tab) + assign(result.AmbiguousSymbols, c.AmbiguousSymbols) + result.InGenericContext = c.InGenericContext + result.InUnrolledContext = c.InUnrolledContext + result.InCompilesContext = c.InCompilesContext + result.converters = c.converters + result.semConstExpr = c.semConstExpr + result.semExpr = c.semExpr + result.semConstBoolExpr = c.semConstBoolExpr + assign(result.includedFiles, c.includedFiles) + result.filename = c.filename + #shallowCopy(result.userPragmas, c.userPragmas) + # XXX mark it as read-only: + result.evalContext = c.evalContext + + proc newContext*(module: PSym, nimfile: string): PContext proc lastOptionEntry*(c: PContext): POptionEntry diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 0b07d84a9..fa39251e7 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1136,14 +1136,28 @@ proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode = # do not halt after first error: msgs.gErrorMax = high(int) + # open a scope for temporary symbol inclusions: + openScope(c.tab) let oldTos = c.tab.tos let oldOwnerLen = len(gOwners) + let oldGenerics = c.generics + let oldContextLen = msgs.getInfoContextLen() + + let oldInGenericContext = c.InGenericContext + let oldInUnrolledContext = c.InUnrolledContext + + c.generics = newGenericsCache() try: discard semExpr(c, n.sons[1]) result.intVal = ord(msgs.gErrorCounter == oldErrorCount) except ERecoverableError: nil # undo symbol table changes (as far as it's possible): + closeScope(c.tab) + c.generics = oldGenerics + c.InGenericContext = oldInGenericContext + c.InUnrolledContext = oldInUnrolledContext + msgs.setInfoContextLen(oldContextLen) setlen(gOwners, oldOwnerLen) while c.tab.tos > oldTos: rawCloseScope(c.tab) dec c.InCompilesContext diff --git a/compiler/suggest.nim b/compiler/suggest.nim index ff1f9607f..e107730b8 100755 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -42,31 +42,33 @@ proc SymToStr(s: PSym, isLocal: bool, section: string): string = proc filterSym(s: PSym): bool {.inline.} = result = s.name.s[0] in lexer.SymChars -proc suggestField(s: PSym) = +proc suggestField(s: PSym, outputs: var int) = if filterSym(s): OutWriteln(SymToStr(s, isLocal=true, sectionSuggest)) + inc outputs template wholeSymTab(cond, section: expr) {.immediate.} = for i in countdown(c.tab.tos-1, 0): for it in items(c.tab.stack[i]): if cond: OutWriteln(SymToStr(it, isLocal = i > ModuleTablePos, section)) + inc outputs -proc suggestSymList(list: PNode) = +proc suggestSymList(list: PNode, outputs: var int) = for i in countup(0, sonsLen(list) - 1): if list.sons[i].kind != nkSym: InternalError(list.info, "getSymFromList") - suggestField(list.sons[i].sym) + suggestField(list.sons[i].sym, outputs) -proc suggestObject(n: PNode) = +proc suggestObject(n: PNode, outputs: var int) = case n.kind of nkRecList: - for i in countup(0, sonsLen(n)-1): suggestObject(n.sons[i]) + for i in countup(0, sonsLen(n)-1): suggestObject(n.sons[i], outputs) of nkRecCase: var L = sonsLen(n) if L > 0: - suggestObject(n.sons[0]) - for i in countup(1, L-1): suggestObject(lastSon(n.sons[i])) - of nkSym: suggestField(n.sym) + suggestObject(n.sons[0], outputs) + for i in countup(1, L-1): suggestObject(lastSon(n.sons[i]), outputs) + of nkSym: suggestField(n.sym, outputs) else: nil proc nameFits(c: PContext, s: PSym, n: PNode): bool = @@ -89,7 +91,7 @@ proc argsFit(c: PContext, candidate: PSym, n, nOrig: PNode): bool = else: result = false -proc suggestCall(c: PContext, n, nOrig: PNode) = +proc suggestCall(c: PContext, n, nOrig: PNode, outputs: var int) = wholeSymTab(filterSym(it) and nameFits(c, it, n) and argsFit(c, it, n, nOrig), sectionContext) @@ -97,18 +99,19 @@ proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} = if s.typ != nil and sonsLen(s.typ) > 1 and s.typ.sons[1] != nil: result = sigmatch.argtypeMatches(c, s.typ.sons[1], firstArg) -proc suggestOperations(c: PContext, n: PNode, typ: PType) = +proc suggestOperations(c: PContext, n: PNode, typ: PType, outputs: var int) = assert typ != nil wholeSymTab(filterSym(it) and typeFits(c, it, typ), sectionSuggest) -proc suggestEverything(c: PContext, n: PNode) = +proc suggestEverything(c: PContext, n: PNode, outputs: var int) = # do not produce too many symbols: for i in countdown(c.tab.tos-1, 1): for it in items(c.tab.stack[i]): if filterSym(it): OutWriteln(SymToStr(it, isLocal = i > ModuleTablePos, sectionSuggest)) + inc outputs -proc suggestFieldAccess(c: PContext, n: PNode) = +proc suggestFieldAccess(c: PContext, n: PNode, outputs: var int) = # special code that deals with ``myObj.``. `n` is NOT the nkDotExpr-node, but # ``myObj``. var typ = n.Typ @@ -120,34 +123,36 @@ proc suggestFieldAccess(c: PContext, n: PNode) = for it in items(c.tab.stack[ModuleTablePos]): if filterSym(it): OutWriteln(SymToStr(it, isLocal=false, sectionSuggest)) + inc outputs else: for it in items(n.sym.tab): if filterSym(it): OutWriteln(SymToStr(it, isLocal=false, sectionSuggest)) + inc outputs else: # fallback: - suggestEverything(c, n) + suggestEverything(c, n, outputs) elif typ.kind == tyEnum and n.kind == nkSym and n.sym.kind == skType: # look up if the identifier belongs to the enum: var t = typ while t != nil: - suggestSymList(t.n) + suggestSymList(t.n, outputs) t = t.sons[0] - suggestOperations(c, n, typ) + suggestOperations(c, n, typ, outputs) else: typ = skipTypes(typ, {tyGenericInst, tyVar, tyPtr, tyRef}) if typ.kind == tyObject: var t = typ while true: - suggestObject(t.n) + suggestObject(t.n, outputs) if t.sons[0] == nil: break t = skipTypes(t.sons[0], {tyGenericInst}) - suggestOperations(c, n, typ) + suggestOperations(c, n, typ, outputs) elif typ.kind == tyTuple and typ.n != nil: - suggestSymList(typ.n) - suggestOperations(c, n, typ) + suggestSymList(typ.n, outputs) + suggestOperations(c, n, typ, outputs) else: - suggestOperations(c, n, typ) + suggestOperations(c, n, typ, outputs) proc findClosestDot(n: PNode): PNode = if n.kind == nkDotExpr and msgs.inCheckpoint(n.info) == cpExact: @@ -177,8 +182,6 @@ proc findClosestSym(n: PNode): PNode = result = findClosestSym(n.sons[i]) if result != nil: return -var recursiveCheck = 0 - proc safeSemExpr(c: PContext, n: PNode): PNode = try: result = c.semExpr(c, n) @@ -195,9 +198,10 @@ proc fuzzySemCheck(c: PContext, n: PNode): PNode = proc suggestExpr*(c: PContext, node: PNode) = var cp = msgs.inCheckpoint(node.info) if cp == cpNone: return - # HACK: This keeps semExpr() from coming here recursively: - if recursiveCheck > 0: return - inc(recursiveCheck) + var outputs = 0 + # This keeps semExpr() from coming here recursively: + if c.InCompilesContext > 0: return + inc(c.InCompilesContext) if optSuggest in gGlobalOptions: var n = findClosestDot(node) @@ -206,9 +210,9 @@ proc suggestExpr*(c: PContext, node: PNode) = if n.kind == nkDotExpr and cp == cpExact: var obj = safeSemExpr(c, n.sons[0]) - suggestFieldAccess(c, obj) + suggestFieldAccess(c, obj, outputs) else: - suggestEverything(c, n) + suggestEverything(c, n, outputs) if optContext in gGlobalOptions: var n = findClosestCall(node) @@ -225,13 +229,22 @@ proc suggestExpr*(c: PContext, node: PNode) = var x = safeSemExpr(c, n.sons[i]) if x.kind == nkEmpty or x.typ == nil: break addSon(a, x) - suggestCall(c, a, n) + suggestCall(c, a, n, outputs) if optDef in gGlobalOptions: var n = findClosestSym(fuzzySemCheck(c, node)) - if n != nil: OutWriteln(SymToStr(n.sym, isLocal=false, sectionDef)) - quit(0) + if n != nil: + OutWriteln(SymToStr(n.sym, isLocal=false, sectionDef)) + inc outputs + + dec(c.InCompilesContext) + if outputs > 0: quit(0) proc suggestStmt*(c: PContext, n: PNode) = suggestExpr(c, n) +proc findSuggest*(c: PContext, n: PNode) = + if n == nil: return + suggestExpr(c, n) + for i in 0.. <safeLen(n): + findSuggest(c, n.sons[i]) diff --git a/todo.txt b/todo.txt index 2668945fa..ac81d8250 100755 --- a/todo.txt +++ b/todo.txt @@ -23,6 +23,7 @@ version 0.9.0 Bugs ---- +- bug: strange shallowCopy(result.tab, c.tab) - bug: pragma statements in combination with symbol files are evaluated twice but this can lead to compilation errors - bug: the parser is not strict enough with newlines: 'echo "a" echo "b"' |