summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/evalffi.nim16
-rw-r--r--compiler/jsgen.nim223
-rw-r--r--doc/tut2.txt4
-rw-r--r--lib/pure/nimprof.nim2
-rw-r--r--lib/pure/osproc.nim15
-rw-r--r--lib/pure/streams.nim5
-rw-r--r--lib/system/alloc.nim2
-rw-r--r--lib/system/gc.nim6
-rw-r--r--lib/system/gc_common.nim8
-rw-r--r--lib/system/jssys.nim81
-rw-r--r--lib/wrappers/openssl.nim11
-rw-r--r--readme.md4
-rw-r--r--tests/js/tstringitems.nim84
-rw-r--r--tests/misc/tints.nim39
-rw-r--r--tests/misc/tunsignedinc.nim34
-rw-r--r--tests/testament/categories.nim2
-rw-r--r--web/community.txt7
-rw-r--r--web/news.txt4
18 files changed, 325 insertions, 222 deletions
diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim
index b1a23802d..75394c2f3 100644
--- a/compiler/evalffi.nim
+++ b/compiler/evalffi.nim
@@ -50,10 +50,10 @@ proc importcSymbol*(sym: PSym): PNode =
   # that contains the address instead:
   result = newNodeIT(nkPtrLit, sym.info, sym.typ)
   case name
-  of "stdin":  result.intVal = cast[TAddress](system.stdin)
-  of "stdout": result.intVal = cast[TAddress](system.stdout)
-  of "stderr": result.intVal = cast[TAddress](system.stderr)
-  of "vmErrnoWrapper": result.intVal = cast[TAddress](myerrno)
+  of "stdin":  result.intVal = cast[ByteAddress](system.stdin)
+  of "stdout": result.intVal = cast[ByteAddress](system.stdout)
+  of "stderr": result.intVal = cast[ByteAddress](system.stderr)
+  of "vmErrnoWrapper": result.intVal = cast[ByteAddress](myerrno)
   else:
     let lib = sym.annex
     if lib != nil and lib.path.kind notin {nkStrLit..nkTripleStrLit}:
@@ -71,7 +71,7 @@ proc importcSymbol*(sym: PSym): PNode =
                                        else: lib.path.strVal, sym.info)
       theAddr = dllhandle.symAddr(name)
     if theAddr.isNil: globalError(sym.info, "cannot import: " & sym.name.s)
-    result.intVal = cast[TAddress](theAddr)
+    result.intVal = cast[ByteAddress](theAddr)
 
 proc mapType(t: ast.PType): ptr libffi.TType =
   if t == nil: return addr libffi.type_void
@@ -107,7 +107,7 @@ proc mapCallConv(cc: TCallingConvention, info: TLineInfo): TABI =
 template rd(T, p: expr): expr {.immediate.} = (cast[ptr T](p))[]
 template wr(T, p, v: expr) {.immediate.} = (cast[ptr T](p))[] = v
 template `+!`(x, y: expr): expr {.immediate.} =
-  cast[pointer](cast[TAddress](x) + y)
+  cast[pointer](cast[ByteAddress](x) + y)
 
 proc packSize(v: PNode, typ: PType): int =
   ## computes the size of the blob
@@ -363,13 +363,13 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
       # in their unboxed representation so nothing it to be unpacked:
       result = n
     else:
-      awi(nkPtrLit, cast[TAddress](p))
+      awi(nkPtrLit, cast[ByteAddress](p))
   of tyPtr, tyRef, tyVar:
     let p = rd(pointer, x)
     if p.isNil:
       setNil()
     elif n == nil or n.kind == nkPtrLit:
-      awi(nkPtrLit, cast[TAddress](p))
+      awi(nkPtrLit, cast[ByteAddress](p))
     elif n != nil and n.len == 1:
       internalAssert n.kind == nkRefTy
       n.sons[0] = unpack(p, typ.lastSon, n.sons[0])
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 14cdf0174..9424a9fc5 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -163,8 +163,31 @@ proc mangleName(s: PSym): Rope =
     add(result, rope(s.id))
     s.loc.r = result
 
-proc makeJSString(s: string): Rope =
-  (if s.isNil: "null".rope else: strutils.escape(s).rope)
+proc escapeJSString(s: string): string =
+   result = newStringOfCap(s.len + s.len shr 2)
+   result.add("\"")
+   for c in items(s):
+     case c
+     of '\l': result.add("\\n")
+     of '\r': result.add("\\r")
+     of '\t': result.add("\\t")
+     of '\b': result.add("\\b")
+     of '\a': result.add("\\a")
+     of '\e': result.add("\\e")
+     of '\v': result.add("\\v")
+     of '\\': result.add("\\\\")
+     of '\'': result.add("\\'")
+     of '\"': result.add("\\\"")
+     else: add(result, c)
+   result.add("\"")
+
+proc makeJSString(s: string, escapeNonAscii = true): Rope =
+  if s.isNil:
+    result = "null".rope
+  elif escapeNonAscii:
+    result = strutils.escape(s).rope
+  else:
+    result = escapeJSString(s).rope
 
 include jstypes
 
@@ -264,7 +287,7 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
     ["", "", "($1 - $2)", "($1 - $2)"], # SubF64
     ["", "", "($1 * $2)", "($1 * $2)"], # MulF64
     ["", "", "($1 / $2)", "($1 / $2)"], # DivF64
-    ["", "", "($1 >>> $2)", "($1 >>> $2)"], # ShrI
+    ["", "", "", ""], # ShrI
     ["", "", "($1 << $2)", "($1 << $2)"], # ShlI
     ["", "", "($1 & $2)", "($1 & $2)"], # BitandI
     ["", "", "($1 | $2)", "($1 | $2)"], # BitorI
@@ -273,21 +296,21 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
     ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI
     ["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinF64
     ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxF64
-    ["addU", "addU", "addU($1, $2)", "addU($1, $2)"], # addU
-    ["subU", "subU", "subU($1, $2)", "subU($1, $2)"], # subU
-    ["mulU", "mulU", "mulU($1, $2)", "mulU($1, $2)"], # mulU
-    ["divU", "divU", "divU($1, $2)", "divU($1, $2)"], # divU
-    ["modU", "modU", "modU($1, $2)", "modU($1, $2)"], # modU
+    ["", "", "", ""], # addU
+    ["", "", "", ""], # subU
+    ["", "", "", ""], # mulU
+    ["", "", "", ""], # divU
+    ["", "", "($1 % $2)", "($1 % $2)"], # modU
     ["", "", "($1 == $2)", "($1 == $2)"], # EqI
     ["", "", "($1 <= $2)", "($1 <= $2)"], # LeI
     ["", "", "($1 < $2)", "($1 < $2)"], # LtI
     ["", "", "($1 == $2)", "($1 == $2)"], # EqF64
     ["", "", "($1 <= $2)", "($1 <= $2)"], # LeF64
     ["", "", "($1 < $2)", "($1 < $2)"], # LtF64
-    ["leU", "leU", "leU($1, $2)", "leU($1, $2)"], # leU
-    ["ltU", "ltU", "ltU($1, $2)", "ltU($1, $2)"], # ltU
-    ["leU64", "leU64", "leU64($1, $2)", "leU64($1, $2)"], # leU64
-    ["ltU64", "ltU64", "ltU64($1, $2)", "ltU64($1, $2)"], # ltU64
+    ["", "", "($1 <= $2)", "($1 <= $2)"], # leU
+    ["", "", "($1 < $2)", "($1 < $2)"], # ltU
+    ["", "", "($1 <= $2)", "($1 <= $2)"], # leU64
+    ["", "", "($1 < $2)", "($1 < $2)"], # ltU64
     ["", "", "($1 == $2)", "($1 == $2)"], # EqEnum
     ["", "", "($1 <= $2)", "($1 <= $2)"], # LeEnum
     ["", "", "($1 < $2)", "($1 < $2)"], # LtEnum
@@ -336,90 +359,6 @@ const # magic checked op; magic unchecked op; checked op; unchecked op
     ["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"],
     ["", "", "$1", "$1"]]
 
-  luaOps: TMagicOps = [
-    ["addInt", "", "addInt($1, $2)", "($1 + $2)"], # AddI
-    ["subInt", "", "subInt($1, $2)", "($1 - $2)"], # SubI
-    ["mulInt", "", "mulInt($1, $2)", "($1 * $2)"], # MulI
-    ["divInt", "", "divInt($1, $2)", "Math.floor($1 / $2)"], # DivI
-    ["modInt", "", "modInt($1, $2)", "Math.floor($1 % $2)"], # ModI
-    ["addInt", "", "addInt($1, $2)", "($1 + $2)"], # Succ
-    ["subInt", "", "subInt($1, $2)", "($1 - $2)"], # Pred
-    ["", "", "($1 + $2)", "($1 + $2)"], # AddF64
-    ["", "", "($1 - $2)", "($1 - $2)"], # SubF64
-    ["", "", "($1 * $2)", "($1 * $2)"], # MulF64
-    ["", "", "($1 / $2)", "($1 / $2)"], # DivF64
-    ["", "", "($1 >>> $2)", "($1 >>> $2)"], # ShrI
-    ["", "", "($1 << $2)", "($1 << $2)"], # ShlI
-    ["", "", "($1 & $2)", "($1 & $2)"], # BitandI
-    ["", "", "($1 | $2)", "($1 | $2)"], # BitorI
-    ["", "", "($1 ^ $2)", "($1 ^ $2)"], # BitxorI
-    ["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinI
-    ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI
-    ["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinF64
-    ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxF64
-    ["addU", "addU", "addU($1, $2)", "addU($1, $2)"], # addU
-    ["subU", "subU", "subU($1, $2)", "subU($1, $2)"], # subU
-    ["mulU", "mulU", "mulU($1, $2)", "mulU($1, $2)"], # mulU
-    ["divU", "divU", "divU($1, $2)", "divU($1, $2)"], # divU
-    ["modU", "modU", "modU($1, $2)", "modU($1, $2)"], # modU
-    ["", "", "($1 == $2)", "($1 == $2)"], # EqI
-    ["", "", "($1 <= $2)", "($1 <= $2)"], # LeI
-    ["", "", "($1 < $2)", "($1 < $2)"], # LtI
-    ["", "", "($1 == $2)", "($1 == $2)"], # EqF64
-    ["", "", "($1 <= $2)", "($1 <= $2)"], # LeF64
-    ["", "", "($1 < $2)", "($1 < $2)"], # LtF64
-    ["leU", "leU", "leU($1, $2)", "leU($1, $2)"], # leU
-    ["ltU", "ltU", "ltU($1, $2)", "ltU($1, $2)"], # ltU
-    ["leU64", "leU64", "leU64($1, $2)", "leU64($1, $2)"], # leU64
-    ["ltU64", "ltU64", "ltU64($1, $2)", "ltU64($1, $2)"], # ltU64
-    ["", "", "($1 == $2)", "($1 == $2)"], # EqEnum
-    ["", "", "($1 <= $2)", "($1 <= $2)"], # LeEnum
-    ["", "", "($1 < $2)", "($1 < $2)"], # LtEnum
-    ["", "", "($1 == $2)", "($1 == $2)"], # EqCh
-    ["", "", "($1 <= $2)", "($1 <= $2)"], # LeCh
-    ["", "", "($1 < $2)", "($1 < $2)"], # LtCh
-    ["", "", "($1 == $2)", "($1 == $2)"], # EqB
-    ["", "", "($1 <= $2)", "($1 <= $2)"], # LeB
-    ["", "", "($1 < $2)", "($1 < $2)"], # LtB
-    ["", "", "($1 == $2)", "($1 == $2)"], # EqRef
-    ["", "", "($1 == $2)", "($1 == $2)"], # EqUntracedRef
-    ["", "", "($1 <= $2)", "($1 <= $2)"], # LePtr
-    ["", "", "($1 < $2)", "($1 < $2)"], # LtPtr
-    ["", "", "($1 == $2)", "($1 == $2)"], # EqCString
-    ["", "", "($1 != $2)", "($1 != $2)"], # Xor
-    ["", "", "($1 == $2)", "($1 == $2)"], # EqProc
-    ["negInt", "", "negInt($1)", "-($1)"], # UnaryMinusI
-    ["negInt64", "", "negInt64($1)", "-($1)"], # UnaryMinusI64
-    ["absInt", "", "absInt($1)", "Math.abs($1)"], # AbsI
-    ["", "", "not ($1)", "not ($1)"], # Not
-    ["", "", "+($1)", "+($1)"], # UnaryPlusI
-    ["", "", "~($1)", "~($1)"], # BitnotI
-    ["", "", "+($1)", "+($1)"], # UnaryPlusF64
-    ["", "", "-($1)", "-($1)"], # UnaryMinusF64
-    ["", "", "Math.abs($1)", "Math.abs($1)"], # AbsF64
-    ["Ze8ToI", "Ze8ToI", "Ze8ToI($1)", "Ze8ToI($1)"], # mZe8ToI
-    ["Ze8ToI64", "Ze8ToI64", "Ze8ToI64($1)", "Ze8ToI64($1)"], # mZe8ToI64
-    ["Ze16ToI", "Ze16ToI", "Ze16ToI($1)", "Ze16ToI($1)"], # mZe16ToI
-    ["Ze16ToI64", "Ze16ToI64", "Ze16ToI64($1)", "Ze16ToI64($1)"], # mZe16ToI64
-    ["Ze32ToI64", "Ze32ToI64", "Ze32ToI64($1)", "Ze32ToI64($1)"], # mZe32ToI64
-    ["ZeIToI64", "ZeIToI64", "ZeIToI64($1)", "ZeIToI64($1)"], # mZeIToI64
-    ["toU8", "toU8", "toU8($1)", "toU8($1)"], # toU8
-    ["toU16", "toU16", "toU16($1)", "toU16($1)"], # toU16
-    ["toU32", "toU32", "toU32($1)", "toU32($1)"], # toU32
-    ["", "", "$1", "$1"],     # ToFloat
-    ["", "", "$1", "$1"],     # ToBiggestFloat
-    ["", "", "Math.floor($1)", "Math.floor($1)"], # ToInt
-    ["", "", "Math.floor($1)", "Math.floor($1)"], # ToBiggestInt
-    ["nimCharToStr", "nimCharToStr", "nimCharToStr($1)", "nimCharToStr($1)"],
-    ["nimBoolToStr", "nimBoolToStr", "nimBoolToStr($1)", "nimBoolToStr($1)"], [
-      "cstrToNimstr", "cstrToNimstr", "cstrToNimstr(($1)+\"\")",
-      "cstrToNimstr(($1)+\"\")"], ["cstrToNimstr", "cstrToNimstr",
-                                   "cstrToNimstr(($1)+\"\")",
-                                   "cstrToNimstr(($1)+\"\")"], ["cstrToNimstr",
-      "cstrToNimstr", "cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")"],
-    ["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"],
-    ["", "", "$1", "$1"]]
-
 proc binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
   var x, y: TCompRes
   useMagic(p, magic)
@@ -428,6 +367,23 @@ proc binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
   r.res = frmt % [x.rdLoc, y.rdLoc]
   r.kind = resExpr
 
+proc unsignedTrimmer(size: BiggestInt): Rope =
+  case size
+    of 1: rope"& 0xff"
+    of 2: rope"& 0xffff"
+    of 4: rope">>> 0"
+    else: rope""
+
+proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string, reassign: bool = false) =
+  var x, y: TCompRes
+  gen(p, n.sons[1], x)
+  gen(p, n.sons[2], y)
+  let trimmer = unsignedTrimmer(n[1].typ.skipTypes(abstractRange).size)
+  if reassign:
+    r.res = "$1 = (($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
+  else:
+    r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
+
 proc ternaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
   var x, y, z: TCompRes
   useMagic(p, magic)
@@ -455,10 +411,22 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic, ops: TMagicOps) =
   else:
     gen(p, n.sons[1], r)
     r.res = ops[op][i + 2] % [r.rdLoc]
-  r.kind = resExpr
 
 proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
-  arithAux(p, n, r, op, jsOps | luaOps)
+  case op
+  of mAddU: binaryUintExpr(p, n, r, "+")
+  of mSubU: binaryUintExpr(p, n, r, "-")
+  of mMulU: binaryUintExpr(p, n, r, "*")
+  of mDivU: binaryUintExpr(p, n, r, "/")
+  of mShrI:
+    var x, y: TCompRes
+    gen(p, n.sons[1], x)
+    gen(p, n.sons[2], y)
+    let trimmer = unsignedTrimmer(n[1].typ.skipTypes(abstractRange).size)
+    r.res = "(($1 $2) >>> $3)" % [x.rdLoc, trimmer, y.rdLoc]
+  else:
+    arithAux(p, n, r, op, jsOps)
+  r.kind = resExpr
 
 proc genLineDir(p: PProc, n: PNode) =
   let line = toLinenumber(n.info)
@@ -632,7 +600,7 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
           if stringSwitch:
             case e.kind
             of nkStrLit..nkTripleStrLit: addf(p.body, "case $1: ",
-                [makeJSString(e.strVal)])
+                [makeJSString(e.strVal, false)])
             else: internalError(e.info, "jsgen.genCaseStmt: 2")
           else:
             gen(p, e, cond)
@@ -1388,7 +1356,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
   of mEqStr: binaryExpr(p, n, r, "eqStrings", "eqStrings($1, $2)")
   of mLeStr: binaryExpr(p, n, r, "cmpStrings", "(cmpStrings($1, $2) <= 0)")
   of mLtStr: binaryExpr(p, n, r, "cmpStrings", "(cmpStrings($1, $2) < 0)")
-  of mIsNil: unaryExpr(p, n, r, "", "$1 == null")
+  of mIsNil: unaryExpr(p, n, r, "", "($1 === null)")
   of mEnumToStr: genRepr(p, n, r)
   of mNew, mNewFinalize: genNew(p, n)
   of mSizeOf: r.res = rope(getSize(n.sons[1].typ))
@@ -1406,11 +1374,17 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
     else:
       unaryExpr(p, n, r, "", "($1 != null ? ($1.length-1) : -1)")
   of mInc:
-    if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 += $2")
-    else: binaryExpr(p, n, r, "addInt", "$1 = addInt($1, $2)")
+    if n[1].typ.skipTypes(abstractRange).kind in tyUInt .. tyUInt64:
+      binaryUintExpr(p, n, r, "+", true)
+    else:
+      if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 += $2")
+      else: binaryExpr(p, n, r, "addInt", "$1 = addInt($1, $2)")
   of ast.mDec:
-    if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")
-    else: binaryExpr(p, n, r, "subInt", "$1 = subInt($1, $2)")
+    if n[1].typ.skipTypes(abstractRange).kind in tyUInt .. tyUInt64:
+      binaryUintExpr(p, n, r, "-", true)
+    else:
+      if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")
+      else: binaryExpr(p, n, r, "subInt", "$1 = subInt($1, $2)")
   of mSetLengthStr: binaryExpr(p, n, r, "", "$1.length = $2+1; $1[$1.length-1] = 0")
   of mSetLengthSeq: binaryExpr(p, n, r, "", "$1.length = $2")
   of mCard: unaryExpr(p, n, r, "SetCard", "SetCard($1)")
@@ -1627,6 +1601,37 @@ proc genPragma(p: PProc, n: PNode) =
     of wEmit: genAsmOrEmitStmt(p, it.sons[1])
     else: discard
 
+proc genCast(p: PProc, n: PNode, r: var TCompRes) =
+  var dest = skipTypes(n.typ, abstractVarRange)
+  var src = skipTypes(n.sons[1].typ, abstractVarRange)
+  gen(p, n.sons[1], r)
+  if dest.kind == src.kind:
+    # no-op conversion
+    return
+  let toInt = (dest.kind in tyInt .. tyInt32)
+  let toUint = (dest.kind in tyUInt .. tyUInt32)
+  let fromInt = (src.kind in tyInt .. tyInt32)
+  let fromUint = (src.kind in tyUInt .. tyUInt32)
+
+  if toUint and (fromInt or fromUint):
+    let trimmer = unsignedTrimmer(dest.size)
+    r.res = "($1 $2)" % [r.res, trimmer]
+  elif toInt:
+    if fromInt:
+      let trimmer = unsignedTrimmer(dest.size)
+      r.res = "($1 $2)" % [r.res, trimmer]
+    elif fromUint:
+      if src.size == 4 and dest.size == 4:
+        r.res = "($1|0)" % [r.res]
+      else:
+        let trimmer = unsignedTrimmer(dest.size)
+        let minuend = case dest.size
+          of 1: "0xfe"
+          of 2: "0xfffe"
+          of 4: "0xfffffffe"
+          else: ""
+        r.res = "($1 - ($2 $3))" % [rope minuend, r.res, trimmer]
+
 proc gen(p: PProc, n: PNode, r: var TCompRes) =
   r.typ = etyNone
   r.kind = resNone
@@ -1635,7 +1640,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
   case n.kind
   of nkSym:
     genSym(p, n, r)
-  of nkCharLit..nkInt64Lit:
+  of nkCharLit..nkUInt32Lit:
     if n.typ.kind == tyBool:
       r.res = if n.intVal == 0: rope"false" else: rope"true"
     else:
@@ -1654,10 +1659,10 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
       r.kind = resExpr
   of nkStrLit..nkTripleStrLit:
     if skipTypes(n.typ, abstractVarRange).kind == tyString:
-      useMagic(p, "cstrToNimstr")
-      r.res = "cstrToNimstr($1)" % [makeJSString(n.strVal)]
+      useMagic(p, "makeNimstrLit")
+      r.res = "makeNimstrLit($1)" % [makeJSString(n.strVal)]
     else:
-      r.res = makeJSString(n.strVal)
+      r.res = makeJSString(n.strVal, false)
     r.kind = resExpr
   of nkFloatLit..nkFloat64Lit:
     let f = n.floatVal
@@ -1688,7 +1693,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
   of nkCheckedFieldExpr: genCheckedFieldAccess(p, n, r)
   of nkObjDownConv: gen(p, n.sons[0], r)
   of nkObjUpConv: upConv(p, n, r)
-  of nkCast: gen(p, n.sons[1], r)
+  of nkCast: genCast(p, n, r)
   of nkChckRangeF: genRangeChck(p, n, r, "chckRangeF")
   of nkChckRange64: genRangeChck(p, n, r, "chckRange64")
   of nkChckRange: genRangeChck(p, n, r, "chckRange")
diff --git a/doc/tut2.txt b/doc/tut2.txt
index 563344570..f60818da6 100644
--- a/doc/tut2.txt
+++ b/doc/tut2.txt
@@ -1000,7 +1000,9 @@ JavaScript-compatible code you should remember the following:
 - ``addr`` and ``ptr`` have slightly different semantic meaning in JavaScript.
   It is recommended to avoid those if you're not sure how they are translated
   to JavaScript.
-- ``cast[T](x)`` in JavaScript is translated to ``(x)``.
+- ``cast[T](x)`` in JavaScript is translated to ``(x)``, except for casting
+  between signed/unsigned ints, in which case it behaves as static cast in
+  C language.
 - ``cstring`` in JavaScript means JavaScript string. It is a good practice to
   use ``cstring`` only when it is semantically appropriate. E.g. don't use
   ``cstring`` as a binary data buffer.
diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim
index e2397b91c..5a7deaab0 100644
--- a/lib/pure/nimprof.nim
+++ b/lib/pure/nimprof.nim
@@ -12,7 +12,7 @@
 ## report at program exit.
 
 when not defined(profiler) and not defined(memProfiler):
-  {.warning: "Profiling support is turned off!".}
+  {.error: "Profiling support is turned off! Enable profiling by passing `--profiler:on --stackTrace:on` to the compiler (see the Nim Compiler User Guide for more options).".}
 
 # We don't want to profile the profiling code ...
 {.push profiler: off.}
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index 8560c3ee4..34fb81520 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -886,7 +886,7 @@ elif not defined(useNimRtl):
     discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error))
     exitnow(1)
 
-  when defined(macosx) or defined(freebsd) or defined(netbsd) or defined(android):
+  when not defined(uClibc) and (not defined(linux) or defined(android)):
     var environ {.importc.}: cstringArray
 
   proc startProcessAfterFork(data: ptr StartProcessData) =
@@ -916,17 +916,16 @@ elif not defined(useNimRtl):
     discard fcntl(data.pErrorPipe[writeIdx], F_SETFD, FD_CLOEXEC)
 
     if data.optionPoUsePath:
-      when defined(macosx) or defined(freebsd) or defined(netbsd) or defined(android):
+      when defined(uClibc):
+        # uClibc environment (OpenWrt included) doesn't have the full execvpe
+        discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
+      elif defined(linux) and not defined(android):
+        discard execvpe(data.sysCommand, data.sysArgs, data.sysEnv)
+      else:
         # MacOSX doesn't have execvpe, so we need workaround.
         # On MacOSX we can arrive here only from fork, so this is safe:
         environ = data.sysEnv
         discard execvp(data.sysCommand, data.sysArgs)
-      else:
-        when defined(uClibc):
-          # uClibc environment (OpenWrt included) doesn't have the full execvpe
-          discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
-        else:
-          discard execvpe(data.sysCommand, data.sysArgs, data.sysEnv)
     else:
       discard execve(data.sysCommand, data.sysArgs, data.sysEnv)
 
diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim
index 38e91fee4..bb6175a12 100644
--- a/lib/pure/streams.nim
+++ b/lib/pure/streams.nim
@@ -148,7 +148,10 @@ proc write*[T](s: Stream, x: T) =
 proc write*(s: Stream, x: string) =
   ## writes the string `x` to the the stream `s`. No length field or
   ## terminating zero is written.
-  writeData(s, cstring(x), x.len)
+  when nimvm:
+    writeData(s, cstring(x), x.len)
+  else:
+    if x.len > 0: writeData(s, unsafeAddr x[0], x.len)
 
 proc writeLn*(s: Stream, args: varargs[string, `$`]) {.deprecated.} =
   ## **Deprecated since version 0.11.4:** Use **writeLine** instead.
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index b4462ed83..6de8e19e7 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -688,7 +688,7 @@ proc rawDealloc(a: var MemRegion, p: pointer) =
     sysAssert(((cast[ByteAddress](p) and PageMask) - smallChunkOverhead()) %%
                s == 0, "rawDealloc 3")
     var f = cast[ptr FreeCell](p)
-    #echo("setting to nil: ", $cast[TAddress](addr(f.zeroField)))
+    #echo("setting to nil: ", $cast[ByteAddress](addr(f.zeroField)))
     sysAssert(f.zeroField != 0, "rawDealloc 1")
     f.zeroField = 0
     f.next = c.freeList
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index c25cf4606..727b039d7 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -659,7 +659,7 @@ when useMarkForDebug or useBackupGc:
   proc stackMarkS(gch: var GcHeap, p: pointer) {.inline.} =
     # the addresses are not as cells on the stack, so turn them to cells:
     var cell = usrToCell(p)
-    var c = cast[TAddress](cell)
+    var c = cast[ByteAddress](cell)
     if c >% PageSize:
       # fast check: does it look like a cell?
       var objStart = cast[PCell](interiorAllocatedPtr(gch.region, cell))
@@ -805,8 +805,8 @@ proc markThreadStacks(gch: var GcHeap) =
     while it != nil:
       # mark registers:
       for i in 0 .. high(it.registers): gcMark(gch, it.registers[i])
-      var sp = cast[TAddress](it.stackBottom)
-      var max = cast[TAddress](it.stackTop)
+      var sp = cast[ByteAddress](it.stackBottom)
+      var max = cast[ByteAddress](it.stackTop)
       # XXX stack direction?
       # XXX unroll this loop:
       while sp <=% max:
diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim
index 47e8b4b1f..fdedcaf18 100644
--- a/lib/system/gc_common.nim
+++ b/lib/system/gc_common.nim
@@ -131,9 +131,9 @@ when defined(sparc): # For SPARC architecture.
   proc isOnStack(p: pointer): bool =
     var stackTop {.volatile.}: pointer
     stackTop = addr(stackTop)
-    var b = cast[TAddress](gch.stackBottom)
-    var a = cast[TAddress](stackTop)
-    var x = cast[TAddress](p)
+    var b = cast[ByteAddress](gch.stackBottom)
+    var a = cast[ByteAddress](stackTop)
+    var x = cast[ByteAddress](p)
     result = a <=% x and x <=% b
 
   template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} =
@@ -150,7 +150,7 @@ when defined(sparc): # For SPARC architecture.
     # Addresses decrease as the stack grows.
     while sp <= max:
       gcMark(gch, sp[])
-      sp = cast[PPointer](cast[TAddress](sp) +% sizeof(pointer))
+      sp = cast[PPointer](cast[ByteAddress](sp) +% sizeof(pointer))
 
 elif defined(ELATE):
   {.error: "stack marking code is to be written for this architecture".}
diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim
index 5bac54772..6eadae17a 100644
--- a/lib/system/jssys.nim
+++ b/lib/system/jssys.nim
@@ -165,15 +165,46 @@ proc SetConstr() {.varargs, asmNoStackFrame, compilerproc.} =
     return result;
   """
 
+proc makeNimstrLit(c: cstring): string {.asmNoStackFrame, compilerproc.} =
+  {.emit: """
+  var ln = `c`.length;
+  var result = new Array(ln + 1);
+  var i = 0;
+  for (; i < ln; ++i) {
+    result[i] = `c`.charCodeAt(i);
+  }
+  result[i] = 0; // terminating zero
+  return result;
+  """.}
+
 proc cstrToNimstr(c: cstring): string {.asmNoStackFrame, compilerproc.} =
-  asm """
-    var result = [];
-    for (var i = 0; i < `c`.length; ++i) {
-      result[i] = `c`.charCodeAt(i);
+  {.emit: """
+  var ln = `c`.length;
+  var result = new Array(ln);
+  var r = 0;
+  for (var i = 0; i < ln; ++i) {
+    var ch = `c`.charCodeAt(i);
+
+    if (ch < 128) {
+      result[r] = ch;
     }
-    result[result.length] = 0; // terminating zero
-    return result;
-  """
+    else if((ch > 127) && (ch < 2048)) {
+      result[r] = (ch >> 6) | 192;
+      ++r;
+      result[r] = (ch & 63) | 128;
+    }
+    else {
+      result[r] = (ch >> 12) | 224;
+      ++r;
+      result[r] = ((ch >> 6) & 63) | 128;
+      ++r;
+      result[r] = (ch & 63) | 128;
+    }
+    ++r;
+  }
+  result[r] = 0; // terminating zero
+  return result;
+  """.}
 
 proc toJSStr(s: string): cstring {.asmNoStackFrame, compilerproc.} =
   asm """
@@ -417,42 +448,6 @@ proc absInt(a: int): int {.compilerproc.} =
 proc absInt64(a: int64): int64 {.compilerproc.} =
   result = if a < 0: a*(-1) else: a
 
-proc leU(a, b: int): bool {.compilerproc.} =
-  result = abs(a) <= abs(b)
-
-proc ltU(a, b: int): bool {.compilerproc.} =
-  result = abs(a) < abs(b)
-
-proc leU64(a, b: int64): bool {.compilerproc.} =
-  result = abs(a) <= abs(b)
-proc ltU64(a, b: int64): bool {.compilerproc.} =
-  result = abs(a) < abs(b)
-
-proc addU(a, b: int): int {.compilerproc.} =
-  result = abs(a) + abs(b)
-proc addU64(a, b: int64): int64 {.compilerproc.} =
-  result = abs(a) + abs(b)
-
-proc subU(a, b: int): int {.compilerproc.} =
-  result = abs(a) - abs(b)
-proc subU64(a, b: int64): int64 {.compilerproc.} =
-  result = abs(a) - abs(b)
-
-proc mulU(a, b: int): int {.compilerproc.} =
-  result = abs(a) * abs(b)
-proc mulU64(a, b: int64): int64 {.compilerproc.} =
-  result = abs(a) * abs(b)
-
-proc divU(a, b: int): int {.compilerproc.} =
-  result = abs(a) div abs(b)
-proc divU64(a, b: int64): int64 {.compilerproc.} =
-  result = abs(a) div abs(b)
-
-proc modU(a, b: int): int {.compilerproc.} =
-  result = abs(a) mod abs(b)
-proc modU64(a, b: int64): int64 {.compilerproc.} =
-  result = abs(a) mod abs(b)
-
 proc ze*(a: int): int {.compilerproc.} =
   result = a
 
diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim
index a227ac98c..05843e2d3 100644
--- a/lib/wrappers/openssl.nim
+++ b/lib/wrappers/openssl.nim
@@ -496,13 +496,12 @@ type
     data: array[MD5_LBLOCK, MD5_LONG]
     num: cuint
 
-{.pragma: ic, importc: "$1".}
 {.push callconv:cdecl, dynlib:DLLUtilName.}
-proc md5_Init*(c: var MD5_CTX): cint{.ic.}
-proc md5_Update*(c: var MD5_CTX; data: pointer; len: csize): cint{.ic.}
-proc md5_Final*(md: cstring; c: var MD5_CTX): cint{.ic.}
-proc md5*(d: ptr cuchar; n: csize; md: ptr cuchar): ptr cuchar{.ic.}
-proc md5_Transform*(c: var MD5_CTX; b: ptr cuchar){.ic.}
+proc md5_Init*(c: var MD5_CTX): cint{.importc: "MD5_Init".}
+proc md5_Update*(c: var MD5_CTX; data: pointer; len: csize): cint{.importc: "MD5_Update".}
+proc md5_Final*(md: cstring; c: var MD5_CTX): cint{.importc: "MD5_Final".}
+proc md5*(d: ptr cuchar; n: csize; md: ptr cuchar): ptr cuchar{.importc: "MD5".}
+proc md5_Transform*(c: var MD5_CTX; b: ptr cuchar){.importc: "MD5_Transform".}
 {.pop.}
 
 from strutils import toHex,toLower
diff --git a/readme.md b/readme.md
index 32dbad9f1..27b2273f0 100644
--- a/readme.md
+++ b/readme.md
@@ -39,9 +39,9 @@ To build from source you will need:
 If you are on a fairly modern *nix system, the following steps should work:
 
 ```
-$ git clone git://github.com/nim-lang/Nim.git
+$ git clone https://github.com/nim-lang/Nim.git
 $ cd Nim
-$ git clone --depth 1 git://github.com/nim-lang/csources
+$ git clone --depth 1 https://github.com/nim-lang/csources
 $ cd csources && sh build.sh
 $ cd ..
 $ bin/nim c koch
diff --git a/tests/js/tstringitems.nim b/tests/js/tstringitems.nim
index f4ea02fec..20aed6e8b 100644
--- a/tests/js/tstringitems.nim
+++ b/tests/js/tstringitems.nim
@@ -3,22 +3,76 @@ discard """
 Hello'''
 """
 
-# bug #2581
+block: # bug #2581
+  const someVars = [ "Hello" ]
+  var someVars2 = [ "Hello" ]
 
-const someVars = [ "Hello" ]
-var someVars2 = [ "Hello" ]
+  proc getSomeVar: string =
+      for i in someVars:
+          if i == "Hello":
+              result = i
+              break
 
-proc getSomeVar: string =
-    for i in someVars:
-        if i == "Hello":
-            result = i
-            break
+  proc getSomeVar2: string =
+      for i in someVars2:
+          if i == "Hello":
+              result = i
+              break
 
-proc getSomeVar2: string =
-    for i in someVars2:
-        if i == "Hello":
-            result = i
-            break
+  echo getSomeVar()
+  echo getSomeVar2()
 
-echo getSomeVar()
-echo getSomeVar2()
+block: # Test compile-time binary data generation, invalid unicode
+  proc signatureMaker(): string {. compiletime .} =
+    const signatureBytes = [137, 80, 78, 71, 13, 10, 26, 10]
+    result = ""
+    for c in signatureBytes: result.add chr(c)
+
+  const cSig = signatureMaker()
+
+  var rSig = newString(8)
+  rSig[0] = chr(137)
+  rSig[1] = chr(80)
+  rSig[2] = chr(78)
+  rSig[3] = chr(71)
+  rSig[4] = chr(13)
+  rSig[5] = chr(10)
+  rSig[6] = chr(26)
+  rSig[7] = chr(10)
+
+  doAssert(rSig == cSig)
+
+block: # Test unicode strings
+  const constStr = "Привет!"
+  var jsStr : cstring
+  {.emit: """`jsStr`[0] = "Привет!";""".}
+
+  doAssert($jsStr == constStr)
+  var runtimeStr = "При"
+  runtimeStr &= "вет!"
+
+  doAssert(runtimeStr == constStr)
+
+block: # Conversions from/to cstring
+  proc stringSaysHelloInRussian(s: cstring): bool =
+    {.emit: """`result` = (`s` === "Привет!");""".}
+
+  doAssert(stringSaysHelloInRussian("Привет!"))
+
+  const constStr = "Привет!"
+  doAssert(stringSaysHelloInRussian(constStr))
+
+  var rtStr = "Привет!"
+  doAssert(stringSaysHelloInRussian(rtStr))
+
+block: # String case of
+  const constStr = "Привет!"
+  var s = "Привет!"
+
+  case s
+  of constStr: discard
+  else: doAssert(false)
+
+  case s
+  of "Привет!": discard
+  else: doAssert(false)
diff --git a/tests/misc/tints.nim b/tests/misc/tints.nim
index ded24fb5c..5bfb8a17c 100644
--- a/tests/misc/tints.nim
+++ b/tests/misc/tints.nim
@@ -23,24 +23,29 @@ template test(opr, a, b, c: expr): stmt {.immediate.} =
 
 test(`+`, 12'i8, -13'i16, -1'i16)
 test(`shl`, 0b11, 0b100, 0b110000)
-test(`shl`, 0b11'i32, 0b100'i64, 0b110000'i64)
+when not defined(js):
+  test(`shl`, 0b11'i32, 0b100'i64, 0b110000'i64)
 test(`shl`, 0b11'i32, 0b100'i32, 0b110000'i32)
 
 test(`or`, 0xf0f0'i16, 0x0d0d'i16, 0xfdfd'i16)
 test(`and`, 0xf0f0'i16, 0xfdfd'i16, 0xf0f0'i16)
 
-test(`shr`, 0xffffffffffffffff'i64, 0x4'i64, 0x0fffffffffffffff'i64)
+when not defined(js):
+  test(`shr`, 0xffffffffffffffff'i64, 0x4'i64, 0x0fffffffffffffff'i64)
 test(`shr`, 0xffff'i16, 0x4'i16, 0x0fff'i16)
 test(`shr`, 0xff'i8, 0x4'i8, 0x0f'i8)
 
-test(`shr`, 0xffffffff'i64, 0x4'i64, 0x0fffffff'i64)
+when not defined(js):
+  test(`shr`, 0xffffffff'i64, 0x4'i64, 0x0fffffff'i64)
 test(`shr`, 0xffffffff'i32, 0x4'i32, 0x0fffffff'i32)
 
-test(`shl`, 0xffffffffffffffff'i64, 0x4'i64, 0xfffffffffffffff0'i64)
+when not defined(js):
+  test(`shl`, 0xffffffffffffffff'i64, 0x4'i64, 0xfffffffffffffff0'i64)
 test(`shl`, 0xffff'i16, 0x4'i16, 0xfff0'i16)
 test(`shl`, 0xff'i8, 0x4'i8, 0xf0'i8)
 
-test(`shl`, 0xffffffff'i64, 0x4'i64, 0xffffffff0'i64)
+when not defined(js):
+  test(`shl`, 0xffffffff'i64, 0x4'i64, 0xffffffff0'i64)
 test(`shl`, 0xffffffff'i32, 0x4'i32, 0xfffffff0'i32)
 
 # bug #916
@@ -50,5 +55,27 @@ proc unc(a: float): float =
 echo int(unc(0.5)), " ", int(unc(-0.5))
 echo int(0.5), " ", int(-0.5)
 
-echo("Success") #OUT Success
+block: # Casts to uint
+  template testCast(fromValue: typed, toType: typed, expectedResult: typed) =
+    let src = fromValue
+    let dst = cast[toType](src)
+    if dst != expectedResult:
+      echo "Casting ", astToStr(fromValue), " to ", astToStr(toType), " = ", dst.int, " instead of ", astToStr(expectedResult)
+    doAssert(dst == expectedResult)
+
+  testCast(-1'i16, uint16, 0xffff'u16)
+  testCast(0xffff'u16, int16, -1'i16)
+
+  testCast(0xff'u16, uint8, 0xff'u8)
+  testCast(0xffff'u16, uint8, 0xff'u8)
+
+  testCast(-1'i16, uint32, 0xffffffff'u32)
+  testCast(0xffffffff'u32, int32, -1)
 
+  testCast(0xfffffffe'u32, int32, -2'i32)
+  testCast(0xffffff'u32, int16, -1'i32)
+
+  testCast(-5'i32, uint8, 251'u8)
+
+
+echo("Success") #OUT Success
diff --git a/tests/misc/tunsignedinc.nim b/tests/misc/tunsignedinc.nim
index 95622156f..60c0559b0 100644
--- a/tests/misc/tunsignedinc.nim
+++ b/tests/misc/tunsignedinc.nim
@@ -1,14 +1,28 @@
-discard """
-  output: '''253'''
-"""
 
-# bug #2427
+block: # bug #2427
+  var x = 0'u8
+  dec x # OverflowError
+  x -= 1 # OverflowError
+  x = x - 1 # No error
 
-import unsigned
+  doAssert(x == 253'u8)
 
-var x = 0'u8
-dec x # OverflowError
-x -= 1 # OverflowError
-x = x - 1 # No error
+block:
+  var x = 130'u8
+  x += 130'u8
+  doAssert(x == 4'u8)
 
-echo x
+block:
+  var x = 40000'u16
+  x = x + 40000'u16
+  doAssert(x == 14464'u16)
+
+block:
+  var x = 4000000000'u32
+  x = x + 4000000000'u32
+  doAssert(x == 3705032704'u32)
+
+block:
+  var x = 123'u16
+  x -= 125
+  doAssert(x == 65534'u16)
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index 73d72289c..ff83379b8 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -220,7 +220,7 @@ proc jsTests(r: var TResults, cat: Category, options: string) =
                    "actiontable/tactiontable", "method/tmultim1",
                    "method/tmultim3", "method/tmultim4",
                    "varres/tvarres0", "varres/tvarres3", "varres/tvarres4",
-                   "varres/tvartup"]:
+                   "varres/tvartup", "misc/tints", "misc/tunsignedinc"]:
     test "tests/" & testfile & ".nim"
 
   for testfile in ["pure/strutils"]:
diff --git a/web/community.txt b/web/community.txt
index fba59f946..f63ad5c25 100644
--- a/web/community.txt
+++ b/web/community.txt
@@ -88,6 +88,13 @@ Nim's Community
 
 .. container:: standout
 
+  Gitter
+  ------
+
+  The `Gitter Chatroom for Nim <https://gitter.im/nim-lang/Nim>`_ is the persistent logged "natural" chatroom for GitHub repositories and very easy to access for GitHub users. This does not need additional software and can send notifications about messages by email.
+
+.. container:: standout
+
   Meetup
   ------
   
diff --git a/web/news.txt b/web/news.txt
index 62c3cef24..61a74127f 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -101,7 +101,7 @@ The following used to work as the environment creation used to be attached to th
     var s: seq[proc(): int {.closure.}] = @[]
     for i in 0 ..< 30:
       let ii = i
-      s.add(proc(): int = return ii*ii))
+      s.add(proc(): int = return ii*ii)
 
 This behaviour has changed in 0.13.0 and now needs to be written as:
 
@@ -133,8 +133,6 @@ via a commit, for a full list see
   (`#3498 <https://github.com/nim-lang/Nim/issues/3498>`_)
 - Fixed "multimethods: Error: internal error: cgmeth.genConv"
   (`#3550 <https://github.com/nim-lang/Nim/issues/3550>`_)
-- Fixed "multimethods: Error: internal error: cgmeth.genConv"
-  (`#3550 <https://github.com/nim-lang/Nim/issues/3550>`_)
 - Fixed "nimscript - SIGSEGV in except block"
   (`#3546 <https://github.com/nim-lang/Nim/issues/3546>`_)
 - Fixed "Bool literals in macros do not work."