summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2016-07-29 17:35:51 +0200
committerAndreas Rumpf <rumpf_a@web.de>2016-07-29 23:51:01 +0200
commit60b187513ed8e2a061816a912e372a1c81794d50 (patch)
tree9ee88f0234c633d232b55fc9bbe2cca38b2b0866
parent9ee5b5eabca9455f0c31a89c865013afa5a2c39e (diff)
downloadNim-60b187513ed8e2a061816a912e372a1c81794d50.tar.gz
stdlib and compiler don't use .immediate anymore
-rw-r--r--compiler/ast.nim2
-rw-r--r--compiler/ccgmerge.nim2
-rw-r--r--compiler/ccgstmts.nim2
-rw-r--r--compiler/extccomp.nim2
-rw-r--r--compiler/jsgen.nim2
-rw-r--r--compiler/parser.nim2
-rw-r--r--compiler/pragmas.nim5
-rw-r--r--compiler/semfold.nim4
-rw-r--r--compiler/semgnrc.nim9
-rw-r--r--compiler/semparallel.nim2
-rw-r--r--compiler/semtempl.nim8
-rw-r--r--compiler/sigmatch.nim6
-rw-r--r--compiler/suggest.nim2
-rw-r--r--compiler/types.nim2
-rw-r--r--compiler/vm.nim19
-rw-r--r--compiler/vmdef.nim12
-rw-r--r--compiler/vmgen.nim4
-rw-r--r--compiler/vmhooks.nim4
-rw-r--r--compiler/vmops.nim16
-rw-r--r--lib/core/macros.nim17
-rw-r--r--lib/impure/nre.nim6
-rw-r--r--lib/pure/asyncdispatch.nim8
-rw-r--r--lib/pure/collections/sequtils.nim24
-rw-r--r--lib/pure/collections/sets.nim4
-rw-r--r--lib/pure/collections/tableimpl.nim14
-rw-r--r--lib/pure/collections/tables.nim16
-rw-r--r--lib/pure/future.nim6
-rw-r--r--lib/pure/net.nim4
-rw-r--r--lib/pure/os.nim18
-rw-r--r--lib/pure/strutils.nim2
-rw-r--r--lib/pure/times.nim63
-rw-r--r--lib/pure/unittest.nim18
-rw-r--r--lib/system.nim26
-rw-r--r--tests/macros/tdumptree.nim2
-rw-r--r--todo.txt4
-rw-r--r--web/news/version_0_15_released.rst4
36 files changed, 169 insertions, 172 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 4c98219f9..8a3c76435 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -278,6 +278,8 @@ const
   sfImmediate* = sfDeadCodeElim
     # macro or template is immediately expanded
     # without considering any possible overloads
+  sfAllUntyped* = sfVolatile # macro or template is immediately expanded \
+    # in a generic context
 
   sfDirty* = sfPure
     # template is not hygienic (old styled template)
diff --git a/compiler/ccgmerge.nim b/compiler/ccgmerge.nim
index 2e77cd2a6..1b2104174 100644
--- a/compiler/ccgmerge.nim
+++ b/compiler/ccgmerge.nim
@@ -229,7 +229,7 @@ proc processMergeInfo(L: var TBaseLexer, m: BModule) =
 when not defined(nimhygiene):
   {.pragma: inject.}
 
-template withCFile(cfilename: string, body: stmt) {.immediate.} =
+template withCFile(cfilename: string, body: untyped) =
   var s = llStreamOpen(cfilename, fmRead)
   if s == nil: return
   var L {.inject.}: TBaseLexer
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 70d50b060..4836527a2 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -136,7 +136,7 @@ proc exprBlock(p: BProc, n: PNode, d: var TLoc) =
   expr(p, n, d)
   endBlock(p)
 
-template preserveBreakIdx(body: stmt): stmt {.immediate.} =
+template preserveBreakIdx(body: untyped): untyped =
   var oldBreakIdx = p.breakIdx
   body
   p.breakIdx = oldBreakIdx
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index eb9aac490..2dcfc0226 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -61,7 +61,7 @@ type
 # When adding new compilers, the cmake sources could be a good reference:
 # http://cmake.org/gitweb?p=cmake.git;a=tree;f=Modules/Platform;
 
-template compiler(name: expr, settings: stmt): stmt {.immediate.} =
+template compiler(name, settings: untyped): untyped =
   proc name: TInfoCC {.compileTime.} = settings
 
 # GNU C and C++ Compiler
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index a60b0cc5e..244bba681 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -95,7 +95,7 @@ type
     up: PProc     # up the call chain; required for closure support
     declaredGlobals: IntSet
 
-template `|`(a, b: expr): expr {.immediate, dirty.} =
+template `|`(a, b: untyped): untyped {.dirty.} =
   (if p.target == targetJS: a else: b)
 
 proc newGlobals(): PGlobals =
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 8b20b56db..2623dea9e 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -98,7 +98,7 @@ proc parMessage(p: TParser, msg: TMsgKind, tok: TToken) =
   ## Produce and emit a parser message to output about the token `tok`
   parMessage(p, msg, prettyTok(tok))
 
-template withInd(p: expr, body: stmt) {.immediate.} =
+template withInd(p, body: untyped) =
   let oldInd = p.currInd
   p.currInd = p.tok.indent
   body
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index d7d1ed838..50d5bb1b5 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -626,7 +626,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         processImportCompilerProc(sym, getOptionalStr(c, it, "$1"))
       of wExtern: setExternName(sym, expectStrLit(c, it))
       of wImmediate:
-        if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate)
+        if sym.kind in {skTemplate, skMacro}:
+          incl(sym.flags, sfImmediate)
+          incl(sym.flags, sfAllUntyped)
+          message(n.info, warnDeprecated, "use 'untyped' parameters instead; immediate")
         else: invalidPragma(it)
       of wDirty:
         if sym.kind == skTemplate: incl(sym.flags, sfDirty)
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index e9ee50d74..7c734e33b 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -143,7 +143,7 @@ proc getIntervalType*(m: TMagic, n: PNode): PType =
   const ordIntLit = {nkIntLit..nkUInt64Lit}
   result = n.typ
 
-  template commutativeOp(opr: expr) {.immediate.} =
+  template commutativeOp(opr: untyped) =
     let a = n.sons[1]
     let b = n.sons[2]
     if isIntRangeOrLit(a.typ) and isIntRangeOrLit(b.typ):
@@ -151,7 +151,7 @@ proc getIntervalType*(m: TMagic, n: PNode): PType =
                          opr(pickMinInt(a), pickMinInt(b)),
                          opr(pickMaxInt(a), pickMaxInt(b)))
 
-  template binaryOp(opr: expr) {.immediate.} =
+  template binaryOp(opr: untyped) =
     let a = n.sons[1]
     let b = n.sons[2]
     if isIntRange(a.typ) and b.kind in {nkIntLit..nkUInt64Lit}:
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index b78679411..0fd2e546e 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -48,7 +48,10 @@ proc semGenericStmtScope(c: PContext, n: PNode,
   closeScope(c)
 
 template macroToExpand(s: expr): expr =
-  s.kind in {skMacro, skTemplate} and (s.typ.len == 1 or sfImmediate in s.flags)
+  s.kind in {skMacro, skTemplate} and (s.typ.len == 1 or sfAllUntyped in s.flags)
+
+template macroToExpandSym(s: expr): expr =
+  s.kind in {skMacro, skTemplate} and (s.typ.len == 1)
 
 proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
                           ctx: var GenericCtx): PNode =
@@ -61,14 +64,14 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
   of skProc, skMethod, skIterator, skConverter, skModule:
     result = symChoice(c, n, s, scOpen)
   of skTemplate:
-    if macroToExpand(s):
+    if macroToExpandSym(s):
       styleCheckUse(n.info, s)
       result = semTemplateExpr(c, n, s, {efNoSemCheck})
       result = semGenericStmt(c, result, {}, ctx)
     else:
       result = symChoice(c, n, s, scOpen)
   of skMacro:
-    if macroToExpand(s):
+    if macroToExpandSym(s):
       styleCheckUse(n.info, s)
       result = semMacroExpr(c, n, n, s, {efNoSemCheck})
       result = semGenericStmt(c, result, {}, ctx)
diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim
index a4ec14250..21429a8d8 100644
--- a/compiler/semparallel.nim
+++ b/compiler/semparallel.nim
@@ -260,7 +260,7 @@ proc min(a, b: PNode): PNode =
 
 proc fromSystem(op: PSym): bool = sfSystemModule in getModule(op).flags
 
-template pushSpawnId(c: expr, body: stmt) {.immediate, dirty.} =
+template pushSpawnId(c, body) {.dirty.} =
   inc c.spawns
   let oldSpawnId = c.currentSpawnId
   c.currentSpawnId = c.spawns
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index a4498a3ae..3ee019674 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -577,13 +577,16 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
   else:
     gp = newNodeI(nkGenericParams, n.info)
   # process parameters:
+  var allUntyped = true
   if n.sons[paramsPos].kind != nkEmpty:
     semParamList(c, n.sons[paramsPos], gp, s)
     # a template's parameters are not gensym'ed even if that was originally the
     # case as we determine whether it's a template parameter in the template
     # body by the absence of the sfGenSym flag:
     for i in 1 .. s.typ.n.len-1:
-      s.typ.n.sons[i].sym.flags.excl sfGenSym
+      let param = s.typ.n.sons[i].sym
+      param.flags.excl sfGenSym
+      if param.typ.kind != tyExpr: allUntyped = false
     if sonsLen(gp) > 0:
       if n.sons[genericParamsPos].kind == nkEmpty:
         # we have a list of implicit type parameters:
@@ -599,6 +602,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
     s.typ.n = newNodeI(nkFormalParams, n.info)
     rawAddSon(s.typ, newTypeS(tyStmt, c))
     addSon(s.typ.n, newNodeIT(nkType, n.info, s.typ.sons[0]))
+  if allUntyped: incl(s.flags, sfAllUntyped)
   if n.sons[patternPos].kind != nkEmpty:
     n.sons[patternPos] = semPattern(c, n.sons[patternPos])
   var ctx: TemplCtx
@@ -629,7 +633,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
 
 proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
   template templToExpand(s: expr): expr =
-    s.kind == skTemplate and (s.typ.len == 1 or sfImmediate in s.flags)
+    s.kind == skTemplate and (s.typ.len == 1 or sfAllUntyped in s.flags)
 
   proc newParam(c: var TemplCtx, n: PNode, s: PSym): PNode =
     # the param added in the current scope is actually wrong here for
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 9a8f865a6..b8fd8bf1e 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -691,7 +691,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       put(c.bindings, f, bound)
     return res
 
-  template considerPreviousT(body: stmt) {.immediate.} =
+  template considerPreviousT(body: untyped) =
     var prev = PType(idTableGet(c.bindings, f))
     if prev == nil: body
     else: return typeRel(c, prev, a)
@@ -1591,7 +1591,7 @@ template isVarargsUntyped(x): expr =
 
 proc matchesAux(c: PContext, n, nOrig: PNode,
                 m: var TCandidate, marker: var IntSet) =
-  template checkConstraint(n: expr) {.immediate, dirty.} =
+  template checkConstraint(n: untyped) {.dirty.} =
     if not formal.constraint.isNil:
       if matchNodeKinds(formal.constraint, n):
         # better match over other routines with no such restriction:
@@ -1816,7 +1816,7 @@ proc instTypeBoundOp*(c: PContext; dc: PSym; t: PType; info: TLineInfo;
 include suggest
 
 when not declared(tests):
-  template tests(s: stmt) {.immediate.} = discard
+  template tests(s: untyped) = discard
 
 tests:
   var dummyOwner = newSym(skModule, getIdent("test_module"), nil, UnknownLineInfo())
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index f35ff2142..c127b968c 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -138,7 +138,7 @@ proc suggestField(c: PContext, s: PSym, outputs: var int) =
     suggestResult(symToSuggest(s, isLocal=true, $ideSug, 100))
     inc outputs
 
-template wholeSymTab(cond, section: expr) {.immediate.} =
+template wholeSymTab(cond, section: untyped) =
   var isLocal = true
   for scope in walkScopes(c.currentScope):
     if scope == c.topLevelScope: isLocal = false
diff --git a/compiler/types.nim b/compiler/types.nim
index 5fbab85b9..42ca0f9fc 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -806,7 +806,7 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
     elif a.n != b.n and (a.n == nil or b.n == nil) and IgnoreTupleFields notin c.flags:
       result = false
 
-template ifFastObjectTypeCheckFailed(a, b: PType, body: stmt) {.immediate.} =
+template ifFastObjectTypeCheckFailed(a, b: PType, body: untyped) =
   if tfFromGeneric notin a.flags + b.flags:
     # fast case: id comparison suffices:
     result = a.id == b.id
diff --git a/compiler/vm.nim b/compiler/vm.nim
index f275b7b9b..ac4ea6ad9 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -92,34 +92,34 @@ when not defined(nimComputedGoto):
 
 proc myreset(n: var TFullReg) = reset(n)
 
-template ensureKind(k: expr) {.immediate, dirty.} =
+template ensureKind(k: untyped) {.dirty.} =
   if regs[ra].kind != k:
     myreset(regs[ra])
     regs[ra].kind = k
 
-template decodeB(k: expr) {.immediate, dirty.} =
+template decodeB(k: untyped) {.dirty.} =
   let rb = instr.regB
   ensureKind(k)
 
-template decodeBC(k: expr) {.immediate, dirty.} =
+template decodeBC(k: untyped) {.dirty.} =
   let rb = instr.regB
   let rc = instr.regC
   ensureKind(k)
 
-template declBC() {.immediate, dirty.} =
+template declBC() {.dirty.} =
   let rb = instr.regB
   let rc = instr.regC
 
-template decodeBImm(k: expr) {.immediate, dirty.} =
+template decodeBImm(k: untyped) {.dirty.} =
   let rb = instr.regB
   let imm = instr.regC - byteExcess
   ensureKind(k)
 
-template decodeBx(k: expr) {.immediate, dirty.} =
+template decodeBx(k: expr) {.dirty.} =
   let rbx = instr.regBx - wordExcess
   ensureKind(k)
 
-template move(a, b: expr) {.immediate, dirty.} = system.shallowCopy(a, b)
+template move(a, b: untyped) {.dirty.} = system.shallowCopy(a, b)
 # XXX fix minor 'shallowCopy' overloading bug in compiler
 
 proc createStrKeepNode(x: var TFullReg; keepNode=true) =
@@ -1573,7 +1573,7 @@ proc setupMacroParam(x: PNode, typ: PType): TFullReg =
 var evalMacroCounter: int
 
 proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
-  # XXX GlobalError() is ugly here, but I don't know a better solution for now
+  # XXX globalError() is ugly here, but I don't know a better solution for now
   inc(evalMacroCounter)
   if evalMacroCounter > 100:
     globalError(n.info, errTemplateInstantiationTooNested)
@@ -1603,7 +1603,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
 
   # return value:
   tos.slots[0].kind = rkNode
-  tos.slots[0].node = newNodeIT(nkEmpty, n.info, sym.typ.sons[0])
+  tos.slots[0].node = newNodeI(nkEmpty, n.info)
 
   # setup parameters:
   for i in 1.. <sym.typ.len:
@@ -1623,4 +1623,3 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
   if cyclicTree(result): globalError(n.info, errCyclicTree)
   dec(evalMacroCounter)
   c.callsite = nil
-  #debug result
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index 337e4ec8f..83c1dbf43 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -230,10 +230,10 @@ const
   slotSomeTemp* = slotTempUnknown
   relativeJumps* = {opcTJmp, opcFJmp, opcJmp, opcJmpBack}
 
-template opcode*(x: TInstr): TOpcode {.immediate.} = TOpcode(x.uint32 and 0xff'u32)
-template regA*(x: TInstr): TRegister {.immediate.} = TRegister(x.uint32 shr 8'u32 and 0xff'u32)
-template regB*(x: TInstr): TRegister {.immediate.} = TRegister(x.uint32 shr 16'u32 and 0xff'u32)
-template regC*(x: TInstr): TRegister {.immediate.} = TRegister(x.uint32 shr 24'u32)
-template regBx*(x: TInstr): int {.immediate.} = (x.uint32 shr 16'u32).int
+template opcode*(x: TInstr): TOpcode = TOpcode(x.uint32 and 0xff'u32)
+template regA*(x: TInstr): TRegister = TRegister(x.uint32 shr 8'u32 and 0xff'u32)
+template regB*(x: TInstr): TRegister = TRegister(x.uint32 shr 16'u32 and 0xff'u32)
+template regC*(x: TInstr): TRegister = TRegister(x.uint32 shr 24'u32)
+template regBx*(x: TInstr): int = (x.uint32 shr 16'u32).int
 
-template jmpDiff*(x: TInstr): int {.immediate.} = regBx(x) - wordExcess
+template jmpDiff*(x: TInstr): int = regBx(x) - wordExcess
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 1c1d03a4f..8991c238f 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -231,7 +231,7 @@ proc getTempRange(cc: PCtx; n: int; kind: TSlotKind): TRegister =
 proc freeTempRange(c: PCtx; start: TRegister, n: int) =
   for i in start .. start+n-1: c.freeTemp(TRegister(i))
 
-template withTemp(tmp, typ: expr, body: stmt) {.immediate, dirty.} =
+template withTemp(tmp, typ, body: untyped) {.dirty.} =
   var tmp = getTemp(c, typ)
   body
   c.freeTemp(tmp)
@@ -241,7 +241,7 @@ proc popBlock(c: PCtx; oldLen: int) =
     c.patch(f)
   c.prc.blocks.setLen(oldLen)
 
-template withBlock(labl: PSym; body: stmt) {.immediate, dirty.} =
+template withBlock(labl: PSym; body: untyped) {.dirty.} =
   var oldLen {.gensym.} = c.prc.blocks.len
   c.prc.blocks.add TBlock(label: labl, fixups: @[])
   body
diff --git a/compiler/vmhooks.nim b/compiler/vmhooks.nim
index 3456e893b..548a3af97 100644
--- a/compiler/vmhooks.nim
+++ b/compiler/vmhooks.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-template setX(k, field) {.immediate, dirty.} =
+template setX(k, field) {.dirty.} =
   var s: seq[TFullReg]
   move(s, cast[seq[TFullReg]](a.slots))
   if s[a.ra].kind != k:
@@ -48,7 +48,7 @@ proc setResult*(a: VmArgs; v: seq[string]) =
   for x in v: n.add newStrNode(nkStrLit, x)
   s[a.ra].node = n
 
-template getX(k, field) {.immediate, dirty.} =
+template getX(k, field) {.dirty.} =
   doAssert i < a.rc-1
   let s = cast[seq[TFullReg]](a.slots)
   doAssert s[i+a.rb+1].kind == k
diff --git a/compiler/vmops.nim b/compiler/vmops.nim
index d0b3119e2..1c2725a98 100644
--- a/compiler/vmops.nim
+++ b/compiler/vmops.nim
@@ -15,36 +15,36 @@ from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
 
 from os import getEnv, existsEnv, dirExists, fileExists, walkDir
 
-template mathop(op) {.immediate, dirty.} =
+template mathop(op) {.dirty.} =
   registerCallback(c, "stdlib.math." & astToStr(op), `op Wrapper`)
 
-template osop(op) {.immediate, dirty.} =
+template osop(op) {.dirty.} =
   registerCallback(c, "stdlib.os." & astToStr(op), `op Wrapper`)
 
-template systemop(op) {.immediate, dirty.} =
+template systemop(op) {.dirty.} =
   registerCallback(c, "stdlib.system." & astToStr(op), `op Wrapper`)
 
-template wrap1f_math(op) {.immediate, dirty.} =
+template wrap1f_math(op) {.dirty.} =
   proc `op Wrapper`(a: VmArgs) {.nimcall.} =
     setResult(a, op(getFloat(a, 0)))
   mathop op
 
-template wrap2f_math(op) {.immediate, dirty.} =
+template wrap2f_math(op) {.dirty.} =
   proc `op Wrapper`(a: VmArgs) {.nimcall.} =
     setResult(a, op(getFloat(a, 0), getFloat(a, 1)))
   mathop op
 
-template wrap1s_os(op) {.immediate, dirty.} =
+template wrap1s_os(op) {.dirty.} =
   proc `op Wrapper`(a: VmArgs) {.nimcall.} =
     setResult(a, op(getString(a, 0)))
   osop op
 
-template wrap1s_system(op) {.immediate, dirty.} =
+template wrap1s_system(op) {.dirty.} =
   proc `op Wrapper`(a: VmArgs) {.nimcall.} =
     setResult(a, op(getString(a, 0)))
   systemop op
 
-template wrap2svoid_system(op) {.immediate, dirty.} =
+template wrap2svoid_system(op) {.dirty.} =
   proc `op Wrapper`(a: VmArgs) {.nimcall.} =
     op(getString(a, 0), getString(a, 1))
   systemop op
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 9623bec28..4296cb0ae 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -508,7 +508,7 @@ proc lispRepr*(n: NimNode): string {.compileTime, benign.} =
 
   add(result, ")")
 
-macro dumpTree*(s: stmt): stmt {.immediate.} = echo s.treeRepr
+macro dumpTree*(s: untyped): untyped = echo s.treeRepr
   ## Accepts a block of nim code and prints the parsed abstract syntax
   ## tree using the `toTree` function. Printing is done *at compile time*.
   ##
@@ -516,17 +516,17 @@ macro dumpTree*(s: stmt): stmt {.immediate.} = echo s.treeRepr
   ## tree and to discover what kind of nodes must be created to represent
   ## a certain expression/statement.
 
-macro dumpLisp*(s: stmt): stmt {.immediate.} = echo s.lispRepr
+macro dumpLisp*(s: untyped): untyped = echo s.lispRepr
   ## Accepts a block of nim code and prints the parsed abstract syntax
   ## tree using the `toLisp` function. Printing is done *at compile time*.
   ##
   ## See `dumpTree`.
 
-macro dumpTreeImm*(s: stmt): stmt {.immediate, deprecated.} = echo s.treeRepr
-  ## The ``immediate`` version of `dumpTree`.
+macro dumpTreeImm*(s: untyped): untyped {.deprecated.} = echo s.treeRepr
+  ## Deprecated.
 
-macro dumpLispImm*(s: stmt): stmt {.immediate, deprecated.} = echo s.lispRepr
-  ## The ``immediate`` version of `dumpLisp`.
+macro dumpLispImm*(s: untyped): untyped {.deprecated.} = echo s.lispRepr
+  ## Deprecated.
 
 
 proc newEmptyNode*(): NimNode {.compileTime, noSideEffect.} =
@@ -701,7 +701,7 @@ proc addPragma*(someProc, pragma: NimNode) {.compileTime.} =
     someProc.pragma = pragmaNode
   pragmaNode.add(pragma)
 
-template badNodeKind(k; f): stmt{.immediate.} =
+template badNodeKind(k, f) =
   assert false, "Invalid node kind " & $k & " for macros.`" & $f & "`"
 
 proc body*(someProc: NimNode): NimNode {.compileTime.} =
@@ -758,8 +758,7 @@ iterator children*(n: NimNode): NimNode {.inline.} =
   for i in 0 ..< n.len:
     yield n[i]
 
-template findChild*(n: NimNode; cond: expr): NimNode {.
-  immediate, dirty.} =
+template findChild*(n: NimNode; cond: untyped): NimNode {.dirty.} =
   ## Find the first child node matching condition (or nil).
   ##
   ## .. code-block:: nim
diff --git a/lib/impure/nre.nim b/lib/impure/nre.nim
index 76a0f3db6..557bb0549 100644
--- a/lib/impure/nre.nim
+++ b/lib/impure/nre.nim
@@ -274,7 +274,7 @@ proc `[]`*(pattern: Captures, name: string): string =
   let pattern = RegexMatch(pattern)
   return pattern.captures[pattern.pattern.captureNameToId.fget(name)]
 
-template toTableImpl(cond: bool): stmt {.immediate, dirty.} =
+template toTableImpl(cond: untyped) {.dirty.} =
   for key in RegexMatch(pattern).pattern.captureNameId.keys:
     let nextVal = pattern[key]
     if cond:
@@ -291,7 +291,7 @@ proc toTable*(pattern: CaptureBounds, default = none(Slice[int])):
   result = initTable[string, Option[Slice[int]]]()
   toTableImpl(nextVal.isNone)
 
-template itemsImpl(cond: bool): stmt {.immediate, dirty.} =
+template itemsImpl(cond: untyped) {.dirty.} =
   for i in 0 .. <RegexMatch(pattern).pattern.captureCount:
     let nextVal = pattern[i]
     # done in this roundabout way to avoid multiple yields (potential code
@@ -625,7 +625,7 @@ proc split*(str: string, pattern: Regex, maxSplit = -1, start = 0): seq[string]
     result.add(str.substr(bounds.b + 1, str.high))
 
 template replaceImpl(str: string, pattern: Regex,
-                     replacement: expr): stmt {.immediate, dirty.} =
+                     replacement: untyped) {.dirty.} =
   # XXX seems very similar to split, maybe I can reduce code duplication
   # somehow?
   result = ""
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index 92a737a47..79bc1b96d 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -983,7 +983,7 @@ when defined(windows) or defined(nimdoc):
     let dwLocalAddressLength = Dword(sizeof (Sockaddr_in) + 16)
     let dwRemoteAddressLength = Dword(sizeof(Sockaddr_in) + 16)
 
-    template completeAccept(): stmt {.immediate, dirty.} =
+    template completeAccept() {.dirty.} =
       var listenSock = socket
       let setoptRet = setsockopt(clientSock, SOL_SOCKET,
           SO_UPDATE_ACCEPT_CONTEXT, addr listenSock,
@@ -1003,7 +1003,7 @@ when defined(windows) or defined(nimdoc):
          client: clientSock.AsyncFD)
       )
 
-    template failAccept(errcode): stmt =
+    template failAccept(errcode) =
       if flags.isDisconnectionError(errcode):
         var newAcceptFut = acceptAddr(socket, flags)
         newAcceptFut.callback =
@@ -1590,7 +1590,7 @@ proc skipStmtList(node: NimNode): NimNode {.compileTime.} =
     result = node[0]
 
 template createCb(retFutureSym, iteratorNameSym,
-                   name: expr): stmt {.immediate.} =
+                   name: untyped) =
   var nameIterVar = iteratorNameSym
   #{.push stackTrace: off.}
   proc cb {.closure,gcsafe.} =
@@ -1925,7 +1925,7 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
   #if prc[0].getName == "testInfix":
   #  echo(toStrLit(result))
 
-macro async*(prc: stmt): stmt {.immediate.} =
+macro async*(prc: untyped): untyped =
   ## Macro which processes async procedures into the appropriate
   ## iterators and yield statements.
   if prc.kind == nnkStmtList:
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index 0817b38a3..ef8409443 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -355,7 +355,7 @@ proc insert*[T](dest: var seq[T], src: openArray[T], pos=0) =
     inc(j)
 
 
-template filterIt*(seq1, pred: expr): expr =
+template filterIt*(seq1, pred: untyped): untyped =
   ## Returns a new sequence with all the items that fulfilled the predicate.
   ##
   ## Unlike the `proc` version, the predicate needs to be an expression using
@@ -374,7 +374,7 @@ template filterIt*(seq1, pred: expr): expr =
     if pred: result.add(it)
   result
 
-template keepItIf*(varSeq: seq, pred: expr) =
+template keepItIf*(varSeq: seq, pred: untyped) =
   ## Convenience template around the ``keepIf`` proc to reduce typing.
   ##
   ## Unlike the `proc` version, the predicate needs to be an expression using
@@ -409,7 +409,7 @@ proc all*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): bool =
       return false
   return true
 
-template allIt*(seq1, pred: expr): bool {.immediate.} =
+template allIt*(seq1, pred: untyped): bool =
   ## Checks if every item fulfills the predicate.
   ##
   ## Example:
@@ -440,7 +440,7 @@ proc any*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): bool =
       return true
   return false
 
-template anyIt*(seq1, pred: expr): bool {.immediate.} =
+template anyIt*(seq1, pred: untyped): bool =
   ## Checks if some item fulfills the predicate.
   ##
   ## Example:
@@ -456,7 +456,7 @@ template anyIt*(seq1, pred: expr): bool {.immediate.} =
       break
   result
 
-template toSeq*(iter: expr): expr {.immediate.} =
+template toSeq*(iter: untyped): untyped =
   ## Transforms any iterator into a sequence.
   ##
   ## Example:
@@ -482,7 +482,7 @@ template toSeq*(iter: expr): expr {.immediate.} =
       result.add(x)
     result
 
-template foldl*(sequence, operation: expr): expr =
+template foldl*(sequence, operation: untyped): untyped =
   ## Template to fold a sequence from left to right, returning the accumulation.
   ##
   ## The sequence is required to have at least a single element. Debug versions
@@ -519,7 +519,7 @@ template foldl*(sequence, operation: expr): expr =
     result = operation
   result
 
-template foldl*(sequence, operation: expr, first): expr =
+template foldl*(sequence, operation, first): untyped =
   ## Template to fold a sequence from left to right, returning the accumulation.
   ##
   ## This version of ``foldl`` gets a starting parameter. This makes it possible
@@ -544,7 +544,7 @@ template foldl*(sequence, operation: expr, first): expr =
     result = operation
   result
 
-template foldr*(sequence, operation: expr): expr =
+template foldr*(sequence, operation: untyped): untyped =
   ## Template to fold a sequence from right to left, returning the accumulation.
   ##
   ## The sequence is required to have at least a single element. Debug versions
@@ -581,7 +581,7 @@ template foldr*(sequence, operation: expr): expr =
     result = operation
   result
 
-template mapIt*(seq1, typ, op: expr): expr {.deprecated.}=
+template mapIt*(seq1, typ, op: untyped): untyped =
   ## Convenience template around the ``map`` proc to reduce typing.
   ##
   ## The template injects the ``it`` variable which you can use directly in an
@@ -602,7 +602,7 @@ template mapIt*(seq1, typ, op: expr): expr {.deprecated.}=
   result
 
 
-template mapIt*(seq1, op: expr): expr =
+template mapIt*(seq1, op: untyped): untyped =
   ## Convenience template around the ``map`` proc to reduce typing.
   ##
   ## The template injects the ``it`` variable which you can use directly in an
@@ -631,7 +631,7 @@ template mapIt*(seq1, op: expr): expr =
       result.add(op)
   result
 
-template applyIt*(varSeq, op: expr) =
+template applyIt*(varSeq, op: untyped) =
   ## Convenience template around the mutable ``apply`` proc to reduce typing.
   ##
   ## The template injects the ``it`` variable which you can use directly in an
@@ -648,7 +648,7 @@ template applyIt*(varSeq, op: expr) =
 
 
 
-template newSeqWith*(len: int, init: expr): expr =
+template newSeqWith*(len: int, init: untyped): untyped =
   ## creates a new sequence, calling `init` to initialize each value. Example:
   ##
   ## .. code-block::
diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim
index 20e06aaae..da32c1950 100644
--- a/lib/pure/collections/sets.nim
+++ b/lib/pure/collections/sets.nim
@@ -286,7 +286,7 @@ proc excl*[A](s: var HashSet[A], key: A) =
       var r = j         # though may be adaptable to other simple sequences.
       s.data[i].hcode = 0              # mark current EMPTY
       s.data[i].key = default(type(s.data[i].key))
-      doWhile ((i >= r and r > j) or (r > j and j > i) or (j > i and i >= r)):
+      doWhile((i >= r and r > j) or (r > j and j > i) or (j > i and i >= r)):
         i = (i + 1) and msk            # increment mod table size
         if isEmpty(s.data[i].hcode):   # end of collision cluster; So all done
           return
@@ -615,7 +615,7 @@ proc card*[A](s: OrderedSet[A]): int {.inline.} =
   ## <http://en.wikipedia.org/wiki/Cardinality>`_ of a set.
   result = s.counter
 
-template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} =
+template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} =
   var h = s.first
   while h >= 0:
     var nxt = s.data[h].next
diff --git a/lib/pure/collections/tableimpl.nim b/lib/pure/collections/tableimpl.nim
index 1bbf19ee9..f4a135e01 100644
--- a/lib/pure/collections/tableimpl.nim
+++ b/lib/pure/collections/tableimpl.nim
@@ -72,14 +72,14 @@ proc rawInsert[X, A, B](t: var X, data: var KeyValuePairSeq[A, B],
                      key: A, val: B, hc: Hash, h: Hash) =
   rawInsertImpl()
 
-template addImpl(enlarge) {.dirty, immediate.} =
+template addImpl(enlarge) {.dirty.} =
   if mustRehash(t.dataLen, t.counter): enlarge(t)
   var hc: Hash
   var j = rawGetDeep(t, key, hc)
   rawInsert(t, t.data, key, val, hc, j)
   inc(t.counter)
 
-template maybeRehashPutImpl(enlarge) {.dirty, immediate.} =
+template maybeRehashPutImpl(enlarge) {.dirty.} =
   if mustRehash(t.dataLen, t.counter):
     enlarge(t)
     index = rawGetKnownHC(t, key, hc)
@@ -87,13 +87,13 @@ template maybeRehashPutImpl(enlarge) {.dirty, immediate.} =
   rawInsert(t, t.data, key, val, hc, index)
   inc(t.counter)
 
-template putImpl(enlarge) {.dirty, immediate.} =
+template putImpl(enlarge) {.dirty.} =
   var hc: Hash
   var index = rawGet(t, key, hc)
   if index >= 0: t.data[index].val = val
   else: maybeRehashPutImpl(enlarge)
 
-template mgetOrPutImpl(enlarge) {.dirty, immediate.} =
+template mgetOrPutImpl(enlarge) {.dirty.} =
   var hc: Hash
   var index = rawGet(t, key, hc)
   if index < 0:
@@ -102,7 +102,7 @@ template mgetOrPutImpl(enlarge) {.dirty, immediate.} =
   # either way return modifiable val
   result = t.data[index].val
 
-template hasKeyOrPutImpl(enlarge) {.dirty, immediate.} =
+template hasKeyOrPutImpl(enlarge) {.dirty.} =
   var hc: Hash
   var index = rawGet(t, key, hc)
   if index < 0:
@@ -112,7 +112,7 @@ template hasKeyOrPutImpl(enlarge) {.dirty, immediate.} =
 
 proc default[T](t: typedesc[T]): T {.inline.} = discard
 
-template delImpl() {.dirty, immediate.} =
+template delImpl() {.dirty.} =
   var hc: Hash
   var i = rawGet(t, key, hc)
   let msk = maxHash(t)
@@ -140,7 +140,7 @@ template delImpl() {.dirty, immediate.} =
         else:
           shallowCopy(t.data[j], t.data[i]) # data[j] will be marked EMPTY next loop
 
-template clearImpl() {.dirty, immediate.} =
+template clearImpl() {.dirty.} =
   for i in 0 .. <t.data.len:
     t.data[i].hcode = 0
     t.data[i].key = default(type(t.data[i].key))
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim
index 8d56669da..9e7e2e0e5 100644
--- a/lib/pure/collections/tables.nim
+++ b/lib/pure/collections/tables.nim
@@ -113,8 +113,8 @@ type
 
 {.deprecated: [TTable: Table, PTable: TableRef].}
 
-template maxHash(t): expr {.immediate.} = high(t.data)
-template dataLen(t): expr = len(t.data)
+template maxHash(t): untyped = high(t.data)
+template dataLen(t): untyped = len(t.data)
 
 include tableimpl
 
@@ -135,7 +135,7 @@ proc len*[A, B](t: Table[A, B]): int =
   ## returns the number of keys in `t`.
   result = t.counter
 
-template get(t, key): untyped {.immediate.} =
+template get(t, key): untyped =
   ## retrieves the value at ``t[key]``. The value can be modified.
   ## If `key` is not in `t`, the ``KeyError`` exception is raised.
   mixin rawGet
@@ -148,7 +148,7 @@ template get(t, key): untyped {.immediate.} =
     else:
       raise newException(KeyError, "key not found")
 
-template getOrDefaultImpl(t, key): untyped {.immediate.} =
+template getOrDefaultImpl(t, key): untyped =
   mixin rawGet
   var hc: Hash
   var index = rawGet(t, key, hc)
@@ -311,7 +311,7 @@ proc toTable*[A, B](pairs: openArray[(A,
   result = initTable[A, B](rightSize(pairs.len))
   for key, val in items(pairs): result[key] = val
 
-template dollarImpl(): stmt {.dirty.} =
+template dollarImpl(): untyped {.dirty.} =
   if t.len == 0:
     result = "{:}"
   else:
@@ -463,7 +463,7 @@ proc clear*[A, B](t: OrderedTable[A, B] | OrderedTableRef[A, B]) =
   t.first = -1
   t.last = -1
 
-template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} =
+template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} =
   var h = t.first
   while h >= 0:
     var nxt = t.data[h].next
@@ -649,7 +649,7 @@ proc len*[A, B](t: OrderedTableRef[A, B]): int {.inline.} =
   ## returns the number of keys in `t`.
   result = t.counter
 
-template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} =
+template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} =
   var h = t.first
   while h >= 0:
     var nxt = t.data[h].next
@@ -824,7 +824,7 @@ proc rawGet[A](t: CountTable[A], key: A): int =
     h = nextTry(h, high(t.data))
   result = -1 - h                   # < 0 => MISSING; insert idx = -1 - result
 
-template ctget(t, key: untyped): untyped {.immediate.} =
+template ctget(t, key: untyped): untyped =
   var index = rawGet(t, key)
   if index >= 0: result = t.data[index].val
   else:
diff --git a/lib/pure/future.nim b/lib/pure/future.nim
index 4e2c1d893..67975cfcb 100644
--- a/lib/pure/future.nim
+++ b/lib/pure/future.nim
@@ -46,7 +46,7 @@ proc createProcType(p, b: NimNode): NimNode {.compileTime.} =
   #echo(treeRepr(result))
   #echo(result.toStrLit())
 
-macro `=>`*(p, b: expr): expr {.immediate.} =
+macro `=>`*(p, b: untyped): untyped =
   ## Syntax sugar for anonymous procedures.
   ##
   ## .. code-block:: nim
@@ -107,7 +107,7 @@ macro `=>`*(p, b: expr): expr {.immediate.} =
   #echo(result.toStrLit())
   #return result # TODO: Bug?
 
-macro `->`*(p, b: expr): expr {.immediate.} =
+macro `->`*(p, b: untyped): untyped =
   ## Syntax sugar for procedure types.
   ##
   ## .. code-block:: nim
@@ -125,7 +125,7 @@ macro `->`*(p, b: expr): expr {.immediate.} =
 type ListComprehension = object
 var lc*: ListComprehension
 
-macro `[]`*(lc: ListComprehension, comp, typ: expr): expr =
+macro `[]`*(lc: ListComprehension, comp, typ: untyped): untyped =
   ## List comprehension, returns a sequence. `comp` is the actual list
   ## comprehension, for example ``x | (x <- 1..10, x mod 2 == 0)``. `typ` is
   ## the type that will be stored inside the result seq.
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index 7898883cf..9501f6dc7 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -1000,11 +1000,11 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1,
   ##
   ## **Warning**: Only the ``SafeDisconn`` flag is currently supported.
 
-  template addNLIfEmpty(): stmt =
+  template addNLIfEmpty() =
     if line.len == 0:
       line.string.add("\c\L")
 
-  template raiseSockError(): stmt {.dirty, immediate.} =
+  template raiseSockError() {.dirty.} =
     let lastError = getSocketError(socket)
     if flags.isDisconnectionError(lastError): setLen(line.string, 0); return
     socket.socketError(n, lastError = lastError)
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 9eb4cf57d..65bbab3d4 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -173,24 +173,24 @@ proc osLastError*(): OSErrorCode =
 
 when defined(windows):
   when useWinUnicode:
-    template wrapUnary(varname, winApiProc, arg: expr) {.immediate.} =
+    template wrapUnary(varname, winApiProc, arg: untyped) =
       var varname = winApiProc(newWideCString(arg))
 
-    template wrapBinary(varname, winApiProc, arg, arg2: expr) {.immediate.} =
+    template wrapBinary(varname, winApiProc, arg, arg2: untyped) =
       var varname = winApiProc(newWideCString(arg), arg2)
     proc findFirstFile(a: string, b: var WIN32_FIND_DATA): Handle =
       result = findFirstFileW(newWideCString(a), b)
-    template findNextFile(a, b: expr): expr = findNextFileW(a, b)
-    template getCommandLine(): expr = getCommandLineW()
+    template findNextFile(a, b: untyped): untyped = findNextFileW(a, b)
+    template getCommandLine(): untyped = getCommandLineW()
 
-    template getFilename(f: expr): expr =
+    template getFilename(f: untyped): untyped =
       $cast[WideCString](addr(f.cFilename[0]))
   else:
-    template findFirstFile(a, b: expr): expr = findFirstFileA(a, b)
-    template findNextFile(a, b: expr): expr = findNextFileA(a, b)
-    template getCommandLine(): expr = getCommandLineA()
+    template findFirstFile(a, b: untyped): untyped = findFirstFileA(a, b)
+    template findNextFile(a, b: untyped): untyped = findNextFileA(a, b)
+    template getCommandLine(): untyped = getCommandLineA()
 
-    template getFilename(f: expr): expr = $f.cFilename
+    template getFilename(f: untyped): untyped = $f.cFilename
 
   proc skipFindData(f: WIN32_FIND_DATA): bool {.inline.} =
     # Note - takes advantage of null delimiter in the cstring
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 9b6cf45c5..bfc32bc71 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -475,7 +475,7 @@ proc isNilOrWhitespace*(s: string): bool {.noSideEffect, procvar, rtl, extern: "
 
   result = true
   for c in s:
-    if not c.isSpace():
+    if not c.isSpaceAscii():
       return false
 
 proc substrEq(s: string, pos: int, substr: string): bool =
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index d6cb5c9da..d6eb29e1c 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -998,21 +998,14 @@ proc parseToken(info: var TimeInfo; token, value: string; j: var int) =
     info.monthday = value[j..j+1].parseInt()
     j += 2
   of "ddd":
-    case value[j..j+2].toLower()
-    of "sun":
-      info.weekday = dSun
-    of "mon":
-      info.weekday = dMon
-    of "tue":
-      info.weekday = dTue
-    of "wed":
-      info.weekday = dWed
-    of "thu":
-      info.weekday = dThu
-    of "fri":
-      info.weekday = dFri
-    of "sat":
-      info.weekday = dSat
+    case value[j..j+2].toLowerAscii()
+    of "sun": info.weekday = dSun
+    of "mon": info.weekday = dMon
+    of "tue": info.weekday = dTue
+    of "wed": info.weekday = dWed
+    of "thu": info.weekday = dThu
+    of "fri": info.weekday = dFri
+    of "sat": info.weekday = dSat
     else:
       raise newException(ValueError,
         "Couldn't parse day of week (ddd), got: " & value[j..j+2])
@@ -1066,31 +1059,19 @@ proc parseToken(info: var TimeInfo; token, value: string; j: var int) =
     j += 2
     info.month = Month(month-1)
   of "MMM":
-    case value[j..j+2].toLower():
-    of "jan":
-      info.month =  mJan
-    of "feb":
-      info.month =  mFeb
-    of "mar":
-      info.month =  mMar
-    of "apr":
-      info.month =  mApr
-    of "may":
-      info.month =  mMay
-    of "jun":
-      info.month =  mJun
-    of "jul":
-      info.month =  mJul
-    of "aug":
-      info.month =  mAug
-    of "sep":
-      info.month =  mSep
-    of "oct":
-      info.month =  mOct
-    of "nov":
-      info.month =  mNov
-    of "dec":
-      info.month =  mDec
+    case value[j..j+2].toLowerAscii():
+    of "jan": info.month =  mJan
+    of "feb": info.month =  mFeb
+    of "mar": info.month =  mMar
+    of "apr": info.month =  mApr
+    of "may": info.month =  mMay
+    of "jun": info.month =  mJun
+    of "jul": info.month =  mJul
+    of "aug": info.month =  mAug
+    of "sep": info.month =  mSep
+    of "oct": info.month =  mOct
+    of "nov": info.month =  mNov
+    of "dec": info.month =  mDec
     else:
       raise newException(ValueError,
         "Couldn't parse month (MMM), got: " & value)
@@ -1187,7 +1168,7 @@ proc parseToken(info: var TimeInfo; token, value: string; j: var int) =
         "Couldn't parse timezone offset (zzz), got: " & value[j])
     j += 6
   of "ZZZ":
-    info.tzname = value[j..j+2].toUpper()
+    info.tzname = value[j..j+2].toUpperAscii()
     j += 3
   else:
     # Ignore the token and move forward in the value string by the same length
diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim
index 7e3983a0d..92ddc3e75 100644
--- a/lib/pure/unittest.nim
+++ b/lib/pure/unittest.nim
@@ -77,7 +77,7 @@ checkpoints = @[]
 proc shouldRun(testName: string): bool =
   result = true
 
-template suite*(name: expr, body: stmt): stmt {.immediate, dirty.} =
+template suite*(name, body) {.dirty.} =
   ## Declare a test suite identified by `name` with optional ``setup``
   ## and/or ``teardown`` section.
   ##
@@ -106,13 +106,13 @@ template suite*(name: expr, body: stmt): stmt {.immediate, dirty.} =
   ##  [OK] 2 + 2 = 4
   ##  [OK] (2 + -2) != 4
   block:
-    template setup(setupBody: stmt): stmt {.immediate, dirty.} =
+    template setup(setupBody: untyped) {.dirty.} =
       var testSetupIMPLFlag = true
-      template testSetupIMPL: stmt {.immediate, dirty.} = setupBody
+      template testSetupIMPL: untyped {.dirty.} = setupBody
 
-    template teardown(teardownBody: stmt): stmt {.immediate, dirty.} =
+    template teardown(teardownBody: untyped) {.dirty.} =
       var testTeardownIMPLFlag = true
-      template testTeardownIMPL: stmt {.immediate, dirty.} = teardownBody
+      template testTeardownIMPL: untyped {.dirty.} = teardownBody
 
     body
 
@@ -135,7 +135,7 @@ proc testDone(name: string, s: TestStatus) =
     else:
       rawPrint()
 
-template test*(name: expr, body: stmt): stmt {.immediate, dirty.} =
+template test*(name, body) {.dirty.} =
   ## Define a single test case identified by `name`.
   ##
   ## .. code-block:: nim
@@ -226,7 +226,7 @@ template skip* =
   testStatusIMPL = SKIPPED
   checkpoints = @[]
 
-macro check*(conditions: stmt): stmt {.immediate.} =
+macro check*(conditions: untyped): untyped =
   ## Verify if a statement or a list of statements is true.
   ## A helpful error message and set checkpoints are printed out on
   ## failure (if ``outputLevel`` is not ``PRINT_NONE``).
@@ -318,7 +318,7 @@ macro check*(conditions: stmt): stmt {.immediate.} =
 
     result = getAst(rewrite(checked, checked.lineinfo, checked.toStrLit))
 
-template require*(conditions: stmt): stmt {.immediate.} =
+template require*(conditions: untyped) =
   ## Same as `check` except any failed test causes the program to quit
   ## immediately. Any teardown statements are not executed and the failed
   ## test output is not generated.
@@ -328,7 +328,7 @@ template require*(conditions: stmt): stmt {.immediate.} =
     check conditions
   abortOnError = savedAbortOnError
 
-macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} =
+macro expect*(exceptions: varargs[typed], body: untyped): untyped =
   ## Test if `body` raises an exception found in the passed `exceptions`.
   ## The test passes if the raised exception is part of the acceptable
   ## exceptions. Otherwise, it fails.
diff --git a/lib/system.nim b/lib/system.nim
index b4919db2d..2b19b5633 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -338,15 +338,15 @@ proc `<` *[T](x, y: ref T): bool {.magic: "LtPtr", noSideEffect.}
 proc `<` *[T](x, y: ptr T): bool {.magic: "LtPtr", noSideEffect.}
 proc `<` *(x, y: pointer): bool {.magic: "LtPtr", noSideEffect.}
 
-template `!=` * (x, y: expr): expr {.immediate.} =
+template `!=` * (x, y: untyped): untyped =
   ## unequals operator. This is a shorthand for ``not (x == y)``.
   not (x == y)
 
-template `>=` * (x, y: expr): expr {.immediate.} =
+template `>=` * (x, y: untyped): untyped =
   ## "is greater or equals" operator. This is the same as ``y <= x``.
   y <= x
 
-template `>` * (x, y: expr): expr {.immediate.} =
+template `>` * (x, y: untyped): untyped =
   ## "is greater" operator. This is the same as ``y < x``.
   y < x
 
@@ -1098,13 +1098,13 @@ proc contains*[T](s: Slice[T], value: T): bool {.noSideEffect, inline.} =
   ##   assert((1..3).contains(4) == false)
   result = s.a <= value and value <= s.b
 
-template `in` * (x, y: expr): expr {.immediate, dirty.} = contains(y, x)
+template `in` * (x, y: untyped): untyped {.dirty.} = contains(y, x)
   ## Sugar for contains
   ##
   ## .. code-block:: Nim
   ##   assert(1 in (1..3) == true)
   ##   assert(5 in (1..3) == false)
-template `notin` * (x, y: expr): expr {.immediate, dirty.} = not contains(y, x)
+template `notin` * (x, y: untyped): untyped {.dirty.} = not contains(y, x)
   ## Sugar for not containing
   ##
   ## .. code-block:: Nim
@@ -1123,7 +1123,7 @@ proc `is` *[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.}
   ##
   ##   assert(test[int](3) == 3)
   ##   assert(test[string]("xyz") == 0)
-template `isnot` *(x, y: expr): expr {.immediate.} = not (x is y)
+template `isnot` *(x, y: untyped): untyped = not (x is y)
   ## Negated version of `is`. Equivalent to ``not(x is y)``.
 
 proc `of` *[T, S](x: T, y: S): bool {.magic: "Of", noSideEffect.}
@@ -1742,11 +1742,11 @@ proc swap*[T](a, b: var T) {.magic: "Swap", noSideEffect.}
   ## swaps the values `a` and `b`. This is often more efficient than
   ## ``tmp = a; a = b; b = tmp``. Particularly useful for sorting algorithms.
 
-template `>=%` *(x, y: expr): expr {.immediate.} = y <=% x
+template `>=%` *(x, y: untyped): untyped = y <=% x
   ## treats `x` and `y` as unsigned and compares them.
   ## Returns true iff ``unsigned(x) >= unsigned(y)``.
 
-template `>%` *(x, y: expr): expr {.immediate.} = y <% x
+template `>%` *(x, y: untyped): untyped = y <% x
   ## treats `x` and `y` as unsigned and compares them.
   ## Returns true iff ``unsigned(x) > unsigned(y)``.
 
@@ -1874,7 +1874,7 @@ iterator countdown*[T](a, b: T, step = 1): T {.inline.} =
       yield res
       dec(res, step)
 
-template countupImpl(incr: stmt) {.immediate, dirty.} =
+template countupImpl(incr: untyped) {.dirty.} =
   when T is IntLikeForCount:
     var res = int(a)
     while res <= int(b):
@@ -3181,7 +3181,7 @@ proc `/`*(x, y: int): float {.inline, noSideEffect.} =
   ## integer division that results in a float.
   result = toFloat(x) / toFloat(y)
 
-template spliceImpl(s, a, L, b: expr): stmt {.immediate.} =
+template spliceImpl(s, a, L, b: untyped): untyped =
   # make room for additional elements or cut:
   var slen = s.len
   var shift = b.len - L
@@ -3467,7 +3467,7 @@ iterator mitems*(a: var string): var char {.inline.} =
 when not defined(nimhygiene):
   {.pragma: inject.}
 
-template onFailedAssert*(msg: expr, code: stmt): stmt {.dirty, immediate.} =
+template onFailedAssert*(msg, code: untyped): untyped {.dirty.} =
   ## Sets an assertion failure handler that will intercept any assert
   ## statements following `onFailedAssert` in the current module scope.
   ##
@@ -3480,7 +3480,7 @@ template onFailedAssert*(msg: expr, code: stmt): stmt {.dirty, immediate.} =
   ##    e.lineinfo = instantiationInfo(-2)
   ##    raise e
   ##
-  template failedAssertImpl(msgIMPL: string): stmt {.dirty.} =
+  template failedAssertImpl(msgIMPL: string): untyped {.dirty.} =
     let msg = msgIMPL
     code
 
@@ -3643,7 +3643,7 @@ proc `==` *(x, y: cstring): bool {.magic: "EqCString", noSideEffect,
   elif x.isNil or y.isNil: result = false
   else: result = strcmp(x, y) == 0
 
-template closureScope*(body: untyped): stmt =
+template closureScope*(body: untyped): untyped =
   ## Useful when creating a closure in a loop to capture local loop variables by
   ## their current iteration values. Example:
   ##
diff --git a/tests/macros/tdumptree.nim b/tests/macros/tdumptree.nim
index e5160b7ba..58b011b45 100644
--- a/tests/macros/tdumptree.nim
+++ b/tests/macros/tdumptree.nim
@@ -3,7 +3,7 @@ msg: '''StmtList
   VarSection
     IdentDefs
       Ident !"x"
-      nil
+      Empty
       Call
         DotExpr
           Ident !"foo"
diff --git a/todo.txt b/todo.txt
index 235d79b78..38d0fef58 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,7 +1,9 @@
 version 1.0 battle plan
 =======================
 
-- Deprecate ``immediate`` for templates and macros
+- tests/stdlib/tnre.nim
+- tests/closure/tflatmap.nim
+
 - fix "high priority" bugs
 - try to fix as many compiler crashes as reasonable
 
diff --git a/web/news/version_0_15_released.rst b/web/news/version_0_15_released.rst
index e16bdc9ae..c440161c4 100644
--- a/web/news/version_0_15_released.rst
+++ b/web/news/version_0_15_released.rst
@@ -30,6 +30,10 @@ Changes affecting backwards compatibility
   discussion.
 - Overloading the special operators ``.``, ``.()``, ``.=``, ``()`` now
   should be enabled via ``{.experimental.}``.
+- ``immediate`` templates and macros are now deprecated.
+  Instead use ``untyped`` parameters.
+- The metatype ``expr`` is deprecated. Use ``untyped`` instead.
+- The metatype ``stmt`` is deprecated. Use ``typed`` instead.
 
 
 Library Additions