summary refs log tree commit diff stats
path: root/tests/macros
diff options
context:
space:
mode:
Diffstat (limited to 'tests/macros')
-rw-r--r--tests/macros/m18235.nim42
-rw-r--r--tests/macros/macro_bug.nim11
-rw-r--r--tests/macros/mparsefile.nim4
-rw-r--r--tests/macros/t14227.nim23
-rw-r--r--tests/macros/t14329.nim4
-rw-r--r--tests/macros/t14511.nim54
-rw-r--r--tests/macros/t14847.nim20
-rw-r--r--tests/macros/t15691.nim22
-rw-r--r--tests/macros/t15751.nim11
-rw-r--r--tests/macros/t16758.nim38
-rw-r--r--tests/macros/t17836.nim15
-rw-r--r--tests/macros/t18203.nim15
-rw-r--r--tests/macros/t18235.nim18
-rw-r--r--tests/macros/t19766_20114.nim16
-rw-r--r--tests/macros/t20067.nim28
-rw-r--r--tests/macros/t20435.nim30
-rw-r--r--tests/macros/t21593.nim13
-rw-r--r--tests/macros/t23032_1.nim19
-rw-r--r--tests/macros/t23032_2.nim20
-rw-r--r--tests/macros/t23547.nim23
-rw-r--r--tests/macros/t23784.nim157
-rw-r--r--tests/macros/t7454.nim8
-rw-r--r--tests/macros/t7875.nim22
-rw-r--r--tests/macros/t8997.nim26
-rw-r--r--tests/macros/tastrepr.nim58
-rw-r--r--tests/macros/tbindsym.nim44
-rw-r--r--tests/macros/tbugs.nim106
-rw-r--r--tests/macros/tcasestmtmacro.nim33
-rw-r--r--tests/macros/tclosuremacro.nim69
-rw-r--r--tests/macros/tcollect.nim63
-rw-r--r--tests/macros/tcomplexecho.nim4
-rw-r--r--tests/macros/tcprag.nim32
-rw-r--r--tests/macros/tdebugstmt.nim29
-rw-r--r--tests/macros/tdumpast.nim168
-rw-r--r--tests/macros/tdumpast2.nim2
-rw-r--r--tests/macros/tdumpastgen.nim45
-rw-r--r--tests/macros/tdumptree.nim11
-rw-r--r--tests/macros/tescape_var_into_quotedo_as_const.nim36
-rw-r--r--tests/macros/texpectIdent1.nim18
-rw-r--r--tests/macros/texpectIdent2.nim24
-rw-r--r--tests/macros/texprcolonexpr.nim19
-rw-r--r--tests/macros/tfail_parse.nim15
-rw-r--r--tests/macros/tforloop_macro1.nim44
-rw-r--r--tests/macros/tgentemplates.nim35
-rw-r--r--tests/macros/tgetimpl.nim93
-rw-r--r--tests/macros/tgetraiseslist.nim29
-rw-r--r--tests/macros/tgettype.nim105
-rw-r--r--tests/macros/tgettype2.nim99
-rw-r--r--tests/macros/tgettype3.nim48
-rw-r--r--tests/macros/tgettypeinst.nim140
-rw-r--r--tests/macros/tgettypeinst7737.nim61
-rw-r--r--tests/macros/tidgen.nim19
-rw-r--r--tests/macros/tincremental.nim150
-rw-r--r--tests/macros/tinvalidtypesym.nim14
-rw-r--r--tests/macros/tisexported.nim10
-rw-r--r--tests/macros/tlexerex.nim16
-rw-r--r--tests/macros/tlocktypednode1.nim12
-rw-r--r--tests/macros/tlocktypednode2.nim12
-rw-r--r--tests/macros/tlocktypednode3.nim15
-rw-r--r--tests/macros/tmacro1.nim102
-rw-r--r--tests/macros/tmacro2.nim10
-rw-r--r--tests/macros/tmacro3.nim7
-rw-r--r--tests/macros/tmacro4.nim8
-rw-r--r--tests/macros/tmacro5.nim8
-rw-r--r--tests/macros/tmacro6.nim75
-rw-r--r--tests/macros/tmacro7.nim36
-rw-r--r--tests/macros/tmacro8.nim35
-rw-r--r--tests/macros/tmacro_in_template.nim10
-rw-r--r--tests/macros/tmacroaspragma.nim3
-rw-r--r--tests/macros/tmacrogenerics.nim11
-rw-r--r--tests/macros/tmacrogensym.nim (renamed from tests/macros/tgensym.nim)16
-rw-r--r--tests/macros/tmacrogetimpl.nim31
-rw-r--r--tests/macros/tmacros1.nim64
-rw-r--r--tests/macros/tmacros_issues.nim521
-rw-r--r--tests/macros/tmacros_various.nim391
-rw-r--r--tests/macros/tmacrostmt.nim137
-rw-r--r--tests/macros/tmacrotypes.nim159
-rw-r--r--tests/macros/tmemit.nim27
-rw-r--r--tests/macros/tmsginfo.nim24
-rw-r--r--tests/macros/tnewlit.nim194
-rw-r--r--tests/macros/tnewproc.nim51
-rw-r--r--tests/macros/tnimnode_for_runtime.nim12
-rw-r--r--tests/macros/tnodecompare.nim44
-rw-r--r--tests/macros/tparsefile.nim11
-rw-r--r--tests/macros/tprintf.nim16
-rw-r--r--tests/macros/tprocgettype.nim28
-rw-r--r--tests/macros/tprochelpers.nim22
-rw-r--r--tests/macros/tquotedo.nim51
-rw-r--r--tests/macros/tquotewords.nim6
-rw-r--r--tests/macros/trecmacro.nim4
-rw-r--r--tests/macros/treturnsempty.nim3
-rw-r--r--tests/macros/tsame_name_497.nim3
-rw-r--r--tests/macros/tsametype.nim3
-rw-r--r--tests/macros/tslice.nim38
-rw-r--r--tests/macros/tstaticparamsmacro.nim21
-rw-r--r--tests/macros/tstringinterp.nim9
-rw-r--r--tests/macros/tstructuredlogging.nim154
-rw-r--r--tests/macros/ttemplatesymbols.nim171
-rw-r--r--tests/macros/ttryparseexpr.nim8
-rw-r--r--tests/macros/ttypenodes.nim16
-rw-r--r--tests/macros/tvarargsuntyped.nim108
-rw-r--r--tests/macros/tvarnimnode.nim19
-rw-r--r--tests/macros/tvtable.nim6
-rw-r--r--tests/macros/twrapiterator.nim19
-rw-r--r--tests/macros/typesafeprintf.nim7
-rw-r--r--tests/macros/typesapi.nim17
-rw-r--r--tests/macros/typesapi2.nim5
107 files changed, 4524 insertions, 514 deletions
diff --git a/tests/macros/m18235.nim b/tests/macros/m18235.nim
new file mode 100644
index 000000000..6bb4547e0
--- /dev/null
+++ b/tests/macros/m18235.nim
@@ -0,0 +1,42 @@
+import macros
+
+# Necessary code to update the AST on a symbol across module boundaries when
+# processed by a type macro. Used by a test of a corresponding name of this
+# file.
+
+macro eexport(n: typed): untyped =
+  result = copyNimTree(n)
+  # turn exported nnkSym -> nnkPostfix(*, nnkIdent), forcing re-sem
+  result[0] = nnkPostfix.newTree(ident"*").add:
+    n.name.strVal.ident
+
+macro unexport(n: typed): untyped =
+  result = copyNimTree(n)
+  # turn nnkSym -> nnkIdent, forcing re-sem and dropping any exported-ness
+  # that might be present
+  result[0] = n.name.strVal.ident
+
+proc foo*() {.unexport.} = discard
+proc bar() {.eexport.} = discard
+
+proc foooof*() {.unexport, eexport, unexport.} = discard
+proc barrab() {.eexport, unexport, eexport.} = discard
+
+macro eexportMulti(n: typed): untyped =
+  # use the call version of `eexport` macro for one or more decls
+  result = copyNimTree(n)
+  for i in 0..<result.len:
+    result[i] = newCall(ident"eexport", result[i])
+
+macro unexportMulti(n: typed): untyped =
+  # use the call version of `unexport` macro for one or more decls
+  result = copyNimTree(n)
+  for i in 0..<result.len:
+    result[i] = newCall(ident"unexport", result[i])
+
+unexportMulti:
+  proc oof*() = discard
+
+eexportMulti:
+  proc rab() = discard
+  proc baz*() = discard
\ No newline at end of file
diff --git a/tests/macros/macro_bug.nim b/tests/macros/macro_bug.nim
index 0d0fa76ac..c723a4ab6 100644
--- a/tests/macros/macro_bug.nim
+++ b/tests/macros/macro_bug.nim
@@ -1,6 +1,7 @@
 import macros
 
-macro macro_bug*(s: stmt): stmt {.immediate.} =
+macro macro_bug*(s: untyped) =
+  echo s.treeRepr
   s.expectKind({nnkProcDef, nnkMethodDef})
 
   var params = s.params
@@ -9,9 +10,9 @@ macro macro_bug*(s: stmt): stmt {.immediate.} =
   result = newNimNode(nnkProcDef).add(
     s.name, s[1], genericParams, params, pragma(s), newEmptyNode())
 
+  # don't really do anything
   var body = body(s)
-
-  # Fails here.
-  var call = newCall("macro_bug", s.params[1][0])
-  body.insert(0, call)
   result.add(body)
+
+  echo "result:"
+  echo result.repr
diff --git a/tests/macros/mparsefile.nim b/tests/macros/mparsefile.nim
new file mode 100644
index 000000000..8ac99d568
--- /dev/null
+++ b/tests/macros/mparsefile.nim
@@ -0,0 +1,4 @@
+let a = 1
+let b = 2
+let c =
+let d = 4
diff --git a/tests/macros/t14227.nim b/tests/macros/t14227.nim
new file mode 100644
index 000000000..4206e2c06
--- /dev/null
+++ b/tests/macros/t14227.nim
@@ -0,0 +1,23 @@
+discard """
+  action: "compile"
+"""
+import sugar
+
+
+block:
+  let y = @[@[1, 2], @[2, 4, 6]]
+  let x = collect(newSeq):
+    for i in y:
+      if i.len > 2:
+        for j in i:
+          j
+  echo(x)
+
+block:
+  let y = @[@[1, 2], @[2, 4, 6]]
+  let x = collect(newSeq):
+    for i in y:
+      for j in i:
+        if i.len > 2:
+          j
+  echo(x)
diff --git a/tests/macros/t14329.nim b/tests/macros/t14329.nim
new file mode 100644
index 000000000..b5606424a
--- /dev/null
+++ b/tests/macros/t14329.nim
@@ -0,0 +1,4 @@
+import macros
+
+macro myMacro(n) =
+  let x = if true: newLit"test" else: error "error", n
diff --git a/tests/macros/t14511.nim b/tests/macros/t14511.nim
new file mode 100644
index 000000000..f3b1e2894
--- /dev/null
+++ b/tests/macros/t14511.nim
@@ -0,0 +1,54 @@
+discard """
+  output: "true\n(y: XInt, a: 5)\n(y: XString, b: \"abc\")"
+"""
+
+import macros
+
+block TEST_1:
+  # https://github.com/nim-lang/Nim/issues/14511
+
+  template myPragma() {.pragma.}
+
+  type
+    XType = enum
+      XInt,
+      XString,
+      XUnused
+    X = object
+      case y {.myPragma.}: XType
+        of XInt, XUnused:
+          a: int
+        else: # <-- Else case caused the "Error: index 1 not in 0 .. 0" error
+          b: string
+
+  var x: X = X(y: XInt, a: 5)
+  echo x.y.hasCustomPragma(myPragma)
+  echo x
+  echo X(y: XString, b: "abc")
+
+
+block TEST_2:
+  template myDevice(val: string) {.pragma.}
+  template myKey(val: string) {.pragma.}
+  template myMouse(val: string) {.pragma.}
+
+  type
+    Device {.pure.} = enum Keyboard, Mouse
+    Key = enum Key1, Key2
+    Mouse = enum Mouse1, Mouse2
+
+  type
+    Obj = object of RootObj
+      case device {.myDevice: "MyDevicePragmaStr".}: Device
+      of Device.Keyboard:
+        key {.myKey: "MyKeyPragmaStr".}: Key
+      else: # <-- Else case caused the "Error: index 1 not in 0 .. 0" error
+        mouse {.myMouse: "MyMousePragmaStr".}: Mouse
+
+  var obj: Obj
+  assert obj.device.hasCustomPragma(myDevice) == true
+  assert obj.key.hasCustomPragma(myKey) == true
+  assert obj.mouse.hasCustomPragma(myMouse) == true
+  assert obj.device.getCustomPragmaVal(myDevice) == "MyDevicePragmaStr"
+  assert obj.key.getCustomPragmaVal(myKey) == "MyKeyPragmaStr"
+  assert obj.mouse.getCustomPragmaVal(myMouse) == "MyMousePragmaStr"
\ No newline at end of file
diff --git a/tests/macros/t14847.nim b/tests/macros/t14847.nim
new file mode 100644
index 000000000..0e6d0dd2d
--- /dev/null
+++ b/tests/macros/t14847.nim
@@ -0,0 +1,20 @@
+discard """
+  output: "98"
+"""
+import macros
+
+#bug #14847
+proc hello*(b: string) =
+  echo b
+
+macro dispatch(pro: typed, params: untyped): untyped =
+  var impl = pro.getImpl
+  let id = ident(pro.strVal & "_coverage")
+  impl[0] = id
+  let call = newCall(id, params)
+
+  result = newStmtList()
+  result.add(impl)
+  result.add(call)
+
+dispatch(hello, "98")
diff --git a/tests/macros/t15691.nim b/tests/macros/t15691.nim
new file mode 100644
index 000000000..c1e8a8648
--- /dev/null
+++ b/tests/macros/t15691.nim
@@ -0,0 +1,22 @@
+discard """
+  action: compile
+"""
+
+import std/macros
+
+macro simplifiedExpandMacros(body: typed): untyped =
+  result = body
+
+simplifiedExpandMacros:
+  proc testProc() = discard
+
+simplifiedExpandMacros:
+  template testTemplate(): untyped = discard
+
+# Error: illformed AST: macro testMacro(): untyped =
+simplifiedExpandMacros:
+  macro testMacro(): untyped = discard
+
+# Error: illformed AST: converter testConverter(x: int): float =
+simplifiedExpandMacros:
+  converter testConverter(x: int): float = discard
diff --git a/tests/macros/t15751.nim b/tests/macros/t15751.nim
new file mode 100644
index 000000000..fcabb2f9e
--- /dev/null
+++ b/tests/macros/t15751.nim
@@ -0,0 +1,11 @@
+discard """
+  cmd: "nim c --hints:off $file"
+  nimout: "out"
+"""
+
+# bug #15751
+macro print(n: untyped): untyped =
+  echo n.repr
+
+print:
+  out
diff --git a/tests/macros/t16758.nim b/tests/macros/t16758.nim
new file mode 100644
index 000000000..66b6d42c5
--- /dev/null
+++ b/tests/macros/t16758.nim
@@ -0,0 +1,38 @@
+discard """

+errormsg: "'blk.p(a)' has nil child at index 1"

+action: reject

+"""

+import macros

+

+type BlockLiteral[T] = object

+  p: T

+

+proc p[T](a:int) = echo 1

+proc p[T](a:string) = echo "a"

+

+iterator arguments(formalParams: NimNode): NimNode =

+  var iParam = 0

+  for i in 1 ..< formalParams.len:

+    let pp = formalParams[i]

+    for j in 0 .. pp.len - 3:

+      yield pp[j]

+      inc iParam

+

+macro implementInvoke(T: typedesc): untyped =

+  let t = getTypeImpl(T)[1]

+

+  let call = newCall(newDotExpr(ident"blk", ident"p"))

+  let params = copyNimTree(t[0])

+  result = newProc(ident"invoke", body = call)

+  # result[2] = newTree(nnkGenericParams,T)

+  for n in arguments(params):

+    call.add(n)

+  

+  params.insert(1, newIdentDefs(ident"blk", newTree(nnkBracketExpr, bindSym"BlockLiteral", T)))

+  result.params = params

+

+proc getInvoke(T: typedesc) =

+  implementInvoke(T)

+

+

+getInvoke(proc(a: int))

diff --git a/tests/macros/t17836.nim b/tests/macros/t17836.nim
new file mode 100644
index 000000000..2453637f5
--- /dev/null
+++ b/tests/macros/t17836.nim
@@ -0,0 +1,15 @@
+import macros
+
+# Ensure that `isNil` works in the typed macro context when pass procs.
+
+type
+  O = object
+    fn: proc(i: int): int
+
+var o: O
+
+macro typedBug(expr: typed) =
+  doAssert expr[1] != nil
+  doAssert not expr[1].isNil
+
+typedBug(o.fn)
\ No newline at end of file
diff --git a/tests/macros/t18203.nim b/tests/macros/t18203.nim
new file mode 100644
index 000000000..aae0a2690
--- /dev/null
+++ b/tests/macros/t18203.nim
@@ -0,0 +1,15 @@
+discard """
+  matrix: "--hint:SuccessX:off --hint:Link:off --hint:Conf:off --hint:CC:off --hint:XDeclaredButNotUsed:on"
+  nimout: '''
+'''
+nimoutFull: true
+action: compile
+"""
+
+# bug #18203
+import std/macros
+
+macro foo(x: typed) = newProc ident"bar"
+proc bar() {.foo.} = raise
+bar()
+
diff --git a/tests/macros/t18235.nim b/tests/macros/t18235.nim
new file mode 100644
index 000000000..ba5c48a24
--- /dev/null
+++ b/tests/macros/t18235.nim
@@ -0,0 +1,18 @@
+import m18235
+
+# this must error out because it was never actually exported
+doAssert(not declared(foo))
+doAssert not compiles(foo())
+
+doAssert(not declared(foooof))
+doAssert not compiles(foooof())
+
+doAssert(not declared(oof))
+doAssert not compiles(oof())
+
+# this should have been exported just fine
+
+bar()
+barrab()
+rab()
+baz()
\ No newline at end of file
diff --git a/tests/macros/t19766_20114.nim b/tests/macros/t19766_20114.nim
new file mode 100644
index 000000000..ac336f150
--- /dev/null
+++ b/tests/macros/t19766_20114.nim
@@ -0,0 +1,16 @@
+discard """
+  action: compile
+  nimout: '''
+const
+  foo {.strdefine.} = "abc"
+let hey {.tddd.} = 5
+'''
+"""
+
+import macros
+
+template tddd {.pragma.}
+
+expandMacros:
+  const foo {.strdefine.} = "abc"
+  let hey {.tddd.} = 5
diff --git a/tests/macros/t20067.nim b/tests/macros/t20067.nim
new file mode 100644
index 000000000..0ee3a4712
--- /dev/null
+++ b/tests/macros/t20067.nim
@@ -0,0 +1,28 @@
+discard """
+  output: '''
+b.defaultVal = foo
+$c.defaultVal = bar
+'''
+"""
+
+import macros
+
+# #18976
+
+macro getString(identifier): string =
+  result = newLit($identifier)
+doAssert getString(abc) == "abc"
+doAssert getString(`a b c`) == "abc"
+
+# #20067
+
+template defaultVal*(value : typed) {.pragma.}
+
+type A = ref object
+  b {.defaultVal: "foo".}: string
+  `$c` {.defaultVal: "bar".}: string
+
+let a = A(b: "a", `$c`: "b")
+
+echo "b.defaultVal = " & a.b.getCustomPragmaVal(defaultVal)
+echo "$c.defaultVal = " & a.`$c`.getCustomPragmaVal(defaultVal)
diff --git a/tests/macros/t20435.nim b/tests/macros/t20435.nim
new file mode 100644
index 000000000..824282198
--- /dev/null
+++ b/tests/macros/t20435.nim
@@ -0,0 +1,30 @@
+
+#[
+  A better test requires matching, so the use of @ working can be showcased
+  For example:
+
+  proc regularCase[T]() = 
+    case [(1, 3), (3, 4)]:
+    of [(1, @a), (_, @b)]:
+      echo a, b
+    else: discard
+]#
+
+{.experimental: "caseStmtMacros".}
+
+import macros
+
+type Foo = object
+
+macro `case`(obj: Foo) = quote do: discard
+
+proc notGeneric() =
+  case Foo()
+  of a b c d: discard
+
+proc generic[T]() =
+  case Foo()
+  of a b c d: discard
+
+notGeneric()
+generic[int]()
diff --git a/tests/macros/t21593.nim b/tests/macros/t21593.nim
new file mode 100644
index 000000000..b0b7ebe75
--- /dev/null
+++ b/tests/macros/t21593.nim
@@ -0,0 +1,13 @@
+discard """
+nimout: '''
+StmtList
+  UIntLit 18446744073709551615
+  IntLit -1'''
+"""
+
+import macros
+
+dumpTree:
+  0xFFFFFFFF_FFFFFFFF'u
+  0xFFFFFFFF_FFFFFFFF
+
diff --git a/tests/macros/t23032_1.nim b/tests/macros/t23032_1.nim
new file mode 100644
index 000000000..4e1707414
--- /dev/null
+++ b/tests/macros/t23032_1.nim
@@ -0,0 +1,19 @@
+import std/macros
+
+type A[T, H] = object
+
+proc `%*`(a: A): bool = true
+proc `%*`[T](a: A[int, T]): bool = false
+
+macro collapse(s: untyped) =
+  result = newStmtList()
+  result.add quote do:
+    doAssert(`s`(A[float, int]()) == true)
+
+macro startHere(n: untyped): untyped =
+  result = newStmtList()
+  let s = n[0]
+  result.add quote do:
+    `s`.collapse()
+
+startHere(`a` %* `b`)
diff --git a/tests/macros/t23032_2.nim b/tests/macros/t23032_2.nim
new file mode 100644
index 000000000..8dde29e10
--- /dev/null
+++ b/tests/macros/t23032_2.nim
@@ -0,0 +1,20 @@
+discard """
+  action: "reject"
+  errormsg: "ambiguous identifier: '%*'"
+"""
+import std/macros
+
+type A[T, H] = object
+
+proc `%*`[T](a: A) = discard
+proc `%*`[T](a: A[int, T]) = discard
+
+macro collapse(s: typed) = discard
+
+macro startHere(n: untyped): untyped =
+  result = newStmtList()
+  let s = n[0]
+  result.add quote do:
+    collapse(`s`.typeof())
+
+startHere(`a` %* `b`)
diff --git a/tests/macros/t23547.nim b/tests/macros/t23547.nim
new file mode 100644
index 000000000..9a2bff9ff
--- /dev/null
+++ b/tests/macros/t23547.nim
@@ -0,0 +1,23 @@
+# https://github.com/nim-lang/Nim/issues/23547
+
+type
+  A[T] = object
+    x: T
+
+proc mulCheckSparse[F](dummy: var A[F], xmulchecksparse: static A[F]) =
+  static:
+    echo "mulCheckSparse: ", typeof(dummy), ", ", typeof(xmulchecksparse) # when generic params not specified: A[system.int], A
+
+template sumImpl(xsumimpl: typed) =
+  static:
+    echo "sumImpl: ", typeof(xsumimpl) # A
+  var a = A[int](x: 55)
+  mulCheckSparse(a, xsumimpl) # fails here
+
+proc sum[T](xsum: static T) =
+  static:
+    echo "sum: ", typeof(xsum) # A[system.int]
+  sumImpl(xsum)
+
+const constA = A[int](x : 100)
+sum[A[int]](constA)
diff --git a/tests/macros/t23784.nim b/tests/macros/t23784.nim
new file mode 100644
index 000000000..31b4544c6
--- /dev/null
+++ b/tests/macros/t23784.nim
@@ -0,0 +1,157 @@
+discard """
+  joinable: false
+"""
+
+
+# debug ICE: genCheckedRecordField
+# apparently after https://github.com/nim-lang/Nim/pull/23477
+
+# bug #23784
+
+import std/bitops, std/macros
+
+# --------------------------------------------------------------
+
+type Algebra = enum
+  BN254_Snarks
+
+type SecretWord* = distinct uint64
+const WordBitWidth* = sizeof(SecretWord) * 8
+
+func wordsRequired*(bits: int): int {.inline.} =
+  const divShiftor = fastLog2(WordBitWidth)
+  result = (bits + WordBitWidth - 1) shr divShiftor
+
+type
+  BigInt*[bits: static int] = object
+    limbs*: array[bits.wordsRequired, SecretWord]  # <--- crash points to here
+
+# --------------------------------------------------------------
+
+const CurveBitWidth = [
+  BN254_Snarks: 254
+]
+
+const BN254_Snarks_Modulus = BigInt[254](limbs: [SecretWord 0x1, SecretWord 0x2, SecretWord 0x3, SecretWord 0x4])
+const BN254_Snarks_Order = BigInt[254](limbs: [SecretWord 0x1, SecretWord 0x1, SecretWord 0x2, SecretWord 0x2])
+
+func montyOne*(M: BigInt[254]): BigInt[254] =
+  ## Returns "1 (mod M)" in the Montgomery domain.
+  ## This is equivalent to R (mod M) in the natural domain
+  BigInt[254](limbs: [SecretWord 0x1, SecretWord 0x1, SecretWord 0x1, SecretWord 0x1])
+
+
+{.experimental: "dynamicBindSym".}
+
+type
+  DerivedConstantMode* = enum
+    kModulus
+    kOrder
+
+macro genDerivedConstants*(mode: static DerivedConstantMode): untyped =
+  ## Generate constants derived from the main constants
+  ##
+  ## For example
+  ## - the Montgomery magic constant "R^2 mod N" in ROM
+  ##   For each curve under the private symbol "MyCurve_R2modP"
+  ## - the Montgomery magic constant -1/P mod 2^Wordbitwidth
+  ##   For each curve under the private symbol "MyCurve_NegInvModWord
+  ## - ...
+
+  # Now typedesc are NimNode and there is no way to translate
+  # NimNode -> typedesc easily so we can't
+  # "for curve in low(Curve) .. high(Curve):"
+  # As an ugly workaround, we count
+  # The item at position 0 is a pragma
+  result = newStmtList()
+
+  template used(name: string): NimNode =
+    nnkPragmaExpr.newTree(
+      ident(name),
+      nnkPragma.newTree(ident"used")
+    )
+
+  let ff = if mode == kModulus: "_Fp" else: "_Fr"
+
+  for curveSym in low(Algebra) .. high(Algebra):
+    let curve = $curveSym
+    let M = if mode == kModulus: bindSym(curve & "_Modulus")
+            else: bindSym(curve & "_Order")
+
+    # const MyCurve_montyOne = montyOne(MyCurve_Modulus)
+    result.add newConstStmt(
+      used(curve & ff & "_MontyOne"), newCall(
+        bindSym"montyOne",
+        M
+      )
+    )
+
+# --------------------------------------------------------------
+
+{.experimental: "dynamicBindSym".}
+
+genDerivedConstants(kModulus)
+genDerivedConstants(kOrder)
+
+proc bindConstant(ff: NimNode, property: string): NimNode =
+  # Need to workaround https://github.com/nim-lang/Nim/issues/14021
+  # which prevents checking if a type FF[Name] = Fp[Name] or Fr[Name]
+  # was instantiated with Fp or Fr.
+  # getTypeInst only returns FF and sameType doesn't work.
+  # so quote do + when checks.
+  let T = getTypeInst(ff)
+  T.expectKind(nnkBracketExpr)
+  doAssert T[0].eqIdent("typedesc")
+
+  let curve =
+    if T[1].kind == nnkBracketExpr: # typedesc[Fp[BLS12_381]] as used internally
+      # doAssert T[1][0].eqIdent"Fp" or T[1][0].eqIdent"Fr", "Found ident: '" & $T[1][0] & "' instead of 'Fp' or 'Fr'"
+      T[1][1].expectKind(nnkIntLit) # static enum are ints in the VM
+      $Algebra(T[1][1].intVal)
+    else: # typedesc[bls12381_fp] alias as used for C exports
+      let T1 = getTypeInst(T[1].getImpl()[2])
+      if T1.kind != nnkBracketExpr or
+         T1[1].kind != nnkIntLit:
+        echo T.repr()
+        echo T1.repr()
+        echo getTypeInst(T1).treerepr()
+        error "getTypeInst didn't return the full instantiation." &
+          " Dealing with types in macros is hard, complain at https://github.com/nim-lang/RFCs/issues/44"
+      $Algebra(T1[1].intVal)
+
+  let curve_fp = bindSym(curve & "_Fp_" & property)
+  let curve_fr = bindSym(curve & "_Fr_" & property)
+  result = quote do:
+    when `ff` is Fp:
+      `curve_fp`
+    elif `ff` is Fr:
+      `curve_fr`
+    else:
+      {.error: "Unreachable, received type: " & $`ff`.}
+
+# --------------------------------------------------------------
+
+template matchingBigInt*(Name: static Algebra): untyped =
+  ## BigInt type necessary to store the prime field Fp
+  # Workaround: https://github.com/nim-lang/Nim/issues/16774
+  # as we cannot do array accesses in type section.
+  # Due to generic sandwiches, it must be exported.
+  BigInt[CurveBitWidth[Name]]
+
+type
+  Fp*[Name: static Algebra] = object
+    mres*: matchingBigInt(Name)
+
+macro getMontyOne*(ff: type Fp): untyped =
+  ## Get one in Montgomery representation (i.e. R mod P)
+  result = bindConstant(ff, "MontyOne")
+
+func getOne*(T: type Fp): T {.noInit, inline.} =
+  result = cast[ptr T](unsafeAddr getMontyOne(T))[]
+
+# --------------------------------------------------------------
+proc foo(T: Fp) =
+  discard T
+
+let a = Fp[BN254_Snarks].getOne()
+foo(a) # oops this was a leftover that broke the bisect.
diff --git a/tests/macros/t7454.nim b/tests/macros/t7454.nim
new file mode 100644
index 000000000..e527de0c3
--- /dev/null
+++ b/tests/macros/t7454.nim
@@ -0,0 +1,8 @@
+discard """
+errormsg: "expression has no type:"
+line: 8
+"""
+
+macro p(t: typedesc): typedesc =
+  discard
+var a: p(int)
diff --git a/tests/macros/t7875.nim b/tests/macros/t7875.nim
new file mode 100644
index 000000000..7b6e47b86
--- /dev/null
+++ b/tests/macros/t7875.nim
@@ -0,0 +1,22 @@
+discard """
+  nimout: "var mysym`gensym0: MyType[float32]"
+  joinable: false
+"""
+
+import macros
+
+type
+  MyType[T] = object
+
+# this is totally fine
+var mysym: MyType[float32]
+
+macro foobar(): untyped =
+  let floatSym = bindSym"float32"
+
+  result = quote do:
+    var mysym: MyType[`floatSym`]
+
+  echo result.repr
+
+foobar()
diff --git a/tests/macros/t8997.nim b/tests/macros/t8997.nim
new file mode 100644
index 000000000..b06223717
--- /dev/null
+++ b/tests/macros/t8997.nim
@@ -0,0 +1,26 @@
+discard """
+  errormsg: "illformed AST: "
+  line: 24
+"""
+
+import macros
+
+type
+  Node* = ref object
+    children: seq[Node]
+
+proc newNode*(): Node =
+  Node(children: newSeq[Node]())
+
+macro build*(body: untyped): untyped =
+
+  template appendElement(tmp, childrenBlock) {.dirty.} =
+    bind newNode
+    let tmp = newNode()
+    tmp.children = childrenBlock  # this line seems to be the problem
+
+  let tmp = genSym(nskLet, "tmp")
+  let childrenBlock = newEmptyNode()
+  result = getAst(appendElement(tmp, childrenBlock))
+
+build(body)
diff --git a/tests/macros/tastrepr.nim b/tests/macros/tastrepr.nim
new file mode 100644
index 000000000..96a37c7a2
--- /dev/null
+++ b/tests/macros/tastrepr.nim
@@ -0,0 +1,58 @@
+discard """
+output: '''
+
+var data = @[(1, "one"), (2, "two")]
+for (i, d) in pairs(data):
+  discard
+for i, d in pairs(data):
+  discard
+for i, (x, y) in pairs(data):
+  discard
+var
+  a = 1
+  b = 2
+type
+  A* = object
+
+var data = @[(1, "one"), (2, "two")]
+for (i, d) in pairs(data):
+  discard
+for i, d in pairs(data):
+  discard
+for i, (x, y) in pairs(data):
+  discard
+var (a, b) = (1, 2)
+type
+  A* = object
+
+var t04 = 1.0'f128
+t04 = 2.0'f128
+'''
+"""
+
+import macros
+
+macro echoTypedRepr(arg: typed) =
+  result = newCall(ident"echo", newLit(arg.repr))
+
+macro echoUntypedRepr(arg: untyped) =
+  result = newCall(ident"echo", newLit(arg.repr))
+
+template echoTypedAndUntypedRepr(arg: untyped) =
+  echoTypedRepr(arg)
+  echoUntypedRepr(arg)
+
+echoTypedAndUntypedRepr:
+  var data = @[(1,"one"), (2,"two")]
+  for (i, d) in pairs(data):
+    discard
+  for i, d in pairs(data):
+    discard
+  for i, (x,y) in pairs(data):
+    discard
+  var (a,b) = (1,2)
+  type A* = object # issue #22933
+
+echoUntypedRepr:
+  var t04 = 1'f128
+  t04 = 2'f128
diff --git a/tests/macros/tbindsym.nim b/tests/macros/tbindsym.nim
index e1e3b5112..a493d6a88 100644
--- a/tests/macros/tbindsym.nim
+++ b/tests/macros/tbindsym.nim
@@ -1,4 +1,9 @@
 discard """
+  nimout: '''initApple
+deinitApple
+Coral
+enum
+  redCoral, blackCoral'''
   output: '''TFoo
 TBar'''
 """
@@ -11,7 +16,7 @@ type
   TTextKind = enum
     TFoo, TBar
 
-macro test: stmt =
+macro test: untyped =
   var x = @[TFoo, TBar]
   result = newStmtList()
   for i in x:
@@ -23,3 +28,40 @@ macro test: stmt =
         bindSym("TBar"))
 
 test()
+
+# issue 7827, bindSym power up
+{.experimental: "dynamicBindSym".}
+type
+  Apple = ref object
+    name: string
+    color: int
+    weight: int
+
+proc initApple(name: string): Apple =
+  discard
+
+proc deinitApple(x: Apple) =
+  discard
+
+macro wrapObject(obj: typed, n: varargs[untyped]): untyped =
+  let m = n[0]
+  for x in m:
+    var z = bindSym x
+    echo z.repr
+
+wrapObject(Apple):
+  initApple
+  deinitApple
+
+type
+  Coral = enum
+    redCoral
+    blackCoral
+
+macro mixer(): untyped =
+  let m = "Co" & "ral"
+  let x = bindSym(m)
+  echo x.repr
+  echo getType(x).repr
+
+mixer()
diff --git a/tests/macros/tbugs.nim b/tests/macros/tbugs.nim
deleted file mode 100644
index 1bfce6bc4..000000000
--- a/tests/macros/tbugs.nim
+++ /dev/null
@@ -1,106 +0,0 @@
-discard """
-msg: '''a
-s
-d
-f
-TTaa
-TTaa
-TTaa
-TTaa
-true
-true
-nil
-42
-false
-true'''
-
-output: '''test
-2'''
-"""
-
-type
-  Foo = object
-    s: char
-
-iterator test2(f: string): Foo =
-  for i in f:
-    yield Foo(s: i)
-
-macro test(): stmt =
-  for i in test2("asdf"):
-    echo i.s
-
-test()
-
-
-# bug 1297
-
-import macros
-
-type TType = tuple[s: string]
-
-macro echotest(): stmt =
-  var t: TType
-  t.s = ""
-  t.s.add("test")
-  result = newCall(newIdentNode("echo"), newStrLitNode(t.s))
-
-echotest()
-
-# bug #1103
-
-type
-    Td = tuple
-        a:string
-        b:int
-
-proc get_data(d: Td) : string {.compileTime.} =
-    result = d.a # Works if a literal string is used here.
-    # Bugs if line A or B is active. Works with C
-    result &= "aa"          # A
-    #result.add("aa")       # B
-    #result = result & "aa" # C
-
-macro m(s:static[Td]) : stmt =
-    echo get_data(s)
-    echo get_data(s)
-    result = newEmptyNode()
-
-const s=("TT", 3)
-m(s)
-m(s)
-
-# bug #933
-
-proc nilcheck(): NimNode {.compileTime.} =
-  echo(result == nil) # true
-  echo(result.isNil) # true
-  echo(repr(result)) # nil
-
-macro testnilcheck(): stmt =
-  result = newNimNode(nnkStmtList)
-  discard nilcheck()
-
-testnilcheck()
-
-# bug #1323
-
-proc calc(): array[1, int] =
-  result[0].inc()
-  result[0].inc()
-
-const c = calc()
-echo c[0]
-
-
-# bug #3046
-
-macro sampleMacroInt(i: int): stmt =
-  echo i.intVal
-
-macro sampleMacroBool(b: bool): stmt =
-  echo b.boolVal
-
-sampleMacroInt(42)
-sampleMacroBool(false)
-sampleMacroBool(system.true)
diff --git a/tests/macros/tcasestmtmacro.nim b/tests/macros/tcasestmtmacro.nim
new file mode 100644
index 000000000..32019a92a
--- /dev/null
+++ b/tests/macros/tcasestmtmacro.nim
@@ -0,0 +1,33 @@
+discard """
+  output: '''
+yes
+'''
+"""
+
+import macros
+
+macro `case`(n: tuple): untyped =
+  result = newTree(nnkIfStmt)
+  let selector = n[0]
+  for i in 1 ..< n.len:
+    let it = n[i]
+    case it.kind
+    of nnkElse, nnkElifBranch, nnkElifExpr, nnkElseExpr:
+      result.add it
+    of nnkOfBranch:
+      for j in 0..it.len-2:
+        let cond = newCall("==", selector, it[j])
+        result.add newTree(nnkElifBranch, cond, it[^1])
+    else:
+      error "custom 'case' for tuple cannot handle this node", it
+
+var correct = false
+
+case ("foo", 78)
+of ("foo", 78):
+  correct = true
+  echo "yes"
+of ("bar", 88): echo "no"
+else: discard
+
+doAssert correct
diff --git a/tests/macros/tclosuremacro.nim b/tests/macros/tclosuremacro.nim
index c29fbe1c8..44c2411a5 100644
--- a/tests/macros/tclosuremacro.nim
+++ b/tests/macros/tclosuremacro.nim
@@ -1,15 +1,14 @@
 discard """
-  output: '''10
-10
-10
-3
-3
+  output: '''
 noReturn
-6
+calling mystuff
+yes
+calling mystuff
+yes
 '''
 """
 
-import future
+import sugar, macros
 
 proc twoParams(x: (int, int) -> int): int =
   result = x(5, 5)
@@ -26,18 +25,56 @@ proc noReturn(x: () -> void) =
 proc doWithOneAndTwo(f: (int, int) -> int): int =
   f(1,2)
 
-echo twoParams(proc (a, b: auto): auto = a + b)
-echo twoParams((x, y) => x + y)
-
-echo oneParam(x => x+5)
-
-echo noParams(() => 3)
-
-echo doWithOneAndTwo((x, y) => x + y)
+doAssert twoParams(proc (a, b: auto): auto = a + b) == 10
+doAssert twoParams((x, y) => x + y) == 10
+doAssert oneParam(x => x+5) == 10
+doAssert noParams(() => 3) == 3
+doAssert doWithOneAndTwo((x, y) => x + y) == 3
 
 noReturn((() -> void) => echo("noReturn"))
 
 proc pass2(f: (int, int) -> int): (int) -> int =
   ((x: int) -> int) => f(2, x)
 
-echo pass2((x, y) => x + y)(4)
+doAssert pass2((x, y) => x + y)(4) == 6
+
+const fun = (x, y: int) {.noSideEffect.} => x + y
+
+doAssert typeof(fun) is (proc (x, y: int): int {.nimcall.})
+doAssert fun(3, 4) == 7
+
+proc register(name: string; x: proc()) =
+  echo "calling ", name
+  x()
+
+register("mystuff", proc () =
+  echo "yes"
+)
+
+proc helper(x: NimNode): NimNode =
+  if x.kind == nnkProcDef:
+    result = copyNimTree(x)
+    result[0] = newEmptyNode()
+    result = newCall("register", newLit($x[0]), result)
+  else:
+    result = copyNimNode(x)
+    for i in 0..<x.len:
+      result.add helper(x[i])
+
+macro m(x: untyped): untyped =
+  result = helper(x)
+
+m:
+  proc mystuff() =
+    echo "yes"
+
+const typedParamAndPragma = (x, y: int) -> int => x + y
+doAssert typedParamAndPragma(1, 2) == 3
+
+type
+  Bot = object
+    call: proc (): string {.noSideEffect.}
+
+var myBot = Bot()
+myBot.call = () {.noSideEffect.} => "I'm a bot."
+doAssert myBot.call() == "I'm a bot."
diff --git a/tests/macros/tcollect.nim b/tests/macros/tcollect.nim
new file mode 100644
index 000000000..ae28ab61b
--- /dev/null
+++ b/tests/macros/tcollect.nim
@@ -0,0 +1,63 @@
+discard """
+  output: '''@[2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4]
+@[0, 1, 2, 3]'''
+"""
+
+const data = [1,2,3,4,5,6]
+
+import macros
+
+macro collect(body): untyped =
+  # analyse the body, find the deepest expression 'it' and replace it via
+  # 'result.add it'
+  let res = genSym(nskVar, "collectResult")
+
+  when false:
+    proc detectForLoopVar(n: NimNode): NimNode =
+      if n.kind == nnkForStmt:
+        result = n[0]
+      else:
+        for x in n:
+          result = detectForLoopVar(x)
+          if result != nil: return result
+        return nil
+
+  proc t(n, res: NimNode): NimNode =
+    case n.kind
+    of nnkStmtList, nnkStmtListExpr, nnkBlockStmt, nnkBlockExpr,
+       nnkWhileStmt,
+       nnkForStmt, nnkIfExpr, nnkIfStmt, nnkTryStmt, nnkCaseStmt,
+       nnkElifBranch, nnkElse, nnkElifExpr:
+      result = copyNimTree(n)
+      if n.len >= 1:
+        result[^1] = t(n[^1], res)
+    else:
+      if true: #n == it:
+        template adder(res, it) =
+          res.add it
+        result = getAst adder(res, n)
+      else:
+        result = n
+
+  when false:
+    let it = detectForLoopVar(body)
+    if it == nil: error("no for loop in body", body)
+
+  let v = newTree(nnkVarSection,
+     newTree(nnkIdentDefs, res, newTree(nnkBracketExpr, bindSym"seq",
+     newCall(bindSym"type", body)), newEmptyNode()))
+
+  result = newTree(nnkStmtListExpr, v, t(body, res), res)
+  #echo repr result
+
+let stuff = collect:
+  var i = -1
+  while i < 4:
+    inc i
+    for it in data:
+      if it < 5 and it > 1:
+        it
+
+echo stuff
+
+echo collect(for i in 0..3: i)
diff --git a/tests/macros/tcomplexecho.nim b/tests/macros/tcomplexecho.nim
index f7f933c1c..d58fa561c 100644
--- a/tests/macros/tcomplexecho.nim
+++ b/tests/macros/tcomplexecho.nim
@@ -10,7 +10,7 @@ OK
 import macros
 
 # Bug from the forum
-macro addEcho1(s: untyped): stmt =
+macro addEcho1(s: untyped): untyped =
   s.body.add(newCall("echo", newStrLitNode("OK")))
   result = s
 
@@ -32,7 +32,7 @@ proc foo(): seq[NimNode] {.compiletime.} =
   result.add test()
   result.add parseExpr("echo(5+56)")
 
-macro bar(): stmt =
+macro bar() =
   result = newNimNode(nnkStmtList)
   let x = foo()
   for xx in x:
diff --git a/tests/macros/tcprag.nim b/tests/macros/tcprag.nim
new file mode 100644
index 000000000..71618883f
--- /dev/null
+++ b/tests/macros/tcprag.nim
@@ -0,0 +1,32 @@
+discard """
+  output: '''true
+true
+true
+'''
+"""
+
+# issue #7615
+import macros
+
+template table(name: string) {.pragma.}
+
+type
+   User {.table("tuser").} = object
+      id: int
+      name: string
+      age: int
+
+echo User.hasCustomPragma(table)
+
+
+## crash: Error: internal error: (filename: "sempass2.nim", line: 560, column: 19)
+macro m1(T: typedesc): untyped =
+  getAST hasCustomPragma(T, table)
+echo m1(User) # Oops crash
+
+
+## This works
+macro m2(T: typedesc): untyped =
+  result = quote do:
+    `T`.hasCustomPragma(table)
+echo m2(User)
diff --git a/tests/macros/tdebugstmt.nim b/tests/macros/tdebugstmt.nim
deleted file mode 100644
index 421f8fd14..000000000
--- a/tests/macros/tdebugstmt.nim
+++ /dev/null
@@ -1,29 +0,0 @@
-discard """
-  output: '''a[0]: 42
-a[1]: 45
-x: some string'''
-"""
-
-import macros
-
-macro debug(n: varargs[expr]): stmt =
-  # `n` is a Nim AST that contains the whole macro invocation
-  # this macro returns a list of statements:
-  result = newNimNode(nnkStmtList, n)
-  # iterate over any argument that is passed to this macro:
-  for i in 0..n.len-1:
-    # add a call to the statement list that writes the expression;
-    # `toStrLit` converts an AST to its string representation:
-    add(result, newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
-    # add a call to the statement list that writes ": "
-    add(result, newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
-    # add a call to the statement list that writes the expressions value:
-    add(result, newCall("writeLine", newIdentNode("stdout"), n[i]))
-
-var
-  a: array [0..10, int]
-  x = "some string"
-a[0] = 42
-a[1] = 45
-
-debug(a[0], a[1], x)
diff --git a/tests/macros/tdumpast.nim b/tests/macros/tdumpast.nim
index e3388591a..484b3c2f3 100644
--- a/tests/macros/tdumpast.nim
+++ b/tests/macros/tdumpast.nim
@@ -2,32 +2,160 @@
 
 import macros
 
-template plus(a, b: expr): expr {.dirty} =
-  a + b
+block:
+  template plus(a, b: untyped): untyped {.dirty} =
+    a + b
 
-macro call(e: expr): expr =
-  result = newCall("foo", newStrLitNode("bar"))
+  macro call(e: untyped): untyped =
+    result = newCall("foo", newStrLitNode("bar"))
 
-macro dumpAST(n: stmt): stmt {.immediate.} =
-  # dump AST as a side-effect and return the inner node
-  let n = callsite()
-  echo n.lispRepr
-  echo n.treeRepr
+  macro dumpAST(n: untyped): string =
+    var msg = ""
+    msg.add "lispRepr:\n" & n.lispRepr & "\n"
+    msg.add "treeRepr:\n" & n.treeRepr & "\n"
 
-  var plusAst = getAst(plus(1, 2))
-  echo plusAst.lispRepr
+    var plusAst = getAst(plus(1, 2))
+    msg.add "lispRepr:\n" & n.lispRepr & "\n"
 
-  var callAst = getAst(call())
-  echo callAst.lispRepr
+    var callAst = getAst(call(4))
+    msg.add "callAst.lispRepr:\n" & callAst.lispRepr & "\n"
 
-  var e = parseExpr("foo(bar + baz)")
-  echo e.lispRepr
+    var e = parseExpr("foo(bar + baz)")
+    msg.add "e.lispRepr:\n" & e.lispRepr & "\n"
+    result = msg.newLit
 
-  result = n[1]
+  let a = dumpAST:
+    proc add(x, y: int): int =
+      return x + y
+    const foo = 3
 
-dumpAST:
-  proc add(x, y: int): int =
-    return x + y
+  doAssert a == """
+lispRepr:
+(StmtList (ProcDef (Ident "add") (Empty) (Empty) (FormalParams (Ident "int") (IdentDefs (Ident "x") (Ident "y") (Ident "int") (Empty))) (Empty) (Empty) (StmtList (ReturnStmt (Infix (Ident "+") (Ident "x") (Ident "y"))))) (ConstSection (ConstDef (Ident "foo") (Empty) (IntLit 3))))
+treeRepr:
+StmtList
+  ProcDef
+    Ident "add"
+    Empty
+    Empty
+    FormalParams
+      Ident "int"
+      IdentDefs
+        Ident "x"
+        Ident "y"
+        Ident "int"
+        Empty
+    Empty
+    Empty
+    StmtList
+      ReturnStmt
+        Infix
+          Ident "+"
+          Ident "x"
+          Ident "y"
+  ConstSection
+    ConstDef
+      Ident "foo"
+      Empty
+      IntLit 3
+lispRepr:
+(StmtList (ProcDef (Ident "add") (Empty) (Empty) (FormalParams (Ident "int") (IdentDefs (Ident "x") (Ident "y") (Ident "int") (Empty))) (Empty) (Empty) (StmtList (ReturnStmt (Infix (Ident "+") (Ident "x") (Ident "y"))))) (ConstSection (ConstDef (Ident "foo") (Empty) (IntLit 3))))
+callAst.lispRepr:
+(Call (Ident "foo") (StrLit "bar"))
+e.lispRepr:
+(Call (Ident "foo") (Infix (Ident "+") (Ident "bar") (Ident "baz")))
+"""
 
-  proc sub(x, y: int): int = return x - y
+macro fun() =
+  let n = quote do:
+    1+1 == 2
+  doAssert n.repr == "1 + 1 == 2", n.repr
+fun()
 
+macro fun2(): untyped =
+  let n = quote do:
+    1 + 2 * 3 == 1 + 6
+  doAssert n.repr == "1 + 2 * 3 == 1 + 6", n.repr
+fun2()
+
+macro fun3(): untyped =
+  let n = quote do:
+    int | float | array | seq | object | ptr | pointer | float32
+  doAssert n.repr == "int | float | array | seq | object | ptr | pointer | float32", n.repr
+fun3()
+
+macro fun4() =
+  let n = quote do:
+    (a: 1)
+  doAssert n.repr == "(a: 1)", n.repr
+fun4()
+
+# nkTupleConstr vs nkPar tests:
+block: # lispRepr
+  macro lispRepr2(a: untyped): string = newLit a.lispRepr
+
+  doAssert lispRepr2(()) == """(TupleConstr)"""
+  doAssert lispRepr2((a: 1)) == """(TupleConstr (ExprColonExpr (Ident "a") (IntLit 1)))"""
+  doAssert lispRepr2((a: 1, b: 2)) == """(TupleConstr (ExprColonExpr (Ident "a") (IntLit 1)) (ExprColonExpr (Ident "b") (IntLit 2)))"""
+  doAssert lispRepr2((1,)) == """(TupleConstr (IntLit 1))"""
+  doAssert lispRepr2((1, 2)) == """(TupleConstr (IntLit 1) (IntLit 2))"""
+  doAssert lispRepr2((1, 2, 3.0)) == """(TupleConstr (IntLit 1) (IntLit 2) (FloatLit 3.0))"""
+  doAssert lispRepr2((1)) == """(Par (IntLit 1))"""
+  doAssert lispRepr2((1+2)) == """(Par (Infix (Ident "+") (IntLit 1) (IntLit 2)))"""
+
+block: # repr
+  macro repr2(a: untyped): string = newLit a.repr
+
+  doAssert repr2(()) == "()"
+  doAssert repr2((a: 1)) == "(a: 1)"
+  doAssert repr2((a: 1, b: 2)) == "(a: 1, b: 2)"
+  doAssert repr2((1,)) == "(1,)"
+  doAssert repr2((1, 2)) == "(1, 2)"
+  doAssert repr2((1, 2, 3.0)) == "(1, 2, 3.0)"
+  doAssert repr2((1)) == "(1)"
+  doAssert repr2((1+2)) == "(1 + 2)"
+
+block: # treeRepr
+  macro treeRepr2(a: untyped): string = newLit a.treeRepr
+  macro treeRepr3(a: typed): string = newLit a.treeRepr
+
+  doAssert treeRepr2(1+1 == 2) == """
+Infix
+  Ident "=="
+  Infix
+    Ident "+"
+    IntLit 1
+    IntLit 1
+  IntLit 2"""
+
+  proc baz() = discard
+  proc baz(a: int) = discard
+  proc baz(a: float) = discard
+
+  doAssert treeRepr3(baz()) == """
+Call
+  Sym "baz""""
+
+  let a = treeRepr3(block:
+    proc bar(a: auto) = baz())
+  doAssert a == """
+BlockStmt
+  Empty
+  ProcDef
+    Sym "bar"
+    Empty
+    GenericParams
+      Sym "a:type"
+    FormalParams
+      Empty
+      IdentDefs
+        Sym "a"
+        Sym "auto"
+        Empty
+    Empty
+    Bracket
+      Empty
+      Empty
+    StmtList
+      Call
+        OpenSymChoice 3 "baz""""
diff --git a/tests/macros/tdumpast2.nim b/tests/macros/tdumpast2.nim
index 6b694fa77..c4c591b2a 100644
--- a/tests/macros/tdumpast2.nim
+++ b/tests/macros/tdumpast2.nim
@@ -21,7 +21,7 @@ proc dumpit(n: NimNode): string {.compileTime.} =
       add(result, dumpit(n[j]))
   add(result, ")")
 
-macro dumpAST(n: stmt): stmt {.immediate.} =
+macro dumpAST(n): untyped =
   # dump AST as a side-effect and return the inner node
   let n = callsite()
   echo dumpit(n)
diff --git a/tests/macros/tdumpastgen.nim b/tests/macros/tdumpastgen.nim
new file mode 100644
index 000000000..0e0581f6a
--- /dev/null
+++ b/tests/macros/tdumpastgen.nim
@@ -0,0 +1,45 @@
+discard """
+nimout: '''nnkStmtList.newTree(
+  nnkVarSection.newTree(
+    nnkIdentDefs.newTree(
+      newIdentNode("x"),
+      newEmptyNode(),
+      nnkCall.newTree(
+        nnkDotExpr.newTree(
+          newIdentNode("baz"),
+          newIdentNode("create")
+        ),
+        newLit(56)
+      )
+    )
+  ),
+  nnkProcDef.newTree(
+    newIdentNode("foo"),
+    newEmptyNode(),
+    newEmptyNode(),
+    nnkFormalParams.newTree(
+      newEmptyNode()
+    ),
+    newEmptyNode(),
+    newEmptyNode(),
+    nnkStmtList.newTree(
+      newCommentStmtNode("This is a docstring"),
+      nnkCommand.newTree(
+        newIdentNode("echo"),
+        newLit("bar")
+      )
+    )
+  )
+)'''
+"""
+
+# disabled; can't work as the output is done by the compiler
+
+import macros
+
+dumpAstGen:
+  var x = baz.create(56)
+
+  proc foo() =
+    ## This is a docstring
+    echo "bar"
diff --git a/tests/macros/tdumptree.nim b/tests/macros/tdumptree.nim
index e5160b7ba..f540306c4 100644
--- a/tests/macros/tdumptree.nim
+++ b/tests/macros/tdumptree.nim
@@ -1,13 +1,14 @@
 discard """
-msg: '''StmtList
+nimout: '''
+StmtList
   VarSection
     IdentDefs
-      Ident !"x"
-      nil
+      Ident "x"
+      Empty
       Call
         DotExpr
-          Ident !"foo"
-          Ident !"create"
+          Ident "foo"
+          Ident "create"
         IntLit 56'''
 """
 
diff --git a/tests/macros/tescape_var_into_quotedo_as_const.nim b/tests/macros/tescape_var_into_quotedo_as_const.nim
new file mode 100644
index 000000000..1ed93f012
--- /dev/null
+++ b/tests/macros/tescape_var_into_quotedo_as_const.nim
@@ -0,0 +1,36 @@
+discard """
+  output: '''ok'''
+"""
+# bug #9864
+import macros, tables
+
+proc bar(shOpt: Table[string, int]) = discard
+
+macro dispatchGen(): untyped =
+  var shOpt = initTable[string, int]()
+  shOpt["foo"] = 10
+  result = quote do:
+     bar(`shOpt`)
+
+dispatchGen()
+
+type
+  Foo = object
+    data: seq[int]
+
+proc barB(a: Foo) = discard
+
+proc shOptB(): auto =
+  var shOpt: Foo
+  shOpt.data.setLen 1 # fails
+  shOpt
+
+macro dispatchGenB(): untyped =
+  var shOpt = shOptB() # fails
+
+  result = quote do:
+     barB(`shOpt`)
+
+dispatchGenB()
+
+echo "ok"
diff --git a/tests/macros/texpectIdent1.nim b/tests/macros/texpectIdent1.nim
new file mode 100644
index 000000000..26e52afb5
--- /dev/null
+++ b/tests/macros/texpectIdent1.nim
@@ -0,0 +1,18 @@
+discard """
+errormsg: "Expected identifier to be `foo` here"
+line: 18
+"""
+
+import macros
+
+macro testUntyped(arg: untyped): void =
+  arg.expectKind nnkStmtList
+  arg.expectLen 2
+  arg[0].expectKind nnkCall
+  arg[0][0].expectIdent "foo"  # must pass
+  arg[1].expectKind nnkCall
+  arg[1][0].expectIdent "foo"  # must fail
+
+testUntyped:
+  foo(123)
+  bar(321)
diff --git a/tests/macros/texpectIdent2.nim b/tests/macros/texpectIdent2.nim
new file mode 100644
index 000000000..887a6ddc3
--- /dev/null
+++ b/tests/macros/texpectIdent2.nim
@@ -0,0 +1,24 @@
+discard """
+errormsg: "Expected identifier to be `foo` here"
+line: 24
+"""
+
+import macros
+
+macro testTyped(arg: typed): void =
+  arg.expectKind nnkStmtList
+  arg.expectLen 2
+  arg[0].expectKind nnkCall
+  arg[0][0].expectIdent "foo"  # must pass
+  arg[1].expectKind nnkCall
+  arg[1][0].expectIdent "foo"  # must fail
+
+proc foo(arg: int) =
+  discard
+
+proc bar(arg: int) =
+  discard
+
+testTyped:
+  foo(123)
+  bar(321)
diff --git a/tests/macros/texprcolonexpr.nim b/tests/macros/texprcolonexpr.nim
deleted file mode 100644
index 3b2c86b77..000000000
--- a/tests/macros/texprcolonexpr.nim
+++ /dev/null
@@ -1,19 +0,0 @@
-discard """
-  msg: '''
-Infix
-  Ident !"=>"
-  Call
-    Ident !"name"
-    Ident !"a"
-    ExprColonExpr
-      Ident !"b"
-      Ident !"cint"
-  NilLit nil
-'''
-"""
-import macros
-
-macro def(x: stmt): stmt {.immediate.} =
-  echo treeRepr(x)
-
-def name(a, b:cint) => nil
diff --git a/tests/macros/tfail_parse.nim b/tests/macros/tfail_parse.nim
new file mode 100644
index 000000000..1925f2b69
--- /dev/null
+++ b/tests/macros/tfail_parse.nim
@@ -0,0 +1,15 @@
+discard """
+action: "reject"
+cmd: "nim check $file"
+errormsg: "expected expression, but got multiple statements [ValueError]"
+file: "macros.nim"
+"""
+
+import macros
+static:
+  discard parseStmt("'")
+  discard parseExpr("'")
+  discard parseExpr("""
+proc foo()
+proc foo() = discard
+""")
diff --git a/tests/macros/tforloop_macro1.nim b/tests/macros/tforloop_macro1.nim
new file mode 100644
index 000000000..a8f45c7ac
--- /dev/null
+++ b/tests/macros/tforloop_macro1.nim
@@ -0,0 +1,44 @@
+discard """
+  output: '''0 1
+1 2
+2 3
+0 1
+1 2
+2 3
+0 1
+1 2
+2 3
+3 5'''
+"""
+
+import macros
+
+macro mymacro(): untyped =
+  result = newLit([1, 2, 3])
+
+for a, b in mymacro():
+  echo a, " ", b
+
+macro enumerate(x: ForLoopStmt): untyped =
+  expectKind x, nnkForStmt
+  # we strip off the first for loop variable and use
+  # it as an integer counter:
+  result = newStmtList()
+  result.add newVarStmt(x[0], newLit(0))
+  var body = x[^1]
+  if body.kind != nnkStmtList:
+    body = newTree(nnkStmtList, body)
+  body.add newCall(bindSym"inc", x[0])
+  var newFor = newTree(nnkForStmt)
+  for i in 1..x.len-3:
+    newFor.add x[i]
+  # transform enumerate(X) to 'X'
+  newFor.add x[^2][1]
+  newFor.add body
+  result.add newFor
+
+for a, b in enumerate(items([1, 2, 3])):
+  echo a, " ", b
+
+for a2, b2 in enumerate([1, 2, 3, 5]):
+  echo a2, " ", b2
diff --git a/tests/macros/tgentemplates.nim b/tests/macros/tgentemplates.nim
deleted file mode 100644
index 764b94bc7..000000000
--- a/tests/macros/tgentemplates.nim
+++ /dev/null
@@ -1,35 +0,0 @@
-# bug #1140
-
-import parseutils, macros
-
-proc parse_until_symbol(node: NimNode, value: string, index: var int): bool {.compiletime.} =
-    var splitValue: string
-    var read = value.parseUntil(splitValue, '$', index)
-
-    # when false:
-    if false:
-        var identifier: string
-        read = value.parseWhile(identifier, {}, index)
-        node.add newCall("add", ident("result"), newCall("$", ident(identifier)))
-
-    if splitValue.len > 0:
-        node.insert node.len, newCall("add", ident("result"), newStrLitNode(splitValue))
-
-proc parse_template(node: NimNode, value: string) {.compiletime.} =
-    var index = 0
-    while index < value.len and
-        parse_until_symbol(node, value, index): discard
-
-macro tmpli*(body: expr): stmt =
-    result = newStmtList()
-    result.add parseExpr("result = \"\"")
-    result.parse_template body[1].strVal
-
-
-proc actual: string = tmpli html"""
-    <p>Test!</p>
-    """
-
-proc another: string = tmpli html"""
-    <p>what</p>
-    """
diff --git a/tests/macros/tgetimpl.nim b/tests/macros/tgetimpl.nim
index d38492934..ab33131b0 100644
--- a/tests/macros/tgetimpl.nim
+++ b/tests/macros/tgetimpl.nim
@@ -1,6 +1,7 @@
 discard """
-  msg: '''"muhaha"
+  nimout: '''foo = "muhaha"
 proc poo(x, y: int) =
+  let y = x
   echo ["poo"]'''
 """
 
@@ -10,11 +11,93 @@ const
   foo = "muhaha"
 
 proc poo(x, y: int) =
+  let y = x
   echo "poo"
 
 macro m(x: typed): untyped =
-  echo repr x.symbol.getImpl
-  result = x
+  echo repr x.getImpl
 
-discard m foo
-discard m poo
+m(foo)
+m(poo)
+
+#------------
+
+macro checkOwner(x: typed, check_id: static[int]): untyped =
+  let sym = case check_id:
+    of 0: x
+    of 1: x.getImpl.body[0][0][0]
+    of 2: x.getImpl.body[0][0][^1]
+    of 3: x.getImpl.body[1][0]
+    else: x
+  result = newStrLitNode($sym.owner.symKind)
+
+macro isSameOwner(x, y: typed): untyped =
+  result =
+    if x.owner == y.owner: bindSym"true"
+    else: bindSym"false"
+
+
+static:
+  doAssert checkOwner(foo, 0) == "nskModule"
+  doAssert checkOwner(poo, 0) == "nskModule"
+  doAssert checkOwner(poo, 1) == "nskProc"
+  doAssert checkOwner(poo, 2) == "nskProc"
+  doAssert checkOwner(poo, 3) == "nskModule"
+  doAssert isSameOwner(foo, poo)
+  proc wrappedScope() =
+    proc dummyproc() = discard
+    doAssert isSameOwner(foo, dummyproc) == false
+    doAssert isSameOwner(poo, dummyproc) == false
+  wrappedScope()
+
+macro check_gen_proc(ex: typed): (bool, bool) =
+  let lenChoice = bindsym"len"
+  var is_equal = false 
+  var is_instance_of = false 
+  for child in lenChoice:
+    if not is_equal:
+      is_equal = ex[0] == child
+    if not is_instance_of:
+      is_instance_of = isInstantiationOf(ex[0], child)
+         
+  result = nnkTupleConstr.newTree(newLit(is_equal), newLit(is_instance_of))
+
+# check that len(seq[int]) is not equal to bindSym"len", but is instance of it
+let a = @[1,2,3]
+assert: check_gen_proc(len(a)) == (false, true)
+
+
+#---------------------------------------------------------------
+# issue #16110
+
+macro check(x: type): untyped =
+  let z = getType(x)
+  let y = getImpl(z[1])  
+  var sym = y[0]
+  if sym.kind == nnkPragmaExpr: sym = sym[0]
+  if sym.kind == nnkPostfix: sym = sym[1]
+  expectKind(z[1], nnkSym)
+  expectKind(sym, nnkSym)
+  expectKind(y[2], nnkObjectTy)
+  doAssert(sym == z[1])
+
+type
+  TirePtr = ptr object
+    code: int
+
+  TireRef* = ref object
+    code: int
+
+  TireRef2* {.inheritable.} = ref object
+    code: int
+
+  TireRef3* {.inheritable.} = object
+    code: int
+
+var z1: TirePtr
+check(typeof(z1[]))
+var z2: TireRef
+check(typeof(z2[]))
+var z3: TireRef2
+check(typeof(z3[]))
+check(TireRef3)
diff --git a/tests/macros/tgetraiseslist.nim b/tests/macros/tgetraiseslist.nim
new file mode 100644
index 000000000..79694a66f
--- /dev/null
+++ b/tests/macros/tgetraiseslist.nim
@@ -0,0 +1,29 @@
+discard """
+  nimout: '''##[ValueError, Gen[string]]##
+%%[RootEffect]%%
+true true'''
+"""
+
+import macros
+import std / effecttraits
+
+type
+  Gen[T] = object of CatchableError
+    x: T
+
+macro m(call: typed): untyped =
+  echo "##", repr getRaisesList(call[0]), "##"
+  echo "%%", repr getTagsList(call[0]), "%%"
+  echo isGcSafe(call[0]), " ", hasNoSideEffects(call[0])
+  result = call
+
+proc gutenTag() {.tags: RootEffect.} = discard
+
+proc r(inp: int) =
+  if inp == 0:
+    raise newException(ValueError, "bah")
+  elif inp == 1:
+    raise newException(Gen[string], "bahB")
+  gutenTag()
+
+m r(2)
diff --git a/tests/macros/tgettype.nim b/tests/macros/tgettype.nim
index 0eab6c0a0..d91efe1fe 100644
--- a/tests/macros/tgettype.nim
+++ b/tests/macros/tgettype.nim
@@ -1,20 +1,85 @@
-discard """
-msg: '''ObjectTy(Sym(Model), RecList(Sym(name), Sym(password)))
-BracketExpr(Sym(typeDesc), Sym(User))'''
-"""
-import strutils, macros
-
-type
-  Model = object of RootObj
-  User = object of Model
-    name : string
-    password : string
-
-macro testUser: expr =
-  return newLit(User.getType.lispRepr)
-
-macro testGeneric(T: typedesc[Model]): expr =
-  return newLit(T.getType.lispRepr)
-
-echo testUser
-echo User.testGeneric
+import std/macros
+import stdtest/testutils
+
+# getType
+
+block:
+  type
+    Model = object of RootObj
+    User = object of Model
+      name : string
+      password : string
+
+  macro testUser: string =
+    result = newLit(User.getType.lispRepr)
+
+  macro testGeneric(T: typedesc[Model]): string=
+    result = newLit(T.getType.lispRepr)
+
+  doAssert testUser == """(ObjectTy (Empty) (Sym "Model") (RecList (Sym "name") (Sym "password")))"""
+  doAssert User.testGeneric == """(BracketExpr (Sym "typeDesc") (Sym "User"))"""
+
+  macro assertVoid(e: typed): untyped =
+    assert(getTypeInst(e).typeKind == ntyVoid)
+
+  proc voidProc() = discard
+
+  assertVoid voidProc()
+
+block:
+  # refs #18220; not an actual solution (yet) but at least shows what's currently
+  # possible
+
+  type Callable1[R, T, U] = concept fn
+    fn(default(T)) is R
+    fn is U
+
+  # note that typetraits.arity doesn't work
+  macro arity(a: typed): int =
+    # number of params
+    # this is not production code!
+    let a2 = a.getType[1] # this used to crash nim, with: `vmdeps.nim(292, 25) `false``
+    newLit a2.len - 1
+
+  type Callable2[R, T, U] = concept fn
+    fn(default(T)) is R
+    fn is U
+    arity(U) == 2
+
+  proc map1[T, R, U](a: T, fn: Callable1[R, T, U]): R =
+    let fn = U(fn)
+      # `cast[U](fn)` would also work;
+      # this is currently needed otherwise, sigmatch errors with:
+      # Error: attempting to call routine: 'fn'
+      #  found 'fn' [param declared in tgettype.nim(53, 28)]
+      # this can be fixed in future work
+    fn(a)
+
+  proc map2[T, R, U](a: T, fn: Callable2[R, T, U]): R =
+    let fn = U(fn)
+    fn(a)
+
+  proc fn1(a: int, a2 = 'x'): string = $(a, a2, "fn1")
+  proc fn2(a: int, a2 = "zoo"): string = $(a, a2, "fn2")
+  proc fn3(a: int, a2 = "zoo2"): string = $(a, a2, "fn3")
+  proc fn4(a: int): string {.inline.} = $(a, "fn4")
+  proc fn5(a: int): string = $(a, "fn5")
+
+  assertAll:
+    # Callable1
+    1.map1(fn1) == """(1, 'x', "fn1")"""
+    1.map1(fn2) == """(1, "zoo", "fn2")"""
+    1.map1(fn3) == """(1, "zoo", "fn3")"""
+      # fn3's optional param is not honored, because fn3 and fn2 yield same
+      # generic instantiation; this is a caveat with this approach
+      # There are several possible ways to improve things in future work.
+    1.map1(fn4) == """(1, "fn4")"""
+    1.map1(fn5) == """(1, "fn5")"""
+
+    # Callable2; prevents passing procs with optional params to avoid above
+    # mentioned caveat, but more restrictive
+    not compiles(1.map2(fn1))
+    not compiles(1.map2(fn2))
+    not compiles(1.map2(fn3))
+    1.map2(fn4) == """(1, "fn4")"""
+    1.map2(fn5) == """(1, "fn5")"""
diff --git a/tests/macros/tgettype2.nim b/tests/macros/tgettype2.nim
new file mode 100644
index 000000000..c579cf6ff
--- /dev/null
+++ b/tests/macros/tgettype2.nim
@@ -0,0 +1,99 @@
+discard """
+output: '''
+############
+#### gt ####
+############
+gt(Foo):	typeDesc[Foo]
+gt(Bar):	typeDesc[Bar]
+gt(Baz):	typeDesc[int]
+gt(foo):	distinct[int]
+gt(bar):	distinct[int]
+gt(baz):	int, int
+gt(v):	seq[int]
+gt(vv):	seq[float]
+gt(t):	distinct[tuple[int, int]]
+gt(tt):	distinct[tuple[float, float]]
+gt(s):	distinct[tuple[int, int]]
+#############
+#### gt2 ####
+#############
+gt2(Foo): 	Foo
+gt2(Bar): 	Bar
+gt2(Baz): 	Baz
+gt2(foo): 	Foo
+gt2(bar): 	Bar
+gt2(baz): 	Baz
+gt2(v): 	seq[int]
+gt2(vv): 	seq[float]
+gt2(t): 	MyType[system.int]
+gt2(tt): 	MyType[system.float]
+gt2(s): 	MySimpleType
+'''
+"""
+
+import macros, typetraits
+
+type Foo = distinct int
+type Bar = distinct int
+type Baz = int
+
+let foo = 0.Foo
+let bar = 1.Bar
+let baz = 2.Baz
+
+type MyType[T] = distinct tuple[a,b:T]
+type MySimpleType = distinct tuple[a,b: int]
+
+var v: seq[int]
+var vv: seq[float]
+var t: MyType[int]
+var tt: MyType[float]
+var s: MySimpleType
+
+echo "############"
+echo "#### gt ####"
+echo "############"
+
+macro gt(a: typed): string =
+  let b = a.getType
+  var str = "gt(" & $a & "):\t" & b.repr
+  if b.kind == nnkSym: # bad predicat to check weather the type has an implementation
+    str = str & ", " & b.getType.repr  # append the implementation to the result
+  result = newLit(str)
+
+echo gt(Foo) # typeDesc[Foo]
+echo gt(Bar) # typeDesc[Bar]
+echo gt(Baz) # typeDesc[int]     shouldn't it be typeDesc[Baz]?
+echo gt(foo) # distinct[int]     I would prefer Foo, distinct[int]
+echo gt(bar) # distinct[int]     I would prefer Bar, distinct[int]
+echo gt(baz) # int, int          I would prefer Baz, int
+
+echo gt(v)   # seq[int], ok
+echo gt(vv)  # seq[float], ok
+echo gt(t)   # MyType, distinct[tuple[int, int]]      I would prefer MyType[int],   distinct[tuple[int, int]]
+echo gt(tt)  # MyType, distinct[tuple[float, float]]  I would prefer MyType[float], distinct[tuple[int, int]]
+echo gt(s)   # distinct[tuple[int, int]]              I would prefer MySimpleType, distinct[tuple[int,int]]
+
+echo "#############"
+echo "#### gt2 ####"
+echo "#############"
+
+# get type name via typetraits
+
+macro gt2(a: typed): string =
+  let prefix = "gt2(" & $a & "): \t"
+  result = quote do:
+    `prefix` & `a`.type.name
+
+echo gt2(Foo) # Foo  shouldn't this be typeDesc[Foo] ?
+echo gt2(Bar) # Bar  shouldn't this be typeDesc[Bar] ?
+echo gt2(Baz) # Baz  shouldn't this be typeDesc[Baz] ?
+echo gt2(foo) # Foo
+echo gt2(bar) # Bar
+echo gt2(baz) # Baz
+
+echo gt2(v)   # seq[int]
+echo gt2(vv)  # seq[float]
+echo gt2(t)   # MyType[system.int]      why is it system.int and not just int like in seq?
+echo gt2(tt)  # MyType[system.float]    why is it system.float and not just float like in seq?
+echo gt2(s)   # MySimpleType
diff --git a/tests/macros/tgettype3.nim b/tests/macros/tgettype3.nim
new file mode 100644
index 000000000..786d09d8b
--- /dev/null
+++ b/tests/macros/tgettype3.nim
@@ -0,0 +1,48 @@
+discard """
+  output: "vec2"
+"""
+# bug #5131
+
+import macros
+
+type
+    vecBase[I: static[int], T] = distinct array[I, T]
+    vec2* = vecBase[2, float32]
+
+proc isRange(n: NimNode, rangeLen: int = -1): bool =
+    if n.kind == nnkBracketExpr and $(n[0]) == "range":
+        if rangeLen == -1:
+            result = true
+        elif n[2].intVal - n[1].intVal + 1 == rangeLen:
+            result = true
+
+proc getTypeName(t: NimNode, skipVar = false): string =
+    case t.kind
+    of nnkBracketExpr:
+        if $(t[0]) == "array" and t[1].isRange(2) and $(t[2]) == "float32":
+            result = "vec2"
+        elif $(t[0]) == "array" and t[1].isRange(3) and $(t[2]) == "float32":
+            result = "vec3"
+        elif $(t[0]) == "array" and t[1].isRange(4) and $(t[2]) == "float32":
+            result = "vec4"
+        elif $(t[0]) == "distinct":
+            result = getTypeName(t[1], skipVar)
+    of nnkSym:
+        case $t
+        of "vecBase": result = getTypeName(getType(t), skipVar)
+        of "float32": result = "float"
+        else:
+            result = $t
+    of nnkVarTy:
+        result = getTypeName(t[0])
+        if not skipVar:
+            result = "inout " & result
+    else:
+        echo "UNKNOWN TYPE: ", treeRepr(t)
+        assert(false, "Unknown type")
+
+macro typeName(t: typed): string =
+    result = newLit(getTypeName(getType(t)))
+
+var tt : vec2
+echo typeName(tt)
diff --git a/tests/macros/tgettypeinst.nim b/tests/macros/tgettypeinst.nim
index 22e03a119..e722f14aa 100644
--- a/tests/macros/tgettypeinst.nim
+++ b/tests/macros/tgettypeinst.nim
@@ -1,7 +1,7 @@
 discard """
 """
 
-import macros, strUtils
+import macros
 
 proc symToIdent(x: NimNode): NimNode =
   case x.kind:
@@ -21,49 +21,69 @@ proc symToIdent(x: NimNode): NimNode =
       for c in x:
         result.add symToIdent(c)
 
-macro testX(x,inst0: typed; recurse: static[bool]; implX: stmt): typed =
+# check getTypeInst and getTypeImpl for given symbol x
+macro testX(x,inst0: typed; recurse: static[bool]; implX: typed) =
+  # check that getTypeInst(x) equals inst0
   let inst = x.getTypeInst
-  let impl = x.getTypeImpl
-  let inst0r = inst0.symToIdent.treeRepr
   let instr = inst.symToIdent.treeRepr
-  #echo inst0r
-  #echo instr
-  doAssert(instr == inst0r)
+  let inst0r = inst0.symToIdent.treeRepr
+  if instr != inst0r:
+    echo "instr:\n", instr
+    echo "inst0r:\n", inst0r
+    doAssert(instr == inst0r)
+
+  # check that getTypeImpl(x) is correct
+  #  if implX is nil then compare to inst0
+  #  else we expect implX to be a type definition
+  #       and we extract the implementation from that
+  let impl = x.getTypeImpl
   var impl0 =
     if implX.kind == nnkNilLit: inst0
     else: implX[0][2]
-  let impl0r = impl0.symToIdent.treerepr
   let implr = impl.symToIdent.treerepr
-  #echo impl0r
-  #echo implr
-  doAssert(implr == impl0r)
-  template echoString(s:string) = echo s.replace("\n","\n  ")
+  let impl0r = impl0.symToIdent.treerepr
+  if implr != impl0r:
+    echo "implr:\n", implr
+    echo "impl0r:\n", impl0r
+    doAssert(implr == impl0r)
+
   result = newStmtList()
+  #template echoString(s: string) = echo s.replace("\n","\n  ")
   #result.add getAst(echoString("  " & inst0.repr))
   #result.add getAst(echoString("  " & inst.repr))
   #result.add getAst(echoString("  " & impl0.repr))
   #result.add getAst(echoString("  " & impl.repr))
+
   if recurse:
-    template testDecl(n, m :typed) =
+    # now test using a newly formed variable of type getTypeInst(x)
+    template testDecl(n,m: typed) =
       testV(n, false):
         type _ = m
     result.add getAst(testDecl(inst.symToIdent, impl.symToIdent))
 
+# test with a variable (instance) of type
 template testV(inst, recurse, impl) =
   block:
     #echo "testV(" & astToStr(inst) & ", " & $recurse & "):" & astToStr(impl)
     var x: inst
     testX(x, inst, recurse, impl)
-template testT(inst, recurse) =
+
+# test with a newly created typedesc (myType)
+# using the passed type as the implementation
+template testT(impl, recurse) =
   block:
-    type myType = inst
+    type myType = impl
     testV(myType, recurse):
-      type _ = inst
+      type _ = impl
 
+# test a built-in type whose instance is equal to the implementation
 template test(inst) =
   testT(inst, false)
   testV(inst, true, nil)
-template test(inst, impl) = testV(inst, true, impl)
+
+# test a custom type with provided implementation
+template test(inst, impl) =
+  testV(inst, true, impl)
 
 type
   Model = object of RootObj
@@ -87,9 +107,24 @@ type
     value:T
   Foo[N:static[int],T] = object
   Bar[N:static[int],T] = object
-    #baz:Foo[N+1,GenericObject[T]]
+    #baz:Foo[N+1,GenericObject[T]]  # currently fails
     baz:Foo[N,GenericObject[T]]
 
+  Generic[T] = seq[int]
+  Concrete = Generic[int]
+
+  Generic2[T1, T2] = seq[T1]
+  Concrete2 = Generic2[int, float]
+
+  Alias1 = float
+  Alias2 = Concrete
+  Alias3 = Concrete2
+
+  Vec[N: static[int],T] = object
+    arr: array[N,T]
+  Vec4[T] = Vec[4,T]
+
+
 test(bool)
 test(char)
 test(int)
@@ -97,13 +132,17 @@ test(float)
 test(ptr int)
 test(ref int)
 test(array[1..10,Bar[2,Foo[3,float]]])
+test(array[MyEnum,Bar[2,Foo[3,float]]])
 test(distinct Bar[2,Foo[3,float]])
 test(tuple[a:int,b:Foo[-1,float]])
-#test(MyEnum):
-#  type _ = enum
-#    valueA, valueB, valueC
-test(set[MyEnum])
 test(seq[int])
+test(set[MyEnum])
+test(proc (a: int, b: Foo[2,float]))
+test(proc (a: int, b: Foo[2,float]): Bar[3,int])
+
+test(MyEnum):
+  type _ = enum
+    valueA, valueB, valueC
 test(Bar[2,Foo[3,float]]):
   type _ = object
     baz: Foo[2, GenericObject[Foo[3, float]]]
@@ -118,5 +157,58 @@ test(Tree):
     value: int
     left: ref Tree
     right: ref Tree
-test(proc (a: int, b: Foo[2,float]))
-test(proc (a: int, b: Foo[2,float]): Bar[3,int])
+test(Concrete):
+  type _ = seq[int]
+test(Generic[int]):
+  type _ = seq[int]
+test(Generic[float]):
+  type _ = seq[int]
+test(Concrete2):
+  type _ = seq[int]
+test(Generic2[int,float]):
+  type _ = seq[int]
+test(Alias1):
+  type _ = float
+test(Alias2):
+  type _ = seq[int]
+test(Alias3):
+  type _ = seq[int]
+test(Vec[4,float32]):
+  type _ = object
+    arr: array[0..3,float32]
+test(Vec4[float32]):
+  type _ = object
+    arr: array[0..3,float32]
+
+# bug #4862
+static:
+  discard typedesc[(int, int)].getTypeImpl
+
+# custom pragmas
+template myAttr() {.pragma.}
+template myAttr2() {.pragma.}
+template myAttr3() {.pragma.}
+template serializationKey(key: string) {.pragma.}
+
+type
+  MyObj {.packed,myAttr,serializationKey: "one".} = object
+    myField {.myAttr2,serializationKey: "two".}: int
+    myField2 {.myAttr3,serializationKey: "three".}: float
+
+# field pragmas not currently supported
+test(MyObj):
+  type
+    _ {.packed,myAttr,serializationKey: "one".} = object
+      myField: int
+      myField2: float
+
+block t9600:
+  type
+    Apple = ref object of RootObj
+
+  macro mixer(x: typed): untyped =
+    let w = getType(x)
+    let v = getTypeImpl(w[1])
+
+  var z: Apple
+  mixer(z)
diff --git a/tests/macros/tgettypeinst7737.nim b/tests/macros/tgettypeinst7737.nim
new file mode 100644
index 000000000..e49f82562
--- /dev/null
+++ b/tests/macros/tgettypeinst7737.nim
@@ -0,0 +1,61 @@
+discard """
+  nimout: '''
+seq[int]
+CustomSeq[int]
+'''
+"""
+
+import macros, typetraits, sequtils
+
+block: # issue #7737 original
+  type
+    CustomSeq[T] = object
+      data: seq[T]
+
+  proc getSubType(T: NimNode): NimNode =
+    echo getTypeInst(T).repr
+    result = getTypeInst(T)[1]
+
+  macro typed_helper(x: varargs[typed]): untyped =
+    let foo = getSubType(x[0])
+    result = quote do: discard
+
+  macro untyped_heavylifting(x: varargs[untyped]): untyped =
+    var containers = nnkArgList.newTree()
+    for arg in x:
+      case arg.kind:
+      of nnkInfix:
+        if eqIdent(arg[0], "in"):
+          containers.add arg[2]
+      else:
+        discard
+    result = quote do:
+      typed_helper(`containers`)
+  var a, b, c: seq[int]
+  untyped_heavylifting z in c, x in a, y in b:
+    discard
+  ## The following gives me CustomSeq instead
+  ## of CustomSeq[int] in getTypeInst
+  var u, v, w: CustomSeq[int]
+  untyped_heavylifting z in u, x in v, y in w:
+    discard
+
+block: # issue #7737 comment
+  type
+    CustomSeq[T] = object
+      data: seq[T]
+  # when using just one argument, `foo` and `bar` should be exactly
+  # identical.
+  macro foo(arg: typed): string =
+    result = newLit(arg.getTypeInst.repr)
+  macro bar(args: varargs[typed]): untyped =
+    result = newTree(nnkBracket)
+    for arg in args:
+      result.add newLit(arg.getTypeInst.repr)
+  var
+    a: seq[int]
+    b: CustomSeq[int]
+  doAssert foo(a) == "seq[int]"
+  doAssert bar(a) == ["seq[int]"]
+  doAssert foo(b) == "CustomSeq[int]"
+  doAssert bar(b) == ["CustomSeq[int]"]
diff --git a/tests/macros/tidgen.nim b/tests/macros/tidgen.nim
deleted file mode 100644
index 2fe9e0f82..000000000
--- a/tests/macros/tidgen.nim
+++ /dev/null
@@ -1,19 +0,0 @@
-discard """
-  output: "3 4"
-"""
-
-import macros
-
-# Test compile-time state in same module
-
-var gid {.compileTime.} = 3
-
-macro genId(): expr =
-  result = newIntLitNode(gid)
-  inc gid
-
-proc Id1(): int {.compileTime.} = return genId()
-proc Id2(): int {.compileTime.} = return genId()
-
-echo Id1(), " ", Id2()
-
diff --git a/tests/macros/tincremental.nim b/tests/macros/tincremental.nim
new file mode 100644
index 000000000..401d6f3f8
--- /dev/null
+++ b/tests/macros/tincremental.nim
@@ -0,0 +1,150 @@
+discard """
+  output: '''heavy_calc_impl is called
+sub_calc1_impl is called
+sub_calc2_impl is called
+** no changes recompute effectively
+** change one input and recompute effectively
+heavy_calc_impl is called
+sub_calc2_impl is called'''
+"""
+
+# sample incremental
+
+import tables
+import macros
+
+var inputs = initTable[string, float]() 
+var cache = initTable[string, float]()
+var dep_tree {.compileTime.} = initTable[string, string]()
+
+macro symHash(s: typed{nkSym}): string = 
+  result = newStrLitNode(symBodyHash(s))
+
+#######################################################################################
+
+template graph_node(key: string) {.pragma.}
+
+proc tag(n: NimNode): NimNode = 
+  ## returns graph node unique name of a function or nil if it is not a graph node
+  expectKind(n, {nnkProcDef, nnkFuncDef})
+  for p in n.pragma:
+    if p.len > 0 and p[0] == bindSym"graph_node":
+      return p[1]
+  return nil 
+
+macro graph_node_key(n: typed{nkSym}): untyped =
+  result = newStrLitNode(n.symBodyHash)
+
+macro graph_discovery(n: typed{nkSym}): untyped =
+  # discovers graph dependency tree and updated dep_tree global var
+  let mytag = newStrLitNode(n.symBodyHash)
+  var visited: seq[NimNode]
+  proc discover(n: NimNode) = 
+    case n.kind:
+      of nnkNone..pred(nnkSym), succ(nnkSym)..nnkNilLit: discard
+      of nnkSym:
+        if n.symKind in {nskFunc, nskProc}:
+          if n notin visited:
+            visited.add n
+            let tag = n.getImpl.tag
+            if tag != nil:
+              dep_tree[tag.strVal] =  mytag.strVal
+            else:
+              discover(n.getImpl.body)
+      else:
+        for child in n:
+          discover(child)
+  discover(n.getImpl.body)
+  result = newEmptyNode()
+
+#######################################################################################
+
+macro incremental_input(key: static[string], n: untyped{nkFuncDef}): untyped =
+  # mark leaf nodes of the graph
+  template getInput(key) {.dirty.} =
+    {.noSideEffect.}:
+      inputs[key]
+  result = n
+  result.pragma = nnkPragma.newTree(nnkCall.newTree(bindSym"graph_node", newStrLitNode(key)))
+  result.body = getAst(getInput(key))
+
+macro incremental(n: untyped{nkFuncDef}): untyped =
+  ## incrementalize side effect free computation
+  ## wraps function into caching layer, mark caching function as a graph_node
+  ## injects dependency discovery between graph nodes
+  template cache_func_body(func_name, func_name_str, func_call) {.dirty.} =
+    {.noSideEffect.}: 
+      graph_discovery(func_name)
+      let key = graph_node_key(func_name)
+      if key in cache:
+        result = cache[key]
+      else:
+        echo func_name_str & " is called"
+        result = func_call
+        cache[key] = result
+
+  let func_name = n.name.strVal & "_impl"
+  let func_call = nnkCall.newTree(ident func_name)
+  for i in 1..<n.params.len:
+    func_call.add n.params[i][0]
+  let cache_func = n.copyNimTree
+  cache_func.body = getAst(cache_func_body(ident func_name, func_name, func_call))
+  cache_func.pragma = nnkPragma.newTree(newCall(bindSym"graph_node", 
+    newCall(bindSym"symHash", ident func_name)))
+  
+  n.name = ident(func_name)
+  result = nnkStmtList.newTree(n, cache_func)
+
+###########################################################################
+### Example
+###########################################################################
+
+func input1(): float {.incremental_input("a1").}
+
+func input2(): float {.incremental_input("a2").}
+
+func sub_calc1(a: float): float  {.incremental.} = 
+  a + input1()
+
+func sub_calc2(b: float): float  {.incremental.} = 
+  b + input2()
+
+func heavy_calc(a: float, b: float): float {.incremental.} = 
+  sub_calc1(a) + sub_calc2(b)
+
+###########################################################################
+## graph finalize and inputs
+###########################################################################
+
+macro finalize_dep_tree(): untyped = 
+  result = nnkTableConstr.newNimNode
+  for key, val in dep_tree:
+    result.add nnkExprColonExpr.newTree(newStrLitNode key, newStrLitNode val)
+  result = nnkCall.newTree(bindSym"toTable", result)
+
+const dep_tree_final = finalize_dep_tree()
+
+proc set_input(key: string, val: float) = 
+  ## set input value
+  ## all affected nodes of graph are invalidated
+  inputs[key] = val
+  var k = key
+  while k != "":
+    k = dep_tree_final.getOrDefault(k , "")
+    cache.del(k)
+
+###########################################################################
+## demo
+###########################################################################
+
+set_input("a1", 5)
+set_input("a2", 2)
+discard heavy_calc(5.0, 10.0)
+
+echo "** no changes recompute effectively"
+discard heavy_calc(5.0, 10.0)
+
+echo "** change one input and recompute effectively"
+
+set_input("a2", 10)
+discard heavy_calc(5.0, 10.0)
diff --git a/tests/macros/tinvalidtypesym.nim b/tests/macros/tinvalidtypesym.nim
new file mode 100644
index 000000000..af6f31d10
--- /dev/null
+++ b/tests/macros/tinvalidtypesym.nim
@@ -0,0 +1,14 @@
+discard """
+errormsg: "type expected, but symbol 'MyType' has no type."
+"""
+
+import macros
+
+macro foobar(name) =
+  let sym = genSym(nskType, "MyType")
+
+  result = quote do:
+    type
+      `name` = `sym`
+
+foobar(MyAlias)
diff --git a/tests/macros/tisexported.nim b/tests/macros/tisexported.nim
new file mode 100644
index 000000000..53766edf5
--- /dev/null
+++ b/tests/macros/tisexported.nim
@@ -0,0 +1,10 @@
+import macros
+
+proc t1* = discard
+proc t2 = discard
+
+macro check(p1: typed, p2: typed) =
+  doAssert isExported(p1) == true
+  doAssert isExported(p2) == false
+
+check t1, t2
diff --git a/tests/macros/tlexerex.nim b/tests/macros/tlexerex.nim
deleted file mode 100644
index d348a4bcc..000000000
--- a/tests/macros/tlexerex.nim
+++ /dev/null
@@ -1,16 +0,0 @@
-
-import macros
-
-macro match*(s: cstring|string; pos: int; sections: untyped): untyped =
-  for sec in sections.children:
-    expectKind sec, nnkOfBranch
-    expectLen sec, 2
-  result = newStmtList()
-
-when isMainModule:
-  var input = "the input"
-  var pos = 0
-  match input, pos:
-  of r"[a-zA-Z_]\w+": echo "an identifier"
-  of r"\d+": echo "an integer"
-  of r".": echo "something else"
diff --git a/tests/macros/tlocktypednode1.nim b/tests/macros/tlocktypednode1.nim
new file mode 100644
index 000000000..f760c7cf1
--- /dev/null
+++ b/tests/macros/tlocktypednode1.nim
@@ -0,0 +1,12 @@
+discard """
+errormsg: "typechecked nodes may not be modified"
+"""
+
+import macros
+
+macro doSomething(arg: typed): untyped =
+  echo arg.treeREpr
+  result = arg
+  result.add newCall(bindSym"echo", newLit(1))
+
+doSomething((echo(1); echo(2)))
diff --git a/tests/macros/tlocktypednode2.nim b/tests/macros/tlocktypednode2.nim
new file mode 100644
index 000000000..e921772b0
--- /dev/null
+++ b/tests/macros/tlocktypednode2.nim
@@ -0,0 +1,12 @@
+discard """
+errormsg: "typechecked nodes may not be modified"
+"""
+
+import macros
+
+macro doSomething(arg: typed): untyped =
+  echo arg.treeREpr
+  result = arg
+  result[0] = newCall(bindSym"echo", newLit(1))
+
+doSomething((echo(1); echo(2)))
diff --git a/tests/macros/tlocktypednode3.nim b/tests/macros/tlocktypednode3.nim
new file mode 100644
index 000000000..0eb9d4467
--- /dev/null
+++ b/tests/macros/tlocktypednode3.nim
@@ -0,0 +1,15 @@
+discard """
+errormsg: "typechecked nodes may not be modified"
+"""
+
+import macros
+
+macro doSomething(arg: typed): untyped =
+  echo arg.treeREpr
+  result = arg
+  result.add(
+    newCall(bindSym"echo", newLit(3)),
+    newCall(bindSym"echo", newLit(1))
+  )
+
+doSomething((echo(1); echo(2)))
diff --git a/tests/macros/tmacro1.nim b/tests/macros/tmacro1.nim
index 2dd5c31df..18bbeb53d 100644
--- a/tests/macros/tmacro1.nim
+++ b/tests/macros/tmacro1.nim
@@ -1,8 +1,6 @@
 import  macros
 
-from uri import `/`
-
-macro test*(a: stmt): stmt {.immediate.} =
+macro test*(a: untyped): untyped =
   var nodes: tuple[a, b: int]
   nodes.a = 4
   nodes[1] = 45
@@ -18,6 +16,104 @@ macro test*(a: stmt): stmt {.immediate.} =
   t.b = true
   t.z = 4.5
 
+
 test:
   "hi"
 
+
+template assertNot(arg: untyped): untyped =
+  assert(not(arg))
+
+
+proc foo(arg: int): void =
+  discard
+
+proc foo(arg: float): void =
+  discard
+
+static:
+  ## test eqIdent
+  let a = "abc_def"
+  let b = "abcDef"
+  let c = "AbcDef"
+  let d = nnkBracketExpr.newTree() # not an identifier at all
+
+  assert eqIdent(             a ,              b )
+  assert eqIdent(newIdentNode(a),              b )
+  assert eqIdent(             a , newIdentNode(b))
+  assert eqIdent(newIdentNode(a), newIdentNode(b))
+
+  assert eqIdent(               a ,                b )
+  assert eqIdent(genSym(nskLet, a),                b )
+  assert eqIdent(               a , genSym(nskLet, b))
+  assert eqIdent(genSym(nskLet, a), genSym(nskLet, b))
+
+  assert eqIdent(newIdentNode(  a), newIdentNode(  b))
+  assert eqIdent(genSym(nskLet, a), newIdentNode(  b))
+  assert eqIdent(newIdentNode(  a), genSym(nskLet, b))
+  assert eqIdent(genSym(nskLet, a), genSym(nskLet, b))
+
+  assertNot eqIdent(             c ,              b )
+  assertNot eqIdent(newIdentNode(c),              b )
+  assertNot eqIdent(             c , newIdentNode(b))
+  assertNot eqIdent(newIdentNode(c), newIdentNode(b))
+
+  assertNot eqIdent(               c ,                b )
+  assertNot eqIdent(genSym(nskLet, c),                b )
+  assertNot eqIdent(               c , genSym(nskLet, b))
+  assertNot eqIdent(genSym(nskLet, c), genSym(nskLet, b))
+
+  assertNot eqIdent(newIdentNode(  c), newIdentNode(  b))
+  assertNot eqIdent(genSym(nskLet, c), newIdentNode(  b))
+  assertNot eqIdent(newIdentNode(  c), genSym(nskLet, b))
+  assertNot eqIdent(genSym(nskLet, c), genSym(nskLet, b))
+
+  # eqIdent on non identifier at all
+  assertNot eqIdent(a,d)
+
+  # eqIdent on sym choice
+  let fooSym = bindSym"foo"
+  assert fooSym.kind in {nnkOpenSymChoice, nnkClosedSymChoice}
+  assert    fooSym.eqIdent("fOO")
+  assertNot fooSym.eqIdent("bar")
+
+  # eqIdent on exported and backtick quoted identifiers
+  let procName = ident("proc")
+  let quoted = nnkAccQuoted.newTree(procName)
+  let exported = nnkPostfix.newTree(ident"*", procName)
+  let exportedQuoted = nnkPostfix.newTree(ident"*", quoted)
+
+  let nodes = @[procName, quoted, exported, exportedQuoted]
+
+  for i in 0 ..< nodes.len:
+    for j in 0 ..< nodes.len:
+      doAssert eqIdent(nodes[i], nodes[j])
+
+  for node in nodes:
+    doAssert eqIdent(node, "proc")
+
+
+  var empty: NimNode
+  var myLit = newLit("str")
+
+  assert( (empty or myLit) == myLit )
+
+  empty = newEmptyNode()
+
+  assert( (empty or myLit) == myLit )
+
+  proc bottom(): NimNode =
+    quit("may not be evaluated")
+
+  assert( (myLit or bottom()) == myLit )
+
+type
+  Fruit = enum
+    apple
+    banana
+    orange
+
+macro foo(x: typed) =
+  doAssert Fruit(x.intVal) == banana
+
+foo(banana)
diff --git a/tests/macros/tmacro2.nim b/tests/macros/tmacro2.nim
index 17f312925..1ad63ec8c 100644
--- a/tests/macros/tmacro2.nim
+++ b/tests/macros/tmacro2.nim
@@ -12,7 +12,7 @@ proc testBlock(): string {.compileTime.} =
     echo "outer block"
   result = "ta-da"
 
-macro mac(n: expr): expr =
+macro mac(n: typed): string =
   let n = callsite()
   expectKind(n, nnkCall)
   expectLen(n, 2)
@@ -26,3 +26,11 @@ const t = mac("HEllo World")
 echo s, " ", t
 
 
+#-----------------------------------------------------------------------------
+# issue #15326
+macro m(n:typed):auto =
+  result = n
+
+proc f[T](x:T): T {.m.} = x
+
+discard f(3)
\ No newline at end of file
diff --git a/tests/macros/tmacro3.nim b/tests/macros/tmacro3.nim
index d7421ff7f..38e8349e7 100644
--- a/tests/macros/tmacro3.nim
+++ b/tests/macros/tmacro3.nim
@@ -8,7 +8,7 @@ type
     TA = tuple[a: int]
     PA = ref TA
 
-macro test*(a: stmt): stmt {.immediate.} =
+macro test*(a: untyped): untyped =
   var val: PA
   new(val)
   val.a = 4
@@ -16,9 +16,9 @@ macro test*(a: stmt): stmt {.immediate.} =
 test:
   "hi"
 
-macro test2*(a: stmt): stmt {.immediate.} =
+macro test2*(a: untyped): untyped =
   proc testproc(recurse: int) =
-    echo "Thats weird"
+    echo "That's weird"
     var o : NimNode = nil
     echo "  no its not!"
     o = newNimNode(nnkNone)
@@ -28,4 +28,3 @@ macro test2*(a: stmt): stmt {.immediate.} =
 
 test2:
   "hi"
-
diff --git a/tests/macros/tmacro4.nim b/tests/macros/tmacro4.nim
index a56369369..cb0399894 100644
--- a/tests/macros/tmacro4.nim
+++ b/tests/macros/tmacro4.nim
@@ -2,18 +2,16 @@ discard """
   output: "after"
 """
 
-import
-  macros, strutils
+import macros
 
-macro test_macro*(n: stmt): stmt {.immediate.} =
+macro test_macro*(s: string, n: untyped): untyped =
   result = newNimNode(nnkStmtList)
   var ass : NimNode = newNimNode(nnkAsgn)
   add(ass, newIdentNode("str"))
   add(ass, newStrLitNode("after"))
   add(result, ass)
-when isMainModule:
+when true:
   var str: string = "before"
   test_macro(str):
     var i : integer = 123
   echo str
-
diff --git a/tests/macros/tmacro5.nim b/tests/macros/tmacro5.nim
index d7a4fe8c8..802fb28d5 100644
--- a/tests/macros/tmacro5.nim
+++ b/tests/macros/tmacro5.nim
@@ -3,7 +3,7 @@ import macros,json
 var decls{.compileTime.}: seq[NimNode] = @[]
 var impls{.compileTime.}: seq[NimNode] = @[]
 
-macro importImpl_forward(name, returns): stmt {.immediate.} =
+macro importImpl_forward(name, returns: untyped): untyped =
   result = newNimNode(nnkEmpty)
   var func_name = newNimNode(nnkAccQuoted)
   func_name.add newIdentNode("import")
@@ -19,7 +19,7 @@ macro importImpl_forward(name, returns): stmt {.immediate.} =
   res[3].add returns
   var p1 = newNimNode(nnkIdentDefs)
   p1.add newIdentNode("dat")
-  p1.add newIdentNOde("PJsonNode")
+  p1.add newIdentNOde("JsonNode")
   p1.add newNimNode(nnkEmpty)
   res[3].add p1
   var p2 = newNimNode(nnkIdentDefs)
@@ -38,7 +38,7 @@ macro importImpl_forward(name, returns): stmt {.immediate.} =
   decls.add res
   echo(repr(res))
 
-macro importImpl(name, returns: expr, body: stmt): stmt {.immediate.} =
+macro importImpl(name, returns, body: untyped) =
   #var res = getAST(importImpl_forward(name, returns))
   discard getAST(importImpl_forward(name, returns))
   var res = copyNimTree(decls[decls.high])
@@ -46,7 +46,7 @@ macro importImpl(name, returns: expr, body: stmt): stmt {.immediate.} =
   echo repr(res)
   impls.add res
 
-macro okayy:stmt =
+macro okayy() =
   result = newNimNode(nnkStmtList)
   for node in decls: result.add node
   for node in impls: result.add node
diff --git a/tests/macros/tmacro6.nim b/tests/macros/tmacro6.nim
new file mode 100644
index 000000000..c65d34b6d
--- /dev/null
+++ b/tests/macros/tmacro6.nim
@@ -0,0 +1,75 @@
+discard """
+errormsg: "expression '123' is of type 'int literal(123)' and has to be used (or discarded)"
+line: 71
+"""
+
+import macros
+
+proc foo(a, b, c: int): int =
+  result += a
+  result += b
+  result += c
+
+macro bar(a, b, c: int): int =
+  result = newCall(ident"echo")
+  result.add a
+  result.add b
+  result.add c
+
+macro baz(a, b, c: int): int =
+  let stmt = nnkStmtListExpr.newTree()
+  stmt.add newCall(ident"echo", a)
+  stmt.add newCall(ident"echo", b)
+  stmt.add newCall(ident"echo", c)
+  stmt.add newLit(123)
+  return c
+
+# test no result type with explicit return
+
+macro baz2(a, b, c: int) =
+  let stmt = nnkStmtListExpr.newTree()
+  stmt.add newCall(ident"echo", a)
+  stmt.add newCall(ident"echo", b)
+  stmt.add newCall(ident"echo", c)
+  return stmt
+
+# test explicit void type with explicit return
+
+macro baz3(a, b, c: int): void =
+  let stmt = nnkStmtListExpr.newTree()
+  stmt.add newCall(ident"echo", a)
+  stmt.add newCall(ident"echo", b)
+  stmt.add newCall(ident"echo", c)
+  return stmt
+
+# test no result type with result variable
+
+macro baz4(a, b, c: int) =
+  result = nnkStmtListExpr.newTree()
+  result.add newCall(ident"echo", a)
+  result.add newCall(ident"echo", b)
+  result.add newCall(ident"echo", c)
+
+# test explicit void type with result variable
+
+macro baz5(a, b, c: int): void =
+  let result = nnkStmtListExpr.newTree()
+  result.add newCall(ident"echo", a)
+  result.add newCall(ident"echo", b)
+  result.add newCall(ident"echo", c)
+
+macro foobar1(): int =
+  result = quote do:
+    echo "Hello World"
+    1337
+
+echo foobar1()
+
+# this should create an error message, because 123 has to be discarded.
+
+macro foobar2() =
+  result = quote do:
+    echo "Hello World"
+    123
+
+echo foobar2()
diff --git a/tests/macros/tmacro7.nim b/tests/macros/tmacro7.nim
new file mode 100644
index 000000000..602191506
--- /dev/null
+++ b/tests/macros/tmacro7.nim
@@ -0,0 +1,36 @@
+discard """
+output: '''
+calling!stuff
+calling!stuff
+'''
+disabled: true
+"""
+
+# this test modifies an already semchecked ast (bad things happen)
+# this test relies on the bug #4547
+# issue #7792
+
+import macros
+
+proc callProc(str: string) =
+  echo "calling!" & str
+
+macro testMacro(code: typed): untyped =
+  let stmtList = newNimNode(nnkStmtList)
+
+  let stmts = code[6]
+
+  for n in stmts.children:
+    # the error happens here
+    stmtList.add(newCall(bindSym("callProc"), newLit("stuff")))
+
+  code[6] = stmtList
+
+  result = newEmptyNode()
+
+proc main() {.testMacro.} =
+  echo "test"
+  echo "test2"
+
+when isMainModule:
+  main()
diff --git a/tests/macros/tmacro8.nim b/tests/macros/tmacro8.nim
new file mode 100644
index 000000000..fdcec4dd4
--- /dev/null
+++ b/tests/macros/tmacro8.nim
@@ -0,0 +1,35 @@
+# issue #8573
+
+import
+  macros,
+  strutils,
+  terminal
+
+type LogSeverity* = enum
+  sevError = "Error"
+  sevWarn  = "Warn"
+  sevInfo  = "Info"
+  sevDebug = "Debug"
+
+macro log*(severity: static[LogSeverity], group: static[string], m: varargs[typed]): untyped =
+  let sevStr   = align("[" & toUpperAscii($severity) & "] ", 8)
+  let sevColor = case severity
+    of sevError: fgRed
+    of sevWarn:  fgYellow
+    of sevInfo:  fgWhite
+    of sevDebug: fgBlack
+
+  let groupStr = "[" & $group & "] "
+
+  result = quote do:
+    setStyle({ styleBright })
+    setForegroundColor(sevColor) # <==
+    write(stdout, sevStr)
+
+    setStyle({ styleDim })
+    setForegroundColor(fgWhite)
+    write(stdout, groupStr)
+
+  let wl = newCall(bindSym"styledWriteLine", bindSym"stdout")
+  for arg in m: wl.add(arg)
+  result.add(wl)
diff --git a/tests/macros/tmacro_in_template.nim b/tests/macros/tmacro_in_template.nim
deleted file mode 100644
index 8f7753cea..000000000
--- a/tests/macros/tmacro_in_template.nim
+++ /dev/null
@@ -1,10 +0,0 @@
-
-# bug #1944
-import macros
-
-template t(e: expr): stmt =
-  macro m(eNode: expr): stmt =
-    echo eNode.treeRepr
-  m e
-
-t 5
diff --git a/tests/macros/tmacroaspragma.nim b/tests/macros/tmacroaspragma.nim
index 0e5c352b3..5f06f2425 100644
--- a/tests/macros/tmacroaspragma.nim
+++ b/tests/macros/tmacroaspragma.nim
@@ -1,8 +1,7 @@
 import macros
 
-macro foo(x: stmt): stmt =
+macro foo(x: untyped): untyped =
   echo treerepr(callsite())
   result = newNimNode(nnkStmtList)
 
 proc zoo() {.foo.} = echo "hi"
-
diff --git a/tests/macros/tmacrogenerics.nim b/tests/macros/tmacrogenerics.nim
index 919a15b46..c31b5564c 100644
--- a/tests/macros/tmacrogenerics.nim
+++ b/tests/macros/tmacrogenerics.nim
@@ -1,8 +1,9 @@
 discard """
-  file: "tmacrogenerics.nim"
-  msg: '''
-instantiation 1 with typedesc and typedesc
-counter: 1
+  nimout: '''
+instantiation 1 with typeDesc[int] and typeDesc[float]
+instantiation 2 with typeDesc[float] and typeDesc[string]
+instantiation 3 with typeDesc[string] and typeDesc[string]
+counter: 3
 '''
   output: "int\nfloat\nint\nstring"
 """
@@ -13,7 +14,7 @@ var counter {.compileTime.} = 0
 
 macro makeBar(A, B: typedesc): typedesc =
   inc counter
-  echo "instantiation ", counter, " with ", A.name, " and ", B.name
+  echo "instantiation ", counter, " with ", A.getTypeInst.repr, " and ", B.getTypeInst.repr
   result = A
 
 type
diff --git a/tests/macros/tgensym.nim b/tests/macros/tmacrogensym.nim
index a4d1a3606..7c0d75f82 100644
--- a/tests/macros/tgensym.nim
+++ b/tests/macros/tmacrogensym.nim
@@ -1,6 +1,6 @@
 import nativesockets, asyncdispatch, macros
 var p = newDispatcher()
-var sock = newAsyncNativeSocket()
+var sock = createAsyncNativeSocket()
 
 proc convertReturns(node, retFutureSym: NimNode): NimNode {.compileTime.} =
   case node.kind
@@ -8,10 +8,10 @@ proc convertReturns(node, retFutureSym: NimNode): NimNode {.compileTime.} =
     result = newCall(newIdentNode("complete"), retFutureSym, node[0])
   else:
     result = node
-    for i in 0 .. <node.len:
+    for i in 0 ..< node.len:
       result[i] = convertReturns(node[i], retFutureSym)
 
-macro async2(prc: stmt): stmt {.immediate.} =
+macro async2(prc: untyped): untyped =
   expectKind(prc, nnkProcDef)
 
   var outerProcBody = newNimNode(nnkStmtList)
@@ -27,7 +27,8 @@ macro async2(prc: stmt): stmt {.immediate.} =
 
   # -> iterator nameIter(): FutureBase {.closure.} = <proc_body>
   # Changing this line to: newIdentNode($prc[0].ident & "Iter") # will make it work.
-  var iteratorNameSym = genSym(nskIterator, $prc[0].ident & "Iter")
+  var iteratorNameSym = genSym(nskIterator, $prc[0] & "Iter")
+  assert iteratorNameSym.symKind == nskIterator
   #var iteratorNameSym = newIdentNode($prc[0].ident & "Iter")
   var procBody = prc[6].convertReturns(retFutureSym)
 
@@ -38,10 +39,11 @@ macro async2(prc: stmt): stmt {.immediate.} =
 
   # -> var nameIterVar = nameIter
   # -> var first = nameIterVar()
-  var varNameIterSym = newIdentNode($prc[0].ident & "IterVar") #genSym(nskVar, $prc[0].ident & "IterVar")
+  var varNameIterSym = newIdentNode($prc[0] & "IterVar") #genSym(nskVar, $prc[0].ident & "IterVar")
   var varNameIter = newVarStmt(varNameIterSym, iteratorNameSym)
   outerProcBody.add varNameIter
   var varFirstSym = genSym(nskVar, "first")
+  assert varFirstSym.symKind ==  nskVar
   var varFirst = newVarStmt(varFirstSym, newCall(varNameIterSym))
   outerProcBody.add varFirst
 
@@ -49,8 +51,8 @@ macro async2(prc: stmt): stmt {.immediate.} =
   result = prc
 
   # Remove the 'closure' pragma.
-  for i in 0 .. <result[4].len:
-    if result[4][i].ident == !"async":
+  for i in 0 ..< result[4].len:
+    if result[4][i] == newIdentNode("async"):
       result[4].del(i)
 
   result[6] = outerProcBody
diff --git a/tests/macros/tmacrogetimpl.nim b/tests/macros/tmacrogetimpl.nim
new file mode 100644
index 000000000..1d996ff29
--- /dev/null
+++ b/tests/macros/tmacrogetimpl.nim
@@ -0,0 +1,31 @@
+import macros
+
+# bug #5034
+
+macro copyImpl(srsProc: typed, toSym: untyped) =
+  result = copyNimTree(getImplTransformed(srsProc))
+  result[0] = ident $toSym.toStrLit()
+
+proc foo1(x: float, one: bool = true): float =
+  if one:
+    return 1'f
+  result = x
+
+proc bar1(what: string): string =
+  ## be a little more adversarial with `skResult`
+  proc buzz: string =
+    result = "lightyear"
+  if what == "buzz":
+    result = "buzz " & buzz()
+  else:
+    result = what
+  return result
+
+copyImpl(foo1, foo2)
+doAssert foo1(1'f) == 1.0
+doAssert foo2(10.0, false) == 10.0
+doAssert foo2(10.0) == 1.0
+
+copyImpl(bar1, bar2)
+doAssert bar1("buzz") == "buzz lightyear"
+doAssert bar1("macros") == "macros"
diff --git a/tests/macros/tmacros1.nim b/tests/macros/tmacros1.nim
index 1a1073a44..c588ff7e6 100644
--- a/tests/macros/tmacros1.nim
+++ b/tests/macros/tmacros1.nim
@@ -1,23 +1,25 @@
 discard """
-  output: "Got: 'nnkCall' hi"
+  output: '''Got: 'nnkCall' hi
+{a}
+{b}
+{a, b}'''
 """
 
-import
-  macros, strutils
+import macros
 
-macro outterMacro*(n: stmt): stmt {.immediate.} =
+macro outterMacro*(n, blck: untyped): untyped =
   let n = callsite()
   var j : string = "hi"
   proc innerProc(i: int): string =
     echo "Using arg ! " & n.repr
     result = "Got: '" & $n.kind & "' " & $j
   var callNode = n[0]
-  expectKind(n, TNimrodNodeKind.nnkCall)
-  if n.len != 3 or n[1].kind != TNimrodNodeKind.nnkIdent:
+  expectKind(n, NimNodeKind.nnkCall)
+  if n.len != 3 or n[1].kind != NimNodeKind.nnkIdent:
     error("Macro " & callNode.repr &
       " requires the ident passed as parameter (eg: " & callNode.repr &
       "(the_name_you_want)): statements.")
-  result = newNimNode(TNimrodNodeKind.nnkStmtList)
+  result = newNimNode(NimNodeKind.nnkStmtList)
   var ass : NimNode = newNimNode(nnkAsgn)
   ass.add(newIdentNode(n[1].ident))
   ass.add(newStrLitNode(innerProc(4)))
@@ -28,4 +30,52 @@ outterMacro(str):
   "hellow"
 echo str
 
+type E = enum a b
+macro enumerators1(): set[E] = newLit({a})
 
+macro enumerators2(): set[E] =
+  return newLit({b})
+
+macro enumerators3(): set[E] =
+  result = newLit({E.low .. E.high})
+
+var myEnums: set[E]
+
+
+myEnums = enumerators1()
+echo myEnums
+myEnums = enumerators2()
+echo myEnums
+myEnums = enumerators3()
+echo myEnums
+
+#10751
+
+type Tuple = tuple
+  a: string
+  b: int
+
+macro foo(t: static Tuple): untyped =
+  doAssert t.a == "foo"
+  doAssert t.b == 12345
+
+foo((a: "foo", b: 12345))
+
+
+# bug #16307
+
+macro bug(x: untyped): string =
+  newLit repr(x)
+
+let res = bug:
+  block:
+    ## one
+    ## two
+    ## three
+
+doAssert res == """
+
+block:
+  ## one
+  ## two
+  ## three"""
diff --git a/tests/macros/tmacros_issues.nim b/tests/macros/tmacros_issues.nim
new file mode 100644
index 000000000..a81c51658
--- /dev/null
+++ b/tests/macros/tmacros_issues.nim
@@ -0,0 +1,521 @@
+discard """
+  nimout: '''
+IntLit 5
+proc (x: int): string => typeDesc[proc[string, int]]
+proc (x: int): void => typeDesc[proc[void, int]]
+proc (x: int) => typeDesc[proc[void, int]]
+x => seq[int]
+a
+s
+d
+f
+TTaa
+TTaa
+TTaa
+TTaa
+true
+true
+nil
+42
+false
+true
+@[i0, i1, i2, i3, i4]
+@[tmp, tmp, tmp, tmp, tmp]
+'''
+
+  output: '''
+range[0 .. 100]
+array[0 .. 100, int]
+10
+test
+0o377'i8
+0o000000000755'i32
+1
+2
+3
+foo1
+foo2
+foo3
+true
+false
+true
+false
+1.0
+'''
+"""
+
+
+import macros, parseutils
+
+
+block t7723:
+  macro foo1(): untyped =
+    result = newStmtList()
+    result.add quote do:
+      proc init(foo: int, bar: typedesc[int]): int =
+        foo
+
+  #expandMacros:
+  foo1()
+
+  doAssert init(1, int) == 1
+
+
+
+block t8706:
+  macro varargsLen(args:varargs[untyped]): untyped =
+    doAssert args.kind == nnkArgList
+    doAssert args.len == 0
+    result = newLit(args.len)
+
+  template bar(a0:varargs[untyped]): untyped =
+    varargsLen(a0)
+
+  template foo(x: int, a0:varargs[untyped]): untyped =
+    bar(a0)
+
+  doAssert foo(42) == 0
+  doAssert bar() == 0
+
+
+
+block t9194:
+  type
+    Foo1 = range[0 .. 100]
+    Foo2 = array[0 .. 100, int]
+
+  macro get(T: typedesc): untyped =
+    # Get the X out of typedesc[X]
+    let tmp = getTypeImpl(T)
+    result = newStrLitNode(getTypeImpl(tmp[1]).repr)
+
+  echo Foo1.get
+  echo Foo2.get
+
+
+
+block t1944:
+  template t(e: untyped): untyped =
+    macro m(eNode: untyped): untyped =
+      echo eNode.treeRepr
+    m e
+
+  t 5
+
+
+block t926:
+  proc test(f: var NimNode) {.compileTime.} =
+    f = newNimNode(nnkStmtList)
+    f.add newCall(newIdentNode("echo"), newLit(10))
+
+  macro blah(prc: untyped): untyped =
+    result = prc
+    test(result)
+
+  proc test() {.blah.} =
+    echo 5
+
+
+
+block t2211:
+  macro showType(t:typed): untyped =
+    let ty = t.getType
+    echo t.repr, " => ", ty.repr
+
+  showType(proc(x:int): string)
+  showType(proc(x:int): void)
+  showType(proc(x:int))
+
+  var x: seq[int]
+  showType(x)
+
+
+
+block t1140:
+  proc parse_until_symbol(node: NimNode, value: string, index: var int): bool {.compiletime.} =
+    var splitValue: string
+    var read = value.parseUntil(splitValue, '$', index)
+
+    # when false:
+    if false:
+        var identifier: string
+        read = value.parseWhile(identifier, {}, index)
+        node.add newCall("add", ident("result"), newCall("$", ident(identifier)))
+
+    if splitValue.len > 0:
+        node.insert node.len, newCall("add", ident("result"), newStrLitNode(splitValue))
+
+  proc parse_template(node: NimNode, value: string) {.compiletime.} =
+      var index = 0
+      while index < value.len and
+          parse_until_symbol(node, value, index): discard
+
+  macro tmpli(body: untyped): typed =
+      result = newStmtList()
+      result.add parseExpr("result = \"\"")
+      result.parse_template body[1].strVal
+
+
+  proc actual: string {.used.} = tmpli html"""
+      <p>Test!</p>
+      """
+
+  proc another: string {.used.} = tmpli html"""
+      <p>what</p>
+      """
+
+
+
+block tbugs:
+  type
+    Foo = object
+      s: char
+
+  iterator test2(f: string): Foo =
+    for i in f:
+      yield Foo(s: i)
+
+  macro test(): untyped =
+    for i in test2("asdf"):
+      echo i.s
+
+  test()
+
+
+  # bug 1297
+
+  type TType = tuple[s: string]
+
+  macro echotest(): untyped =
+    var t: TType
+    t.s = ""
+    t.s.add("test")
+    result = newCall(newIdentNode("echo"), newStrLitNode(t.s))
+
+  echotest()
+
+  # bug #1103
+
+  type
+      Td = tuple
+          a:string
+          b:int
+
+  proc get_data(d: Td) : string {.compileTime.} =
+      result = d.a # Works if a literal string is used here.
+      # Bugs if line A or B is active. Works with C
+      result &= "aa"          # A
+      #result.add("aa")       # B
+      #result = result & "aa" # C
+
+  macro m(s:static[Td]) : untyped =
+      echo get_data(s)
+      echo get_data(s)
+      result = newEmptyNode()
+
+  const s = ("TT", 3)
+  m(s)
+  m(s)
+
+  # bug #933
+
+  proc nilcheck(): NimNode {.compileTime.} =
+    echo(result == nil) # true
+    echo(result.isNil) # true
+    echo(repr(result)) # nil
+
+  macro testnilcheck(): untyped =
+    result = newNimNode(nnkStmtList)
+    discard nilcheck()
+
+  testnilcheck()
+
+  # bug #1323
+
+  proc calc(): array[1, int] =
+    result[0].inc()
+    result[0].inc()
+
+  const c = calc()
+  doAssert c[0] == 2
+
+
+  # bug #3046
+
+  macro sampleMacroInt(i: int): untyped =
+    echo i.intVal
+
+  macro sampleMacroBool(b: bool): untyped =
+    echo b.boolVal
+
+  sampleMacroInt(42)
+  sampleMacroBool(false)
+  sampleMacroBool(system.true)
+
+
+# bug #11131
+macro toRendererBug(n): untyped =
+  result = newLit repr(n)
+
+echo toRendererBug(0o377'i8)
+echo toRendererBug(0o755'i32)
+
+# bug #12129
+macro foobar() =
+  var loopVars = newSeq[NimNode](5)
+  for i, sym in loopVars.mpairs():
+    sym = ident("i" & $i)
+  echo loopVars
+  for sym in loopVars.mitems():
+    sym = ident("tmp")
+  echo loopVars
+
+foobar()
+
+
+# bug #13253
+import macros
+
+type
+  FooBar = object
+    a: seq[int]
+
+macro genFoobar(a: static FooBar): untyped =
+  result = newStmtList()
+  for b in a.a:
+    result.add(newCall(bindSym"echo", newLit b))
+
+proc foobar(a: static FooBar) =
+  genFoobar(a)  # removing this make it work
+  for b in a.a:
+    echo "foo" & $b
+
+proc main() =
+  const a: seq[int] = @[1, 2,3]
+  # Error: type mismatch: got <array[0..2, int]> but expected 'seq[int]'
+  const fb = Foobar(a: a)
+  foobar(fb)
+main()
+
+# bug #13484
+
+proc defForward(id, nid: NimNode): NimNode =
+  result = newProc(id, @[newIdentNode("bool"), newIdentDefs(nid, newIdentNode("int"))], body=newEmptyNode())
+
+proc defEven(evenid, oddid, nid: NimNode): NimNode =
+  result = quote do:
+    proc `evenid`(`nid`: int): bool =
+      if `nid` == 0:
+        return true
+      else:
+        return `oddid`(`nid` - 1)
+
+proc defOdd(evenid, oddid, nid: NimNode): NimNode =
+  result = quote do:
+    proc `oddid`(`nid`: int): bool =
+      if `nid` == 0:
+        return false
+      else:
+        return `evenid`(`nid` - 1)
+
+proc callNode(funid, param: NimNode): NimNode =
+  result = quote do:
+    `funid`(`param`)
+
+macro testEvenOdd3(): untyped =
+  let
+    evenid = newIdentNode("even3")
+    oddid = newIdentNode("odd3")
+    nid = newIdentNode("n")
+    oddForward = defForward(oddid, nid)
+    even = defEven(evenid, oddid, nid)
+    odd = defOdd(evenid, oddid, nid)
+    callEven = callNode(evenid, newLit(42))
+    callOdd = callNode(oddid, newLit(42))
+  result = quote do:
+    `oddForward`
+    `even`
+    `odd`
+    echo `callEven`
+    echo `callOdd`
+
+macro testEvenOdd4(): untyped =
+  let
+    evenid = newIdentNode("even4")
+    oddid = newIdentNode("odd4")
+    nid = newIdentNode("n")
+    oddForward = defForward(oddid, nid)
+    even = defEven(evenid, oddid, nid)
+    odd = defOdd(evenid, oddid, nid)
+    callEven = callNode(evenid, newLit(42))
+    callOdd = callNode(oddid, newLit(42))
+  # rewrite the body of proc node.
+  oddForward[6] = newStmtList()
+  result = quote do:
+    `oddForward`
+    `even`
+    `odd`
+    echo `callEven`
+    echo `callOdd`
+
+macro testEvenOdd5(): untyped =
+  let
+    evenid = genSym(nskProc, "even5")
+    oddid = genSym(nskProc, "odd5")
+    nid = newIdentNode("n")
+    oddForward = defForward(oddid, nid)
+    even = defEven(evenid, oddid, nid)
+    odd = defOdd(evenid, oddid, nid)
+    callEven = callNode(evenid, newLit(42))
+    callOdd = callNode(oddid, newLit(42))
+  result = quote do:
+    `oddForward`
+    `even`
+    `odd`
+    echo `callEven`
+    echo `callOdd`
+
+macro testEvenOdd6(): untyped =
+  let
+    evenid = genSym(nskProc, "even6")
+    oddid = genSym(nskProc, "odd6")
+    nid = newIdentNode("n")
+    oddForward = defForward(oddid, nid)
+    even = defEven(evenid, oddid, nid)
+    odd = defOdd(evenid, oddid, nid)
+    callEven = callNode(evenid, newLit(42))
+    callOdd = callNode(oddid, newLit(42))
+  # rewrite the body of proc node.
+  oddForward[6] = newStmtList()
+  result = quote do:
+    `oddForward`
+    `even`
+    `odd`
+    echo `callEven`
+    echo `callOdd`
+
+# it works
+testEvenOdd3()
+
+# it causes an error (redefinition of odd4), which is correct
+assert not compiles testEvenOdd4()
+
+# it caused an error (still forwarded: odd5)
+testEvenOdd5()
+
+# it works, because the forward decl and definition share the symbol and the compiler is forgiving here
+#testEvenOdd6() #Don't test it though, the compiler may become more strict in the future
+
+# bug #15385
+var captured_funcs {.compileTime.}: seq[NimNode] = @[]
+
+macro aad*(fns: varargs[typed]): typed =
+  result = newStmtList()
+  for fn in fns:
+    captured_funcs.add fn[0]
+    result.add fn
+
+func exp*(x: float): float ## get different error if you remove forward declaration
+
+func exp*(x: float): float {.aad.} =
+  var x1 = min(max(x, -708.4), 709.8)
+  var result: float   ## looks weird because it is taken from template expansion
+  result = x1 + 1.0
+  result
+
+template check_accuracy(f: untyped, rng: Slice[float], n: int, verbose = false): auto =
+
+  proc check_accuracy: tuple[avg_ulp: float, max_ulp: int] {.gensym.} =
+    let k = (rng.b - rng.a) / (float) n
+    var
+      res, x: float
+      i, max_ulp = 0
+      avg_ulp = 0.0
+
+    x = rng.a
+    while (i < n):
+      res = f(x)
+      i.inc
+      x = x + 0.001
+    (avg_ulp, max_ulp)
+  check_accuracy()
+
+discard check_accuracy(exp, -730.0..709.4, 4)
+
+# And without forward decl
+macro aad2*(fns: varargs[typed]): typed =
+  result = newStmtList()
+  for fn in fns:
+    captured_funcs.add fn[0]
+    result.add fn
+
+func exp2*(x: float): float {.aad2.} =
+  var x1 = min(max(x, -708.4), 709.8)
+  var result: float   ## looks weird because it is taken from template expansion
+  result = x1 + 1.0
+  result
+
+template check_accuracy2(f: untyped, rng: Slice[float], n: int, verbose = false): auto =
+
+  proc check_accuracy2: tuple[avg_ulp: float, max_ulp: int] {.gensym.} =
+    let k = (rng.b - rng.a) / (float) n
+    var
+      res, x: float
+      i, max_ulp = 0
+      avg_ulp = 0.0
+
+    x = rng.a
+    while (i < n):
+      res = f(x)
+      i.inc
+      x = x + 0.001
+    (avg_ulp, max_ulp)
+  check_accuracy2()
+
+discard check_accuracy2(exp2, -730.0..709.4, 4)
+
+# And minimized:
+macro aadMin(fn: typed): typed = fn
+
+func expMin: float
+
+func expMin: float {.aadMin.} = 1
+
+echo expMin()
+
+
+# doubly-typed forward decls
+macro noop(x: typed) = x
+noop:
+  proc cally() = discard
+
+cally()
+
+noop:
+  proc barry()
+
+proc barry() = discard
+
+# some more:
+proc barry2() {.noop.}
+proc barry2() = discard
+
+proc barry3() {.noop.}
+proc barry3() {.noop.} = discard
+
+
+# issue #15389
+block double_sem_for_procs:
+
+  macro aad(fns: varargs[typed]): typed =
+    result = newStmtList()
+    for fn in fns:
+      result.add fn
+
+  func exp(x: float): float {.aad.} =
+    var x1 = min(max(x, -708.4), 709.8)
+    if x1 > 0.0:
+      return x1 + 1.0
+    result = 10.0
+
+  discard exp(5.0)
diff --git a/tests/macros/tmacros_various.nim b/tests/macros/tmacros_various.nim
new file mode 100644
index 000000000..e351b4527
--- /dev/null
+++ b/tests/macros/tmacros_various.nim
@@ -0,0 +1,391 @@
+discard """
+  nimout: '''
+Infix
+  Ident "=>"
+  Call
+    Ident "name"
+    Ident "a"
+    ExprColonExpr
+      Ident "b"
+      Ident "cint"
+  NilLit
+macrocache ok
+'''
+
+  output: '''
+x = 10
+x + y = 30
+proc foo[T, N: static[int]]()
+proc foo[T; N: static[int]]()
+a[0]: 42
+a[1]: 45
+x: some string
+([("key", "val"), ("keyB", "2")], [("val", "key"), ("2", "keyB")])
+([("key", "val"), ("keyB", "2")], [("val", "key"), ("2", "keyB")])
+0
+0
+0
+'''
+"""
+
+
+import macros, sugar, macrocache
+
+
+block tdump:
+  let
+    x = 10
+    y = 20
+  dump x
+  dump(x + y)
+
+
+block texprcolonexpr:
+  macro def(x): untyped =
+    echo treeRepr(x)
+
+  def name(a, b:cint) => nil
+
+
+
+block tgenericparams:
+  macro test():string =
+    let expr0 = "proc foo[T, N: static[int]]()"
+    let expr1 = "proc foo[T; N: static[int]]()"
+
+    newLit($toStrLit(parseExpr(expr0)) & "\n" & $toStrLit(parseExpr(expr1)))
+
+  echo test()
+
+
+
+block tidgen:
+  # Test compile-time state in same module
+  var gid {.compileTime.} = 3
+
+  macro genId(): int =
+    result = newIntLitNode(gid)
+    inc gid
+
+  proc Id1(): int {.compileTime.} = return genId()
+  proc Id2(): int {.compileTime.} = return genId()
+
+  doAssert Id1() == 3
+  doAssert Id2() == 4
+
+
+
+block tlexerex:
+  macro match(s: cstring|string; pos: int; sections: varargs[untyped]): untyped =
+    for sec in sections:
+      expectKind sec, nnkOfBranch
+      expectLen sec, 2
+    result = newStmtList()
+
+  var input = "the input"
+  var pos = 0
+  match input, pos:
+  of r"[a-zA-Z_]\w+": echo "an identifier"
+  of r"\d+": echo "an integer"
+  of r".": echo "something else"
+
+
+
+block tcopylineinfo:
+  # issue #5617, feature request
+  type Test = object
+
+  macro mixer(n: typed): untyped =
+    let x = newIdentNode("echo")
+    x.copyLineInfo(n)
+    result = newLit(x.lineInfo == n.lineInfo)
+
+  var z = mixer(Test)
+  doAssert z
+
+block tsetgetlineinfo:
+  # issue #21098, feature request
+  type Test = object
+
+  macro mixer1(n: typed): untyped =
+    let x = newIdentNode("echo")
+    var lineInfo = n.lineInfoObj
+    x.setLineInfo lineInfo
+    result = newLit(x.lineInfo == n.lineInfo)
+
+  macro mixer2(n: typed): untyped =
+    let x = newIdentNode("echo")
+    var lineInfo = n.lineInfoObj
+    lineInfo.line += 1
+    x.setLineInfo lineInfo
+    result = newLit(x.lineInfo != n.lineInfo)
+
+  doAssert mixer1(Test)
+
+  doAssert mixer2(Test)
+
+
+
+block tdebugstmt:
+  macro debug(n: varargs[untyped]): untyped =
+    result = newNimNode(nnkStmtList, n)
+    for i in 0..n.len-1:
+      add(result, newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
+      add(result, newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
+      add(result, newCall("writeLine", newIdentNode("stdout"), n[i]))
+
+  var
+    a: array[0..10, int]
+    x = "some string"
+  a[0] = 42
+  a[1] = 45
+
+  debug(a[0], a[1], x)
+
+const
+  pairs = {"key": "val", "keyB": "2"}
+
+macro bilookups(arg: static[openArray[(string, string)]]): untyped =
+  var a = newTree(nnkBracket)
+  var b = newTree(nnkBracket)
+  for (k, v) in items(arg):
+    a.add(newTree(nnkTupleConstr, newLit k, newLit v))
+    b.add(newTree(nnkTupleConstr, newLit v, newLit k))
+  result = newTree(nnkTupleConstr, a, b)
+
+macro bilookups2(arg: untyped): untyped =
+  var a = newTree(nnkBracket)
+  var b = newTree(nnkBracket)
+  arg.expectKind(nnkTableConstr)
+  for x in items(arg):
+    x.expectKind(nnkExprColonExpr)
+    a.add(newTree(nnkTupleConstr, x[0], x[1]))
+    b.add(newTree(nnkTupleConstr, x[1], x[0]))
+  result = newTree(nnkTupleConstr, a, b)
+
+const cnst1 = bilookups(pairs)
+echo cnst1
+const cnst2 = bilookups2({"key": "val", "keyB": "2"})
+echo cnst2
+
+
+
+# macrocache #11404
+const
+  mcTable = CacheTable"nimTest"
+  mcSeq = CacheSeq"nimTest"
+  mcCounter = CacheCounter"nimTest"
+
+static:
+  doAssert(mcCounter.value == 0) # CacheCounter.value
+  mcCounter.inc                  # CacheCounter.inc
+  doAssert(mcCounter.value == 1) # CacheCounter.value
+
+  let a = newLit(1)
+  let b = newLit(2)
+  let c = newLit(3)
+  let d = newLit(4)
+
+  mcSeq.add a # CacheSeq.add
+  mcSeq.add b # CacheSeq.add
+  mcSeq.add c # CacheSeq.add
+
+  doAssert(mcSeq.len == 3)  # CacheSeq.len
+  #doAssert(c in mcSeq)      # CacheSeq.contains
+  #doAssert(d notin mcSeq)   # CacheSeq.contains
+
+  mcSeq.incl d              # CacheSeq.incl
+  doAssert(mcSeq.len == 4)  # CacheSeq.len
+
+  mcSeq.incl c              # CacheSeq.incl
+  doAssert(mcSeq.len == 4)  # CacheSeq.len
+
+  doAssert(mcSeq[3] == d)   # CacheSeq.[]
+
+  #doAssert(mcSeq.pop() == d)# CacheSeq.pop
+  #doAssert(mcSeq.len == 3)  # CacheSeq.len
+
+  doAssert(mcTable.len == 0)  # CacheTable.len
+  mcTable["a"] = a            # CacheTable.[]=
+  doAssert(mcTable.len == 1)  # CacheTable.len
+
+  doAssert(mcTable["a"] == a) # CacheTable.[]
+  #doAssert("a" in mcTable)    # CacheTable.contains
+  #doAssert(mcTable.hasKey("a"))# CacheTable.hasKey
+
+  for k, v in mcTable:  # CacheTable.items
+    doAssert(k == "a")
+    doAssert(v == a)
+
+  echo "macrocache ok"
+
+block tupleNewLitTests:
+  macro t(): untyped =
+    result = newLit (1, "foo", (), (1,), (a1: 'x', a2: @["ba"]))
+  doAssert $t() == """(1, "foo", (), (1,), (a1: 'x', a2: @["ba"]))"""
+    # this `$` test is needed because tuple equality doesn't distinguish
+    # between named vs unnamed tuples
+  doAssert t() == (1, "foo", (), (1, ), (a1: 'x', a2: @["ba"]))
+
+from strutils import contains
+block getImplTransformed:
+  macro bar(a: typed): string =
+    # newLit a.getImpl.repr # this would be before code transformation
+    let b = a.getImplTransformed
+    newLit b.repr
+  template toExpand() =
+    for ai in 0..2: echo ai
+  proc baz(a=1): int =
+    defer: discard
+    toExpand()
+    12
+  const code = bar(baz)
+  # sanity check:
+  doAssert "finally" in code # `defer` is lowered to try/finally
+  doAssert "while" in code # `for` is lowered to `while`
+  doAssert "toExpand" notin code
+    # template is expanded (but that would already be the case with
+    # `a.getImpl.repr`, unlike the other transformations mentioned above
+
+
+# test macro resemming
+macro makeVar(): untyped =
+  quote:
+    var tensorY {.inject.}: int
+
+macro noop(a: typed): untyped =
+  a
+
+noop:
+  makeVar
+echo tensorY
+
+macro xbenchmark(body: typed): untyped =
+  result = body
+
+xbenchmark:
+  proc fastSHA(inputtest: string) =
+    discard inputtest
+  fastSHA("hey")
+
+block: # issue #4547
+  macro lazy(stmtList : typed) : untyped =
+    let decl = stmtList[0]
+    decl.expectKind nnkLetSection
+    let name = decl[0][0].strVal
+    let call = decl[0][2].copy
+    call.expectKind nnkCall
+    let ident = newIdentNode("get" & name)
+    result = quote do:
+      var value : type(`call`)
+      proc `ident`() : type(`call`) =
+        if value.isNil:
+          value = `call`
+        value
+  type MyObject = object
+    a,b: int    
+  # this part, the macro call and it's result (written in the comment below) is important
+  lazy:
+    let y = new(MyObject)
+  #[
+    var value: type(new(MyObject))
+    proc gety(): type(new(MyObject)) =
+      if value.isNil:
+        value = new(MyObject)
+      value    
+  ]#
+  doAssert gety().a == 0  # works and should work
+  doAssert gety().b == 0  # works and should work
+  doAssert not declared(y)
+  doAssert not compiles(y.a)       # identifier y should not exist anymore
+  doAssert not compiles(y.b)       # identifier y should not exist anymore
+
+block: # bug #13511
+  type
+    Builder = ref object
+      components: seq[Component]
+    Component = object
+
+  proc add(builder: var Builder, component: Component) {.compileTime.} =
+    builder.components.add(component)
+
+  macro debugAst(arg: typed): untyped =
+    ## just for debugging purpose.
+    discard arg.treeRepr
+    return arg
+
+  static:
+    var component = Component()
+    var builder = Builder()
+
+    template foo(): untyped =
+      ## WAS: this doc comment causes compilation failure.
+      builder
+
+    debugAst:
+      add(foo(), component)
+
+block: # bug #15118
+  macro flop(name: static string) =
+    let id = genSym(nskType, "env")
+    let r =
+      nnkStmtList.newTree(
+        nnkTypeSection.newTree(
+          nnkTypeDef.newTree(
+            id,
+            newEmptyNode(),
+            nnkRefTy.newTree(
+              nnkObjectTy.newTree(
+                newEmptyNode(),
+                newEmptyNode(),
+                nnkRecList.newTree(
+                  nnkIdentDefs.newTree(
+                    newIdentNode(name),
+                    newIdentNode("int"),
+                    newEmptyNode()
+                  )
+                )
+              ) 
+            )
+          )
+        ),
+
+        # var f: T
+  
+        nnkVarSection.newTree(
+          nnkIdentDefs.newTree(
+            newIdentNode("f"),
+            id,
+            newEmptyNode()
+          )
+        ),
+
+        # echo f.a
+        nnkCommand.newTree(
+          newIdentNode("new"),
+          newIdentNode("f")
+        ),
+
+        nnkCommand.newTree(
+          newIdentNode("echo"),
+          nnkDotExpr.newTree(
+            newIdentNode("f"),
+            newIdentNode(name)
+          )
+        )
+      )
+    r
+
+
+  block:
+    flop("a")
+
+  block:
+    flop("b")
+
+static:
+  block:
+    const containsTable = CacheTable"containsTable"
+    doAssert "foo" notin containsTable
+    containsTable["foo"] = newLit 42
+    doAssert "foo" in containsTable
diff --git a/tests/macros/tmacrostmt.nim b/tests/macros/tmacrostmt.nim
index 23e2f358c..817bc8352 100644
--- a/tests/macros/tmacrostmt.nim
+++ b/tests/macros/tmacrostmt.nim
@@ -1,5 +1,5 @@
 import macros
-macro case_token(n: stmt): stmt {.immediate.} =
+macro case_token(n: varargs[untyped]): untyped =
   # creates a lexical analyzer from regular expressions
   # ... (implementation is an exercise for the reader :-)
   nil
@@ -18,9 +18,138 @@ case_token: inc i
 
 #bug #488
 
-macro foo: stmt =
+macro foo() =
   var exp = newCall("whatwhat", newIntLitNode(1))
-  if compiles(getAst(exp)): return exp
-  else: echo "Does not compute!"
+  if compiles(getAst(exp)):
+    return exp
+  else: echo "Does not compute! (test OK)"
 
 foo()
+
+#------------------------------------
+# bug #8287
+type MyString = distinct string
+
+proc `$` (c: MyString): string {.borrow.}
+
+proc `!!` (c: cstring): int =
+  c.len
+
+proc f(name: MyString): int =
+  !! $ name
+
+macro repr_and_parse(fn: typed) =
+  let fn_impl = fn.getImpl
+  fn_impl.name = genSym(nskProc, $fn_impl.name)
+  echo fn_impl.repr
+  result = parseStmt(fn_impl.repr)
+
+macro repr_to_string(fn: typed): string =
+  let fn_impl = fn.getImpl
+  result = newStrLitNode(fn_impl.repr)
+
+repr_and_parse(f)
+
+
+#------------------------------------
+# bugs #8343 and #8344
+proc one_if_proc(x, y : int): int =
+  if x < y: result = x
+  else: result = y
+
+proc test_block(x, y : int): int =
+  block label:
+    result = x
+    result = y
+
+#------------------------------------
+# bugs #8348
+
+template `>`(x, y: untyped): untyped =
+  ## "is greater" operator. This is the same as ``y < x``.
+  y < x
+
+proc test_cond_stmtlist(x, y: int): int =
+  result = x
+  if x > y:
+    result = x
+
+
+#------------------------------------
+# bug #8762
+proc t2(a, b: int): int =
+  `+`(a, b)
+
+
+#------------------------------------
+# bug #8761
+
+proc fn1(x, y: int):int =
+  2 * (x + y)
+
+proc fn2(x, y: float): float =
+  (y + 2 * x) / (x - y)
+
+proc fn3(x, y: int): bool =
+  (((x and 3) div 4) or (x mod (y xor -1))) == 0 or y notin [1,2]
+
+proc fn4(x: int): int =
+  if x mod 2 == 0: return x + 2
+  else: return 0
+
+proc fn5(a, b: float): float =
+  result = - a * a / (b * b)
+
+proc `{}`(x: seq[float], i: int, j: int): float = 
+  x[i + 0 * j]
+
+proc `{}=`(x: var seq[float], i: int, val: float) = 
+  x[i] = val
+
+proc fn6() =
+  var a = @[1.0, 2.0]
+  let z = a{0, 1} 
+  a{2} = 5.0
+
+
+#------------------------------------
+# bug #10807
+proc fn_unsafeaddr(x: int): int =
+  cast[int](unsafeAddr(x))
+
+static:
+  let fn1s = "proc fn1(x, y: int): int =\n  result = 2 * (x + y)\n"
+  let fn2s = "proc fn2(x, y: float): float =\n  result = (y + 2 * x) / (x - y)\n"
+  let fn3s = "proc fn3(x, y: int): bool =\n  result = ((x and 3) div 4 or x mod (y xor -1)) == 0 or not contains([1, 2], y)\n"
+  let fn4s = "proc fn4(x: int): int =\n  if x mod 2 == 0:\n    return x + 2\n  else:\n    return 0\n"
+  let fn5s = "proc fn5(a, b: float): float =\n  result = -a * a / (b * b)\n"
+  let fn6s = "proc fn6() =\n  var a = @[1.0, 2.0]\n  let z = a{0, 1}\n  a{2} = 5.0\n"
+  let fnAddr = "proc fn_unsafeaddr(x: int): int =\n  result = cast[int](addr(x))\n"
+
+  doAssert fn1.repr_to_string == fn1s
+  doAssert fn2.repr_to_string == fn2s
+  doAssert fn3.repr_to_string == fn3s
+  doAssert fn4.repr_to_string == fn4s
+  doAssert fn5.repr_to_string == fn5s
+  doAssert fn6.repr_to_string == fn6s
+  doAssert fn_unsafeaddr.repr_to_string == fnAddr
+
+#------------------------------------
+# bug #8763
+
+type
+  A {.pure.} = enum
+    X, Y
+  B {.pure.} = enum
+    X, Y
+
+proc test_pure_enums(a: B) =
+  case a
+    of B.X: echo B.X
+    of B.Y: echo B.Y
+
+repr_and_parse(one_if_proc)
+repr_and_parse(test_block)
+repr_and_parse(test_cond_stmtlist)
+repr_and_parse(t2)
+repr_and_parse(test_pure_enums)
diff --git a/tests/macros/tmacrotypes.nim b/tests/macros/tmacrotypes.nim
index 991668930..13b421303 100644
--- a/tests/macros/tmacrotypes.nim
+++ b/tests/macros/tmacrotypes.nim
@@ -1,16 +1,157 @@
 discard """
-  nimout: '''void
-int'''
+  nimout: '''intProc; ntyProc; proc[int, int, float]; proc (a: int; b: float): int {.nimcall.}
+void; ntyVoid; void; void
+int; ntyInt; int; int
+proc () {.nimcall.}; ntyProc; proc[void]; proc () {.nimcall.}
+voidProc; ntyProc; proc[void]; proc () {.nimcall.}
+listing fields for ObjType
+a: string
+b: int
+listing fields for ObjRef
+skipping ref type
+a: string
+b: int
+listing fields for RefType
+skipping ref type
+a: int
+b: float
+listing fields for typeof(a)
+skipping ref type
+a: string
+b: int
+listing fields for typeof(b)
+skipping ref type
+a: string
+b: int
+listing fields for typeof(c)
+skipping ref type
+a: int
+b: float
+listing fields for typeof(x)
+a: string
+b: int
+listing fields for typeof(x)
+a: int
+b: float
+typeDesc[range[1 .. 5]]; ntyTypeDesc; typeDesc[range[1, 5]]; typeDesc[range[1 .. 5]]
+typeDesc[range]; ntyTypeDesc; typeDesc[range[T]]; typeDesc[range]'''
 """
 
-import macros
+import macros, typetraits
 
-macro checkType(ex: stmt; expected: expr): stmt =
-  var t = ex.getType()
-  echo t
+macro checkType(ex: typed): untyped =
+  echo ex.getTypeInst.repr, "; ", ex.typeKind, "; ", ex.getType.repr, "; ", ex.getTypeImpl.repr
+
+macro checkProcType(fn: typed): untyped =
+  if fn.kind == nnkProcDef:
+    result = fn
+  let fn_sym = if fn.kind == nnkProcDef: fn[0] else: fn
+  echo fn_sym, "; ", fn_sym.typeKind, "; ", fn_sym.getType.repr, "; ", fn_sym.getTypeImpl.repr
 
 proc voidProc = echo "hello"
-proc intProc(a: int, b: float): int = 10
+proc intProc(a: int, b: float): int {.checkProcType.} = 10
+
+checkType(voidProc())
+checkType(intProc(10, 20.0))
+checkType(voidProc)
+checkProcType(voidProc)
+
+macro listFields(T: typed) =
+  echo "listing fields for ", repr(T)
+  let inputExprType = getType(T)
+
+  var objType = inputExprType[1]
+  if objType.kind == nnkBracketExpr and objType.len > 1:
+    if ((objType[0].kind == nnkRefTy) or
+        (objType[0].kind == nnkSym and eqIdent(objType[0], "ref"))):
+      echo "skipping ref type"
+      objType = objType[1]
+
+  let typeAst = objType.getImpl
+
+  var objectDef = typeAst[2]
+  if objectDef.kind == nnkRefTy:
+    objectDef = objectDef[0]
+
+  let recList = objectDef[2]
+  for rec in recList:
+    echo $rec[0], ": ", $rec[1]
+
+type
+  ObjType* = object of RootObj
+    a: string
+    b: int
+
+  ObjRef = ref ObjType
+
+  RefType* = ref object of RootObj
+    a: int
+    b: float
+
+listFields ObjType
+listFields ObjRef
+listFields RefType
+
+let
+  a = new ObjType
+  b = new ObjRef
+  c = new RefType
+
+listFields typeOf(a)
+listFields typeOf(b)
+listFields typeOf(c)
+
+proc genericProc(x: object) =
+  listFields typeOf(x)
+
+genericProc a[]
+genericProc b[]
+genericProc c[]
+
+# bug #10548
+block:
+  var c {.compileTime.} = 0
+
+  macro meshImpl(arg: typed): untyped =
+    inc c
+    result = arg
+
+  type
+    Blub = int32
+    Mesh = meshImpl(Club)
+    Club = Blub
+
+  static: doAssert(c == 1)
+
+# bug #10702
+type
+  VectorElementType = SomeNumber | bool
+  Vec*[N : static[int], T: VectorElementType] = object
+    arr*: array[N, T]
+
+type
+  Vec4*[T: VectorElementType] = Vec[4,T]
+  Vec3*[T: VectorElementType] = Vec[3,T]
+  Vec2*[T: VectorElementType] = Vec[2,T]
+
+template vecGen(U:untyped,V:typed):typed=
+  ## ``U`` suffix
+  ## ``V`` valType
+  ##
+  type
+    `Vec2 U`* {.inject.} = Vec2[V]
+    `Vec3 U`* {.inject.} = Vec3[V]
+    `Vec4 U`* {.inject.} = Vec4[V]
+
+vecGen(f, float32)
+
+macro foobar(arg: typed): untyped =
+  let typ = arg.getTypeInst
+  doAssert typ.getImpl[^1].kind == nnkCall
+
+var x: Vec2f
+
+foobar(x)
 
-checkType(voidProc(), "void")
-checkType(intProc(10, 20.0), "int")
+checkType(range[1..5])
+checkType(range)
diff --git a/tests/macros/tmemit.nim b/tests/macros/tmemit.nim
index e5aed3172..6c9f9f935 100644
--- a/tests/macros/tmemit.nim
+++ b/tests/macros/tmemit.nim
@@ -1,15 +1,15 @@
 discard """
-  output: '''HELLO WORLD
-c_func'''
+  output: '''
+c_func
+12
+'''
 """
 
 import macros, strutils
 
-emit("echo " & '"' & "hello world".toUpper & '"')
-
 # bug #1025
 
-macro foo(icname): stmt =
+macro foo(icname): untyped =
   let ic = newStrLitNode($icname)
   result = quote do:
     proc x* =
@@ -19,3 +19,20 @@ macro foo(icname): stmt =
 
 foo(c_func)
 x()
+
+
+template volatileLoad[T](x: ptr T): T =
+  var res: T
+  {.emit: [res, " = (*(", type(x[]), " volatile*)", x, ");"].}
+  res
+
+template volatileStore[T](x: ptr T; y: T) =
+  {.emit: ["*((", type(x[]), " volatile*)(", x, ")) = ", y, ";"].}
+
+proc main =
+  var st: int
+  var foo: ptr int = addr st
+  volatileStore(foo, 12)
+  echo volatileLoad(foo)
+
+main()
diff --git a/tests/macros/tmsginfo.nim b/tests/macros/tmsginfo.nim
new file mode 100644
index 000000000..f08a231fb
--- /dev/null
+++ b/tests/macros/tmsginfo.nim
@@ -0,0 +1,24 @@
+discard """
+  nimout: '''tmsginfo.nim(21, 1) Warning: foo1 [User]
+tmsginfo.nim(22, 13) template/generic instantiation of `foo2` from here
+tmsginfo.nim(15, 10) Warning: foo2 [User]
+tmsginfo.nim(23, 1) Hint: foo3 [User]
+tmsginfo.nim(19, 7) Hint: foo4 [User]
+'''
+"""
+
+import macros
+
+macro foo1(y: untyped): untyped =
+  warning("foo1", y)
+macro foo2(y: untyped): untyped =
+  warning("foo2")
+macro foo3(y: untyped): untyped =
+  hint("foo3", y)
+macro foo4(y: untyped): untyped =
+  hint("foo4")
+
+proc x1() {.foo1.} = discard
+proc x2() {.foo2.} = discard
+proc x3() {.foo3.} = discard
+proc x4() {.foo4.} = discard
diff --git a/tests/macros/tnewlit.nim b/tests/macros/tnewlit.nim
new file mode 100644
index 000000000..70683f880
--- /dev/null
+++ b/tests/macros/tnewlit.nim
@@ -0,0 +1,194 @@
+import macros
+
+type
+  MyType = object
+    a : int
+    b : string
+
+  RefObject = ref object
+    x: int
+
+  RegularObject = object
+    x: int
+
+  ObjectRefAlias = ref RegularObject
+
+macro test_newLit_MyType: untyped =
+  let mt = MyType(a: 123, b:"foobar")
+  result = newLit(mt)
+
+doAssert test_newLit_MyType == MyType(a: 123, b:"foobar")
+
+macro test_newLit_array: untyped =
+  let arr = [1,2,3,4,5]
+  result = newLit(arr)
+
+doAssert test_newLit_array == [1,2,3,4,5]
+
+macro test_newLit_seq_int: untyped =
+  let s: seq[int] = @[1,2,3,4,5]
+  result = newLit(s)
+
+block:
+  let tmp: seq[int] = test_newLit_seq_int
+  doAssert tmp == @[1,2,3,4,5]
+
+macro test_newLit_seq_int8: untyped =
+  let s: seq[int8] = @[1'i8,2,3,4,5]
+  result = newLit(s)
+
+block:
+  let tmp: seq[int8] = test_newLit_seq_int8
+  doAssert tmp == @[1'i8,2,3,4,5]
+
+macro test_newLit_seq_int16: untyped =
+  let s: seq[int16] = @[1'i16,2,3,4,5]
+  result = newLit(s)
+
+block:
+  let tmp: seq[int16] = test_newLit_seq_int16
+  doAssert tmp == @[1'i16,2,3,4,5]
+
+macro test_newLit_seq_int32: untyped =
+  let s: seq[int32] = @[1'i32,2,3,4,5]
+  result = newLit(s)
+
+block:
+  let tmp: seq[int32] = test_newLit_seq_int32
+  doAssert tmp == @[1'i32,2,3,4,5]
+
+macro test_newLit_seq_int64: untyped =
+  let s: seq[int64] = @[1'i64,2,3,4,5]
+  result = newLit(s)
+
+block:
+  let tmp: seq[int64] = test_newLit_seq_int64
+  doAssert tmp == @[1'i64,2,3,4,5]
+
+macro test_newLit_seq_uint: untyped =
+  let s: seq[uint] = @[1u,2,3,4,5]
+  result = newLit(s)
+
+block:
+  let tmp: seq[uint] = test_newLit_seq_uint
+  doAssert tmp == @[1u,2,3,4,5]
+
+macro test_newLit_seq_uint8: untyped =
+  let s: seq[uint8] = @[1'u8,2,3,4,5]
+  result = newLit(s)
+
+block:
+  let tmp: seq[uint8] = test_newLit_seq_uint8
+  doAssert tmp == @[1'u8,2,3,4,5]
+
+macro test_newLit_seq_uint16: untyped =
+  let s: seq[uint16] = @[1'u16,2,3,4,5]
+  result = newLit(s)
+
+block:
+  let tmp: seq[uint16] = test_newLit_seq_uint16
+  doAssert tmp == @[1'u16,2,3,4,5]
+
+macro test_newLit_seq_uint32: untyped =
+  let s: seq[uint32] = @[1'u32,2,3,4,5]
+  result = newLit(s)
+
+block:
+  let tmp: seq[uint32] = test_newLit_seq_uint32
+  doAssert tmp == @[1'u32,2,3,4,5]
+
+macro test_newLit_seq_uint64: untyped =
+  let s: seq[uint64] = @[1'u64,2,3,4,5]
+  result = newLit(s)
+
+block:
+  let tmp: seq[uint64] = test_newLit_seq_uint64
+  doAssert tmp == @[1'u64,2,3,4,5]
+
+macro test_newLit_seq_float: untyped =
+  let s: seq[float] = @[1.0, 2,3,4,5]
+  result = newLit(s)
+
+block:
+  let tmp: seq[float] = test_newLit_seq_float
+  doAssert tmp == @[1.0, 2,3,4,5]
+
+macro test_newLit_seq_float32: untyped =
+  let s: seq[float32] = @[1.0'f32, 2,3,4,5]
+  result = newLit(s)
+
+block:
+  let tmp: seq[float32] = test_newLit_seq_float32
+  doAssert tmp == @[1.0'f32, 2,3,4,5]
+
+macro test_newLit_seq_float64: untyped =
+  let s: seq[float64] = @[1.0'f64, 2,3,4,5]
+  result = newLit(s)
+
+block:
+  let tmp: seq[float64] = test_newLit_seq_float64
+  doAssert tmp == @[1.0'f64, 2,3,4,5]
+
+macro test_newLit_tuple: untyped =
+  let tup: tuple[a:int,b:string] = (a: 123, b: "223")
+  result = newLit(tup)
+
+doAssert test_newLit_tuple == (a: 123, b: "223")
+
+type
+  ComposedType = object
+    mt: MyType
+    arr: array[4,int]
+    data: seq[byte]
+
+macro test_newLit_ComposedType: untyped =
+  let ct = ComposedType(mt: MyType(a: 123, b:"abc"), arr: [1,2,3,4], data: @[1.byte, 3, 7, 127])
+  result = newLit(ct)
+
+doAssert test_newLit_ComposedType == ComposedType(mt: MyType(a: 123, b:"abc"), arr: [1,2,3,4], data: @[1.byte, 3, 7, 127])
+
+macro test_newLit_empty_seq_string: untyped =
+  var strSeq = newSeq[string](0)
+  result = newLit(strSeq)
+
+block:
+  # x needs to be of type seq[string]
+  var x = test_newLit_empty_seq_string
+  x.add("xyz")
+
+type
+  MyEnum = enum
+    meA
+    meB
+
+macro test_newLit_Enum: untyped =
+  result = newLit(meA)
+
+block:
+  let tmp: MyEnum = meA
+  doAssert tmp == test_newLit_Enum
+
+macro test_newLit_set: untyped =
+  let myset = {MyEnum.low .. MyEnum.high}
+  result = newLit(myset)
+
+block:
+  let tmp: set[MyEnum] = {MyEnum.low .. MyEnum.high}
+  doAssert tmp == test_newLit_set
+
+macro test_newLit_ref_object: untyped =
+  var x = RefObject(x: 10)
+  return newLit(x)
+
+block:
+  let x = test_newLit_ref_object()
+  doAssert $(x[]) == "(x: 10)"
+
+macro test_newLit_object_ref_alias: untyped =
+  var x = ObjectRefAlias(x: 10)
+  return newLit(x)
+
+block:
+  let x = test_newLit_object_ref_alias()
+  doAssert $(x[]) == "(x: 10)"
+
diff --git a/tests/macros/tnewproc.nim b/tests/macros/tnewproc.nim
new file mode 100644
index 000000000..a5bfd6dca
--- /dev/null
+++ b/tests/macros/tnewproc.nim
@@ -0,0 +1,51 @@
+import macros
+
+macro test(a: untyped): untyped =
+  # proc hello*(x: int = 3, y: float32): int {.inline.} = discard
+  let
+    nameNode = nnkPostfix.newTree(
+      newIdentNode("*"),
+      newIdentNode("hello")
+    )
+    params = @[
+      newIdentNode("int"),
+      nnkIdentDefs.newTree(
+        newIdentNode("x"),
+        newIdentNode("int"),
+        newLit(3)
+      ),
+      nnkIdentDefs.newTree(
+        newIdentNode("y"),
+        newIdentNode("float32"),
+        newEmptyNode()
+      )
+    ]
+    paramsNode = nnkFormalParams.newTree(params)
+    pragmasNode = nnkPragma.newTree(
+      newIdentNode("inline")
+    )
+    bodyNode = nnkStmtList.newTree(
+      nnkDiscardStmt.newTree(
+        newEmptyNode()
+      )
+    )
+
+  var
+    expected = nnkProcDef.newTree(
+      nameNode,
+      newEmptyNode(),
+      newEmptyNode(),
+      paramsNode,
+      pragmasNode,
+      newEmptyNode(),
+      bodyNode
+    )
+
+  doAssert expected == newProc(name=nameNode, params=params,
+                                    body = bodyNode, pragmas=pragmasNode)
+  expected.pragma = newEmptyNode()
+  doAssert expected == newProc(name=nameNode, params=params,
+                                    body = bodyNode)
+
+test:
+  42
diff --git a/tests/macros/tnimnode_for_runtime.nim b/tests/macros/tnimnode_for_runtime.nim
deleted file mode 100644
index 0520cd0dd..000000000
--- a/tests/macros/tnimnode_for_runtime.nim
+++ /dev/null
@@ -1,12 +0,0 @@
-discard """
-  output: "bla"
-"""
-
-import macros
-proc makeMacro: NimNode =
-  result = nil
-
-var p = makeMacro()
-
-echo "bla"
-
diff --git a/tests/macros/tnodecompare.nim b/tests/macros/tnodecompare.nim
index 3870c7559..5ffb495b1 100644
--- a/tests/macros/tnodecompare.nim
+++ b/tests/macros/tnodecompare.nim
@@ -1,39 +1,39 @@
-discard """
-output: '''true
-false
-true
-false
-true
-false
-true
-false'''
-"""
-
 import macros
 
-macro test(a: typed, b: typed): expr =
+static:
+  let nodeA = newCommentStmtNode("this is a comment")
+  doAssert nodeA.repr == "## this is a comment"
+  doAssert nodeA.strVal == "this is a comment"
+  doAssert $nodeA == "this is a comment"
+
+  let nodeB = newCommentStmtNode("this is a comment")
+  doAssert nodeA == nodeB
+  nodeB.strVal = "this is a different comment"
+  doAssert nodeA != nodeB
+
+macro test(a: typed, b: typed): untyped =
   newLit(a == b)
 
-echo test(1, 1)
-echo test(1, 2)
+doAssert test(1, 1) == true
+doAssert test(1, 2) == false
 
 type
   Obj = object of RootObj
   Other = object of RootObj
 
-echo test(Obj, Obj)
-echo test(Obj, Other)
+doAssert test(Obj, Obj) == true
+doAssert test(Obj, Other) == false
 
 var a, b: int
 
-echo test(a, a)
-echo test(a, b)
+doAssert test(a, a) == true
+doAssert test(a, b) == false
 
-macro test2: expr =
+macro test2: untyped =
   newLit(bindSym"Obj" == bindSym"Obj")
 
-macro test3: expr =
+macro test3: untyped =
   newLit(bindSym"Obj" == bindSym"Other")
 
-echo test2()
-echo test3()
+doAssert test2() == true
+doAssert test3() == false
diff --git a/tests/macros/tparsefile.nim b/tests/macros/tparsefile.nim
new file mode 100644
index 000000000..a41223f80
--- /dev/null
+++ b/tests/macros/tparsefile.nim
@@ -0,0 +1,11 @@
+import macros
+
+static:
+  let fn = "mparsefile.nim"
+  var raised = false
+  try:
+    discard parseStmt(staticRead(fn), filename = fn)
+  except ValueError as e:
+    raised = true
+    doAssert e.msg == "mparsefile.nim(4, 1) Error: invalid indentation"
+  doAssert raised
diff --git a/tests/macros/tprintf.nim b/tests/macros/tprintf.nim
deleted file mode 100644
index 94cbfbc2b..000000000
--- a/tests/macros/tprintf.nim
+++ /dev/null
@@ -1,16 +0,0 @@
-discard """
-  file: "tprintf.nim"
-  output: "Andreas Rumpf"
-"""
-# Test a printf proc
-
-proc printf(file: TFile, args: openarray[string]) =
-  var i = 0
-  while i < args.len:
-    write(file, args[i])
-    inc(i)
-
-printf(stdout, ["Andreas ", "Rumpf\n"])
-#OUT Andreas Rumpf
-
-
diff --git a/tests/macros/tprocgettype.nim b/tests/macros/tprocgettype.nim
new file mode 100644
index 000000000..0c1cc4270
--- /dev/null
+++ b/tests/macros/tprocgettype.nim
@@ -0,0 +1,28 @@
+discard """
+  nimout: '''
+var x: proc () {.cdecl.} = foo
+var x: iterator (): int {.closure.} = bar
+'''
+"""
+
+# issue #19010
+
+import macros
+
+macro createVar(x: typed): untyped =
+  result = nnkVarSection.newTree:
+    newIdentDefs(ident"x", getTypeInst(x), copy(x))
+  
+  echo repr result
+
+block:
+  proc foo() {.cdecl.} = discard
+
+  createVar(foo)
+  x()
+
+block:
+  iterator bar(): int {.closure.} = discard
+
+  createVar(bar)
+  for a in x(): discard
diff --git a/tests/macros/tprochelpers.nim b/tests/macros/tprochelpers.nim
new file mode 100644
index 000000000..d95a2ced8
--- /dev/null
+++ b/tests/macros/tprochelpers.nim
@@ -0,0 +1,22 @@
+import std/macros
+import stdtest/testutils
+
+macro test1(prc: untyped): untyped =
+  assertAll:
+    prc.params.len == 2
+    prc.params[1].len == 4
+    prc.pragma.len == 2
+
+  prc.params = nnkFormalParams.newTree(
+    ident("int")
+  )
+  prc.pragma = newEmptyNode()
+
+  assertAll:
+    prc.params.len == 1
+    prc.pragma.len == 0
+  prc
+
+proc test(a, b: int): int {.gcsafe, raises: [], test1.} = 5
+
+type hello = proc(a, b: int): int {.gcsafe, raises: [], test1.}
diff --git a/tests/macros/tquotedo.nim b/tests/macros/tquotedo.nim
new file mode 100644
index 000000000..6acb8ef4e
--- /dev/null
+++ b/tests/macros/tquotedo.nim
@@ -0,0 +1,51 @@
+discard """
+output: '''
+123
+Hallo Welt
+Hallo Welt
+1
+()
+'''
+"""
+
+import macros
+
+macro mac(): untyped =
+  quote do:
+    proc test(): int =
+      (proc(): int = result = 123)()
+
+mac()
+echo test()
+
+macro foobar(arg: untyped): untyped =
+  result = arg
+  result.add quote do:
+    `result`
+
+foobar:
+  echo "Hallo Welt"
+
+# bug #3744
+import macros
+macro t(): untyped =
+  return quote do:
+    proc tp(): int =
+      result = 1
+t()
+
+echo tp()
+
+
+# https://github.com/nim-lang/Nim/issues/9866
+type
+  # Foo = int # works
+  Foo = object # fails
+
+macro dispatchGen(): untyped =
+  var shOpt: Foo
+  result = quote do:
+    let baz = `shOpt`
+    echo `shOpt`
+
+dispatchGen()
diff --git a/tests/macros/tquotewords.nim b/tests/macros/tquotewords.nim
index 7a575f541..e718d25f9 100644
--- a/tests/macros/tquotewords.nim
+++ b/tests/macros/tquotewords.nim
@@ -1,12 +1,11 @@
 discard """
-  file: "tquotewords.nim"
   output: "thisanexample"
 """
 # Test an idea I recently had:
 
 import macros
 
-macro quoteWords(n: expr): expr {.immediate.} =
+macro quoteWords(n: varargs[untyped]): untyped =
   let n = callsite()
   result = newNimNode(nnkBracket, n)
   for i in 1..n.len-1:
@@ -21,6 +20,3 @@ for w in items(myWordList):
   s.add(w)
 
 echo s #OUT thisanexample
-
-
-
diff --git a/tests/macros/trecmacro.nim b/tests/macros/trecmacro.nim
index 28b6db530..d804178bc 100644
--- a/tests/macros/trecmacro.nim
+++ b/tests/macros/trecmacro.nim
@@ -1,10 +1,10 @@
 discard """
+  errormsg: "recursive dependency: 'dump'"
   file: "trecmacro.nim"
   line: 8
-  errormsg: "recursive dependency: 'dump'"
 """
 
-macro dump(n: stmt): stmt =
+macro dump(n: untyped): untyped =
   dump(n)
   if kind(n) == nnkNone:
     nil
diff --git a/tests/macros/treturnsempty.nim b/tests/macros/treturnsempty.nim
index 7af26a747..a5a678af3 100644
--- a/tests/macros/treturnsempty.nim
+++ b/tests/macros/treturnsempty.nim
@@ -3,10 +3,9 @@ discard """
   line: 11
 """
 # bug #2372
-macro foo(dummy: int): stmt =
+macro foo(dummy: int): untyped =
   discard
 
 proc takeStr(s: string) = echo s
 
 takeStr foo(12)
-
diff --git a/tests/macros/tsame_name_497.nim b/tests/macros/tsame_name_497.nim
index ed5d5c6d8..9f26a4024 100644
--- a/tests/macros/tsame_name_497.nim
+++ b/tests/macros/tsame_name_497.nim
@@ -1,6 +1,3 @@
-discard """
-  disabled: true
-"""
 
 import macro_bug
 
diff --git a/tests/macros/tsametype.nim b/tests/macros/tsametype.nim
index 34296015f..5219a3767 100644
--- a/tests/macros/tsametype.nim
+++ b/tests/macros/tsametype.nim
@@ -9,11 +9,12 @@ true
 false
 true
 false'''
+joinable: false
 """
 
 import macros
 
-macro same(a: typedesc, b: typedesc): expr =
+macro same(a: typedesc, b: typedesc): untyped =
   newLit(a.getType[1].sameType b.getType[1])
 
 echo same(int, int)
diff --git a/tests/macros/tslice.nim b/tests/macros/tslice.nim
new file mode 100644
index 000000000..c64289ec6
--- /dev/null
+++ b/tests/macros/tslice.nim
@@ -0,0 +1,38 @@
+import macros
+
+macro test(): untyped =
+  result = nnkStmtList.newTree()
+  let n = nnkStmtList.newTree(
+    newIdentNode("one"),
+    newIdentNode("two"),
+    newIdentNode("three"),
+    newIdentNode("four"),
+    newIdentNode("five"),
+    newIdentNode("six")
+  )
+
+  var i = 1
+  for x in n[1 .. ^2]:
+    assert x == n[i]
+    i.inc
+  assert i == 5
+
+  i = 3
+  for x in n[3..^1]:
+    assert x == n[i]
+    i.inc
+  assert i == 6
+
+  i = 0
+  for x in n[0..3]:
+    assert x == n[i]
+    i.inc
+  assert i == 4
+
+  i = 0
+  for x in n[0..5]:
+    assert x == n[i]
+    i.inc
+  assert i == 6
+
+test()
diff --git a/tests/macros/tstaticparamsmacro.nim b/tests/macros/tstaticparamsmacro.nim
index f6ecb3a9f..2632ca730 100644
--- a/tests/macros/tstaticparamsmacro.nim
+++ b/tests/macros/tstaticparamsmacro.nim
@@ -1,14 +1,15 @@
 discard """
-  msg: '''letters
+  nimout: '''
+letters
 aa
 bb
 numbers
 11
 22
 AST a
-[(11, 22), (33, 44)]
+@[(c: 11, d: 22), (c: 33, d: 44)]
 AST b
-(e: [55, 66], f: [77, 88])
+(e: @[55, 66], f: @[77, 88])
 55
 10
 20Test
@@ -25,7 +26,7 @@ type
 
 const data: Tconfig = (@["aa", "bb"], @[11, 22])
 
-macro mymacro(data: static[TConfig]): stmt =
+macro mymacro(data: static[TConfig]): untyped =
   echo "letters"
   for s in items(data.letters):
     echo s
@@ -43,11 +44,11 @@ const
   a : Ta = @[(11, 22), (33, 44)]
   b : Tb = (@[55,66], @[77, 88])
 
-macro mA(data: static[Ta]): stmt =
-  echo "AST a \n", repr(data)
+macro mA(data: static[Ta]): untyped =
+  echo "AST a\n", repr(data)
 
-macro mB(data: static[Tb]): stmt =
-  echo "AST b \n", repr(data)
+macro mB(data: static[Tb]): untyped =
+  echo "AST b\n", repr(data)
   echo data.e[0]
 
 mA(a)
@@ -56,13 +57,13 @@ mB(b)
 type
   Foo[N: static[int], Z: static[string]] = object
 
-macro staticIntMacro(f: static[int]): stmt = echo f
+macro staticIntMacro(f: static[int]): untyped = echo f
 staticIntMacro 10
 
 var
   x: Foo[20, "Test"]
 
-macro genericMacro[N; Z: static[string]](f: Foo[N, Z], ll = 3, zz = 12): stmt =
+macro genericMacro[N; Z: static[string]](f: Foo[N, Z], ll = 3, zz = 12): untyped =
   echo N, Z
 
 genericMacro x
diff --git a/tests/macros/tstringinterp.nim b/tests/macros/tstringinterp.nim
index bc79cdaba..74c73599b 100644
--- a/tests/macros/tstringinterp.nim
+++ b/tests/macros/tstringinterp.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tstringinterp.nim"
   output: "Hello Alice, 64 | Hello Bob, 10$"
 """
 
@@ -9,7 +8,7 @@ proc concat(strings: varargs[string]): string =
   result = newString(0)
   for s in items(strings): result.add(s)
 
-template processInterpolations(e: expr) =
+template processInterpolations(e) =
   var s = e[1].strVal
   for f in interpolatedFragments(s):
     case f.kind
@@ -17,7 +16,7 @@ template processInterpolations(e: expr) =
     of ikDollar:      addDollar()
     of ikVar, ikExpr: addExpr(newCall("$", parseExpr(f.value)))
 
-macro formatStyleInterpolation(e: expr): expr =
+macro formatStyleInterpolation(e: untyped): untyped =
   let e = callsite()
   var
     formatString = ""
@@ -41,7 +40,7 @@ macro formatStyleInterpolation(e: expr): expr =
   result[1].strVal = formatString
   result[2] = arrayNode
 
-macro concatStyleInterpolation(e: expr): expr =
+macro concatStyleInterpolation(e: untyped): untyped =
   let e = callsite()
   var args: seq[NimNode]
   newSeq(args, 0)
@@ -71,4 +70,4 @@ var
   s2 = formatStyleInterpolation"Hello ${bob}, ${sum(alice.len, bob.len, 2)}$$"
 
 write(stdout, s1 & " | " & s2)
-
+write(stdout, "\n")
diff --git a/tests/macros/tstructuredlogging.nim b/tests/macros/tstructuredlogging.nim
new file mode 100644
index 000000000..649c6c0bd
--- /dev/null
+++ b/tests/macros/tstructuredlogging.nim
@@ -0,0 +1,154 @@
+discard """
+output: '''
+main started: a=10, b=inner-b, c=10, d=some-d, x=16, z=20
+exiting: a=12, b=overridden-b, c=100, msg=bye bye, x=16
+'''
+"""
+
+import macros, tables
+
+template scopeHolder =
+  0 # scope revision number
+
+type
+  BindingsSet = Table[string, NimNode]
+
+proc actualBody(n: NimNode): NimNode =
+  # skip over the double StmtList node introduced in `mergeScopes`
+  result = n.body
+  if result.kind == nnkStmtList and result[0].kind == nnkStmtList:
+    result = result[0]
+
+iterator bindings(n: NimNode, skip = 0): (string, NimNode) =
+  for i in skip ..< n.len:
+    let child = n[i]
+    if child.kind in {nnkAsgn, nnkExprEqExpr}:
+      let name = $child[0]
+      let value = child[1]
+      yield (name, value)
+
+proc scopeRevision(scopeHolder: NimNode): int =
+  # get the revision number from a scopeHolder sym
+  assert scopeHolder.kind == nnkSym
+  var revisionNode = scopeHolder.getImpl.actualBody[0]
+  result = int(revisionNode.intVal)
+
+proc lastScopeHolder(scopeHolders: NimNode): NimNode =
+  # get the most recent scopeHolder from a symChoice node
+  if scopeHolders.kind in {nnkClosedSymChoice, nnkOpenSymChoice}:
+    var bestScopeRev = 0
+    assert scopeHolders.len > 0
+    for scope in scopeHolders:
+      let rev = scope.scopeRevision
+      if result == nil or rev > bestScopeRev:
+        result = scope
+        bestScopeRev = rev
+  else:
+    result = scopeHolders
+
+  assert result.kind == nnkSym
+
+macro mergeScopes(scopeHolders: typed, newBindings: untyped): untyped =
+  var
+    bestScope = scopeHolders.lastScopeHolder
+    bestScopeRev = bestScope.scopeRevision
+
+  var finalBindings = initTable[string, NimNode]()
+  for k, v in bindings(bestScope.getImpl.actualBody, skip = 1):
+    finalBindings[k] = v
+
+  for k, v in bindings(newBindings):
+    finalBindings[k] = v
+
+  var newScopeDefinition = newStmtList(newLit(bestScopeRev + 1))
+
+  for k, v in finalBindings:
+    newScopeDefinition.add newAssignment(newIdentNode(k), v)
+
+  result = quote:
+    template scopeHolder {.redefine.} = `newScopeDefinition`
+
+template scope(newBindings: untyped) {.dirty.} =
+  mergeScopes(bindSym"scopeHolder", newBindings)
+
+type
+  TextLogRecord = object
+    line: string
+
+  StdoutLogRecord = object
+
+template setProperty(r: var TextLogRecord, key: string, val: string, isFirst: bool) =
+  if not first: r.line.add ", "
+  r.line.add key
+  r.line.add "="
+  r.line.add val
+
+template setEventName(r: var StdoutLogRecord, name: string) =
+  stdout.write(name & ": ")
+
+template setProperty(r: var StdoutLogRecord, key: string, val: auto, isFirst: bool) =
+  when not isFirst: stdout.write ", "
+  stdout.write key
+  stdout.write "="
+  stdout.write $val
+
+template flushRecord(r: var StdoutLogRecord) =
+  stdout.write "\n"
+  stdout.flushFile
+
+macro logImpl(scopeHolders: typed,
+              logStmtProps: varargs[untyped]): untyped =
+  let lexicalScope = scopeHolders.lastScopeHolder.getImpl.actualBody
+  var finalBindings = initOrderedTable[string, NimNode]()
+
+  for k, v in bindings(lexicalScope, skip = 1):
+    finalBindings[k] = v
+
+  for k, v in bindings(logStmtProps, skip = 1):
+    finalBindings[k] = v
+
+  finalBindings.sort(system.cmp)
+
+  let eventName = logStmtProps[0]
+  assert eventName.kind in {nnkStrLit}
+  let record = genSym(nskVar, "record")
+
+  result = quote:
+    var `record`: StdoutLogRecord
+    setEventName(`record`, `eventName`)
+
+  var isFirst = true
+  for k, v in finalBindings:
+    result.add newCall(newIdentNode"setProperty",
+                       record, newLit(k), v, newLit(isFirst))
+    isFirst = false
+
+  result.add newCall(newIdentNode"flushRecord", record)
+
+template log(props: varargs[untyped]) {.dirty.} =
+  logImpl(bindSym"scopeHolder", props)
+
+scope:
+  a = 12
+  b = "original-b"
+
+scope:
+  x = 16
+  b = "overridden-b"
+
+scope:
+  c = 100
+
+proc main =
+  scope:
+    c = 10
+
+  scope:
+    z = 20
+
+  log("main started", a = 10, b = "inner-b", d = "some-d")
+
+main()
+
+log("exiting", msg = "bye bye")
+
diff --git a/tests/macros/ttemplatesymbols.nim b/tests/macros/ttemplatesymbols.nim
new file mode 100644
index 000000000..3182de79d
--- /dev/null
+++ b/tests/macros/ttemplatesymbols.nim
@@ -0,0 +1,171 @@
+import
+  macros, algorithm, strutils
+
+proc normalProc(x: int) =
+  echo x
+
+template templateWithtouParams =
+  echo 10
+
+proc overloadedProc(x: int) =
+  echo x
+
+proc overloadedProc(x: string) =
+  echo x
+
+proc overloadedProc[T](x: T) =
+  echo x
+
+template normalTemplate(x: int) =
+  echo x
+
+template overloadedTemplate(x: int) =
+  echo x
+
+template overloadedTemplate(x: string) =
+  echo x
+
+macro normalMacro(x: int): untyped =
+  discard
+
+macro macroWithoutParams: untyped =
+  discard
+
+macro inspectSymbol(sym: typed, expected: static[string]): untyped =
+  if sym.kind == nnkSym:
+    echo "Symbol node:"
+    let res = sym.getImpl.repr & "\n"
+    echo res
+    # echo "|", res, "|"
+    # echo "|", expected, "|"
+    if expected.len > 0: assert res == expected
+  elif sym.kind in {nnkClosedSymChoice, nnkOpenSymChoice}:
+    echo "Begin sym choice:"
+    var results = newSeq[string](0)
+    for innerSym in sym:
+      results.add innerSym.getImpl.repr
+    sort(results, cmp[string])
+    let res = results.join("\n") & "\n"
+    echo res
+    if expected.len > 0: assert res == expected
+    echo "End symchoice."
+  else:
+    echo "Non-symbol node: ", sym.kind
+    if expected.len > 0: assert $sym.kind == expected
+
+macro inspectUntyped(sym: untyped, expected: static[string]): untyped =
+  let res = sym.repr
+  echo "Untyped node: ", res
+  assert res == expected
+
+inspectSymbol templateWithtouParams, "nnkCommand"
+  # this template is expanded, because bindSym was not used
+  # the end result is the template body (nnkCommand)
+
+inspectSymbol bindSym("templateWithtouParams"), """
+template templateWithtouParams() =
+  echo 10
+
+"""
+
+inspectSymbol macroWithoutParams, "nnkEmpty"
+  # Just like the template above, the macro was expanded
+
+inspectSymbol bindSym("macroWithoutParams"), """
+macro macroWithoutParams(): untyped =
+  discard
+
+"""
+
+inspectSymbol normalMacro, """
+macro normalMacro(x: int): untyped =
+  discard
+
+"""
+  # Since the normalMacro has params, it's automatically
+  # treated as a symbol here (no need for `bindSym`)
+
+inspectSymbol bindSym("normalMacro"), """
+macro normalMacro(x: int): untyped =
+  discard
+
+"""
+
+inspectSymbol normalTemplate, """
+template normalTemplate(x: int) =
+  echo x
+
+"""
+
+inspectSymbol bindSym("normalTemplate"), """
+template normalTemplate(x: int) =
+  echo x
+
+"""
+
+inspectSymbol overloadedTemplate, """
+template overloadedTemplate(x: int) =
+  echo x
+
+template overloadedTemplate(x: string) =
+  echo x
+
+"""
+
+inspectSymbol bindSym("overloadedTemplate"), """
+template overloadedTemplate(x: int) =
+  echo x
+
+template overloadedTemplate(x: string) =
+  echo x
+
+"""
+
+inspectUntyped bindSym("overloadedTemplate"), """bindSym("overloadedTemplate")"""
+  # binSym is active only in the presence of `typed` params.
+  # `untyped` params still get the raw AST
+
+inspectSymbol normalProc, """
+proc normalProc(x: int) =
+  echo [x]
+
+"""
+
+inspectSymbol bindSym("normalProc"), """
+proc normalProc(x: int) =
+  echo [x]
+
+"""
+
+inspectSymbol overloadedProc, """
+proc overloadedProc(x: int) =
+  echo [x]
+
+proc overloadedProc(x: string) =
+  echo [x]
+
+proc overloadedProc[T](x: T) =
+  echo x
+
+"""
+
+inspectSymbol overloadedProc[float], """
+proc overloadedProc(x: T) =
+  echo [x]
+
+"""
+  # As expected, when we select a specific generic, the
+  # AST is no longer a symChoice
+
+inspectSymbol bindSym("overloadedProc"), """
+proc overloadedProc(x: int) =
+  echo [x]
+
+proc overloadedProc(x: string) =
+  echo [x]
+
+proc overloadedProc[T](x: T) =
+  echo x
+
+"""
+
diff --git a/tests/macros/ttryparseexpr.nim b/tests/macros/ttryparseexpr.nim
index c7bbc8e5b..e6e9e9880 100644
--- a/tests/macros/ttryparseexpr.nim
+++ b/tests/macros/ttryparseexpr.nim
@@ -1,11 +1,11 @@
 discard """
-  outputsub: '''Error: invalid indentation 45'''
+  outputsub: '''Error: expression expected, but found '[EOF]' 45'''
 """
 
 # feature request #1473
 import macros
 
-macro test(text: string): expr =
+macro test(text: string): untyped =
   try:
     result = parseExpr(text.strVal)
   except ValueError:
@@ -18,3 +18,7 @@ const
   c = test("\"") # bug #2504
 
 echo a, " ", b
+
+static:
+  # Issue #9918
+  discard parseStmt("echo(1+1);")
diff --git a/tests/macros/ttypenodes.nim b/tests/macros/ttypenodes.nim
new file mode 100644
index 000000000..233ea9780
--- /dev/null
+++ b/tests/macros/ttypenodes.nim
@@ -0,0 +1,16 @@
+import macros
+
+macro makeEnum(): untyped =
+  newTree(nnkEnumTy, newEmptyNode(), ident"a", ident"b", ident"c")
+
+macro makeObject(): untyped =
+  newTree(nnkObjectTy, newEmptyNode(), newEmptyNode(), newTree(nnkRecList,
+    newTree(nnkIdentDefs, ident"x", ident"y", ident"int", newEmptyNode())))
+
+type
+  Foo = makeEnum()
+  Bar = makeObject()
+
+doAssert {a, b, c} is set[Foo]
+let bar = Bar(x: 3, y: 4)
+doAssert (bar.x, bar.y) == (3, 4)
diff --git a/tests/macros/tvarargsuntyped.nim b/tests/macros/tvarargsuntyped.nim
new file mode 100644
index 000000000..5a06adcca
--- /dev/null
+++ b/tests/macros/tvarargsuntyped.nim
@@ -0,0 +1,108 @@
+discard """
+  output: '''Let's go!
+(left: 2, r: 7, x: 8, height: 4, s: test, width: 3, y: 9, top: 1, g: 7, b: 8)
+(left: 2, r: 7, x: 8, height: 4, s: text, width: 3, y: 9, top: 1, g: 7, b: 8)
+(left: 2, r: 7, x: 8, height: 4, s: text, width: 3, y: 9, top: 4, g: 7, b: 8)
+(left: 2, r: 7, x: 8, height: 4, s: test, width: 3, y: 9, top: 1, g: 7, b: 8)
+10
+hello 18.0'''
+"""
+
+import macros
+
+proc internalBar(top, left, width, height: cint, s: string, x, y: int, r,g,b: int) =
+  echo "(left: ", left, ", r: ", r, ", x: ", x, ", height: ", height, ", s: ", s,
+    ", width: ", width, ", y: ", y, ", top: ", top, ", g: ", g, ", b: ", b, ")"
+
+# we need these dummy constructors due to the wrong implementation
+# of 'varargs[untyped]' in the compiler:
+
+proc point(x, y: int): int = discard
+proc color(r, g, b: int): int = discard
+proc rect(a, b, c, d: int): int = discard
+
+template declareUnpackingMacro(nimname,extname) =
+  macro nimname(n: varargs[untyped]): untyped =
+    var s: string = astToStr(extname) & "("
+    var first = true
+    echo repr n
+    for x in n.children:
+      var unpack = false
+      if x.kind in nnkCallKinds:
+        case $x[0]
+        of "point":
+          expectLen(x, 3)
+          unpack = true
+        of "rect":
+          expectLen(x, 5)
+          unpack = true
+        of "color":
+          expectLen(x, 4)
+          unpack = true
+        else: discard
+      if unpack:
+        for i in 1..<x.len:
+          if first:
+            first = false
+          else:
+            add(s, ", ")
+          add(s, repr(x[i]))
+      else:
+        if first:
+          first = false
+        else:
+          add(s, ", ")
+        add(s, repr(x))
+
+    add(s, ")")
+    echo s
+    result = parseStmt(s)
+
+declareUnpackingMacro(bar,internalBar)
+
+type MyInt = distinct int
+
+proc myInt(i: int): MyInt = cast[MyInt](i)
+
+converter toCInt(mi: MyInt): cint = cast[cint](mi)
+
+echo "Let's go!"
+
+bar(rect(1, 2, 3, 4), "test", point(8, 9), color(7,7,8))
+
+bar(1,2,3,4,"text",8,9,7,7,8)
+
+bar(myInt(4),2,3,4,"text",8,9,7,7,8)
+
+let top: cint = 1
+let left: cint = 2
+let width: cint = 3
+let height: cint = 4
+
+bar(rect(top, left, width, height), "test", point(8, 9), color(7,7,8))
+
+
+# bug #10075
+
+import macros
+
+proc convert_hidden_stdconv(args: NimNode): NimNode =
+  var n = args
+  while n.len == 1 and n[0].kind == nnkHiddenStdConv:
+    n = n[0][1]
+  return n
+
+macro t2(s: int, v: varargs[untyped]): untyped =
+  let v = convert_hidden_stdconv(v)
+  echo v.treeRepr
+  let (v1, v2) = (v[0], v[1])
+  quote do:
+    echo `v1`, " ", `v2`
+
+template t1(s: int, v: varargs[typed]) =
+  #static:
+  #   dumpTree v
+  echo s
+  t2(s, v)
+
+t1(10, "hello", 18.0)
diff --git a/tests/macros/tvarnimnode.nim b/tests/macros/tvarnimnode.nim
deleted file mode 100644
index ab0f66caa..000000000
--- a/tests/macros/tvarnimnode.nim
+++ /dev/null
@@ -1,19 +0,0 @@
-discard """
-  output: 10
-"""
-
-#bug #926
-
-import macros
-
-proc test(f: var NimNode) {.compileTime.} =
-  f = newNimNode(nnkStmtList)
-  f.add newCall(newIdentNode("echo"), newLit(10))
-
-macro blah(prc: stmt): stmt =
-  result = prc
-
-  test(result)
-
-proc test() {.blah.} =
-  echo 5
diff --git a/tests/macros/tvtable.nim b/tests/macros/tvtable.nim
index cc5d7a5d9..0f322b7d5 100644
--- a/tests/macros/tvtable.nim
+++ b/tests/macros/tvtable.nim
@@ -18,7 +18,7 @@ type
   # it's also possible to use a strongly typed tuple here
   VTable = array[0..1, pointer]
 
-  TBase = object {.inheritable.}
+  TBase {.inheritable.} = object
     vtbl: ptr VTable
 
   TUserObject1 = object of TBase
@@ -58,10 +58,10 @@ proc create(T: typedesc): T =
   result.vtbl = getVTable(T)
 
 proc baseFoo(o: var TBase): int =
-  return cast[fooProc[TBase]](o.vtbl[0]) (o)
+  return cast[fooProc[TBase]](o.vtbl[0])(o)
 
 proc baseBar(o: var TBase) =
-  cast[barProc[TBase]](o.vtbl[1]) (o)
+  cast[barProc[TBase]](o.vtbl[1])(o)
 
 var a = TUserObject1.create
 var b = TUserObject2.create
diff --git a/tests/macros/twrapiterator.nim b/tests/macros/twrapiterator.nim
new file mode 100644
index 000000000..e153ae980
--- /dev/null
+++ b/tests/macros/twrapiterator.nim
@@ -0,0 +1,19 @@
+
+import macros
+
+# bug #7093
+
+macro foobar(arg: untyped): untyped =
+  let procDef = quote do:
+    proc foo(): void =
+      echo "bar"
+
+
+  result = newStmtList(
+    arg, procDef
+  )
+
+  echo result.repr
+
+iterator bar(): int {.foobar.} =
+  discard
diff --git a/tests/macros/typesafeprintf.nim b/tests/macros/typesafeprintf.nim
index 2f4622f3e..daf213bd3 100644
--- a/tests/macros/typesafeprintf.nim
+++ b/tests/macros/typesafeprintf.nim
@@ -9,7 +9,7 @@ proc printfImpl(formatstr: cstring) {.importc: "printf", varargs.}
 
 iterator tokenize(format: string): char =
   var i = 0
-  while true:
+  while i < format.len:
     case format[i]
     of '%':
       case format[i+1]
@@ -42,7 +42,8 @@ macro printf(formatString: string{lit}, args: varargs[typed]): untyped =
             $expectedType & ", actual type: " & $actualType
 
   # keep the original callsite, but use cprintf instead
-  result = callsite()
-  result[0] = bindSym"printfImpl"
+  result = newCall(bindSym"printfImpl")
+  result.add formatString
+  for a in args: result.add a
 
 printf("test %d\n", 10)
diff --git a/tests/macros/typesapi.nim b/tests/macros/typesapi.nim
deleted file mode 100644
index 670b39c9e..000000000
--- a/tests/macros/typesapi.nim
+++ /dev/null
@@ -1,17 +0,0 @@
-discard """
-  nimout: '''proc (x: int): string => typeDesc[proc[string, int]]
-proc (x: int): void => typeDesc[proc[void, int]]
-proc (x: int) => typeDesc[proc[void, int]]'''
-"""
-
-#2211
-
-import macros
-
-macro showType(t:stmt): stmt =
-  let ty = t.getType
-  echo t.repr, " => ", ty.repr
-
-showType(proc(x:int): string)
-showType(proc(x:int): void)
-showType(proc(x:int))
diff --git a/tests/macros/typesapi2.nim b/tests/macros/typesapi2.nim
index 2e59d2154..0130049c0 100644
--- a/tests/macros/typesapi2.nim
+++ b/tests/macros/typesapi2.nim
@@ -2,7 +2,7 @@
 # be used as a type
 import macros
 
-macro testTypesym (t:stmt): expr =
+macro testTypesym (t:typed): untyped =
     var ty = t.getType
     if ty.typekind == ntyTypedesc:
         # skip typedesc get to the real type
@@ -31,7 +31,7 @@ static: assert(ref int is testTypesym(ref int))
 static: assert(void is testTypesym(void))
 
 
-macro tts2 (t:stmt, idx:int): expr =
+macro tts2 (t:typed, idx:int): untyped =
     var ty = t.getType
     if ty.typekind == ntyTypedesc:
         # skip typedesc get to the real type
@@ -46,4 +46,3 @@ static:
     assert(tts2(TestFN2, 1) is string)
     assert(tts2(TestFN2, 2) is int)
     assert(tts2(TestFN2, 3) is float)
-