Removed most of variant-object specific code

* fieldPairs() already handles variant objects fine. decided not to
   go further along the way of identifying object variants by their
   discriminants in tag URIs.
 * variant objects are now supported just like normal objects.
This commit is contained in:
Felix Krause 2016-06-05 15:43:39 +02:00
parent a0c435d6eb
commit e81da97a17
3 changed files with 26 additions and 86 deletions

View File

@ -387,16 +387,22 @@ proc representObject*[K, V](value: OrderedTable[K, V], ts: TagStyle,
yield endMapEvent() yield endMapEvent()
yield endSeqEvent() yield endSeqEvent()
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
proc yamlTag*(T: typedesc[object|enum]): proc yamlTag*(T: typedesc[object|enum]):
TagId {.inline, noSideEffect, raises: [].} = TagId {.inline, raises: [].} =
when compiles(yamlTag(T)): result = yamlTag(T)
else:
var uri = "!nim:custom:" & (typetraits.name(type(T))) var uri = "!nim:custom:" & (typetraits.name(type(T)))
try: serializationTagLibrary.tags[uri] try: serializationTagLibrary.tags[uri]
except KeyError: serializationTagLibrary.registerUri(uri) except KeyError: serializationTagLibrary.registerUri(uri)
proc yamlTag*(T: typedesc[tuple]): proc yamlTag*(T: typedesc[tuple]):
TagId {.inline, noSideEffect, raises: [].} = TagId {.inline, raises: [].} =
var var
i: T i: T
uri = "!nim:tuple(" uri = "!nim:tuple("
@ -423,6 +429,9 @@ proc constructObject*[O: object|tuple](
raise newException(YamlConstructionError, raise newException(YamlConstructionError,
"Expected field name, got " & $e.kind) "Expected field name, got " & $e.kind)
let name = e.scalarContent let name = e.scalarContent
when compiles(implicitVariantObject(O)):
discard
else:
for fname, value in fieldPairs(result): for fname, value in fieldPairs(result):
if fname == name: if fname == name:
constructChild(s, c, value) constructChild(s, c, value)
@ -625,6 +634,11 @@ proc representChild*[O](value: ref O, ts: TagStyle, c: SerializationContext):
yield event yield event
except KeyError: assert false, "Can never happen" except KeyError: assert false, "Can never happen"
proc representChild*[O](value: O, ts: TagStyle,
c: SerializationContext): RawYamlStream =
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) =
var context = newConstructionContext() var context = newConstructionContext()
try: try:

View File

@ -1,27 +0,0 @@
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

@ -624,57 +624,10 @@ proc representChild*(value: string, ts: TagStyle, c: SerializationContext):
RawYamlStream {.inline.} RawYamlStream {.inline.}
## Represents a Nim string. Supports nil strings. ## 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, proc representChild*[O](value: O, ts: TagStyle,
c: SerializationContext): c: SerializationContext):
RawYamlStream {.raises: [].} = 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].}