summary refs log tree commit diff stats
path: root/lib/core/macros.nim
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2011-11-04 04:56:40 +0200
committerZahary Karadjov <zahary@gmail.com>2011-11-04 04:56:40 +0200
commitb72480ec88fa2826853b281a0c14054b51bd6c3b (patch)
tree6e385992ccf426eb0901dd9f3aa82a746f5b4465 /lib/core/macros.nim
parent4a436120bd235b7c91e5ef2a6ccdad5edb3f2daf (diff)
downloadNim-b72480ec88fa2826853b281a0c14054b51bd6c3b.tar.gz
new kind of AST printer that prints indented trees
AST-to-string conversion procs renamed to repr, treeRepr and lispRepr for better consistency
new dumpTree and dumpLisp procs for quick AST inspection of arbitrary nimrod blocks
Diffstat (limited to 'lib/core/macros.nim')
-rwxr-xr-xlib/core/macros.nim109
1 files changed, 73 insertions, 36 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 8a589896d..2e75e8d5d 100755
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -189,40 +189,8 @@ proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
   return newStrLitNode(repr(n))

 

 proc lineinfo*(n: PNimrodNode): string {.magic: "NLineInfo".}

-

-proc toLisp*(n: PNimrodNode): string {.compileTime.} =

-  ## Convert the AST `n` to a human-readable string

-  ##

-  ## You can use this as a tool to explore the Nimrod's abstract syntax 

-  ## tree and to discover what kind of nodes must be created to represent

-  ## a certain expression/statement

-

-  if n == nil: return "nil"

-

-  result = $n.kind

-  add(result, "(")

-  

-  case n.kind

-  of nnkEmpty: nil # same as nil node in this representation

-  of nnkNilLit: add(result, "nil")

-  of nnkCharLit..nnkInt64Lit: add(result, $n.intVal)

-  of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal)

-  of nnkStrLit..nnkTripleStrLit: add(result, $n.strVal)

-  of nnkIdent: add(result, $n.ident)

-  of nnkSym, nnkNone: assert false

-  else:

-    add(result, toLisp(n[0]))

-    for j in 1..n.len-1:

-      add(result, ", ")

-      add(result, toLisp(n[j]))

-

-  add(result, ")")

-

-proc toYaml*(n: PNimrodNode): string {.magic: "AstToYaml".}

-  ## Converts the AST `n` to an YAML string

-  ##

-  ## Provides more detailed, potentially harder to digest information

-  ## than `toLisp`

+  ## returns the position the node appears in the original source file

+  ## in the form filename(line, col)

 

 proc parseExpr*(s: string): expr {.magic: "ParseExprToAst".}

   ## Compiles the passed string to its AST representation.

@@ -275,8 +243,8 @@ proc newCall*(theProc: string,
   result.add(newIdentNode(theProc))

   result.add(args)

 

-proc nestList*(theProc: TNimrodIdent,  

-               x: PNimrodNode): PNimrodNode {.compileTime.} = 

+proc nestList*(theProc: TNimrodIdent,

+               x: PNimrodNode): PNimrodNode {.compileTime.} =

   ## nests the list `x` into a tree of call expressions:

   ## ``[a, b, c]`` is transformed into ``theProc(a, theProc(c, d))``

   var L = x.len

@@ -285,3 +253,72 @@ proc nestList*(theProc: TNimrodIdent,
   for i in countdown(L-3, 0):

     a = newCall(theProc, x[i], copyNimTree(a))

 

+proc treeRepr*(n: PNimrodNode): string {.compileTime.} =

+  ## Convert the AST `n` to a human-readable tree-like string

+  ##

+  ## see also `repr` and `lispRepr`

+

+  proc traverse(res: var string, level: int, n: PNimrodNode) =

+    for i in 0..level-1: res.add "  "

+    

+    if n == nil:

+      res.add "nil"

+    else:

+      res.add(($n.kind).substr(3))

+      

+      case n.kind

+      of nnkEmpty: nil # same as nil node in this representation

+      of nnkNilLit: res.add(" nil")

+      of nnkCharLit..nnkInt64Lit: res.add(" " & $n.intVal)

+      of nnkFloatLit..nnkFloat64Lit: res.add(" " & $n.floatVal)

+      of nnkStrLit..nnkTripleStrLit: res.add(" " & $n.strVal)

+      of nnkIdent: res.add(" " & $n.ident)

+      of nnkSym, nnkNone: assert false

+      else:

+        for j in 0..n.len-1:

+          res.add "\n"

+          traverse(res, level + 1, n[j])

+

+  result = ""

+  traverse(result, 0, n)

+

+proc lispRepr*(n: PNimrodNode): string {.compileTime.} =

+  ## Convert the AST `n` to a human-readable lisp-like string

+  ##

+  ## see also `repr` and `treeRepr`

+  

+  if n == nil: return "nil"

+

+  result = ($n.kind).substr(3)

+  add(result, "(")

+  

+  case n.kind

+  of nnkEmpty: nil # same as nil node in this representation

+  of nnkNilLit: add(result, "nil")

+  of nnkCharLit..nnkInt64Lit: add(result, $n.intVal)

+  of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal)

+  of nnkStrLit..nnkTripleStrLit: add(result, $n.strVal)

+  of nnkIdent: add(result, $n.ident)

+  of nnkSym, nnkNone: assert false

+  else:

+    add(result, lispRepr(n[0]))

+    for j in 1..n.len-1:

+      add(result, ", ")

+      add(result, lispRepr(n[j]))

+

+  add(result, ")")

+

+macro dumpTree*(s: stmt): stmt = echo s[1].treeRepr

+  ## Accepts a block of nimrod code and prints the parsed abstract syntax

+  ## tree using the `toTree` function.

+  ##

+  ## You can use this as a tool to explore the Nimrod's abstract syntax 

+  ## tree and to discover what kind of nodes must be created to represent

+  ## a certain expression/statement

+

+macro dumpLisp*(s: stmt): stmt = echo s[1].lispRepr

+  ## Accepts a block of nimrod code and prints the parsed abstract syntax

+  ## tree using the `toLisp` function.

+  ##

+  ## see `dumpTree`

+