Skip to content

Instantly share code, notes, and snippets.

@copygirl
Last active October 25, 2018 08:51
Show Gist options
  • Save copygirl/c1d5b87c88ce76baddc9ad8f148612c5 to your computer and use it in GitHub Desktop.
Save copygirl/c1d5b87c88ce76baddc9ad8f148612c5 to your computer and use it in GitHub Desktop.
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