summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/evalffi.nim16
-rw-r--r--compiler/jsgen.nim95
-rw-r--r--compiler/renderer.nim6
-rw-r--r--doc/manual/exceptions.txt10
-rw-r--r--doc/manual/modules.txt2
-rw-r--r--doc/manual/procs.txt10
-rw-r--r--doc/manual/stmts.txt32
-rw-r--r--doc/manual/types.txt2
-rw-r--r--doc/nimc.txt30
-rw-r--r--doc/tut1.txt124
-rw-r--r--doc/tut2.txt10
-rw-r--r--lib/pure/nimprof.nim2
-rw-r--r--lib/pure/ospaths.nim4
-rw-r--r--lib/pure/osproc.nim15
-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.nim45
-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/testament/categories.nim2
23 files changed, 369 insertions, 190 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 c36f5a5a3..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
@@ -344,19 +367,22 @@ 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 = case n[1].typ.skipTypes(abstractRange).size
-    of 1: "& 0xff"
-    of 2: "& 0xffff"
-    of 4: ">>> 0"
-    else: ""
+  let trimmer = unsignedTrimmer(n[1].typ.skipTypes(abstractRange).size)
   if reassign:
-    r.res = "$1 = (($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, rope trimmer]
+    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, rope trimmer]
+    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
@@ -392,6 +418,12 @@ proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
   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
@@ -568,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)
@@ -1324,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))
@@ -1569,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
@@ -1596,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
@@ -1630,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/compiler/renderer.nim b/compiler/renderer.nim
index 8e4aa1831..34688c798 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -438,7 +438,7 @@ proc lsub(n: PNode): int =
         len("if_:_")
   of nkElifExpr: result = lsons(n) + len("_elif_:_")
   of nkElseExpr: result = lsub(n.sons[0]) + len("_else:_") # type descriptions
-  of nkTypeOfExpr: result = (if n.len > 0: lsub(n.sons[0]) else: 0)+len("type_")
+  of nkTypeOfExpr: result = (if n.len > 0: lsub(n.sons[0]) else: 0)+len("type()")
   of nkRefTy: result = (if n.len > 0: lsub(n.sons[0])+1 else: 0) + len("ref")
   of nkPtrTy: result = (if n.len > 0: lsub(n.sons[0])+1 else: 0) + len("ptr")
   of nkVarTy: result = (if n.len > 0: lsub(n.sons[0])+1 else: 0) + len("var")
@@ -1030,8 +1030,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     putWithSpace(g, tkColon, ":")
     gsub(g, n.sons[0])
   of nkTypeOfExpr:
-    putWithSpace(g, tkType, "type")
+    put(g, tkType, "type")
+    put(g, tkParLe, "(")
     if n.len > 0: gsub(g, n.sons[0])
+    put(g, tkParRi, ")")
   of nkRefTy:
     if sonsLen(n) > 0:
       putWithSpace(g, tkRef, "ref")
diff --git a/doc/manual/exceptions.txt b/doc/manual/exceptions.txt
index 0010d5d09..e7af65386 100644
--- a/doc/manual/exceptions.txt
+++ b/doc/manual/exceptions.txt
@@ -15,15 +15,15 @@ Example:
     try:
       var a = readLine(f)
       var b = readLine(f)
-      echo("sum: " & $(parseInt(a) + parseInt(b)))
+      echo "sum: " & $(parseInt(a) + parseInt(b))
     except OverflowError:
-      echo("overflow!")
+      echo "overflow!"
     except ValueError:
-      echo("could not convert string to integer")
+      echo "could not convert string to integer"
     except IOError:
-      echo("IO error!")
+      echo "IO error!"
     except:
-      echo("Unknown exception!")
+      echo "Unknown exception!"
     finally:
       close(f)
 
diff --git a/doc/manual/modules.txt b/doc/manual/modules.txt
index ac47d89dd..9cb6a11af 100644
--- a/doc/manual/modules.txt
+++ b/doc/manual/modules.txt
@@ -144,7 +144,7 @@ modules don't need to import a module's dependencies:
 
   # B.MyObject has been imported implicitly here:
   var x: MyObject
-  echo($x)
+  echo $x
 
 Note on paths
 -----------
diff --git a/doc/manual/procs.txt b/doc/manual/procs.txt
index 654893286..9ce92de0d 100644
--- a/doc/manual/procs.txt
+++ b/doc/manual/procs.txt
@@ -129,9 +129,9 @@ to supply any type of first argument for procedures:
 
 .. code-block:: nim
 
-  echo("abc".len) # is the same as echo(len("abc"))
-  echo("abc".toUpper())
-  echo({'a', 'b', 'c'}.card)
+  echo "abc".len # is the same as echo len "abc"
+  echo "abc".toUpper()
+  echo {'a', 'b', 'c'}.card
   stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo")
 
 Another way to look at the method call syntax is that it provides the missing
@@ -486,7 +486,7 @@ state are automatically saved between calls. Example:
       inc(i)
 
   for ch in items("hello world"): # `ch` is an iteration variable
-    echo(ch)
+    echo ch
 
 The compiler generates code as if the programmer would have written this:
 
@@ -494,7 +494,7 @@ The compiler generates code as if the programmer would have written this:
   var i = 0
   while i < len(a):
     var ch = a[i]
-    echo(ch)
+    echo ch
     inc(i)
 
 If the iterator yields a tuple, there can be as many iteration variables
diff --git a/doc/manual/stmts.txt b/doc/manual/stmts.txt
index 59f7eef55..83852b1ff 100644
--- a/doc/manual/stmts.txt
+++ b/doc/manual/stmts.txt
@@ -234,11 +234,11 @@ Example:
   var name = readLine(stdin)
 
   if name == "Andreas":
-    echo("What a nice name!")
+    echo "What a nice name!"
   elif name == "":
-    echo("Don't you have a name?")
+    echo "Don't you have a name?"
   else:
-    echo("Boring name...")
+    echo "Boring name..."
 
 The ``if`` statement is a simple way to make a branch in the control flow:
 The expression after the keyword ``if`` is evaluated, if it is true
@@ -269,17 +269,17 @@ Example:
 
   case readline(stdin)
   of "delete-everything", "restart-computer":
-    echo("permission denied")
-  of "go-for-a-walk":     echo("please yourself")
-  else:                   echo("unknown command")
+    echo "permission denied"
+  of "go-for-a-walk":     echo "please yourself"
+  else:                   echo "unknown command"
 
   # indentation of the branches is also allowed; and so is an optional colon
   # after the selecting expression:
   case readline(stdin):
     of "delete-everything", "restart-computer":
-      echo("permission denied")
-    of "go-for-a-walk":     echo("please yourself")
-    else:                   echo("unknown command")
+      echo "permission denied"
+    of "go-for-a-walk":     echo "please yourself"
+    else:                   echo "unknown command"
 
 
 The ``case`` statement is similar to the if statement, but it represents
@@ -326,13 +326,13 @@ Example:
 .. code-block:: nim
 
   when sizeof(int) == 2:
-    echo("running on a 16 bit system!")
+    echo "running on a 16 bit system!"
   elif sizeof(int) == 4:
-    echo("running on a 32 bit system!")
+    echo "running on a 32 bit system!"
   elif sizeof(int) == 8:
-    echo("running on a 64 bit system!")
+    echo "running on a 64 bit system!"
   else:
-    echo("cannot happen!")
+    echo "cannot happen!"
 
 The ``when`` statement is almost identical to the ``if`` statement with some
 exceptions:
@@ -435,7 +435,7 @@ Example:
         if a[j][i] == 7:
           found = true
           break myblock # leave the block, in this case both for-loops
-  echo(found)
+  echo found
 
 The block statement is a means to group statements to a (named) ``block``.
 Inside the block, the ``break`` statement is allowed to leave the block
@@ -462,10 +462,10 @@ While statement
 Example:
 
 .. code-block:: nim
-  echo("Please tell me your password: \n")
+  echo "Please tell me your password: \n"
   var pw = readLine(stdin)
   while pw != "12345":
-    echo("Wrong password! Next try: \n")
+    echo "Wrong password! Next try: \n"
     pw = readLine(stdin)
 
 
diff --git a/doc/manual/types.txt b/doc/manual/types.txt
index babf3286f..a1596bcea 100644
--- a/doc/manual/types.txt
+++ b/doc/manual/types.txt
@@ -546,7 +546,7 @@ so that the builtin ``echo`` proc does what is expected:
 .. code-block:: nim
   proc echo*(x: varargs[expr, `$`]) {...}
 
-  echo(@[1, 2, 3])
+  echo @[1, 2, 3]
   # prints "@[1, 2, 3]" and not "123"
 
 
diff --git a/doc/nimc.txt b/doc/nimc.txt
index 95449d060..e7cb57037 100644
--- a/doc/nimc.txt
+++ b/doc/nimc.txt
@@ -333,21 +333,21 @@ Nim provides language integration with external IDEs through the
 idetools command. See the documentation of `idetools <idetools.html>`_
 for further information.
 
-
-Nim interactive mode
-====================
-
-The Nim compiler supports an interactive mode. This is also known as
-a `REPL`:idx: (*read eval print loop*). If Nim has been built with the
-``-d:useGnuReadline`` switch, it uses the GNU readline library for terminal
-input management. To start Nim in interactive mode use the command
-``nim i``. To quit use the ``quit()`` command. To determine whether an input
-line is an incomplete statement to be continued these rules are used:
-
-1. The line ends with ``[-+*/\\<>!\?\|%&$@~,;:=#^]\s*$`` (operator symbol followed by optional whitespace).
-2. The line starts with a space (indentation).
-3. The line is within a triple quoted string literal. However, the detection
-   does not work if the line contains more than one ``"""``.
+..
+  Nim interactive mode
+  ====================
+
+  The Nim compiler supports an interactive mode. This is also known as
+  a `REPL`:idx: (*read eval print loop*). If Nim has been built with the
+  ``-d:useGnuReadline`` switch, it uses the GNU readline library for terminal
+  input management. To start Nim in interactive mode use the command
+  ``nim secret``. To quit use the ``quit()`` command. To determine whether an input
+  line is an incomplete statement to be continued these rules are used:
+
+  1. The line ends with ``[-+*/\\<>!\?\|%&$@~,;:=#^]\s*$`` (operator symbol followed by optional whitespace).
+  2. The line starts with a space (indentation).
+  3. The line is within a triple quoted string literal. However, the detection
+     does not work if the line contains more than one ``"""``.
 
 
 Nim for embedded systems
diff --git a/doc/tut1.txt b/doc/tut1.txt
index 747c1a3ff..d896a7044 100644
--- a/doc/tut1.txt
+++ b/doc/tut1.txt
@@ -31,9 +31,9 @@ We start the tour with a modified "hello world" program:
 
 .. code-block:: Nim
   # This is a comment
-  echo("What's your name? ")
+  echo "What's your name? "
   var name: string = readLine(stdin)
-  echo("Hi, ", name, "!")
+  echo "Hi, ", name, "!"
 
 
 Save this code to the file "greetings.nim". Now compile and run it::
@@ -250,11 +250,11 @@ The if statement is one way to branch the control flow:
 .. code-block:: nim
   let name = readLine(stdin)
   if name == "":
-    echo("Poor soul, you lost your name?")
+    echo "Poor soul, you lost your name?"
   elif name == "name":
-    echo("Very funny, your name is name.")
+    echo "Very funny, your name is name."
   else:
-    echo("Hi, ", name, "!")
+    echo "Hi, ", name, "!"
 
 There can be zero or more ``elif`` parts, and the ``else`` part is optional.
 The keyword ``elif`` is short for ``else if``, and is useful to avoid
@@ -272,13 +272,13 @@ a multi-branch:
   let name = readLine(stdin)
   case name
   of "":
-    echo("Poor soul, you lost your name?")
+    echo "Poor soul, you lost your name?"
   of "name":
-    echo("Very funny, your name is name.")
+    echo "Very funny, your name is name."
   of "Dave", "Frank":
-    echo("Cool name!")
+    echo "Cool name!"
   else:
-    echo("Hi, ", name, "!")
+    echo "Hi, ", name, "!"
 
 As it can be seen, for an ``of`` branch a comma separated list of values is also
 allowed.
@@ -291,11 +291,11 @@ For integers or other ordinal types value ranges are also possible:
   # this statement will be explained later:
   from strutils import parseInt
 
-  echo("A number please: ")
+  echo "A number please: "
   let n = parseInt(readLine(stdin))
   case n
-  of 0..2, 4..7: echo("The number is in the set: {0, 1, 2, 4, 5, 6, 7}")
-  of 3, 8: echo("The number is 3 or 8")
+  of 0..2, 4..7: echo "The number is in the set: {0, 1, 2, 4, 5, 6, 7}"
+  of 3, 8: echo "The number is 3 or 8"
 
 However, the above code does not compile: the reason is that you have to cover
 every value that ``n`` may contain, but the code only handles the values
@@ -306,8 +306,8 @@ the compiler that for every other value nothing should be done:
 .. code-block:: nim
   ...
   case n
-  of 0..2, 4..7: echo("The number is in the set: {0, 1, 2, 4, 5, 6, 7}")
-  of 3, 8: echo("The number is 3 or 8")
+  of 0..2, 4..7: echo "The number is in the set: {0, 1, 2, 4, 5, 6, 7}"
+  of 3, 8: echo "The number is 3 or 8"
   else: discard
 
 The empty `discard statement`_ is a *do nothing* statement. The compiler knows
@@ -327,10 +327,10 @@ The while statement is a simple looping construct:
 
 .. code-block:: nim
 
-  echo("What's your name? ")
+  echo "What's your name? "
   var name = readLine(stdin)
   while name == "":
-    echo("Please tell me your name: ")
+    echo "Please tell me your name: "
     name = readLine(stdin)
     # no ``var``, because we do not declare a new variable here
 
@@ -346,9 +346,9 @@ provides. The example uses the built-in `countup <system.html#countup>`_
 iterator:
 
 .. code-block:: nim
-  echo("Counting to ten: ")
+  echo "Counting to ten: "
   for i in countup(1, 10):
-    echo($i)
+    echo $i
   # --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines
 
 The built-in `$ <system.html#$>`_ operator turns an integer (``int``) and many
@@ -358,19 +358,19 @@ other types into a string. The variable ``i`` is implicitly declared by the
 Each value is ``echo``-ed. This code does the same:
 
 .. code-block:: nim
-  echo("Counting to 10: ")
+  echo "Counting to 10: "
   var i = 1
   while i <= 10:
-    echo($i)
+    echo $i
     inc(i) # increment i by 1
   # --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines
 
 Counting down can be achieved as easily (but is less often needed):
 
 .. code-block:: nim
-  echo("Counting down from 10 to 1: ")
+  echo "Counting down from 10 to 1: "
   for i in countdown(10, 1):
-    echo($i)
+    echo $i
   # --> Outputs 10 9 8 7 6 5 4 3 2 1 on different lines
 
 Since counting up occurs so often in programs, Nim also has a `..
@@ -390,7 +390,7 @@ outside the loop:
 .. code-block:: nim
   while false:
     var x = "hi"
-  echo(x) # does not work
+  echo x # does not work
 
 A while (for) statement introduces an implicit block. Identifiers
 are only visible within the block they have been declared. The ``block``
@@ -399,7 +399,7 @@ statement can be used to open a new block explicitly:
 .. code-block:: nim
   block myblock:
     var x = "hi"
-  echo(x) # does not work either
+  echo x # does not work either
 
 The block's *label* (``myblock`` in the example) is optional.
 
@@ -412,18 +412,18 @@ innermost construct, unless a label of a block is given:
 
 .. code-block:: nim
   block myblock:
-    echo("entering block")
+    echo "entering block"
     while true:
-      echo("looping")
+      echo "looping"
       break # leaves the loop, but not the block
-    echo("still in block")
+    echo "still in block"
 
   block myblock2:
-    echo("entering block")
+    echo "entering block"
     while true:
-      echo("looping")
+      echo "looping"
       break myblock2 # leaves the block (and the loop)
-    echo("still in block")
+    echo "still in block"
 
 
 Continue statement
@@ -435,7 +435,7 @@ the next iteration immediately:
   while true:
     let x = readLine(stdin)
     if x == "": continue
-    echo(x)
+    echo x
 
 
 When statement
@@ -446,13 +446,13 @@ Example:
 .. code-block:: nim
 
   when system.hostOS == "windows":
-    echo("running on Windows!")
+    echo "running on Windows!"
   elif system.hostOS == "linux":
-    echo("running on Linux!")
+    echo "running on Linux!"
   elif system.hostOS == "macosx":
-    echo("running on Mac OS X!")
+    echo "running on Mac OS X!"
   else:
-    echo("unknown operating system")
+    echo "unknown operating system"
 
 The ``when`` statement is almost identical to the ``if`` statement with some
 differences:
@@ -533,17 +533,17 @@ procedures are defined with the ``proc`` keyword:
 
 .. code-block:: nim
   proc yes(question: string): bool =
-    echo(question, " (y/n)")
+    echo question, " (y/n)"
     while true:
       case readLine(stdin)
       of "y", "Y", "yes", "Yes": return true
       of "n", "N", "no", "No": return false
-      else: echo("Please be clear: yes or no")
+      else: echo "Please be clear: yes or no"
 
   if yes("Should I delete all your important files?"):
-    echo("I'm sorry Dave, I'm afraid I can't do that.")
+    echo "I'm sorry Dave, I'm afraid I can't do that."
   else:
-    echo("I think you know what the problem is just as well as I do.")
+    echo "I think you know what the problem is just as well as I do."
 
 This example shows a procedure named ``yes`` that asks the user a ``question``
 and returns true if they answered "yes" (or something similar) and returns
@@ -611,8 +611,8 @@ caller, a ``var`` parameter can be used:
   var
     x, y: int
   divmod(8, 5, x, y) # modifies x and y
-  echo(x)
-  echo(y)
+  echo x
+  echo y
 
 In the example, ``res`` and ``remainder`` are `var parameters`.
 Var parameters can be modified by the procedure and the changes are
@@ -701,8 +701,8 @@ Nim provides the ability to overload procedures similar to C++:
     if x: result = "true"
     else: result = "false"
 
-  echo(toString(13))   # calls the toString(x: int) proc
-  echo(toString(true)) # calls the toString(x: bool) proc
+  echo toString(13)   # calls the toString(x: int) proc
+  echo toString(true) # calls the toString(x: bool) proc
 
 (Note that ``toString`` is usually the `$ <system.html#$>`_ operator in
 Nim.) The compiler chooses the most appropriate proc for the ``toString``
@@ -743,7 +743,7 @@ The "``" notation can also be used to call an operator just like any other
 procedure:
 
 .. code-block:: nim
-  if `==`( `+`(3, 4), 7): echo("True")
+  if `==`( `+`(3, 4), 7): echo "True"
 
 
 Forward declarations
@@ -790,9 +790,9 @@ Iterators
 Let's return to the boring counting example:
 
 .. code-block:: nim
-  echo("Counting to ten: ")
+  echo "Counting to ten: "
   for i in countup(1, 10):
-    echo($i)
+    echo $i
 
 Can a `countup <system.html#countup>`_ proc be written that supports this
 loop? Lets try:
@@ -1000,15 +1000,15 @@ there is a difference between the ``$`` and ``repr`` outputs:
     myString = "nim"
     myInteger = 42
     myFloat = 3.14
-  echo($myBool, ":", repr(myBool))
+  echo $myBool, ":", repr(myBool)
   # --> true:true
-  echo($myCharacter, ":", repr(myCharacter))
+  echo $myCharacter, ":", repr(myCharacter)
   # --> n:'n'
-  echo($myString, ":", repr(myString))
+  echo $myString, ":", repr(myString)
   # --> nim:0x10fa8c050"nim"
-  echo($myInteger, ":", repr(myInteger))
+  echo $myInteger, ":", repr(myInteger)
   # --> 42:42
-  echo($myFloat, ":", repr(myFloat))
+  echo $myFloat, ":", repr(myFloat)
   # --> 3.1400000000000001e+00:3.1400000000000001e+00
 
 
@@ -1040,7 +1040,7 @@ at runtime by 0, the second by 1 and so on. Example:
       north, east, south, west
 
   var x = south      # `x` is of type `Direction`; its value is `south`
-  echo($x)           # writes "south" to `stdout`
+  echo $x           # writes "south" to `stdout`
 
 All comparison operators can be used with enumeration types.
 
@@ -1133,7 +1133,7 @@ Arrays can be constructed via ``[]``:
     x: IntArray
   x = [1, 2, 3, 4, 5, 6]
   for i in low(x)..high(x):
-    echo(x[i])
+    echo x[i]
 
 The notation ``x[i]`` is used to access the i-th element of ``x``.
 Array access is always bounds checked (at compile-time or at runtime). These
@@ -1208,7 +1208,7 @@ to specify a range from zero to the specified index minus one:
   x = [1, 2, 3, 4, 5, 6]
   y = x
   for i in low(x)..high(x):
-    echo(x[i], y[i])
+    echo x[i], y[i]
 
 
 Sequences
@@ -1254,13 +1254,13 @@ value. Here the ``for`` statement is looping over the results from the
 
 .. code-block:: nim
   for i in @[3, 4, 5]:
-    echo($i)
+    echo $i
   # --> 3
   # --> 4
   # --> 5
 
   for i, value in @[3, 4, 5]:
-    echo("index: ", $i, ", value:", $value)
+    echo "index: ", $i, ", value:", $value
   # --> index: 0, value:3
   # --> index: 1, value:4
   # --> index: 2, value:5
@@ -1386,16 +1386,16 @@ integer.
   # the same, but less readable:
   person = ("Peter", 30)
 
-  echo(person.name) # "Peter"
-  echo(person.age)  # 30
+  echo person.name # "Peter"
+  echo person.age  # 30
 
-  echo(person[0]) # "Peter"
-  echo(person[1]) # 30
+  echo person[0] # "Peter"
+  echo person[1] # 30
 
   # You don't need to declare tuples in a separate type section.
   var building: tuple[street: string, number: int]
   building = ("Rue del Percebe", 13)
-  echo(building.street)
+  echo building.street
 
   # The following line does not compile, they are different tuples!
   #person = building
@@ -1503,7 +1503,7 @@ techniques.
 Example:
 
 .. code-block:: nim
-  proc echoItem(x: int) = echo(x)
+  proc echoItem(x: int) = echo x
 
   proc forEach(action: proc (x: int)) =
     const
diff --git a/doc/tut2.txt b/doc/tut2.txt
index 563344570..3f94325ff 100644
--- a/doc/tut2.txt
+++ b/doc/tut2.txt
@@ -204,9 +204,9 @@ for any type:
 
 .. code-block:: nim
 
-  echo("abc".len) # is the same as echo(len("abc"))
-  echo("abc".toUpper())
-  echo({'a', 'b', 'c'}.card)
+  echo "abc".len # is the same as echo len("abc")
+  echo "abc".toUpper()
+  echo {'a', 'b', 'c'}.card
   stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo")
 
 (Another way to look at the method call syntax is that it provides the missing
@@ -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/ospaths.nim b/lib/pure/ospaths.nim
index e9f5bee0a..9fc816f2f 100644
--- a/lib/pure/ospaths.nim
+++ b/lib/pure/ospaths.nim
@@ -567,7 +567,9 @@ when declared(getEnv) or defined(nimscript):
     var path = string(getEnv("PATH"))
     for candidate in split(path, PathSep):
       when defined(windows):
-        var x = candidate / result
+        var x = (if candidate[0] == '"' and candidate[^1] == '"':
+                  substr(candidate, 1, candidate.len-2) else: candidate) /
+               result
       else:
         var x = expandTilde(candidate) / result
       if existsFile(x): return x
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/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 3df460952..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 """
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/testament/categories.nim b/tests/testament/categories.nim
index 3200c7da9..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", "misc/tunsignedinc"]:
+                   "varres/tvartup", "misc/tints", "misc/tunsignedinc"]:
     test "tests/" & testfile & ".nim"
 
   for testfile in ["pure/strutils"]: