summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgexprs.nim61
-rw-r--r--compiler/ccgstmts.nim5
-rw-r--r--compiler/ccgtypes.nim8
-rw-r--r--compiler/cgen.nim23
-rw-r--r--compiler/cgendata.nim2
-rw-r--r--compiler/semexprs.nim1
-rw-r--r--compiler/semfold.nim130
-rw-r--r--doc/manual/types.txt20
-rw-r--r--lib/pure/md5.nim12
-rw-r--r--lib/pure/securehash.nim4
-rw-r--r--lib/pure/strutils.nim2
11 files changed, 46 insertions, 222 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index e62956a0c..0ec16710f 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -134,12 +134,32 @@ proc genSetNode(p: BProc, n: PNode): Rope =
   else:
     result = genRawSetData(cs, size)
 
+proc getStorageLoc(n: PNode): TStorageLoc =
+  case n.kind
+  of nkSym:
+    case n.sym.kind
+    of skParam, skTemp:
+      result = OnStack
+    of skVar, skForVar, skResult, skLet:
+      if sfGlobal in n.sym.flags: result = OnHeap
+      else: result = OnStack
+    of skConst:
+      if sfGlobal in n.sym.flags: result = OnHeap
+      else: result = OnUnknown
+    else: result = OnUnknown
+  of nkDerefExpr, nkHiddenDeref:
+    case n.sons[0].typ.kind
+    of tyVar: result = OnUnknown
+    of tyPtr: result = OnStack
+    of tyRef: result = OnHeap
+    else: internalError(n.info, "getStorageLoc")
+  of nkBracketExpr, nkDotExpr, nkObjDownConv, nkObjUpConv:
+    result = getStorageLoc(n.sons[0])
+  else: result = OnUnknown
+
 proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   if dest.s == OnStack or not usesNativeGC():
     linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
-  elif dest.s == OnStackShadowDup:
-    linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
-    linefmt(p, cpsStmts, "$1 = $2;$n", dupLoc(dest), rdLoc(src))
   elif dest.s == OnHeap:
     # location is on heap
     # now the writer barrier is inlined for performance:
@@ -166,8 +186,6 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   else:
     linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n",
             addrLoc(dest), rdLoc(src))
-    if preciseStack():
-      linefmt(p, cpsStmts, "$1 = $2;$n", dupLoc(dest), rdLoc(src))
 
 proc asgnComplexity(n: PNode): int =
   if n != nil:
@@ -225,7 +243,7 @@ proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
 
 proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   # Consider:
-  # type MyFastString {.shallow.} = string
+  # type TMyFastString {.shallow.} = string
   # Due to the implementation of pragmas this would end up to set the
   # tfShallow flag for the built-in string type too! So we check only
   # here for this flag, where it is reasonably safe to do so
@@ -243,9 +261,6 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   else:
     linefmt(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
             addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
-  if dest.s == OnStackShadowDup:
-    linefmt(p, cpsStmts, "#genericAssignDup((void*)&$1, (void*)$2, $3);$n",
-            dupLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
 
 proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   # This function replaces all other methods for generating
@@ -264,17 +279,12 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
     else:
       linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
               addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t))
-      if dest.s == OnStackShadowDup:
-        linefmt(p, cpsStmts, "$1 = $2;$n", dest.dupLoc, dest.rdLoc)
   of tyString:
     if needToCopy notin flags and src.s != OnStatic:
       genRefAssign(p, dest, src, flags)
     else:
       if dest.s == OnStack or not usesNativeGC():
         linefmt(p, cpsStmts, "$1 = #copyString($2);$n", dest.rdLoc, src.rdLoc)
-      elif dest.s == OnStackShadowDup:
-        linefmt(p, cpsStmts, "$1 = #copyString($2);$n", dest.rdLoc, src.rdLoc)
-        linefmt(p, cpsStmts, "$1 = $2;$n", dest.dupLoc, dest.rdLoc)
       elif dest.s == OnHeap:
         # we use a temporary to care for the dreaded self assignment:
         var tmp: TLoc
@@ -285,8 +295,6 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
       else:
         linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
                addrLoc(dest), rdLoc(src))
-        if preciseStack():
-          linefmt(p, cpsStmts, "$1 = $2;$n", dest.dupLoc, dest.rdLoc)
   of tyProc:
     if needsComplexAssignment(dest.t):
       # optimize closure assignment:
@@ -735,9 +743,6 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
   else: internalError(e.info, "genTupleElem")
   addf(r, ".Field$1", [rope(i)])
   putIntoDest(p, d, tupType.sons[i], r, a.s)
-  if a.s == OnStackShadowDup:
-    d.s = OnStackShadowDup
-    d.dup = ropef("$1[$2]", a.dup, ithRefInTuple(tupType, i))
 
 proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope): PSym =
   var ty = ty
@@ -762,18 +767,12 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
     # so we use Field$i
     addf(r, ".Field$1", [rope(f.position)])
     putIntoDest(p, d, f.typ, r, a.s)
-    if a.s == OnStackShadowDup:
-      d.s = OnStackShadowDup
-      d.dup = ropef("$1[$2]", a.dup, ithRefInTuple(ty, f.position))
   else:
     let field = lookupFieldAgain(p, ty, f, r)
     if field.loc.r == nil: fillObjectFields(p.module, ty)
     if field.loc.r == nil: internalError(e.info, "genRecordField 3 " & typeToString(ty))
     addf(r, ".$1", [field.loc.r])
     putIntoDest(p, d, field.typ, r, a.s)
-    if a.s == OnStackShadowDup and field.loc.dup != nil:
-      d.s = OnStackShadowDup
-      d.dup = ropef("$1.$2", a.dup, field.loc.dup)
   #d.s = a.s
 
 proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
@@ -825,9 +824,6 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
     genFieldCheck(p, e, r, field, ty)
     add(r, rfmt(nil, ".$1", field.loc.r))
     putIntoDest(p, d, field.typ, r, a.s)
-    if a.s == OnStackShadowDup and field.loc.dup != nil:
-      d.s = OnStackShadowDup
-      d.dup = ropef("$1.$2", a.dup, field.loc.dup)
   else:
     genRecordField(p, e.sons[0], d)
 
@@ -855,9 +851,6 @@ proc genArrayElem(p: BProc, x, y: PNode, d: var TLoc) =
   d.inheritLocation(a)
   putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
               rfmt(nil, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.s)
-  if a.s == OnStackShadowDup:
-    d.s = OnStackShadowDup
-    d.dup = ropef("$1[($2)- $3]", a.dup, rdCharLoc(b), first)
 
 proc genCStringElem(p: BProc, x, y: PNode, d: var TLoc) =
   var a, b: TLoc
@@ -878,9 +871,6 @@ proc genOpenArrayElem(p: BProc, x, y: PNode, d: var TLoc) =
   if d.k == locNone: d.s = a.s
   putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
               rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.s)
-  if a.s == OnStackShadowDup:
-    d.s = OnStackShadowDup
-    d.dup = ropef("$1[$2]", a.dup, rdCharLoc(b))
 
 proc genSeqElem(p: BProc, x, y: PNode, d: var TLoc) =
   var a, b: TLoc
@@ -1185,7 +1175,6 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
   var t = e.typ.skipTypes(abstractInst)
   getTemp(p, t, tmp)
   let isRef = t.kind == tyRef
-  let stck = stackPlacement(t)
   var r = rdLoc(tmp)
   if isRef:
     rawGenNew(p, tmp, nil)
@@ -1209,7 +1198,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
     add(tmp2.r, field.loc.r)
     tmp2.k = locTemp
     tmp2.t = field.loc.t
-    tmp2.s = if isRef: OnHeap else: stck
+    tmp2.s = if isRef: OnHeap else: OnStack
     expr(p, it.sons[1], tmp2)
 
   if d.k == locNone:
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 27bb89f60..378951d9d 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -802,8 +802,6 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
   endBlock(p, ropecg(p.module, "} catch (NimException& $1) {$n", [exc]))
   if optStackTrace in p.options:
     linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n")
-  if p.gcFrameLen > 0:
-    linefmt(p, cpsStmts, "#setGcFrame((#GcFrameBase*)&GCF_);$n")
   inc p.inExceptBlock
   var i = 1
   var catchAllPresent = false
@@ -912,9 +910,6 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
   linefmt(p, cpsStmts, "#popSafePoint();$n")
   if optStackTrace in p.options:
     linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n")
-  if p.gcFrameLen > 0:
-    linefmt(p, cpsStmts, "#setGcFrame((#GcFrameBase*)&GCF_);$n")
-
   inc p.inExceptBlock
   var i = 1
   while (i < length) and (t.sons[i].kind == nkExceptBranch):
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 1c14d95f1..0c81ca814 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -282,7 +282,7 @@ proc ccgIntroducedPtr(s: PSym): bool =
 
 proc fillResult(param: PSym) =
   fillLoc(param.loc, locParam, param.typ, ~"Result",
-          stackPlacement(param.typ))
+          OnStack)
   if mapReturnType(param.typ) != ctArray and isInvalidReturnType(param.typ):
     incl(param.loc.flags, lfIndirect)
     param.loc.s = OnUnknown
@@ -376,9 +376,9 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
     result = getTypeDescAux(m, t, check)
 
 proc paramStorageLoc(param: PSym): TStorageLoc =
-  let t = param.typ.skipTypes({tyVar, tyTypeDesc})
-  if t.kind notin {tyArray, tyOpenArray, tyVarargs}:
-    result = stackPlacement(t)
+  if param.typ.skipTypes({tyVar, tyTypeDesc}).kind notin {
+          tyArray, tyOpenArray, tyVarargs}:
+    result = OnStack
   else:
     result = OnUnknown
 
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index d9e771ce7..3797a92c2 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -242,10 +242,6 @@ proc addrLoc(a: TLoc): Rope =
   if lfIndirect notin a.flags and mapType(a.t) != ctArray:
     result = "(&" & result & ")"
 
-proc dupLoc(a: TLoc): Rope =
-  result = a.dup
-  assert result != nil
-
 proc rdCharLoc(a: TLoc): Rope =
   # read a location that may need a char-cast:
   result = rdLoc(a)
@@ -290,13 +286,12 @@ proc resetLoc(p: BProc, loc: var TLoc) =
   if not isComplexValueType(typ):
     if containsGcRef:
       var nilLoc: TLoc
-      initLoc(nilLoc, locTemp, loc.t, stackPlacement(typ))
+      initLoc(nilLoc, locTemp, loc.t, OnStack)
       nilLoc.r = rope("NIM_NIL")
       genRefAssign(p, loc, nilLoc, {afSrcIsNil})
     else:
       linefmt(p, cpsStmts, "$1 = 0;$n", rdLoc(loc))
   else:
-    # XXX use stackPlacement here?
     if optNilCheck in p.options:
       linefmt(p, cpsStmts, "#chckNil((void*)$1);$n", addrLoc(loc))
     if loc.s != OnStack:
@@ -346,21 +341,17 @@ proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
   linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r)
   result.k = locTemp
   result.t = t
-  result.s = stackPlacement(t)
+  result.s = OnStack
   result.flags = {}
   constructLoc(p, result, not needsInit)
 
 proc initGCFrame(p: BProc): Rope =
-  if p.gcFrameLen > 0:
-    result = ropegc(p.module, """
-    struct {#GcFrameBase b_; $1} GCF_;$n
-    GCF_.b_.L=$2;$n
-    #pushGcFrame((GcFrameBase*)&GCF_);$n""" % [
-    p.gcFrameType, rope(p.gcFrameLen)])
+  if p.gcFrameId > 0: result = "struct {$1} GCFRAME_;$n" % [p.gcFrameType]
 
 proc deinitGCFrame(p: BProc): Rope =
-  if p.gcFrameLen > 0:
-    result = ropecg(p.module, "#popGcFrame();$n")
+  if p.gcFrameId > 0:
+    result = ropecg(p.module,
+                    "if (((NU)&GCFRAME_) < 4096) #nimGCFrame(&GCFRAME_);$n")
 
 proc localDebugInfo(p: BProc, s: PSym) =
   if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
@@ -377,7 +368,7 @@ proc localDebugInfo(p: BProc, s: PSym) =
 
 proc localVarDecl(p: BProc; s: PSym): Rope =
   if s.loc.k == locNone:
-    fillLoc(s.loc, locLocalVar, s.typ, mangleLocalName(p, s), stackPlacement(s.typ))
+    fillLoc(s.loc, locLocalVar, s.typ, mangleLocalName(p, s), OnStack)
     if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
   result = getTypeDesc(p.module, s.typ)
   if s.constraint.isNil:
diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim
index 2f927c83e..be087095f 100644
--- a/compiler/cgendata.nim
+++ b/compiler/cgendata.nim
@@ -90,7 +90,7 @@ type
     splitDecls*: int          # > 0 if we are in some context for C++ that
                               # requires 'T x = T()' to become 'T x; x = T()'
                               # (yes, C++ is weird like that)
-    gcFrameLen*: int          # the number of slots in the GC-Frame
+    gcFrameId*: Natural       # for the GC stack marking
     gcFrameType*: Rope        # the struct {} we put the GC markers into
     sigConflicts*: CountTable[string]
 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 76d4be766..5f48e2fc5 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -588,7 +588,6 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
       result = semfold.getConstExpr(c.module, call)
       if result.isNil: result = n
       else: return result
-    result.typ = semfold.getIntervalType(callee.magic, call)
 
   block maybeLabelAsStatic:
     # XXX: temporary work-around needed for tlateboundstatic.
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 84cb0071f..612df1ba3 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -92,26 +92,6 @@ proc pickIntRange(a, b: PType): PType =
 proc isIntRangeOrLit(t: PType): bool =
   result = isIntRange(t) or isIntLit(t)
 
-proc pickMinInt(n: PNode): BiggestInt =
-  if n.kind in {nkIntLit..nkUInt64Lit}:
-    result = n.intVal
-  elif isIntLit(n.typ):
-    result = n.typ.n.intVal
-  elif isIntRange(n.typ):
-    result = firstOrd(n.typ)
-  else:
-    internalError(n.info, "pickMinInt")
-
-proc pickMaxInt(n: PNode): BiggestInt =
-  if n.kind in {nkIntLit..nkUInt64Lit}:
-    result = n.intVal
-  elif isIntLit(n.typ):
-    result = n.typ.n.intVal
-  elif isIntRange(n.typ):
-    result = lastOrd(n.typ)
-  else:
-    internalError(n.info, "pickMaxInt")
-
 proc makeRange(typ: PType, first, last: BiggestInt): PType =
   let minA = min(first, last)
   let maxA = max(first, last)
@@ -137,116 +117,6 @@ proc makeRangeF(typ: PType, first, last: BiggestFloat): PType =
   result.n = n
   addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
 
-proc getIntervalType*(m: TMagic, n: PNode): PType =
-  # Nim requires interval arithmetic for ``range`` types. Lots of tedious
-  # work but the feature is very nice for reducing explicit conversions.
-  const ordIntLit = {nkIntLit..nkUInt64Lit}
-  result = n.typ
-
-  template commutativeOp(opr: untyped) =
-    let a = n.sons[1]
-    let b = n.sons[2]
-    if isIntRangeOrLit(a.typ) and isIntRangeOrLit(b.typ):
-      result = makeRange(pickIntRange(a.typ, b.typ),
-                         opr(pickMinInt(a), pickMinInt(b)),
-                         opr(pickMaxInt(a), pickMaxInt(b)))
-
-  template binaryOp(opr: untyped) =
-    let a = n.sons[1]
-    let b = n.sons[2]
-    if isIntRange(a.typ) and b.kind in {nkIntLit..nkUInt64Lit}:
-      result = makeRange(a.typ,
-                         opr(pickMinInt(a), pickMinInt(b)),
-                         opr(pickMaxInt(a), pickMaxInt(b)))
-
-  case m
-  of mUnaryMinusI, mUnaryMinusI64:
-    let a = n.sons[1].typ
-    if isIntRange(a):
-      # (1..3) * (-1) == (-3.. -1)
-      result = makeRange(a, 0|-|lastOrd(a), 0|-|firstOrd(a))
-  of mUnaryMinusF64:
-    let a = n.sons[1].typ
-    if isFloatRange(a):
-      result = makeRangeF(a, -getFloat(a.n.sons[1]),
-                             -getFloat(a.n.sons[0]))
-  of mAbsF64:
-    let a = n.sons[1].typ
-    if isFloatRange(a):
-      # abs(-5.. 1) == (1..5)
-      if a.n[0].floatVal <= 0.0:
-        result = makeRangeF(a, 0.0, abs(getFloat(a.n.sons[0])))
-      else:
-        result = makeRangeF(a, abs(getFloat(a.n.sons[1])),
-                               abs(getFloat(a.n.sons[0])))
-  of mAbsI:
-    let a = n.sons[1].typ
-    if isIntRange(a):
-      if a.n[0].intVal <= 0:
-        result = makeRange(a, 0, `|abs|`(getInt(a.n.sons[0])))
-      else:
-        result = makeRange(a, `|abs|`(getInt(a.n.sons[1])),
-                              `|abs|`(getInt(a.n.sons[0])))
-  of mSucc:
-    let a = n.sons[1].typ
-    let b = n.sons[2].typ
-    if isIntRange(a) and isIntLit(b):
-      # (-5.. 1) + 6 == (-5 + 6)..(-1 + 6)
-      result = makeRange(a, pickMinInt(n.sons[1]) |+| pickMinInt(n.sons[2]),
-                            pickMaxInt(n.sons[1]) |+| pickMaxInt(n.sons[2]))
-  of mPred:
-    let a = n.sons[1].typ
-    let b = n.sons[2].typ
-    if isIntRange(a) and isIntLit(b):
-      result = makeRange(a, pickMinInt(n.sons[1]) |-| pickMinInt(n.sons[2]),
-                            pickMaxInt(n.sons[1]) |-| pickMaxInt(n.sons[2]))
-  of mAddI, mAddU:
-    commutativeOp(`|+|`)
-  of mMulI, mMulU:
-    commutativeOp(`|*|`)
-  of mSubI, mSubU:
-    binaryOp(`|-|`)
-  of mBitandI:
-    # since uint64 is still not even valid for 'range' (since it's no ordinal
-    # yet), we exclude it from the list (see bug #1638) for now:
-    var a = n.sons[1]
-    var b = n.sons[2]
-    # symmetrical:
-    if b.kind notin ordIntLit: swap(a, b)
-    if b.kind in ordIntLit:
-      let x = b.intVal|+|1
-      if (x and -x) == x and x >= 0:
-        result = makeRange(n.typ, 0, b.intVal)
-  of mModU:
-    let a = n.sons[1]
-    let b = n.sons[2]
-    if b.kind in ordIntLit:
-      if b.intVal >= 0:
-        result = makeRange(n.typ, 0, b.intVal-1)
-      else:
-        result = makeRange(n.typ, b.intVal+1, 0)
-  of mModI:
-    # so ... if you ever wondered about modulo's signedness; this defines it:
-    let a = n.sons[1]
-    let b = n.sons[2]
-    if b.kind in {nkIntLit..nkUInt64Lit}:
-      if b.intVal >= 0:
-        result = makeRange(n.typ, -(b.intVal-1), b.intVal-1)
-      else:
-        result = makeRange(n.typ, b.intVal+1, -(b.intVal+1))
-  of mDivI, mDivU:
-    binaryOp(`|div|`)
-  of mMinI:
-    commutativeOp(min)
-  of mMaxI:
-    commutativeOp(max)
-  else: discard
-
-discard """
-  mShlI,
-  mShrI, mAddF64, mSubF64, mMulF64, mDivF64, mMaxF64, mMinF64
-"""
-
 proc evalIs(n, a: PNode): PNode =
   # XXX: This should use the standard isOpImpl
   internalAssert a.kind == nkSym and a.sym.kind == skType
diff --git a/doc/manual/types.txt b/doc/manual/types.txt
index e6875f2df..927cda9e1 100644
--- a/doc/manual/types.txt
+++ b/doc/manual/types.txt
@@ -136,26 +136,6 @@ determined). Assignments from the base type to one of its subrange types
 
 A subrange type has the same size as its base type (``int`` in the example).
 
-Nim requires `interval arithmetic`:idx: for subrange types over a set
-of built-in operators that involve constants: ``x %% 3`` is of
-type ``range[0..2]``. The following built-in operators for integers are
-affected by this rule: ``-``, ``+``, ``*``, ``min``, ``max``, ``succ``,
-``pred``, ``mod``, ``div``, ``%%``, ``and`` (bitwise ``and``).
-
-Bitwise ``and`` only produces a ``range`` if one of its operands is a
-constant *x* so that (x+1) is a power of two.
-(Bitwise ``and`` is then a ``%%`` operation.)
-
-This means that the following code is accepted:
-
-.. code-block:: nim
-  case (x and 3) + 7
-  of 7: echo "A"
-  of 8: echo "B"
-  of 9: echo "C"
-  of 10: echo "D"
-  # note: no ``else`` required as (x and 3) + 7 has the type: range[7..10]
-
 
 Pre-defined floating point types
 --------------------------------
diff --git a/lib/pure/md5.nim b/lib/pure/md5.nim
index 44b9ed0d4..1ff3a9824 100644
--- a/lib/pure/md5.nim
+++ b/lib/pure/md5.nim
@@ -78,10 +78,10 @@ proc encode(dest: var MD5Block, src: cstring) =
 proc decode(dest: var openArray[uint8], src: openArray[uint32]) =
   var i = 0
   for j in 0..high(src):
-    dest[i] = src[j] and 0xff'u32
-    dest[i+1] = src[j] shr 8 and 0xff'u32
-    dest[i+2] = src[j] shr 16 and 0xff'u32
-    dest[i+3] = src[j] shr 24 and 0xff'u32
+    dest[i] = uint8(src[j] and 0xff'u32)
+    dest[i+1] = uint8(src[j] shr 8 and 0xff'u32)
+    dest[i+2] = uint8(src[j] shr 16 and 0xff'u32)
+    dest[i+3] = uint8(src[j] shr 24 and 0xff'u32)
     inc(i, 4)
 
 proc transform(buffer: pointer, state: var MD5State) =
@@ -216,8 +216,8 @@ proc `$`*(d: MD5Digest): string =
   const digits = "0123456789abcdef"
   result = ""
   for i in 0..15:
-    add(result, digits[(d[i] shr 4) and 0xF])
-    add(result, digits[d[i] and 0xF])
+    add(result, digits[(d[i].int shr 4) and 0xF])
+    add(result, digits[d[i].int and 0xF])
 
 proc getMD5*(s: string): string =
   ## computes an MD5 value of `s` and returns its string representation
diff --git a/lib/pure/securehash.nim b/lib/pure/securehash.nim
index f141732a7..c19146669 100644
--- a/lib/pure/securehash.nim
+++ b/lib/pure/securehash.nim
@@ -148,13 +148,13 @@ proc sha1(src: cstring; len: int): Sha1Digest =
   while lastBlockBytes < endCurrentBlock:
 
     var value = uint32(src[lastBlockBytes + currentBlock]) shl
-                ((3'u32 - (lastBlockBytes and 3)) shl 3)
+                ((3'u32 - uint32(lastBlockBytes and 3)) shl 3)
 
     w[lastBlockBytes shr 2] = w[lastBlockBytes shr 2] or value
     inc(lastBlockBytes)
 
   w[lastBlockBytes shr 2] = w[lastBlockBytes shr 2] or (
-    0x80'u32 shl ((3'u32 - (lastBlockBytes and 3)) shl 3)
+    0x80'u32 shl ((3'u32 - uint32(lastBlockBytes and 3)) shl 3)
   )
 
   if endCurrentBlock >= 56:
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 20b2657f6..346248a25 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -887,7 +887,7 @@ proc toHex*(x: BiggestInt, len: Positive): string {.noSideEffect,
     n = x
   result = newString(len)
   for j in countdown(len-1, 0):
-    result[j] = HexChars[n and 0xF]
+    result[j] = HexChars[(n and 0xF).int]
     n = n shr 4
     # handle negative overflow
     if n == 0 and x < 0: n = -1