Worked on variant objects (not working)

This commit is contained in:
Felix Krause 2016-05-09 19:03:11 +02:00
parent 273093e390
commit f73dfdc6ab
3 changed files with 81 additions and 6 deletions

View File

@ -385,7 +385,7 @@ proc representObject*[K, V](value: OrderedTable[K, V], ts: TagStyle,
yield endSeqEvent() yield endSeqEvent()
template yamlTag*(T: typedesc[object|enum]): expr = template yamlTag*(T: typedesc[object|enum]): expr =
var uri = when compiles(yamlTagId(T)): yamlTagId(T) else: var uri = when compiles(yamlTag(T)): yamlTag(T) else:
"!nim:custom:" & (typetraits.name(type(T))) "!nim:custom:" & (typetraits.name(type(T)))
try: serializationTagLibrary.tags[uri] try: serializationTagLibrary.tags[uri]
except KeyError: serializationTagLibrary.registerUri(uri) except KeyError: serializationTagLibrary.registerUri(uri)
@ -554,10 +554,6 @@ proc constructChild*[O](s: var YamlStream, c: ConstructionContext,
e.parent = getCurrentException() e.parent = getCurrentException()
raise e raise e
proc representChild*[O](value: O, ts: TagStyle, c: SerializationContext):
RawYamlStream =
result = representObject(value, ts, c, presentTag(O, ts))
proc representChild*(value: string, ts: TagStyle, c: SerializationContext): proc representChild*(value: string, ts: TagStyle, c: SerializationContext):
RawYamlStream = RawYamlStream =
if isNil(value): if isNil(value):

27
test1.nim Normal file
View File

@ -0,0 +1,27 @@
import yaml, macros
type
FooKind = enum
fooInt, fooBool, fooNone
FooKind2 = enum
fooAddString, fooAddNone
Foo = object
a: string
case b: FooKind
of fooInt:
c: int32
of fooBool:
d: bool
of fooNone:
discard
case c2: FooKind2
of fooAddString:
e: string
of fooAddNone:
discard
var o = newFileStream(stdout)
var f = Foo(a: "a", b: fooBool, d: true)
dump(f, o)

View File

@ -602,9 +602,61 @@ proc representChild*[O](value: ref O, ts: TagStyle, c: SerializationContext):
## may be represented as alias node if it is already present in the ## may be represented as alias node if it is already present in the
## ``SerializationContext``. ## ``SerializationContext``.
proc representChild*[O](value: O, ts: TagStyle, c: SerializationContext): proc representChild*(value: string, ts: TagStyle, c: SerializationContext):
RawYamlStream {.inline.} RawYamlStream {.inline.}
## Represents a Nim string. Supports nil strings.
proc isVariant(t: typedesc): bool {.compileTime.} =
let typeDesc = getType(t)
if typeDesc.len > 1:
for child in typeDesc[1].children:
if child.kind == nnkRecCase:
return true
return false
macro presentTagDiscriminators(target: string, t: typedesc, val: expr): stmt =
var first = true
let typeDesc = getType(getType(t)[1])
for child in typeDesc[1].children:
if child.kind != nnkRecCase: continue
template discriminantToString(): NimNode =
newNimNode(nnkInfix).add(
newIdentNode("$"), newDotExpr(val, child[0])
)
if first:
first = false
result = newNimNode(nnkInfix).add(
newIdentNode("&"), newStrLitNode("("), discriminantToString()
)
else:
result = newNimNode(nnkInfix).add(
newIdentNode("&"), result, newNimNode(nnkInfix).add(
newIdentNode("&"), newStrLitNode(","), discriminantToString())
)
if first: # no discriminators
result = newNimNode(nnkDiscardStmt).add(newNimNode(nnkEmpty))
else:
result = newNimNode(nnkInfix).add(newIdentNode("&="), target,
newNimNode(nnkInfix).add(newIdentNode("&"), result, newStrLitNode(")")))
template presentVariantObjectTag[O](t: typedesc[object], val: O): TagId =
var oTag = name(t)
presentTagDiscriminators(oTag, t, val)
try: serializationTagLibrary.tags[oTag]
except KeyError: serializationTagLibrary.registerUri(oTag)
proc representChild*[O](value: O, ts: TagStyle,
c: SerializationContext):
RawYamlStream {.raises: [].} =
## Represents an arbitrary Nim object as YAML object. ## Represents an arbitrary Nim object as YAML object.
const isVar = isVariant(O)
when isVar:
result = representObject(value, ts, c, presentVariantObjectTag(O, value))
else:
result = representObject(value, ts, c, if ts == tsNone:
yTagQuestionMark else: yamlTag(O))
proc construct*[T](s: var YamlStream, target: var T) proc construct*[T](s: var YamlStream, target: var T)
{.raises: [YamlConstructionError, YamlStreamError].} {.raises: [YamlConstructionError, YamlStreamError].}