--stdout support; idetools implemented
This commit is contained in:
parent
0a4498bd6b
commit
f8dd74a073
17 changed files with 188 additions and 112 deletions
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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) =
|
||||||
|
|
|
||||||
11
rod/main.nim
11
rod/main.nim
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 =
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
131
rod/suggest.nim
131
rod/suggest.nim
|
|
@ -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) =
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
3
todo.txt
3
todo.txt
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue