Open gabbhack opened 3 years ago
Hack:
import macros
template skipSerializeIf(condition: typed{`proc`}) {.pragma.}
proc alwaysTrue[T](x: T): bool = true
# also crush on
# proc alwaysTrue(x: any): bool = true
# proc alwaysTrue(x: auto): bool = true
# proc alwaysTrue(x: string | int): bool = true
template hack[T](x: T): T = x
type
Test = object
id {.skipSerializeIf(alwaysTrue).}: string
let t = Test()
echo t.id.getCustomPragmaVal(skipSerializeIf).type # proc (x: T): bool
echo hack(t.id.getCustomPragmaVal(skipSerializeIf)(t.id))
Error message could have been better but I don't think this would ever compile. alwaysTrue
proc instantiation needs to happen on skipSerializeIf
invocation but it is no possible at this stage and there is no mechanism to delay it.
Here is better design:
import macros
template skipSerializeIf(cond: bool) {.pragma.}
macro toString(x: untyped): string =
# used just to test
newLit(repr(x))
type
Test = object
id {.skipSerializeIf(true).}: string
id2 {.skipSerializeIf(toString(id2) == "id2").}: string
id3 {.skipSerializeIf(toString(id3) == "id2").}: string
let t = Test()
echo t.id.getCustomPragmaVal(skipSerializeIf).type
echo t.id.getCustomPragmaVal(skipSerializeIf)
echo t.id2.getCustomPragmaVal(skipSerializeIf).type
echo t.id2.getCustomPragmaVal(skipSerializeIf)
echo t.id3.getCustomPragmaVal(skipSerializeIf).type
echo t.id3.getCustomPragmaVal(skipSerializeIf)
@cooldome I may not understand you, but with your design I won't be able to work with values at runtime.
I need something like this:
import options
type
Foo = object
id: int
someOption {.skipSerializeIf(isNone).}: Option[string]
let f = Foo(id: 123)
# in ser isNone is called with the value of someOption field
assert ser(f) == """{"id": 123}"""
I can do this using the hack posted above.
Strange behavior, static does not crash and gives the wrong result
import macros
template skipSerializeIf(condition: typed{`proc`}) {.pragma.}
proc alwaysTrue[T](x: T): bool = true
# also crush on
# proc alwaysTrue(x: any): bool = true
# proc alwaysTrue(x: auto): bool = true
# proc alwaysTrue(x: string | int): bool = true
template hack[T](x: T): T = x
type
Test = object
id {.skipSerializeIf(alwaysTrue).}: string
const t = Test()
static:
echo t.id.getCustomPragmaVal(skipSerializeIf)(t.id) # false
echo hack(t.id.getCustomPragmaVal(skipSerializeIf)(t.id)) # true
Example
https://play.nim-lang.org/#ix=2Fdq
Current Output
Expected Output