Added AST introspection routines as a part of the standard library
This commit is contained in:
parent
daa2c8732d
commit
d541815e4b
4 changed files with 44 additions and 21 deletions
|
|
@ -312,7 +312,7 @@ type
|
||||||
|
|
||||||
TMagic* = enum # symbols that require compiler magic:
|
TMagic* = enum # symbols that require compiler magic:
|
||||||
mNone, mDefined, mDefinedInScope, mLow, mHigh, mSizeOf, mIs, mOf,
|
mNone, mDefined, mDefinedInScope, mLow, mHigh, mSizeOf, mIs, mOf,
|
||||||
mEcho, mShallowCopy, mSlurp,
|
mEcho, mAstToYaml, mShallowCopy, mSlurp,
|
||||||
mUnaryLt, mSucc,
|
mUnaryLt, mSucc,
|
||||||
mPred, mInc, mDec, mOrd, mNew, mNewFinalize, mNewSeq, mLengthOpenArray,
|
mPred, mInc, mDec, mOrd, mNew, mNewFinalize, mNewSeq, mLengthOpenArray,
|
||||||
mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref,
|
mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
# this module does the semantic checking for expressions
|
# this module does the semantic checking for expressions
|
||||||
|
|
||||||
const
|
const
|
||||||
ConstAbstractTypes = {tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
|
ConstAbstractTypes = {tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
|
||||||
tyArrayConstr, tyTuple, tySet}
|
tyArrayConstr, tyTuple, tySet}
|
||||||
|
|
@ -883,6 +884,11 @@ proc setMs(n: PNode, s: PSym): PNode =
|
||||||
n.sons[0] = newSymNode(s)
|
n.sons[0] = newSymNode(s)
|
||||||
n.sons[0].info = n.info
|
n.sons[0].info = n.info
|
||||||
|
|
||||||
|
proc semAstToYaml(c: PContext, n: PNode): PNode =
|
||||||
|
result = newStrNode(nkStrLit, n.treeToYaml.ropeToStr)
|
||||||
|
result.typ = getSysType(tyString)
|
||||||
|
result.info = n.info
|
||||||
|
|
||||||
proc semSlurp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
proc semSlurp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
if sonsLen(n) == 2:
|
if sonsLen(n) == 2:
|
||||||
var a = c.semConstExpr(c, n.sons[1])
|
var a = c.semConstExpr(c, n.sons[1])
|
||||||
|
|
@ -921,6 +927,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
else:
|
else:
|
||||||
result = semDirectOp(c, n, flags)
|
result = semDirectOp(c, n, flags)
|
||||||
of mSlurp: result = semSlurp(c, n, flags)
|
of mSlurp: result = semSlurp(c, n, flags)
|
||||||
|
of mAstToYaml: result = semAstToYaml(c, n)
|
||||||
else: result = semDirectOp(c, n, flags)
|
else: result = semDirectOp(c, n, flags)
|
||||||
|
|
||||||
proc semIfExpr(c: PContext, n: PNode): PNode =
|
proc semIfExpr(c: PContext, n: PNode): PNode =
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,39 @@ proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||||
## in a string literal node
|
## in a string literal node
|
||||||
return newStrLitNode(repr(n))
|
return newStrLitNode(repr(n))
|
||||||
|
|
||||||
|
proc prettyPrint*(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, prettyPrint(n[0]))
|
||||||
|
for j in 1..n.len-1:
|
||||||
|
add(result, ", ")
|
||||||
|
add(result, prettyPrint(n[j]))
|
||||||
|
|
||||||
|
add(result, ")")
|
||||||
|
|
||||||
|
proc toYaml*(n: PNimrodNode) {.magic: "AstToYaml".}
|
||||||
|
## Converts the AST `n` to an YAML string
|
||||||
|
##
|
||||||
|
## Provides more detailed, potentially harder to digest information
|
||||||
|
## than `prettyPrint`
|
||||||
|
|
||||||
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
|
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
|
||||||
## checks that `n` is of kind `k`. If this is not the case,
|
## checks that `n` is of kind `k`. If this is not the case,
|
||||||
## compilation aborts with an error message. This is useful for writing
|
## compilation aborts with an error message. This is useful for writing
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,12 @@
|
||||||
# Dump the contents of a PNimrodNode
|
# Dump the contents of a PNimrodNode
|
||||||
|
|
||||||
import macros
|
import macros
|
||||||
|
|
||||||
proc dumpit(n: PNimrodNode): string {.compileTime.} =
|
|
||||||
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, dumpit(n[0]))
|
|
||||||
for j in 1..n.len-1:
|
|
||||||
add(result, ", ")
|
|
||||||
add(result, dumpit(n[j]))
|
|
||||||
add(result, ")")
|
|
||||||
|
|
||||||
macro dumpAST(n: stmt): stmt =
|
macro dumpAST(n: stmt): stmt =
|
||||||
# dump AST as a side-effect and return the inner node
|
# dump AST as a side-effect and return the inner node
|
||||||
echo dumpit(n)
|
echo n.prettyPrint
|
||||||
|
echo n.toYaml
|
||||||
|
|
||||||
result = n[1]
|
result = n[1]
|
||||||
|
|
||||||
dumpAST:
|
dumpAST:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue