Get symbol kind (#7491)

This commit is contained in:
Arne Döring 2018-04-11 16:48:01 +02:00 • committed by Andreas Rumpf
commit 6baca58693
13 changed files with 319 additions and 272 deletions

View file

@ -26,6 +26,8 @@
- ``macros.astGenRepr``, ``macros.lispRepr`` and ``macros.treeRepr`` - ``macros.astGenRepr``, ``macros.lispRepr`` and ``macros.treeRepr``
now escapes the content of string literals consistently. now escapes the content of string literals consistently.
- ``macros.NimSym`` and ``macros.NimIdent`` is now deprecated in favor
of the more general ``NimNode``.
### Language additions ### Language additions

View file

@ -632,10 +632,11 @@ type
mCpuEndian, mHostOS, mHostCPU, mBuildOS, mBuildCPU, mAppType, mCpuEndian, mHostOS, mHostCPU, mBuildOS, mBuildCPU, mAppType,
mNaN, mInf, mNegInf, mNaN, mInf, mNegInf,
mCompileOption, mCompileOptionArg, mCompileOption, mCompileOptionArg,
mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, mNKind, mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel,
mNKind, mNSymKind
mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal, mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal,
mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNLineInfo, mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNLineInfo,
mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr, mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent,
mNBindSym, mLocals, mNCallSite, mNBindSym, mLocals, mNCallSite,
mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl, mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl,
mNHint, mNWarning, mNError, mNHint, mNWarning, mNError,

View file

@ -113,3 +113,4 @@ proc initDefines*() =
defineSymbol("nimHasRunnableExamples") defineSymbol("nimHasRunnableExamples")
defineSymbol("nimNewDot") defineSymbol("nimNewDot")
defineSymbol("nimHasNilChecks") defineSymbol("nimHasNilChecks")
defineSymbol("nimSymKind")

View file

@ -768,8 +768,10 @@ macro `=~`(x: PNode, pat: untyped): bool =
var conds = newTree(nnkBracket) var conds = newTree(nnkBracket)
m(x, pat, conds) m(x, pat, conds)
when declared(macros.toNimIdent): when compiles(nestList(ident"and", conds)):
result = nestList(toNimIdent"and", conds) result = nestList(ident"and", conds)
#elif declared(macros.toNimIdent):
# result = nestList(toNimIdent"and", conds)
else: else:
result = nestList(!"and", conds) result = nestList(!"and", conds)

View file

@ -892,7 +892,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].node = if a.sym.ast.isNil: newNode(nkNilLit) regs[ra].node = if a.sym.ast.isNil: newNode(nkNilLit)
else: copyTree(a.sym.ast) else: copyTree(a.sym.ast)
else: else:
stackTrace(c, tos, pc, errFieldXNotFound, "symbol") stackTrace(c, tos, pc, errGenerated, "node is not a symbol")
of opcEcho: of opcEcho:
let rb = instr.regB let rb = instr.regB
if rb == 1: if rb == 1:
@ -1233,6 +1233,14 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
decodeB(rkInt) decodeB(rkInt)
regs[ra].intVal = ord(regs[rb].node.kind) regs[ra].intVal = ord(regs[rb].node.kind)
c.comesFromHeuristic = regs[rb].node.info c.comesFromHeuristic = regs[rb].node.info
of opcNSymKind:
decodeB(rkInt)
let a = regs[rb].node
if a.kind == nkSym:
regs[ra].intVal = ord(a.sym.kind)
else:
stackTrace(c, tos, pc, errGenerated, "node is not a symbol")
c.comesFromHeuristic = regs[rb].node.info
of opcNIntVal: of opcNIntVal:
decodeB(rkInt) decodeB(rkInt)
let a = regs[rb].node let a = regs[rb].node
@ -1295,9 +1303,17 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
decodeB(rkNode) decodeB(rkNode)
createStr regs[ra] createStr regs[ra]
let a = regs[rb].node let a = regs[rb].node
if a.kind in {nkStrLit..nkTripleStrLit}: regs[ra].node.strVal = a.strVal case a.kind
elif a.kind == nkCommentStmt: regs[ra].node.strVal = a.comment of {nkStrLit..nkTripleStrLit}:
else: stackTrace(c, tos, pc, errFieldXNotFound, "strVal") regs[ra].node.strVal = a.strVal
of nkCommentStmt:
regs[ra].node.strVal = a.comment
of nkIdent:
regs[ra].node.strVal = a.ident.s
of nkSym:
regs[ra].node.strVal = a.sym.name.s
else:
stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
of opcSlurp: of opcSlurp:
decodeB(rkNode) decodeB(rkNode)
createStr regs[ra] createStr regs[ra]
@ -1387,17 +1403,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
else: else:
regs[ra].node = newNodeI(nkIdent, c.debug[pc]) regs[ra].node = newNodeI(nkIdent, c.debug[pc])
regs[ra].node.ident = getIdent(regs[rb].node.strVal) regs[ra].node.ident = getIdent(regs[rb].node.strVal)
of opcIdentToStr:
decodeB(rkNode)
let a = regs[rb].node
createStr regs[ra]
regs[ra].node.info = c.debug[pc]
if a.kind == nkSym:
regs[ra].node.strVal = a.sym.name.s
elif a.kind == nkIdent:
regs[ra].node.strVal = a.ident.s
else:
stackTrace(c, tos, pc, errFieldXNotFound, "ident")
of opcSetType: of opcSetType:
if regs[ra].kind != rkNode: if regs[ra].kind != rkNode:
internalError(c.debug[pc], "cannot set type") internalError(c.debug[pc], "cannot set type")

View file

@ -79,6 +79,7 @@ type
opcNAdd, opcNAdd,
opcNAddMultiple, opcNAddMultiple,
opcNKind, opcNKind,
opcNSymKind,
opcNIntVal, opcNIntVal,
opcNFloatVal, opcNFloatVal,
opcNSymbol, opcNSymbol,
@ -101,7 +102,6 @@ type
opcNGetLine, opcNGetColumn, opcNGetFile, opcNGetLine, opcNGetColumn, opcNGetFile,
opcEqIdent, opcEqIdent,
opcStrToIdent, opcStrToIdent,
opcIdentToStr,
opcGetImpl, opcGetImpl,
opcEcho, opcEcho,

View file

@ -1080,6 +1080,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mNAdd: genBinaryABC(c, n, dest, opcNAdd) of mNAdd: genBinaryABC(c, n, dest, opcNAdd)
of mNAddMultiple: genBinaryABC(c, n, dest, opcNAddMultiple) of mNAddMultiple: genBinaryABC(c, n, dest, opcNAddMultiple)
of mNKind: genUnaryABC(c, n, dest, opcNKind) of mNKind: genUnaryABC(c, n, dest, opcNKind)
of mNSymKind: genUnaryABC(c, n, dest, opcNSymKind)
of mNIntVal: genUnaryABC(c, n, dest, opcNIntVal) of mNIntVal: genUnaryABC(c, n, dest, opcNIntVal)
of mNFloatVal: genUnaryABC(c, n, dest, opcNFloatVal) of mNFloatVal: genUnaryABC(c, n, dest, opcNFloatVal)
of mNSymbol: genUnaryABC(c, n, dest, opcNSymbol) of mNSymbol: genUnaryABC(c, n, dest, opcNSymbol)
@ -1125,7 +1126,6 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
else: else:
localError(n.info, "invalid bindSym usage") localError(n.info, "invalid bindSym usage")
of mStrToIdent: genUnaryABC(c, n, dest, opcStrToIdent) of mStrToIdent: genUnaryABC(c, n, dest, opcStrToIdent)
of mIdentToStr: genUnaryABC(c, n, dest, opcIdentToStr)
of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent) of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent)
of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimrodNode) of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimrodNode)
of mSameNodeType: genBinaryABC(c, n, dest, opcSameNodeType) of mSameNodeType: genBinaryABC(c, n, dest, opcSameNodeType)

View file

@ -28,12 +28,8 @@ contains:
intVal: BiggestInt ## the int literal intVal: BiggestInt ## the int literal
of nnkFloatLit..nnkFloat64Lit: of nnkFloatLit..nnkFloat64Lit:
floatVal: BiggestFloat ## the float literal floatVal: BiggestFloat ## the float literal
of nnkStrLit..nnkTripleStrLit: of nnkStrLit..nnkTripleStrLit, nnkCommentStmt, nnkIdent, nnkSym:
strVal: string ## the string literal strVal: string ## the string literal
of nnkIdent:
ident: NimIdent ## the identifier
of nnkSym:
symbol: NimSym ## the symbol (after symbol lookup phase)
else: else:
sons: seq[NimNode] ## the node's sons (or children) sons: seq[NimNode] ## the node's sons (or children)
@ -74,8 +70,8 @@ Nim expression Corresponding AST
``"""abc"""`` ``nnkTripleStrLit(strVal = "abc")`` ``"""abc"""`` ``nnkTripleStrLit(strVal = "abc")``
``' '`` ``nnkCharLit(intVal = 32)`` ``' '`` ``nnkCharLit(intVal = 32)``
``nil`` ``nnkNilLit()`` ``nil`` ``nnkNilLit()``
``myIdentifier`` ``nnkIdent(ident = !"myIdentifier")`` ``myIdentifier`` ``nnkIdent(strVal = "myIdentifier")``
``myIdentifier`` after lookup pass: ``nnkSym(symbol = ...)`` ``myIdentifier`` after lookup pass: ``nnkSym(strVal = "myIdentifier", ...)``
----------------- --------------------------------------------- ----------------- ---------------------------------------------
Identifiers are ``nnkIdent`` nodes. After the name lookup pass these nodes Identifiers are ``nnkIdent`` nodes. After the name lookup pass these nodes
@ -97,7 +93,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkCommand( nnkCommand(
nnkIdent(!"echo"), nnkIdent("echo"),
nnkStrLit("abc"), nnkStrLit("abc"),
nnkStrLit("xyz") nnkStrLit("xyz")
) )
@ -115,7 +111,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkCall( nnkCall(
nnkIdent(!"echo"), nnkIdent("echo"),
nnkStrLit("abc"), nnkStrLit("abc"),
nnkStrLit("xyz") nnkStrLit("xyz")
) )
@ -133,7 +129,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkInfix( nnkInfix(
nnkIdent(!"&"), nnkIdent("&"),
nnkStrLit("abc"), nnkStrLit("abc"),
nnkStrLit("xyz") nnkStrLit("xyz")
) )
@ -150,10 +146,10 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkInfix( nnkInfix(
nnkIdent(!"+"), nnkIdent("+"),
nnkIntLit(5), nnkIntLit(5),
nnkInfix( nnkInfix(
nnkIdent(!"*"), nnkIdent("*"),
nnkIntLit(3), nnkIntLit(3),
nnkIntLit(4) nnkIntLit(4)
) )
@ -174,7 +170,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkCall( nnkCall(
nnkAccQuoted( nnkAccQuoted(
nnkIdent(!"+") nnkIdent("+")
), ),
nnkIntLit(3), nnkIntLit(3),
nnkIntLit(4) nnkIntLit(4)
@ -192,7 +188,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkPrefix( nnkPrefix(
nnkIdent(!"?"), nnkIdent("?"),
nnkStrLit("abc") nnkStrLit("abc")
) )
@ -212,8 +208,8 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkPostfix( nnkPostfix(
nnkIdent(!"*"), nnkIdent("*"),
nnkIdent(!"identifier") nnkIdent("identifier")
) )
@ -229,10 +225,10 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkCall( nnkCall(
nnkIdent(!"writeLine"), nnkIdent("writeLine"),
nnkExprEqExpr( nnkExprEqExpr(
nnkIdent(!"file"), nnkIdent("file"),
nnkIdent(!"stdout") nnkIdent("stdout")
), ),
nnkStrLit("hallo") nnkStrLit("hallo")
) )
@ -253,7 +249,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkCallStrLit( nnkCallStrLit(
nnkIdent(!"echo"), nnkIdent("echo"),
nnkRStrLit("hello") nnkRStrLit("hello")
) )
@ -268,7 +264,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkDerefExpr(nnkIdent(!"x")) nnkDerefExpr(nnkIdent("x"))
Addr operator Addr operator
@ -282,7 +278,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkAddr(nnkIdent(!"x")) nnkAddr(nnkIdent("x"))
Cast operator Cast operator
@ -296,7 +292,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkCast(nnkIdent(!"T"), nnkIdent(!"x")) nnkCast(nnkIdent("T"), nnkIdent("x"))
Object access operator ``.`` Object access operator ``.``
@ -310,7 +306,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkDotExpr(nnkIdent(!"x"), nnkIdent(!"y")) nnkDotExpr(nnkIdent("x"), nnkIdent("y"))
If you use Nim's flexible calling syntax (as in ``x.len()``), the result is the If you use Nim's flexible calling syntax (as in ``x.len()``), the result is the
same as above but wrapped in an ``nnkCall``. same as above but wrapped in an ``nnkCall``.
@ -327,7 +323,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkBracketExpr(nnkIdent(!"x"), nnkIdent(!"y")) nnkBracketExpr(nnkIdent("x"), nnkIdent("y"))
Parentheses Parentheses
@ -373,8 +369,8 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkTableConstr( nnkTableConstr(
nnkExprColonExpr(nnkIdent(!"a"), nnkIntLit(3)), nnkExprColonExpr(nnkIdent("a"), nnkIntLit(3)),
nnkExprColonExpr(nnkIdent(!"b"), nnkIntLit(5)) nnkExprColonExpr(nnkIdent("b"), nnkIntLit(5))
) )
@ -410,7 +406,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkInfix( nnkInfix(
nnkIdent(!".."), nnkIdent(".."),
nnkIntLit(1), nnkIntLit(1),
nnkIntLit(3) nnkIntLit(3)
) )
@ -497,7 +493,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkPragma( nnkPragma(
nnkExprColonExpr( nnkExprColonExpr(
nnkIdent(!"emit"), nnkIdent("emit"),
nnkStrLit("#include <stdio.h>") # the "argument" nnkStrLit("#include <stdio.h>") # the "argument"
) )
) )
@ -515,10 +511,10 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkPragma( nnkPragma(
nnkExprColonExpr( nnkExprColonExpr(
nnkIdent(!"pragma"), # this is always first when declaring a new pragma nnkIdent("pragma"), # this is always first when declaring a new pragma
nnkIdent(!"cdeclRename") # the name of the pragma nnkIdent("cdeclRename") # the name of the pragma
), ),
nnkIdent(!"cdecl") nnkIdent("cdecl")
) )
Statements Statements
@ -570,7 +566,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkAsgn(nnkIdent(!"x"), nnkIntLit(42)) nnkAsgn(nnkIdent("x"), nnkIntLit(42))
This is not the syntax for assignment when combined with ``var``, ``let``, This is not the syntax for assignment when combined with ``var``, ``let``,
or ``const``. or ``const``.
@ -736,7 +732,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkBreakStmt(nnkIdent(!"otherLocation")) nnkBreakStmt(nnkIdent("otherLocation"))
If ``break`` is used without a jump-to location, ``nnkEmpty`` replaces ``nnkIdent``. If ``break`` is used without a jump-to location, ``nnkEmpty`` replaces ``nnkIdent``.
@ -751,7 +747,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkBlockStmt(nnkIdent(!"name"), nnkStmtList(...)) nnkBlockStmt(nnkIdent("name"), nnkStmtList(...))
A ``block`` doesn't need an name, in which case ``nnkEmpty`` is used. A ``block`` doesn't need an name, in which case ``nnkEmpty`` is used.
@ -787,7 +783,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkImportStmt(nnkIdent(!"math")) nnkImportStmt(nnkIdent("math"))
With ``except``, we get ``nnkImportExceptStmt``. With ``except``, we get ``nnkImportExceptStmt``.
@ -799,7 +795,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkImportExceptStmt(nnkIdent(!"math"),nnkIdent(!"pow")) nnkImportExceptStmt(nnkIdent("math"),nnkIdent("pow"))
Note that ``import math as m`` does not use a different node; rather, Note that ``import math as m`` does not use a different node; rather,
we use ``nnkImportStmt`` with ``as`` as an infix operator. we use ``nnkImportStmt`` with ``as`` as an infix operator.
@ -814,9 +810,9 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkImportStmt( nnkImportStmt(
nnkInfix( nnkInfix(
nnkIdent(!"as"), nnkIdent("as"),
nnkIdent(!"strutils"), nnkIdent("strutils"),
nnkIdent(!"su") nnkIdent("su")
) )
) )
@ -833,7 +829,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkFromStmt(nnkIdent(!"math"), nnkIdent(!"pow")) nnkFromStmt(nnkIdent("math"), nnkIdent("pow"))
Using ``from math as m import pow`` works identically to the ``as`` modifier Using ``from math as m import pow`` works identically to the ``as`` modifier
with the ``import`` statement, but wrapped in ``nnkFromStmt``. with the ``import`` statement, but wrapped in ``nnkFromStmt``.
@ -852,7 +848,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkExportStmt(nnkIdent(!"unsigned")) nnkExportStmt(nnkIdent("unsigned"))
Similar to the ``import`` statement, the AST is different for Similar to the ``import`` statement, the AST is different for
``export ... except``. ``export ... except``.
@ -865,7 +861,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkExportExceptStmt(nnkIdent(!"math"),nnkIdent(!"pow")) nnkExportExceptStmt(nnkIdent("math"),nnkIdent("pow"))
Include statement Include statement
----------------- -----------------
@ -880,7 +876,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkIncludeStmt(nnkIdent(!"blocks")) nnkIncludeStmt(nnkIdent("blocks"))
Var section Var section
----------- -----------
@ -895,7 +891,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkVarSection( nnkVarSection(
nnkIdentDefs( nnkIdentDefs(
nnkIdent(!"a"), nnkIdent("a"),
nnkEmpty(), # or nnkIdent(...) if the variable declares the type nnkEmpty(), # or nnkIdent(...) if the variable declares the type
nnkIntLit(3), nnkIntLit(3),
) )
@ -925,7 +921,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkLetSection( nnkLetSection(
nnkIdentDefs( nnkIdentDefs(
nnkIdent(!"a"), nnkIdent("a"),
nnkEmpty(), # or nnkIdent(...) for the type nnkEmpty(), # or nnkIdent(...) for the type
nnkIntLit(3), nnkIntLit(3),
) )
@ -944,7 +940,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkConstSection( nnkConstSection(
nnkConstDef( # not nnkConstDefs! nnkConstDef( # not nnkConstDefs!
nnkIdent(!"a"), nnkIdent("a"),
nnkEmpty(), # or nnkIdent(...) if the variable declares the type nnkEmpty(), # or nnkIdent(...) if the variable declares the type
nnkIntLit(3), # required in a const declaration! nnkIntLit(3), # required in a const declaration!
) )
@ -966,9 +962,9 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkTypeSection( nnkTypeSection(
nnkTypeDef( nnkTypeDef(
nnkIdent(!"A"), nnkIdent("A"),
nnkEmpty(), nnkEmpty(),
nnkIdent(!"int") nnkIdent("int")
) )
) )
@ -985,10 +981,10 @@ AST:
.. code-block:: nim .. code-block:: nim
# ... # ...
nnkTypeDef( nnkTypeDef(
nnkIdent(!"MyInt"), nnkIdent("MyInt"),
nnkEmpty(), nnkEmpty(),
nnkDistinctTy( nnkDistinctTy(
nnkIdent(!"int") nnkIdent("int")
) )
) )
@ -1004,10 +1000,10 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkTypeSection( nnkTypeSection(
nnkTypeDef( nnkTypeDef(
nnkIdent(!"A"), nnkIdent("A"),
nnkGenericParams( nnkGenericParams(
nnkIdentDefs( nnkIdentDefs(
nnkIdent(!"T"), nnkIdent("T"),
nnkEmpty(), # if the type is declared with options, like nnkEmpty(), # if the type is declared with options, like
# ``[T: SomeInteger]``, they are given here # ``[T: SomeInteger]``, they are given here
nnkEmpty(), nnkEmpty(),
@ -1031,12 +1027,12 @@ AST:
.. code-block:: nim .. code-block:: nim
# ... # ...
nnkTypeDef( nnkTypeDef(
nnkIdent(!"IO"), nnkIdent("IO"),
nnkEmpty(), nnkEmpty(),
nnkObjectTy( nnkObjectTy(
nnkEmpty(), # no pragmas here nnkEmpty(), # no pragmas here
nnkOfInherit( nnkOfInherit(
nnkIdent(!"RootObj") # inherits from RootObj nnkIdent("RootObj") # inherits from RootObj
) )
nnkEmpty() nnkEmpty()
) )
@ -1062,43 +1058,43 @@ AST:
# ... # ...
nnkObjectTy( nnkObjectTy(
nnkPragma( nnkPragma(
nnkIdent(!"inheritable") nnkIdent("inheritable")
), ),
nnkEmpty(), nnkEmpty(),
nnkRecList( # list of object parameters nnkRecList( # list of object parameters
nnkIdentDefs( nnkIdentDefs(
nnkIdent(!"name"), nnkIdent("name"),
nnkIdent(!"string"), nnkIdent("string"),
nnkEmpty() nnkEmpty()
), ),
nnkRecCase( # case statement within object (not nnkCaseStmt) nnkRecCase( # case statement within object (not nnkCaseStmt)
nnkIdentDefs( nnkIdentDefs(
nnkIdent(!"isFat"), nnkIdent("isFat"),
nnkIdent(!"bool"), nnkIdent("bool"),
nnkEmpty() nnkEmpty()
), ),
nnkOfBranch( nnkOfBranch(
nnkIdent(!"true"), nnkIdent("true"),
nnkRecList( # again, a list of object parameters nnkRecList( # again, a list of object parameters
nnkIdentDefs( nnkIdentDefs(
nnkIdent(!"m"), nnkIdent("m"),
nnkBracketExpr( nnkBracketExpr(
nnkIdent(!"array"), nnkIdent("array"),
nnkIntLit(100000), nnkIntLit(100000),
nnkIdent(!"T") nnkIdent("T")
), ),
nnkEmpty() nnkEmpty()
) )
), ),
nnkOfBranch( nnkOfBranch(
nnkIdent(!"false"), nnkIdent("false"),
nnkRecList( nnkRecList(
nnkIdentDefs( nnkIdentDefs(
nnkIdent(!"m"), nnkIdent("m"),
nnkBracketExpr( nnkBracketExpr(
nnkIdent(!"array"), nnkIdent("array"),
nnkIntLit(10), nnkIntLit(10),
nnkIdent(!"T") nnkIdent("T")
), ),
nnkEmpty() nnkEmpty()
) )
@ -1123,7 +1119,7 @@ AST:
# ... # ...
nnkEnumTy( nnkEnumTy(
nnkEmpty(), nnkEmpty(),
nnkIdent(!"First") # you need at least one nnkIdent or the compiler complains nnkIdent("First") # you need at least one nnkIdent or the compiler complains
) )
The usage of ``concept`` (experimental) is similar to objects. The usage of ``concept`` (experimental) is similar to objects.
@ -1158,9 +1154,9 @@ AST:
.. code-block:: nim .. code-block:: nim
# ... within nnkGenericParams # ... within nnkGenericParams
nnkIdentDefs( nnkIdentDefs(
nnkIdent(!"T"), nnkIdent("T"),
nnkStaticTy( nnkStaticTy(
nnkIdent(!"int") nnkIdent("int")
), ),
nnkEmpty() nnkEmpty()
) )
@ -1180,7 +1176,7 @@ Nim type Corresponding AST
``distinct`` ``nnkDistinctTy`` ``distinct`` ``nnkDistinctTy``
``enum`` ``nnkEnumTy`` ``enum`` ``nnkEnumTy``
``concept`` ``nnkTypeClassTy``\* ``concept`` ``nnkTypeClassTy``\*
``array`` ``nnkBracketExpr(nnkIdent(!"array"),...``\* ``array`` ``nnkBracketExpr(nnkIdent("array"),...``\*
``proc`` ``nnkProcTy`` ``proc`` ``nnkProcTy``
``iterator`` ``nnkIteratorTy`` ``iterator`` ``nnkIteratorTy``
``object`` ``nnkObjectTy`` ``object`` ``nnkObjectTy``
@ -1200,7 +1196,7 @@ AST:
.. code-block:: nim .. code-block:: nim
# ... # ...
nnkTypeDef( nnkTypeDef(
nnkIdent(!"MyProc"), nnkIdent("MyProc"),
nnkGenericParams( # here, not with the proc nnkGenericParams( # here, not with the proc
# ... # ...
) )
@ -1225,7 +1221,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkMixinStmt(nnkIdent(!"x")) nnkMixinStmt(nnkIdent("x"))
Bind statement Bind statement
-------------- --------------
@ -1238,7 +1234,7 @@ Concrete syntax:
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkBindStmt(nnkIdent(!"x")) nnkBindStmt(nnkIdent("x"))
Procedure declaration Procedure declaration
--------------------- ---------------------
@ -1255,26 +1251,26 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkProcDef( nnkProcDef(
nnkPostfix(nnkIdent(!"*"), nnkIdent(!"hello")), # the exported proc name nnkPostfix(nnkIdent("*"), nnkIdent("hello")), # the exported proc name
nnkEmpty(), # patterns for term rewriting in templates and macros (not procs) nnkEmpty(), # patterns for term rewriting in templates and macros (not procs)
nnkGenericParams( # generic type parameters, like with type declaration nnkGenericParams( # generic type parameters, like with type declaration
nnkIdentDefs( nnkIdentDefs(
nnkIdent(!"T"), nnkIdent(!"SomeInteger") nnkIdent("T"), nnkIdent("SomeInteger")
) )
), ),
nnkFormalParams( nnkFormalParams(
nnkIdent(!"int"), # the first FormalParam is the return type. nnkEmpty() if there is none nnkIdent("int"), # the first FormalParam is the return type. nnkEmpty() if there is none
nnkIdentDefs( nnkIdentDefs(
nnkIdent(!"x"), nnkIdent("x"),
nnkIdent(!"int"), # type type (required for procs, not for templates) nnkIdent("int"), # type type (required for procs, not for templates)
nnkIntLit(3) # a default value nnkIntLit(3) # a default value
), ),
nnkIdentDefs( nnkIdentDefs(
nnkIdent(!"y"), nnkIdent("y"),
nnkIdent(!"float32"), nnkIdent("float32"),
nnkEmpty() nnkEmpty()
) )
nnkPragma(nnkIdent(!"inline")), nnkPragma(nnkIdent("inline")),
nnkEmpty(), # reserved slot for future use nnkEmpty(), # reserved slot for future use
nnkStmtList(nnkDiscardStmt(nnkEmpty())) # the meat of the proc nnkStmtList(nnkDiscardStmt(nnkEmpty())) # the meat of the proc
) )
@ -1296,9 +1292,9 @@ AST:
nnkFormalParams( nnkFormalParams(
nnkEmpty(), # no return here nnkEmpty(), # no return here
nnkIdentDefs( nnkIdentDefs(
nnkIdent(!"a"), # the first parameter nnkIdent("a"), # the first parameter
nnkIdent(!"b"), # directly to the second parameter nnkIdent("b"), # directly to the second parameter
nnkIdent(!"int"), # their shared type identifier nnkIdent("int"), # their shared type identifier
nnkEmpty(), # default value would go here nnkEmpty(), # default value would go here
) )
), ),
@ -1318,7 +1314,7 @@ AST:
# ... # ...
nnkFormalParams( nnkFormalParams(
nnkVarTy( nnkVarTy(
nnkIdent(!"int") nnkIdent("int")
) )
) )
@ -1337,7 +1333,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkIteratorDef( nnkIteratorDef(
nnkIdent(!"nonsense"), nnkIdent("nonsense"),
nnkEmpty(), nnkEmpty(),
... ...
) )
@ -1356,7 +1352,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkConverterDef( nnkConverterDef(
nnkIdent(!"toBool"), nnkIdent("toBool"),
# ... # ...
) )
@ -1378,7 +1374,7 @@ AST:
.. code-block:: nim .. code-block:: nim
nnkTemplateDef( nnkTemplateDef(
nnkIdent(!"optOpt"), nnkIdent("optOpt"),
nnkStmtList( # instead of nnkEmpty() nnkStmtList( # instead of nnkEmpty()
expr1 expr1
), ),

View file

@ -118,7 +118,7 @@ type
## use ``ident"abc"``. ## use ``ident"abc"``.
NimSymObj = object # hidden NimSymObj = object # hidden
NimSym* = ref NimSymObj NimSym* {.deprecated.} = ref NimSymObj
## represents a Nim *symbol* in the compiler; a *symbol* is a looked-up ## represents a Nim *symbol* in the compiler; a *symbol* is a looked-up
## *ident*. ## *ident*.
@ -134,25 +134,23 @@ const
proc `!`*(s: string): NimIdent {.magic: "StrToIdent", noSideEffect, deprecated.} proc `!`*(s: string): NimIdent {.magic: "StrToIdent", noSideEffect, deprecated.}
## constructs an identifier from the string `s` ## constructs an identifier from the string `s`
## **Deprecated since version 0.18.0**: Use ``toNimIdent`` instead. ## **Deprecated since version 0.18.0**: Use ``ident`` or ``newIdentNode`` instead.
proc toNimIdent*(s: string): NimIdent {.magic: "StrToIdent", noSideEffect.} proc toNimIdent*(s: string): NimIdent {.magic: "StrToIdent", noSideEffect, deprecated.}
## constructs an identifier from the string `s` ## constructs an identifier from the string `s`
## **Deprecated since version 0.18.1**; Use ``ident`` or ``newIdentNode`` instead.
proc `$`*(i: NimIdent): string {.magic: "IdentToStr", noSideEffect.} proc `==`*(a, b: NimIdent): bool {.magic: "EqIdent", noSideEffect, deprecated.}
## converts a Nim identifier to a string
proc `$`*(s: NimSym): string {.magic: "IdentToStr", noSideEffect.}
## converts a Nim symbol to a string
proc `==`*(a, b: NimIdent): bool {.magic: "EqIdent", noSideEffect.}
## compares two Nim identifiers ## compares two Nim identifiers
## **Deprecated since version 0.18.1**; Use ``==`` on ``NimNode`` instead.
proc `==`*(a, b: NimNode): bool {.magic: "EqNimrodNode", noSideEffect.} proc `==`*(a, b: NimNode): bool {.magic: "EqNimrodNode", noSideEffect.}
## compares two Nim nodes ## compares two Nim nodes
proc `==`*(a, b: NimSym): bool {.magic: "EqNimrodNode", noSideEffect.} proc `==`*(a, b: NimSym): bool {.magic: "EqNimrodNode", noSideEffect, deprecated.}
## compares two Nim symbols ## compares two Nim symbols
## **Deprecated since version 0.18.1**; Use ```==`(NimNode,NimNode)`` instead.
proc sameType*(a, b: NimNode): bool {.magic: "SameNodeType", noSideEffect.} = proc sameType*(a, b: NimNode): bool {.magic: "SameNodeType", noSideEffect.} =
## compares two Nim nodes' types. Return true if the types are the same, ## compares two Nim nodes' types. Return true if the types are the same,
@ -195,8 +193,47 @@ proc kind*(n: NimNode): NimNodeKind {.magic: "NKind", noSideEffect.}
proc intVal*(n: NimNode): BiggestInt {.magic: "NIntVal", noSideEffect.} proc intVal*(n: NimNode): BiggestInt {.magic: "NIntVal", noSideEffect.}
proc floatVal*(n: NimNode): BiggestFloat {.magic: "NFloatVal", noSideEffect.} proc floatVal*(n: NimNode): BiggestFloat {.magic: "NFloatVal", noSideEffect.}
proc symbol*(n: NimNode): NimSym {.magic: "NSymbol", noSideEffect.}
proc ident*(n: NimNode): NimIdent {.magic: "NIdent", noSideEffect.} proc ident*(n: NimNode): NimIdent {.magic: "NIdent", noSideEffect, deprecated.} =
## **Deprecated since version 0.18.1**; All functionality is defined on ``NimNode``.
proc symbol*(n: NimNode): NimSym {.magic: "NSymbol", noSideEffect, deprecated.}
## **Deprecated since version 0.18.1**; All functionality is defined on ``NimNode``.
proc getImpl*(s: NimSym): NimNode {.magic: "GetImpl", noSideEffect, deprecated: "use `getImpl: NimNode -> NimNode` instead".}
when defined(nimSymKind):
proc symKind*(symbol: NimNode): NimSymKind {.magic: "NSymKind", noSideEffect.}
proc getImpl*(symbol: NimNode): NimNode {.magic: "GetImpl", noSideEffect.}
proc strVal*(n: NimNode): string {.magic: "NStrVal", noSideEffect.}
## retrieve the implementation of `symbol`. `symbol` can be a
## routine or a const.
proc `$`*(i: NimIdent): string {.magic: "NStrVal", noSideEffect, deprecated.}
## converts a Nim identifier to a string
## **Deprecated since version 0.18.1**; Use ``strVal`` instead.
proc `$`*(s: NimSym): string {.magic: "NStrVal", noSideEffect, deprecated.}
## converts a Nim symbol to a string
## **Deprecated since version 0.18.1**; Use ``strVal`` instead.
else: # bootstrapping substitute
proc getImpl*(symbol: NimNode): NimNode =
symbol.symbol.getImpl
proc strValOld(n: NimNode): string {.magic: "NStrVal", noSideEffect.}
proc `$`*(s: NimSym): string {.magic: "IdentToStr", noSideEffect.}
proc `$`*(i: NimIdent): string {.magic: "IdentToStr", noSideEffect.}
proc strVal*(n: NimNode): string =
if n.kind == nnkIdent:
$n.ident
elif n.kind == nnkSym:
$n.symbol
else:
n.strValOld
proc getType*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.} proc getType*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.}
## with 'getType' you can access the node's `type`:idx:. A Nim type is ## with 'getType' you can access the node's `type`:idx:. A Nim type is
@ -228,12 +265,15 @@ proc getTypeImpl*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.}
proc getTypeImpl*(n: typedesc): NimNode {.magic: "NGetType", noSideEffect.} proc getTypeImpl*(n: typedesc): NimNode {.magic: "NGetType", noSideEffect.}
## Like getType except it includes generic parameters for the implementation ## Like getType except it includes generic parameters for the implementation
proc strVal*(n: NimNode): string {.magic: "NStrVal", noSideEffect.}
proc `intVal=`*(n: NimNode, val: BiggestInt) {.magic: "NSetIntVal", noSideEffect.} proc `intVal=`*(n: NimNode, val: BiggestInt) {.magic: "NSetIntVal", noSideEffect.}
proc `floatVal=`*(n: NimNode, val: BiggestFloat) {.magic: "NSetFloatVal", noSideEffect.} proc `floatVal=`*(n: NimNode, val: BiggestFloat) {.magic: "NSetFloatVal", noSideEffect.}
proc `symbol=`*(n: NimNode, val: NimSym) {.magic: "NSetSymbol", noSideEffect.}
proc `ident=`*(n: NimNode, val: NimIdent) {.magic: "NSetIdent", noSideEffect.} proc `symbol=`*(n: NimNode, val: NimSym) {.magic: "NSetSymbol", noSideEffect, deprecated.}
## **Deprecated since version 0.18.1**; Generate a new ``NimNode`` with ``genSym`` instead.
proc `ident=`*(n: NimNode, val: NimIdent) {.magic: "NSetIdent", noSideEffect, deprecated.}
## **Deprecated since version 0.18.1**; Generate a new ``NimNode`` with ``ident(string)`` instead.
#proc `typ=`*(n: NimNode, typ: typedesc) {.magic: "NSetType".} #proc `typ=`*(n: NimNode, typ: typedesc) {.magic: "NSetType".}
# this is not sound! Unfortunately forbidding 'typ=' is not enough, as you # this is not sound! Unfortunately forbidding 'typ=' is not enough, as you
# can easily do: # can easily do:
@ -255,11 +295,6 @@ proc newNimNode*(kind: NimNodeKind,
proc copyNimNode*(n: NimNode): NimNode {.magic: "NCopyNimNode", noSideEffect.} proc copyNimNode*(n: NimNode): NimNode {.magic: "NCopyNimNode", noSideEffect.}
proc copyNimTree*(n: NimNode): NimNode {.magic: "NCopyNimTree", noSideEffect.} proc copyNimTree*(n: NimNode): NimNode {.magic: "NCopyNimTree", noSideEffect.}
proc getImpl*(s: NimSym): NimNode {.magic: "GetImpl", noSideEffect.} =
## retrieve the implementation of a symbol `s`. `s` can be a routine or a
## const.
discard
proc error*(msg: string, n: NimNode = nil) {.magic: "NError", benign.} proc error*(msg: string, n: NimNode = nil) {.magic: "NError", benign.}
## writes an error message at compile time ## writes an error message at compile time
@ -294,11 +329,9 @@ proc newIdentNode*(i: NimIdent): NimNode {.compileTime.} =
result = newNimNode(nnkIdent) result = newNimNode(nnkIdent)
result.ident = i result.ident = i
proc newIdentNode*(i: string): NimNode {.compileTime.} = proc newIdentNode*(i: string): NimNode {.magic: "StrToIdent", noSideEffect.}
## creates an identifier node from `i` ## creates an identifier node from `i`. It is simply an alias for
result = newNimNode(nnkIdent) ## ``ident(string)``. Use that, it's shorter.
result.ident = toNimIdent i
type type
BindSymRule* = enum ## specifies how ``bindSym`` behaves BindSymRule* = enum ## specifies how ``bindSym`` behaves
@ -464,9 +497,11 @@ proc newCall*(theProc: NimNode,
result.add(args) result.add(args)
proc newCall*(theProc: NimIdent, proc newCall*(theProc: NimIdent,
args: varargs[NimNode]): NimNode {.compileTime.} = args: varargs[NimNode]): NimNode {.compileTime, deprecated.} =
## produces a new call node. `theProc` is the proc that is called with ## produces a new call node. `theProc` is the proc that is called with
## the arguments ``args[0..]``. ## the arguments ``args[0..]``.
## **Deprecated since version 0.18.1**; Use ``newCall(string, ...)``,
## or ``newCall(NimNode, ...)`` instead.
result = newNimNode(nnkCall) result = newNimNode(nnkCall)
result.add(newIdentNode(theProc)) result.add(newIdentNode(theProc))
result.add(args) result.add(args)
@ -594,17 +629,30 @@ proc newLit*(s: string): NimNode {.compileTime.} =
result = newNimNode(nnkStrLit) result = newNimNode(nnkStrLit)
result.strVal = s result.strVal = s
proc nestList*(theProc: NimIdent, proc nestList*(op: NimNode; pack: NimNode): NimNode {.compileTime.} =
x: NimNode): NimNode {.compileTime.} = ## nests the list `pack` into a tree of call expressions:
## nests the list `x` into a tree of call expressions: ## ``[a, b, c]`` is transformed into ``op(a, op(c, d))``.
## ``[a, b, c]`` is transformed into ``theProc(a, theProc(c, d))``. ## This is also known as fold expression.
if pack.len < 1:
error("`nestList` expects a node with at least 1 child")
result = pack[^1]
for i in countdown(pack.len - 2, 0):
result = newCall(op, pack[i], result)
proc nestList*(op: NimNode; pack: NimNode; init: NimNode): NimNode {.compileTime.} =
## nests the list `pack` into a tree of call expressions:
## ``[a, b, c]`` is transformed into ``op(a, op(c, d))``.
## This is also known as fold expression.
result = init
for i in countdown(pack.len - 1, 0):
result = newCall(op, pack[i], result)
proc nestList*(theProc: NimIdent, x: NimNode): NimNode {.compileTime, deprecated.} =
## **Deprecated since version 0.18.1**; Use one of ``nestList(NimNode, ...)`` instead.
var L = x.len var L = x.len
result = newCall(theProc, x[L-2], x[L-1]) result = newCall(theProc, x[L-2], x[L-1])
for i in countdown(L-3, 0): for i in countdown(L-3, 0):
# XXX the 'copyNimTree' here is necessary due to a bug in the evaluation result = newCall(theProc, x[i], result)
# engine that would otherwise create an endless loop here. :-(
# This could easily user code and so should be fixed in evals.nim somehow.
result = newCall(theProc, x[i], copyNimTree(result))
proc treeRepr*(n: NimNode): string {.compileTime, benign.} = proc treeRepr*(n: NimNode): string {.compileTime, benign.} =
## Convert the AST `n` to a human-readable tree-like string. ## Convert the AST `n` to a human-readable tree-like string.
@ -620,9 +668,8 @@ proc treeRepr*(n: NimNode): string {.compileTime, benign.} =
of nnkNilLit: res.add(" nil") of nnkNilLit: res.add(" nil")
of nnkCharLit..nnkInt64Lit: res.add(" " & $n.intVal) of nnkCharLit..nnkInt64Lit: res.add(" " & $n.intVal)
of nnkFloatLit..nnkFloat64Lit: res.add(" " & $n.floatVal) of nnkFloatLit..nnkFloat64Lit: res.add(" " & $n.floatVal)
of nnkStrLit..nnkTripleStrLit: res.add(" " & $n.strVal.newLit.repr) of nnkStrLit..nnkTripleStrLit, nnkIdent, nnkSym:
of nnkIdent: res.add(" ident\"" & $n.ident & '"') res.add(" " & $n.strVal.newLit.repr)
of nnkSym: res.add(" \"" & $n.symbol & '"')
of nnkNone: assert false of nnkNone: assert false
else: else:
for j in 0..n.len-1: for j in 0..n.len-1:
@ -645,9 +692,8 @@ proc lispRepr*(n: NimNode): string {.compileTime, benign.} =
of nnkNilLit: add(result, "nil") of nnkNilLit: add(result, "nil")
of nnkCharLit..nnkInt64Lit: add(result, $n.intVal) of nnkCharLit..nnkInt64Lit: add(result, $n.intVal)
of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal) of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal)
of nnkStrLit..nnkTripleStrLit, nnkCommentStmt: add(result, n.strVal.newLit.repr) of nnkStrLit..nnkTripleStrLit, nnkCommentStmt, nnkident, nnkSym:
of nnkIdent: add(result, "ident\"" & $n.ident & '"') add(result, n.strVal.newLit.repr)
of nnkSym: add(result, $n.symbol)
of nnkNone: assert false of nnkNone: assert false
else: else:
if n.len > 0: if n.len > 0:
@ -696,9 +742,8 @@ proc astGenRepr*(n: NimNode): string {.compileTime, benign.} =
of nnkCharLit: res.add("'" & $chr(n.intVal) & "'") of nnkCharLit: res.add("'" & $chr(n.intVal) & "'")
of nnkIntLit..nnkInt64Lit: res.add($n.intVal) of nnkIntLit..nnkInt64Lit: res.add($n.intVal)
of nnkFloatLit..nnkFloat64Lit: res.add($n.floatVal) of nnkFloatLit..nnkFloat64Lit: res.add($n.floatVal)
of nnkStrLit..nnkTripleStrLit, nnkCommentStmt: res.add($n.strVal.newLit.repr) of nnkStrLit..nnkTripleStrLit, nnkCommentStmt, nnkIdent, nnkSym:
of nnkIdent: res.add(($n.ident).newLit.repr()) res.add(n.strVal.newLit.repr)
of nnkSym: res.add(($n.symbol).newLit.repr())
of nnkNone: assert false of nnkNone: assert false
else: else:
res.add(".newTree(") res.add(".newTree(")
@ -742,10 +787,10 @@ macro dumpAstGen*(s: untyped): untyped = echo s.astGenRepr
## See `dumpTree`. ## See `dumpTree`.
macro dumpTreeImm*(s: untyped): untyped {.deprecated.} = echo s.treeRepr macro dumpTreeImm*(s: untyped): untyped {.deprecated.} = echo s.treeRepr
## Deprecated. ## Deprecated. Use `dumpTree` instead.
macro dumpLispImm*(s: untyped): untyped {.deprecated.} = echo s.lispRepr macro dumpLispImm*(s: untyped): untyped {.deprecated.} = echo s.lispRepr
## Deprecated. ## Deprecated. Use `dumpLisp` instead.
proc newEmptyNode*(): NimNode {.compileTime, noSideEffect.} = proc newEmptyNode*(): NimNode {.compileTime, noSideEffect.} =
## Create a new empty node ## Create a new empty node
@ -991,28 +1036,21 @@ proc `body=`*(someProc: NimNode, val: NimNode) {.compileTime.} =
proc basename*(a: NimNode): NimNode {.compiletime, benign.} proc basename*(a: NimNode): NimNode {.compiletime, benign.}
proc `$`*(node: NimNode): string {.compileTime.} = proc `$`*(node: NimNode): string {.compileTime.} =
## Get the string of an identifier node ## Get the string of an identifier node
case node.kind case node.kind
of nnkIdent:
result = $node.ident
of nnkPostfix: of nnkPostfix:
result = $node.basename.ident & "*" result = node.basename.strVal & "*"
of nnkStrLit..nnkTripleStrLit: of nnkStrLit..nnkTripleStrLit, nnkCommentStmt, nnkSym, nnkIdent:
result = node.strVal result = node.strVal
of nnkSym:
result = $node.symbol
of nnkOpenSymChoice, nnkClosedSymChoice: of nnkOpenSymChoice, nnkClosedSymChoice:
result = $node[0] result = $node[0]
of nnkAccQuoted: of nnkAccQuoted:
result = $node[0] result = $node[0]
of nnkCommentStmt:
result = node.strVal
else: else:
badNodeKind node.kind, "$" badNodeKind node.kind, "$"
proc ident*(name: string): NimNode {.compileTime,inline.} = newIdentNode(name) proc ident*(name: string): NimNode {.magic: "StrToIdent", noSideEffect.}
## Create a new ident node from a string ## Create a new ident node from a string
iterator items*(n: NimNode): NimNode {.inline.} = iterator items*(n: NimNode): NimNode {.inline.} =
@ -1129,10 +1167,8 @@ proc eqIdent*(node: NimNode; s: string): bool {.compileTime.} =
## is the same as ``s``. Note that this is the preferred way to check! Most ## is the same as ``s``. Note that this is the preferred way to check! Most
## other ways like ``node.ident`` are much more error-prone, unfortunately. ## other ways like ``node.ident`` are much more error-prone, unfortunately.
case node.kind case node.kind
of nnkIdent: of nnkSym, nnkIdent:
result = node.ident == toNimIdent s result = eqIdent(node.strVal, s)
of nnkSym:
result = eqIdent($node.symbol, s)
of nnkOpenSymChoice, nnkClosedSymChoice: of nnkOpenSymChoice, nnkClosedSymChoice:
result = eqIdent($node[0], s) result = eqIdent($node[0], s)
else: else:
@ -1189,11 +1225,11 @@ macro expandMacros*(body: typed): untyped =
proc customPragmaNode(n: NimNode): NimNode = proc customPragmaNode(n: NimNode): NimNode =
expectKind(n, {nnkSym, nnkDotExpr}) expectKind(n, {nnkSym, nnkDotExpr})
if n.kind == nnkSym: if n.kind == nnkSym:
let sym = n.symbol.getImpl() let sym = n.getImpl()
sym.expectRoutine() sym.expectRoutine()
result = sym.pragma result = sym.pragma
elif n.kind == nnkDotExpr: elif n.kind == nnkDotExpr:
let typDef = getImpl(getTypeInst(n[0]).symbol) let typDef = getImpl(getTypeInst(n[0]))
typDef.expectKind(nnkTypeDef) typDef.expectKind(nnkTypeDef)
typDef[2].expectKind(nnkObjectTy) typDef[2].expectKind(nnkObjectTy)
let recList = typDef[2][2] let recList = typDef[2][2]

View file

@ -92,8 +92,10 @@ proc xmlCheckedTag*(e: NimNode, tag: string, optAttr = "", reqAttr = "",
result.add(newStrLitNode("</")) result.add(newStrLitNode("</"))
result.add(newStrLitNode(tag)) result.add(newStrLitNode(tag))
result.add(newStrLitNode(">")) result.add(newStrLitNode(">"))
result = nestList(!"&", result) when compiles(nestList(ident"&", result)):
result = nestList(ident"&", result)
else:
result = nestList(!"&", result)
macro a*(e: varargs[untyped]): untyped = macro a*(e: varargs[untyped]): untyped =
## generates the HTML ``a`` element. ## generates the HTML ``a`` element.

View file

@ -28,6 +28,7 @@ macro async2(prc: untyped): untyped =
# -> iterator nameIter(): FutureBase {.closure.} = <proc_body> # -> iterator nameIter(): FutureBase {.closure.} = <proc_body>
# Changing this line to: newIdentNode($prc[0].ident & "Iter") # will make it work. # 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].ident & "Iter")
assert iteratorNameSym.symKind == nskIterator
#var iteratorNameSym = newIdentNode($prc[0].ident & "Iter") #var iteratorNameSym = newIdentNode($prc[0].ident & "Iter")
var procBody = prc[6].convertReturns(retFutureSym) var procBody = prc[6].convertReturns(retFutureSym)
@ -42,6 +43,7 @@ macro async2(prc: untyped): untyped =
var varNameIter = newVarStmt(varNameIterSym, iteratorNameSym) var varNameIter = newVarStmt(varNameIterSym, iteratorNameSym)
outerProcBody.add varNameIter outerProcBody.add varNameIter
var varFirstSym = genSym(nskVar, "first") var varFirstSym = genSym(nskVar, "first")
assert varFirstSym.symKind == nskVar
var varFirst = newVarStmt(varFirstSym, newCall(varNameIterSym)) var varFirst = newVarStmt(varFirstSym, newCall(varNameIterSym))
outerProcBody.add varFirst outerProcBody.add varFirst

View file

@ -1,82 +1,82 @@
discard """ discard """
nimout: ''' nimout: '''
StmtList StmtList
Ident ident"foo010" Ident "foo010"
Call Call
Ident ident"foo020" Ident "foo020"
Call Call
Ident ident"foo030" Ident "foo030"
Ident ident"x" Ident "x"
Command Command
Ident ident"foo040" Ident "foo040"
Ident ident"x" Ident "x"
Call Call
Ident ident"foo050" Ident "foo050"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident ident"foo060" Ident "foo060"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident ident"foo070" Ident "foo070"
StrLit "test" StrLit "test"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident ident"foo080" Ident "foo080"
StrLit "test" StrLit "test"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident ident"foo090" Ident "foo090"
StrLit "test" StrLit "test"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident ident"foo100" Ident "foo100"
Call Call
StrLit "test" StrLit "test"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident ident"foo101" Ident "foo101"
Call Call
IntLit 10 IntLit 10
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident ident"foo110" Ident "foo110"
IntLit 1 IntLit 1
Par Par
Infix Infix
Ident ident"+" Ident "+"
IntLit 2 IntLit 2
IntLit 3 IntLit 3
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident ident"foo120" Ident "foo120"
IntLit 1 IntLit 1
Call Call
Par Par
Infix Infix
Ident ident"+" Ident "+"
IntLit 2 IntLit 2
IntLit 3 IntLit 3
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident ident"foo130" Ident "foo130"
Do Do
Empty Empty
Empty Empty
@ -84,7 +84,7 @@ StmtList
FormalParams FormalParams
Empty Empty
IdentDefs IdentDefs
Ident ident"x" Ident "x"
Empty Empty
Empty Empty
Empty Empty
@ -93,7 +93,7 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident ident"foo140" Ident "foo140"
Do Do
Empty Empty
Empty Empty
@ -101,8 +101,8 @@ StmtList
FormalParams FormalParams
Empty Empty
IdentDefs IdentDefs
Ident ident"x" Ident "x"
Ident ident"int" Ident "int"
Empty Empty
Empty Empty
Empty Empty
@ -110,16 +110,16 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident ident"foo150" Ident "foo150"
Do Do
Empty Empty
Empty Empty
Empty Empty
FormalParams FormalParams
Ident ident"int" Ident "int"
IdentDefs IdentDefs
Ident ident"x" Ident "x"
Ident ident"int" Ident "int"
Empty Empty
Empty Empty
Empty Empty
@ -127,9 +127,9 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident ident"foo160" Ident "foo160"
Call Call
Ident ident"x" Ident "x"
Do Do
Empty Empty
Empty Empty
@ -137,7 +137,7 @@ StmtList
FormalParams FormalParams
Empty Empty
IdentDefs IdentDefs
Ident ident"y" Ident "y"
Empty Empty
Empty Empty
Empty Empty
@ -146,7 +146,7 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident ident"foo170" Ident "foo170"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
@ -155,7 +155,7 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident ident"foo180" Ident "foo180"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
@ -167,9 +167,9 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Command Command
Ident ident"foo190" Ident "foo190"
Call Call
Ident ident"x" Ident "x"
Do Do
Empty Empty
Empty Empty
@ -177,7 +177,7 @@ StmtList
FormalParams FormalParams
Empty Empty
IdentDefs IdentDefs
Ident ident"y" Ident "y"
Empty Empty
Empty Empty
Empty Empty
@ -190,9 +190,9 @@ StmtList
Empty Empty
Empty Empty
FormalParams FormalParams
Ident ident"int" Ident "int"
IdentDefs IdentDefs
Ident ident"z" Ident "z"
Empty Empty
Empty Empty
Empty Empty
@ -205,10 +205,10 @@ StmtList
Empty Empty
Empty Empty
FormalParams FormalParams
Ident ident"int" Ident "int"
IdentDefs IdentDefs
Ident ident"w" Ident "w"
Ident ident"int" Ident "int"
Empty Empty
Empty Empty
Empty Empty
@ -223,10 +223,10 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
Ident ident"foo200" Ident "foo200"
Ident ident"x" Ident "x"
Call Call
Ident ident"bar" Ident "bar"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
@ -236,53 +236,53 @@ StmtList
Empty Empty
VarSection VarSection
IdentDefs IdentDefs
Ident ident"a" Ident "a"
Empty Empty
Ident ident"foo210" Ident "foo210"
VarSection VarSection
IdentDefs IdentDefs
Ident ident"a" Ident "a"
Empty Empty
Call Call
Ident ident"foo220" Ident "foo220"
VarSection VarSection
IdentDefs IdentDefs
Ident ident"a" Ident "a"
Empty Empty
Call Call
Ident ident"foo230" Ident "foo230"
Ident ident"x" Ident "x"
VarSection VarSection
IdentDefs IdentDefs
Ident ident"a" Ident "a"
Empty Empty
Command Command
Ident ident"foo240" Ident "foo240"
Ident ident"x" Ident "x"
VarSection VarSection
IdentDefs IdentDefs
Ident ident"a" Ident "a"
Empty Empty
Call Call
Ident ident"foo250" Ident "foo250"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
VarSection VarSection
IdentDefs IdentDefs
Ident ident"a" Ident "a"
Empty Empty
Call Call
Ident ident"foo260" Ident "foo260"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
VarSection VarSection
IdentDefs IdentDefs
Ident ident"a" Ident "a"
Empty Empty
Call Call
Ident ident"foo270" Ident "foo270"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
@ -292,12 +292,12 @@ StmtList
Empty Empty
VarSection VarSection
IdentDefs IdentDefs
Ident ident"a" Ident "a"
Empty Empty
Command Command
Ident ident"foo280" Ident "foo280"
Call Call
Ident ident"x" Ident "x"
Do Do
Empty Empty
Empty Empty
@ -305,7 +305,7 @@ StmtList
FormalParams FormalParams
Empty Empty
IdentDefs IdentDefs
Ident ident"y" Ident "y"
Empty Empty
Empty Empty
Empty Empty
@ -318,40 +318,40 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Asgn Asgn
Ident ident"a" Ident "a"
Ident ident"foo290" Ident "foo290"
Asgn Asgn
Ident ident"a" Ident "a"
Call Call
Ident ident"foo300" Ident "foo300"
Asgn Asgn
Ident ident"a" Ident "a"
Call Call
Ident ident"foo310" Ident "foo310"
Ident ident"x" Ident "x"
Asgn Asgn
Ident ident"a" Ident "a"
Command Command
Ident ident"foo320" Ident "foo320"
Ident ident"x" Ident "x"
Asgn Asgn
Ident ident"a" Ident "a"
Call Call
Ident ident"foo330" Ident "foo330"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Asgn Asgn
Ident ident"a" Ident "a"
Call Call
Ident ident"foo340" Ident "foo340"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Asgn Asgn
Ident ident"a" Ident "a"
Call Call
Ident ident"foo350" Ident "foo350"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
@ -360,13 +360,13 @@ StmtList
DiscardStmt DiscardStmt
Empty Empty
Asgn Asgn
Ident ident"a" Ident "a"
Command Command
Ident ident"foo360" Ident "foo360"
Call Call
DotExpr DotExpr
Ident ident"x" Ident "x"
Ident ident"bar" Ident "bar"
Do Do
Empty Empty
Empty Empty
@ -374,7 +374,7 @@ StmtList
FormalParams FormalParams
Empty Empty
IdentDefs IdentDefs
Ident ident"y" Ident "y"
Empty Empty
Empty Empty
Empty Empty
@ -388,20 +388,20 @@ StmtList
Empty Empty
Command Command
DotExpr DotExpr
Ident ident"foo370" Ident "foo370"
Ident ident"add" Ident "add"
Call Call
Ident ident"quote" Ident "quote"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty
Call Call
DotExpr DotExpr
Ident ident"foo380" Ident "foo380"
Ident ident"add" Ident "add"
BracketExpr BracketExpr
Call Call
Ident ident"quote" Ident "quote"
StmtList StmtList
DiscardStmt DiscardStmt
Empty Empty

View file

@ -26,12 +26,12 @@ proc checkNode(arg: NimNode; name: string): void {. compileTime .} =
seqAppend.add(arg) # bit this creates a copy seqAppend.add(arg) # bit this creates a copy
arg.add newCall(ident"echo", newLit("Hello World")) arg.add newCall(ident"echo", newLit("Hello World"))
assertEq arg.lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit("Hello World")))""" assertEq arg.lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident("echo"), StrLit("Hello World")))"""
assertEq node.lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit("Hello World")))""" assertEq node.lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident("echo"), StrLit("Hello World")))"""
assertEq nodeArray[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit("Hello World")))""" assertEq nodeArray[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident("echo"), StrLit("Hello World")))"""
assertEq nodeSeq[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit("Hello World")))""" assertEq nodeSeq[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident("echo"), StrLit("Hello World")))"""
assertEq seqAppend[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit("Hello World")))""" assertEq seqAppend[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident("echo"), StrLit("Hello World")))"""
assertEq seqAppend[1].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit("Hello World")))""" assertEq seqAppend[1].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident("echo"), StrLit("Hello World")))"""
echo "OK" echo "OK"