diff options
author | Araq <rumpf_a@web.de> | 2015-01-30 01:56:03 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2015-01-30 03:04:45 +0100 |
commit | fe30ec83e22f14ee65f1a5225152e01a3713b2c4 (patch) | |
tree | bce984e85865ec2ddf442ffe8e48d07c13ac2fd6 /compiler | |
parent | a9706dcfa2402c17aefc710e9ac925fcac8873ae (diff) | |
download | Nim-fe30ec83e22f14ee65f1a5225152e01a3713b2c4.tar.gz |
nimsuggest improvements
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgstmts.nim | 1 | ||||
-rw-r--r-- | compiler/evaltempl.nim | 2 | ||||
-rw-r--r-- | compiler/lookups.nim | 15 | ||||
-rw-r--r-- | compiler/nimsuggest/nimsuggest.nim.cfg | 1 | ||||
-rw-r--r-- | compiler/parampatterns.nim | 2 | ||||
-rw-r--r-- | compiler/parser.nim | 5 | ||||
-rw-r--r-- | compiler/pragmas.nim | 4 | ||||
-rw-r--r-- | compiler/sem.nim | 26 | ||||
-rw-r--r-- | compiler/semasgn.nim | 2 | ||||
-rw-r--r-- | compiler/semdata.nim | 3 | ||||
-rw-r--r-- | compiler/semfields.nim | 2 | ||||
-rw-r--r-- | compiler/semgnrc.nim | 52 | ||||
-rw-r--r-- | compiler/semstmts.nim | 5 | ||||
-rw-r--r-- | compiler/semtempl.nim | 10 | ||||
-rw-r--r-- | compiler/semtypes.nim | 3 | ||||
-rw-r--r-- | compiler/suggest.nim | 30 |
16 files changed, 110 insertions, 53 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index d7683f2c3..f0870a5df 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -932,6 +932,7 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): PRope = var j = 0 while x[j] in {' ', '\t'}: inc(j) if x[j] in {'"', ':'}: + # don't modify the line if already in quotes or # some clobber register list: app(result, x); app(result, tnl) elif x[j] != '\0': diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim index 946be68f8..29657a2ae 100644 --- a/compiler/evaltempl.nim +++ b/compiler/evaltempl.nim @@ -93,7 +93,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym): PNode = evalTemplateAux(body, args, ctx, result) if result.len == 1: result = result.sons[0] else: - globalError(result.info, errIllFormedAstX, + localError(result.info, errIllFormedAstX, renderTree(result, {renderNoComments})) else: result = copyNode(body) diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 29be693dd..21d07f280 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -1,7 +1,7 @@ # # # The Nim Compiler -# (c) Copyright 2012 Andreas Rumpf +# (c) Copyright 2015 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -22,7 +22,9 @@ proc considerQuotedIdent*(n: PNode): PIdent = of nkSym: result = n.sym.name of nkAccQuoted: case n.len - of 0: globalError(n.info, errIdentifierExpected, renderTree(n)) + of 0: + localError(n.info, errIdentifierExpected, renderTree(n)) + result = getIdent"<Error>" of 1: result = considerQuotedIdent(n.sons[0]) else: var id = "" @@ -31,12 +33,15 @@ proc considerQuotedIdent*(n: PNode): PIdent = case x.kind of nkIdent: id.add(x.ident.s) of nkSym: id.add(x.sym.name.s) - else: globalError(n.info, errIdentifierExpected, renderTree(n)) + else: + localError(n.info, errIdentifierExpected, renderTree(n)) + return getIdent"<Error>" result = getIdent(id) of nkOpenSymChoice, nkClosedSymChoice: result = n.sons[0].sym.name else: - globalError(n.info, errIdentifierExpected, renderTree(n)) - + localError(n.info, errIdentifierExpected, renderTree(n)) + result = getIdent"<Error>" + template addSym*(scope: PScope, s: PSym) = strTableAdd(scope.symbols, s) diff --git a/compiler/nimsuggest/nimsuggest.nim.cfg b/compiler/nimsuggest/nimsuggest.nim.cfg index d1a1e6b62..062092f16 100644 --- a/compiler/nimsuggest/nimsuggest.nim.cfg +++ b/compiler/nimsuggest/nimsuggest.nim.cfg @@ -9,7 +9,6 @@ path:"$lib/packages/docutils" path:"$nim/compiler" define:useStdoutAsStdmsg -symbol:nimsuggest define:nimsuggest cs:partial diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim index 300abea1e..8db786a25 100644 --- a/compiler/parampatterns.nim +++ b/compiler/parampatterns.nim @@ -41,7 +41,7 @@ type const MaxStackSize* = 64 ## max required stack size by the VM -proc patternError(n: PNode) = +proc patternError(n: PNode) = localError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments})) proc add(code: var TPatternCode, op: TOpcode) {.inline.} = diff --git a/compiler/parser.nim b/compiler/parser.nim index adf3b72a3..aae0ce7f9 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -324,7 +324,10 @@ proc parseSymbol(p: var TParser, allowNil = false): PNode = getTok(p) else: parMessage(p, errIdentifierExpected, p.tok) - getTok(p) # BUGFIX: We must consume a token here to prevent endless loops! + # BUGFIX: We must consume a token here to prevent endless loops! + # But: this really sucks for idetools and keywords, so we don't do it + # if it is a keyword: + if not isKeyword(p.tok.tokType): getTok(p) result = ast.emptyNode proc indexExpr(p: var TParser): PNode = diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 735460906..90f87696b 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -447,7 +447,9 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode = addSon(result, newStrNode(nkStrLit, $marker)) if c < 0: break a = c + 1 - else: illFormedAst(n) + else: + illFormedAstLocal(n) + result = newNode(nkAsmStmt, n.info) proc pragmaEmit(c: PContext, n: PNode) = discard getStrLitNode(c, n) diff --git a/compiler/sem.nim b/compiler/sem.nim index 90037fccd..214f471d6 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -47,6 +47,24 @@ proc finishMethod(c: PContext, s: PSym) proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode +template semIdeForTemplateOrGenericCheck(n, requiresCheck) = + # we check quickly if the node is where the cursor is + when defined(nimsuggest): + if n.info.fileIndex == gTrackPos.fileIndex and n.info.line == gTrackPos.line: + requiresCheck = true + +template semIdeForTemplateOrGeneric(c: PContext; n: PNode; + requiresCheck: bool) = + # use only for idetools support; this is pretty slow so generics and + # templates perform some quick check whether the cursor is actually in + # the generic or template. + when defined(nimsuggest): + assert gCmd == cmdIdeTools + if requiresCheck: + if optIdeDebug in gGlobalOptions: + echo "passing to safeSemExpr: ", renderTree(n) + discard safeSemExpr(c, n) + proc typeMismatch(n: PNode, formal, actual: PType) = if formal.kind != tyError and actual.kind != tyError: localError(n.info, errGenerated, msgKindToString(errTypeMismatch) & @@ -359,13 +377,7 @@ proc semConstBoolExpr(c: PContext, n: PNode): PNode = localError(n.info, errConstExprExpected) result = nn -type - TSemGenericFlag = enum - withinBind, withinTypeDesc, withinMixin - TSemGenericFlags = set[TSemGenericFlag] - -proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags, - ctx: var IntSet): PNode +proc semGenericStmt(c: PContext, n: PNode): PNode include semtypes, semtempl, semgnrc, semstmts, semexprs diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim index 0b68bc897..71ebbbafd 100644 --- a/compiler/semasgn.nim +++ b/compiler/semasgn.nim @@ -101,7 +101,7 @@ proc liftBodyObj(c: TLiftCtx; typ, x, y: PNode) = of nkRecList: for t in items(typ): liftBodyObj(c, t, x, y) else: - illFormedAst(typ) + illFormedAstLocal(typ) proc newAsgnCall(op: PSym; x, y: PNode): PNode = result = newNodeI(nkCall, x.info) diff --git a/compiler/semdata.nim b/compiler/semdata.nim index bb82db292..157761591 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -307,6 +307,9 @@ proc markIndirect*(c: PContext, s: PSym) {.inline.} = proc illFormedAst*(n: PNode) = globalError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments})) +proc illFormedAstLocal*(n: PNode) = + localError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments})) + proc checkSonsLen*(n: PNode, length: int) = if sonsLen(n) != length: illFormedAst(n) diff --git a/compiler/semfields.nim b/compiler/semfields.nim index f02c542ed..823bef225 100644 --- a/compiler/semfields.nim +++ b/compiler/semfields.nim @@ -98,7 +98,7 @@ proc semForObjectFields(c: TFieldsCtx, typ, forLoop, father: PNode) = of nkRecList: for t in items(typ): semForObjectFields(c, t, forLoop, father) else: - illFormedAst(typ) + illFormedAstLocal(typ) proc semForFields(c: PContext, n: PNode, m: TMagic): PNode = # so that 'break' etc. work as expected, we produce diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index d69fdb04a..13941fa58 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -25,10 +25,23 @@ proc getIdentNode(n: PNode): PNode = else: illFormedAst(n) result = n - + +type + GenericCtx = object + toMixin: IntSet + cursorInBody: bool # only for nimsuggest + +type + TSemGenericFlag = enum + withinBind, withinTypeDesc, withinMixin + TSemGenericFlags = set[TSemGenericFlag] + +proc semGenericStmt(c: PContext, n: PNode, + flags: TSemGenericFlags, ctx: var GenericCtx): PNode + proc semGenericStmtScope(c: PContext, n: PNode, flags: TSemGenericFlags, - ctx: var IntSet): PNode = + ctx: var GenericCtx): PNode = openScope(c) result = semGenericStmt(c, n, flags, ctx) closeScope(c) @@ -37,7 +50,8 @@ template macroToExpand(s: expr): expr = s.kind in {skMacro, skTemplate} and (s.typ.len == 1 or sfImmediate in s.flags) proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym, - ctx: var IntSet): PNode = + ctx: var GenericCtx): PNode = + semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody) incl(s.flags, sfUsed) case s.kind of skUnknown: @@ -83,17 +97,17 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym, styleCheckUse(n.info, s) proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags, - ctx: var IntSet): PNode = + ctx: var GenericCtx): PNode = result = n let ident = considerQuotedIdent(n) var s = searchInScopes(c, ident).skipAlias(n) if s == nil: - if ident.id notin ctx and withinMixin notin flags: + if ident.id notin ctx.toMixin and withinMixin notin flags: localError(n.info, errUndeclaredIdentifier, ident.s) else: if withinBind in flags: result = symChoice(c, n, s, scClosed) - elif s.name.id in ctx: + elif s.name.id in ctx.toMixin: result = symChoice(c, n, s, scForceOpen) else: result = semGenericStmtSymbol(c, n, s, ctx) @@ -105,8 +119,10 @@ proc newDot(n, b: PNode): PNode = result.add(b) proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags, - ctx: var IntSet; isMacro: var bool): PNode = + ctx: var GenericCtx; isMacro: var bool): PNode = assert n.kind == nkDotExpr + semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody) + let luf = if withinMixin notin flags: {checkUndeclared} else: {} var s = qualifiedLookUp(c, n, luf) @@ -122,7 +138,7 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags, isMacro = s.kind in {skTemplate, skMacro} if withinBind in flags: result = newDot(result, symChoice(c, n, s, scClosed)) - elif s.name.id in ctx: + elif s.name.id in ctx.toMixin: result = newDot(result, symChoice(c, n, s, scForceOpen)) else: let sym = semGenericStmtSymbol(c, n, s, ctx) @@ -137,9 +153,11 @@ proc addTempDecl(c: PContext; n: PNode; kind: TSymKind) = styleCheckDef(n.info, s, kind) proc semGenericStmt(c: PContext, n: PNode, - flags: TSemGenericFlags, ctx: var IntSet): PNode = + flags: TSemGenericFlags, ctx: var GenericCtx): PNode = result = n - if gCmd == cmdIdeTools: suggestStmt(c, n) + #if gCmd == cmdIdeTools: suggestStmt(c, n) + semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody) + case n.kind of nkIdent, nkAccQuoted: result = lookup(c, n, flags, ctx) @@ -162,14 +180,15 @@ proc semGenericStmt(c: PContext, n: PNode, of nkBind: result = semGenericStmt(c, n.sons[0], flags+{withinBind}, ctx) of nkMixinStmt: - result = semMixinStmt(c, n, ctx) + result = semMixinStmt(c, n, ctx.toMixin) of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkCommand, nkCallStrLit: # check if it is an expression macro: checkMinSonsLen(n, 1) let fn = n.sons[0] var s = qualifiedLookUp(c, fn, {}) if s == nil and withinMixin notin flags and - fn.kind in {nkIdent, nkAccQuoted} and considerQuotedIdent(fn).id notin ctx: + fn.kind in {nkIdent, nkAccQuoted} and + considerQuotedIdent(fn).id notin ctx.toMixin: localError(n.info, errUndeclaredIdentifier, fn.renderTree) var first = 0 @@ -177,7 +196,7 @@ proc semGenericStmt(c: PContext, n: PNode, if s != nil: incl(s.flags, sfUsed) mixinContext = s.magic in {mDefined, mDefinedInScope, mCompiles} - let scOption = if s.name.id in ctx: scForceOpen else: scOpen + let scOption = if s.name.id in ctx.toMixin: scForceOpen else: scOpen case s.kind of skMacro: if macroToExpand(s): @@ -377,4 +396,9 @@ proc semGenericStmt(c: PContext, n: PNode, else: for i in countup(0, sonsLen(n) - 1): result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx) - + +proc semGenericStmt(c: PContext, n: PNode): PNode = + var ctx: GenericCtx + ctx.toMixin = initIntset() + result = semGenericStmt(c, n, {}, ctx) + semIdeForTemplateOrGeneric(c, result, ctx.cursorInBody) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 565d4db06..3fe3e40f0 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1060,8 +1060,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, else: if s.typ.sons[0] != nil and kind notin skIterators: addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info)) - var toBind = initIntSet() - n.sons[bodyPos] = semGenericStmtScope(c, n.sons[bodyPos], {}, toBind) + openScope(c) + n.sons[bodyPos] = semGenericStmt(c, n.sons[bodyPos]) + closeScope(c) fixupInstantiatedSymbols(c, s) if sfImportc in s.flags: # so we just ignore the body after semantic checking for importc: diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index e2c46d3ab..3477d3d6f 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -105,10 +105,11 @@ proc replaceIdentBySym(n: var PNode, s: PNode) = else: illFormedAst(n) type - TemplCtx {.pure, final.} = object + TemplCtx = object c: PContext toBind, toMixin, toInject: IntSet owner: PSym + cursorInBody: bool # only for nimsuggest proc getIdentNode(c: var TemplCtx, n: PNode): PNode = case n.kind @@ -259,8 +260,9 @@ proc semTemplSomeDecl(c: var TemplCtx, n: PNode, symKind: TSymKind; start=0) = addLocalDecl(c, a.sons[j], symKind) proc semPattern(c: PContext, n: PNode): PNode -proc semTemplBody(c: var TemplCtx, n: PNode): PNode = +proc semTemplBody(c: var TemplCtx, n: PNode): PNode = result = n + semIdeForTemplateOrGenericCheck(n, c.cursorInBody) case n.kind of nkIdent: if n.ident.id in c.toInject: return n @@ -416,8 +418,9 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode = for i in countup(0, sonsLen(n) - 1): result.sons[i] = semTemplBody(c, n.sons[i]) -proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode = +proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode = result = n + semIdeForTemplateOrGenericCheck(n, c.cursorInBody) case n.kind of nkIdent: let s = qualifiedLookUp(c.c, n, {}) @@ -524,6 +527,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode = if s.typ.sons[0].kind notin {tyStmt, tyTypeDesc}: n.sons[bodyPos] = transformToExpr(n.sons[bodyPos]) # only parameters are resolved, no type checking is performed + semIdeForTemplateOrGeneric(c, n.sons[bodyPos], ctx.cursorInBody) closeScope(c) popOwner() s.ast = n diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index da892dea8..8d1655593 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1178,8 +1178,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = return errorType(c) result = typeExpr.typ.base if result.isMetaType: - var toBind = initIntSet() - var preprocessed = semGenericStmt(c, n, {}, toBind) + var preprocessed = semGenericStmt(c, n) return makeTypeFromExpr(c, preprocessed) of nkIdent, nkAccQuoted: var s = semTypeIdent(c, n) diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 7f8caca6e..194b1fa06 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -256,19 +256,6 @@ proc findClosestSym(n: PNode): PNode = result = findClosestSym(n.sons[i]) if result != nil: return -proc safeSemExpr(c: PContext, n: PNode): PNode = - try: - result = c.semExpr(c, n) - except ERecoverableError: - result = ast.emptyNode - -proc fuzzySemCheck(c: PContext, n: PNode): PNode = - result = safeSemExpr(c, n) - if result == nil or result.kind == nkEmpty: - result = newNodeI(n.kind, n.info) - if n.kind notin {nkNone..nkNilLit}: - for i in 0 .. < sonsLen(n): result.addSon(fuzzySemCheck(c, n.sons[i])) - var usageSym*: PSym lastLineInfo: TLineInfo @@ -312,6 +299,21 @@ proc useSym*(sym: PSym): PNode = result = newSymNode(sym) markUsed(result.info, sym) +proc safeSemExpr*(c: PContext, n: PNode): PNode = + # use only for idetools support! + try: + result = c.semExpr(c, n) + except ERecoverableError: + result = ast.emptyNode + +proc fuzzySemCheck(c: PContext, n: PNode): PNode = + # use only for idetools support! + result = safeSemExpr(c, n) + if result == nil or result.kind == nkEmpty: + result = newNodeIT(n.kind, n.info, errorType(c)) + if n.kind notin {nkNone..nkNilLit}: + for i in 0 .. < sonsLen(n): result.addSon(fuzzySemCheck(c, n.sons[i])) + proc suggestExpr*(c: PContext, node: PNode) = if nfIsCursor notin node.flags: if gTrackPos.line < 0: return @@ -327,6 +329,8 @@ proc suggestExpr*(c: PContext, node: PNode) = if n == nil: n = node if n.kind == nkDotExpr: var obj = safeSemExpr(c, n.sons[0]) + if optIdeDebug in gGlobalOptions: + echo "expression ", renderTree(obj), " has type ", typeToString(obj.typ) suggestFieldAccess(c, obj, outputs) else: suggestEverything(c, n, outputs) |