summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorDominik Picheta <dominikpicheta@gmail.com>2016-04-04 12:06:42 +0100
committerDominik Picheta <dominikpicheta@gmail.com>2016-04-04 12:06:42 +0100
commit436b0031736b7b569f18a90c67e62a483716037a (patch)
treed938d5efd6ea4125c9f5d543ccca7489e637a4cb
parenta70e6b3fde7c251aff68243de1c7adcebc3c67e3 (diff)
parentfbedb6c65514e394f163a68dd530d19d310afadf (diff)
downloadNim-436b0031736b7b569f18a90c67e62a483716037a.tar.gz
Merge branch 'devel' of github.com:nim-lang/Nim into devel
-rw-r--r--compiler/ccgexprs.nim14
-rw-r--r--compiler/cgen.nim3
-rw-r--r--compiler/lambdalifting.nim4
-rw-r--r--compiler/parser.nim1
-rw-r--r--compiler/pragmas.nim5
-rw-r--r--compiler/vm.nim11
-rw-r--r--compiler/vmgen.nim28
-rw-r--r--doc/backends.txt2
-rw-r--r--doc/manual/typedesc.txt32
-rw-r--r--lib/core/locks.nim3
-rw-r--r--lib/core/rlocks.nim1
-rw-r--r--lib/posix/posix.nim13
-rw-r--r--lib/pure/collections/chains.nim44
-rw-r--r--lib/pure/mersenne.nim28
-rw-r--r--lib/pure/net.nim4
-rw-r--r--lib/pure/parseutils.nim41
-rw-r--r--lib/pure/strutils.nim18
-rw-r--r--lib/system.nim1
-rw-r--r--lib/system/dyncalls.nim25
-rw-r--r--lib/system/syslocks.nim61
-rw-r--r--tests/closure/tflatmap.nim24
-rw-r--r--tests/macros/typesafeprintf.nim48
-rw-r--r--tests/stdlib/tparseuints.nim11
-rw-r--r--tests/vm/tanonproc.nim52
-rw-r--r--tests/vm/tinheritance.nim29
-rw-r--r--tests/vm/tmitems.nim31
-rw-r--r--tests/vm/twrong_concat.nim28
-rw-r--r--web/news.txt3
28 files changed, 463 insertions, 102 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 4fcbeeec2..d84a7d92e 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1856,10 +1856,16 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
     initLocExpr(p, n.sons[1], b)
     if n.sons[0].skipConv.kind == nkClosure:
       internalError(n.info, "closure to closure created")
-    getTemp(p, n.typ, tmp)
-    linefmt(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n",
-            tmp.rdLoc, a.rdLoc, b.rdLoc)
-    putLocIntoDest(p, d, tmp)
+    # tasyncawait.nim breaks with this optimization:
+    when false:
+      if d.k != locNone:
+        linefmt(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n",
+                d.rdLoc, a.rdLoc, b.rdLoc)
+    else:
+      getTemp(p, n.typ, tmp)
+      linefmt(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n",
+              tmp.rdLoc, a.rdLoc, b.rdLoc)
+      putLocIntoDest(p, d, tmp)
 
 proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) =
   var arr: TLoc
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index db376821c..4f27a5a46 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -1059,9 +1059,8 @@ proc genModule(m: BModule, cfile: string): Rope =
   result = getFileHeader(cfile)
   result.add(genMergeInfo(m))
 
-  generateHeaders(m)
-
   generateThreadLocalStorage(m)
+  generateHeaders(m)
   for i in countup(cfsHeaders, cfsProcs):
     add(result, genSectionStart(i))
     add(result, m.s[i])
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 53fca4863..959632bab 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -721,6 +721,10 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
       let m = newSymNode(n[namePos].sym)
       m.typ = n.typ
       result = liftCapturedVars(m, owner, d, c)
+  of nkHiddenStdConv:
+    if n.len == 2:
+      n.sons[1] = liftCapturedVars(n[1], owner, d, c)
+      if n[1].kind == nkClosure: result = n[1]
   else:
     if owner.isIterator:
       if n.kind == nkYieldStmt:
diff --git a/compiler/parser.nim b/compiler/parser.nim
index f22177ac1..1ba59b938 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -326,6 +326,7 @@ proc parseSymbol(p: var TParser, allowNil = false): PNode =
         getTok(p)
       else:
         parMessage(p, errIdentifierExpected, p.tok)
+        break
     eat(p, tkAccent)
   else:
     if allowNil and p.tok.tokType == tkNil:
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 2280ef712..38d17eb62 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -256,8 +256,9 @@ proc expectDynlibNode(c: PContext, n: PNode): PNode =
 
 proc processDynLib(c: PContext, n: PNode, sym: PSym) =
   if (sym == nil) or (sym.kind == skModule):
-    POptionEntry(c.optionStack.tail).dynlib = getLib(c, libDynamic,
-        expectDynlibNode(c, n))
+    let lib = getLib(c, libDynamic, expectDynlibNode(c, n))
+    if not lib.isOverriden:
+      POptionEntry(c.optionStack.tail).dynlib = lib
   else:
     if n.kind == nkExprColonExpr:
       var lib = getLib(c, libDynamic, expectDynlibNode(c, n))
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 7220e1b8e..f799334d6 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -10,7 +10,9 @@
 ## This file implements the new evaluation engine for Nim code.
 ## An instruction is 1-3 int32s in memory, it is a register based VM.
 
-const debugEchoCode = false
+const
+  debugEchoCode = false
+  traceCode = debugEchoCode
 
 import ast except getstr
 
@@ -121,7 +123,7 @@ template move(a, b: expr) {.immediate, dirty.} = system.shallowCopy(a, b)
 # XXX fix minor 'shallowCopy' overloading bug in compiler
 
 proc createStrKeepNode(x: var TFullReg; keepNode=true) =
-  if x.node.isNil:
+  if x.node.isNil or not keepNode:
     x.node = newNode(nkStrLit)
   elif x.node.kind == nkNilLit and keepNode:
     when defined(useNodeIds):
@@ -404,7 +406,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     let instr = c.code[pc]
     let ra = instr.regA
     #if c.traceActive:
-    #echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra, " rb ", instr.regB, " rc ", instr.regC
+    when traceCode:
+      echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra, " rb ", instr.regB, " rc ", instr.regC
     #  message(c.debug[pc], warnUser, "Trace")
 
     case instr.opcode
@@ -542,7 +545,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
         if regs[rb].node.kind == nkRefTy:
           regs[ra].node = regs[rb].node.sons[0]
         else:
-          stackTrace(c, tos, pc, errGenerated, "limited VM support for 'ref'")
+          stackTrace(c, tos, pc, errGenerated, "limited VM support for pointers")
       else:
         stackTrace(c, tos, pc, errNilAccess)
     of opcWrDeref:
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 47f16a013..019c79eb3 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -102,6 +102,10 @@ proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) =
   let ins = (opc.uint32 or (a.uint32 shl 8'u32) or
                            (b.uint32 shl 16'u32) or
                            (c.uint32 shl 24'u32)).TInstr
+  when false:
+    if ctx.code.len == 43:
+      writeStackTrace()
+      echo "generating ", opc
   ctx.code.add(ins)
   ctx.debug.add(n.info)
 
@@ -122,6 +126,11 @@ proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: BiggestInt) =
 proc gABx(c: PCtx; n: PNode; opc: TOpcode; a: TRegister = 0; bx: int) =
   # Applies `opc` to `bx` and stores it into register `a`
   # `bx` must be signed and in the range [-32768, 32767]
+  when false:
+    if c.code.len == 43:
+      writeStackTrace()
+      echo "generating ", opc
+
   if bx >= -32768 and bx <= 32767:
     let ins = (opc.uint32 or a.uint32 shl 8'u32 or
               (bx+wordExcess).uint32 shl 16'u32).TInstr
@@ -704,6 +713,10 @@ proc genAddSubInt(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
   c.genNarrow(n, dest)
 
 proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
+  if n.typ.kind == arg.typ.kind and arg.typ.kind == tyProc:
+    # don't do anything for lambda lifting conversions:
+    gen(c, arg, dest)
+    return
   let tmp = c.genx(arg)
   if dest < 0: dest = c.getTemp(n.typ)
   c.gABC(n, opc, dest, tmp)
@@ -1117,7 +1130,10 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
   if isAddr and (let m = canElimAddr(n); m != nil):
     gen(c, m, dest, flags)
     return
-  let newflags = if isAddr: flags+{gfAddrOf} else: flags
+
+  let af = if n[0].kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr}: {gfAddrOf, gfFieldAccess}
+           else: {gfAddrOf}
+  let newflags = if isAddr: flags+af else: flags
   # consider:
   # proc foo(f: var ref int) =
   #   f = new(int)
@@ -1132,7 +1148,7 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
     if gfAddrOf notin flags and fitsRegister(n.typ):
       c.gABC(n, opcNodeToReg, dest, dest)
   elif isAddr and isGlobal(n.sons[0]):
-    gen(c, n.sons[0], dest, flags+{gfAddrOf})
+    gen(c, n.sons[0], dest, flags+af)
   else:
     let tmp = c.genx(n.sons[0], newflags)
     if dest < 0: dest = c.getTemp(n.typ)
@@ -1447,12 +1463,12 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
   of tyObject:
     result = newNodeIT(nkObjConstr, info, t)
     result.add(newNodeIT(nkEmpty, info, t))
-    getNullValueAux(t.n, result)
     # initialize inherited fields:
     var base = t.sons[0]
     while base != nil:
       getNullValueAux(skipTypes(base, skipPtrs).n, result)
       base = base.sons[0]
+    getNullValueAux(t.n, result)
   of tyArray, tyArrayConstr:
     result = newNodeIT(nkBracket, info, t)
     for i in countup(0, int(lengthOrd(t)) - 1):
@@ -1736,9 +1752,9 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
   of declarativeDefs:
     unused(n, dest)
   of nkLambdaKinds:
-    let s = n.sons[namePos].sym
-    discard genProc(c, s)
-    genLit(c, n.sons[namePos], dest)
+    #let s = n.sons[namePos].sym
+    #discard genProc(c, s)
+    genLit(c, newSymNode(n.sons[namePos].sym), dest)
   of nkChckRangeF, nkChckRange64, nkChckRange:
     let
       tmp0 = c.genx(n.sons[0])
diff --git a/doc/backends.txt b/doc/backends.txt
index c7939baec..343af09ed 100644
--- a/doc/backends.txt
+++ b/doc/backends.txt
@@ -420,7 +420,7 @@ function directly will be able to use it since Nim's garbage collector has
 not had a chance to run *yet*. This gives you enough time to make a copy for
 the C side of the program, as calling any further Nim procs *might* trigger
 garbage collection making the previously returned string garbage. Or maybe you
-are `triggering yourself the collection <gc.html>`_.
+are `yourself triggering the collection <gc.html>`_.
 
 
 Custom data types
diff --git a/doc/manual/typedesc.txt b/doc/manual/typedesc.txt
index de1d84d7d..6922d77e4 100644
--- a/doc/manual/typedesc.txt
+++ b/doc/manual/typedesc.txt
@@ -77,38 +77,6 @@ Once bound, typedesc params can appear in the rest of the proc signature:
 
   declareVariableWithType int, 42
 
-When used with macros and .compileTime. procs on the other hand, the compiler
-does not need to instantiate the code multiple times, because types then can be
-manipulated using the unified internal symbol representation. In such context
-typedesc acts as any other type. One can create variables, store typedesc
-values inside containers and so on. For example, here is how one can create
-a type-safe wrapper for the unsafe `printf` function from C:
-
-.. code-block:: nim
-  macro safePrintF(formatString: string{lit}, args: varargs[expr]): expr =
-    var i = 0
-    for c in formatChars(formatString):
-      var expectedType = case c
-        of 'c': char
-        of 'd', 'i', 'x', 'X': int
-        of 'f', 'e', 'E', 'g', 'G': float
-        of 's': string
-        of 'p': pointer
-        else: EOutOfRange
-
-      var actualType = args[i].getType
-      inc i
-
-      if expectedType == EOutOfRange:
-        error c & " is not a valid format character"
-      elif expectedType != actualType:
-        error "type mismatch for argument ", i, ". expected type: ",
-              expectedType.name, ", actual type: ", actualType.name
-
-    # keep the original callsite, but use cprintf instead
-    result = callsite()
-    result[0] = newIdentNode(!"cprintf")
-
 
 Overload resolution can be further influenced by constraining the set of
 types that will match the typedesc param:
diff --git a/lib/core/locks.nim b/lib/core/locks.nim
index 66e0ab520..fbe9c8acf 100644
--- a/lib/core/locks.nim
+++ b/lib/core/locks.nim
@@ -9,6 +9,7 @@
 
 ## This module contains Nim's support for locks and condition vars.
 
+const insideRLocksModule = false
 include "system/syslocks"
 
 type
@@ -63,4 +64,4 @@ template withLock*(a: Lock, body: untyped) =
     try:
       body
     finally:
-      a.release()
\ No newline at end of file
+      a.release()
diff --git a/lib/core/rlocks.nim b/lib/core/rlocks.nim
index 14f04592b..4710d6cf1 100644
--- a/lib/core/rlocks.nim
+++ b/lib/core/rlocks.nim
@@ -9,6 +9,7 @@
 
 ## This module contains Nim's support for reentrant locks.
 
+const insideRLocksModule = true
 include "system/syslocks"
 
 type
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index 4c7b817cb..e932d2845 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -35,6 +35,15 @@ const
   hasSpawnH = not defined(haiku) # should exist for every Posix system nowadays
   hasAioH = defined(linux)
 
+when defined(linux):
+  # On Linux:
+  # timer_{create,delete,settime,gettime},
+  # clock_{getcpuclockid, getres, gettime, nanosleep, settime} lives in librt
+  {.passL: "-lrt".}
+when defined(solaris):
+  # On Solaris hstrerror lives in libresolv
+  {.passL: "-lresolv".}
+
 when false:
   const
     C_IRUSR = 0c000400 ## Read by owner.
@@ -2309,9 +2318,9 @@ proc strftime*(a1: cstring, a2: int, a3: cstring,
            a4: var Tm): int {.importc, header: "<time.h>".}
 proc strptime*(a1, a2: cstring, a3: var Tm): cstring {.importc, header: "<time.h>".}
 proc time*(a1: var Time): Time {.importc, header: "<time.h>".}
-proc timer_create*(a1: var ClockId, a2: var SigEvent,
+proc timer_create*(a1: ClockId, a2: var SigEvent,
                a3: var Timer): cint {.importc, header: "<time.h>".}
-proc timer_delete*(a1: var Timer): cint {.importc, header: "<time.h>".}
+proc timer_delete*(a1: Timer): cint {.importc, header: "<time.h>".}
 proc timer_gettime*(a1: Timer, a2: var Itimerspec): cint {.
   importc, header: "<time.h>".}
 proc timer_getoverrun*(a1: Timer): cint {.importc, header: "<time.h>".}
diff --git a/lib/pure/collections/chains.nim b/lib/pure/collections/chains.nim
new file mode 100644
index 000000000..6b2ecd272
--- /dev/null
+++ b/lib/pure/collections/chains.nim
@@ -0,0 +1,44 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2016 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Template based implementation of singly and doubly linked lists.
+## The involved types should have 'prev' or 'next' fields and the
+## list header should have 'head' or 'tail' fields.
+
+template prepend*(header, node) =
+  when compiles(header.head):
+    when compiles(node.prev):
+      if header.head != nil:
+        header.head.prev = node
+    node.next = header.head
+    header.head = node
+  when compiles(header.tail):
+    if header.tail == nil:
+      header.tail = node
+
+template append*(header, node) =
+  when compiles(header.head):
+    if header.head == nil:
+      header.head = node
+  when compiles(header.tail):
+    when compiles(node.prev):
+      node.prev = header.tail
+    if header.tail != nil:
+      header.tail.next = node
+    header.tail = node
+
+template unlink*(header, node) =
+  if node.next != nil:
+    node.next.prev = node.prev
+  if node.prev != nil:
+    node.prev.next = node.next
+  if header.head == node:
+    header.head = node.prev
+  if header.tail == node:
+    header.tail = node.next
diff --git a/lib/pure/mersenne.nim b/lib/pure/mersenne.nim
index ae0845714..afa343086 100644
--- a/lib/pure/mersenne.nim
+++ b/lib/pure/mersenne.nim
@@ -5,29 +5,31 @@ type
 
 {.deprecated: [TMersenneTwister: MersenneTwister].}
 
-proc newMersenneTwister*(seed: int): MersenneTwister =
+proc newMersenneTwister*(seed: uint32): MersenneTwister =
   result.index = 0
-  result.mt[0]= uint32(seed)
+  result.mt[0] = seed
   for i in 1..623'u32:
-    result.mt[i]= (0x6c078965'u32 * (result.mt[i-1] xor (result.mt[i-1] shr 30'u32)) + i)
+    result.mt[i] = (0x6c078965'u32 * (result.mt[i-1] xor (result.mt[i-1] shr 30'u32)) + i)
 
 proc generateNumbers(m: var MersenneTwister) =
   for i in 0..623:
-    var y = (m.mt[i] and 0x80000000'u32) + (m.mt[(i+1) mod 624] and 0x7fffffff'u32)
+    var y = (m.mt[i] and 0x80000000'u32) +
+            (m.mt[(i+1) mod 624] and 0x7fffffff'u32)
     m.mt[i] = m.mt[(i+397) mod 624] xor uint32(y shr 1'u32)
     if (y mod 2'u32) != 0:
-     m.mt[i] = m.mt[i] xor 0x9908b0df'u32
+      m.mt[i] = m.mt[i] xor 0x9908b0df'u32
 
-proc getNum*(m: var MersenneTwister): int =
+proc getNum*(m: var MersenneTwister): uint32 =
+  ## Returns the next pseudo random number ranging from 0 to high(uint32)
   if m.index == 0:
     generateNumbers(m)
-  var y = m.mt[m.index]
-  y = y xor (y shr 11'u32)
-  y = y xor ((7'u32 shl y) and 0x9d2c5680'u32)
-  y = y xor ((15'u32 shl y) and 0xefc60000'u32)
-  y = y xor (y shr 18'u32)
-  m.index = (m.index+1) mod 624
-  return int(y)
+  result = m.mt[m.index]
+  m.index = (m.index + 1) mod m.mt.len
+
+  result = result xor (result shr 11'u32)
+  result = result xor ((7'u32 shl result) and 0x9d2c5680'u32)
+  result = result xor ((15'u32 shl result) and 0xefc60000'u32)
+  result = result xor (result shr 18'u32)
 
 # Test
 when not defined(testing) and isMainModule:
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index 330682ca9..394bccee3 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -222,9 +222,9 @@ when defined(ssl):
     of protSSLv23:
       newCTX = SSL_CTX_new(SSLv23_method()) # SSlv2,3 and TLS1 support.
     of protSSLv2:
-      raiseSslError("SSLv2 is no longer secure and has been deprecated, use protSSLv3")
+      raiseSslError("SSLv2 is no longer secure and has been deprecated, use protSSLv23")
     of protSSLv3:
-      newCTX = SSL_CTX_new(SSLv3_method())
+      raiseSslError("SSLv3 is no longer secure and has been deprecated, use protSSLv23")
     of protTLSv1:
       newCTX = SSL_CTX_new(TLSv1_method())
 
diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim
index 698bde42a..3e25eba22 100644
--- a/lib/pure/parseutils.nim
+++ b/lib/pure/parseutils.nim
@@ -234,6 +234,47 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
   elif result != 0:
     number = int(res)
 
+# overflowChecks doesn't work with uint64
+proc rawParseUInt(s: string, b: var uint64, start = 0): int =
+  var
+    res = 0'u64
+    prev = 0'u64
+    i = start
+  if s[i] == '+': inc(i) # Allow 
+  if s[i] in {'0'..'9'}:
+    b = 0
+    while s[i] in {'0'..'9'}:
+      prev = res
+      res = res * 10 + (ord(s[i]) - ord('0')).uint64
+      if prev > res:
+        return 0 # overflowChecks emulation
+      inc(i)
+      while s[i] == '_': inc(i) # underscores are allowed and ignored
+    b = res
+    result = i - start
+
+proc parseBiggestUInt*(s: string, number: var uint64, start = 0): int {.
+  rtl, extern: "npuParseBiggestUInt", noSideEffect.} =
+  ## parses an unsigned integer starting at `start` and stores the value into `number`.
+  ## Result is the number of processed chars or 0 if there is no integer or overflow detected.
+  var res: uint64
+  # use 'res' for exception safety (don't write to 'number' in case of an
+  # overflow exception):
+  result = rawParseUInt(s, res, start)
+  number = res
+
+proc parseUInt*(s: string, number: var uint, start = 0): int {.
+  rtl, extern: "npuParseUInt", noSideEffect.} =
+  ## parses an unsigned integer starting at `start` and stores the value into `number`.
+  ## Result is the number of processed chars or 0 if there is no integer or overflow detected.
+  var res: uint64
+  result = parseBiggestUInt(s, res, start)
+  if (sizeof(uint) <= 4) and
+      (res > 0xFFFF_FFFF'u64):
+    raise newException(OverflowError, "overflow")
+  elif result != 0:
+    number = uint(res)
+
 proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
   magic: "ParseBiggestFloat", importc: "nimParseBiggestFloat", noSideEffect.}
   ## parses a float starting at `start` and stores the value into `number`.
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index f2c1e77e1..eebadf4c0 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -560,6 +560,24 @@ proc parseBiggestInt*(s: string): BiggestInt {.noSideEffect, procvar,
   if L != s.len or L == 0:
     raise newException(ValueError, "invalid integer: " & s)
 
+proc parseUInt*(s: string): uint {.noSideEffect, procvar,
+  rtl, extern: "nsuParseUInt".} =
+  ## Parses a decimal unsigned integer value contained in `s`.
+  ##
+  ## If `s` is not a valid integer, `ValueError` is raised.
+  var L = parseutils.parseUInt(s, result, 0)
+  if L != s.len or L == 0:
+    raise newException(ValueError, "invalid unsigned integer: " & s)
+
+proc parseBiggestUInt*(s: string): uint64 {.noSideEffect, procvar,
+  rtl, extern: "nsuParseBiggestUInt".} =
+  ## Parses a decimal unsigned integer value contained in `s`.
+  ##
+  ## If `s` is not a valid integer, `ValueError` is raised.
+  var L = parseutils.parseBiggestUInt(s, result, 0)
+  if L != s.len or L == 0:
+    raise newException(ValueError, "invalid unsigned integer: " & s)
+
 proc parseFloat*(s: string): float {.noSideEffect, procvar,
   rtl, extern: "nsuParseFloat".} =
   ## Parses a decimal floating point value contained in `s`. If `s` is not
diff --git a/lib/system.nim b/lib/system.nim
index d3b18f9e3..53204306d 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2877,6 +2877,7 @@ when not defined(JS): #and not defined(nimscript):
   when declared(initAllocator):
     initAllocator()
   when hasThreadSupport:
+    const insideRLocksModule = false
     include "system/syslocks"
     when hostOS != "standalone": include "system/threads"
   elif not defined(nogc) and not defined(nimscript):
diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim
index 3b3d1f87d..61777e514 100644
--- a/lib/system/dyncalls.nim
+++ b/lib/system/dyncalls.nim
@@ -109,9 +109,30 @@ elif defined(windows) or defined(dos):
   proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr =
     result = getProcAddress(cast[THINSTANCE](lib), name)
     if result != nil: return
-    var decorated: array[250, char]
+    const decorated_length = 250
+    var decorated: array[decorated_length, char]
+    decorated[0] = '_'
+    var m = 1
+    while m < (decorated_length - 5):
+      if name[m - 1] == '\x00': break
+      decorated[m] = name[m - 1]
+      inc(m)
+    decorated[m] = '@'
     for i in countup(0, 50):
-      discard csprintf(decorated, "_%s@%ld", name, i*4)
+      var k = i * 4
+      if k div 100 == 0: 
+        if k div 10 == 0:
+          m = m + 1
+        else:
+          m = m + 2
+      else:
+        m = m + 3
+      decorated[m + 1] = '\x00'
+      while true:
+        decorated[m] = chr(ord('0') + (k %% 10))
+        dec(m)
+        k = k div 10
+        if k == 0: break
       result = getProcAddress(cast[THINSTANCE](lib), decorated)
       if result != nil: return
     procAddrError(name)
diff --git a/lib/system/syslocks.nim b/lib/system/syslocks.nim
index 6dcdfff0d..1695deca1 100644
--- a/lib/system/syslocks.nim
+++ b/lib/system/syslocks.nim
@@ -14,39 +14,41 @@
 when defined(Windows):
   type
     Handle = int
-    SysLock {.final, pure.} = object # CRITICAL_SECTION in WinApi
+
+    SysLock {.importc: "CRITICAL_SECTION",
+              header: "<windows.h>", final, pure.} = object # CRITICAL_SECTION in WinApi
       DebugInfo: pointer
       LockCount: int32
       RecursionCount: int32
       OwningThread: int
       LockSemaphore: int
-      Reserved: int32
+      SpinCount: int
 
     SysCond = Handle
 
   {.deprecated: [THandle: Handle, TSysLock: SysLock, TSysCond: SysCond].}
 
-  proc initSysLock(L: var SysLock) {.stdcall, noSideEffect,
-    dynlib: "kernel32", importc: "InitializeCriticalSection".}
+  proc initSysLock(L: var SysLock) {.importc: "InitializeCriticalSection",
+                                     header: "<windows.h>".}
     ## Initializes the lock `L`.
 
-  proc tryAcquireSysAux(L: var SysLock): int32 {.stdcall, noSideEffect,
-    dynlib: "kernel32", importc: "TryEnterCriticalSection".}
+  proc tryAcquireSysAux(L: var SysLock): int32 {.importc: "TryEnterCriticalSection",
+                                                 header: "<windows.h>".}
     ## Tries to acquire the lock `L`.
 
   proc tryAcquireSys(L: var SysLock): bool {.inline.} =
     result = tryAcquireSysAux(L) != 0'i32
 
-  proc acquireSys(L: var SysLock) {.stdcall, noSideEffect,
-    dynlib: "kernel32", importc: "EnterCriticalSection".}
+  proc acquireSys(L: var SysLock) {.importc: "EnterCriticalSection",
+                                    header: "<windows.h>".}
     ## Acquires the lock `L`.
 
-  proc releaseSys(L: var SysLock) {.stdcall, noSideEffect,
-    dynlib: "kernel32", importc: "LeaveCriticalSection".}
+  proc releaseSys(L: var SysLock) {.importc: "LeaveCriticalSection",
+                                    header: "<windows.h>".}
     ## Releases the lock `L`.
 
-  proc deinitSys(L: var SysLock) {.stdcall, noSideEffect,
-    dynlib: "kernel32", importc: "DeleteCriticalSection".}
+  proc deinitSys(L: var SysLock) {.importc: "DeleteCriticalSection",
+                                   header: "<windows.h>".}
 
   proc createEvent(lpEventAttributes: pointer,
                    bManualReset, bInitialState: int32,
@@ -86,17 +88,16 @@ else:
                           #include <pthread.h>""".} = object
     SysLockType = distinct cint
 
-  proc SysLockType_Reentrant: SysLockType =
-    {.emit: "`result` = PTHREAD_MUTEX_RECURSIVE;".}
-
   proc initSysLock(L: var SysLock, attr: ptr SysLockAttr = nil) {.
     importc: "pthread_mutex_init", header: "<pthread.h>", noSideEffect.}
 
-  proc initSysLockAttr(a: var SysLockAttr) {.
-    importc: "pthread_mutexattr_init", header: "<pthread.h>", noSideEffect.}
-
-  proc setSysLockType(a: var SysLockAttr, t: SysLockType) {.
-    importc: "pthread_mutexattr_settype", header: "<pthread.h>", noSideEffect.}
+  when insideRLocksModule:
+    proc SysLockType_Reentrant: SysLockType =
+      {.emit: "`result` = PTHREAD_MUTEX_RECURSIVE;".}
+    proc initSysLockAttr(a: var SysLockAttr) {.
+      importc: "pthread_mutexattr_init", header: "<pthread.h>", noSideEffect.}
+    proc setSysLockType(a: var SysLockAttr, t: SysLockType) {.
+      importc: "pthread_mutexattr_settype", header: "<pthread.h>", noSideEffect.}
 
   proc acquireSys(L: var SysLock) {.noSideEffect,
     importc: "pthread_mutex_lock", header: "<pthread.h>".}
@@ -111,14 +112,12 @@ else:
   proc deinitSys(L: var SysLock) {.noSideEffect,
     importc: "pthread_mutex_destroy", header: "<pthread.h>".}
 
-  proc initSysCond(cond: var SysCond, cond_attr: pointer = nil) {.
-    importc: "pthread_cond_init", header: "<pthread.h>", noSideEffect.}
-  proc waitSysCond(cond: var SysCond, lock: var SysLock) {.
-    importc: "pthread_cond_wait", header: "<pthread.h>", noSideEffect.}
-  proc signalSysCond(cond: var SysCond) {.
-    importc: "pthread_cond_signal", header: "<pthread.h>", noSideEffect.}
-
-  proc deinitSysCond(cond: var SysCond) {.noSideEffect,
-    importc: "pthread_cond_destroy", header: "<pthread.h>".}
-
-{.pop.}
+  when not insideRLocksModule:
+    proc initSysCond(cond: var SysCond, cond_attr: pointer = nil) {.
+      importc: "pthread_cond_init", header: "<pthread.h>", noSideEffect.}
+    proc waitSysCond(cond: var SysCond, lock: var SysLock) {.
+      importc: "pthread_cond_wait", header: "<pthread.h>", noSideEffect.}
+    proc signalSysCond(cond: var SysCond) {.
+      importc: "pthread_cond_signal", header: "<pthread.h>", noSideEffect.}
+    proc deinitSysCond(cond: var SysCond) {.noSideEffect,
+      importc: "pthread_cond_destroy", header: "<pthread.h>".}
diff --git a/tests/closure/tflatmap.nim b/tests/closure/tflatmap.nim
new file mode 100644
index 000000000..240756424
--- /dev/null
+++ b/tests/closure/tflatmap.nim
@@ -0,0 +1,24 @@
+
+# bug #3995
+
+import future
+
+type
+  RNG* = tuple[]
+  Rand*[A] = (RNG) -> (A, RNG)
+
+proc nextInt*(r: RNG): (int, RNG) =
+  (1, ())
+
+proc flatMap[A,B](f: Rand[A], g: A -> Rand[B]): Rand[B] =
+  (rng: RNG) => (
+    let (a, rng2) = f(rng);
+    let g1 = g(a);
+    g1(rng2)
+  )
+
+proc map[A,B](s: Rand[A], f: A -> B): Rand[B] =
+  let g: A -> Rand[B] = (a: A) => ((rng: RNG) => (f(a), rng))
+  flatMap(s, g)
+
+let f = nextInt.map(i => i - i mod 2)
diff --git a/tests/macros/typesafeprintf.nim b/tests/macros/typesafeprintf.nim
new file mode 100644
index 000000000..2f4622f3e
--- /dev/null
+++ b/tests/macros/typesafeprintf.nim
@@ -0,0 +1,48 @@
+discard """
+  output: '''test 10'''
+"""
+
+# bug #1152
+
+import macros, typetraits
+proc printfImpl(formatstr: cstring) {.importc: "printf", varargs.}
+
+iterator tokenize(format: string): char =
+  var i = 0
+  while true:
+    case format[i]
+    of '%':
+      case format[i+1]
+      of '\0': break
+      else: yield format[i+1]
+      i.inc
+    of '\0': break
+    else: discard
+    i.inc
+
+macro printf(formatString: string{lit}, args: varargs[typed]): untyped =
+  var i = 0
+  let err = getType(bindSym"ValueError")
+  for c in tokenize(formatString.strVal):
+    var expectedType = case c
+      of 'c': getType(bindSym"char")
+      of 'd', 'i', 'x', 'X': getType(bindSym"int")
+      of 'f', 'e', 'E', 'g', 'G': getType(bindSym"float")
+      of 's': getType(bindSym"string")
+      of 'p': getType(bindSym"pointer")
+      else: err
+
+    var actualType = getType(args[i])
+    inc i
+
+    if sameType(expectedType, err):
+      error c & " is not a valid format character"
+    elif not sameType(expectedType, actualType):
+      error "type mismatch for argument " & $i & ". expected type: " &
+            $expectedType & ", actual type: " & $actualType
+
+  # keep the original callsite, but use cprintf instead
+  result = callsite()
+  result[0] = bindSym"printfImpl"
+
+printf("test %d\n", 10)
diff --git a/tests/stdlib/tparseuints.nim b/tests/stdlib/tparseuints.nim
new file mode 100644
index 000000000..5be3bcbd0
--- /dev/null
+++ b/tests/stdlib/tparseuints.nim
@@ -0,0 +1,11 @@
+discard """
+  action: run
+"""
+import unittest, strutils
+
+suite "parseutils":
+  test "uint":
+    check: parseBiggestUInt("0") == 0'u64
+    check: parseBiggestUInt("18446744073709551615") == 0xFFFF_FFFF_FFFF_FFFF'u64
+    expect(ValueError):
+      discard parseBiggestUInt("18446744073709551616")
diff --git a/tests/vm/tanonproc.nim b/tests/vm/tanonproc.nim
new file mode 100644
index 000000000..474b768ca
--- /dev/null
+++ b/tests/vm/tanonproc.nim
@@ -0,0 +1,52 @@
+discard """
+  output: '''`Test`'''
+"""
+
+# bug #3561
+
+import macros, future, strutils
+
+type
+  Option[T] = ref object
+    case valid: bool
+    of true:
+      data: T
+    else:
+      discard
+
+proc some[T](v: T): Option[T] = Option[T](valid: true, data: v)
+proc none[T](v: T): Option[T] = Option[T](valid: false)
+proc none(T: typedesc): Option[T] = Option[T](valid: false)
+
+proc map[T,U](o: Option[T], f: T -> U): Option[U] =
+  case o.valid
+  of true:
+    f(o.data).some
+  else:
+    U.none
+
+proc notEmpty(o: Option[string]): Option[string] =
+  case o.valid
+  of true:
+    if o.data.strip == "": string.none else: o.data.strip.some
+  else:
+    o
+
+proc getOrElse[T](o: Option[T], def: T): T =
+  case o.valid
+  of true:
+    o.data
+  else:
+    def
+
+proc quoteStr(s: string): Option[string] =
+  s.some.notEmpty.map(v => "`" & v & "`")
+
+macro str(s: string): stmt =
+  let x = s.strVal
+  let y = quoteStr(x)
+  let sn = newStrLitNode(y.getOrElse("NONE"))
+  result = quote do:
+    echo `sn`
+
+str"Test"
diff --git a/tests/vm/tinheritance.nim b/tests/vm/tinheritance.nim
new file mode 100644
index 000000000..d465e22b9
--- /dev/null
+++ b/tests/vm/tinheritance.nim
@@ -0,0 +1,29 @@
+discard """
+  msg: '''Hello fred , managed by sally
+Hello sally , managed by bob'''
+"""
+# bug #3973
+
+type
+  EmployeeCode = enum
+    ecCode1,
+    ecCode2
+
+  Person* = object of RootObj
+    name* : string
+    last_name*: string
+
+  Employee* = object of Person
+    empl_code* : EmployeeCode
+    mgr_name* : string
+
+proc test() =
+  var
+    empl1 = Employee(name: "fred", last_name: "smith", mgr_name: "sally", empl_code: ecCode1)
+    empl2 = Employee(name: "sally", last_name: "jones", mgr_name: "bob", empl_code: ecCode2)
+
+  echo "Hello ", empl1.name, " , managed by ", empl1.mgr_name
+  echo "Hello ", empl2.name, " , managed by ", empl2.mgr_name
+
+static:
+  test()
diff --git a/tests/vm/tmitems.nim b/tests/vm/tmitems.nim
new file mode 100644
index 000000000..4ee225eed
--- /dev/null
+++ b/tests/vm/tmitems.nim
@@ -0,0 +1,31 @@
+discard """
+  msg: '''13'''
+  output: '''3
+3
+3'''
+"""
+# bug #3731
+var list {.compileTime.} = newSeq[int]()
+
+macro calc*(): stmt {.immediate.} =
+  list.add(1)
+  for c in list.mitems:
+    c = 13
+
+  for c in list:
+    echo c
+
+calc()
+
+# bug #3859
+import macros
+macro m: stmt =
+  var s = newseq[NimNode](3)
+  # var s: array[3,NimNode]                 # not working either
+  for i in 0..<s.len: s[i] = newLit(3)    # works
+  #for x in s.mitems: x = newLit(3)
+  result = newStmtList()
+  for i in s:
+    result.add newCall(bindsym"echo", i)
+
+m()
diff --git a/tests/vm/twrong_concat.nim b/tests/vm/twrong_concat.nim
new file mode 100644
index 000000000..538ea2527
--- /dev/null
+++ b/tests/vm/twrong_concat.nim
@@ -0,0 +1,28 @@
+discard """
+  output: '''success'''
+"""
+
+# bug #3804
+
+#import sequtils
+
+type AnObj = ref object
+  field: string
+
+#proc aBug(objs: seq[AnObj]) {.compileTime.} =
+#  discard objs.mapIt(it.field & " bug")
+
+proc sameBug(objs: seq[AnObj]) {.compileTime.} =
+  var strSeq = newSeq[string](objs.len)
+  strSeq[0] = objs[0].field & " bug"
+
+static:
+  var objs: seq[AnObj] = @[]
+  objs.add(AnObj(field: "hello"))
+
+  sameBug(objs)
+  # sameBug(objs)
+  echo objs[0].field
+  assert(objs[0].field == "hello") # fails, because (objs[0].field == "hello bug") - mutated!
+
+echo "success"
diff --git a/web/news.txt b/web/news.txt
index e818ed66e..82ed4fe44 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -20,6 +20,9 @@ Changes affecting backwards compatibility
   new experimental ``this`` pragma to achieve a similar effect to what the old ``using`` statement tried to achieve.
 - Typeless parameters have been removed from the language since it would
   clash with ``using``.
+- Procedures in ``mersenne.nim`` (Mersenne Twister implementation) no longer
+  accept and produce ``int`` values which have platform-dependent size -
+  they use ``uint32`` instead.
 
 
 Library Additions