summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-07-30 23:07:19 +0200
committerAraq <rumpf_a@web.de>2012-07-30 23:07:19 +0200
commit674c05f426d586deba1401270f78b74c22c540bc (patch)
tree320432ef06fcfc607ef0e65ab416b84c03803716
parentb0c11d3efbcfc3cd2e8d852ec196930ebace91ad (diff)
downloadNim-674c05f426d586deba1401270f78b74c22c540bc.tar.gz
made compiler more robust for idetools; implemented idetools.usages
-rwxr-xr-xcompiler/commands.nim5
-rwxr-xr-xcompiler/nimsets.nim20
-rwxr-xr-xcompiler/options.nim1
-rwxr-xr-xcompiler/renderer.nim4
-rwxr-xr-xcompiler/semdata.nim8
-rwxr-xr-xcompiler/semexprs.nim22
-rwxr-xr-xcompiler/semstmts.nim10
-rwxr-xr-xcompiler/semtypes.nim9
-rwxr-xr-xcompiler/sigmatch.nim28
-rwxr-xr-xcompiler/suggest.nim33
-rwxr-xr-xdoc/advopt.txt3
11 files changed, 96 insertions, 47 deletions
diff --git a/compiler/commands.nim b/compiler/commands.nim
index db0469e94..b7c64eb4b 100755
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -455,7 +455,10 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
   of "context":
     expectNoArg(switch, arg, pass, info)
     incl(gGlobalOptions, optContext)
-  of "stdout": 
+  of "usages":
+    expectNoArg(switch, arg, pass, info)
+    incl(gGlobalOptions, optUsages)
+  of "stdout":
     expectNoArg(switch, arg, pass, info)
     incl(gGlobalOptions, optStdout)
   else:
diff --git a/compiler/nimsets.nim b/compiler/nimsets.nim
index d475c7b59..282188c64 100755
--- a/compiler/nimsets.nim
+++ b/compiler/nimsets.nim
@@ -31,7 +31,9 @@ proc cardSet*(s: PNode): BiggestInt
 # implementation
 
 proc inSet(s: PNode, elem: PNode): bool = 
-  if s.kind != nkCurly: InternalError(s.info, "inSet")
+  if s.kind != nkCurly: 
+    InternalError(s.info, "inSet")
+    return false
   for i in countup(0, sonsLen(s) - 1): 
     if s.sons[i].kind == nkRange: 
       if leValue(s.sons[i].sons[0], elem) and
@@ -48,17 +50,19 @@ proc overlap(a, b: PNode): bool =
       result = leValue(a.sons[0], b.sons[1]) and
           leValue(b.sons[1], a.sons[1]) or
           leValue(a.sons[0], b.sons[0]) and leValue(b.sons[0], a.sons[1])
-    else: 
+    else:
       result = leValue(a.sons[0], b) and leValue(b, a.sons[1])
-  else: 
-    if b.kind == nkRange: 
+  else:
+    if b.kind == nkRange:
       result = leValue(b.sons[0], a) and leValue(a, b.sons[1])
-    else: 
+    else:
       result = sameValue(a, b)
 
 proc SomeInSet(s: PNode, a, b: PNode): bool = 
   # checks if some element of a..b is in the set s
-  if s.kind != nkCurly: InternalError(s.info, "SomeInSet")
+  if s.kind != nkCurly:
+    InternalError(s.info, "SomeInSet")
+    return false
   for i in countup(0, sonsLen(s) - 1): 
     if s.sons[i].kind == nkRange: 
       if leValue(s.sons[i].sons[0], b) and leValue(b, s.sons[i].sons[1]) or
@@ -164,7 +168,9 @@ proc cardSet(s: PNode): BiggestInt =
       Inc(result)
   
 proc SetHasRange(s: PNode): bool = 
-  if s.kind != nkCurly: InternalError(s.info, "SetHasRange")
+  if s.kind != nkCurly:
+    InternalError(s.info, "SetHasRange")
+    return false
   for i in countup(0, sonsLen(s) - 1): 
     if s.sons[i].kind == nkRange: 
       return true
diff --git a/compiler/options.nim b/compiler/options.nim
index 91f7f778d..de257aa15 100755
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -51,6 +51,7 @@ type                          # please make sure we have under 32 options
     optSuggest,               # ideTools: 'suggest'
     optContext,               # ideTools: 'context'
     optDef,                   # ideTools: 'def'
+    optUsages,                # ideTools: 'usages'
     optThreadAnalysis,        # thread analysis pass
     optTaintMode,             # taint mode turned on
     optTlsEmulation,          # thread var emulation turned on
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 5d8a04198..a1a6de984 100755
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -338,7 +338,9 @@ proc atom(n: PNode): string =
   of nkType: 
     if (n.typ != nil) and (n.typ.sym != nil): result = n.typ.sym.name.s
     else: result = "[type node]"
-  else: InternalError("rnimsyn.atom " & $n.kind)
+  else: 
+    InternalError("rnimsyn.atom " & $n.kind)
+    result = ""
   
 proc lcomma(n: PNode, start: int = 0, theEnd: int = - 1): int = 
   assert(theEnd < 0)
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 26552c294..ebae06ea1 100755
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -146,14 +146,16 @@ proc PushOwner(owner: PSym) =
 
 proc PopOwner() = 
   var length = len(gOwners)
-  if (length <= 0): InternalError("popOwner")
-  setlen(gOwners, length - 1)
+  if length > 0: setlen(gOwners, length - 1)
+  else: InternalError("popOwner")
 
 proc lastOptionEntry(c: PContext): POptionEntry = 
   result = POptionEntry(c.optionStack.tail)
 
 proc pushProcCon*(c: PContext, owner: PSym) {.inline.} = 
-  if owner == nil: InternalError("owner is nil")
+  if owner == nil: 
+    InternalError("owner is nil")
+    return
   var x: PProcCon
   new(x)
   x.owner = owner
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index a82852089..1ed1776ee 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -118,8 +118,10 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
         LocalError(n.info, errIllegalCaptureX, s.name.s)
     result = newSymNode(s, n.info)
   of skGenericParam:
-    if s.ast == nil: InternalError(n.info, "no default for")
-    result = semExpr(c, s.ast)
+    if s.ast != nil: result = semExpr(c, s.ast)
+    else:
+      InternalError(n.info, "no default for")
+      result = emptyNode
   of skType:
     markUsed(n, s)
     result = newSymNode(s, n.info)
@@ -322,14 +324,17 @@ proc changeType(n: PNode, newType: PType) =
   of nkPar: 
     if newType.kind != tyTuple: 
       InternalError(n.info, "changeType: no tuple type for constructor")
-    if newType.n == nil: nil
+    elif newType.n == nil: nil
     elif sonsLen(n) > 0 and n.sons[0].kind == nkExprColonExpr: 
       for i in countup(0, sonsLen(n) - 1): 
         var m = n.sons[i].sons[0]
         if m.kind != nkSym: 
           internalError(m.info, "changeType(): invalid tuple constr")
+          return
         var f = getSymFromList(newType.n, m.sym.name)
-        if f == nil: internalError(m.info, "changeType(): invalid identifier")
+        if f == nil: 
+          internalError(m.info, "changeType(): invalid identifier")
+          return
         changeType(n.sons[i].sons[1], f.typ)
     else:
       for i in countup(0, sonsLen(n) - 1):
@@ -485,7 +490,9 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
       result = newHiddenAddrTaken(c, n)
   of nkDotExpr: 
     checkSonsLen(n, 2)
-    if n.sons[1].kind != nkSym: internalError(n.info, "analyseIfAddressTaken")
+    if n.sons[1].kind != nkSym: 
+      internalError(n.info, "analyseIfAddressTaken")
+      return
     if skipTypes(n.sons[1].sym.typ, abstractInst).kind != tyVar: 
       incl(n.sons[1].sym.flags, sfAddrTaken)
       result = newHiddenAddrTaken(c, n)
@@ -590,6 +597,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
   if result != nil:
     if result.sons[0].kind != nkSym: 
       InternalError("semDirectCallAnalyseEffects")
+      return
     let callee = result.sons[0].sym
     case callee.kind
     of skMacro, skTemplate: nil
@@ -1225,8 +1233,8 @@ proc semIfExpr(c: PContext, n: PNode): PNode =
     of nkElseExpr: 
       checkSonsLen(it, 1)
       it.sons[0] = semExprWithType(c, it.sons[0])
-      if typ == nil: InternalError(it.info, "semIfExpr")
-      it.sons[0] = fitNode(c, typ, it.sons[0])
+      if typ != nil: it.sons[0] = fitNode(c, typ, it.sons[0])
+      else: InternalError(it.info, "semIfExpr")
     else: illFormedAst(n)
   result.typ = typ
 
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 33d0d4f5c..c82e7d8de 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -29,7 +29,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
       checkSonsLen(it, 2)
       var e = semConstExpr(c, it.sons[0])
       if e.kind != nkIntLit: InternalError(n.info, "semWhen")
-      if e.intVal != 0 and result == nil:
+      elif e.intVal != 0 and result == nil:
         setResult(it.sons[1]) 
     of nkElse, nkElseExpr:
       checkSonsLen(it, 1)
@@ -514,8 +514,8 @@ proc addGenericParamListToScope(c: PContext, n: PNode) =
     InternalError(n.info, "addGenericParamListToScope")
   for i in countup(0, sonsLen(n)-1): 
     var a = n.sons[i]
-    if a.kind != nkSym: internalError(a.info, "addGenericParamListToScope")
-    addDecl(c, a.sym)
+    if a.kind == nkSym: addDecl(c, a.sym)
+    else: internalError(a.info, "addGenericParamListToScope")
 
 proc typeSectionLeftSidePass(c: PContext, n: PNode) = 
   # process the symbols on the left side for the whole type section, before
@@ -628,8 +628,8 @@ proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) =
 
 proc addParams(c: PContext, n: PNode, kind: TSymKind) = 
   for i in countup(1, sonsLen(n)-1): 
-    if (n.sons[i].kind != nkSym): InternalError(n.info, "addParams")
-    addParamOrResult(c, n.sons[i].sym, kind)
+    if n.sons[i].kind == nkSym: addParamOrResult(c, n.sons[i].sym, kind)
+    else: InternalError(n.info, "addParams")
 
 proc semBorrow(c: PContext, n: PNode, s: PSym) = 
   # search for the correct alias:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 3a3b0d722..a0e2283a3 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -367,7 +367,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
   checkMinSonsLen(n, 2)
   semRecordNodeAux(c, n.sons[0], check, pos, a, rectype)
   if a.sons[0].kind != nkSym: 
-    internalError("semRecordCase: dicriminant is no symbol")
+    internalError("semRecordCase: discriminant is no symbol")
     return
   incl(a.sons[0].sym.flags, sfDiscriminant)
   var covered: biggestInt = 0
@@ -412,7 +412,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
         if c.InGenericContext == 0:
           var e = semConstBoolExpr(c, it.sons[0])
           if e.kind != nkIntLit: InternalError(e.info, "semRecordNodeAux")
-          if e.intVal != 0 and branch == nil: branch = it.sons[1]
+          elif e.intVal != 0 and branch == nil: branch = it.sons[1]
         else:
           it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
       of nkElse:
@@ -735,6 +735,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
     isConcrete = false
   elif s.typ.containerID == 0: 
     InternalError(n.info, "semtypes.semGeneric")
+    return errorType(c)
   elif sonsLen(n) != sonsLen(s.typ): 
     LocalError(n.info, errWrongNumberOfArguments)
     return errorType(c)
@@ -930,7 +931,9 @@ proc semGenericConstraints(c: PContext, n: PNode, result: PType) =
 
 proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = 
   result = copyNode(n)
-  if n.kind != nkGenericParams: InternalError(n.info, "semGenericParamList")
+  if n.kind != nkGenericParams: 
+    InternalError(n.info, "semGenericParamList")
+    return
   for i in countup(0, sonsLen(n)-1): 
     var a = n.sons[i]
     if a.kind != nkIdentDefs: illFormedAst(n)
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 8ae6250d5..ba0cba749 100755
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -228,24 +228,25 @@ proc minRel(a, b: TTypeRelation): TTypeRelation =
   if a <= b: result = a
   else: result = b
   
-proc tupleRel(c: var TCandidate, f, a: PType): TTypeRelation = 
+proc tupleRel(c: var TCandidate, f, a: PType): TTypeRelation =
   result = isNone
   if sameType(f, a):
     result = isEqual
-  elif sonsLen(a) == sonsLen(f): 
+  elif sonsLen(a) == sonsLen(f):
     result = isEqual
-    for i in countup(0, sonsLen(f) - 1): 
+    for i in countup(0, sonsLen(f) - 1):
       var m = typeRel(c, f.sons[i], a.sons[i])
       if m < isSubtype: return isNone
       result = minRel(result, m)
-    if f.n != nil and a.n != nil: 
-      for i in countup(0, sonsLen(f.n) - 1): 
+    if f.n != nil and a.n != nil:
+      for i in countup(0, sonsLen(f.n) - 1):
         # check field names:
         if f.n.sons[i].kind != nkSym: InternalError(f.n.info, "tupleRel")
-        if a.n.sons[i].kind != nkSym: InternalError(a.n.info, "tupleRel")
-        var x = f.n.sons[i].sym
-        var y = a.n.sons[i].sym
-        if x.name.id != y.name.id: return isNone
+        elif a.n.sons[i].kind != nkSym: InternalError(a.n.info, "tupleRel")
+        else:
+          var x = f.n.sons[i].sym
+          var y = a.n.sons[i].sym
+          if x.name.id != y.name.id: return isNone
 
 proc matchTypeClass(c: var TCandidate, f, a: PType): TTypeRelation =
   for i in countup(0, f.sonsLen - 1):
@@ -501,7 +502,7 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
       for i in countup(1, sonsLen(f) - 1): 
         if a.sons[i].kind == tyGenericParam: 
           InternalError("wrong instantiated type!")
-        if typeRel(c, f.sons[i], a.sons[i]) <= isSubtype: return 
+        elif typeRel(c, f.sons[i], a.sons[i]) <= isSubtype: return 
       result = isGeneric
     else:
       result = typeRel(c, f.sons[0], a)
@@ -539,7 +540,7 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
       result = isNone
   of tyExpr, tyStmt:
     result = isGeneric
-  else: internalError("typeRel(" & $f.kind & ')')
+  else: internalError("typeRel: " & $f.kind)
   
 proc cmpTypes*(f, a: PType): TTypeRelation = 
   var c: TCandidate
@@ -551,7 +552,9 @@ proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
   result = PType(idTableGet(m.bindings, f))
   if result == nil: 
     result = generateTypeInstance(c, m.bindings, arg, f)
-  if result == nil: InternalError(arg.info, "getInstantiatedType")
+  if result == nil:
+    InternalError(arg.info, "getInstantiatedType")
+    result = errorType(c)
   
 proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate, 
                   c: PContext): PNode = 
@@ -794,6 +797,7 @@ proc matchesAux*(c: PContext, n, nOrig: PNode,
       else: 
         if m.callee.n.sons[f].kind != nkSym: 
           InternalError(n.sons[a].info, "matches")
+          return
         formal = m.callee.n.sons[f].sym
         if ContainsOrIncl(marker, formal.position): 
           # already in namedParams:
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index ea7d17d16..240316cec 100755
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -19,7 +19,7 @@ const
   sectionDef = "def"
   sectionContext = "con"
 
-proc SymToStr(s: PSym, isLocal: bool, section: string): string = 
+proc SymToStr(s: PSym, isLocal: bool, section: string, li: TLineInfo): string = 
   result = section
   result.add(sep)
   result.add($s.kind)
@@ -33,11 +33,14 @@ proc SymToStr(s: PSym, isLocal: bool, section: string): string =
   if s.typ != nil: 
     result.add(typeToString(s.typ))
   result.add(sep)
-  result.add(toFilename(s.info))
+  result.add(toFilename(li))
   result.add(sep)
-  result.add($ToLinenumber(s.info))
+  result.add($ToLinenumber(li))
   result.add(sep)
-  result.add($ToColumn(s.info))
+  result.add($ToColumn(li))
+
+proc SymToStr(s: PSym, isLocal: bool, section: string): string = 
+  result = SymToStr(s, isLocal, section, s.info)
 
 proc filterSym(s: PSym): bool {.inline.} = 
   result = s.name.s[0] in lexer.SymChars
@@ -196,6 +199,9 @@ proc fuzzySemCheck(c: PContext, n: PNode): PNode =
     if n.kind notin {nkNone..nkNilLit}:
       for i in 0 .. < sonsLen(n): result.addSon(fuzzySemCheck(c, n.sons[i]))
 
+var
+  usageSym: PSym
+
 proc suggestExpr*(c: PContext, node: PNode) = 
   var cp = msgs.inCheckpoint(node.info)
   if cp == cpNone: return
@@ -233,13 +239,26 @@ proc suggestExpr*(c: PContext, node: PNode) =
       suggestCall(c, a, n, outputs)
   
   if optDef in gGlobalOptions:
-    var n = findClosestSym(fuzzySemCheck(c, node))
-    if n != nil: 
+    let n = findClosestSym(fuzzySemCheck(c, node))
+    if n != nil:
       OutWriteln(SymToStr(n.sym, isLocal=false, sectionDef))
       inc outputs
       
+  if optUsages in gGlobalOptions:
+    if usageSym == nil:
+      let n = findClosestSym(fuzzySemCheck(c, node))
+      if n != nil: 
+        usageSym = n.sym
+        OutWriteln(SymToStr(n.sym, isLocal=false, sectionDef))
+        inc outputs
+    else:
+      let n = node
+      if n.kind == nkSym and n.sym == usageSym:
+        OutWriteln(SymToStr(n.sym, isLocal=false, sectionDef, n.info))
+        inc outputs
+    
   dec(c.InCompilesContext)
-  if outputs > 0: quit(0)
+  if outputs > 0 and optUsages notin gGlobalOptions: quit(0)
 
 proc suggestStmt*(c: PContext, n: PNode) = 
   suggestExpr(c, n)
diff --git a/doc/advopt.txt b/doc/advopt.txt
index 5077de4db..9a642addb 100755
--- a/doc/advopt.txt
+++ b/doc/advopt.txt
@@ -13,8 +13,9 @@ Advanced commands:
   //idetools                compiler support for IDEs: possible options:
     --track:FILE,LINE,COL   track a file/cursor position
     --suggest               suggest all possible symbols at position
-    --def                   list all possible symbols at position
+    --def                   list all possible definitions at position
     --context               list possible invokation context
+    --usages                list all usages of the symbol at position
 
 Advanced options:
   -m, --mainmodule:FILE     set the project main module