made compiler more robust for idetools; implemented idetools.usages

This commit is contained in:
Araq
2012-07-30 23:07:19 +02:00
parent b0c11d3efb
commit 674c05f426
11 changed files with 96 additions and 47 deletions

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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)

View File

@@ -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:

View File

@@ -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)

View File

@@ -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