--stdout support; idetools implemented

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

View File

@@ -1,22 +1,28 @@
Advanced commands:
//compileToC, cc compile project with C code generator
//compileToOC, oc compile project to Objective C code
//rst2html converts a reStructuredText file to HTML
//rst2tex converts a reStructuredText file to TeX
//run run the project (with Tiny C backend; Linux only!)
//rst2html convert a reStructuredText file to HTML
//rst2tex convert a reStructuredText file to TeX
//run run the project (with Tiny C backend; buggy!)
//pretty pretty print the inputfile
//genDepend generate a DOT file containing the
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
//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:
-o, --out:FILE set the output filename
--stdout output to stdout
-w, --warnings:on|off turn all warnings on|off
--warning[X]:on|off turn specific warning X on|off
--hints:on|off turn all hints 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
--noLinking compile but do not link
--noMain do not generate a main procedure
@@ -35,10 +41,11 @@ Advanced options:
--skipCfg do not read the general configuration file
--skipProjCfg do not read the project's configuration file
--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
--listCmd list the commands used to execute external programs
--parallelBuild=0|1|... perform a parallel build
value = number of processors (0 for auto-detect)
--verbosity:0|1|2|3 set Nimrod's verbosity level (0 is default)
-v, --version show detailed version information

View File

@@ -1,16 +1,15 @@
Usage::
nimrod command [options] inputfile [arguments]
nimrod command [options] [projectfile] [arguments]
Command:
//compile, c compile project with default code generator (C)
//doc generate the documentation for inputfile
//i start Nimrod in interactive mode (limited)
//compile, c compile project with default code generator (C)
//doc generate the documentation for inputfile
//i start Nimrod in interactive mode (limited)
Arguments:
arguments are passed to the program being run (if --run option is selected)
Options:
-p, --path:PATH add path to search paths
-o, --out:FILE set the output filename
-d, --define:SYMBOL define a conditional symbol
-u, --undef:SYMBOL undefine a conditional symbol
-f, --forceBuild force rebuilding of all modules
@@ -33,3 +32,4 @@ Options:
-r, --run run the compiled program with given arguments
--advanced show advanced command line switches
-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)
Options:
-p, --path:PATH add path to search paths
-o, --out:FILE set the output filename
-d, --define:SYMBOL define a conditional symbol
-u, --undef:SYMBOL undefine a conditional symbol
-f, --forceBuild force rebuilding of all modules
@@ -70,17 +69,22 @@ Options:
Advanced commands:
compileToC, cc compile project with C code generator
compileToOC, oc compile project to Objective C code
rst2html converts a reStructuredText file to HTML
rst2tex converts a reStructuredText file to TeX
rst2html convert a reStructuredText file to HTML
rst2tex convert a reStructuredText file to TeX
run run the project (with Tiny C backend; buggy!)
pretty pretty print the inputfile
genDepend generate a DOT file containing the
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
suggest list all possible symbols at position;
use with --track option
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:
-o, --out:FILE set the output filename
--stdout output to stdout
-w, --warnings:on|off turn all warnings on|off
--warning[X]:on|off turn specific warning X on|off
--hints:on|off turn all hints on|off
@@ -104,9 +108,8 @@ Advanced options:
--skipCfg do not read the general configuration file
--skipProjCfg do not read the project's configuration file
--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
--track:FILE,LINE,COLUMN track a file position for 'suggest'
--listCmd list the commands used to execute external programs
--parallelBuild=0|1|... perform a parallel build
value = number of processors (0 for auto-detect)
@@ -415,9 +418,6 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
excl(gGlobalOptions, optGenGuiApp)
defineSymbol("library")
else: LocalError(info, errGuiConsoleOrLibExpectedButXFound, arg)
of wListDef:
expectNoArg(switch, arg, pass, info)
if pass in {passCmd2, passPP}: condsyms.listSymbols()
of wPassC, wT:
expectArg(switch, arg, pass, info)
if pass in {passCmd2, passPP}: extccomp.addCompileOption(arg)
@@ -496,6 +496,18 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
of wTrack:
expectArg(switch, arg, pass, 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:
if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
else: InvalidCmdLineOption(pass, switch, info)

View File

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

View File

@@ -857,6 +857,13 @@ proc generateIndex(d: PDoc) =
sortIndex(d.theIndex)
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) =
var ast = parseFile(addFileExt(filename, nimExt))
if ast == nil: return
@@ -864,7 +871,7 @@ proc CommandDoc(filename: string) =
initIndexFile(d)
d.hasToc = true
generateDoc(d, ast)
writeRope(genOutFile(d), getOutFile(filename, HtmlExt))
writeOutput(d, filename, HtmlExt)
generateIndex(d)
proc CommandRstAux(filename, outExt: string) =
@@ -873,8 +880,7 @@ proc CommandRstAux(filename, outExt: string) =
initIndexFile(d)
var rst = rstParse(readFile(filen), false, filen, 0, 1, d.hasToc)
d.modDesc = renderRstToOut(d, rst)
var code = genOutFile(d)
writeRope(code, getOutFile(filename, outExt))
writeOutput(d, filename, outExt)
generateIndex(d)
proc CommandRst2Html(filename: string) =

View File

@@ -251,9 +251,10 @@ proc MainCommand(cmd, filename: string) =
gCmd = cmdGenDepend
wantFile(filename)
CommandGenDepend(filename)
of wListDef:
gCmd = cmdListDef
of wDump:
gCmd = cmdDump
condsyms.ListSymbols()
for it in iterSearchPath(): MessageOut(it)
of wCheck:
gCmd = cmdCheck
wantFile(filename)
@@ -270,9 +271,9 @@ proc MainCommand(cmd, filename: string) =
of wI:
gCmd = cmdInteractive
CommandInteractive()
of wSuggest:
gCmd = cmdSuggest
of wIdeTools:
gCmd = cmdIdeTools
wantFile(filename)
CommandSuggest(filename)
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
optSkipProjConfigFile, # skip the project's config file
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]
TCommands* = enum # Nimrod's commands
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
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)
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
cmdRst2tex, # convert a reStructuredText file to TeX
cmdInteractive, # start interactive session
@@ -121,8 +127,7 @@ proc getOutFile*(filename, ext: string): string =
else: result = changeFileExt(filename, ext)
proc addImplicitMod(filename: string) =
var length: int
length = len(gImplicitMods)
var length = len(gImplicitMods)
setlen(gImplicitMods, length + 1)
gImplicitMods[length] = filename
@@ -166,15 +171,19 @@ proc completeGeneratedFilePath(f: string, createSubDir: bool = true): string =
quit(1)
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 =
if ExistsFile(f):
result = f
else:
var it = PStrEntry(SearchPaths.head)
while it != nil:
result = JoinPath(it.data, f)
if ExistsFile(result): return
it = PStrEntry(it.Next)
for it in iterSearchPath():
result = JoinPath(it, f)
if ExistsFile(result): return
result = ""
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)
else: nil
gcoms(g)
if open(f, filename, fmWrite):
if optStdout in gGlobalOptions:
write(stdout, g.buf)
elif open(f, filename, fmWrite):
write(f, g.buf)
close(f)
else:
rawMessage(errCannotOpenFile, filename)
proc initTokRender(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) =
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 prepend(a: var PRope, b: PRope) = a = con(b, a)
proc WriteRopeRec(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) =
proc writeRope*(f: var tfile, c: PRope) =
var stack = @[c]
while len(stack) > 0:
var it = pop(stack)
@@ -296,7 +288,7 @@ proc newWriteRopeRec(f: var tfile, c: PRope) =
proc WriteRope(head: PRope, filename: string) =
var f: tfile # we use a textfile for automatic buffer handling
if open(f, filename, fmWrite):
if head != nil: newWriteRopeRec(f, head)
if head != nil: WriteRope(f, head)
close(f)
else:
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 =
result = n
if gCmd == cmdSuggest:
if gCmd == cmdIdeTools:
suggestExpr(c, n)
if nfSem in n.flags: return
case n.kind # atoms:

View File

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

View File

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

View File

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

View File

@@ -9,13 +9,17 @@
## 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
sep = '\t'
sectionSuggest = "sug"
sectionDef = "def"
sectionContext = "con"
proc SymToStr(s: PSym, isLocal: bool): string =
result = ""
proc SymToStr(s: PSym, isLocal: bool, section: string): string =
result = section
result.add(sep)
result.add($s.kind)
result.add(sep)
if not isLocal:
@@ -38,13 +42,13 @@ proc filterSym(s: PSym): bool {.inline.} =
proc suggestField(s: PSym) =
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 it in items(c.tab.stack[i]):
if cond:
MessageOut(SymToStr(it, isLocal = i > ModuleTablePos))
MessageOut(SymToStr(it, isLocal = i > ModuleTablePos, section))
proc suggestSymList(list: PNode) =
for i in countup(0, sonsLen(list) - 1):
@@ -86,7 +90,8 @@ proc argsFit(c: PContext, candidate: PSym, n: PNode): bool =
result = false
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.} =
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) =
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) =
wholeSymTab(filterSym(it))
wholeSymTab(filterSym(it), sectionSuggest)
proc suggestFieldAccess(c: PContext, n: PNode) =
# 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:
# all symbols accessible, because we are in the current module:
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:
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:
# fallback:
suggestEverything(c, n)
@@ -139,55 +146,89 @@ proc suggestFieldAccess(c: PContext, n: PNode) =
# fallback:
suggestEverything(c, n)
proc interestingNode(n: PNode): bool {.inline.} =
result = n.kind == nkDotExpr
proc findClosestNode(n: PNode): PNode =
proc findClosestDot(n: PNode): PNode =
if msgs.inCheckpoint(n.info) == cpExact:
result = n
elif n.kind notin {nkNone..nkNilLit}:
for i in 0.. <sonsLen(n):
if interestingNode(n.sons[i]):
result = findClosestNode(n.sons[i])
if n.sons[i].kind == nkDotExpr:
result = findClosestDot(n.sons[i])
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
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) =
var cp = msgs.inCheckpoint(node.info)
if cp == cpNone: return
# HACK: This keeps semExpr() from coming here recursively:
if recursiveCheck > 0: return
inc(recursiveCheck)
var n = findClosestNode(node)
if n == nil: n = node
else: cp = msgs.inCheckpoint(n.info)
block:
case n.kind
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
nkCallStrLit, nkMacroStmt:
when false:
# this provides "context information", not "type suggestion":
var a = copyNode(n)
var x = c.semExpr(c, n.sons[0])
if x.kind == nkEmpty or x.typ == nil: x = n.sons[0]
if optSuggest in gGlobalOptions:
var n = findClosestDot(node)
if n == nil: n = node
else: cp = cpExact
if n.kind == nkDotExpr and cp == cpExact:
var obj = safeSemExpr(c, n.sons[0])
suggestFieldAccess(c, obj)
else:
suggestEverything(c, n)
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)
for i in 1..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, 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)
suggestCall(c, a)
if optDef in gGlobalOptions:
var n = findClosestSym(fuzzySemCheck(c, node))
if n != nil: MessageOut(SymToStr(n.sym, isLocal=false, sectionDef))
quit(0)
proc suggestStmt*(c: PContext, n: PNode) =

View File

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

View File

@@ -57,10 +57,12 @@ type
wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM,
wCompileToOC,
wPretty,
wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wJs, wOC,
wDoc, wGenDepend, wDump, wCheck, wParse, wScan, wJs, wOC,
wRst2html, wRst2tex, wI,
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wThreads,
wRecursivePath, wSuggest, wTrack
wRecursivePath,
wStdout,
wIdeTools, wSuggest, wTrack, wDef, wContext
TSpecialWords* = set[TSpecialWord]
@@ -106,10 +108,12 @@ const
"nomain", "subschar", "acyclic", "index",
"compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm",
"compiletooc",
"pretty", "doc", "gendepend", "listdef", "check", "parse", "scan",
"pretty", "doc", "gendepend", "dump", "check", "parse", "scan",
"js", "oc", "rst2html", "rst2tex", "i",
"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: String): TSpecialWord

View File

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