Here's an extract of my code.
My issue is with the `proc `$`(s: SNodeAny): string =` function.
Basically, it is just a long list of `if` statements (could be a `case` as
well, doesn't matter) to check if the object is of some type, and then apply
the `$` operator on the casted type. I feel this could be replaced by a two
line macro or template, but for this I need to be able to deduce the original
type of the passed SNode before I can cast and apply the `$` operator.
My real code now includes 4 of these kind of functions where I need to check
for every possible node kind, cast it, and apply some kind of generic function
to it.
import strutils
type
IPv4Address = distinct string
IPv6Address = distinct string
MacAddress = distinct string
Interval = distinct float
# ... many more distinct types
type
SNodeAny = ref object of Rootobj
id: string
parent: SNodeAny
SNodeGroup = ref object of SNodeAny
children: seq[SNodeAny]
SNodeParam = ref object of SNodeAny
SNode[T] = ref object of SNodeParam
val: T
proc newSNode[T](id: string, val: T): SNodeAny =
SNode[T](id: id, val: val).SNodeAny
proc newSNodeGroup(id: string, children: openarray[SNodeAny]): SNodeAny =
var s = SNodeGroup(id: id)
for c in children.items:
s.children.add c
c.parent = result
return s
proc `$`(v: IPv4Address): string = v.string
proc `$`(v: IPv6Address): string = v.string
proc `$`(v: MacAddress): string = v.string
proc `$`(v: Interval): string = $ v.float
proc `$`(s: SNodeAny): string =
if s of SNode[bool]:
result = $ s.SNode[:bool].val
if s of SNode[int]:
result = $ s.SNode[:int].val
if s of SNode[IPv4Address]:
result = $ s.SNode[:IPv4Address].val
if s of SNode[IPv6Address]:
result = $ s.SNode[:IPv6Address].val
if s of SNode[MacAddress]:
result = $ s.SNode[:MacAddress].val
if s of SNode[Interval]:
result = $ s.SNode[:Interval].val
# many more of those
proc dump(s: SNodeAny, depth: int = 0) =
var l = repeat(" ", depth)
l.add s.id
if s of SNodeParam:
l.add "=" & $ s
echo l
if s of SNodeGroup:
for c in s.SNodeGroup.children.items:
dump(c, depth+1)
var s = newSNodeGroup("system", [
newSNodeGroup("identification", [
newSNode("name", "device 123"),
newSNode("location", "rack J2"),
newSNode("weight", 42.1),
newSNode("enabled", true),
newSNode("address", IPv4Address("10.0.0.3")),
])
])
s.dump
Run