diff options
author | Kaushal Modi <kaushal.modi@gmail.com> | 2018-10-27 09:10:05 -0400 |
---|---|---|
committer | Dominik Picheta <dominikpicheta@googlemail.com> | 2018-10-27 14:10:05 +0100 |
commit | f8cef575b322d9736df369e2a33f5ade7d800f95 (patch) | |
tree | 64656b79bd130ddf281d2fcfc5733d31f7b31043 /lib/core | |
parent | dd252ce640c7f624acc08a6702193ec15fd7359b (diff) | |
download | Nim-f8cef575b322d9736df369e2a33f5ade7d800f95.tar.gz |
Improve dumpLisp macro (#9515)
* Improve dumpLisp macro - Remove commas from the lisp representation of the AST. - Make the dumpLisp output "pretty" and indented. - Improve docs of `dumpTree` and `dumpLisp` macros. With: dumpLisp: echo "Hello, World!" Output before this commit: StmtList(Command(Ident("echo"), StrLit("Hello, World!"))) Output after this commit: (StmtList (Command (Ident "echo") (StrLit "Hello, World!"))) * Re-use the traverse proc inside treeRepr for lispRepr too - Add module-local `treeTraverse` proc. - Also fix treeRepr/dumpTree not printing nnkCommentStmt node contents. * More doc string updates * Allow unindented lispRepr output for tests * Update a test affected by the lispRepr change * Fix dumpTree * Add note about lispRepr and dumpLisp to changelog [ci skip]
Diffstat (limited to 'lib/core')
-rw-r--r-- | lib/core/macros.nim | 158 |
1 files changed, 96 insertions, 62 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 3801adfc5..87daabb5b 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -732,72 +732,56 @@ proc nestList*(theProc: NimIdent, x: NimNode): NimNode {.compileTime, deprecated for i in countdown(L-3, 0): result = newCall(theProc, x[i], result) -proc treeRepr*(n: NimNode): string {.compileTime, benign.} = - ## Convert the AST `n` to a human-readable tree-like string. - ## - ## See also `repr`, `lispRepr`, and `astGenRepr`. - - proc traverse(res: var string, level: int, n: NimNode) {.benign.} = - for i in 0..level-1: res.add " " - res.add(($n.kind).substr(3)) - - case n.kind - of nnkEmpty, nnkNilLit: discard # same as nil node in this representation - of nnkCharLit..nnkInt64Lit: res.add(" " & $n.intVal) - of nnkFloatLit..nnkFloat64Lit: res.add(" " & $n.floatVal) - of nnkStrLit..nnkTripleStrLit, nnkIdent, nnkSym: - res.add(" " & $n.strVal.newLit.repr) - of nnkNone: assert false +proc treeTraverse(n: NimNode; res: var string; level = 0; isLisp = false, indented = false) {.benign.} = + if level > 0: + if indented: + res.add("\n") + for i in 0 .. level-1: + if isLisp: + res.add(" ") # dumpLisp indentation + else: + res.add(" ") # dumpTree indentation else: - for j in 0..n.len-1: - res.add "\n" - traverse(res, level + 1, n[j]) + res.add(" ") - result = "" - traverse(result, 0, n) - -proc lispRepr*(n: NimNode): string {.compileTime, benign.} = - ## Convert the AST `n` to a human-readable lisp-like string, - ## - ## See also `repr`, `treeRepr`, and `astGenRepr`. - - result = ($n.kind).substr(3) - add(result, "(") + if isLisp: + res.add("(") + res.add(($n.kind).substr(3)) case n.kind - of nnkEmpty, nnkNilLit: discard # same as nil node in this representation - of nnkCharLit..nnkInt64Lit: add(result, $n.intVal) - of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal) - of nnkStrLit..nnkTripleStrLit, nnkCommentStmt, nnkident, nnkSym: - add(result, n.strVal.newLit.repr) - of nnkNone: assert false + of nnkEmpty, nnkNilLit: + discard # same as nil node in this representation + of nnkCharLit .. nnkInt64Lit: + res.add(" " & $n.intVal) + of nnkFloatLit .. nnkFloat64Lit: + res.add(" " & $n.floatVal) + of nnkStrLit .. nnkTripleStrLit, nnkCommentStmt, nnkIdent, nnkSym: + res.add(" " & $n.strVal.newLit.repr) + of nnkNone: + assert false else: - if n.len > 0: - add(result, lispRepr(n[0])) - for j in 1..n.len-1: - add(result, ", ") - add(result, lispRepr(n[j])) + for j in 0 .. n.len-1: + n[j].treeTraverse(res, level+1, isLisp, indented) - add(result, ")") + if isLisp: + res.add(")") -proc astGenRepr*(n: NimNode): string {.compileTime, benign.} = - ## Convert the AST `n` to the code required to generate that AST. So for example - ## - ## .. code-block:: nim - ## astGenRepr: - ## echo "Hello world" +proc treeRepr*(n: NimNode): string {.compileTime, benign.} = + ## Convert the AST `n` to a human-readable tree-like string. ## - ## Would output: + ## See also `repr`, `lispRepr`, and `astGenRepr`. + n.treeTraverse(result, isLisp = false, indented = true) + +proc lispRepr*(n: NimNode; indented = false): string {.compileTime, benign.} = + ## Convert the AST ``n`` to a human-readable lisp-like string. ## - ## .. code-block:: nim - ## nnkStmtList.newTree( - ## nnkCommand.newTree( - ## newIdentNode("echo"), - ## newLit("Hello world") - ## ) - ## ) + ## See also ``repr``, ``treeRepr``, and ``astGenRepr``. + n.treeTraverse(result, isLisp = true, indented = indented) + +proc astGenRepr*(n: NimNode): string {.compileTime, benign.} = + ## Convert the AST ``n`` to the code required to generate that AST. ## - ## See also `repr`, `treeRepr`, and `lispRepr`. + ## See also ``repr``, ``treeRepr``, and ``lispRepr``. const NodeKinds = {nnkEmpty, nnkIdent, nnkSym, nnkNone, nnkCommentStmt} @@ -842,26 +826,76 @@ proc astGenRepr*(n: NimNode): string {.compileTime, benign.} = macro dumpTree*(s: untyped): untyped = echo s.treeRepr ## Accepts a block of nim code and prints the parsed abstract syntax - ## tree using the `treeRepr` function. Printing is done *at compile time*. + ## tree using the ``treeRepr`` proc. Printing is done *at compile time*. ## ## You can use this as a tool to explore the Nim's abstract syntax ## tree and to discover what kind of nodes must be created to represent ## a certain expression/statement. + ## + ## For example: + ## + ## .. code-block:: nim + ## dumpTree: + ## echo "Hello, World!" + ## + ## Outputs: + ## + ## .. code-block:: + ## StmtList + ## Command + ## Ident "echo" + ## StrLit "Hello, World!" + ## + ## Also see ``dumpAstGen`` and ``dumpLisp``. -macro dumpLisp*(s: untyped): untyped = echo s.lispRepr +macro dumpLisp*(s: untyped): untyped = echo s.lispRepr(indented = true) ## Accepts a block of nim code and prints the parsed abstract syntax - ## tree using the `lispRepr` function. Printing is done *at compile time*. + ## tree using the ``lispRepr`` proc. Printing is done *at compile time*. + ## + ## You can use this as a tool to explore the Nim's abstract syntax + ## tree and to discover what kind of nodes must be created to represent + ## a certain expression/statement. ## - ## See `dumpTree`. + ## For example: + ## + ## .. code-block:: nim + ## dumpLisp: + ## echo "Hello, World!" + ## + ## Outputs: + ## + ## .. code-block:: + ## (StmtList + ## (Command + ## (Ident "echo") + ## (StrLit "Hello, World!"))) + ## + ## Also see ``dumpAstGen`` and ``dumpTree``. macro dumpAstGen*(s: untyped): untyped = echo s.astGenRepr ## Accepts a block of nim code and prints the parsed abstract syntax - ## tree using the `astGenRepr` function. Printing is done *at compile time*. + ## tree using the ``astGenRepr`` proc. Printing is done *at compile time*. ## ## You can use this as a tool to write macros quicker by writing example ## outputs and then copying the snippets into the macro for modification. ## - ## See `dumpTree`. + ## For example: + ## + ## .. code-block:: nim + ## dumpAstGen: + ## echo "Hello, World!" + ## + ## Outputs: + ## + ## .. code-block:: nim + ## nnkStmtList.newTree( + ## nnkCommand.newTree( + ## newIdentNode("echo"), + ## newLit("Hello, World!") + ## ) + ## ) + ## + ## Also see ``dumpTree`` and ``dumpLisp``. macro dumpTreeImm*(s: untyped): untyped {.deprecated.} = echo s.treeRepr ## Deprecated. Use `dumpTree` instead. |