summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2020-07-18 01:49:36 -0700
committerGitHub <noreply@github.com>2020-07-18 10:49:36 +0200
commit169ca37d2628312b5d94d5e90c3271179db87a13 (patch)
tree7f5e0a9dc8d4325bdd58eb2a8fb6ba21b671ae41
parentc983466c15f1807c66f4c2f07ba348b0f95584b3 (diff)
downloadNim-169ca37d2628312b5d94d5e90c3271179db87a13.tar.gz
enable,document,test getImplTransformed, very useful for understanding how nim transforms code (#14924)
* enable,document,test getImplTransformed, very useful for understanding how nim transforms code
-rw-r--r--lib/core/macros.nim7
-rw-r--r--tests/macros/tmacros_various.nim20
2 files changed, 25 insertions, 2 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 7b03d4e4d..e4a56d6f9 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -277,9 +277,12 @@ else: # bootstrapping substitute
 
 {.pop.}
 
-when defined(nimSymImplTransform):
+when (NimMajor, NimMinor, NimPatch) >= (1, 3, 5) or defined(nimSymImplTransform):
   proc getImplTransformed*(symbol: NimNode): NimNode {.magic: "GetImplTransf", noSideEffect.}
-    ## For a typed proc returns the AST after transformation pass.
+    ## For a typed proc returns the AST after transformation pass; this is useful
+    ## for debugging how the compiler transforms code (eg: `defer`, `for`) but
+    ## note that code transformations are implementation dependent and subject to change.
+    ## See an example in `tests/macros/tmacros_various.nim`.
 
 when defined(nimHasSymOwnerInMacro):
   proc owner*(sym: NimNode): NimNode {.magic: "SymOwner", noSideEffect.}
diff --git a/tests/macros/tmacros_various.nim b/tests/macros/tmacros_various.nim
index 533db25e1..3cb5aaa8f 100644
--- a/tests/macros/tmacros_various.nim
+++ b/tests/macros/tmacros_various.nim
@@ -202,3 +202,23 @@ block tupleNewLitTests:
     # 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