replaced asArray with a much more powerful mapLiterals macro
This commit is contained in:
parent
5b57abe354
commit
908a25a2ca
3 changed files with 49 additions and 19 deletions
|
|
@ -78,10 +78,13 @@ This now needs to be written as:
|
||||||
via the new ``nim doc0`` command.
|
via the new ``nim doc0`` command.
|
||||||
- Added ``system.getStackTraceEntries`` that allows you to access the stack
|
- Added ``system.getStackTraceEntries`` that allows you to access the stack
|
||||||
trace in a structured manner without string parsing.
|
trace in a structured manner without string parsing.
|
||||||
|
- Added ``sequtils.mapLiterals`` for easier construction of array and tuple
|
||||||
|
literals.
|
||||||
|
- Added ``macros.isAtomicLit`` predicate.
|
||||||
- Moved from stdlib into Nimble packages:
|
- Moved from stdlib into Nimble packages:
|
||||||
- [``basic2d``](https://github.com/nim-lang/basic2d)
|
- [``basic2d``](https://github.com/nim-lang/basic2d)
|
||||||
_deprecated: use ``glm``, ``arraymancer``, ``neo``, or another package instead_
|
_deprecated: use ``glm``, ``arraymancer``, ``neo``, or another package instead_
|
||||||
- [``basic3d``](https://github.com/nim-lang/basic3d)
|
- [``basic3d``](https://github.com/nim-lang/basic3d)
|
||||||
_deprecated: use ``glm``, ``arraymancer``, ``neo``, or another package instead_
|
_deprecated: use ``glm``, ``arraymancer``, ``neo``, or another package instead_
|
||||||
- [``gentabs``](https://github.com/lcrees/gentabs)
|
- [``gentabs``](https://github.com/lcrees/gentabs)
|
||||||
- [``libuv``](https://github.com/lcrees/libuv)
|
- [``libuv``](https://github.com/lcrees/libuv)
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,7 @@ proc `ident=`*(n: NimNode, val: NimIdent) {.magic: "NSetIdent", noSideEffect.}
|
||||||
proc `strVal=`*(n: NimNode, val: string) {.magic: "NSetStrVal", noSideEffect.}
|
proc `strVal=`*(n: NimNode, val: string) {.magic: "NSetStrVal", noSideEffect.}
|
||||||
|
|
||||||
proc newNimNode*(kind: NimNodeKind,
|
proc newNimNode*(kind: NimNodeKind,
|
||||||
lineInfoFrom: NimNode=nil): NimNode
|
lineInfoFrom: NimNode = nil): NimNode
|
||||||
{.magic: "NNewNimNode", noSideEffect.}
|
{.magic: "NNewNimNode", noSideEffect.}
|
||||||
## Creates a new AST node of the specified kind.
|
## Creates a new AST node of the specified kind.
|
||||||
##
|
##
|
||||||
|
|
@ -470,7 +470,6 @@ proc newLit*(c: char): NimNode {.compileTime.} =
|
||||||
result = newNimNode(nnkCharLit)
|
result = newNimNode(nnkCharLit)
|
||||||
result.intVal = ord(c)
|
result.intVal = ord(c)
|
||||||
|
|
||||||
|
|
||||||
proc newLit*(i: int): NimNode {.compileTime.} =
|
proc newLit*(i: int): NimNode {.compileTime.} =
|
||||||
## produces a new integer literal node.
|
## produces a new integer literal node.
|
||||||
result = newNimNode(nnkIntLit)
|
result = newNimNode(nnkIntLit)
|
||||||
|
|
@ -581,6 +580,11 @@ proc newLit*(s: string): NimNode {.compileTime.} =
|
||||||
result = newNimNode(nnkStrLit)
|
result = newNimNode(nnkStrLit)
|
||||||
result.strVal = s
|
result.strVal = s
|
||||||
|
|
||||||
|
proc isAtomicLit*(n: NimNode): bool =
|
||||||
|
## returns true if ``n`` is some kind literal like ``0.3`` (a ``float``
|
||||||
|
## literal) or ``"abc"`` (a ``string`` literal).
|
||||||
|
result = n.kind in {nnkCharLit..nnkNilLit}
|
||||||
|
|
||||||
proc nestList*(theProc: NimIdent,
|
proc nestList*(theProc: NimIdent,
|
||||||
x: NimNode): NimNode {.compileTime.} =
|
x: NimNode): NimNode {.compileTime.} =
|
||||||
## nests the list `x` into a tree of call expressions:
|
## nests the list `x` into a tree of call expressions:
|
||||||
|
|
|
||||||
|
|
@ -706,27 +706,50 @@ template newSeqWith*(len: int, init: untyped): untyped =
|
||||||
result[i] = init
|
result[i] = init
|
||||||
result
|
result
|
||||||
|
|
||||||
macro asArray*(targetType: typedesc, values: typed): untyped =
|
proc mapLitsImpl(constructor: NimNode; op: NimNode; nested: bool): NimNode =
|
||||||
## applies a type conversion to each of the elements in the specified
|
if isAtomicLit(constructor):
|
||||||
## array literal. Each element is converted to the ``targetType`` type..
|
result = newNimNode(nnkCall, lineInfoFrom=constructor)
|
||||||
|
result.add op
|
||||||
|
result.add constructor
|
||||||
|
else:
|
||||||
|
result = newNimNode(constructor.kind, lineInfoFrom=constructor)
|
||||||
|
for v in constructor:
|
||||||
|
if nested or isAtomicLit(v):
|
||||||
|
result.add mapLitsImpl(v, op, nested)
|
||||||
|
else:
|
||||||
|
result.add v
|
||||||
|
|
||||||
|
macro mapLiterals*(constructor, op: untyped;
|
||||||
|
nested = true): untyped =
|
||||||
|
## applies ``op`` to each of the **atomic** literals like ``3``
|
||||||
|
## or ``"abc"`` in the specified ``constructor`` AST. This can
|
||||||
|
## be used to map every array element to some target type:
|
||||||
##
|
##
|
||||||
## Example:
|
## Example:
|
||||||
##
|
##
|
||||||
## .. code-block::
|
## .. code-block::
|
||||||
## let x = asArray(int, [0.1, 1.2, 2.3, 3.4])
|
## let x = mapLiterals([0.1, 1.2, 2.3, 3.4], int)
|
||||||
## doAssert x is array[4, int]
|
## doAssert x is array[4, int]
|
||||||
##
|
##
|
||||||
## Short notation for:
|
## Short notation for:
|
||||||
##
|
##
|
||||||
## .. code-block::
|
## .. code-block::
|
||||||
## let x = [(0.1).int, (1.2).int, (2.3).int, (3.4).int]
|
## let x = [int(0.1), int(1.2), int(2.3), int(3.4)]
|
||||||
values.expectKind(nnkBracket)
|
##
|
||||||
result = newNimNode(nnkBracket, lineInfoFrom=values)
|
## If ``nested`` is true, the literals are replaced everywhere
|
||||||
for i in 0 ..< len(values):
|
## in the ``constructor`` AST, otherwise only the first level
|
||||||
var call = newNimNode(nnkCall, lineInfoFrom=values[i])
|
## is considered:
|
||||||
call.add targetType
|
##
|
||||||
call.add values[i]
|
## .. code-block::
|
||||||
result.add call
|
## mapLiterals((1, ("abc"), 2), float, nested=false)
|
||||||
|
##
|
||||||
|
## Produces::
|
||||||
|
##
|
||||||
|
## (float(1), ("abc"), float(2))
|
||||||
|
##
|
||||||
|
## There are no constraints for the ``constructor`` AST, it
|
||||||
|
## works for nested tuples of arrays of sets etc.
|
||||||
|
result = mapLitsImpl(constructor, op, nested.boolVal)
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
import strutils
|
import strutils
|
||||||
|
|
@ -1016,11 +1039,11 @@ when isMainModule:
|
||||||
seq2D[0][1] = true
|
seq2D[0][1] = true
|
||||||
doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]]
|
doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]]
|
||||||
|
|
||||||
block: # asArray tests
|
block: # mapLiterals tests
|
||||||
let x = asArray(int, [1.2, 2.3, 3.4, 4.5])
|
let x = mapLiterals([0.1, 1.2, 2.3, 3.4], int)
|
||||||
doAssert x is array[4, int]
|
doAssert x is array[4, int]
|
||||||
let y = asArray(`$`, [1.2, 2.3, 3.4, 4.5])
|
doAssert mapLiterals((1, ("abc"), 2), float, nested=false) == (float(1), "abc", float(2))
|
||||||
doAssert y is array[4, string]
|
doAssert mapLiterals(([1], ("abc"), 2), `$`, nested=true) == (["1"], "abc", "2")
|
||||||
|
|
||||||
when not defined(testing):
|
when not defined(testing):
|
||||||
echo "Finished doc tests"
|
echo "Finished doc tests"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue