next steps to perfect 'suggest'

This commit is contained in:
Araq 2011-02-22 08:58:12 +01:00
commit 310faca724
7 changed files with 106 additions and 41 deletions

View file

@ -424,10 +424,10 @@ proc ToFilename*(info: TLineInfo): string =
if info.fileIndex == - 1: result = "???" if info.fileIndex == - 1: result = "???"
else: result = filenames[info.fileIndex] else: result = filenames[info.fileIndex]
proc ToLinenumber*(info: TLineInfo): int = proc ToLinenumber*(info: TLineInfo): int {.inline.} =
result = info.line result = info.line
proc toColumn*(info: TLineInfo): int = proc toColumn*(info: TLineInfo): int {.inline.} =
result = info.col result = info.col
var checkPoints: seq[TLineInfo] = @[] var checkPoints: seq[TLineInfo] = @[]
@ -453,11 +453,18 @@ proc MsgKindToString*(kind: TMsgKind): string =
proc getMessageStr(msg: TMsgKind, arg: string): string = proc getMessageStr(msg: TMsgKind, arg: string): string =
result = `%`(msgKindToString(msg), [arg]) 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)): for i in countup(0, high(checkPoints)):
if (current.line >= checkPoints[i].line) and if current.fileIndex == checkPoints[i].fileIndex:
(current.fileIndex == (checkPoints[i].fileIndex)): if current.line == checkPoints[i].line and
return true abs(current.col-checkPoints[i].col) < 4:
return cpExact
if current.line >= checkPoints[i].line:
return cpFuzzy
type type
TErrorHandling = enum doNothing, doAbort, doRaise TErrorHandling = enum doNothing, doAbort, doRaise

View file

@ -28,8 +28,10 @@ proc considerAcc(n: PNode): PIdent =
GlobalError(n.info, errIdentifierExpected, renderTree(n)) GlobalError(n.info, errIdentifierExpected, renderTree(n))
result = nil result = nil
proc isTopLevel(c: PContext): bool = proc isTopLevel(c: PContext): bool {.inline.} =
result = c.tab.tos <= 2 # 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 = proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
result = newSym(kind, considerAcc(n), getCurrOwner()) result = newSym(kind, considerAcc(n), getCurrOwner())

View file

@ -641,8 +641,6 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
checkSonsLen(n, 2) checkSonsLen(n, 2)
n.sons[0] = semExprWithType(c, n.sons[0], {efAllowType} + flags) 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 i = considerAcc(n.sons[1])
var ty = n.sons[0].Typ var ty = n.sons[0].Typ
var f: PSym = nil var f: PSym = nil

View file

@ -7,11 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
# This module does the instantiation of generic procs. # This module implements the instantiation of generic procs.
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
info: TLineInfo): PSym
# generates an instantiated proc
proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) = proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
if (n.kind != nkGenericParams): if (n.kind != nkGenericParams):

View file

@ -561,11 +561,17 @@ proc IndexTypesMatch*(c: PContext, f, a: PType, arg: PNode): PNode =
initCandidate(m, f) initCandidate(m, f)
result = paramTypesMatch(c, m, f, a, arg) 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) = proc setSon(father: PNode, at: int, son: PNode) =
if sonsLen(father) <= at: setlen(father.sons, at + 1) if sonsLen(father) <= at: setlen(father.sons, at + 1)
father.sons[at] = son 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 f = 1 # iterates over formal parameters
var a = 1 # iterates over the actual given arguments var a = 1 # iterates over the actual given arguments
m.state = csMatch # until proven otherwise 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 m.call.typ = base(m.callee) # may be nil
var formalLen = sonsLen(m.callee.n) var formalLen = sonsLen(m.callee.n)
addSon(m.call, copyTree(n.sons[0])) addSon(m.call, copyTree(n.sons[0]))
var marker: TIntSet
IntSetInit(marker)
var container: PNode = nil # constructed container var container: PNode = nil # constructed container
var formal: PSym = nil var formal: PSym = nil
while a < sonsLen(n): while a < sonsLen(n):
@ -656,13 +660,26 @@ proc matches*(c: PContext, n: PNode, m: var TCandidate) =
setSon(m.call, formal.position + 1, arg) setSon(m.call, formal.position + 1, arg)
inc(a) inc(a)
inc(f) 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): 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 not IntSetContainsOrIncl(marker, formal.position):
if formal.ast == nil: if formal.ast == nil:
if formal.typ.kind == tyOpenArray: if formal.typ.kind == tyOpenArray:
container = newNodeI(nkBracket, n.info) var container = newNodeI(nkBracket, n.info)
addSon(m.call, implicitConv(nkHiddenStdConv, formal.typ, addSon(m.call, implicitConv(nkHiddenStdConv, formal.typ,
container, m, c)) container, m, c))
else: else:

View file

@ -40,17 +40,11 @@ proc suggestField(s: PSym) =
if filterSym(s): if filterSym(s):
MessageOut(SymToStr(s, isLocal=true)) MessageOut(SymToStr(s, isLocal=true))
proc suggestExpr*(c: PContext, n: PNode) = template wholeSymTab(cond: expr) =
if not msgs.inCheckpoint(n.info): return
for i in countdown(c.tab.tos-1, 0): for i in countdown(c.tab.tos-1, 0):
for it in items(c.tab.stack[i]): for it in items(c.tab.stack[i]):
if filterSym(it): if cond:
MessageOut(SymToStr(it, isLocal = i > ModuleTablePos)) MessageOut(SymToStr(it, isLocal = i > ModuleTablePos))
quit(0)
proc suggestStmt*(c: PContext, n: PNode) =
suggestExpr(c, n)
proc suggestSymList(list: PNode) = proc suggestSymList(list: PNode) =
for i in countup(0, sonsLen(list) - 1): for i in countup(0, sonsLen(list) - 1):
@ -65,15 +59,40 @@ proc suggestObject(n: PNode) =
var L = sonsLen(n) var L = sonsLen(n)
if L > 0: if L > 0:
suggestObject(n.sons[0]) suggestObject(n.sons[0])
for i in countup(1, L-1): for i in countup(1, L-1): suggestObject(lastSon(n.sons[i]))
suggestObject(lastSon(n.sons[i]))
of nkSym: suggestField(n.sym) of nkSym: suggestField(n.sym)
else: nil else: nil
proc suggestOperations(c: PContext, n: PNode, typ: PType) = proc nameFits(c: PContext, s: PSym, n: PNode): bool =
nil result = n.sons[0].kind == nkSym and n.sons[0].sym.name.id == s.name.id
proc suggestFieldAccess*(c: PContext, n: PNode) = 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) =
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) =
# special code that deals with ``myObj.``. `n` is NOT the nkDotExpr-node, but # special code that deals with ``myObj.``. `n` is NOT the nkDotExpr-node, but
# ``myObj``. # ``myObj``.
var typ = n.Typ var typ = n.Typ
@ -89,7 +108,7 @@ proc suggestFieldAccess*(c: PContext, n: PNode) =
if filterSym(it): MessageOut(SymToStr(it, isLocal=false)) if filterSym(it): MessageOut(SymToStr(it, isLocal=false))
else: else:
# fallback: # fallback:
suggestExpr(c, n) suggestEverything(c, n)
elif typ.kind == tyEnum: elif typ.kind == tyEnum:
# look up if the identifier belongs to the enum: # look up if the identifier belongs to the enum:
var t = typ var t = typ
@ -111,5 +130,32 @@ proc suggestFieldAccess*(c: PContext, n: PNode) =
suggestOperations(c, n, typ) suggestOperations(c, n, typ)
else: else:
# fallback: # fallback:
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) suggestExpr(c, n)

View file

@ -1,4 +1,4 @@
- 'suggest' needs tweaking: support for '.' - 'suggest' needs tweaking: end-token; testing!
- stdout support for doc, pretty - stdout support for doc, pretty
- thread support: threadvar on Windows seems broken; - thread support: threadvar on Windows seems broken;
@ -16,7 +16,6 @@
High priority (version 0.9.0) High priority (version 0.9.0)
============================= =============================
- fix implicit generic routines - fix implicit generic routines
- fix the streams implementation so that it uses methods - fix the streams implementation so that it uses methods
- fix overloading resolution - fix overloading resolution