summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md4
-rw-r--r--compiler/ccgexprs.nim6
-rw-r--r--compiler/ccgtypes.nim3
-rw-r--r--compiler/cgen.nim6
-rw-r--r--compiler/msgs.nim4
-rw-r--r--compiler/parser.nim17
-rw-r--r--compiler/semcall.nim6
-rw-r--r--compiler/semexprs.nim4
-rw-r--r--compiler/semtypes.nim6
-rw-r--r--compiler/sigmatch.nim4
-rw-r--r--compiler/vm.nim2
-rw-r--r--compiler/vmdef.nim2
-rw-r--r--doc/grammar.txt3
-rw-r--r--doc/manual/lexing.txt6
-rw-r--r--lib/core/macros.nim4
-rw-r--r--lib/pure/algorithm.nim2
-rw-r--r--lib/pure/asyncfile.nim4
-rw-r--r--lib/pure/httpclient.nim2
-rw-r--r--lib/pure/json.nim2
-rw-r--r--lib/pure/xmlparser.nim25
-rw-r--r--lib/system.nim6
-rw-r--r--lib/system/alloc.nim81
-rw-r--r--tests/async/hello.txt1
-rw-r--r--tests/async/tasyncfile.nim11
-rw-r--r--tests/ccgbugs/mymodule.nim12
-rw-r--r--tests/ccgbugs/tforward_decl_only.nim15
-rw-r--r--tests/ccgbugs/tresult_of_array.nim29
-rw-r--r--tests/macros/tdumpastgen.nim28
-rw-r--r--tests/system/talloc.nim (renamed from tests/system/alloc.nim)15
-rw-r--r--tests/system/talloc2.nim37
-rw-r--r--tests/system/tio.nim (renamed from tests/system/io.nim)0
-rw-r--r--tests/system/tparams.nim (renamed from tests/system/params.nim)0
-rw-r--r--todo.txt1
33 files changed, 265 insertions, 83 deletions
diff --git a/changelog.md b/changelog.md
index 6844d3791..77a01b9c7 100644
--- a/changelog.md
+++ b/changelog.md
@@ -27,6 +27,10 @@
 
 ### Compiler changes
 
+- The VM's instruction count limit was raised to 1 billion instructions in order
+  to support more complex computations at compile-time.
+
+
 ### Bugfixes
 
 - The `importcpp` pragma now allows importing the listed fields of generic
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index ba0820e93..060a5fdbd 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1364,6 +1364,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
     if t.kind notin {tyVar, tyLent} or not p.module.compileToCpp:
       r = rfmt(nil, "(*$1)", r)
     t = skipTypes(t.lastSon, typedescInst)
+  discard getTypeDesc(p.module, t)
   if not p.module.compileToCpp:
     while t.kind == tyObject and t.sons[0] != nil:
       add(r, ~".Sup")
@@ -1910,7 +1911,8 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
     if getSize(e.typ) > 8:
       # big set:
       useStringh(p.module)
-      lineF(p, cpsStmts, "memset($1, 0, sizeof($1));$n", [rdLoc(d)])
+      lineF(p, cpsStmts, "memset($1, 0, sizeof($2));$n",
+          [rdLoc(d), getTypeDesc(p.module, e.typ)])
       for i in countup(0, sonsLen(e) - 1):
         if e.sons[i].kind == nkRange:
           getTemp(p, getSysType(tyInt), idx) # our counter
@@ -2061,6 +2063,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
 
 proc downConv(p: BProc, n: PNode, d: var TLoc) =
   if p.module.compileToCpp:
+    discard getTypeDesc(p.module, skipTypes(n[0].typ, abstractPtrs))
     expr(p, n.sons[0], d)     # downcast does C++ for us
   else:
     var dest = skipTypes(n.typ, abstractPtrs)
@@ -2069,6 +2072,7 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
     while arg.kind == nkObjDownConv: arg = arg.sons[0]
 
     var src = skipTypes(arg.typ, abstractPtrs)
+    discard getTypeDesc(p.module, src)
     var a: TLoc
     initLocExpr(p, arg, a)
     var r = rdLoc(a)
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index bdba34e36..4fc029116 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -368,6 +368,8 @@ proc getTypeForward(m: BModule, typ: PType; sig: SigHash): Rope =
     if not isImportedType(concrete):
       addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
           [structOrUnion(typ), result])
+    else:
+      pushType(m, concrete)
     doAssert m.forwTypeCache[sig] == result
   else: internalError("getTypeForward(" & $typ.kind & ')')
 
@@ -665,7 +667,6 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
         let name = getTypeForward(m, et, hashType et)
         result = name & star
         m.typeCache[sig] = result
-        pushType(m, et)
     of tySequence:
       # no restriction! We have a forward declaration for structs
       let name = getTypeForward(m, et, hashType et)
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 8b3da223f..01610010b 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -317,8 +317,10 @@ proc resetLoc(p: BProc, loc: var TLoc) =
       genObjectInit(p, cpsStmts, loc.t, loc, true)
     else:
       useStringh(p.module)
+      # array passed as argument decayed into pointer, bug #7332
+      # so we use getTypeDesc here rather than rdLoc(loc)
       linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n",
-              addrLoc(loc), rdLoc(loc))
+              addrLoc(loc), getTypeDesc(p.module, loc.t))
       # XXX: We can be extra clever here and call memset only
       # on the bytes following the m_type field?
       genObjectInit(p, cpsStmts, loc.t, loc, true)
@@ -335,7 +337,7 @@ proc constructLoc(p: BProc, loc: TLoc, isTemp = false) =
       if not isImportedCppType(typ):
         useStringh(p.module)
         linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n",
-                addrLoc(loc), rdLoc(loc))
+                addrLoc(loc), getTypeDesc(p.module, typ))
     genObjectInit(p, cpsStmts, loc.t, loc, true)
 
 proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index ac4242e67..09413128b 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -357,7 +357,9 @@ const
     errXExpectsTwoArguments: "\'$1\' expects two arguments",
     errXExpectsObjectTypes: "\'$1\' expects object types",
     errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype",
-    errTooManyIterations: "interpretation requires too many iterations",
+    errTooManyIterations: "interpretation requires too many iterations; " &
+      "if you are sure this is not a bug in your code edit " &
+      "compiler/vmdef.MaxLoopIterations and rebuild the compiler",
     errCannotInterpretNodeX: "cannot evaluate \'$1\'",
     errFieldXNotFound: "field \'$1\' cannot be found",
     errInvalidConversionFromTypeX: "invalid conversion from type \'$1\'",
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 4974abcc3..debb0b34d 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -17,6 +17,8 @@
 
 # In fact the grammar is generated from this file:
 when isMainModule:
+  # Leave a note in grammar.txt that it is generated:
+  #| # This file is generated by compiler/parser.nim.
   import pegs
   var outp = open("doc/grammar.txt", fmWrite)
   for line in lines("compiler/parser.nim"):
@@ -818,7 +820,6 @@ proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
     if realInd(p):
       p.currInd = p.tok.indent
       wasIndented = true
-      echo result.info, " yes ", p.currInd
     addSon(branch, parseExpr(p))
     result.add branch
     while sameInd(p) or not wasIndented:
@@ -962,6 +963,8 @@ proc parseTuple(p: var TParser, indentAllowed = false): PNode =
             parMessage(p, errIdentifierExpected, p.tok)
             break
           if not sameInd(p): break
+  elif p.tok.tokType == tkParLe:
+    parMessage(p, errGenerated, "the syntax for tuple types is 'tuple[...]', not 'tuple(...)'")
   else:
     result = newNodeP(nkTupleClassTy, p)
 
@@ -983,6 +986,9 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
         a = parseIdentColonEquals(p, {withBothOptional, withPragma})
       of tkParRi:
         break
+      of tkVar:
+        parMessage(p, errGenerated, "the syntax is 'parameter: var T', not 'var parameter: T'")
+        break
       else:
         parMessage(p, errTokenExpected, ")")
         break
@@ -1675,7 +1681,7 @@ proc parseSection(p: var TParser, kind: TNodeKind,
     parMessage(p, errIdentifierExpected, p.tok)
 
 proc parseConstant(p: var TParser): PNode =
-  #| constant = identWithPragma (colon typedesc)? '=' optInd expr indAndComment
+  #| constant = identWithPragma (colon typeDesc)? '=' optInd expr indAndComment
   result = newNodeP(nkConstDef, p)
   addSon(result, identWithPragma(p))
   if p.tok.tokType == tkColon:
@@ -2130,7 +2136,12 @@ proc parseTopLevelStmt(p: var TParser): PNode =
     if p.tok.indent != 0:
       if p.firstTok and p.tok.indent < 0: discard
       elif p.tok.tokType != tkSemiColon:
-        parMessage(p, errInvalidIndentation)
+        # special casing for better error messages:
+        if p.tok.tokType == tkOpr and p.tok.ident.s == "*":
+          parMessage(p, errGenerated,
+            "invalid indentation; an export marker '*' follows the declared identifier")
+        else:
+          parMessage(p, errInvalidIndentation)
     p.firstTok = false
     case p.tok.tokType
     of tkSemiColon:
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index ba38ed215..0fc12f164 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -190,12 +190,12 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
       if wanted != nil and got != nil:
         effectProblem(wanted, got, candidates)
       if cond: candidates.add "\n"
-    elif err.unmatchedVarParam != 0 and err.unmatchedVarParam < n.len:
-      add(candidates, "for a 'var' type a variable needs to be passed, but '" &
+    if err.unmatchedVarParam != 0 and err.unmatchedVarParam < n.len:
+      candidates.add("  for a 'var' type a variable needs to be passed, but '" &
                       renderNotLValue(n[err.unmatchedVarParam]) &
                       "' is immutable\n")
     for diag in err.diagnostics:
-      add(candidates, diag & "\n")
+      candidates.add(diag & "\n")
 
   result = (prefer, candidates)
 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 8e3aeffbe..49beadc8b 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -192,6 +192,10 @@ proc semConv(c: PContext, n: PNode): PNode =
 
   result.addSon copyTree(n.sons[0])
 
+  # special case to make MyObject(x = 3) produce a nicer error message:
+  if n[1].kind == nkExprEqExpr and
+      targetType.skipTypes(abstractPtrs).kind == tyObject:
+    localError(n.info, "object contruction uses ':', not '='")
   var op = semExprWithType(c, n.sons[1])
   if targetType.isMetaType:
     let final = inferWithMetatype(c, targetType, op, true)
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index e9f4e1a98..be6eac052 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -257,7 +257,8 @@ proc semArrayIndex(c: PContext, n: PNode): PType =
       if e.sym.ast != nil:
         return semArrayIndex(c, e.sym.ast)
       if not isOrdinalType(e.typ.lastSon):
-        localError(n[1].info, errOrdinalTypeExpected)
+        let info = if n.safeLen > 1: n[1].info else: n.info
+        localError(info, errOrdinalTypeExpected)
       result = makeRangeWithStaticExpr(c, e)
       if c.inGenericContext > 0: result.flags.incl tfUnresolved
     elif e.kind in nkCallKinds and hasGenericArguments(e):
@@ -719,7 +720,8 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
           addInheritedFields(c, check, pos, concreteBase)
       else:
         if concreteBase.kind != tyError:
-          localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
+          localError(n.sons[1].info, "inheritance only works with non-final objects; " &
+             "to enable inheritance write '" & typeToString(realBase) & " of RootObj'")
         base = nil
         realBase = nil
   if n.kind != nkObjectTy: internalError(n.info, "semObjectNode")
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 9f802a10e..e4509ff91 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -1242,7 +1242,9 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
         if result < isGeneric: result = isNone
     elif a.kind == tyGenericParam:
       result = isGeneric
-  of tyForward: internalError("forward type in typeRel()")
+  of tyForward:
+    #internalError("forward type in typeRel()")
+    result = isNone
   of tyNil:
     if a.kind == f.kind: result = isEqual
   of tyTuple:
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 23216f0a3..6ea6f1492 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -1490,7 +1490,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
           c.debug[pc])
       x.flags.incl nfIsRef
       # prevent crashes in the compiler resulting from wrong macros:
-      if x.kind == nkIdent: x.ident = getIdent""
+      if x.kind == nkIdent: x.ident = c.cache.emptyIdent
       regs[ra].node = x
     of opcNCopyNimNode:
       decodeB(rkNode)
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index 5395d4bad..dd4bc5060 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -16,7 +16,7 @@ const
   byteExcess* = 128 # we use excess-K for immediates
   wordExcess* = 32768
 
-  MaxLoopIterations* = 1500_000 # max iterations of all loops
+  MaxLoopIterations* = 1_000_000_000 # max iterations of all loops
 
 
 type
diff --git a/doc/grammar.txt b/doc/grammar.txt
index eae3694a0..f25b079f4 100644
--- a/doc/grammar.txt
+++ b/doc/grammar.txt
@@ -1,3 +1,4 @@
+# This file is generated by compiler/parser.nim.
 module = stmt ^* (';' / IND{=})
 comma = ',' COMMENT?
 semicolon = ';' COMMENT?
@@ -155,7 +156,7 @@ routine = optInd identVis pattern? genericParamList?
   paramListColon pragma? ('=' COMMENT? stmt)? indAndComment
 commentStmt = COMMENT
 section(p) = COMMENT? p / (IND{>} (p / COMMENT)^+IND{=} DED)
-constant = identWithPragma (colon typedesc)? '=' optInd expr indAndComment
+constant = identWithPragma (colon typeDesc)? '=' optInd expr indAndComment
 enum = 'enum' optInd (symbol optInd ('=' optInd expr COMMENT?)? comma?)+
 objectWhen = 'when' expr colcom objectPart COMMENT?
             ('elif' expr colcom objectPart COMMENT?)*
diff --git a/doc/manual/lexing.txt b/doc/manual/lexing.txt
index 915e87971..0328ffd55 100644
--- a/doc/manual/lexing.txt
+++ b/doc/manual/lexing.txt
@@ -344,9 +344,11 @@ prefix), binary (prefix ``0b``), octal (prefix ``0o`` or ``0c``) and hexadecimal
 
 There exists a literal for each numerical type that is
 defined. The suffix starting with an apostrophe ('\'') is called a
-`type suffix`:idx:. Literals without a type suffix are of the type ``int``,
+`type suffix`:idx:. Literals without a type suffix are of an integer type,
 unless the literal contains a dot or ``E|e`` in which case it is of
-type ``float``. For notational convenience the apostrophe of a type suffix
+type ``float``. This integer type is ``int`` if the literal is in the range
+``low(i32)..high(i32)``, otherwise it is ``int64``.
+For notational convenience the apostrophe of a type suffix
 is optional if it is not ambiguous (only hexadecimal floating point literals
 with a type suffix can be ambiguous).
 
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index ed9c304fe..d09f5f933 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -678,7 +678,7 @@ proc astGenRepr*(n: NimNode): string {.compileTime, benign.} =
   ## See also `repr`, `treeRepr`, and `lispRepr`.
 
   const
-    NodeKinds = {nnkEmpty, nnkNilLit, nnkIdent, nnkSym, nnkNone}
+    NodeKinds = {nnkEmpty, nnkNilLit, nnkIdent, nnkSym, nnkNone, nnkCommentStmt}
     LitKinds = {nnkCharLit..nnkInt64Lit, nnkFloatLit..nnkFloat64Lit, nnkStrLit..nnkTripleStrLit}
 
   proc escape(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect.} =
@@ -723,7 +723,7 @@ proc astGenRepr*(n: NimNode): string {.compileTime, benign.} =
     of nnkCharLit: res.add("'" & $chr(n.intVal) & "'")
     of nnkIntLit..nnkInt64Lit: res.add($n.intVal)
     of nnkFloatLit..nnkFloat64Lit: res.add($n.floatVal)
-    of nnkStrLit..nnkTripleStrLit: res.add($n.strVal.escape())
+    of nnkStrLit..nnkTripleStrLit, nnkCommentStmt: res.add($n.strVal.escape())
     of nnkIdent: res.add(($n.ident).escape())
     of nnkSym: res.add(($n.symbol).escape())
     of nnkNone: assert false
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index 23a0cdb02..2f7b44b31 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -84,7 +84,7 @@ proc smartBinarySearch*[T](a: openArray[T], key: T): int =
 const
   onlySafeCode = true
 
-proc lowerBound*[T](a: openArray[T], key: T, cmp: proc(x,y: T): int {.closure.}): int =
+proc lowerBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): int {.closure.}): int =
   ## same as binarySearch except that if key is not in `a` then this
   ## returns the location where `key` would be if it were. In other
   ## words if you have a sorted sequence and you call
diff --git a/lib/pure/asyncfile.nim b/lib/pure/asyncfile.nim
index 97bec2815..1df7c3fc0 100644
--- a/lib/pure/asyncfile.nim
+++ b/lib/pure/asyncfile.nim
@@ -78,7 +78,10 @@ proc getFileSize*(f: AsyncFile): int64 =
       raiseOSError(osLastError())
     result = (high shl 32) or low
   else:
+    let curPos = lseek(f.fd.cint, 0, SEEK_CUR)
     result = lseek(f.fd.cint, 0, SEEK_END)
+    f.offset = lseek(f.fd.cint, curPos, SEEK_SET)
+    assert(f.offset == curPos)
 
 proc newAsyncFile*(fd: AsyncFd): AsyncFile =
   ## Creates `AsyncFile` with a previously opened file descriptor `fd`.
@@ -281,6 +284,7 @@ proc read*(f: AsyncFile, size: int): Future[string] =
           result = false # We still want this callback to be called.
       elif res == 0:
         # EOF
+        f.offset = lseek(fd.cint, 0, SEEK_CUR)
         retFuture.complete("")
       else:
         readBuffer.setLen(res)
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 648481ca5..568e453bd 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -622,7 +622,7 @@ proc get*(url: string, extraHeaders = "", maxRedirects = 5,
   ## | An optional timeout can be specified in milliseconds, if reading from the
   ## server takes longer than specified an ETimeout exception will be raised.
   ##
-  ## ## **Deprecated since version 0.15.0**: use ``HttpClient.get`` instead.
+  ## **Deprecated since version 0.15.0**: use ``HttpClient.get`` instead.
   result = request(url, httpGET, extraHeaders, "", sslContext, timeout,
                    userAgent, proxy)
   var lastURL = url
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index bbde4db5f..2b58d154e 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -734,7 +734,7 @@ proc getFields*(n: JsonNode,
   else: return n.fields
 
 proc getElems*(n: JsonNode, default: seq[JsonNode] = @[]): seq[JsonNode] =
-  ## Retrieves the int value of a `JArray JsonNode`.
+  ## Retrieves the array of a `JArray JsonNode`.
   ##
   ## Returns ``default`` if ``n`` is not a ``JArray``, or if ``n`` is nil.
   if n.isNil or n.kind != JArray: return default
diff --git a/lib/pure/xmlparser.nim b/lib/pure/xmlparser.nim
index 22bd259b7..9159b4bfc 100644
--- a/lib/pure/xmlparser.nim
+++ b/lib/pure/xmlparser.nim
@@ -12,9 +12,9 @@
 import streams, parsexml, strtabs, xmltree
 
 type
-  XmlError* = object of ValueError ## exception that is raised
-                                   ## for invalid XML
-    errors*: seq[string]           ## all detected parsing errors
+  XmlError* = object of ValueError ## Exception that is raised
+                                   ## for invalid XML.
+    errors*: seq[string]           ## All detected parsing errors.
 
 {.deprecated: [EInvalidXml: XmlError].}
 
@@ -102,8 +102,8 @@ proc parse(x: var XmlParser, errors: var seq[string]): XmlNode =
 
 proc parseXml*(s: Stream, filename: string,
                errors: var seq[string]): XmlNode =
-  ## parses the XML from stream `s` and returns a ``PXmlNode``. Every
-  ## occurred parsing error is added to the `errors` sequence.
+  ## Parses the XML from stream ``s`` and returns a ``XmlNode``. Every
+  ## occurred parsing error is added to the ``errors`` sequence.
   var x: XmlParser
   open(x, s, filename, {reportComments})
   while true:
@@ -121,15 +121,20 @@ proc parseXml*(s: Stream, filename: string,
   close(x)
 
 proc parseXml*(s: Stream): XmlNode =
-  ## parses the XTML from stream `s` and returns a ``PXmlNode``. All parsing
-  ## errors are turned into an ``EInvalidXML`` exception.
+  ## Parses the XML from stream ``s`` and returns a ``XmlNode``. All parsing
+  ## errors are turned into an ``XmlError`` exception.
   var errors: seq[string] = @[]
-  result = parseXml(s, "unknown_html_doc", errors)
+  result = parseXml(s, "unknown_xml_doc", errors)
   if errors.len > 0: raiseInvalidXml(errors)
 
+proc parseXml*(str: string): XmlNode =
+  ## Parses the XML from string ``str`` and returns a ``XmlNode``. All parsing
+  ## errors are turned into an ``XmlError`` exception.
+  parseXml(newStringStream(str))
+
 proc loadXml*(path: string, errors: var seq[string]): XmlNode =
   ## Loads and parses XML from file specified by ``path``, and returns
-  ## a ``PXmlNode``. Every occurred parsing error is added to the `errors`
+  ## a ``XmlNode``. Every occurred parsing error is added to the ``errors``
   ## sequence.
   var s = newFileStream(path, fmRead)
   if s == nil: raise newException(IOError, "Unable to read file: " & path)
@@ -137,7 +142,7 @@ proc loadXml*(path: string, errors: var seq[string]): XmlNode =
 
 proc loadXml*(path: string): XmlNode =
   ## Loads and parses XML from file specified by ``path``, and returns
-  ## a ``PXmlNode``.  All parsing errors are turned into an ``EInvalidXML``
+  ## a ``XmlNode``. All parsing errors are turned into an ``XmlError``
   ## exception.
   var errors: seq[string] = @[]
   result = loadXml(path, errors)
diff --git a/lib/system.nim b/lib/system.nim
index b71a3c73c..7a8c81666 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -1774,7 +1774,7 @@ when not defined(nimscript):
     proc createU*(T: typedesc, size = 1.Positive): ptr T {.inline, benign.} =
       ## allocates a new memory block with at least ``T.sizeof * size``
       ## bytes. The block has to be freed with ``resize(block, 0)`` or
-      ## ``free(block)``. The block is not initialized, so reading
+      ## ``dealloc(block)``. The block is not initialized, so reading
       ## from it before writing to it is undefined behaviour!
       ## The allocated memory belongs to its allocating thread!
       ## Use `createSharedU` to allocate from a shared heap.
@@ -1789,7 +1789,7 @@ when not defined(nimscript):
     proc create*(T: typedesc, size = 1.Positive): ptr T {.inline, benign.} =
       ## allocates a new memory block with at least ``T.sizeof * size``
       ## bytes. The block has to be freed with ``resize(block, 0)`` or
-      ## ``free(block)``. The block is initialized with all bytes
+      ## ``dealloc(block)``. The block is initialized with all bytes
       ## containing zero, so it is somewhat safer than ``createU``.
       ## The allocated memory belongs to its allocating thread!
       ## Use `createShared` to allocate from a shared heap.
@@ -1807,7 +1807,7 @@ when not defined(nimscript):
       ## grows or shrinks a given memory block. If p is **nil** then a new
       ## memory block is returned. In either way the block has at least
       ## ``T.sizeof * newSize`` bytes. If ``newSize == 0`` and p is not
-      ## **nil** ``resize`` calls ``free(p)``. In other cases the block
+      ## **nil** ``resize`` calls ``dealloc(p)``. In other cases the block
       ## has to be freed with ``free``. The allocated memory belongs to
       ## its allocating thread!
       ## Use `resizeShared` to reallocate from a shared heap.
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index 4291013a2..6aef4f411 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -29,7 +29,9 @@ const
   FliOffset = 6
   RealFli = MaxFli - FliOffset
 
-  HugeChunkSize = int high(int32) - 1 # 2 GB, depends on TLSF's impl
+  # size of chunks in last matrix bin
+  MaxBigChunkSize = 1 shl MaxFli - 1 shl (MaxFli-MaxLog2Sli-1)
+  HugeChunkSize = MaxBigChunkSize + 1
 
 type
   PTrunk = ptr Trunk
@@ -154,10 +156,11 @@ proc mappingSearch(r, fl, sl: var int) {.inline.} =
   # PageSize alignment:
   let t = roundup((1 shl (msbit(uint32 r) - MaxLog2Sli)), PageSize) - 1
   r = r + t
+  r = r and not t
+  r = min(r, MaxBigChunkSize)
   fl = msbit(uint32 r)
   sl = (r shr (fl - MaxLog2Sli)) - MaxSli
   dec fl, FliOffset
-  r = r and not t
   sysAssert((r and PageMask) == 0, "mappingSearch: still not aligned")
 
 # See http://www.gii.upv.es/tlsf/files/papers/tlsf_desc.pdf for details of
@@ -518,55 +521,61 @@ proc updatePrevSize(a: var MemRegion, c: PBigChunk,
   if isAccessible(a, ri):
     ri.prevSize = prevSize or (ri.prevSize and 1)
 
+proc splitChunk2(a: var MemRegion, c: PBigChunk, size: int): PBigChunk =
+  result = cast[PBigChunk](cast[ByteAddress](c) +% size)
+  result.size = c.size - size
+  track("result.origSize", addr result.origSize, sizeof(int))
+  # XXX check if these two nil assignments are dead code given
+  # addChunkToMatrix's implementation:
+  result.next = nil
+  result.prev = nil
+  # size and not used:
+  result.prevSize = size
+  sysAssert((size and 1) == 0, "splitChunk 2")
+  sysAssert((size and PageMask) == 0,
+      "splitChunk: size is not a multiple of the PageSize")
+  updatePrevSize(a, c, result.size)
+  c.size = size
+  incl(a, a.chunkStarts, pageIndex(result))
+
+proc splitChunk(a: var MemRegion, c: PBigChunk, size: int) =
+  let rest = splitChunk2(a, c, size)
+  addChunkToMatrix(a, rest)
+
 proc freeBigChunk(a: var MemRegion, c: PBigChunk) =
   var c = c
   sysAssert(c.size >= PageSize, "freeBigChunk")
   inc(a.freeMem, c.size)
-  when coalescRight:
-    var ri = cast[PChunk](cast[ByteAddress](c) +% c.size)
-    sysAssert((cast[ByteAddress](ri) and PageMask) == 0, "freeBigChunk 2")
-    if isAccessible(a, ri) and chunkUnused(ri):
-      sysAssert(not isSmallChunk(ri), "freeBigChunk 3")
-      if not isSmallChunk(ri):
-        removeChunkFromMatrix(a, cast[PBigChunk](ri))
-        inc(c.size, ri.size)
-        excl(a.chunkStarts, pageIndex(ri))
+  c.prevSize = c.prevSize and not 1  # set 'used' to false
   when coalescLeft:
-    let prevSize = c.prevSize and not 1
+    let prevSize = c.prevSize
     if prevSize != 0:
       var le = cast[PChunk](cast[ByteAddress](c) -% prevSize)
       sysAssert((cast[ByteAddress](le) and PageMask) == 0, "freeBigChunk 4")
       if isAccessible(a, le) and chunkUnused(le):
         sysAssert(not isSmallChunk(le), "freeBigChunk 5")
-        if not isSmallChunk(le):
+        if not isSmallChunk(le) and le.size < MaxBigChunkSize:
           removeChunkFromMatrix(a, cast[PBigChunk](le))
           inc(le.size, c.size)
           excl(a.chunkStarts, pageIndex(c))
           c = cast[PBigChunk](le)
-
-  incl(a, a.chunkStarts, pageIndex(c))
-  updatePrevSize(a, c, c.size)
+          if c.size > MaxBigChunkSize:
+            let rest = splitChunk2(a, c, MaxBigChunkSize)
+            addChunkToMatrix(a, c)
+            c = rest
+  when coalescRight:
+    var ri = cast[PChunk](cast[ByteAddress](c) +% c.size)
+    sysAssert((cast[ByteAddress](ri) and PageMask) == 0, "freeBigChunk 2")
+    if isAccessible(a, ri) and chunkUnused(ri):
+      sysAssert(not isSmallChunk(ri), "freeBigChunk 3")
+      if not isSmallChunk(ri) and c.size < MaxBigChunkSize:
+        removeChunkFromMatrix(a, cast[PBigChunk](ri))
+        inc(c.size, ri.size)
+        excl(a.chunkStarts, pageIndex(ri))
+        if c.size > MaxBigChunkSize:
+          let rest = splitChunk2(a, c, MaxBigChunkSize)
+          addChunkToMatrix(a, rest)
   addChunkToMatrix(a, c)
-  # set 'used' to false:
-  c.prevSize = c.prevSize and not 1
-
-proc splitChunk(a: var MemRegion, c: PBigChunk, size: int) =
-  var rest = cast[PBigChunk](cast[ByteAddress](c) +% size)
-  rest.size = c.size - size
-  track("rest.origSize", addr rest.origSize, sizeof(int))
-  # XXX check if these two nil assignments are dead code given
-  # addChunkToMatrix's implementation:
-  rest.next = nil
-  rest.prev = nil
-  # size and not used:
-  rest.prevSize = size
-  sysAssert((size and 1) == 0, "splitChunk 2")
-  sysAssert((size and PageMask) == 0,
-      "splitChunk: size is not a multiple of the PageSize")
-  updatePrevSize(a, c, rest.size)
-  c.size = size
-  incl(a, a.chunkStarts, pageIndex(rest))
-  addChunkToMatrix(a, rest)
 
 proc getBigChunk(a: var MemRegion, size: int): PBigChunk =
   sysAssert(size > 0, "getBigChunk 2")
diff --git a/tests/async/hello.txt b/tests/async/hello.txt
new file mode 100644
index 000000000..854d6c20a
--- /dev/null
+++ b/tests/async/hello.txt
@@ -0,0 +1 @@
+hello humans!
\ No newline at end of file
diff --git a/tests/async/tasyncfile.nim b/tests/async/tasyncfile.nim
index aa7f03ab1..c7b71a2f7 100644
--- a/tests/async/tasyncfile.nim
+++ b/tests/async/tasyncfile.nim
@@ -1,4 +1,8 @@
 discard """
+  output: '''13
+hello humans!
+13
+'''
   file: "tasyncfile.nim"
   exitcode: 0
 """
@@ -48,5 +52,12 @@ proc main() {.async.} =
     doAssert data == "t3"
     file.close()
 
+  # Issue #7347
+  block:
+    let appDir = getAppDir()
+    var file = openAsync(appDir & DirSep & "hello.txt")
+    echo file.getFileSize()
+    echo await file.readAll()
+    echo file.getFilePos()
 
 waitFor main()
diff --git a/tests/ccgbugs/mymodule.nim b/tests/ccgbugs/mymodule.nim
new file mode 100644
index 000000000..d3306ec49
--- /dev/null
+++ b/tests/ccgbugs/mymodule.nim
@@ -0,0 +1,12 @@
+type
+  MyRefObject* = ref object
+    s: string
+
+
+proc newMyRefObject*(s: string): MyRefObject =
+  new(result)
+  result.s = s
+  
+proc `$`*(o: MyRefObject): string =
+  o.s
+  
\ No newline at end of file
diff --git a/tests/ccgbugs/tforward_decl_only.nim b/tests/ccgbugs/tforward_decl_only.nim
new file mode 100644
index 000000000..dcd74eaf4
--- /dev/null
+++ b/tests/ccgbugs/tforward_decl_only.nim
@@ -0,0 +1,15 @@
+discard """
+ccodecheck: "\\i !@('struct tyObject_MyRefObject'[0-z]+' {')"
+output: "hello"
+"""
+
+# issue #7339 
+# Test that MyRefObject is only forward declared as it used only by reference
+
+import mymodule
+type AnotherType = object
+  f: MyRefObject 
+
+let x = AnotherType(f: newMyRefObject("hello"))
+echo $x.f
+
diff --git a/tests/ccgbugs/tresult_of_array.nim b/tests/ccgbugs/tresult_of_array.nim
new file mode 100644
index 000000000..fb5abf18a
--- /dev/null
+++ b/tests/ccgbugs/tresult_of_array.nim
@@ -0,0 +1,29 @@
+discard """
+  output: '''false
+true
+false
+[false, false, false]
+'''
+"""
+
+# bug #7332
+# resetLoc generate incorrect memset code
+# because of array passed as argument decaying into a pointer
+
+import tables
+const tableOfArray = {
+    "one": [true, false, false],
+    "two": [false, true, false],
+    "three": [false, false, true]
+}.toTable()
+for i in 0..2:
+    echo tableOfArray["two"][i]
+
+var seqOfArray = @[
+    [true, false, false],
+    [false, true, false],
+    [false, false, true]
+]
+proc crashingProc*[B](t: seq[B], index: Natural): B =
+    discard
+echo seqOfArray.crashingProc(0)
diff --git a/tests/macros/tdumpastgen.nim b/tests/macros/tdumpastgen.nim
index faed77225..0a1836886 100644
--- a/tests/macros/tdumpastgen.nim
+++ b/tests/macros/tdumpastgen.nim
@@ -2,16 +2,33 @@ discard """
 msg: '''nnkStmtList.newTree(
   nnkVarSection.newTree(
     nnkIdentDefs.newTree(
-      newIdentNode(!"x"),
+      newIdentNode("x"),
       newEmptyNode(),
       nnkCall.newTree(
         nnkDotExpr.newTree(
-          newIdentNode(!"foo"),
-          newIdentNode(!"create")
+          newIdentNode("baz"),
+          newIdentNode("create")
         ),
         newLit(56)
       )
     )
+  ),
+  nnkProcDef.newTree(
+    newIdentNode("foo"),
+    newEmptyNode(),
+    newEmptyNode(),
+    nnkFormalParams.newTree(
+      newEmptyNode()
+    ),
+    newEmptyNode(),
+    newEmptyNode(),
+    nnkStmtList.newTree(
+      newCommentStmtNode("This is a docstring"),
+      nnkCommand.newTree(
+        newIdentNode("echo"),
+        newLit("bar")
+      )
+    )
   )
 )'''
 """
@@ -21,5 +38,8 @@ msg: '''nnkStmtList.newTree(
 import macros
 
 dumpAstGen:
-  var x = foo.create(56)
+  var x = baz.create(56)
 
+  proc foo() =
+    ## This is a docstring
+    echo "bar"
diff --git a/tests/system/alloc.nim b/tests/system/talloc.nim
index 7abefec2a..18396041d 100644
--- a/tests/system/alloc.nim
+++ b/tests/system/talloc.nim
@@ -8,7 +8,7 @@ x.dealloc()
 
 x = createU(int, 3)
 assert x != nil
-x.free()
+x.dealloc()
 
 x = create(int, 4)
 assert cast[ptr array[4, int]](x)[0] == 0
@@ -18,7 +18,7 @@ assert cast[ptr array[4, int]](x)[3] == 0
 
 x = x.resize(4)
 assert x != nil
-x.free()
+x.dealloc()
 
 x = cast[ptr int](allocShared(100))
 assert x != nil
@@ -26,7 +26,7 @@ deallocShared(x)
 
 x = createSharedU(int, 3)
 assert x != nil
-x.freeShared()
+x.deallocShared()
 
 x = createShared(int, 3)
 assert x != nil
@@ -37,7 +37,7 @@ assert cast[ptr array[3, int]](x)[2] == 0
 assert x != nil
 x = cast[ptr int](x.resizeShared(2))
 assert x != nil
-x.freeShared()
+x.deallocShared()
 
 x = create(int, 10)
 assert x != nil
@@ -49,4 +49,9 @@ x = createShared(int, 1)
 assert x != nil
 x = x.resizeShared(1)
 assert x != nil
-x.freeShared()
+x.deallocShared()
+
+x = cast[ptr int](alloc0(125 shl 23))
+dealloc(x)
+x = cast[ptr int](alloc0(126 shl 23))
+dealloc(x)
diff --git a/tests/system/talloc2.nim b/tests/system/talloc2.nim
new file mode 100644
index 000000000..c8cab78a1
--- /dev/null
+++ b/tests/system/talloc2.nim
@@ -0,0 +1,37 @@
+const
+  nmax = 2*1024*1024*1024
+
+proc test(n: int) =
+  var a = alloc0(9999)
+  var t = cast[ptr UncheckedArray[int8]](alloc(n))
+  var b = alloc0(9999)
+  t[0] = 1
+  t[1] = 2
+  t[n-2] = 3
+  t[n-1] = 4
+  dealloc(a)
+  dealloc(t)
+  dealloc(b)
+
+# allocator adds 48 bytes to BigChunk
+# BigChunk allocator edges at 2^n * (1 - s) for s = [1..32]/64
+proc test2(n: int) =
+  let d = n div 256  # cover edges and more
+  for i in countdown(128,1):
+    for j in [-4096, -64, -49, -48, -47, -32, 0, 4096]:
+      let b = n + j - i*d
+      if b>0 and b<=nmax:
+        test(b)
+        #echo b, ": ", getTotalMem(), " ", getOccupiedMem(), " ", getFreeMem()
+
+proc test3 =
+  var n = 1
+  while n <= nmax:
+    test2(n)
+    n *= 2
+  n = nmax
+  while n >= 1:
+    test2(n)
+    n = n div 2
+
+test3()
diff --git a/tests/system/io.nim b/tests/system/tio.nim
index 3d4df806b..3d4df806b 100644
--- a/tests/system/io.nim
+++ b/tests/system/tio.nim
diff --git a/tests/system/params.nim b/tests/system/tparams.nim
index 1358212f2..1358212f2 100644
--- a/tests/system/params.nim
+++ b/tests/system/tparams.nim
diff --git a/todo.txt b/todo.txt
index e06ddf555..32bc32630 100644
--- a/todo.txt
+++ b/todo.txt
@@ -45,7 +45,6 @@ Bugs
 
 - VM: Pegs do not work at compile-time
 - blocks can "export" an identifier but the CCG generates {} for them ...
-- ConcreteTypes in a 'case' means we don't check for duplicated case branches
 
 
 GC