Rename PNimrodNode to NimNode

This commit is contained in:
def
2015-03-17 17:50:32 +01:00
parent 8e651fa0d4
commit fd4e629905
30 changed files with 508 additions and 518 deletions

View File

@@ -85,11 +85,11 @@ type
ntyInt8, ntyInt16, ntyInt32, ntyInt64,
ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128,
ntyUInt, ntyUInt8, ntyUInt16, ntyUInt32, ntyUInt64,
ntyBigNum,
ntyConst, ntyMutable, ntyVarargs,
ntyBigNum,
ntyConst, ntyMutable, ntyVarargs,
ntyIter,
ntyError
TNimTypeKinds* {.deprecated.} = set[NimTypeKind]
NimSymKind* = enum
nskUnknown, nskConditional, nskDynLib, nskParam,
@@ -120,12 +120,10 @@ const
nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
nnkCallStrLit}
{.push warning[deprecated]: off.}
proc `[]`*(n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild", noSideEffect.}
proc `[]`*(n: NimNode, i: int): NimNode {.magic: "NChild", noSideEffect.}
## get `n`'s `i`'th child.
proc `[]=`*(n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild",
proc `[]=`*(n: NimNode, i: int, child: NimNode) {.magic: "NSetChild",
noSideEffect.}
## set `n`'s `i`'th child to `child`.
@@ -141,34 +139,34 @@ proc `$`*(s: NimSym): string {.magic: "IdentToStr", noSideEffect.}
proc `==`*(a, b: NimIdent): bool {.magic: "EqIdent", noSideEffect.}
## compares two Nim identifiers
proc `==`*(a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.}
proc `==`*(a, b: NimNode): bool {.magic: "EqNimrodNode", noSideEffect.}
## compares two Nim nodes
proc len*(n: PNimrodNode): int {.magic: "NLen", noSideEffect.}
proc len*(n: NimNode): int {.magic: "NLen", noSideEffect.}
## returns the number of children of `n`.
proc add*(father, child: PNimrodNode): PNimrodNode {.magic: "NAdd", discardable,
proc add*(father, child: NimNode): NimNode {.magic: "NAdd", discardable,
noSideEffect, locks: 0.}
## Adds the `child` to the `father` node. Returns the
## father node so that calls can be nested.
proc add*(father: PNimrodNode, children: varargs[PNimrodNode]): PNimrodNode {.
proc add*(father: NimNode, children: varargs[NimNode]): NimNode {.
magic: "NAddMultiple", discardable, noSideEffect, locks: 0.}
## Adds each child of `children` to the `father` node.
## Returns the `father` node so that calls can be nested.
proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel", noSideEffect.}
proc del*(father: NimNode, idx = 0, n = 1) {.magic: "NDel", noSideEffect.}
## deletes `n` children of `father` starting at index `idx`.
proc kind*(n: PNimrodNode): TNimrodNodeKind {.magic: "NKind", noSideEffect.}
proc kind*(n: NimNode): NimNodeKind {.magic: "NKind", noSideEffect.}
## returns the `kind` of the node `n`.
proc intVal*(n: PNimrodNode): BiggestInt {.magic: "NIntVal", noSideEffect.}
proc floatVal*(n: PNimrodNode): BiggestFloat {.magic: "NFloatVal", noSideEffect.}
proc symbol*(n: PNimrodNode): NimSym {.magic: "NSymbol", noSideEffect.}
proc ident*(n: PNimrodNode): NimIdent {.magic: "NIdent", noSideEffect.}
proc intVal*(n: NimNode): BiggestInt {.magic: "NIntVal", 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 getType*(n: PNimrodNode): PNimrodNode {.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
## mapped to a Nim AST too, so it's slightly confusing but it means the same
## API can be used to traverse types. Recursive types are flattened for you
@@ -176,30 +174,30 @@ proc getType*(n: PNimrodNode): PNimrodNode {.magic: "NGetType", noSideEffect.}
## resolve recursive types, you have to call 'getType' again. To see what
## kind of type it is, call `typeKind` on getType's result.
proc typeKind*(n: PNimrodNode): NimTypeKind {.magic: "NGetType", noSideEffect.}
proc typeKind*(n: NimNode): NimTypeKind {.magic: "NGetType", noSideEffect.}
## Returns the type kind of the node 'n' that should represent a type, that
## means the node should have been obtained via `getType`.
proc strVal*(n: PNimrodNode): string {.magic: "NStrVal", noSideEffect.}
proc strVal*(n: NimNode): string {.magic: "NStrVal", noSideEffect.}
proc `intVal=`*(n: PNimrodNode, val: BiggestInt) {.magic: "NSetIntVal", noSideEffect.}
proc `floatVal=`*(n: PNimrodNode, val: BiggestFloat) {.magic: "NSetFloatVal", noSideEffect.}
proc `symbol=`*(n: PNimrodNode, val: NimSym) {.magic: "NSetSymbol", noSideEffect.}
proc `ident=`*(n: PNimrodNode, val: NimIdent) {.magic: "NSetIdent", noSideEffect.}
#proc `typ=`*(n: PNimrodNode, typ: typedesc) {.magic: "NSetType".}
proc `intVal=`*(n: NimNode, val: BiggestInt) {.magic: "NSetIntVal", 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 `typ=`*(n: NimNode, typ: typedesc) {.magic: "NSetType".}
# this is not sound! Unfortunately forbidding 'typ=' is not enough, as you
# can easily do:
# let bracket = semCheck([1, 2])
# let fake = semCheck(2.0)
# bracket[0] = fake # constructs a mixed array with ints and floats!
proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal", noSideEffect.}
proc `strVal=`*(n: NimNode, val: string) {.magic: "NSetStrVal", noSideEffect.}
proc newNimNode*(kind: TNimrodNodeKind,
n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode", noSideEffect.}
proc newNimNode*(kind: NimNodeKind,
n: NimNode=nil): NimNode {.magic: "NNewNimNode", noSideEffect.}
proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode", noSideEffect.}
proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree", noSideEffect.}
proc copyNimNode*(n: NimNode): NimNode {.magic: "NCopyNimNode", noSideEffect.}
proc copyNimTree*(n: NimNode): NimNode {.magic: "NCopyNimTree", noSideEffect.}
proc error*(msg: string) {.magic: "NError", benign.}
## writes an error message at compile time
@@ -210,27 +208,27 @@ proc warning*(msg: string) {.magic: "NWarning", benign.}
proc hint*(msg: string) {.magic: "NHint", benign.}
## writes a hint message at compile time
proc newStrLitNode*(s: string): PNimrodNode {.compileTime, noSideEffect.} =
proc newStrLitNode*(s: string): NimNode {.compileTime, noSideEffect.} =
## creates a string literal node from `s`
result = newNimNode(nnkStrLit)
result.strVal = s
proc newIntLitNode*(i: BiggestInt): PNimrodNode {.compileTime.} =
proc newIntLitNode*(i: BiggestInt): NimNode {.compileTime.} =
## creates a int literal node from `i`
result = newNimNode(nnkIntLit)
result.intVal = i
proc newFloatLitNode*(f: BiggestFloat): PNimrodNode {.compileTime.} =
proc newFloatLitNode*(f: BiggestFloat): NimNode {.compileTime.} =
## creates a float literal node from `f`
result = newNimNode(nnkFloatLit)
result.floatVal = f
proc newIdentNode*(i: NimIdent): PNimrodNode {.compileTime.} =
proc newIdentNode*(i: NimIdent): NimNode {.compileTime.} =
## creates an identifier node from `i`
result = newNimNode(nnkIdent)
result.ident = i
proc newIdentNode*(i: string): PNimrodNode {.compileTime.} =
proc newIdentNode*(i: string): NimNode {.compileTime.} =
## creates an identifier node from `i`
result = newNimNode(nnkIdent)
result.ident = !i
@@ -247,7 +245,7 @@ type
{.deprecated: [TBindSymRule: BindSymRule].}
proc bindSym*(ident: string, rule: BindSymRule = brClosed): PNimrodNode {.
proc bindSym*(ident: string, rule: BindSymRule = brClosed): NimNode {.
magic: "NBindSym", noSideEffect.}
## creates a node that binds `ident` to a symbol node. The bound symbol
## may be an overloaded symbol.
@@ -258,48 +256,48 @@ proc bindSym*(ident: string, rule: BindSymRule = brClosed): PNimrodNode {.
## If ``rule == brForceOpen`` always an ``nkOpenSymChoice`` tree is
## returned even if the symbol is not ambiguous.
proc genSym*(kind: NimSymKind = nskLet; ident = ""): PNimrodNode {.
proc genSym*(kind: NimSymKind = nskLet; ident = ""): NimNode {.
magic: "NGenSym", noSideEffect.}
## generates a fresh symbol that is guaranteed to be unique. The symbol
## needs to occur in a declaration context.
proc callsite*(): PNimrodNode {.magic: "NCallSite", benign.}
proc callsite*(): NimNode {.magic: "NCallSite", benign.}
## returns the AST of the invocation expression that invoked this macro.
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
proc toStrLit*(n: NimNode): NimNode {.compileTime.} =
## converts the AST `n` to the concrete Nim code and wraps that
## in a string literal node
return newStrLitNode(repr(n))
proc lineinfo*(n: PNimrodNode): string {.magic: "NLineInfo", noSideEffect.}
proc lineinfo*(n: NimNode): string {.magic: "NLineInfo", noSideEffect.}
## returns the position the node appears in the original source file
## in the form filename(line, col)
proc internalParseExpr(s: string): PNimrodNode {.
proc internalParseExpr(s: string): NimNode {.
magic: "ParseExprToAst", noSideEffect.}
proc internalParseStmt(s: string): PNimrodNode {.
proc internalParseStmt(s: string): NimNode {.
magic: "ParseStmtToAst", noSideEffect.}
proc internalErrorFlag*(): string {.magic: "NError", noSideEffect.}
## Some builtins set an error flag. This is then turned into a proper
## exception. **Note**: Ordinary application code should not call this.
proc parseExpr*(s: string): PNimrodNode {.noSideEffect, compileTime.} =
proc parseExpr*(s: string): NimNode {.noSideEffect, compileTime.} =
## Compiles the passed string to its AST representation.
## Expects a single expression. Raises ``ValueError`` for parsing errors.
result = internalParseExpr(s)
let x = internalErrorFlag()
if x.len > 0: raise newException(ValueError, x)
proc parseStmt*(s: string): PNimrodNode {.noSideEffect, compileTime.} =
proc parseStmt*(s: string): NimNode {.noSideEffect, compileTime.} =
## Compiles the passed string to its AST representation.
## Expects one or more statements. Raises ``ValueError`` for parsing errors.
result = internalParseStmt(s)
let x = internalErrorFlag()
if x.len > 0: raise newException(ValueError, x)
proc getAst*(macroOrTemplate: expr): PNimrodNode {.magic: "ExpandToAst", noSideEffect.}
proc getAst*(macroOrTemplate: expr): NimNode {.magic: "ExpandToAst", noSideEffect.}
## Obtains the AST nodes returned from a macro or template invocation.
## Example:
##
@@ -308,10 +306,10 @@ proc getAst*(macroOrTemplate: expr): PNimrodNode {.magic: "ExpandToAst", noSideE
## macro FooMacro() =
## var ast = getAst(BarTemplate())
proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst", noSideEffect.}
proc quote*(bl: stmt, op = "``"): NimNode {.magic: "QuoteAst", noSideEffect.}
## Quasi-quoting operator.
## Accepts an expression or a block and returns the AST that represents it.
## Within the quoted AST, you are able to interpolate PNimrodNode expressions
## Within the quoted AST, you are able to interpolate NimNode expressions
## from the surrounding scope. If no operator is given, quoting is done using
## backticks. Otherwise, the given operator must be used as a prefix operator
## for any interpolated expression. The original meaning of the interpolation
@@ -339,26 +337,26 @@ proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst", noSideEffect.
## if not `ex`:
## echo `info` & ": Check failed: " & `expString`
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
proc expectKind*(n: NimNode, k: NimNodeKind) {.compileTime.} =
## checks that `n` is of kind `k`. If this is not the case,
## compilation aborts with an error message. This is useful for writing
## macros that check the AST that is passed to them.
if n.kind != k: error("Expected a node of kind " & $k & ", got " & $n.kind)
proc expectMinLen*(n: PNimrodNode, min: int) {.compileTime.} =
proc expectMinLen*(n: NimNode, min: int) {.compileTime.} =
## checks that `n` has at least `min` children. If this is not the case,
## compilation aborts with an error message. This is useful for writing
## macros that check its number of arguments.
if n.len < min: error("macro expects a node with " & $min & " children")
proc expectLen*(n: PNimrodNode, len: int) {.compileTime.} =
proc expectLen*(n: NimNode, len: int) {.compileTime.} =
## checks that `n` has exactly `len` children. If this is not the case,
## compilation aborts with an error message. This is useful for writing
## macros that check its number of arguments.
if n.len != len: error("macro expects a node with " & $len & " children")
proc newCall*(theProc: PNimrodNode,
args: varargs[PNimrodNode]): PNimrodNode {.compileTime.} =
proc newCall*(theProc: NimNode,
args: varargs[NimNode]): NimNode {.compileTime.} =
## produces a new call node. `theProc` is the proc that is called with
## the arguments ``args[0..]``.
result = newNimNode(nnkCall)
@@ -366,7 +364,7 @@ proc newCall*(theProc: PNimrodNode,
result.add(args)
proc newCall*(theProc: NimIdent,
args: varargs[PNimrodNode]): PNimrodNode {.compileTime.} =
args: varargs[NimNode]): NimNode {.compileTime.} =
## produces a new call node. `theProc` is the proc that is called with
## the arguments ``args[0..]``.
result = newNimNode(nnkCall)
@@ -374,35 +372,35 @@ proc newCall*(theProc: NimIdent,
result.add(args)
proc newCall*(theProc: string,
args: varargs[PNimrodNode]): PNimrodNode {.compileTime.} =
args: varargs[NimNode]): NimNode {.compileTime.} =
## produces a new call node. `theProc` is the proc that is called with
## the arguments ``args[0..]``.
result = newNimNode(nnkCall)
result.add(newIdentNode(theProc))
result.add(args)
proc newLit*(c: char): PNimrodNode {.compileTime.} =
proc newLit*(c: char): NimNode {.compileTime.} =
## produces a new character literal node.
result = newNimNode(nnkCharLit)
result.intVal = ord(c)
proc newLit*(i: BiggestInt): PNimrodNode {.compileTime.} =
proc newLit*(i: BiggestInt): NimNode {.compileTime.} =
## produces a new integer literal node.
result = newNimNode(nnkIntLit)
result.intVal = i
proc newLit*(f: BiggestFloat): PNimrodNode {.compileTime.} =
proc newLit*(f: BiggestFloat): NimNode {.compileTime.} =
## produces a new float literal node.
result = newNimNode(nnkFloatLit)
result.floatVal = f
proc newLit*(s: string): PNimrodNode {.compileTime.} =
proc newLit*(s: string): NimNode {.compileTime.} =
## produces a new string literal node.
result = newNimNode(nnkStrLit)
result.strVal = s
proc nestList*(theProc: NimIdent,
x: PNimrodNode): PNimrodNode {.compileTime.} =
x: NimNode): NimNode {.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
@@ -413,11 +411,11 @@ proc nestList*(theProc: NimIdent,
# This could easily user code and so should be fixed in evals.nim somehow.
result = newCall(theProc, x[i], copyNimTree(result))
proc treeRepr*(n: PNimrodNode): string {.compileTime, benign.} =
proc treeRepr*(n: NimNode): string {.compileTime, benign.} =
## 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) {.benign.} =
proc traverse(res: var string, level: int, n: NimNode) {.benign.} =
for i in 0..level-1: res.add " "
res.add(($n.kind).substr(3))
@@ -438,7 +436,7 @@ proc treeRepr*(n: PNimrodNode): string {.compileTime, benign.} =
result = ""
traverse(result, 0, n)
proc lispRepr*(n: PNimrodNode): string {.compileTime, benign.} =
proc lispRepr*(n: NimNode): string {.compileTime, benign.} =
## Convert the AST `n` to a human-readable lisp-like string,
##
## See also `repr` and `treeRepr`.
@@ -485,56 +483,56 @@ macro dumpLispImm*(s: stmt): stmt {.immediate, deprecated.} = echo s.lispRepr
## The ``immediate`` version of `dumpLisp`.
proc newEmptyNode*(): PNimrodNode {.compileTime, noSideEffect.} =
proc newEmptyNode*(): NimNode {.compileTime, noSideEffect.} =
## Create a new empty node
result = newNimNode(nnkEmpty)
proc newStmtList*(stmts: varargs[PNimrodNode]): PNimrodNode {.compileTime.}=
proc newStmtList*(stmts: varargs[NimNode]): NimNode {.compileTime.}=
## Create a new statement list
result = newNimNode(nnkStmtList).add(stmts)
proc newPar*(exprs: varargs[PNimrodNode]): PNimrodNode {.compileTime.}=
proc newPar*(exprs: varargs[NimNode]): NimNode {.compileTime.}=
## Create a new parentheses-enclosed expression
newNimNode(nnkPar).add(exprs)
proc newBlockStmt*(label, body: PNimrodNode): PNimrodNode {.compileTime.} =
proc newBlockStmt*(label, body: NimNode): NimNode {.compileTime.} =
## Create a new block statement with label
return newNimNode(nnkBlockStmt).add(label, body)
proc newBlockStmt*(body: PNimrodNode): PNimrodNode {.compiletime.} =
proc newBlockStmt*(body: NimNode): NimNode {.compiletime.} =
## Create a new block: stmt
return newNimNode(nnkBlockStmt).add(newEmptyNode(), body)
proc newVarStmt*(name, value: PNimrodNode): PNimrodNode {.compiletime.} =
proc newVarStmt*(name, value: NimNode): NimNode {.compiletime.} =
## Create a new var stmt
return newNimNode(nnkVarSection).add(
newNimNode(nnkIdentDefs).add(name, newNimNode(nnkEmpty), value))
proc newLetStmt*(name, value: PNimrodNode): PNimrodNode {.compiletime.} =
proc newLetStmt*(name, value: NimNode): NimNode {.compiletime.} =
## Create a new let stmt
return newNimNode(nnkLetSection).add(
newNimNode(nnkIdentDefs).add(name, newNimNode(nnkEmpty), value))
proc newConstStmt*(name, value: PNimrodNode): PNimrodNode {.compileTime.} =
proc newConstStmt*(name, value: NimNode): NimNode {.compileTime.} =
## Create a new const stmt
newNimNode(nnkConstSection).add(
newNimNode(nnkConstDef).add(name, newNimNode(nnkEmpty), value))
proc newAssignment*(lhs, rhs: PNimrodNode): PNimrodNode {.compileTime.} =
proc newAssignment*(lhs, rhs: NimNode): NimNode {.compileTime.} =
return newNimNode(nnkAsgn).add(lhs, rhs)
proc newDotExpr*(a, b: PNimrodNode): PNimrodNode {.compileTime.} =
proc newDotExpr*(a, b: NimNode): NimNode {.compileTime.} =
## Create new dot expression
## a.dot(b) -> `a.b`
return newNimNode(nnkDotExpr).add(a, b)
proc newColonExpr*(a, b: PNimrodNode): PNimrodNode {.compileTime.} =
proc newColonExpr*(a, b: NimNode): NimNode {.compileTime.} =
## Create new colon expression
## newColonExpr(a, b) -> `a: b`
newNimNode(nnkExprColonExpr).add(a, b)
proc newIdentDefs*(name, kind: PNimrodNode;
default = newEmptyNode()): PNimrodNode {.compileTime.} =
proc newIdentDefs*(name, kind: NimNode;
default = newEmptyNode()): NimNode {.compileTime.} =
## Creates a new ``nnkIdentDefs`` node of a specific kind and value.
##
## ``nnkIdentDefs`` need to have at least three children, but they can have
@@ -565,13 +563,13 @@ proc newIdentDefs*(name, kind: PNimrodNode;
## newStrLitNode("Hello"))
newNimNode(nnkIdentDefs).add(name, kind, default)
proc newNilLit*(): PNimrodNode {.compileTime.} =
proc newNilLit*(): NimNode {.compileTime.} =
## New nil literal shortcut
result = newNimNode(nnkNilLit)
proc high*(node: PNimrodNode): int {.compileTime.} = len(node) - 1
proc high*(node: NimNode): int {.compileTime.} = len(node) - 1
## Return the highest index available for a node
proc last*(node: PNimrodNode): PNimrodNode {.compileTime.} = node[node.high]
proc last*(node: NimNode): NimNode {.compileTime.} = node[node.high]
## Return the last item in nodes children. Same as `node[node.high()]`
@@ -581,11 +579,11 @@ const
CallNodes* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
nnkCallStrLit, nnkHiddenCallConv}
proc expectKind*(n: PNimrodNode; k: set[TNimrodNodeKind]) {.compileTime.} =
proc expectKind*(n: NimNode; k: set[NimNodeKind]) {.compileTime.} =
assert n.kind in k, "Expected one of " & $k & ", got " & $n.kind
proc newProc*(name = newEmptyNode(); params: openArray[PNimrodNode] = [newEmptyNode()];
body: PNimrodNode = newStmtList(), procType = nnkProcDef): PNimrodNode {.compileTime.} =
proc newProc*(name = newEmptyNode(); params: openArray[NimNode] = [newEmptyNode()];
body: NimNode = newStmtList(), procType = nnkProcDef): NimNode {.compileTime.} =
## shortcut for creating a new proc
##
## The ``params`` array must start with the return type of the proc,
@@ -600,8 +598,8 @@ proc newProc*(name = newEmptyNode(); params: openArray[PNimrodNode] = [newEmptyN
newEmptyNode(),
body)
proc newIfStmt*(branches: varargs[tuple[cond, body: PNimrodNode]]):
PNimrodNode {.compiletime.} =
proc newIfStmt*(branches: varargs[tuple[cond, body: NimNode]]):
NimNode {.compiletime.} =
## Constructor for ``if`` statements.
##
## .. code-block:: nim
@@ -616,35 +614,35 @@ proc newIfStmt*(branches: varargs[tuple[cond, body: PNimrodNode]]):
result.add(newNimNode(nnkElifBranch).add(i.cond, i.body))
proc copyChildrenTo*(src, dest: PNimrodNode) {.compileTime.}=
proc copyChildrenTo*(src, dest: NimNode) {.compileTime.}=
## Copy all children from `src` to `dest`
for i in 0 .. < src.len:
dest.add src[i].copyNimTree
template expectRoutine(node: PNimrodNode): stmt =
template expectRoutine(node: NimNode): stmt =
expectKind(node, RoutineNodes)
proc name*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
proc name*(someProc: NimNode): NimNode {.compileTime.} =
someProc.expectRoutine
result = someProc[0]
proc `name=`*(someProc: PNimrodNode; val: PNimrodNode) {.compileTime.} =
proc `name=`*(someProc: NimNode; val: NimNode) {.compileTime.} =
someProc.expectRoutine
someProc[0] = val
proc params*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
proc params*(someProc: NimNode): NimNode {.compileTime.} =
someProc.expectRoutine
result = someProc[3]
proc `params=`* (someProc: PNimrodNode; params: PNimrodNode) {.compileTime.}=
proc `params=`* (someProc: NimNode; params: NimNode) {.compileTime.}=
someProc.expectRoutine
assert params.kind == nnkFormalParams
someProc[3] = params
proc pragma*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
proc pragma*(someProc: NimNode): NimNode {.compileTime.} =
## Get the pragma of a proc type
## These will be expanded
someProc.expectRoutine
result = someProc[4]
proc `pragma=`*(someProc: PNimrodNode; val: PNimrodNode){.compileTime.}=
proc `pragma=`*(someProc: NimNode; val: NimNode){.compileTime.}=
## Set the pragma of a proc type
someProc.expectRoutine
assert val.kind in {nnkEmpty, nnkPragma}
@@ -654,7 +652,7 @@ proc `pragma=`*(someProc: PNimrodNode; val: PNimrodNode){.compileTime.}=
template badNodeKind(k; f): stmt{.immediate.} =
assert false, "Invalid node kind " & $k & " for macros.`" & $f & "`"
proc body*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
proc body*(someProc: NimNode): NimNode {.compileTime.} =
case someProc.kind:
of RoutineNodes:
return someProc[6]
@@ -665,7 +663,7 @@ proc body*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
else:
badNodeKind someProc.kind, "body"
proc `body=`*(someProc: PNimrodNode, val: PNimrodNode) {.compileTime.} =
proc `body=`*(someProc: NimNode, val: NimNode) {.compileTime.} =
case someProc.kind
of RoutineNodes:
someProc[6] = val
@@ -676,10 +674,10 @@ proc `body=`*(someProc: PNimrodNode, val: PNimrodNode) {.compileTime.} =
else:
badNodeKind someProc.kind, "body="
proc basename*(a: PNimrodNode): PNimrodNode {.compiletime, benign.}
proc basename*(a: NimNode): NimNode {.compiletime, benign.}
proc `$`*(node: PNimrodNode): string {.compileTime.} =
proc `$`*(node: NimNode): string {.compileTime.} =
## Get the string of an identifier node
case node.kind
of nnkIdent:
@@ -693,14 +691,14 @@ proc `$`*(node: PNimrodNode): string {.compileTime.} =
else:
badNodeKind node.kind, "$"
proc ident*(name: string): PNimrodNode {.compileTime,inline.} = newIdentNode(name)
proc ident*(name: string): NimNode {.compileTime,inline.} = newIdentNode(name)
## Create a new ident node from a string
iterator children*(n: PNimrodNode): PNimrodNode {.inline.}=
iterator children*(n: NimNode): NimNode {.inline.}=
for i in 0 .. high(n):
yield n[i]
template findChild*(n: PNimrodNode; cond: expr): PNimrodNode {.
template findChild*(n: NimNode; cond: expr): NimNode {.
immediate, dirty.} =
## Find the first child node matching condition (or nil).
##
@@ -708,14 +706,14 @@ template findChild*(n: PNimrodNode; cond: expr): PNimrodNode {.
## var res = findChild(n, it.kind == nnkPostfix and
## it.basename.ident == !"foo")
block:
var result: PNimrodNode
var result: NimNode
for it in n.children:
if cond:
result = it
break
result
proc insert*(a: PNimrodNode; pos: int; b: PNimrodNode) {.compileTime.} =
proc insert*(a: NimNode; pos: int; b: NimNode) {.compileTime.} =
## Insert node B into A at pos
if high(a) < pos:
## add some empty nodes first
@@ -730,7 +728,7 @@ proc insert*(a: PNimrodNode; pos: int; b: PNimrodNode) {.compileTime.} =
a[i + 1] = a[i]
a[pos] = b
proc basename*(a: PNimrodNode): PNimrodNode =
proc basename*(a: NimNode): NimNode =
## Pull an identifier from prefix/postfix expressions
case a.kind
of nnkIdent: return a
@@ -738,39 +736,39 @@ proc basename*(a: PNimrodNode): PNimrodNode =
else:
quit "Do not know how to get basename of ("& treeRepr(a) &")\n"& repr(a)
proc `basename=`*(a: PNimrodNode; val: string) {.compileTime.}=
proc `basename=`*(a: NimNode; val: string) {.compileTime.}=
case a.kind
of nnkIdent: macros.`ident=`(a, !val)
of nnkPostfix, nnkPrefix: a[1] = ident(val)
else:
quit "Do not know how to get basename of ("& treeRepr(a)& ")\n"& repr(a)
proc postfix*(node: PNimrodNode; op: string): PNimrodNode {.compileTime.} =
proc postfix*(node: NimNode; op: string): NimNode {.compileTime.} =
newNimNode(nnkPostfix).add(ident(op), node)
proc prefix*(node: PNimrodNode; op: string): PNimrodNode {.compileTime.} =
proc prefix*(node: NimNode; op: string): NimNode {.compileTime.} =
newNimNode(nnkPrefix).add(ident(op), node)
proc infix*(a: PNimrodNode; op: string;
b: PNimrodNode): PNimrodNode {.compileTime.} =
proc infix*(a: NimNode; op: string;
b: NimNode): NimNode {.compileTime.} =
newNimNode(nnkInfix).add(ident(op), a, b)
proc unpackPostfix*(node: PNimrodNode): tuple[node: PNimrodNode; op: string] {.
proc unpackPostfix*(node: NimNode): tuple[node: NimNode; op: string] {.
compileTime.} =
node.expectKind nnkPostfix
result = (node[0], $node[1])
proc unpackPrefix*(node: PNimrodNode): tuple[node: PNimrodNode; op: string] {.
proc unpackPrefix*(node: NimNode): tuple[node: NimNode; op: string] {.
compileTime.} =
node.expectKind nnkPrefix
result = (node[0], $node[1])
proc unpackInfix*(node: PNimrodNode): tuple[left: PNimrodNode; op: string;
right: PNimrodNode] {.compileTime.} =
proc unpackInfix*(node: NimNode): tuple[left: NimNode; op: string;
right: NimNode] {.compileTime.} =
assert node.kind == nnkInfix
result = (node[0], $node[1], node[2])
proc copy*(node: PNimrodNode): PNimrodNode {.compileTime.} =
proc copy*(node: NimNode): NimNode {.compileTime.} =
## An alias for copyNimTree().
return node.copyNimTree()
@@ -793,7 +791,7 @@ proc cmpIgnoreStyle(a, b: cstring): int {.noSideEffect.} =
proc eqIdent* (a, b: string): bool = cmpIgnoreStyle(a, b) == 0
## Check if two idents are identical.
proc hasArgOfName* (params: PNimrodNode; name: string): bool {.compiletime.}=
proc hasArgOfName* (params: NimNode; name: string): bool {.compiletime.}=
## Search nnkFormalParams for an argument.
assert params.kind == nnkFormalParams
for i in 1 .. <params.len:
@@ -801,7 +799,7 @@ proc hasArgOfName* (params: PNimrodNode; name: string): bool {.compiletime.}=
if name.eqIdent( $ node[0]):
return true
proc addIdentIfAbsent*(dest: PNimrodNode, ident: string) {.compiletime.} =
proc addIdentIfAbsent*(dest: NimNode, ident: string) {.compiletime.} =
## Add ident to dest if it is not present. This is intended for use
## with pragmas.
for node in dest.children:
@@ -825,5 +823,3 @@ when not defined(booting):
macro payload: stmt {.gensym.} =
result = parseStmt(e)
payload()
{.pop.}

View File

@@ -1064,13 +1064,13 @@ proc accept*(socket: TAsyncFD,
# -- Await Macro
proc skipUntilStmtList(node: PNimrodNode): PNimrodNode {.compileTime.} =
proc skipUntilStmtList(node: NimNode): NimNode {.compileTime.} =
# Skips a nest of StmtList's.
result = node
if node[0].kind == nnkStmtList:
result = skipUntilStmtList(node[0])
proc skipStmtList(node: PNimrodNode): PNimrodNode {.compileTime.} =
proc skipStmtList(node: NimNode): NimNode {.compileTime.} =
result = node
if node[0].kind == nnkStmtList:
result = node[0]
@@ -1098,11 +1098,11 @@ template createCb(retFutureSym, iteratorNameSym,
cb()
#{.pop.}
proc generateExceptionCheck(futSym,
tryStmt, rootReceiver, fromNode: PNimrodNode): PNimrodNode {.compileTime.} =
tryStmt, rootReceiver, fromNode: NimNode): NimNode {.compileTime.} =
if tryStmt.kind == nnkNilLit:
result = rootReceiver
else:
var exceptionChecks: seq[tuple[cond, body: PNimrodNode]] = @[]
var exceptionChecks: seq[tuple[cond, body: NimNode]] = @[]
let errorNode = newDotExpr(futSym, newIdentNode("error"))
for i in 1 .. <tryStmt.len:
let exceptBranch = tryStmt[i]
@@ -1110,7 +1110,7 @@ proc generateExceptionCheck(futSym,
exceptionChecks.add((newIdentNode("true"), exceptBranch[0]))
else:
var exceptIdentCount = 0
var ifCond: PNimrodNode
var ifCond: NimNode
for i in 0 .. <exceptBranch.len:
let child = exceptBranch[i]
if child.kind == nnkIdent:
@@ -1144,10 +1144,10 @@ proc generateExceptionCheck(futSym,
)
result.add elseNode
template createVar(result: var PNimrodNode, futSymName: string,
asyncProc: PNimrodNode,
template createVar(result: var NimNode, futSymName: string,
asyncProc: NimNode,
valueReceiver, rootReceiver: expr,
fromNode: PNimrodNode) =
fromNode: NimNode) =
result = newNimNode(nnkStmtList, fromNode)
var futSym = genSym(nskVar, "future")
result.add newVarStmt(futSym, asyncProc) # -> var future<x> = y
@@ -1155,9 +1155,9 @@ template createVar(result: var PNimrodNode, futSymName: string,
valueReceiver = newDotExpr(futSym, newIdentNode("read")) # -> future<x>.read
result.add generateExceptionCheck(futSym, tryStmt, rootReceiver, fromNode)
proc processBody(node, retFutureSym: PNimrodNode,
proc processBody(node, retFutureSym: NimNode,
subTypeIsVoid: bool,
tryStmt: PNimrodNode): PNimrodNode {.compileTime.} =
tryStmt: NimNode): NimNode {.compileTime.} =
#echo(node.treeRepr)
result = node
case node.kind
@@ -1183,7 +1183,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
result = newNimNode(nnkYieldStmt, node).add(node[1]) # -> yield x
of nnkCall, nnkCommand:
# await foo(p, x)
var futureValue: PNimrodNode
var futureValue: NimNode
result.createVar("future" & $node[1][0].toStrLit, node[1], futureValue,
futureValue, node)
else:
@@ -1232,8 +1232,8 @@ proc processBody(node, retFutureSym: PNimrodNode,
# working in ``except``?
tryBody[1] = processBody(n[1], retFutureSym, subTypeIsVoid, nil)
proc processForTry(n: PNimrodNode, i: var int,
res: PNimrodNode): bool {.compileTime.} =
proc processForTry(n: NimNode, i: var int,
res: NimNode): bool {.compileTime.} =
## Transforms the body of the tryStmt. Does not transform the
## body in ``except``.
## Returns true if the tryStmt node was transformed into an ifStmt.
@@ -1275,7 +1275,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
for i in 0 .. <result.len:
result[i] = processBody(result[i], retFutureSym, subTypeIsVoid, tryStmt)
proc getName(node: PNimrodNode): string {.compileTime.} =
proc getName(node: NimNode): string {.compileTime.} =
case node.kind
of nnkPostfix:
return $node[1].ident

View File

@@ -12,7 +12,7 @@
import macros
proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} =
proc createProcType(p, b: NimNode): NimNode {.compileTime.} =
#echo treeRepr(p)
#echo treeRepr(b)
result = newNimNode(nnkProcTy)
@@ -44,7 +44,7 @@ proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} =
formalParams.add identDefs
else:
error("Incorrect type list in proc type declaration.")
result.add formalParams
result.add newEmptyNode()
#echo(treeRepr(result))
@@ -59,10 +59,10 @@ macro `=>`*(p, b: expr): expr {.immediate.} =
## f(2, 2)
##
## passTwoAndTwo((x, y) => x + y) # 4
#echo treeRepr(p)
#echo(treeRepr(b))
var params: seq[PNimrodNode] = @[newIdentNode("auto")]
var params: seq[NimNode] = @[newIdentNode("auto")]
case p.kind
of nnkPar:
@@ -118,7 +118,7 @@ macro `->`*(p, b: expr): expr {.immediate.} =
##
## proc pass2(f: (float, float) -> float): float =
## f(2, 2)
##
##
## # is the same as:
##
## proc pass2(f: proc (x, y: float): float): float =

View File

@@ -12,7 +12,7 @@
## as ``from htmlgen import nil`` and then fully qualify the macros.
##
##
## This module implements a simple `XML`:idx: and `HTML`:idx: code
## This module implements a simple `XML`:idx: and `HTML`:idx: code
## generator. Each commonly used HTML tag has a corresponding macro
## that generates a string with its HTML representation.
##
@@ -21,9 +21,9 @@
## .. code-block:: Nim
## var nim = "Nim"
## echo h1(a(href="http://nim-lang.org", nim))
##
##
## Writes the string::
##
##
## <h1><a href="http://nim-lang.org">Nim</a></h1>
##
@@ -36,16 +36,16 @@ const
"onmouseover onmousemove onmouseout onkeypress onkeydown onkeyup "
commonAttr* = coreAttr & eventAttr
proc getIdent(e: PNimrodNode): string {.compileTime.} =
proc getIdent(e: NimNode): string {.compileTime.} =
case e.kind
of nnkIdent: result = normalize($e.ident)
of nnkAccQuoted:
of nnkAccQuoted:
result = getIdent(e[0])
for i in 1 .. e.len-1:
result.add getIdent(e[i])
else: error("cannot extract identifier from node: " & toStrLit(e).strVal)
proc delete[T](s: var seq[T], attr: T): bool =
proc delete[T](s: var seq[T], attr: T): bool =
var idx = find(s, attr)
if idx >= 0:
var L = s.len
@@ -53,10 +53,10 @@ proc delete[T](s: var seq[T], attr: T): bool =
setLen(s, L-1)
result = true
proc xmlCheckedTag*(e: PNimrodNode, tag: string, optAttr = "", reqAttr = "",
isLeaf = false): PNimrodNode {.compileTime.} =
proc xmlCheckedTag*(e: NimNode, tag: string, optAttr = "", reqAttr = "",
isLeaf = false): NimNode {.compileTime.} =
## use this procedure to define a new XML tag
# copy the attributes; when iterating over them these lists
# will be modified, so that each attribute is only given one value
var req = split(reqAttr)
@@ -66,7 +66,7 @@ proc xmlCheckedTag*(e: PNimrodNode, tag: string, optAttr = "", reqAttr = "",
result.add(newStrLitNode(tag))
# first pass over attributes:
for i in 1..e.len-1:
if e[i].kind == nnkExprEqExpr:
if e[i].kind == nnkExprEqExpr:
var name = getIdent(e[i][0])
if delete(req, name) or delete(opt, name):
result.add(newStrLitNode(" "))
@@ -81,7 +81,7 @@ proc xmlCheckedTag*(e: PNimrodNode, tag: string, optAttr = "", reqAttr = "",
error(req[0] & " attribute for '" & tag & "' element expected")
if isLeaf:
for i in 1..e.len-1:
if e[i].kind != nnkExprEqExpr:
if e[i].kind != nnkExprEqExpr:
error("element " & tag & " cannot be nested")
result.add(newStrLitNode(" />"))
else:
@@ -95,389 +95,389 @@ proc xmlCheckedTag*(e: PNimrodNode, tag: string, optAttr = "", reqAttr = "",
result = nestList(!"&", result)
macro a*(e: expr): expr {.immediate.} =
macro a*(e: expr): expr {.immediate.} =
## generates the HTML ``a`` element.
let e = callsite()
result = xmlCheckedTag(e, "a", "href charset type hreflang rel rev " &
"accesskey tabindex" & commonAttr)
macro acronym*(e: expr): expr {.immediate.} =
macro acronym*(e: expr): expr {.immediate.} =
## generates the HTML ``acronym`` element.
let e = callsite()
result = xmlCheckedTag(e, "acronym", commonAttr)
macro address*(e: expr): expr {.immediate.} =
macro address*(e: expr): expr {.immediate.} =
## generates the HTML ``address`` element.
let e = callsite()
result = xmlCheckedTag(e, "address", commonAttr)
macro area*(e: expr): expr {.immediate.} =
macro area*(e: expr): expr {.immediate.} =
## generates the HTML ``area`` element.
let e = callsite()
result = xmlCheckedTag(e, "area", "shape coords href nohref" &
" accesskey tabindex" & commonAttr, "alt", true)
macro b*(e: expr): expr {.immediate.} =
macro b*(e: expr): expr {.immediate.} =
## generates the HTML ``b`` element.
let e = callsite()
result = xmlCheckedTag(e, "b", commonAttr)
macro base*(e: expr): expr {.immediate.} =
macro base*(e: expr): expr {.immediate.} =
## generates the HTML ``base`` element.
let e = callsite()
result = xmlCheckedTag(e, "base", "", "href", true)
macro big*(e: expr): expr {.immediate.} =
macro big*(e: expr): expr {.immediate.} =
## generates the HTML ``big`` element.
let e = callsite()
result = xmlCheckedTag(e, "big", commonAttr)
macro blockquote*(e: expr): expr {.immediate.} =
macro blockquote*(e: expr): expr {.immediate.} =
## generates the HTML ``blockquote`` element.
let e = callsite()
result = xmlCheckedTag(e, "blockquote", " cite" & commonAttr)
macro body*(e: expr): expr {.immediate.} =
macro body*(e: expr): expr {.immediate.} =
## generates the HTML ``body`` element.
let e = callsite()
result = xmlCheckedTag(e, "body", commonAttr)
macro br*(e: expr): expr {.immediate.} =
macro br*(e: expr): expr {.immediate.} =
## generates the HTML ``br`` element.
let e = callsite()
result = xmlCheckedTag(e, "br", "", "", true)
macro button*(e: expr): expr {.immediate.} =
macro button*(e: expr): expr {.immediate.} =
## generates the HTML ``button`` element.
let e = callsite()
result = xmlCheckedTag(e, "button", "accesskey tabindex " &
"disabled name type value" & commonAttr)
macro caption*(e: expr): expr {.immediate.} =
macro caption*(e: expr): expr {.immediate.} =
## generates the HTML ``caption`` element.
let e = callsite()
result = xmlCheckedTag(e, "caption", commonAttr)
macro cite*(e: expr): expr {.immediate.} =
macro cite*(e: expr): expr {.immediate.} =
## generates the HTML ``cite`` element.
let e = callsite()
result = xmlCheckedTag(e, "cite", commonAttr)
macro code*(e: expr): expr {.immediate.} =
macro code*(e: expr): expr {.immediate.} =
## generates the HTML ``code`` element.
let e = callsite()
result = xmlCheckedTag(e, "code", commonAttr)
macro col*(e: expr): expr {.immediate.} =
macro col*(e: expr): expr {.immediate.} =
## generates the HTML ``col`` element.
let e = callsite()
result = xmlCheckedTag(e, "col", "span align valign" & commonAttr, "", true)
macro colgroup*(e: expr): expr {.immediate.} =
macro colgroup*(e: expr): expr {.immediate.} =
## generates the HTML ``colgroup`` element.
let e = callsite()
result = xmlCheckedTag(e, "colgroup", "span align valign" & commonAttr)
macro dd*(e: expr): expr {.immediate.} =
macro dd*(e: expr): expr {.immediate.} =
## generates the HTML ``dd`` element.
let e = callsite()
result = xmlCheckedTag(e, "dd", commonAttr)
macro del*(e: expr): expr {.immediate.} =
macro del*(e: expr): expr {.immediate.} =
## generates the HTML ``del`` element.
let e = callsite()
result = xmlCheckedTag(e, "del", "cite datetime" & commonAttr)
macro dfn*(e: expr): expr {.immediate.} =
macro dfn*(e: expr): expr {.immediate.} =
## generates the HTML ``dfn`` element.
let e = callsite()
result = xmlCheckedTag(e, "dfn", commonAttr)
macro `div`*(e: expr): expr {.immediate.} =
macro `div`*(e: expr): expr {.immediate.} =
## generates the HTML ``div`` element.
let e = callsite()
result = xmlCheckedTag(e, "div", commonAttr)
macro dl*(e: expr): expr {.immediate.} =
macro dl*(e: expr): expr {.immediate.} =
## generates the HTML ``dl`` element.
let e = callsite()
result = xmlCheckedTag(e, "dl", commonAttr)
macro dt*(e: expr): expr {.immediate.} =
macro dt*(e: expr): expr {.immediate.} =
## generates the HTML ``dt`` element.
let e = callsite()
result = xmlCheckedTag(e, "dt", commonAttr)
macro em*(e: expr): expr {.immediate.} =
macro em*(e: expr): expr {.immediate.} =
## generates the HTML ``em`` element.
let e = callsite()
result = xmlCheckedTag(e, "em", commonAttr)
macro fieldset*(e: expr): expr {.immediate.} =
macro fieldset*(e: expr): expr {.immediate.} =
## generates the HTML ``fieldset`` element.
let e = callsite()
result = xmlCheckedTag(e, "fieldset", commonAttr)
macro form*(e: expr): expr {.immediate.} =
macro form*(e: expr): expr {.immediate.} =
## generates the HTML ``form`` element.
let e = callsite()
result = xmlCheckedTag(e, "form", "method encype accept accept-charset" &
result = xmlCheckedTag(e, "form", "method encype accept accept-charset" &
commonAttr, "action")
macro h1*(e: expr): expr {.immediate.} =
macro h1*(e: expr): expr {.immediate.} =
## generates the HTML ``h1`` element.
let e = callsite()
result = xmlCheckedTag(e, "h1", commonAttr)
macro h2*(e: expr): expr {.immediate.} =
macro h2*(e: expr): expr {.immediate.} =
## generates the HTML ``h2`` element.
let e = callsite()
result = xmlCheckedTag(e, "h2", commonAttr)
macro h3*(e: expr): expr {.immediate.} =
macro h3*(e: expr): expr {.immediate.} =
## generates the HTML ``h3`` element.
let e = callsite()
result = xmlCheckedTag(e, "h3", commonAttr)
macro h4*(e: expr): expr {.immediate.} =
macro h4*(e: expr): expr {.immediate.} =
## generates the HTML ``h4`` element.
let e = callsite()
result = xmlCheckedTag(e, "h4", commonAttr)
macro h5*(e: expr): expr {.immediate.} =
macro h5*(e: expr): expr {.immediate.} =
## generates the HTML ``h5`` element.
let e = callsite()
result = xmlCheckedTag(e, "h5", commonAttr)
macro h6*(e: expr): expr {.immediate.} =
macro h6*(e: expr): expr {.immediate.} =
## generates the HTML ``h6`` element.
let e = callsite()
result = xmlCheckedTag(e, "h6", commonAttr)
macro head*(e: expr): expr {.immediate.} =
macro head*(e: expr): expr {.immediate.} =
## generates the HTML ``head`` element.
let e = callsite()
result = xmlCheckedTag(e, "head", "profile")
macro html*(e: expr): expr {.immediate.} =
macro html*(e: expr): expr {.immediate.} =
## generates the HTML ``html`` element.
let e = callsite()
result = xmlCheckedTag(e, "html", "xmlns", "")
macro hr*(): expr {.immediate.} =
macro hr*(): expr {.immediate.} =
## generates the HTML ``hr`` element.
let e = callsite()
result = xmlCheckedTag(e, "hr", commonAttr, "", true)
macro i*(e: expr): expr {.immediate.} =
macro i*(e: expr): expr {.immediate.} =
## generates the HTML ``i`` element.
let e = callsite()
result = xmlCheckedTag(e, "i", commonAttr)
macro img*(e: expr): expr {.immediate.} =
macro img*(e: expr): expr {.immediate.} =
## generates the HTML ``img`` element.
let e = callsite()
result = xmlCheckedTag(e, "img", "longdesc height width", "src alt", true)
macro input*(e: expr): expr {.immediate.} =
macro input*(e: expr): expr {.immediate.} =
## generates the HTML ``input`` element.
let e = callsite()
result = xmlCheckedTag(e, "input", "name type value checked maxlength src" &
" alt accept disabled readonly accesskey tabindex" & commonAttr, "", true)
macro ins*(e: expr): expr {.immediate.} =
macro ins*(e: expr): expr {.immediate.} =
## generates the HTML ``ins`` element.
let e = callsite()
result = xmlCheckedTag(e, "ins", "cite datetime" & commonAttr)
macro kbd*(e: expr): expr {.immediate.} =
macro kbd*(e: expr): expr {.immediate.} =
## generates the HTML ``kbd`` element.
let e = callsite()
result = xmlCheckedTag(e, "kbd", commonAttr)
macro label*(e: expr): expr {.immediate.} =
macro label*(e: expr): expr {.immediate.} =
## generates the HTML ``label`` element.
let e = callsite()
result = xmlCheckedTag(e, "label", "for accesskey" & commonAttr)
macro legend*(e: expr): expr {.immediate.} =
macro legend*(e: expr): expr {.immediate.} =
## generates the HTML ``legend`` element.
let e = callsite()
result = xmlCheckedTag(e, "legend", "accesskey" & commonAttr)
macro li*(e: expr): expr {.immediate.} =
macro li*(e: expr): expr {.immediate.} =
## generates the HTML ``li`` element.
let e = callsite()
result = xmlCheckedTag(e, "li", commonAttr)
macro link*(e: expr): expr {.immediate.} =
macro link*(e: expr): expr {.immediate.} =
## generates the HTML ``link`` element.
let e = callsite()
result = xmlCheckedTag(e, "link", "href charset hreflang type rel rev media" &
result = xmlCheckedTag(e, "link", "href charset hreflang type rel rev media" &
commonAttr, "", true)
macro map*(e: expr): expr {.immediate.} =
macro map*(e: expr): expr {.immediate.} =
## generates the HTML ``map`` element.
let e = callsite()
result = xmlCheckedTag(e, "map", "class title" & eventAttr, "id", false)
macro meta*(e: expr): expr {.immediate.} =
macro meta*(e: expr): expr {.immediate.} =
## generates the HTML ``meta`` element.
let e = callsite()
result = xmlCheckedTag(e, "meta", "name http-equiv scheme", "content", true)
macro noscript*(e: expr): expr {.immediate.} =
macro noscript*(e: expr): expr {.immediate.} =
## generates the HTML ``noscript`` element.
let e = callsite()
result = xmlCheckedTag(e, "noscript", commonAttr)
macro `object`*(e: expr): expr {.immediate.} =
macro `object`*(e: expr): expr {.immediate.} =
## generates the HTML ``object`` element.
let e = callsite()
result = xmlCheckedTag(e, "object", "classid data codebase declare type " &
"codetype archive standby width height name tabindex" & commonAttr)
macro ol*(e: expr): expr {.immediate.} =
macro ol*(e: expr): expr {.immediate.} =
## generates the HTML ``ol`` element.
let e = callsite()
result = xmlCheckedTag(e, "ol", commonAttr)
macro optgroup*(e: expr): expr {.immediate.} =
macro optgroup*(e: expr): expr {.immediate.} =
## generates the HTML ``optgroup`` element.
let e = callsite()
result = xmlCheckedTag(e, "optgroup", "disabled" & commonAttr, "label", false)
macro option*(e: expr): expr {.immediate.} =
macro option*(e: expr): expr {.immediate.} =
## generates the HTML ``option`` element.
let e = callsite()
result = xmlCheckedTag(e, "option", "selected value" & commonAttr)
macro p*(e: expr): expr {.immediate.} =
macro p*(e: expr): expr {.immediate.} =
## generates the HTML ``p`` element.
let e = callsite()
result = xmlCheckedTag(e, "p", commonAttr)
macro param*(e: expr): expr {.immediate.} =
macro param*(e: expr): expr {.immediate.} =
## generates the HTML ``param`` element.
let e = callsite()
result = xmlCheckedTag(e, "param", "value id type valuetype", "name", true)
macro pre*(e: expr): expr {.immediate.} =
macro pre*(e: expr): expr {.immediate.} =
## generates the HTML ``pre`` element.
let e = callsite()
result = xmlCheckedTag(e, "pre", commonAttr)
macro q*(e: expr): expr {.immediate.} =
macro q*(e: expr): expr {.immediate.} =
## generates the HTML ``q`` element.
let e = callsite()
result = xmlCheckedTag(e, "q", "cite" & commonAttr)
macro samp*(e: expr): expr {.immediate.} =
macro samp*(e: expr): expr {.immediate.} =
## generates the HTML ``samp`` element.
let e = callsite()
result = xmlCheckedTag(e, "samp", commonAttr)
macro script*(e: expr): expr {.immediate.} =
macro script*(e: expr): expr {.immediate.} =
## generates the HTML ``script`` element.
let e = callsite()
result = xmlCheckedTag(e, "script", "src charset defer", "type", false)
macro select*(e: expr): expr {.immediate.} =
macro select*(e: expr): expr {.immediate.} =
## generates the HTML ``select`` element.
let e = callsite()
result = xmlCheckedTag(e, "select", "name size multiple disabled tabindex" &
result = xmlCheckedTag(e, "select", "name size multiple disabled tabindex" &
commonAttr)
macro small*(e: expr): expr {.immediate.} =
macro small*(e: expr): expr {.immediate.} =
## generates the HTML ``small`` element.
let e = callsite()
result = xmlCheckedTag(e, "small", commonAttr)
macro span*(e: expr): expr {.immediate.} =
macro span*(e: expr): expr {.immediate.} =
## generates the HTML ``span`` element.
let e = callsite()
result = xmlCheckedTag(e, "span", commonAttr)
macro strong*(e: expr): expr {.immediate.} =
macro strong*(e: expr): expr {.immediate.} =
## generates the HTML ``strong`` element.
let e = callsite()
result = xmlCheckedTag(e, "strong", commonAttr)
macro style*(e: expr): expr {.immediate.} =
macro style*(e: expr): expr {.immediate.} =
## generates the HTML ``style`` element.
let e = callsite()
result = xmlCheckedTag(e, "style", "media title", "type")
macro sub*(e: expr): expr {.immediate.} =
macro sub*(e: expr): expr {.immediate.} =
## generates the HTML ``sub`` element.
let e = callsite()
result = xmlCheckedTag(e, "sub", commonAttr)
macro sup*(e: expr): expr {.immediate.} =
macro sup*(e: expr): expr {.immediate.} =
## generates the HTML ``sup`` element.
let e = callsite()
result = xmlCheckedTag(e, "sup", commonAttr)
macro table*(e: expr): expr {.immediate.} =
macro table*(e: expr): expr {.immediate.} =
## generates the HTML ``table`` element.
let e = callsite()
result = xmlCheckedTag(e, "table", "summary border cellpadding cellspacing" &
" frame rules width" & commonAttr)
macro tbody*(e: expr): expr {.immediate.} =
macro tbody*(e: expr): expr {.immediate.} =
## generates the HTML ``tbody`` element.
let e = callsite()
result = xmlCheckedTag(e, "tbody", "align valign" & commonAttr)
macro td*(e: expr): expr {.immediate.} =
macro td*(e: expr): expr {.immediate.} =
## generates the HTML ``td`` element.
let e = callsite()
result = xmlCheckedTag(e, "td", "colspan rowspan abbr axis headers scope" &
" align valign" & commonAttr)
macro textarea*(e: expr): expr {.immediate.} =
macro textarea*(e: expr): expr {.immediate.} =
## generates the HTML ``textarea`` element.
let e = callsite()
result = xmlCheckedTag(e, "textarea", " name disabled readonly accesskey" &
" tabindex" & commonAttr, "rows cols", false)
macro tfoot*(e: expr): expr {.immediate.} =
macro tfoot*(e: expr): expr {.immediate.} =
## generates the HTML ``tfoot`` element.
let e = callsite()
result = xmlCheckedTag(e, "tfoot", "align valign" & commonAttr)
macro th*(e: expr): expr {.immediate.} =
macro th*(e: expr): expr {.immediate.} =
## generates the HTML ``th`` element.
let e = callsite()
result = xmlCheckedTag(e, "th", "colspan rowspan abbr axis headers scope" &
" align valign" & commonAttr)
macro thead*(e: expr): expr {.immediate.} =
macro thead*(e: expr): expr {.immediate.} =
## generates the HTML ``thead`` element.
let e = callsite()
result = xmlCheckedTag(e, "thead", "align valign" & commonAttr)
macro title*(e: expr): expr {.immediate.} =
macro title*(e: expr): expr {.immediate.} =
## generates the HTML ``title`` element.
let e = callsite()
result = xmlCheckedTag(e, "title")
macro tr*(e: expr): expr {.immediate.} =
macro tr*(e: expr): expr {.immediate.} =
## generates the HTML ``tr`` element.
let e = callsite()
result = xmlCheckedTag(e, "tr", "align valign" & commonAttr)
macro tt*(e: expr): expr {.immediate.} =
macro tt*(e: expr): expr {.immediate.} =
## generates the HTML ``tt`` element.
let e = callsite()
result = xmlCheckedTag(e, "tt", commonAttr)
macro ul*(e: expr): expr {.immediate.} =
macro ul*(e: expr): expr {.immediate.} =
## generates the HTML ``ul`` element.
let e = callsite()
result = xmlCheckedTag(e, "ul", commonAttr)
macro `var`*(e: expr): expr {.immediate.} =
macro `var`*(e: expr): expr {.immediate.} =
## generates the HTML ``var`` element.
let e = callsite()
result = xmlCheckedTag(e, "var", commonAttr)

View File

@@ -8,8 +8,8 @@
#
## This module implements a simple high performance `JSON`:idx:
## parser. JSON (JavaScript Object Notation) is a lightweight
## data-interchange format that is easy for humans to read and write
## parser. JSON (JavaScript Object Notation) is a lightweight
## data-interchange format that is easy for humans to read and write
## (unlike XML). It is easy for machines to parse and generate.
## JSON is based on a subset of the JavaScript Programming Language,
## Standard ECMA-262 3rd Edition - December 1999.
@@ -50,10 +50,10 @@
## }
## ]
import
import
hashes, strutils, lexbase, streams, unicode, macros
type
type
JsonEventKind* = enum ## enumeration of all events that may occur when parsing
jsonError, ## an error occurred during parsing
jsonEof, ## end of file reached
@@ -67,7 +67,7 @@ type
jsonObjectEnd, ## end of an object: the ``}`` token
jsonArrayStart, ## start of an array: the ``[`` token
jsonArrayEnd ## start of an array: the ``]`` token
TTokKind = enum # must be synchronized with TJsonEventKind!
tkError,
tkEof,
@@ -83,7 +83,7 @@ type
tkBracketRi,
tkColon,
tkComma
JsonError* = enum ## enumeration that lists all errors that can occur
errNone, ## no error
errInvalidToken, ## invalid token
@@ -96,8 +96,8 @@ type
errEOC_Expected, ## ``*/`` expected
errEofExpected, ## EOF expected
errExprExpected ## expr expected
ParserState = enum
ParserState = enum
stateEof, stateStart, stateObject, stateArray, stateExpectArrayComma,
stateExpectObjectComma, stateExpectColon, stateExpectValue
@@ -111,7 +111,7 @@ type
{.deprecated: [TJsonEventKind: JsonEventKind, TJsonError: JsonError,
TJsonParser: JsonParser].}
const
errorMessages: array [JsonError, string] = [
"no error",
@@ -146,56 +146,56 @@ proc open*(my: var JsonParser, input: Stream, filename: string) =
my.state = @[stateStart]
my.kind = jsonError
my.a = ""
proc close*(my: var JsonParser) {.inline.} =
proc close*(my: var JsonParser) {.inline.} =
## closes the parser `my` and its associated input stream.
lexbase.close(my)
proc str*(my: JsonParser): string {.inline.} =
## returns the character data for the events: ``jsonInt``, ``jsonFloat``,
proc str*(my: JsonParser): string {.inline.} =
## returns the character data for the events: ``jsonInt``, ``jsonFloat``,
## ``jsonString``
assert(my.kind in {jsonInt, jsonFloat, jsonString})
return my.a
proc getInt*(my: JsonParser): BiggestInt {.inline.} =
proc getInt*(my: JsonParser): BiggestInt {.inline.} =
## returns the number for the event: ``jsonInt``
assert(my.kind == jsonInt)
return parseBiggestInt(my.a)
proc getFloat*(my: JsonParser): float {.inline.} =
proc getFloat*(my: JsonParser): float {.inline.} =
## returns the number for the event: ``jsonFloat``
assert(my.kind == jsonFloat)
return parseFloat(my.a)
proc kind*(my: JsonParser): JsonEventKind {.inline.} =
proc kind*(my: JsonParser): JsonEventKind {.inline.} =
## returns the current event type for the JSON parser
return my.kind
proc getColumn*(my: JsonParser): int {.inline.} =
proc getColumn*(my: JsonParser): int {.inline.} =
## get the current column the parser has arrived at.
result = getColNumber(my, my.bufpos)
proc getLine*(my: JsonParser): int {.inline.} =
proc getLine*(my: JsonParser): int {.inline.} =
## get the current line the parser has arrived at.
result = my.lineNumber
proc getFilename*(my: JsonParser): string {.inline.} =
proc getFilename*(my: JsonParser): string {.inline.} =
## get the filename of the file that the parser processes.
result = my.filename
proc errorMsg*(my: JsonParser): string =
proc errorMsg*(my: JsonParser): string =
## returns a helpful error message for the event ``jsonError``
assert(my.kind == jsonError)
result = "$1($2, $3) Error: $4" % [
my.filename, $getLine(my), $getColumn(my), errorMessages[my.err]]
proc errorMsgExpected*(my: JsonParser, e: string): string =
proc errorMsgExpected*(my: JsonParser, e: string): string =
## returns an error message "`e` expected" in the same format as the
## other error messages
## other error messages
result = "$1($2, $3) Error: $4" % [
my.filename, $getLine(my), $getColumn(my), e & " expected"]
proc handleHexChar(c: char, x: var int): bool =
proc handleHexChar(c: char, x: var int): bool =
result = true # Success
case c
of '0'..'9': x = (x shl 4) or (ord(c) - ord('0'))
@@ -208,8 +208,8 @@ proc parseString(my: var JsonParser): TTokKind =
var pos = my.bufpos + 1
var buf = my.buf
while true:
case buf[pos]
of '\0':
case buf[pos]
of '\0':
my.err = errQuoteExpected
result = tkError
break
@@ -218,21 +218,21 @@ proc parseString(my: var JsonParser): TTokKind =
break
of '\\':
case buf[pos+1]
of '\\', '"', '\'', '/':
of '\\', '"', '\'', '/':
add(my.a, buf[pos+1])
inc(pos, 2)
of 'b':
add(my.a, '\b')
inc(pos, 2)
inc(pos, 2)
of 'f':
add(my.a, '\f')
inc(pos, 2)
inc(pos, 2)
of 'n':
add(my.a, '\L')
inc(pos, 2)
inc(pos, 2)
of 'r':
add(my.a, '\C')
inc(pos, 2)
inc(pos, 2)
of 't':
add(my.a, '\t')
inc(pos, 2)
@@ -244,15 +244,15 @@ proc parseString(my: var JsonParser): TTokKind =
if handleHexChar(buf[pos], r): inc(pos)
if handleHexChar(buf[pos], r): inc(pos)
add(my.a, toUTF8(Rune(r)))
else:
else:
# don't bother with the error
add(my.a, buf[pos])
inc(pos)
of '\c':
of '\c':
pos = lexbase.handleCR(my, pos)
buf = my.buf
add(my.a, '\c')
of '\L':
of '\L':
pos = lexbase.handleLF(my, pos)
buf = my.buf
add(my.a, '\L')
@@ -260,25 +260,25 @@ proc parseString(my: var JsonParser): TTokKind =
add(my.a, buf[pos])
inc(pos)
my.bufpos = pos # store back
proc skip(my: var JsonParser) =
proc skip(my: var JsonParser) =
var pos = my.bufpos
var buf = my.buf
while true:
while true:
case buf[pos]
of '/':
if buf[pos+1] == '/':
of '/':
if buf[pos+1] == '/':
# skip line comment:
inc(pos, 2)
while true:
case buf[pos]
of '\0':
case buf[pos]
of '\0':
break
of '\c':
of '\c':
pos = lexbase.handleCR(my, pos)
buf = my.buf
break
of '\L':
of '\L':
pos = lexbase.handleLF(my, pos)
buf = my.buf
break
@@ -288,44 +288,44 @@ proc skip(my: var JsonParser) =
# skip long comment:
inc(pos, 2)
while true:
case buf[pos]
of '\0':
case buf[pos]
of '\0':
my.err = errEOC_Expected
break
of '\c':
of '\c':
pos = lexbase.handleCR(my, pos)
buf = my.buf
of '\L':
of '\L':
pos = lexbase.handleLF(my, pos)
buf = my.buf
of '*':
inc(pos)
if buf[pos] == '/':
if buf[pos] == '/':
inc(pos)
break
else:
inc(pos)
else:
else:
break
of ' ', '\t':
of ' ', '\t':
inc(pos)
of '\c':
of '\c':
pos = lexbase.handleCR(my, pos)
buf = my.buf
of '\L':
of '\L':
pos = lexbase.handleLF(my, pos)
buf = my.buf
else:
break
my.bufpos = pos
proc parseNumber(my: var JsonParser) =
proc parseNumber(my: var JsonParser) =
var pos = my.bufpos
var buf = my.buf
if buf[pos] == '-':
if buf[pos] == '-':
add(my.a, '-')
inc(pos)
if buf[pos] == '.':
if buf[pos] == '.':
add(my.a, "0.")
inc(pos)
else:
@@ -350,7 +350,7 @@ proc parseNumber(my: var JsonParser) =
inc(pos)
my.bufpos = pos
proc parseName(my: var JsonParser) =
proc parseName(my: var JsonParser) =
var pos = my.bufpos
var buf = my.buf
if buf[pos] in IdentStartChars:
@@ -359,11 +359,11 @@ proc parseName(my: var JsonParser) =
inc(pos)
my.bufpos = pos
proc getTok(my: var JsonParser): TTokKind =
proc getTok(my: var JsonParser): TTokKind =
setLen(my.a, 0)
skip(my) # skip whitespace, comments
case my.buf[my.bufpos]
of '-', '.', '0'..'9':
of '-', '.', '0'..'9':
parseNumber(my)
if {'.', 'e', 'E'} in my.a:
result = tkFloat
@@ -393,17 +393,17 @@ proc getTok(my: var JsonParser): TTokKind =
result = tkEof
of 'a'..'z', 'A'..'Z', '_':
parseName(my)
case my.a
case my.a
of "null": result = tkNull
of "true": result = tkTrue
of "false": result = tkFalse
else: result = tkError
else:
else:
inc(my.bufpos)
result = tkError
my.tok = result
proc next*(my: var JsonParser) =
proc next*(my: var JsonParser) =
## retrieves the first/next event. This controls the parser.
var tk = getTok(my)
var i = my.state.len-1
@@ -416,13 +416,13 @@ proc next*(my: var JsonParser) =
else:
my.kind = jsonError
my.err = errEofExpected
of stateStart:
# tokens allowed?
of stateStart:
# tokens allowed?
case tk
of tkString, tkInt, tkFloat, tkTrue, tkFalse, tkNull:
my.state[i] = stateEof # expect EOF next!
my.kind = JsonEventKind(ord(tk))
of tkBracketLe:
of tkBracketLe:
my.state.add(stateArray) # we expect any
my.kind = jsonArrayStart
of tkCurlyLe:
@@ -433,12 +433,12 @@ proc next*(my: var JsonParser) =
else:
my.kind = jsonError
my.err = errEofExpected
of stateObject:
of stateObject:
case tk
of tkString, tkInt, tkFloat, tkTrue, tkFalse, tkNull:
my.state.add(stateExpectColon)
my.kind = JsonEventKind(ord(tk))
of tkBracketLe:
of tkBracketLe:
my.state.add(stateExpectColon)
my.state.add(stateArray)
my.kind = jsonArrayStart
@@ -457,7 +457,7 @@ proc next*(my: var JsonParser) =
of tkString, tkInt, tkFloat, tkTrue, tkFalse, tkNull:
my.state.add(stateExpectArrayComma) # expect value next!
my.kind = JsonEventKind(ord(tk))
of tkBracketLe:
of tkBracketLe:
my.state.add(stateExpectArrayComma)
my.state.add(stateArray)
my.kind = jsonArrayStart
@@ -472,8 +472,8 @@ proc next*(my: var JsonParser) =
my.kind = jsonError
my.err = errBracketRiExpected
of stateExpectArrayComma:
case tk
of tkComma:
case tk
of tkComma:
discard my.state.pop()
next(my)
of tkBracketRi:
@@ -484,8 +484,8 @@ proc next*(my: var JsonParser) =
my.kind = jsonError
my.err = errBracketRiExpected
of stateExpectObjectComma:
case tk
of tkComma:
case tk
of tkComma:
discard my.state.pop()
next(my)
of tkCurlyRi:
@@ -495,9 +495,9 @@ proc next*(my: var JsonParser) =
else:
my.kind = jsonError
my.err = errCurlyRiExpected
of stateExpectColon:
case tk
of tkColon:
of stateExpectColon:
case tk
of tkColon:
my.state[i] = stateExpectValue
next(my)
else:
@@ -508,7 +508,7 @@ proc next*(my: var JsonParser) =
of tkString, tkInt, tkFloat, tkTrue, tkFalse, tkNull:
my.state[i] = stateExpectObjectComma
my.kind = JsonEventKind(ord(tk))
of tkBracketLe:
of tkBracketLe:
my.state[i] = stateExpectObjectComma
my.state.add(stateArray)
my.kind = jsonArrayStart
@@ -532,8 +532,8 @@ type
JString,
JObject,
JArray
JsonNode* = ref JsonNodeObj ## JSON node
JsonNode* = ref JsonNodeObj ## JSON node
JsonNodeObj* {.acyclic.} = object
case kind*: JsonNodeKind
of JString:
@@ -644,7 +644,7 @@ proc `%`*(elements: openArray[JsonNode]): JsonNode =
newSeq(result.elems, elements.len)
for i, p in pairs(elements): result.elems[i] = p
proc toJson(x: PNimrodNode): PNimrodNode {.compiletime.} =
proc toJson(x: NimNode): NimNode {.compiletime.} =
case x.kind
of nnkBracket:
result = newNimNode(nnkBracket)
@@ -672,7 +672,7 @@ proc `==`* (a,b: JsonNode): bool =
if a.isNil:
if b.isNil: return true
return false
elif b.isNil or a.kind != b.kind:
elif b.isNil or a.kind != b.kind:
return false
else:
return case a.kind
@@ -709,7 +709,7 @@ proc hash* (n:JsonNode): THash =
of JNull:
result = hash(0)
proc len*(n: JsonNode): int =
proc len*(n: JsonNode): int =
## If `n` is a `JArray`, it returns the number of elements.
## If `n` is a `JObject`, it returns the number of pairs.
## Else it returns 0.
@@ -727,7 +727,7 @@ proc `[]`*(node: JsonNode, name: string): JsonNode =
if key == name:
return item
return nil
proc `[]`*(node: JsonNode, index: int): JsonNode =
## Gets the node at `index` in an Array. Result is undefined if `index`
## is out of bounds
@@ -744,12 +744,12 @@ proc hasKey*(node: JsonNode, key: string): bool =
proc existsKey*(node: JsonNode, key: string): bool {.deprecated.} = node.hasKey(key)
## Deprecated for `hasKey`
proc add*(father, child: JsonNode) =
## Adds `child` to a JArray node `father`.
proc add*(father, child: JsonNode) =
## Adds `child` to a JArray node `father`.
assert father.kind == JArray
father.elems.add(child)
proc add*(obj: JsonNode, key: string, val: JsonNode) =
proc add*(obj: JsonNode, key: string, val: JsonNode) =
## Adds ``(key, val)`` pair to the JObject node `obj`. For speed
## reasons no check for duplicate keys is performed!
## But ``[]=`` performs the check.
@@ -760,7 +760,7 @@ proc `[]=`*(obj: JsonNode, key: string, val: JsonNode) =
## Sets a field from a `JObject`. Performs a check for duplicate keys.
assert(obj.kind == JObject)
for i in 0..obj.fields.len-1:
if obj.fields[i].key == key:
if obj.fields[i].key == key:
obj.fields[i].val = val
return
obj.fields.add((key, val))
@@ -815,17 +815,17 @@ proc copy*(p: JsonNode): JsonNode =
# ------------- pretty printing ----------------------------------------------
proc indent(s: var string, i: int) =
proc indent(s: var string, i: int) =
s.add(spaces(i))
proc newIndent(curr, indent: int, ml: bool): int =
if ml: return curr + indent
else: return indent
proc nl(s: var string, ml: bool) =
proc nl(s: var string, ml: bool) =
if ml: s.add("\n")
proc escapeJson*(s: string): string =
proc escapeJson*(s: string): string =
## Converts a string `s` to its JSON representation.
result = newStringOfCap(s.len + s.len shr 3)
result.add("\"")
@@ -842,13 +842,13 @@ proc escapeJson*(s: string): string =
result.add(toHex(r, 4))
result.add("\"")
proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
lstArr = false, currIndent = 0) =
case node.kind
of JObject:
if currIndent != 0 and not lstArr: result.nl(ml)
result.indent(currIndent) # Indentation
if node.fields.len > 0:
if node.fields.len > 0:
result.add("{")
result.nl(ml) # New line
for i in 0..len(node.fields)-1:
@@ -856,17 +856,17 @@ proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
result.add(", ")
result.nl(ml) # New Line
# Need to indent more than {
result.indent(newIndent(currIndent, indent, ml))
result.indent(newIndent(currIndent, indent, ml))
result.add(escapeJson(node.fields[i].key))
result.add(": ")
toPretty(result, node.fields[i].val, indent, ml, false,
toPretty(result, node.fields[i].val, indent, ml, false,
newIndent(currIndent, indent, ml))
result.nl(ml)
result.indent(currIndent) # indent the same as {
result.add("}")
else:
result.add("{}")
of JString:
of JString:
if lstArr: result.indent(currIndent)
result.add(escapeJson(node.str))
of JInt:
@@ -934,11 +934,11 @@ iterator mpairs*(node: var JsonNode): var tuple[key: string, val: JsonNode] =
for keyVal in mitems(node.fields):
yield keyVal
proc eat(p: var JsonParser, tok: TTokKind) =
proc eat(p: var JsonParser, tok: TTokKind) =
if p.tok == tok: discard getTok(p)
else: raiseParseErr(p, tokToStr[tok])
proc parseJson(p: var JsonParser): JsonNode =
proc parseJson(p: var JsonParser): JsonNode =
## Parses JSON from a JSON Parser `p`.
case p.tok
of tkString:
@@ -955,17 +955,17 @@ proc parseJson(p: var JsonParser): JsonNode =
of tkTrue:
result = newJBool(true)
discard getTok(p)
of tkFalse:
of tkFalse:
result = newJBool(false)
discard getTok(p)
of tkNull:
of tkNull:
result = newJNull()
discard getTok(p)
of tkCurlyLe:
of tkCurlyLe:
result = newJObject()
discard getTok(p)
while p.tok != tkCurlyRi:
if p.tok != tkString:
while p.tok != tkCurlyRi:
if p.tok != tkString:
raiseParseErr(p, "string literal as key expected")
var key = p.a
discard getTok(p)
@@ -978,7 +978,7 @@ proc parseJson(p: var JsonParser): JsonNode =
of tkBracketLe:
result = newJArray()
discard getTok(p)
while p.tok != tkBracketRi:
while p.tok != tkBracketRi:
result.add(parseJson(p))
if p.tok != tkComma: break
discard getTok(p)
@@ -1098,10 +1098,10 @@ when false:
of jsonObjectEnd: echo("}")
of jsonArrayStart: echo("[")
of jsonArrayEnd: echo("]")
close(x)
# { "json": 5 }
# { "json": 5 }
# To get that we shall use, obj["json"]
when isMainModule:

View File

@@ -47,7 +47,7 @@ type
{.deprecated: [TTestStatus: TestStatus, TOutputLevel: OutputLevel]}
var
var
abortOnError* {.threadvar.}: bool
outputLevel* {.threadvar.}: OutputLevel
colorOutput* {.threadvar.}: bool
@@ -144,7 +144,7 @@ macro check*(conditions: stmt): stmt {.immediate.} =
when compiles(string($value)):
checkpoint(name & " was " & $value)
proc inspectArgs(exp: PNimrodNode) =
proc inspectArgs(exp: NimNode) =
for i in 1 .. <exp.len:
if exp[i].kind notin nnkLiterals:
inc counter
@@ -202,7 +202,7 @@ template require*(conditions: stmt): stmt {.immediate, dirty.} =
macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} =
let exp = callsite()
template expectBody(errorTypes, lineInfoLit: expr,
body: stmt): PNimrodNode {.dirty.} =
body: stmt): NimNode {.dirty.} =
try:
body
checkpoint(lineInfoLit & ": Expect Failed, no exception was thrown.")

View File

@@ -12,20 +12,20 @@
import macros, strtabs
type
XmlNode* = ref XmlNodeObj ## an XML tree consists of ``PXmlNode``'s.
XmlNode* = ref XmlNodeObj ## an XML tree consists of ``PXmlNode``'s.
XmlNodeKind* = enum ## different kinds of ``PXmlNode``'s
xnText, ## a text element
xnElement, ## an element with 0 or more children
xnCData, ## a CDATA node
xnEntity, ## an entity (like ``&thing;``)
xnComment ## an XML comment
XmlAttributes* = StringTableRef ## an alias for a string to string mapping
XmlNodeObj {.acyclic.} = object
XmlNodeObj {.acyclic.} = object
case k: XmlNodeKind # private, use the kind() proc to read this field.
of xnText, xnComment, xnCData, xnEntity:
of xnText, xnComment, xnCData, xnEntity:
fText: string
of xnElement:
fTag: string
@@ -41,34 +41,34 @@ proc newXmlNode(kind: XmlNodeKind): XmlNode =
new(result)
result.k = kind
proc newElement*(tag: string): XmlNode =
proc newElement*(tag: string): XmlNode =
## creates a new ``PXmlNode`` of kind ``xnText`` with the given `tag`.
result = newXmlNode(xnElement)
result.fTag = tag
result.s = @[]
# init attributes lazily to safe memory
proc newText*(text: string): XmlNode =
proc newText*(text: string): XmlNode =
## creates a new ``PXmlNode`` of kind ``xnText`` with the text `text`.
result = newXmlNode(xnText)
result.fText = text
proc newComment*(comment: string): XmlNode =
proc newComment*(comment: string): XmlNode =
## creates a new ``PXmlNode`` of kind ``xnComment`` with the text `comment`.
result = newXmlNode(xnComment)
result.fText = comment
proc newCData*(cdata: string): XmlNode =
proc newCData*(cdata: string): XmlNode =
## creates a new ``PXmlNode`` of kind ``xnComment`` with the text `cdata`.
result = newXmlNode(xnCData)
result.fText = cdata
proc newEntity*(entity: string): XmlNode =
proc newEntity*(entity: string): XmlNode =
## creates a new ``PXmlNode`` of kind ``xnEntity`` with the text `entity`.
result = newXmlNode(xnCData)
result.fText = entity
proc text*(n: XmlNode): string {.inline.} =
proc text*(n: XmlNode): string {.inline.} =
## gets the associated text with the node `n`. `n` can be a CDATA, Text,
## comment, or entity node.
assert n.k in {xnText, xnComment, xnCData, xnEntity}
@@ -93,16 +93,16 @@ proc innerText*(n: XmlNode): string =
for i in 0 .. n.s.len-1:
if n.s[i].k in {xnText, xnEntity}: result.add(n.s[i].fText)
proc tag*(n: XmlNode): string {.inline.} =
proc tag*(n: XmlNode): string {.inline.} =
## gets the tag name of `n`. `n` has to be an ``xnElement`` node.
assert n.k == xnElement
result = n.fTag
proc add*(father, son: XmlNode) {.inline.} =
proc add*(father, son: XmlNode) {.inline.} =
## adds the child `son` to `father`.
add(father.s, son)
proc len*(n: XmlNode): int {.inline.} =
proc len*(n: XmlNode): int {.inline.} =
## returns the number `n`'s children.
if n.k == xnElement: result = len(n.s)
@@ -110,38 +110,38 @@ proc kind*(n: XmlNode): XmlNodeKind {.inline.} =
## returns `n`'s kind.
result = n.k
proc `[]`* (n: XmlNode, i: int): XmlNode {.inline.} =
proc `[]`* (n: XmlNode, i: int): XmlNode {.inline.} =
## returns the `i`'th child of `n`.
assert n.k == xnElement
result = n.s[i]
proc mget* (n: var XmlNode, i: int): var XmlNode {.inline.} =
proc mget* (n: var XmlNode, i: int): var XmlNode {.inline.} =
## returns the `i`'th child of `n` so that it can be modified
assert n.k == xnElement
result = n.s[i]
iterator items*(n: XmlNode): XmlNode {.inline.} =
iterator items*(n: XmlNode): XmlNode {.inline.} =
## iterates over any child of `n`.
assert n.k == xnElement
for i in 0 .. n.len-1: yield n[i]
iterator mitems*(n: var XmlNode): var XmlNode {.inline.} =
iterator mitems*(n: var XmlNode): var XmlNode {.inline.} =
## iterates over any child of `n`.
assert n.k == xnElement
for i in 0 .. n.len-1: yield mget(n, i)
proc attrs*(n: XmlNode): XmlAttributes {.inline.} =
proc attrs*(n: XmlNode): XmlAttributes {.inline.} =
## gets the attributes belonging to `n`.
## Returns `nil` if attributes have not been initialised for this node.
assert n.k == xnElement
result = n.fAttr
proc `attrs=`*(n: XmlNode, attr: XmlAttributes) {.inline.} =
proc `attrs=`*(n: XmlNode, attr: XmlAttributes) {.inline.} =
## sets the attributes belonging to `n`.
assert n.k == xnElement
n.fAttr = attr
proc attrsLen*(n: XmlNode): int {.inline.} =
proc attrsLen*(n: XmlNode): int {.inline.} =
## returns the number of `n`'s attributes.
assert n.k == xnElement
if not isNil(n.fAttr): result = len(n.fAttr)
@@ -151,12 +151,12 @@ proc clientData*(n: XmlNode): int {.inline.} =
## parser and generator.
result = n.fClientData
proc `clientData=`*(n: XmlNode, data: int) {.inline.} =
proc `clientData=`*(n: XmlNode, data: int) {.inline.} =
## sets the client data of `n`. The client data field is used by the HTML
## parser and generator.
n.fClientData = data
proc addEscaped*(result: var string, s: string) =
proc addEscaped*(result: var string, s: string) =
## same as ``result.add(escape(s))``, but more efficient.
for c in items(s):
case c
@@ -168,8 +168,8 @@ proc addEscaped*(result: var string, s: string) =
of '/': result.add("&#x2F;")
else: result.add(c)
proc escape*(s: string): string =
## escapes `s` for inclusion into an XML document.
proc escape*(s: string): string =
## escapes `s` for inclusion into an XML document.
## Escapes these characters:
##
## ------------ -------------------
@@ -184,26 +184,26 @@ proc escape*(s: string): string =
## ------------ -------------------
result = newStringOfCap(s.len)
addEscaped(result, s)
proc addIndent(result: var string, indent: int) =
proc addIndent(result: var string, indent: int) =
result.add("\n")
for i in 1..indent: result.add(' ')
proc noWhitespace(n: XmlNode): bool =
#for i in 1..n.len-1:
# if n[i].kind != n[0].kind: return true
for i in 0..n.len-1:
if n[i].kind in {xnText, xnEntity}: return true
proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) =
proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) =
## adds the textual representation of `n` to `result`.
if n == nil: return
case n.k
of xnElement:
result.add('<')
result.add(n.fTag)
if not isNil(n.fAttr):
for key, val in pairs(n.fAttr):
if not isNil(n.fAttr):
for key, val in pairs(n.fAttr):
result.add(' ')
result.add(key)
result.add("=\"")
@@ -217,7 +217,7 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) =
# because this would be wrong. For example: ``a<b>b</b>`` is
# different from ``a <b>b</b>``.
for i in 0..n.len-1: result.add(n[i], indent+indWidth, indWidth)
else:
else:
for i in 0..n.len-1:
result.addIndent(indent+indWidth)
result.add(n[i], indent+indWidth, indWidth)
@@ -227,7 +227,7 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) =
result.add("</")
result.add(n.fTag)
result.add(">")
else:
else:
result.add(" />")
of xnText:
result.addEscaped(n.fText)
@@ -245,7 +245,7 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) =
result.add(';')
const
xmlHeader* = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
xmlHeader* = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
## header to use for complete XML output
proc `$`*(n: XmlNode): string =
@@ -255,21 +255,21 @@ proc `$`*(n: XmlNode): string =
result.add(n)
proc newXmlTree*(tag: string, children: openArray[XmlNode],
attributes: XmlAttributes = nil): XmlNode =
attributes: XmlAttributes = nil): XmlNode =
## creates a new XML tree with `tag`, `children` and `attributes`
result = newXmlNode(xnElement)
result.fTag = tag
newSeq(result.s, children.len)
for i in 0..children.len-1: result.s[i] = children[i]
result.fAttr = attributes
proc xmlConstructor(e: PNimrodNode): PNimrodNode {.compileTime.} =
proc xmlConstructor(e: NimNode): NimNode {.compileTime.} =
expectLen(e, 2)
var a = e[1]
if a.kind == nnkCall:
result = newCall("newXmlTree", toStrLit(a[0]))
var attrs = newNimNode(nnkBracket, a)
var newStringTabCall = newCall("newStringTable", attrs,
var newStringTabCall = newCall("newStringTable", attrs,
newIdentNode("modeCaseSensitive"))
var elements = newNimNode(nnkBracket, a)
for i in 1..a.len-1:
@@ -280,13 +280,13 @@ proc xmlConstructor(e: PNimrodNode): PNimrodNode {.compileTime.} =
else:
elements.add(a[i])
result.add(elements)
if attrs.len > 1:
if attrs.len > 1:
#echo repr(newStringTabCall)
result.add(newStringTabCall)
else:
result = newCall("newXmlTree", toStrLit(a))
macro `<>`*(x: expr): expr {.immediate.} =
macro `<>`*(x: expr): expr {.immediate.} =
## Constructor macro for XML. Example usage:
##
## .. code-block:: nim

View File

@@ -3149,15 +3149,9 @@ proc shallow*(s: var string) {.noSideEffect, inline.} =
type
NimNodeObj = object
when defined(nimnode):
type
NimNode* {.magic: "PNimrodNode".} = ref NimNodeObj
## represents a Nim AST node. Macros operate on this type.
{.deprecated: [PNimrodNode: NimNode].}
else:
type
PNimrodNode* {.magic: "PNimrodNode".} = ref NimNodeObj
## represents a Nim AST node. Macros operate on this type.
NimNode* {.magic: "PNimrodNode".} = ref NimNodeObj
## represents a Nim AST node. Macros operate on this type.
{.deprecated: [PNimrodNode: NimNode].}
when false:
template eval*(blk: stmt): stmt =