--stdout support; idetools implemented

This commit is contained in:
Araq 2011-02-25 01:53:58 +01:00
commit f8dd74a073
17 changed files with 188 additions and 112 deletions

View file

@ -1,22 +1,28 @@
Advanced commands: Advanced commands:
//compileToC, cc compile project with C code generator //compileToC, cc compile project with C code generator
//compileToOC, oc compile project to Objective C code //compileToOC, oc compile project to Objective C code
//rst2html converts a reStructuredText file to HTML //rst2html convert a reStructuredText file to HTML
//rst2tex converts a reStructuredText file to TeX //rst2tex convert a reStructuredText file to TeX
//run run the project (with Tiny C backend; Linux only!) //run run the project (with Tiny C backend; buggy!)
//pretty pretty print the inputfile //pretty pretty print the inputfile
//genDepend generate a DOT file containing the //genDepend generate a DOT file containing the
module dependency graph module dependency graph
//listDef list all defined conditionals and exit //dump dump all defined conditionals and search paths
//check checks the project for syntax and semantic //check checks the project for syntax and semantic
//parse parses a single file (for debugging Nimrod) //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
--context list possible invokation context
Advanced options: Advanced options:
-o, --out:FILE set the output filename
--stdout output to stdout
-w, --warnings:on|off turn all warnings on|off -w, --warnings:on|off turn all warnings on|off
--warning[X]:on|off turn specific warning X on|off --warning[X]:on|off turn specific warning X on|off
--hints:on|off turn all hints on|off --hints:on|off turn all hints on|off
--hint[X]:on|off turn specific hint X on|off --hint[X]:on|off turn specific hint X on|off
--lib:PATH set the path to the system.nim library --lib:PATH set the system library path
-c, --compileOnly compile only; do not assemble or link -c, --compileOnly compile only; do not assemble or link
--noLinking compile but do not link --noLinking compile but do not link
--noMain do not generate a main procedure --noMain do not generate a main procedure
@ -35,10 +41,11 @@ Advanced options:
--skipCfg do not read the general configuration file --skipCfg do not read the general configuration file
--skipProjCfg do not read the project's configuration file --skipProjCfg do not read the project's configuration file
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC --gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC
--index:FILE use FILE to generate a documenation index file --index:FILE use FILE to generate a documentation index file
--putenv:key=value set an environment variable --putenv:key=value set an environment variable
--listCmd list the commands used to execute external programs --listCmd list the commands used to execute external programs
--parallelBuild=0|1|... perform a parallel build --parallelBuild=0|1|... perform a parallel build
value = number of processors (0 for auto-detect) value = number of processors (0 for auto-detect)
--verbosity:0|1|2|3 set Nimrod's verbosity level (0 is default) --verbosity:0|1|2|3 set Nimrod's verbosity level (0 is default)
-v, --version show detailed version information -v, --version show detailed version information

View file

@ -1,16 +1,15 @@
Usage:: Usage::
nimrod command [options] inputfile [arguments] nimrod command [options] [projectfile] [arguments]
Command: Command:
//compile, c compile project with default code generator (C) //compile, c compile project with default code generator (C)
//doc generate the documentation for inputfile //doc generate the documentation for inputfile
//i start Nimrod in interactive mode (limited) //i start Nimrod in interactive mode (limited)
Arguments: Arguments:
arguments are passed to the program being run (if --run option is selected) arguments are passed to the program being run (if --run option is selected)
Options: Options:
-p, --path:PATH add path to search paths -p, --path:PATH add path to search paths
-o, --out:FILE set the output filename
-d, --define:SYMBOL define a conditional symbol -d, --define:SYMBOL define a conditional symbol
-u, --undef:SYMBOL undefine a conditional symbol -u, --undef:SYMBOL undefine a conditional symbol
-f, --forceBuild force rebuilding of all modules -f, --forceBuild force rebuilding of all modules
@ -33,3 +32,4 @@ Options:
-r, --run run the compiled program with given arguments -r, --run run the compiled program with given arguments
--advanced show advanced command line switches --advanced show advanced command line switches
-h, --help show this help -h, --help show this help

View file

@ -41,7 +41,6 @@ Arguments:
arguments are passed to the program being run (if --run option is selected) arguments are passed to the program being run (if --run option is selected)
Options: Options:
-p, --path:PATH add path to search paths -p, --path:PATH add path to search paths
-o, --out:FILE set the output filename
-d, --define:SYMBOL define a conditional symbol -d, --define:SYMBOL define a conditional symbol
-u, --undef:SYMBOL undefine a conditional symbol -u, --undef:SYMBOL undefine a conditional symbol
-f, --forceBuild force rebuilding of all modules -f, --forceBuild force rebuilding of all modules
@ -70,17 +69,22 @@ Options:
Advanced commands: Advanced commands:
compileToC, cc compile project with C code generator compileToC, cc compile project with C code generator
compileToOC, oc compile project to Objective C code compileToOC, oc compile project to Objective C code
rst2html converts a reStructuredText file to HTML rst2html convert a reStructuredText file to HTML
rst2tex converts a reStructuredText file to TeX rst2tex convert a reStructuredText file to TeX
run run the project (with Tiny C backend; buggy!) run run the project (with Tiny C backend; buggy!)
pretty pretty print the inputfile pretty pretty print the inputfile
genDepend generate a DOT file containing the genDepend generate a DOT file containing the
module dependency graph module dependency graph
listDef list all defined conditionals and exit dump dump all defined conditionals and search paths
check checks the project for syntax and semantic check checks the project for syntax and semantic
suggest list all possible symbols at position; idetools compiler support for IDEs: possible options:
use with --track option --track:FILE,LINE,COL track a file/cursor position
--suggest suggest all possible symbols at position
--def list all possible symbols at position
--context list possible invokation context
Advanced options: Advanced options:
-o, --out:FILE set the output filename
--stdout output to stdout
-w, --warnings:on|off turn all warnings on|off -w, --warnings:on|off turn all warnings on|off
--warning[X]:on|off turn specific warning X on|off --warning[X]:on|off turn specific warning X on|off
--hints:on|off turn all hints on|off --hints:on|off turn all hints on|off
@ -104,9 +108,8 @@ Advanced options:
--skipCfg do not read the general configuration file --skipCfg do not read the general configuration file
--skipProjCfg do not read the project's configuration file --skipProjCfg do not read the project's configuration file
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC --gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC
--index:FILE use FILE to generate a documenation index file --index:FILE use FILE to generate a documentation index file
--putenv:key=value set an environment variable --putenv:key=value set an environment variable
--track:FILE,LINE,COLUMN track a file position for 'suggest'
--listCmd list the commands used to execute external programs --listCmd list the commands used to execute external programs
--parallelBuild=0|1|... perform a parallel build --parallelBuild=0|1|... perform a parallel build
value = number of processors (0 for auto-detect) value = number of processors (0 for auto-detect)
@ -415,9 +418,6 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
excl(gGlobalOptions, optGenGuiApp) excl(gGlobalOptions, optGenGuiApp)
defineSymbol("library") defineSymbol("library")
else: LocalError(info, errGuiConsoleOrLibExpectedButXFound, arg) else: LocalError(info, errGuiConsoleOrLibExpectedButXFound, arg)
of wListDef:
expectNoArg(switch, arg, pass, info)
if pass in {passCmd2, passPP}: condsyms.listSymbols()
of wPassC, wT: of wPassC, wT:
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
if pass in {passCmd2, passPP}: extccomp.addCompileOption(arg) if pass in {passCmd2, passPP}: extccomp.addCompileOption(arg)
@ -496,6 +496,18 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
of wTrack: of wTrack:
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
track(arg, info) track(arg, info)
of wSuggest:
expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optSuggest)
of wDef:
expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optDef)
of wContext:
expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optContext)
of wStdout:
expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optStdout)
else: else:
if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg) if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
else: InvalidCmdLineOption(pass, switch, info) else: InvalidCmdLineOption(pass, switch, info)

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2008 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.

View file

@ -857,6 +857,13 @@ proc generateIndex(d: PDoc) =
sortIndex(d.theIndex) sortIndex(d.theIndex)
writeRope(renderRstToRst(d, d.indexFile), gIndexFile) writeRope(renderRstToRst(d, d.indexFile), gIndexFile)
proc writeOutput(d: PDoc, filename, outExt: string) =
var content = genOutFile(d)
if optStdout in gGlobalOptions:
writeRope(stdout, content)
else:
writeRope(content, getOutFile(filename, outExt))
proc CommandDoc(filename: string) = proc CommandDoc(filename: string) =
var ast = parseFile(addFileExt(filename, nimExt)) var ast = parseFile(addFileExt(filename, nimExt))
if ast == nil: return if ast == nil: return
@ -864,7 +871,7 @@ proc CommandDoc(filename: string) =
initIndexFile(d) initIndexFile(d)
d.hasToc = true d.hasToc = true
generateDoc(d, ast) generateDoc(d, ast)
writeRope(genOutFile(d), getOutFile(filename, HtmlExt)) writeOutput(d, filename, HtmlExt)
generateIndex(d) generateIndex(d)
proc CommandRstAux(filename, outExt: string) = proc CommandRstAux(filename, outExt: string) =
@ -873,8 +880,7 @@ proc CommandRstAux(filename, outExt: string) =
initIndexFile(d) initIndexFile(d)
var rst = rstParse(readFile(filen), false, filen, 0, 1, d.hasToc) var rst = rstParse(readFile(filen), false, filen, 0, 1, d.hasToc)
d.modDesc = renderRstToOut(d, rst) d.modDesc = renderRstToOut(d, rst)
var code = genOutFile(d) writeOutput(d, filename, outExt)
writeRope(code, getOutFile(filename, outExt))
generateIndex(d) generateIndex(d)
proc CommandRst2Html(filename: string) = proc CommandRst2Html(filename: string) =

View file

@ -251,9 +251,10 @@ proc MainCommand(cmd, filename: string) =
gCmd = cmdGenDepend gCmd = cmdGenDepend
wantFile(filename) wantFile(filename)
CommandGenDepend(filename) CommandGenDepend(filename)
of wListDef: of wDump:
gCmd = cmdListDef gCmd = cmdDump
condsyms.ListSymbols() condsyms.ListSymbols()
for it in iterSearchPath(): MessageOut(it)
of wCheck: of wCheck:
gCmd = cmdCheck gCmd = cmdCheck
wantFile(filename) wantFile(filename)
@ -270,9 +271,9 @@ proc MainCommand(cmd, filename: string) =
of wI: of wI:
gCmd = cmdInteractive gCmd = cmdInteractive
CommandInteractive() CommandInteractive()
of wSuggest: of wIdeTools:
gCmd = cmdSuggest gCmd = cmdIdeTools
wantFile(filename) wantFile(filename)
CommandSuggest(filename) CommandSuggest(filename)
else: rawMessage(errInvalidCommandX, cmd) else: rawMessage(errInvalidCommandX, cmd)

View file

@ -42,15 +42,21 @@ type # please make sure we have under 32 options
optSkipConfigFile, # skip the general config file optSkipConfigFile, # skip the general config file
optSkipProjConfigFile, # skip the project's config file optSkipProjConfigFile, # skip the project's config file
optNoMain, # do not generate a "main" proc optNoMain, # do not generate a "main" proc
optThreads # support for multi-threading optThreads, # support for multi-threading
optStdout, # output to stdout
optSuggest, # ideTools: 'suggest'
optContext, # ideTools: 'context'
optDef # ideTools: 'def'
TGlobalOptions* = set[TGlobalOption] TGlobalOptions* = set[TGlobalOption]
TCommands* = enum # Nimrod's commands TCommands* = enum # Nimrod's commands
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
cmdCompileToEcmaScript, cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc, cmdCompileToEcmaScript, cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc,
cmdGenDepend, cmdListDef, cmdCheck, # semantic checking for whole project cmdGenDepend, cmdDump,
cmdCheck, # semantic checking for whole project
cmdParse, # parse a single file (for debugging) cmdParse, # parse a single file (for debugging)
cmdScan, # scan a single file (for debugging) cmdScan, # scan a single file (for debugging)
cmdSuggest, # suggest feature (auto-completion for IDEs) cmdIdeTools, # ide tools
cmdDef, # def feature (find definition for IDEs)
cmdRst2html, # convert a reStructuredText file to HTML cmdRst2html, # convert a reStructuredText file to HTML
cmdRst2tex, # convert a reStructuredText file to TeX cmdRst2tex, # convert a reStructuredText file to TeX
cmdInteractive, # start interactive session cmdInteractive, # start interactive session
@ -121,8 +127,7 @@ proc getOutFile*(filename, ext: string): string =
else: result = changeFileExt(filename, ext) else: result = changeFileExt(filename, ext)
proc addImplicitMod(filename: string) = proc addImplicitMod(filename: string) =
var length: int var length = len(gImplicitMods)
length = len(gImplicitMods)
setlen(gImplicitMods, length + 1) setlen(gImplicitMods, length + 1)
gImplicitMods[length] = filename gImplicitMods[length] = filename
@ -166,15 +171,19 @@ proc completeGeneratedFilePath(f: string, createSubDir: bool = true): string =
quit(1) quit(1)
result = joinPath(subdir, tail) result = joinPath(subdir, tail)
iterator iterSearchPath*(): string =
var it = PStrEntry(SearchPaths.head)
while it != nil:
yield it.data
it = PStrEntry(it.Next)
proc rawFindFile(f: string): string = proc rawFindFile(f: string): string =
if ExistsFile(f): if ExistsFile(f):
result = f result = f
else: else:
var it = PStrEntry(SearchPaths.head) for it in iterSearchPath():
while it != nil: result = JoinPath(it, f)
result = JoinPath(it.data, f) if ExistsFile(result): return
if ExistsFile(result): return
it = PStrEntry(it.Next)
result = "" result = ""
proc FindFile(f: string): string = proc FindFile(f: string): string =

View file

@ -1058,9 +1058,13 @@ proc renderModule(n: PNode, filename: string, renderFlags: TRenderFlags = {}) =
of nkTypeSection, nkConstSection, nkVarSection, nkCommentStmt: putNL(g) of nkTypeSection, nkConstSection, nkVarSection, nkCommentStmt: putNL(g)
else: nil else: nil
gcoms(g) gcoms(g)
if open(f, filename, fmWrite): if optStdout in gGlobalOptions:
write(stdout, g.buf)
elif open(f, filename, fmWrite):
write(f, g.buf) write(f, g.buf)
close(f) close(f)
else:
rawMessage(errCannotOpenFile, filename)
proc initTokRender(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) = proc initTokRender(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) =
initSrcGen(r, renderFlags) initSrcGen(r, renderFlags)

View file

@ -274,15 +274,7 @@ proc app(a: var PRope, b: PRope) = a = con(a, b)
proc app(a: var PRope, b: string) = a = con(a, b) proc app(a: var PRope, b: string) = a = con(a, b)
proc prepend(a: var PRope, b: PRope) = a = con(b, a) proc prepend(a: var PRope, b: PRope) = a = con(b, a)
proc WriteRopeRec(f: var tfile, c: PRope) = proc writeRope*(f: var tfile, c: PRope) =
if c == nil: return
if (c.data != nil):
write(f, c.data)
else:
writeRopeRec(f, c.left)
writeRopeRec(f, c.right)
proc newWriteRopeRec(f: var tfile, c: PRope) =
var stack = @[c] var stack = @[c]
while len(stack) > 0: while len(stack) > 0:
var it = pop(stack) var it = pop(stack)
@ -296,7 +288,7 @@ proc newWriteRopeRec(f: var tfile, c: PRope) =
proc WriteRope(head: PRope, filename: string) = proc WriteRope(head: PRope, filename: string) =
var f: tfile # we use a textfile for automatic buffer handling var f: tfile # we use a textfile for automatic buffer handling
if open(f, filename, fmWrite): if open(f, filename, fmWrite):
if head != nil: newWriteRopeRec(f, head) if head != nil: WriteRope(f, head)
close(f) close(f)
else: else:
rawMessage(errCannotOpenFile, filename) rawMessage(errCannotOpenFile, filename)

View file

@ -953,7 +953,7 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = n result = n
if gCmd == cmdSuggest: if gCmd == cmdIdeTools:
suggestExpr(c, n) suggestExpr(c, n)
if nfSem in n.flags: return if nfSem in n.flags: return
case n.kind # atoms: case n.kind # atoms:

View file

@ -67,7 +67,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
L: int L: int
a: PNode a: PNode
result = n result = n
if gCmd == cmdSuggest: suggestStmt(c, n) if gCmd == cmdIdeTools: suggestStmt(c, n)
case n.kind case n.kind
of nkIdent: of nkIdent:
var s = SymtabGet(c.Tab, n.ident) var s = SymtabGet(c.Tab, n.ident)

View file

@ -275,7 +275,7 @@ proc semVar(c: PContext, n: PNode): PNode =
result = copyNode(n) result = copyNode(n)
for i in countup(0, sonsLen(n)-1): for i in countup(0, sonsLen(n)-1):
var a = n.sons[i] var a = n.sons[i]
if gCmd == cmdSuggest: suggestStmt(c, a) if gCmd == cmdIdeTools: suggestStmt(c, a)
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): IllFormedAst(a) if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): IllFormedAst(a)
checkMinSonsLen(a, 3) checkMinSonsLen(a, 3)
@ -332,7 +332,7 @@ proc semConst(c: PContext, n: PNode): PNode =
result = copyNode(n) result = copyNode(n)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var a = n.sons[i] var a = n.sons[i]
if gCmd == cmdSuggest: suggestStmt(c, a) if gCmd == cmdIdeTools: suggestStmt(c, a)
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if (a.kind != nkConstDef): IllFormedAst(a) if (a.kind != nkConstDef): IllFormedAst(a)
checkSonsLen(a, 3) checkSonsLen(a, 3)
@ -485,7 +485,7 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
# we even look at the type definitions on the right # we even look at the type definitions on the right
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var a = n.sons[i] var a = n.sons[i]
if gCmd == cmdSuggest: suggestStmt(c, a) if gCmd == cmdIdeTools: suggestStmt(c, a)
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if a.kind != nkTypeDef: IllFormedAst(a) if a.kind != nkTypeDef: IllFormedAst(a)
checkSonsLen(a, 3) checkSonsLen(a, 3)
@ -795,7 +795,7 @@ proc SemStmt(c: PContext, n: PNode): PNode =
const # must be last statements in a block: const # must be last statements in a block:
LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt} LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
result = n result = n
if gCmd == cmdSuggest: if gCmd == cmdIdeTools:
suggestStmt(c, n) suggestStmt(c, n)
if nfSem in n.flags: return if nfSem in n.flags: return
case n.kind case n.kind

View file

@ -566,6 +566,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
s: PSym s: PSym
t: PType t: PType
result = nil result = nil
if gCmd == cmdIdeTools: suggestExpr(c, n)
case n.kind case n.kind
of nkEmpty: nil of nkEmpty: nil
of nkTypeOfExpr: of nkTypeOfExpr:

View file

@ -9,13 +9,17 @@
## This file implements features required for IDE support. ## This file implements features required for IDE support.
import scanner, idents, ast, astalgo, semdata, msgs, types, sigmatch import scanner, idents, ast, astalgo, semdata, msgs, types, sigmatch, options
const const
sep = '\t' sep = '\t'
sectionSuggest = "sug"
sectionDef = "def"
sectionContext = "con"
proc SymToStr(s: PSym, isLocal: bool): string = proc SymToStr(s: PSym, isLocal: bool, section: string): string =
result = "" result = section
result.add(sep)
result.add($s.kind) result.add($s.kind)
result.add(sep) result.add(sep)
if not isLocal: if not isLocal:
@ -38,13 +42,13 @@ proc filterSym(s: PSym): bool {.inline.} =
proc suggestField(s: PSym) = proc suggestField(s: PSym) =
if filterSym(s): if filterSym(s):
MessageOut(SymToStr(s, isLocal=true)) MessageOut(SymToStr(s, isLocal=true, sectionSuggest))
template wholeSymTab(cond: expr) = template wholeSymTab(cond, section: expr) =
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 cond: if cond:
MessageOut(SymToStr(it, isLocal = i > ModuleTablePos)) MessageOut(SymToStr(it, isLocal = i > ModuleTablePos, section))
proc suggestSymList(list: PNode) = proc suggestSymList(list: PNode) =
for i in countup(0, sonsLen(list) - 1): for i in countup(0, sonsLen(list) - 1):
@ -86,7 +90,8 @@ proc argsFit(c: PContext, candidate: PSym, n: PNode): bool =
result = false result = false
proc suggestCall(c: PContext, n: PNode) = proc suggestCall(c: PContext, n: PNode) =
wholeSymTab(filterSym(it) and nameFits(c, it, n) and argsFit(c, it, n)) wholeSymTab(filterSym(it) and nameFits(c, it, n) and argsFit(c, it, n),
sectionContext)
proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} = proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} =
if s.typ != nil and sonsLen(s.typ) > 1 and s.typ.sons[1] != nil: if s.typ != nil and sonsLen(s.typ) > 1 and s.typ.sons[1] != nil:
@ -94,10 +99,10 @@ proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} =
proc suggestOperations(c: PContext, n: PNode, typ: PType) = proc suggestOperations(c: PContext, n: PNode, typ: PType) =
assert typ != nil assert typ != nil
wholeSymTab(filterSym(it) and typeFits(c, it, typ)) wholeSymTab(filterSym(it) and typeFits(c, it, typ), sectionSuggest)
proc suggestEverything(c: PContext, n: PNode) = proc suggestEverything(c: PContext, n: PNode) =
wholeSymTab(filterSym(it)) wholeSymTab(filterSym(it), sectionSuggest)
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 # special code that deals with ``myObj.``. `n` is NOT the nkDotExpr-node, but
@ -109,10 +114,12 @@ proc suggestFieldAccess(c: PContext, n: PNode) =
if n.sym == c.module: if n.sym == c.module:
# all symbols accessible, because we are in the current module: # all symbols accessible, because we are in the current module:
for it in items(c.tab.stack[ModuleTablePos]): for it in items(c.tab.stack[ModuleTablePos]):
if filterSym(it): MessageOut(SymToStr(it, isLocal=false)) if filterSym(it):
MessageOut(SymToStr(it, isLocal=false, sectionSuggest))
else: else:
for it in items(n.sym.tab): for it in items(n.sym.tab):
if filterSym(it): MessageOut(SymToStr(it, isLocal=false)) if filterSym(it):
MessageOut(SymToStr(it, isLocal=false, sectionSuggest))
else: else:
# fallback: # fallback:
suggestEverything(c, n) suggestEverything(c, n)
@ -139,55 +146,89 @@ proc suggestFieldAccess(c: PContext, n: PNode) =
# fallback: # fallback:
suggestEverything(c, n) suggestEverything(c, n)
proc interestingNode(n: PNode): bool {.inline.} = proc findClosestDot(n: PNode): PNode =
result = n.kind == nkDotExpr
proc findClosestNode(n: PNode): PNode =
if msgs.inCheckpoint(n.info) == cpExact: if msgs.inCheckpoint(n.info) == cpExact:
result = n result = n
elif n.kind notin {nkNone..nkNilLit}: elif n.kind notin {nkNone..nkNilLit}:
for i in 0.. <sonsLen(n): for i in 0.. <sonsLen(n):
if interestingNode(n.sons[i]): if n.sons[i].kind == nkDotExpr:
result = findClosestNode(n.sons[i]) result = findClosestDot(n.sons[i])
if result != nil: return if result != nil: return
const
CallNodes = {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit,
nkMacroStmt}
proc findClosestCall(n: PNode): PNode =
if msgs.inCheckpoint(n.info) == cpExact:
result = n
elif n.kind notin {nkNone..nkNilLit}:
for i in 0.. <sonsLen(n):
if n.sons[i].kind in callNodes:
result = findClosestCall(n.sons[i])
if result != nil: return
proc findClosestSym(n: PNode): PNode =
if n.kind == nkSym and msgs.inCheckpoint(n.info) == cpExact:
result = n
elif n.kind notin {nkNone..nkNilLit}:
for i in 0.. <sonsLen(n):
result = findClosestSym(n.sons[i])
if result != nil: return
var recursiveCheck = 0 var recursiveCheck = 0
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]))
proc suggestExpr*(c: PContext, node: PNode) = proc suggestExpr*(c: PContext, node: PNode) =
var cp = msgs.inCheckpoint(node.info) var cp = msgs.inCheckpoint(node.info)
if cp == cpNone: return if cp == cpNone: return
# HACK: This keeps semExpr() from coming here recursively: # HACK: This keeps semExpr() from coming here recursively:
if recursiveCheck > 0: return if recursiveCheck > 0: return
inc(recursiveCheck) inc(recursiveCheck)
var n = findClosestNode(node)
if n == nil: n = node if optSuggest in gGlobalOptions:
else: cp = msgs.inCheckpoint(n.info) var n = findClosestDot(node)
block: if n == nil: n = node
case n.kind else: cp = cpExact
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
nkCallStrLit, nkMacroStmt: if n.kind == nkDotExpr and cp == cpExact:
when false: var obj = safeSemExpr(c, n.sons[0])
# this provides "context information", not "type suggestion": suggestFieldAccess(c, obj)
var a = copyNode(n) else:
var x = c.semExpr(c, n.sons[0]) suggestEverything(c, n)
if x.kind == nkEmpty or x.typ == nil: x = n.sons[0]
if optContext in gGlobalOptions:
var n = findClosestCall(node)
if n == nil: n = node
else: cp = cpExact
if n.kind in CallNodes:
var a = copyNode(n)
var x = safeSemExpr(c, n.sons[0])
if x.kind == nkEmpty or x.typ == nil: x = n.sons[0]
addSon(a, x)
for i in 1..sonsLen(n)-1:
# use as many typed arguments as possible:
var x = safeSemExpr(c, n.sons[i])
if x.kind == nkEmpty or x.typ == nil: break
addSon(a, x) addSon(a, x)
for i in 1..sonsLen(n)-1: suggestCall(c, a)
# use as many typed arguments as possible:
var x = c.semExpr(c, n.sons[i]) if optDef in gGlobalOptions:
if x.kind == nkEmpty or x.typ == nil: break var n = findClosestSym(fuzzySemCheck(c, node))
addSon(a, x) if n != nil: MessageOut(SymToStr(n.sym, isLocal=false, sectionDef))
suggestCall(c, a)
break
else:
nil
of nkDotExpr:
if cp == cpExact:
var obj = c.semExpr(c, n.sons[0])
suggestFieldAccess(c, obj)
break
else: nil
suggestEverything(c, n)
quit(0) quit(0)
proc suggestStmt*(c: PContext, n: PNode) = proc suggestStmt*(c: PContext, n: PNode) =

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
# Implements the dispatcher for the different parsers. ## Implements the dispatcher for the different parsers.
import import
strutils, llstream, ast, astalgo, idents, scanner, options, msgs, pnimsyn, strutils, llstream, ast, astalgo, idents, scanner, options, msgs, pnimsyn,

View file

@ -57,10 +57,12 @@ type
wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM,
wCompileToOC, wCompileToOC,
wPretty, wPretty,
wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wJs, wOC, wDoc, wGenDepend, wDump, wCheck, wParse, wScan, wJs, wOC,
wRst2html, wRst2tex, wI, wRst2html, wRst2tex, wI,
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wThreads, wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wThreads,
wRecursivePath, wSuggest, wTrack wRecursivePath,
wStdout,
wIdeTools, wSuggest, wTrack, wDef, wContext
TSpecialWords* = set[TSpecialWord] TSpecialWords* = set[TSpecialWord]
@ -106,10 +108,12 @@ const
"nomain", "subschar", "acyclic", "index", "nomain", "subschar", "acyclic", "index",
"compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm", "compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm",
"compiletooc", "compiletooc",
"pretty", "doc", "gendepend", "listdef", "check", "parse", "scan", "pretty", "doc", "gendepend", "dump", "check", "parse", "scan",
"js", "oc", "rst2html", "rst2tex", "i", "js", "oc", "rst2html", "rst2tex", "i",
"write", "putenv", "prependenv", "appendenv", "threadvar", "emit", "write", "putenv", "prependenv", "appendenv", "threadvar", "emit",
"threads", "recursivepath", "suggest", "track"] "threads", "recursivepath",
"stdout",
"idetools", "suggest", "track", "def", "context"]
proc whichKeyword*(id: PIdent): TSpecialWord proc whichKeyword*(id: PIdent): TSpecialWord
proc whichKeyword*(id: String): TSpecialWord proc whichKeyword*(id: String): TSpecialWord

View file

@ -1,5 +1,4 @@
- 'suggest' needs tweaking: end-token; testing! - 'nimrod def': does not always work
- stdout support for doc, pretty
- BUG: gcleak.nim - BUG: gcleak.nim
- thread support: threadvar on Windows seems broken; - thread support: threadvar on Windows seems broken;