Last active
October 25, 2018 08:51
-
-
Save copygirl/c1d5b87c88ce76baddc9ad8f148612c5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import | |
macros, | |
options, | |
sets, | |
strutils, | |
typetraits | |
macro foo(i: static[int]): untyped = | |
echo $i | |
foo(1) | |
foo(2) | |
macro makeEitherType(size: static[int]): untyped = | |
echo $size | |
result = parseStmt """ | |
type | |
EitherX*[TYPES] = object | |
case which: range[0..LEN] | |
of X: valueX: TX | |
proc has*[TYPES](either: EitherX[TYPES], want: typedesc): bool = | |
when want is TX: either.which == X | |
else: {.fatal: ("'$#' is not a valid type for " % [$want, $type(either)]).} | |
proc unsafeGet*[TYPES](either: EitherX[TYPES], want: typedesc): want = | |
when want is TX: either.valueX | |
else: {.fatal.} | |
proc get*[TYPES](either: EitherX[TYPES], want: typedesc): want = | |
if not either.has(want): raise newException( | |
ValueError, "$# is not a '$#'" % [type(either), $want]) | |
either.unsafeGet(want) | |
proc option*[TYPES](either: EitherX[TYPES], want: typedesc): Option[want] = | |
if not either.has(want): return want.none | |
when want is TX: either.valueX.some | |
else: {.fatal.} | |
# proc `[]`*[TYPES](either: EitherX[TYPES], want: typedesc): want = | |
# either.get(want) | |
""" | |
echo result.treeRepr | |
let setter = parseStmt """ | |
proc set*[TYPES](either: var EitherX[TYPES], value: TX) = | |
either.which = X | |
either.valueX = value | |
""" | |
proc process(node: NimNode, index: Option[int] = int.none): NimNode = | |
case node.kind: | |
of nnkIdent: | |
return | |
if index.isSome: | |
let i = index.get() | |
case $node.ident: | |
of "X": newLit(i) | |
of "valueX": newIdentNode("value" & $i) | |
of "TX": newIdentNode("T" & $i) | |
else: node | |
elif ($node.ident).startsWith("EitherX"): | |
newIdentNode("Either" & $size) | |
elif $node.ident == "LEN": | |
newLit(size) | |
else: node | |
of nnkIdentDefs: | |
if (node[0].kind == nnkIdent and $node[0].ident == "TYPES"): | |
node.del(0) | |
for i in 0..<size: | |
node.insert(i, newIdentNode("T" & $i)) | |
of nnkBracketExpr: | |
if node[0].kind == nnkIdent and ($node[0].ident).startsWith("EitherX"): | |
node[0] = newIdentNode("Either" & $size) | |
node.del(1) | |
for i in 0..<size: | |
node.add(newIdentNode("T" & $i)) | |
of nnkRecCase: | |
discard process(node[0]) | |
for i in 1..<size: | |
node.add(process(node[1].copyNimTree(), i.some)) | |
discard process(node[1], 0.some) | |
return node | |
of nnkWhenStmt: | |
for i in 1..<size: | |
node.add(process(node[0].copyNimTree(), i.some)) | |
discard process(node[0], 0.some) | |
return node | |
else: discard | |
for i in 0..<node.len: | |
node[i] = process(node[i], index) | |
node | |
discard process(result) | |
for i in 0..<size: | |
result.add(process(setter.copyNimTree(), i.some)) | |
echo result.repr | |
makeEitherType(2) | |
# makeEitherType(3) | |
# makeEitherType(4) | |
# makeEitherType(5) | |
# makeEitherType(6) | |
when isMainModule: | |
var either: Either2[string, int] | |
either.set("foo") | |
# echo "type: " & $either.getType() | |
echo "is string: " & $either.has(string) | |
echo "is int: " & $either.has(int) | |
# echo "is bool: " & $either.has(bool) | |
echo $either[string] | |
echo $either.option(int) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment