summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/babelcmd.nim4
-rw-r--r--compiler/ccgmerge.nim18
-rw-r--r--compiler/commands.nim7
-rw-r--r--compiler/condsyms.nim10
-rw-r--r--compiler/evals.nim4
-rw-r--r--compiler/lexer.nim16
-rw-r--r--compiler/main.nim40
-rw-r--r--compiler/msgs.nim5
-rw-r--r--compiler/nimlexbase.nim (renamed from compiler/lexbase.nim)0
-rw-r--r--compiler/nimsets.nim4
-rw-r--r--compiler/options.nim4
-rw-r--r--compiler/parsecfg.nim2
-rw-r--r--compiler/semmagic.nim3
-rw-r--r--compiler/service.nim3
-rw-r--r--config/nimrod.cfg1
-rw-r--r--lib/core/macros.nim14
-rw-r--r--lib/pure/htmlgen.nim6
-rw-r--r--lib/pure/streams.nim6
-rw-r--r--lib/system.nim7
-rw-r--r--tests/caas/basic-recompile.txt7
-rw-r--r--tests/caas/compile-then-def.txt9
-rw-r--r--tests/caas/def-then-compile.txt7
-rw-r--r--tests/caas/imported.nim3
-rw-r--r--tests/caas/main.nim7
-rw-r--r--tests/caasdriver.nim86
-rw-r--r--tests/run/tbug499771.nim12
-rw-r--r--tests/run/tlenopenarray.nim7
-rw-r--r--tests/run/tvarargs_vs_generic.nim26
-rw-r--r--tests/run/tvarious1.nim14
-rw-r--r--tests/tester.nim8
-rw-r--r--web/news.txt2
31 files changed, 278 insertions, 64 deletions
diff --git a/compiler/babelcmd.nim b/compiler/babelcmd.nim
index 956c6a6ae..b67a26040 100644
--- a/compiler/babelcmd.nim
+++ b/compiler/babelcmd.nim
@@ -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)
diff --git a/compiler/ccgmerge.nim b/compiler/ccgmerge.nim
index 751e507e9..c6c294b97 100644
--- a/compiler/ccgmerge.nim
+++ b/compiler/ccgmerge.nim
@@ -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':
diff --git a/compiler/commands.nim b/compiler/commands.nim
index 8b03dfec4..27da03bbe 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -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,
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index 17366f6e9..be6cb9875 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -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
diff --git a/compiler/evals.nim b/compiler/evals.nim
index 2a9fae5f0..3f5b7887a 100644
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -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 
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index 93649c888..6660ff65c 100644
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -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:
diff --git a/compiler/main.nim b/compiler/main.nim
index b5186ba6c..46ef65e81 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -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())])
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 4099d7622..e11e47bac 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -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", 
diff --git a/compiler/lexbase.nim b/compiler/nimlexbase.nim
index 6d45a825a..6d45a825a 100644
--- a/compiler/lexbase.nim
+++ b/compiler/nimlexbase.nim
diff --git a/compiler/nimsets.nim b/compiler/nimsets.nim
index 118046283..93bccae24 100644
--- a/compiler/nimsets.nim
+++ b/compiler/nimsets.nim
@@ -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))
diff --git a/compiler/options.nim b/compiler/options.nim
index ca20d7c83..08a5ba010 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -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
 
diff --git a/compiler/parsecfg.nim b/compiler/parsecfg.nim
index 965160bd5..e0d1afff1 100644
--- a/compiler/parsecfg.nim
+++ b/compiler/parsecfg.nim
@@ -12,7 +12,7 @@
 # standard library.
 
 import 
-  llstream, nhashes, strutils, lexbase
+  llstream, nhashes, strutils, nimlexbase
 
 type 
   TCfgEventKind* = enum 
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 31eb7a9d5..058964fc8 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -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)
diff --git a/compiler/service.nim b/compiler/service.nim
index e2de6e5a0..b3c7fbc83 100644
--- a/compiler/service.nim
+++ b/compiler/service.nim
@@ -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")
diff --git a/config/nimrod.cfg b/config/nimrod.cfg
index 159cbe1bd..d9075a20f 100644
--- a/config/nimrod.cfg
+++ b/config/nimrod.cfg
@@ -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
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 4598fa9ea..949719316 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -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: PNimrodNode, children: varargs[PNimrodNode]) {.
-  magic: "NAddMultiple".}
-  ## adds each child of `children` 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]): 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`.
diff --git a/lib/pure/htmlgen.nim b/lib/pure/htmlgen.nim
index 75af2c892..8d90f8589 100644
--- a/lib/pure/htmlgen.nim
+++ b/lib/pure/htmlgen.nim
@@ -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")
 
diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim
index 4a196127c..764471b78 100644
--- a/lib/pure/streams.nim
+++ b/lib/pure/streams.nim
@@ -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):
diff --git a/lib/system.nim b/lib/system.nim
index 80e38ad7b..5dafd6e13 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -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)
 
diff --git a/tests/caas/basic-recompile.txt b/tests/caas/basic-recompile.txt
new file mode 100644
index 000000000..9c943fe88
--- /dev/null
+++ b/tests/caas/basic-recompile.txt
@@ -0,0 +1,7 @@
+main.nim
+> c
+SuccessX
+> c
+! Processing
+SuccessX
+
diff --git a/tests/caas/compile-then-def.txt b/tests/caas/compile-then-def.txt
new file mode 100644
index 000000000..a5080c50d
--- /dev/null
+++ b/tests/caas/compile-then-def.txt
@@ -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
diff --git a/tests/caas/def-then-compile.txt b/tests/caas/def-then-compile.txt
new file mode 100644
index 000000000..efa4dcbb3
--- /dev/null
+++ b/tests/caas/def-then-compile.txt
@@ -0,0 +1,7 @@
+main.nim
+> idetools --track:main.nim,5,18 --def main.nim
+strutils.toUpper
+SuccessX
+> c
+SuccessX
+
diff --git a/tests/caas/imported.nim b/tests/caas/imported.nim
new file mode 100644
index 000000000..a4bc5c0e6
--- /dev/null
+++ b/tests/caas/imported.nim
@@ -0,0 +1,3 @@
+proc `+++`*(a,b: string): string =
+  return a & "  " & b
+
diff --git a/tests/caas/main.nim b/tests/caas/main.nim
new file mode 100644
index 000000000..fafeff93b
--- /dev/null
+++ b/tests/caas/main.nim
@@ -0,0 +1,7 @@
+import imported, strutils
+
+proc main =
+  var t1 = "text"
+  var t2 = t1.toUpper
+  echo(t1 +++ t2)
+
diff --git a/tests/caasdriver.nim b/tests/caasdriver.nim
new file mode 100644
index 000000000..3f3d3671e
--- /dev/null
+++ b/tests/caasdriver.nim
@@ -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
+    
diff --git a/tests/run/tbug499771.nim b/tests/run/tbug499771.nim
index 633ab39f6..682148422 100644
--- a/tests/run/tbug499771.nim
+++ b/tests/run/tbug499771.nim
@@ -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
diff --git a/tests/run/tlenopenarray.nim b/tests/run/tlenopenarray.nim
deleted file mode 100644
index 3ab27c8f7..000000000
--- a/tests/run/tlenopenarray.nim
+++ /dev/null
@@ -1,7 +0,0 @@
-discard """
-  file: "tlenopenarray.nim"
-  output: "1"
-"""
-
-echo len([1_000_000]) #OUT 1
-
diff --git a/tests/run/tvarargs_vs_generic.nim b/tests/run/tvarargs_vs_generic.nim
new file mode 100644
index 000000000..7c1fa67b2
--- /dev/null
+++ b/tests/run/tvarargs_vs_generic.nim
@@ -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"
+
diff --git a/tests/run/tvarious1.nim b/tests/run/tvarious1.nim
new file mode 100644
index 000000000..d30d91234
--- /dev/null
+++ b/tests/run/tvarious1.nim
@@ -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]
diff --git a/tests/tester.nim b/tests/tester.nim
index 2b60151a8..8c8e31fe8 100644
--- a/tests/tester.nim
+++ b/tests/tester.nim
@@ -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)
diff --git a/web/news.txt b/web/news.txt
index 667b8a210..26c681d95 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -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