summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xrod/msgs.nim23
-rwxr-xr-xrod/sem.nim6
-rwxr-xr-xrod/semexprs.nim2
-rwxr-xr-xrod/seminst.nim6
-rwxr-xr-xrod/sigmatch.nim29
-rw-r--r--rod/suggest.nim76
-rwxr-xr-xtodo.txt3
7 files changed, 105 insertions, 40 deletions
diff --git a/rod/msgs.nim b/rod/msgs.nim
index 00ec61941..ef3886344 100755
--- a/rod/msgs.nim
+++ b/rod/msgs.nim
@@ -398,8 +398,8 @@ proc UnknownLineInfo*(): TLineInfo =
   result.fileIndex = -1
 
 var 
-  filenames: seq[string] = @ []
-  msgContext: seq[TLineInfo] = @ []
+  filenames: seq[string] = @[]
+  msgContext: seq[TLineInfo] = @[]
 
 proc pushInfoContext*(info: TLineInfo) = 
   msgContext.add(info)
@@ -424,10 +424,10 @@ proc ToFilename*(info: TLineInfo): string =
   if info.fileIndex == - 1: result = "???"
   else: result = filenames[info.fileIndex]
   
-proc ToLinenumber*(info: TLineInfo): int = 
+proc ToLinenumber*(info: TLineInfo): int {.inline.} = 
   result = info.line
 
-proc toColumn*(info: TLineInfo): int = 
+proc toColumn*(info: TLineInfo): int {.inline.} = 
   result = info.col
 
 var checkPoints: seq[TLineInfo] = @[]
@@ -453,11 +453,18 @@ proc MsgKindToString*(kind: TMsgKind): string =
 proc getMessageStr(msg: TMsgKind, arg: string): string = 
   result = `%`(msgKindToString(msg), [arg])
 
-proc inCheckpoint*(current: TLineInfo): bool = 
+type
+  TCheckPointResult* = enum 
+    cpNone, cpFuzzy, cpExact
+
+proc inCheckpoint*(current: TLineInfo): TCheckPointResult = 
   for i in countup(0, high(checkPoints)): 
-    if (current.line >= checkPoints[i].line) and
-        (current.fileIndex == (checkPoints[i].fileIndex)): 
-      return true
+    if current.fileIndex == checkPoints[i].fileIndex:
+      if current.line == checkPoints[i].line and
+          abs(current.col-checkPoints[i].col) < 4:
+        return cpExact
+      if current.line >= checkPoints[i].line:
+        return cpFuzzy
 
 type
   TErrorHandling = enum doNothing, doAbort, doRaise
diff --git a/rod/sem.nim b/rod/sem.nim
index 66fc66cbe..eec579dda 100755
--- a/rod/sem.nim
+++ b/rod/sem.nim
@@ -28,8 +28,10 @@ proc considerAcc(n: PNode): PIdent =
     GlobalError(n.info, errIdentifierExpected, renderTree(n))
     result = nil
 
-proc isTopLevel(c: PContext): bool = 
-  result = c.tab.tos <= 2
+proc isTopLevel(c: PContext): bool {.inline.} = 
+  # if we encountered an error, we treat as top-level so that
+  # cascading errors are not that strange:
+  result = c.tab.tos <= 2 or msgs.gErrorCounter > 0
 
 proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = 
   result = newSym(kind, considerAcc(n), getCurrOwner())
diff --git a/rod/semexprs.nim b/rod/semexprs.nim
index b16bf11dc..762eb951a 100755
--- a/rod/semexprs.nim
+++ b/rod/semexprs.nim
@@ -641,8 +641,6 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
 
   checkSonsLen(n, 2)
   n.sons[0] = semExprWithType(c, n.sons[0], {efAllowType} + flags)
-  if gCmd == cmdSuggest: 
-    suggestFieldAccess(c, n.sons[0])
   var i = considerAcc(n.sons[1])
   var ty = n.sons[0].Typ
   var f: PSym = nil
diff --git a/rod/seminst.nim b/rod/seminst.nim
index d32aff15e..3cd86b904 100755
--- a/rod/seminst.nim
+++ b/rod/seminst.nim
@@ -7,11 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-# This module does the instantiation of generic procs.
-
-proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
-                      info: TLineInfo): PSym
-  # generates an instantiated proc
+# This module implements the instantiation of generic procs.
 
 proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) = 
   if (n.kind != nkGenericParams): 
diff --git a/rod/sigmatch.nim b/rod/sigmatch.nim
index dc0b1bbc4..b25008e1e 100755
--- a/rod/sigmatch.nim
+++ b/rod/sigmatch.nim
@@ -561,11 +561,17 @@ proc IndexTypesMatch*(c: PContext, f, a: PType, arg: PNode): PNode =
   initCandidate(m, f)
   result = paramTypesMatch(c, m, f, a, arg)
 
+proc argtypeMatches*(c: PContext, f, a: PType): bool = 
+  var m: TCandidate
+  initCandidate(m, f)
+  result = paramTypesMatch(c, m, f, a, nil) != nil  
+
 proc setSon(father: PNode, at: int, son: PNode) = 
   if sonsLen(father) <= at: setlen(father.sons, at + 1)
   father.sons[at] = son
 
-proc matches*(c: PContext, n: PNode, m: var TCandidate) = 
+proc matchesAux*(c: PContext, n: PNode, m: var TCandidate, 
+                 marker: var TIntSet) = 
   var f = 1 # iterates over formal parameters
   var a = 1 # iterates over the actual given arguments
   m.state = csMatch           # until proven otherwise
@@ -573,8 +579,6 @@ proc matches*(c: PContext, n: PNode, m: var TCandidate) =
   m.call.typ = base(m.callee) # may be nil
   var formalLen = sonsLen(m.callee.n)
   addSon(m.call, copyTree(n.sons[0]))
-  var marker: TIntSet
-  IntSetInit(marker)
   var container: PNode = nil # constructed container
   var formal: PSym = nil
   while a < sonsLen(n): 
@@ -656,13 +660,26 @@ proc matches*(c: PContext, n: PNode, m: var TCandidate) =
           setSon(m.call, formal.position + 1, arg)
     inc(a)
     inc(f)
-  f = 1
+
+proc partialMatch*(c: PContext, n: PNode, m: var TCandidate) = 
+  # for 'suggest' support:
+  var marker: TIntSet
+  IntSetInit(marker)
+  matchesAux(c, n, m, marker)  
+
+proc matches*(c: PContext, n: PNode, m: var TCandidate) = 
+  var marker: TIntSet
+  IntSetInit(marker)
+  matchesAux(c, n, m, marker)
+  if m.state == csNoMatch: return
+  # check that every formal parameter got a value:
+  var f = 1
   while f < sonsLen(m.callee.n): 
-    formal = m.callee.n.sons[f].sym
+    var formal = m.callee.n.sons[f].sym
     if not IntSetContainsOrIncl(marker, formal.position): 
       if formal.ast == nil: 
         if formal.typ.kind == tyOpenArray:
-          container = newNodeI(nkBracket, n.info)
+          var container = newNodeI(nkBracket, n.info)
           addSon(m.call, implicitConv(nkHiddenStdConv, formal.typ, 
                                       container, m, c))
         else:
diff --git a/rod/suggest.nim b/rod/suggest.nim
index 5eaa2bd9e..bddb247c3 100644
--- a/rod/suggest.nim
+++ b/rod/suggest.nim
@@ -40,17 +40,11 @@ proc suggestField(s: PSym) =
   if filterSym(s):
     MessageOut(SymToStr(s, isLocal=true))
 
-proc suggestExpr*(c: PContext, n: PNode) = 
-  if not msgs.inCheckpoint(n.info): return
-
+template wholeSymTab(cond: expr) = 
   for i in countdown(c.tab.tos-1, 0): 
     for it in items(c.tab.stack[i]): 
-      if filterSym(it):
+      if cond:
         MessageOut(SymToStr(it, isLocal = i > ModuleTablePos))
-  quit(0)
-
-proc suggestStmt*(c: PContext, n: PNode) = 
-  suggestExpr(c, n)
 
 proc suggestSymList(list: PNode) = 
   for i in countup(0, sonsLen(list) - 1): 
@@ -60,20 +54,45 @@ proc suggestSymList(list: PNode) =
 proc suggestObject(n: PNode) = 
   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])
   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]))
+      for i in countup(1, L-1): suggestObject(lastSon(n.sons[i]))
   of nkSym: suggestField(n.sym)
   else: nil
 
+proc nameFits(c: PContext, s: PSym, n: PNode): bool = 
+  result = n.sons[0].kind == nkSym and n.sons[0].sym.name.id == s.name.id
+
+proc argsFit(c: PContext, candidate: PSym, n: PNode): bool = 
+  case candidate.kind 
+  of skProc, skIterator, skMethod:
+    var m: TCandidate
+    initCandidate(m, candidate, nil)
+    sigmatch.partialMatch(c, n, m)
+    result = m.state != csNoMatch
+  of skTemplate, skMacro:
+    result = true
+  else:
+    result = false
+
+proc suggestCall*(c: PContext, n: PNode) = 
+  wholeSymTab(filterSym(it) and nameFits(c, it, n) and argsFit(c, it, n))
+
+proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} = 
+  if s.typ != nil and sonsLen(s.typ) > 1:
+    result = sigmatch.argtypeMatches(c, s.typ.sons[1], firstArg)
+
 proc suggestOperations(c: PContext, n: PNode, typ: PType) =
-  nil
+  assert typ != nil
+  wholeSymTab(filterSym(it) and typeFits(c, it, typ))
+
+proc suggestEverything(c: PContext, n: PNode) = 
+  wholeSymTab(filterSym(it))
 
-proc suggestFieldAccess*(c: PContext, n: PNode) =
+proc suggestFieldAccess(c: PContext, n: PNode) =
   # special code that deals with ``myObj.``. `n` is NOT the nkDotExpr-node, but
   # ``myObj``.
   var typ = n.Typ
@@ -89,7 +108,7 @@ proc suggestFieldAccess*(c: PContext, n: PNode) =
           if filterSym(it): MessageOut(SymToStr(it, isLocal=false))
     else:
       # fallback:
-      suggestExpr(c, n)
+      suggestEverything(c, n)
   elif typ.kind == tyEnum: 
     # look up if the identifier belongs to the enum:
     var t = typ
@@ -111,5 +130,32 @@ proc suggestFieldAccess*(c: PContext, n: PNode) =
       suggestOperations(c, n, typ)
     else:
       # fallback: 
-      suggestExpr(c, n)
+      suggestEverything(c, n)
+
+proc suggestExpr*(c: PContext, n: PNode) = 
+  var cp = msgs.inCheckpoint(n.info)
+  if cp == cpNone: return
+  block:
+    case n.kind
+    of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, 
+        nkCallStrLit, nkMacroStmt: 
+      var a = copyNode(n)
+      for i in 0..sonsLen(n)-1:
+        # use as many typed arguments as possible:
+        var x = c.semExpr(c, n.sons[i])
+        if x.kind == nkEmpty or x.typ == nil: break
+        addSon(a, x)
+      suggestCall(c, n)
+      break
+    of nkDotExpr: 
+      if cp == cpExact:
+        var obj = c.semExpr(c, n.sons[0])
+        suggestFieldAccess(c, obj)
+        break
+    else: nil
+    suggestEverything(c, n)
+  quit(0)
+
+proc suggestStmt*(c: PContext, n: PNode) = 
+  suggestExpr(c, n)
 
diff --git a/todo.txt b/todo.txt
index 3ce1fb65a..aa51ab09a 100755
--- a/todo.txt
+++ b/todo.txt
@@ -1,4 +1,4 @@
-- 'suggest' needs tweaking: support for '.'
+- 'suggest' needs tweaking: end-token; testing!
 - stdout support for doc, pretty
 
 - thread support: threadvar on Windows seems broken; 
@@ -16,7 +16,6 @@
 High priority (version 0.9.0)
 =============================
 
-
 - fix implicit generic routines
 - fix the streams implementation so that it uses methods
 - fix overloading resolution