summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules3
-rwxr-xr-xbootstrap.sh (renamed from build.sh)2
-rw-r--r--compiler/installer.ini6
-rw-r--r--compiler/jsgen.nim7
m---------csources0
-rw-r--r--doc/manual/about.txt14
-rw-r--r--doc/manual/definitions.txt2
-rw-r--r--doc/manual/effects.txt2
-rw-r--r--doc/manual/lexing.txt4
-rw-r--r--doc/manual/modules.txt3
-rw-r--r--doc/manual/pragmas.txt23
-rw-r--r--doc/manual/procs.txt65
-rw-r--r--doc/manual/stmts.txt20
-rw-r--r--doc/manual/trmacros.txt18
-rw-r--r--doc/manual/type_rel.txt6
-rw-r--r--doc/manual/types.txt4
-rw-r--r--koch.nim7
-rw-r--r--lib/pure/json.nim29
-rw-r--r--lib/pure/logging.nim2
-rw-r--r--lib/pure/optionals.nim160
-rw-r--r--lib/pure/streams.nim2
-rw-r--r--lib/pure/xmltree.nim3
-rw-r--r--lib/system/mmdisp.nim3
-rw-r--r--tests/js/tobjfieldbyvar.nim20
-rw-r--r--tools/niminst/niminst.nim18
26 files changed, 307 insertions, 117 deletions
diff --git a/.gitignore b/.gitignore
index 462df4efc..1971a23cb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,4 @@ xcuserdata/
 /testresults.html
 /testresults.json
 testament.db
+/csources
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 26f35d82c..000000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "csources"]
-	path = csources
-	url = ../../nim-lang/csources.git
diff --git a/build.sh b/bootstrap.sh
index 91e169241..ade74a9aa 100755
--- a/build.sh
+++ b/bootstrap.sh
@@ -3,7 +3,7 @@ set -e
 set -x
 
 if [ ! -e csources/.git ]; then
-	git submodule update --init --depth 1
+	git clone --depth 1 git://github.com/nim-lang/csources.git csources
 fi
 
 cd "csources"
diff --git a/compiler/installer.ini b/compiler/installer.ini
index fff82cb5b..821309a34 100644
--- a/compiler/installer.ini
+++ b/compiler/installer.ini
@@ -203,7 +203,11 @@ Files: "tests/stdlib/*.nim"
 Files: "tests/system/*.nim"
 Files: "tests/template/*.nim"
 Files: "tests/testament/*.nim"
-Files: "tests/testdata/*.nim"
+Files: "tests/testdata/*.csv"
+Files: "tests/testdata/*.html"
+Files: "tests/testdata/*.json"
+Files: "tests/testdata/*.txt"
+Files: "tests/testdata/*.xml"
 Files: "tests/threads/*.nim"
 Files: "tests/threads/*.cfg"
 Files: "tests/trmacros/*.nim"
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 5c7071498..0f6323abc 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -880,7 +880,7 @@ proc genFieldAccess(p: PProc, n: PNode, r: var TCompRes) =
   if skipTypes(n.sons[0].typ, abstractVarRange).kind == tyTuple:
     r.res = "$1.Field$2" % [r.res, getFieldPosition(n.sons[1]).rope]
   else:
-    if n.sons[1].kind != nkSym: internalError(n.sons[1].info, "genFieldAddr")
+    if n.sons[1].kind != nkSym: internalError(n.sons[1].info, "genFieldAccess")
     var f = n.sons[1].sym
     if f.loc.r == nil: f.loc.r = mangleName(f)
     r.res = "$1.$2" % [r.res, f.loc.r]
@@ -970,7 +970,10 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
   of nkCheckedFieldExpr:
     genCheckedFieldAddr(p, n, r)
   of nkDotExpr:
-    genFieldAddr(p, n.sons[0], r)
+    if mapType(n.typ) == etyBaseIndex:
+      genFieldAddr(p, n.sons[0], r)
+    else:
+      genFieldAccess(p, n.sons[0], r)
   of nkBracketExpr:
     var ty = skipTypes(n.sons[0].typ, abstractVarRange)
     if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange)
diff --git a/csources b/csources
deleted file mode 160000
-Subproject 15724e2e1f3e7749d508dfcd995e84fea285080
diff --git a/doc/manual/about.txt b/doc/manual/about.txt
index 78167efe3..8528ff978 100644
--- a/doc/manual/about.txt
+++ b/doc/manual/about.txt
@@ -1,15 +1,15 @@
 About this document
 ===================
 
-**Note**: This document is a draft! Several of Nim's features need more
-precise wording. This manual will evolve into a proper specification some
-day.
+**Note**: This document is a draft! Several of Nim's features may need more
+precise wording. This manual is constantly evolving until the 1.0 release and is
+not to be considered as the final proper specification.
 
 This document describes the lexis, the syntax, and the semantics of Nim.
 
-The language constructs are explained using an extended BNF, in
-which ``(a)*`` means 0 or more ``a``'s, ``a+`` means 1 or more ``a``'s, and
-``(a)?`` means an optional *a*. Parentheses may be used to group elements.
+The language constructs are explained using an extended BNF, in which ``(a)*``
+means 0 or more ``a``'s, ``a+`` means 1 or more ``a``'s, and ``(a)?`` means an
+optional *a*. Parentheses may be used to group elements.
 
 ``&`` is the lookahead operator; ``&a`` means that an ``a`` is expected but
 not consumed. It will be consumed in the following rule.
@@ -33,5 +33,5 @@ and ``a ^* b`` is short for ``(a (b a)*)?``. Example::
   arrayConstructor = '[' expr ^* ',' ']'
 
 Other parts of Nim - like scoping rules or runtime semantics are only
-described in an informal manner for now.
+described in the, more easily comprehensible, informal manner for now.
 
diff --git a/doc/manual/definitions.txt b/doc/manual/definitions.txt
index 9eb20f70f..9004ce658 100644
--- a/doc/manual/definitions.txt
+++ b/doc/manual/definitions.txt
@@ -30,7 +30,7 @@ exceptions* or *dying with a fatal error*. However, the implementation
 provides a means to disable these runtime checks. See the section pragmas_
 for details. 
 
-Wether a checked runtime error results in an exception or in a fatal error at
+Whether a checked runtime error results in an exception or in a fatal error at
 runtime is implementation specific. Thus the following program is always
 invalid:
 
diff --git a/doc/manual/effects.txt b/doc/manual/effects.txt
index a79f6ea85..40532b080 100644
--- a/doc/manual/effects.txt
+++ b/doc/manual/effects.txt
@@ -48,7 +48,7 @@ possibly raised exceptions; the algorithm operates on ``p``'s call graph:
    However if the call is of the form ``f(...)`` where ``f`` is a parameter
    of the currently analysed routine it is ignored. The call is optimistically 
    assumed to have no effect. Rule 2 compensates for this case.
-2. Every expression of some proc type wihtin a call that is not a call 
+2. Every expression of some proc type within a call that is not a call 
    itself (and not nil) is assumed to be called indirectly somehow and thus 
    its raises list is added to ``p``'s raises list.
 3. Every call to a proc ``q`` which has an unknown body (due to a forward 
diff --git a/doc/manual/lexing.txt b/doc/manual/lexing.txt
index df6d85636..ab1cd632d 100644
--- a/doc/manual/lexing.txt
+++ b/doc/manual/lexing.txt
@@ -25,7 +25,7 @@ a separate token. This trick allows parsing of Nim with only 1 token of
 lookahead.
 
 The parser uses a stack of indentation levels: the stack consists of integers
-counting the spaces. The indentation information is queried at strategic 
+counting the spaces. The indentation information is queried at strategic
 places in the parser but ignored otherwise: The pseudo terminal ``IND{>}``
 denotes an indentation that consists of more spaces than the entry at the top
 of the stack; IND{=} an indentation that has the same number of spaces. ``DED``
@@ -80,7 +80,7 @@ underscores ``__`` are not allowed::
   digit ::= '0'..'9'
   IDENTIFIER ::= letter ( ['_'] (letter | digit) )*
 
-Currently any unicode character with an ordinal value > 127 (non ASCII) is
+Currently any Unicode character with an ordinal value > 127 (non ASCII) is
 classified as a ``letter`` and may thus be part of an identifier but later
 versions of the language may assign some Unicode characters to belong to the
 operator characters instead.
diff --git a/doc/manual/modules.txt b/doc/manual/modules.txt
index 70f6026b2..fe3360773 100644
--- a/doc/manual/modules.txt
+++ b/doc/manual/modules.txt
@@ -178,8 +178,7 @@ Module scope
 ~~~~~~~~~~~~
 All identifiers of a module are valid from the point of declaration until
 the end of the module. Identifiers from indirectly dependent modules are *not* 
-available. The `system`:idx: module is automatically imported in every other 
-module.
+available. The `system`:idx: module is automatically imported in every module.
 
 If a module imports an identifier by two different modules, each occurrence of
 the identifier has to be qualified, unless it is an overloaded procedure or
diff --git a/doc/manual/pragmas.txt b/doc/manual/pragmas.txt
index 39aebd826..51125f576 100644
--- a/doc/manual/pragmas.txt
+++ b/doc/manual/pragmas.txt
@@ -18,9 +18,7 @@ The deprecated pragma is used to mark a symbol as deprecated:
   proc p() {.deprecated.}
   var x {.deprecated.}: char
 
-It can also be used as a statement. Then it takes a list of *renamings*. The
-upcoming ``nimfix`` tool can automatically update the code and perform these
-renamings:
+It can also be used as a statement, in that case it takes a list of *renamings*.
 
 .. code-block:: nim
   type
@@ -28,6 +26,9 @@ renamings:
     Stream = ref object
   {.deprecated: [TFile: File, PStream: Stream].}
 
+The ``nimfix`` tool can be used to, without effort, automatically update your
+code and refactor it by performing these renamings.
+
 
 noSideEffect pragma
 -------------------
@@ -54,9 +55,7 @@ destructor pragma
 -----------------
 
 The ``destructor`` pragma is used to mark a proc to act as a type destructor.
-Its usage is deprecated, use the ``override`` pragma instead.
-See `type bound operations`_.
-
+Its usage is deprecated, See `type bound operations`_ instead.
 
 override pragma
 ---------------
@@ -371,7 +370,7 @@ The ``register`` pragma is for variables only. It declares the variable as
 in a hardware register for faster access. C compilers usually ignore this
 though and for good reasons: Often they do a better job without it anyway.
 
-In highly specific cases (a dispatch loop of an bytecode interpreter for
+In highly specific cases (a dispatch loop of a bytecode interpreter for
 example) it may provide benefits, though.
 
 
@@ -429,13 +428,13 @@ Example:
   2. When a top level call is encountered (usually at the very end of the module),
   the compiler will try to determine the actual types of all of the symbols in the
   matching overload set. This is a potentially recursive process as the signatures
-  of the symbols may include other call expressions, whoose types will be resolved
+  of the symbols may include other call expressions, whose types will be resolved
   at this point too.
 
-  3. Finally, after the best overload is picked, the compiler will start compiling
-  the body of the respective symbol. This in turn will lead the compiler to discover
-  more call expresions that need to be resolved and steps 2 and 3 will be repeated
-  as necessary.
+  3. Finally, after the best overload is picked, the compiler will start
+  compiling the body of the respective symbol. This in turn will lead the
+  compiler to discover more call expressions that need to be resolved and steps
+  2 and 3 will be repeated as necessary.
 
   Please note that if a callable symbol is never used in this scenario, its body
   will never be compiled. This is the default behavior leading to best compilation
diff --git a/doc/manual/procs.txt b/doc/manual/procs.txt
index 9de984ecf..38e343686 100644
--- a/doc/manual/procs.txt
+++ b/doc/manual/procs.txt
@@ -2,17 +2,46 @@ Procedures
 ==========
 
 What most programming languages call `methods`:idx: or `functions`:idx: are
-called `procedures`:idx: in Nim (which is the correct terminology). A
-procedure declaration defines an identifier and associates it with a block
-of code. 
-A procedure may call itself recursively. A parameter may be given a default
-value that is used if the caller does not provide a value for this parameter.
-
-If the proc declaration has no body, it is a `forward`:idx: declaration. If
-the proc returns a value, the procedure body can access an implicitly declared
+called `procedures`:idx: in Nim (which is the correct terminology). A procedure
+declaration consists of an identifier, zero or more formal parameters, a return
+value type and a block of code. Formal parameters are declared as a list of
+identifiers separated by either comma or semicolon. A parameter is given a type
+by ``: typename``. The type applies to all parameters immediately before it,
+until either the beginning of the parameter list, a semicolon separator or an
+already typed parameter, is reached. The semicolon can be used to make
+separation of types and subsequent identifiers more distinct.
+
+.. code-block:: nim
+  # Using only commas
+  proc foo(a, b: int, c, d: bool): int
+
+  # Using semicolon for visual distinction
+  proc foo(a, b: int; c, d: bool): int
+
+  # Will fail: a is untyped since ';' stops type propagation.
+  proc foo(a; b: int; c, d: bool): int
+
+A parameter may be declared with a default value which is used if the caller
+does not provide a value for the argument.
+
+.. code-block:: nim
+  # b is optional with 47 as its default value
+  proc foo(a: int, b: int = 47): int
+
+Parameters can be declared mutable and so allow the proc to modify those
+arguments, by using the type modifier `var`.
+
+.. code-block:: nim
+  # "returning" a value to the caller through the 2nd argument
+  # Notice that the function uses no actual return value at all (ie void)
+  proc foo(inp: int, outp: var int) =
+    outp = inp + 47
+
+If the proc declaration has no body, it is a `forward`:idx: declaration. If the
+proc returns a value, the procedure body can access an implicitly declared
 variable named `result`:idx: that represents the return value. Procs can be
-overloaded. The overloading resolution algorithm tries to find the proc that is
-the best match for the arguments. Example:
+overloaded. The overloading resolution algorithm determines which proc is the
+best match for the arguments. Example:
 
 .. code-block:: nim
 
@@ -41,9 +70,8 @@ Calling a procedure can be done in many different ways:
   # call as a command statement: no () needed:
   callme 0, 1, "abc", '\t'
 
+A procedure may call itself recursively.
 
-A procedure cannot modify its parameters (unless the parameters have the type
-`var`).
 
 `Operators`:idx: are procedures with a special operator symbol as identifier:
 
@@ -475,7 +503,7 @@ If the for loop has exactly 2 variables, a ``pairs`` iterator is implicitly
 invoked.
 
 Symbol lookup of the identifiers ``items``/``pairs`` is performed after 
-the rewriting step, so that all overloadings of ``items``/``pairs`` are taken
+the rewriting step, so that all overloads of ``items``/``pairs`` are taken
 into account.
 
 
@@ -511,11 +539,12 @@ Closure iterators have other restrictions than inline iterators:
 
 1. ``yield`` in a closure iterator can not occur in a ``try`` statement.
 2. For now, a closure iterator cannot be evaluated at compile time.
-3. ``return`` is allowed in a closure iterator (but rarely useful).
-4. Both inline and closure iterators cannot be recursive.
+3. ``return`` is allowed in a closure iterator (but rarely useful) and ends 
+   iteration.
+4. Neither inline nor closure iterators can be recursive.
 
 Iterators that are neither marked ``{.closure.}`` nor ``{.inline.}`` explicitly
-default to being inline, but that this may change in future versions of the
+default to being inline, but this may change in future versions of the
 implementation.
 
 The ``iterator`` type is always of the calling convention ``closure`` 
@@ -612,8 +641,8 @@ parameters of an outer factory proc:
   Implicit return type
   --------------------
 
-  Since inline interators must always produce values that will be consumed in
-  a for loop, the compiler will implicity use the ``auto`` return type if no
+  Since inline iterators must always produce values that will be consumed in
+  a for loop, the compiler will implicitly use the ``auto`` return type if no
   type is given by the user. In contrast, since closure iterators can be used
   as a collaborative tasking system, ``void`` is a valid return type for them.
 
diff --git a/doc/manual/stmts.txt b/doc/manual/stmts.txt
index 210ca7064..32c01dccb 100644
--- a/doc/manual/stmts.txt
+++ b/doc/manual/stmts.txt
@@ -10,7 +10,7 @@ Statements are separated into `simple statements`:idx: and
 Simple statements are statements that cannot contain other statements like
 assignments, calls or the ``return`` statement; complex statements can
 contain other statements. To avoid the `dangling else problem`:idx:, complex
-statements always have to be intended. The details can be found in the grammar.
+statements always have to be indented. The details can be found in the grammar.
 
 
 Statement list expression
@@ -229,22 +229,18 @@ the expression after the ``elif`` is evaluated (if there is an
 ``elif`` branch), if it is true the corresponding statements after
 the ``:`` are executed. This goes on until the last ``elif``. If all
 conditions fail, the ``else`` part is executed. If there is no ``else``
-part, execution continues with the statement after the ``if`` statement.
+part, execution continues with the next statement.
 
-The scoping for an ``if`` statement is slightly subtle to support an important
-use case. A new scope starts for the ``if``/``elif`` condition and ends after
-the corresponding *then* block:
+In ``if`` statements new scopes begin immediately after the ``if``/``elif``/``else`` keywords and ends after the corresponding *then* block.
+For visualization purposes the scopes have been enclosed in ``{|  |}`` in the following example:
 
 .. code-block:: nim
   if {| (let m = input =~ re"(\w+)=\w+"; m.isMatch):
     echo "key ", m[0], " value ", m[1]  |}
   elif {| (let m = input =~ re""; m.isMatch):
-    echo "new m in this scope" |}
-  else:
-    # 'm' not declared here
-
-In the example the scopes have been enclosed in ``{|  |}``.
-
+    echo "new m in this scope"  |}
+  else: {|
+    echo "m not declared here"  |}
 
 Case statement
 --------------
@@ -601,7 +597,7 @@ A table constructor is syntactic sugar for an array constructor:
 
 The empty table can be written ``{:}`` (in contrast to the empty set
 which is ``{}``) which is thus another way to write as the empty array
-constructor ``[]``. This slightly unusal way of supporting tables
+constructor ``[]``. This slightly unusual way of supporting tables
 has lots of advantages:
 
 * The order of the (key,value)-pairs is preserved, thus it is easy to
diff --git a/doc/manual/trmacros.txt b/doc/manual/trmacros.txt
index 90d01e475..5ff24a36a 100644
--- a/doc/manual/trmacros.txt
+++ b/doc/manual/trmacros.txt
@@ -43,6 +43,10 @@ Fortunately Nim supports side effect analysis:
   
   echo f() * 2 # not optimized ;-)
 
+You can make one overload matching with a constraint and one without, and the
+one with a constraint will have precedence, and so you can handle both cases
+differently.
+
 So what about ``2 * a``? We should tell the compiler ``*`` is commutative. We
 cannot really do that however as the following code only swaps arguments
 blindly:
@@ -105,8 +109,10 @@ Predicate                Meaning
                          with the marked parameter.
 ===================      =====================================================
 
+Predicates that share their name with a keyword have to be escaped with 
+backticks: `` `const` ``.
 The ``alias`` and ``noalias`` predicates refer not only to the matching AST,
-but also to every other bound parameter; syntactially they need to occur after
+but also to every other bound parameter; syntactically they need to occur after
 the ordinary AST predicates:
 
 .. code-block:: nim
@@ -144,7 +150,7 @@ constant folding, so the following does not work:
 
 The reason is that the compiler already transformed the 1 into "1" for
 the ``echo`` statement. However, a term rewriting macro should not change the
-semantics anyway. In fact they can be deactived with the ``--patterns:off``
+semantics anyway. In fact they can be deactivated with the ``--patterns:off``
 command line option or temporarily with the ``patterns`` pragma. 
 
 
@@ -345,15 +351,15 @@ optimization for types that have copying semantics:
     ## puts a (key, value)-pair into `t`. The semantics of string require
     ## a copy here:
     let idx = findInsertionPosition(key)
-    t[idx] = key
-    t[idx] = val
+    t[idx].key = key
+    t[idx].val = val
 
   proc `[]=`*(t: var Table, key: string{call}, val: string{call}) =
     ## puts a (key, value)-pair into `t`. Optimized version that knows that
     ## the strings are unique and thus don't need to be copied:
     let idx = findInsertionPosition(key)
-    shallowCopy t[idx], key
-    shallowCopy t[idx], val
+    shallowCopy t[idx].key, key
+    shallowCopy t[idx].val, val
 
   var t: Table
   # overloading resolution ensures that the optimized []= is called here:
diff --git a/doc/manual/type_rel.txt b/doc/manual/type_rel.txt
index d1593a02e..5c8372e1e 100644
--- a/doc/manual/type_rel.txt
+++ b/doc/manual/type_rel.txt
@@ -9,11 +9,11 @@ Type equality
 -------------
 Nim uses structural type equivalence for most types. Only for objects,
 enumerations and distinct types name equivalence is used. The following
-algorithm (in pseudo-code) determines type equality:
+algorithm, *in pseudo-code*, determines type equality:
 
 .. code-block:: nim
   proc typeEqualsAux(a, b: PType,
-                     s: var set[PType * PType]): bool =
+                     s: var HashSet[(PType, PType)]): bool =
     if (a,b) in s: return true
     incl(s, (a,b))
     if a.kind == b.kind:
@@ -43,7 +43,7 @@ algorithm (in pseudo-code) determines type equality:
                  a.callingConvention == b.callingConvention
 
   proc typeEquals(a, b: PType): bool =
-    var s: set[PType * PType] = {}
+    var s: HashSet[(PType, PType)] = {}
     result = typeEqualsAux(a, b, s)
 
 Since types are graphs which can have cycles, the above algorithm needs an
diff --git a/doc/manual/types.txt b/doc/manual/types.txt
index 689605f08..81ae9d6b4 100644
--- a/doc/manual/types.txt
+++ b/doc/manual/types.txt
@@ -803,7 +803,7 @@ exclude ``nil`` as a valid value with the ``not nil`` annotation:
   p(x)
 
 The compiler ensures that every code path initializes variables which contain
-not nilable pointers. The details of this analysis are still to be specified
+non nilable pointers. The details of this analysis are still to be specified
 here.
 
 
@@ -1132,7 +1132,7 @@ that don't. Distinct types provide a means to introduce a new string type
 
 
 It is an essential property of abstract types that they **do not** imply a
-subtype relation between the abtract type and its base type. Explict type
+subtype relation between the abstract type and its base type. Explicit type
 conversions from ``string`` to ``SQL`` are allowed:
 
 .. code-block:: nim
diff --git a/koch.nim b/koch.nim
index a951b422f..fc292401a 100644
--- a/koch.nim
+++ b/koch.nim
@@ -47,6 +47,7 @@ Possible Commands:
   csource [options]        builds the C sources for installation
   pdf                      builds the PDF documentation
   zip                      builds the installation ZIP package
+  xz                       builds the installation XZ package
   nsis [options]           builds the NSIS Setup installer (for Windows)
   tests [options]          run the testsuite
   update                   updates nim to the latest version from github
@@ -106,10 +107,10 @@ proc zip(args: string) =
   exec("$# --var:version=$# --var:mingw=none --main:compiler/nim.nim zip compiler/installer.ini" %
        ["tools/niminst/niminst".exe, VersionAsString])
 
-proc targz(args: string) =
+proc xz(args: string) =
   exec("$3 cc -r $2 --var:version=$1 --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini" %
        [VersionAsString, compileNimInst, findNim()])
-  exec("$# --var:version=$# --var:mingw=none --main:compiler/nim.nim targz compiler/installer.ini" %
+  exec("$# --var:version=$# --var:mingw=none --main:compiler/nim.nim xz compiler/installer.ini" %
        ["tools" / "niminst" / "niminst".exe, VersionAsString])
 
 proc buildTool(toolname, args: string) =
@@ -367,7 +368,7 @@ of cmdArgument:
   of "pdf": pdf()
   of "csource", "csources": csource(op.cmdLineRest)
   of "zip": zip(op.cmdLineRest)
-  of "targz": targz(op.cmdLineRest)
+  of "xz": xz(op.cmdLineRest)
   of "nsis": nsis(op.cmdLineRest)
   of "install": install(op.cmdLineRest)
   of "test", "tests": tests(op.cmdLineRest)
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 518572be3..0959bb221 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -1187,24 +1187,13 @@ when false:
 # To get that we shall use, obj["json"]
 
 when isMainModule:
-  #var node = parse("{ \"test\": null }")
-  #echo(node.existsKey("test56"))
-
   var parsed = parseFile("tests/testdata/jsontest.json")
   var parsed2 = parseFile("tests/testdata/jsontest2.json")
 
-  when not defined(testing):
-    echo(parsed)
-    echo()
-    echo(pretty(parsed, 2))
-    echo()
-    echo(parsed["keyÄÖöoßß"])
-    echo()
-    echo(pretty(parsed2))
-    try:
-      echo(parsed["key2"][12123])
-      raise newException(ValueError, "That line was expected to fail")
-    except IndexError: echo()
+  try:
+    discard parsed["key2"][12123]
+    assert(false)
+  except IndexError: assert(true)
 
   let testJson = parseJson"""{ "a": [1, 2, 3, 4], "b": "asd" }"""
   # nil passthrough
@@ -1271,13 +1260,3 @@ when isMainModule:
       }
     ]
   assert j3 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}]
-
-  when not defined(testing):
-    discard """
-    while true:
-      var json = stdin.readLine()
-      var node = parse(json)
-      echo(node)
-      echo()
-      echo()
-    """
diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim
index a2ea53472..cc5340211 100644
--- a/lib/pure/logging.nim
+++ b/lib/pure/logging.nim
@@ -66,7 +66,7 @@ type
   Logger* = ref object of RootObj ## abstract logger; the base type of all loggers
     levelThreshold*: Level    ## only messages of level >= levelThreshold
                               ## should be processed
-    fmtStr: string ## = defaultFmtStr by default, see substituteLog for $date etc.
+    fmtStr*: string ## = defaultFmtStr by default, see substituteLog for $date etc.
 
   ConsoleLogger* = ref object of Logger ## logger that writes the messages to the
                                         ## console
diff --git a/lib/pure/optionals.nim b/lib/pure/optionals.nim
new file mode 100644
index 000000000..ef01e1260
--- /dev/null
+++ b/lib/pure/optionals.nim
@@ -0,0 +1,160 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Nim Contributors
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Abstract
+## ========
+##
+## This module implements types which encapsulate an optional value.
+##
+## A value of type ``Option[T]`` either contains a value `x` (represented as
+## ``some(x)``) or is empty (``none(T)``).
+##
+## This can be useful when you have a value that can be present or not.  The
+## absence of a value is often represented by ``nil``, but it is not always
+## available, nor is it always a good solution.
+##
+##
+## Tutorial
+## ========
+##
+## Let's start with an example: a procedure that finds the index of a character
+## in a string.
+##
+## .. code-block:: nim
+##
+##   import optionals
+##
+##   proc find(haystack: string, needle: char): Option[int] =
+##     for i, c in haystack:
+##       if c == needle:
+##         return some(i)
+##     return none(int)  # This line is actually optional,
+##                       # because the default is empty
+##
+## .. code-block:: nim
+##
+##   try:
+##     assert("abc".find('c').get() == 2)  # Immediately extract the value
+##   except UnpackError:  # If there is no value
+##     assert false  # This will not be reached, because the value is present
+##
+## The ``get`` operation demonstrated above returns the underlying value, or
+## raises ``UnpackError`` if there is no value. There is another option for
+## obtaining the value: ``unsafeGet``, but you must only use it when you are
+## absolutely sure the value is present (e.g. after checking ``isSome``). If
+## you do not care about the tiny overhead that ``get`` causes, you should
+## simply never use ``unsafeGet``.
+##
+## How to deal with an absence of a value:
+##
+## .. code-block:: nim
+##
+##   let result = "team".find('i')
+##
+##   # Nothing was found, so the result is `none`.
+##   assert(result == none(int))
+##   # It has no value:
+##   assert(result.isNone)
+##
+##   try:
+##     echo result.get()
+##     assert(false)  # This will not be reached
+##   except UnpackError:  # Because an exception is raised
+##     discard
+
+import typetraits
+
+
+type
+  Option*[T] = object
+    ## An optional type that stores its value and state separately in a boolean.
+    val: T
+    has: bool
+  UnpackError* = ref object of ValueError
+
+
+proc some*[T](val: T): Option[T] =
+  ## Returns a ``Option`` that has this value.
+  result.has = true
+  result.val = val
+
+proc none*(T: typedesc): Option[T] =
+  ## Returns a ``Option`` for this type that has no value.
+  result.has = false
+
+
+proc isSome*[T](self: Option[T]): bool =
+  self.has
+
+proc isNone*[T](self: Option[T]): bool =
+  not self.has
+
+
+proc unsafeGet*[T](self: Option[T]): T =
+  ## Returns the value of a ``some``. Behavior is undefined for ``none``.
+  assert self.isSome
+  self.val
+
+proc get*[T](self: Option[T]): T =
+  ## Returns contents of the Option. If it is none, then an exception is
+  ## thrown.
+  if self.isNone:
+    raise UnpackError(msg : "Can't obtain a value from a `none`")
+  self.val
+
+
+proc `==`*(a, b: Option): bool =
+  ## Returns ``true`` if both ``Option``s are ``none``,
+  ## or if they have equal values
+  (a.has and b.has and a.val == b.val) or (not a.has and not b.has)
+
+
+when isMainModule:
+  import unittest
+
+  suite "optionals":
+    # work around a bug in unittest
+    let intNone = none(int)
+    let stringNone = none(string)
+
+    test "example":
+      proc find(haystack: string, needle: char): Option[int] =
+        for i, c in haystack:
+          if c == needle:
+            return some i
+
+      check("abc".find('c').get() == 2)
+
+      let result = "team".find('i')
+
+      check result == intNone
+      check result.isNone
+
+    test "some":
+      check some(6).get() == 6
+      check some("a").unsafeGet() == "a"
+      check some(6).isSome
+      check some("a").isSome
+
+    test "none":
+      expect UnpackError:
+        discard none(int).get()
+      check(none(int).isNone)
+      check(not none(string).isSome)
+
+    test "equality":
+      check some("a") == some("a")
+      check some(7) != some(6)
+      check some("a") != stringNone
+      check intNone == intNone
+
+      when compiles(some("a") == some(5)):
+        check false
+      when compiles(none(string) == none(int)):
+        check false
diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim
index f51c979eb..c85a09bad 100644
--- a/lib/pure/streams.nim
+++ b/lib/pure/streams.nim
@@ -449,7 +449,7 @@ else:
       if handle < 0: raise newEOS("posix.open() call failed")
     result = newFileHandleStream(handle)
 
-when defined(testing):
+when isMainModule and defined(testing):
   var ss = newStringStream("The quick brown fox jumped over the lazy dog.\nThe lazy dog ran")
   assert(ss.getPosition == 0)
   assert(ss.peekStr(5) == "The q")
diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index 7526a989a..bbe3c05b7 100644
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -337,8 +337,7 @@ proc findAll*(n: XmlNode, tag: string, result: var seq[XmlNode]) =
       continue
     if child.tag == tag:
       result.add(child)
-    elif child.k == xnElement:
-      child.findAll(tag, result)
+    child.findAll(tag, result)
 
 proc findAll*(n: XmlNode, tag: string): seq[XmlNode] =
   ## Shortcut version to assign in let blocks. Example:
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index a378f86e7..bdbb3a95a 100644
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -70,7 +70,7 @@ when defined(boehmgc):
   elif defined(macosx):
     const boehmLib = "libgc.dylib"
   else:
-    const boehmLib = "/usr/lib/libgc.so.1"
+    const boehmLib = "libgc.so.1"
 
   proc boehmGCinit {.importc: "GC_init", dynlib: boehmLib.}
   proc boehmGC_disable {.importc: "GC_disable", dynlib: boehmLib.}
@@ -335,4 +335,3 @@ else:
     include "system/gc"
 
 {.pop.}
-
diff --git a/tests/js/tobjfieldbyvar.nim b/tests/js/tobjfieldbyvar.nim
new file mode 100644
index 000000000..91a3c1315
--- /dev/null
+++ b/tests/js/tobjfieldbyvar.nim
@@ -0,0 +1,20 @@
+discard """
+  output: '''5
+'''
+"""
+
+# bug #2798
+
+type Inner = object
+  value: int
+
+type Outer = object
+  i: Inner
+
+proc test(i: var Inner) =
+  i.value += 5
+
+var o: Outer
+test(o.i)
+
+echo o.i.value
diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim
index f0ae45484..99befa92d 100644
--- a/tools/niminst/niminst.nim
+++ b/tools/niminst/niminst.nim
@@ -35,7 +35,7 @@ type
     actionNsis,   # action: create NSIS installer
     actionScripts # action: create install and deinstall scripts
     actionZip,    # action: create zip file
-    actionTargz,  # action: create targz file
+    actionXz,     # action: create xz file
     actionDeb     # action: prepare deb package
 
   FileCategory = enum
@@ -172,7 +172,7 @@ proc parseCmdLine(c: var ConfigData) =
           of "csource": incl(c.actions, actionCSource)
           of "scripts": incl(c.actions, actionScripts)
           of "zip": incl(c.actions, actionZip)
-          of "targz": incl(c.actions, actionTargz)
+          of "xz": incl(c.actions, actionXz)
           of "inno": incl(c.actions, actionInno)
           of "nsis": incl(c.actions, actionNsis)
           of "deb": incl(c.actions, actionDeb)
@@ -560,9 +560,9 @@ when haveZipLib:
     else:
       quit("Cannot open for writing: " & n)
 
-proc targzDist(c: var ConfigData) =
+proc xzDist(c: var ConfigData) =
   let proj = toLower(c.name) & "-" & c.version
-  var n = "$#.tar.gz" % proj
+  var n = "$#.tar.xz" % proj
   let tmpDir = if c.outdir.len == 0: "build" else: c.outdir
 
   template processFile(z, dest, src) =
@@ -571,7 +571,7 @@ proc targzDist(c: var ConfigData) =
     echo "Copying ", s, " to ", tmpDir / d
     let destdir = tmpdir / d.splitFile.dir
     if not dirExists(destdir): createDir(destdir)
-    copyFile(s, tmpDir / d)
+    copyFileWithPermissions(s, tmpDir / d)
 
   processFile(z, proj / buildBatFile32, "build" / buildBatFile32)
   processFile(z, proj / buildBatFile64, "build" / buildBatFile64)
@@ -593,9 +593,7 @@ proc targzDist(c: var ConfigData) =
   let oldDir = getCurrentDir()
   setCurrentDir(tmpDir)
   try:
-    #if execShellCmd("7z a -ttar $1.tar $1" % proj) != 0 or
-    #   execShellCmd("7z a -tgzip $1.tar.gz $1.tar" % proj) != 0 or
-    if execShellCmd("7z a -tzip $1.zip $1" % proj) != 0:
+    if execShellCmd("XZ_OPT=-9 tar Jcf $1.tar.xz $1" % proj) != 0:
       echo("External program failed")
   finally:
     setCurrentDir(oldDir)
@@ -666,7 +664,7 @@ if actionZip in c.actions:
     zipDist(c)
   else:
     quit("libzip is not installed")
-if actionTargz in c.actions:
-  targzDist(c)
+if actionXz in c.actions:
+  xzDist(c)
 if actionDeb in c.actions:
   debDist(c)