summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2015-01-30 01:56:03 +0100
committerAraq <rumpf_a@web.de>2015-01-30 03:04:45 +0100
commitfe30ec83e22f14ee65f1a5225152e01a3713b2c4 (patch)
treebce984e85865ec2ddf442ffe8e48d07c13ac2fd6 /compiler
parenta9706dcfa2402c17aefc710e9ac925fcac8873ae (diff)
downloadNim-fe30ec83e22f14ee65f1a5225152e01a3713b2c4.tar.gz
nimsuggest improvements
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ccgstmts.nim1
-rw-r--r--compiler/evaltempl.nim2
-rw-r--r--compiler/lookups.nim15
-rw-r--r--compiler/nimsuggest/nimsuggest.nim.cfg1
-rw-r--r--compiler/parampatterns.nim2
-rw-r--r--compiler/parser.nim5
-rw-r--r--compiler/pragmas.nim4
-rw-r--r--compiler/sem.nim26
-rw-r--r--compiler/semasgn.nim2
-rw-r--r--compiler/semdata.nim3
-rw-r--r--compiler/semfields.nim2
-rw-r--r--compiler/semgnrc.nim52
-rw-r--r--compiler/semstmts.nim5
-rw-r--r--compiler/semtempl.nim10
-rw-r--r--compiler/semtypes.nim3
-rw-r--r--compiler/suggest.nim30
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)