Merge branch 'master' into newparser

This commit is contained in:
Araq
2013-05-04 19:10:12 +02:00
31 changed files with 277 additions and 63 deletions

View File

@@ -60,7 +60,7 @@ iterator chosen(packages: PStringTable): string =
proc addBabelPath(p: string, info: TLineInfo) =
if not contains(options.searchPaths, p):
Message(info, hintPath, p)
if gVerbosity >= 1: Message(info, hintPath, p)
lists.PrependStr(options.lazyPaths, p)
proc addPathWithNimFiles(p: string, info: TLineInfo) =
@@ -83,7 +83,7 @@ proc addPathRec(dir: string, info: TLineInfo) =
if k == pcDir and p[pos] != '.':
addPackage(packages, p)
for p in packages.chosen:
addPathWithNimFiles(p, info)
addBabelPath(p, info)
proc babelPath*(path: string, info: TLineInfo) =
addPathRec(path, info)

View File

@@ -11,7 +11,7 @@
## is needed for incremental compilation.
import
ast, astalgo, ropes, options, strutils, lexbase, msgs, cgendata, rodutils,
ast, astalgo, ropes, options, strutils, nimlexbase, msgs, cgendata, rodutils,
intsets, platform, llstream
# Careful! Section marks need to contain a tabulator so that they cannot
@@ -119,8 +119,8 @@ proc skipWhite(L: var TBaseLexer) =
var pos = L.bufpos
while true:
case ^pos
of CR: pos = lexbase.HandleCR(L, pos)
of LF: pos = lexbase.HandleLF(L, pos)
of CR: pos = nimlexbase.HandleCR(L, pos)
of LF: pos = nimlexbase.HandleLF(L, pos)
of ' ': inc pos
else: break
L.bufpos = pos
@@ -129,8 +129,8 @@ proc skipUntilCmd(L: var TBaseLexer) =
var pos = L.bufpos
while true:
case ^pos
of CR: pos = lexbase.HandleCR(L, pos)
of LF: pos = lexbase.HandleLF(L, pos)
of CR: pos = nimlexbase.HandleCR(L, pos)
of LF: pos = nimlexbase.HandleLF(L, pos)
of '\0': break
of '/':
if ^(pos+1) == '*' and ^(pos+2) == '\t':
@@ -153,11 +153,11 @@ when false:
while true:
case buf[pos]
of CR:
pos = lexbase.HandleCR(L, pos)
pos = nimlexbase.HandleCR(L, pos)
buf = L.buf
result.data.add(tnl)
of LF:
pos = lexbase.HandleLF(L, pos)
pos = nimlexbase.HandleLF(L, pos)
buf = L.buf
result.data.add(tnl)
of '\0':
@@ -179,11 +179,11 @@ proc readVerbatimSection(L: var TBaseLexer): PRope =
while true:
case buf[pos]
of CR:
pos = lexbase.HandleCR(L, pos)
pos = nimlexbase.HandleCR(L, pos)
buf = L.buf
r.add(tnl)
of LF:
pos = lexbase.HandleLF(L, pos)
pos = nimlexbase.HandleLF(L, pos)
buf = L.buf
r.add(tnl)
of '\0':

View File

@@ -197,8 +197,11 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
else: InvalidCmdLineOption(passCmd1, switch, info)
proc processPath(path: string, notRelativeToProj = false): string =
let p = if notRelativeToProj or os.isAbsolute(path) or '$' in path: path
else: options.gProjectPath / path
let p = if notRelativeToProj or os.isAbsolute(path) or
'$' in path or path[0] == '.':
path
else:
options.gProjectPath / path
result = UnixToNativePath(p % ["nimrod", getPrefixDir(), "lib", libpath,
"home", removeTrailingDirSep(os.getHomeDir()),
"projectname", options.gProjectName,

View File

@@ -10,7 +10,7 @@
# This module handles the conditional symbols.
import
ast, astalgo, msgs, hashes, platform, strutils, idents
ast, astalgo, hashes, platform, strutils, idents
var gSymbols*: TStrTable
@@ -35,14 +35,12 @@ proc isDefined*(symbol: PIdent): bool =
proc isDefined*(symbol: string): bool =
result = isDefined(getIdent(symbol))
proc ListSymbols*() =
iterator definedSymbolNames*: string =
var it: TTabIter
var s = InitTabIter(it, gSymbols)
OutWriteln("-- List of currently defined symbols --")
while s != nil:
if s.position == 1: OutWriteln(s.name.s)
while s != nil:
if s.position == 1: yield s.name.s
s = nextIter(it, gSymbols)
OutWriteln("-- End of list --")
proc countDefinedSymbols*(): int =
var it: TTabIter

View File

@@ -1099,7 +1099,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[2], {efLValue})
if isSpecial(result): return
addSon(a, result)
result = emptyNode
result = a
of mNAddMultiple:
result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return
@@ -1107,7 +1107,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[2], {efLValue})
if isSpecial(result): return
for i in countup(0, sonsLen(result) - 1): addSon(a, result.sons[i])
result = emptyNode
result = a
of mNDel:
result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return

View File

@@ -16,7 +16,7 @@
# DOS or Macintosh text files, even when it is not the native format.
import
hashes, options, msgs, strutils, platform, idents, lexbase, llstream,
hashes, options, msgs, strutils, platform, idents, nimlexbase, llstream,
wordrecg
const
@@ -508,10 +508,10 @@ proc HandleCRLF(L: var TLexer, pos: int): int =
case L.buf[pos]
of CR:
registerLine()
result = lexbase.HandleCR(L, pos)
result = nimlexbase.HandleCR(L, pos)
of LF:
registerLine()
result = lexbase.HandleLF(L, pos)
result = nimlexbase.HandleLF(L, pos)
else: result = pos
proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
@@ -537,7 +537,7 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
pos = HandleCRLF(L, pos)
buf = L.buf
add(tok.literal, tnl)
of lexbase.EndOfFile:
of nimlexbase.EndOfFile:
var line2 = L.linenumber
L.LineNumber = line
lexMessagePos(L, errClosingTripleQuoteExpected, L.lineStart)
@@ -559,7 +559,7 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
else:
inc(pos) # skip '"'
break
elif c in {CR, LF, lexbase.EndOfFile}:
elif c in {CR, LF, nimlexbase.EndOfFile}:
lexMessage(L, errClosingQuoteExpected)
break
elif (c == '\\') and not rawMode:
@@ -640,7 +640,7 @@ proc scanComment(L: var TLexer, tok: var TToken) =
var col = getColNumber(L, pos)
while true:
var lastBackslash = -1
while buf[pos] notin {CR, LF, lexbase.EndOfFile}:
while buf[pos] notin {CR, LF, nimlexbase.EndOfFile}:
if buf[pos] == '\\': lastBackslash = pos+1
add(tok.literal, buf[pos])
inc(pos)
@@ -648,7 +648,7 @@ proc scanComment(L: var TLexer, tok: var TToken) =
# a backslash is a continuation character if only followed by spaces
# plus a newline:
while buf[lastBackslash] == ' ': inc(lastBackslash)
if buf[lastBackslash] notin {CR, LF, lexbase.EndOfFile}:
if buf[lastBackslash] notin {CR, LF, nimlexbase.EndOfFile}:
# false positive:
lastBackslash = -1
@@ -795,7 +795,7 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
else:
if c in OpChars:
getOperator(L, tok)
elif c == lexbase.EndOfFile:
elif c == nimlexbase.EndOfFile:
tok.toktype = tkEof
tok.indent = 0
else:

View File

@@ -14,7 +14,7 @@ import
llstream, strutils, ast, astalgo, lexer, syntaxes, renderer, options, msgs,
os, lists, condsyms, rodread, rodwrite, ropes, trees, times,
wordrecg, sem, semdata, idents, passes, docgen, extccomp,
cgen, jsgen, cgendata,
cgen, jsgen, cgendata, json, nversion,
platform, nimconf, importer, passaux, depends, evals, types, idgen,
tables, docgen2, service, magicsys, parser, crc, ccgutils
@@ -392,6 +392,15 @@ proc wantMainModule =
gProjectMainIdx = addFileExt(gProjectFull, nimExt).fileInfoIdx
proc requireMainModuleOption =
if optMainModule.len == 0:
Fatal(gCmdLineInfo, errMainModuleMustBeSpecified)
else:
gProjectName = optMainModule
gProjectFull = gProjectPath / gProjectName
gProjectMainIdx = addFileExt(gProjectFull, nimExt).fileInfoIdx
proc resetMemory =
resetCompilationLists()
ccgutils.resetCaches()
@@ -529,9 +538,30 @@ proc MainCommand =
wantMainModule()
CommandGenDepend()
of "dump":
gCmd = cmdDump
condsyms.ListSymbols()
for it in iterSearchPath(searchPaths): MsgWriteln(it)
gcmd = cmdDump
if getconfigvar("dump.format") == "json":
requireMainModuleOption()
var definedSymbols = newJArray()
for s in definedSymbolNames(): definedSymbols.elems.add(%s)
var libpaths = newJArray()
for dir in itersearchpath(searchpaths): libpaths.elems.add(%dir)
var dumpdata = % [
(key: "version", val: %VersionAsString),
(key: "project_path", val: %gProjectFull),
(key: "defined_symbols", val: definedSymbols),
(key: "lib_paths", val: libpaths)
]
outWriteLn($dumpdata)
else:
outWriteLn("-- list of currently defined symbols --")
for s in definedSymbolNames(): outWriteLn(s)
outWriteLn("-- end of list --")
for it in iterSearchPath(searchpaths): msgWriteLn(it)
of "check":
gCmd = cmdCheck
wantMainModule()
@@ -568,7 +598,7 @@ proc MainCommand =
else:
rawMessage(errInvalidCommandX, command)
if msgs.gErrorCounter == 0 and gCmd notin {cmdInterpret, cmdRun}:
if msgs.gErrorCounter == 0 and gCmd notin {cmdInterpret, cmdRun, cmdDump}:
rawMessage(hintSuccessX, [$gLinesCompiled,
formatFloat(epochTime() - gLastCmdTime, ffDecimal, 3),
formatSize(getTotalMem())])

View File

@@ -83,7 +83,9 @@ type
errInvalidCommandX, errXOnlyAtModuleScope,
errXNeedsParamObjectType,
errTemplateInstantiationTooNested, errInstantiationFrom,
errInvalidIndexValueForTuple, errCommandExpectsFilename, errXExpected,
errInvalidIndexValueForTuple, errCommandExpectsFilename,
errMainModuleMustBeSpecified,
errXExpected,
errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError,
errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile,
errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitely,
@@ -301,6 +303,7 @@ const
errInstantiationFrom: "instantiation from here",
errInvalidIndexValueForTuple: "invalid index value for tuple subscript",
errCommandExpectsFilename: "command expects a filename argument",
errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file",
errXExpected: "\'$1\' expected",
errInvalidSectionStart: "invalid section start",
errGridTableNotImplemented: "grid table is not implemented",

View File

@@ -98,13 +98,13 @@ proc ToTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode =
result.typ = settype
result.info = info
e = 0
while e < high(s) * elemSize:
while e < len(s) * elemSize:
if bitSetIn(s, e):
a = e
b = e
while true:
Inc(b)
if (b > high(s) * elemSize) or not bitSetIn(s, b): break
if (b >= len(s) * elemSize) or not bitSetIn(s, b): break
Dec(b)
if a == b:
addSon(result, newIntTypeNode(nkIntLit, a + first, elemType))

View File

@@ -100,14 +100,14 @@ var
searchPaths*, lazyPaths*: TLinkedList
outFile*: string = ""
headerFile*: string = ""
gVerbosity*: int # how verbose the compiler is
gVerbosity* = 1 # how verbose the compiler is
gNumberOfProcessors*: int # number of processors
gWholeProject*: bool # for 'doc2': output any dependency
gEvalExpr* = "" # expression for idetools --eval
gLastCmdTime*: float # when caas is enabled, we measure each command
gListFullPaths*: bool
isServing*: bool = false
proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools}
proc usesNativeGC*(): bool {.inline.} = gSelectedGC >= gcRefc

View File

@@ -12,7 +12,7 @@
# standard library.
import
llstream, nhashes, strutils, lexbase
llstream, nhashes, strutils, nimlexbase
type
TCfgEventKind* = enum

View File

@@ -23,9 +23,10 @@ proc expectIntLit(c: PContext, n: PNode): int =
proc semInstantiationInfo(c: PContext, n: PNode): PNode =
result = newNodeIT(nkPar, n.info, n.typ)
let idx = expectIntLit(c, n.sons[1])
let useFullPaths = expectIntLit(c, n.sons[2])
let info = getInfoContext(idx)
var filename = newNodeIT(nkStrLit, n.info, getSysType(tyString))
filename.strVal = ToFilename(info)
filename.strVal = if useFullPaths != 0: info.toFullPath else: info.ToFilename
var line = newNodeIT(nkIntLit, n.info, getSysType(tyInt))
line.intVal = ToLinenumber(info)
result.add(filename)

View File

@@ -73,6 +73,9 @@ proc serve*(action: proc (){.nimcall.}) =
var line = stdin.readLine.string
if line == "quit": quit()
execute line
echo ""
FlushFile(stdout)
of "tcp", "":
var server = Socket()
let p = getConfigVar("server.port")

View File

@@ -55,7 +55,6 @@ path="$lib/pure/unidecode"
@end
# additional options always passed to the compiler:
--verbosity: "1"
--parallel_build: "0" # 0 to auto-detect number of processors
hint[LineTooLong]=off

View File

@@ -130,12 +130,14 @@ proc `==`*(a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.}
proc len*(n: PNimrodNode): int {.magic: "NLen".}
## returns the number of children of `n`.
proc add*(father, child: PNimrodNode) {.magic: "NAdd".}
## adds the `child` to the `father` node
proc add*(father, child: PNimrodNode): PNimrodNode {.magic: "NAdd", discardable.}
## Adds the `child` to the `father` node. Returns the
## father node so that calls can be nested.
proc add*(father: PNimrodNode, children: varargs[PNimrodNode]) {.
magic: "NAddMultiple".}
## adds each child of `children` to the `father` node
proc add*(father: PNimrodNode, children: varargs[PNimrodNode]): PNimrodNode {.
magic: "NAddMultiple", discardable.}
## Adds each child of `children` to the `father` node.
## Returns the `father` node so that calls can be nested.
proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel".}
## deletes `n` children of `father` starting at index `idx`.

View File

@@ -34,7 +34,10 @@ const
proc getIdent(e: PNimrodNode): string {.compileTime.} =
case e.kind
of nnkIdent: result = normalize($e.ident)
of nnkAccQuoted: result = getIdent(e[0])
of nnkAccQuoted:
result = getIdent(e[0])
for i in 1 .. e.len-1:
result.add getIdent(e[i])
else: error("cannot extract identifier from node: " & toStrLit(e).strVal)
proc delete[T](s: var seq[T], attr: T): bool =
@@ -478,4 +481,5 @@ macro `var`*(e: expr): expr {.immediate.} =
when isMainModule:
var nim = "Nimrod"
echo h1(a(href="http://nimrod-code.org", nim))
echo form(action="test", `accept-charset` = "Content-Type")

View File

@@ -106,6 +106,12 @@ proc write*(s: PStream, x: string) =
## terminating zero is written.
writeData(s, cstring(x), x.len)
proc writeln*(s: PStream, args: varargs[string, `$`]) =
## writes one or more strings to the the stream `s` followed
## by a new line. No length field or terminating zero is written.
for str in args: write(s, str)
write(s, "\n")
proc read[T](s: PStream, result: var T) =
## generic read procedure. Reads `result` from the stream `s`.
if readData(s, addr(result), sizeof(T)) != sizeof(T):

View File

@@ -2407,8 +2407,8 @@ proc astToStr*[T](x: T): string {.magic: "AstToStr", noSideEffect.}
## converts the AST of `x` into a string representation. This is very useful
## for debugging.
proc InstantiationInfo*(index = -1): tuple[filename: string, line: int] {.
magic: "InstantiationInfo", noSideEffect.}
proc InstantiationInfo*(index = -1, fullPaths = false): tuple[
filename: string, line: int] {. magic: "InstantiationInfo", noSideEffect.}
## provides access to the compiler's instantiation stack line information.
##
## This proc is mostly useful for meta programming (eg. ``assert`` template)
@@ -2438,6 +2438,9 @@ proc InstantiationInfo*(index = -1): tuple[filename: string, line: int] {.
## testException(EInvalidIndex, tester(1))
## # --> Test failure at example.nim:20 with 'tester(1)'
template CurrentSourcePath*: string = InstantiationInfo(-1, true).filename
## returns the full file-system path of the current source
proc raiseAssert*(msg: string) {.noinline.} =
raise newException(EAssertionFailed, msg)

View File

@@ -0,0 +1,7 @@
main.nim
> c
SuccessX
> c
! Processing
SuccessX

View File

@@ -0,0 +1,9 @@
main.nim
> c
SuccessX
> idetools --track:main.nim,5,18 --def main.nim
strutils.toUpper
SuccessX
> idetools --track:main.nim,5,18 --def main.nim
strutils.toUpper
SuccessX

View File

@@ -0,0 +1,7 @@
main.nim
> idetools --track:main.nim,5,18 --def main.nim
strutils.toUpper
SuccessX
> c
SuccessX

3
tests/caas/imported.nim Normal file
View File

@@ -0,0 +1,3 @@
proc `+++`*(a,b: string): string =
return a & " " & b

7
tests/caas/main.nim Normal file
View File

@@ -0,0 +1,7 @@
import imported, strutils
proc main =
var t1 = "text"
var t2 = t1.toUpper
echo(t1 +++ t2)

86
tests/caasdriver.nim Normal file
View File

@@ -0,0 +1,86 @@
import osproc, streams, os, strutils, re
type
TNimrodSession* = object
nim: PProcess
proc dirname(path: string): string = path.splitPath()[0]
var
TesterDir = getAppDir()
NimrodBin = TesterDir / "../bin/nimrod"
proc startNimrodSession*(project: string): TNimrodSession =
result.nim = startProcess(NimrodBin,
workingDir = project.dirname,
args = ["serve", "--server.type:stdin", project])
proc doCommand*(session: var TNimrodSession, command: string): string =
session.nim.inputStream.write(command & "\n")
session.nim.inputStream.flush
result = ""
while true:
var line = TaintedString("")
if session.nim.outputStream.readLine(line):
if line.string == "": break
result.add(line.string & "\n")
else:
result = "FAILED TO EXECUTE: " & command & "\n" & result
break
proc close(session: var TNimrodSession) {.destructor.} =
session.nim.close
proc doScenario(script: string, output: PStream): bool =
result = true
var f = open(script)
var project = TaintedString("")
if f.readLine(project):
var
s = startNimrodSession(script.dirname / project.string)
tline = TaintedString("")
lastOutput = ""
ln = 1
while f.readLine(tline):
var line = tline.string
inc ln
if line.strip.len == 0: continue
if line.startsWith(">"):
lastOutput = s.doCommand(line.substr(1).strip)
output.writeln line, "\n", lastOutput
else:
var expectMatch = true
var pattern = line
if line.startsWith("!"):
pattern = line.substr(1).strip
expectMatch = false
var actualMatch = lastOutput.find(re(pattern)) != -1
if expectMatch == actualMatch:
output.writeln "SUCCESS ", line
else:
output.writeln "FAILURE ", line
result = false
iterator caasTestsRunner*(filter = ""): tuple[test, output: string,
status: bool] =
for scenario in os.walkFiles(TesterDir / "caas/*.txt"):
if filter.len > 0 and find(scenario, filter) == -1: continue
var outStream = newStringStream()
let r = doScenario(scenario, outStream)
yield (scenario, outStream.data, r)
when isMainModule:
var filter = ""
if paramCount() > 0: filter = paramStr(1)
for t, o, r in caasTestsRunner(filter):
echo t, "\n", o

View File

@@ -1,12 +1,14 @@
discard """
file: "tbug499771.nim"
output: "TSubRange: 5 from 1 to 10"
output: '''TSubRange: 5 from 1 to 10
true true true'''
"""
type TSubRange = range[1 .. 10]
type
TSubRange = range[1 .. 10]
TEnum = enum A, B, C
var sr: TSubRange = 5
echo("TSubRange: " & $sr & " from " & $low(TSubRange) & " to " &
$high(TSubRange))
const cset = {A} + {B}
echo A in cset, " ", B in cset, " ", C notin cset

View File

@@ -1,7 +0,0 @@
discard """
file: "tlenopenarray.nim"
output: "1"
"""
echo len([1_000_000]) #OUT 1

View File

@@ -0,0 +1,26 @@
discard """
output: "direct\nopenarray\nvarargs"
"""
proc withDirectType(args: string) =
echo "direct"
proc withDirectType[T](arg: T) =
echo "generic"
proc withOpenArray(args: openarray[string]) =
echo "openarray"
proc withOpenArray[T](arg: T) =
echo "generic"
proc withVarargs(args: varargs[string]) =
echo "varargs"
proc withVarargs[T](arg: T) =
echo "generic"
withDirectType "string"
withOpenArray "string"
withVarargs "string"

14
tests/run/tvarious1.nim Normal file
View File

@@ -0,0 +1,14 @@
discard """
file: "tlenopenarray.nim"
output: '''1
0'''
"""
echo len([1_000_000]) #OUT 1
type
TArray = array[0..3, int]
TVector = distinct array[0..3, int]
proc `[]`(v: TVector; idx: int): int = TArray(v)[idx]
var v: TVector
echo v[2]

View File

@@ -11,7 +11,7 @@
import
parseutils, strutils, pegs, os, osproc, streams, parsecfg, browsers, json,
marshal, cgi, parseopt
marshal, cgi, parseopt, caasdriver
const
cmdTemplate = r"nimrod cc --hints:on $# $#"
@@ -38,6 +38,7 @@ type
reExeNotFound,
reIgnored, # test is ignored
reSuccess # test was successful
TTarget = enum
targetC, targetCpp, targetObjC, targetJS
@@ -363,6 +364,10 @@ proc outputJSON(reject, compile, run: TResults) =
var s = pretty(doc)
writeFile(jsonFile, s)
proc runCaasTests(r: var TResults) =
for test, output, status in caasTestsRunner():
r.addResult(test, "", output, if status: reSuccess else: reOutputsDiffer)
proc main() =
os.putenv "NIMTEST_NO_COLOR", "1"
os.putenv "NIMTEST_OUTPUT_LVL", "PRINT_FAILURES"
@@ -404,6 +409,7 @@ proc main() =
writeResults(runJson, r)
of "special":
runSpecialTests(r, p.cmdLineRest.string)
runCaasTests(r)
writeResults(runJson, r)
of "rodfiles":
runRodFiles(r, p.cmdLineRest.string)

View File

@@ -29,6 +29,8 @@ Library Additions
- Added ``system.unsafeNew`` to support hacky variable length objects.
- ``system.fields`` and ``system.fieldPairs`` support ``object`` too; they
used to only support tuples.
- Added ``system.CurrentSourcePath`` returning the full file-system path of
the current source file
Changes affecting backwards compatibility