I'm working on component system for Karax as part of my Sauer tool.
One of the things I want to standardize are container components: the kind of components that have content in them. Like a panel or a layout.
My approach is that a component exposes a render template that accepts a code block and produces a VNode. Like this:
template render*(panel: Panel, body: untyped): untyped =
buildHtml:
tdiv(style = panel.style):
body
This works with a single component but fails to compile if I use another component in it.
I've created a minimal code example to demonstrate it. This fails:
import karax/[karax, karaxdsl, vdom]
template foo(body: untyped): untyped =
buildHtml:
tdiv:
h1: text "foo"
body
template bar(b: string, body: untyped): untyped =
buildHtml:
tdiv:
h1: text "bar"
body
proc render*: VNode =
buildHtml:
foo:
bar:
p: text "Spam"
setRenderer(render)
This works:
proc render*: VNode =
buildHtml:
foo: #or bar:
p: text "Spam"
Is this expected behavior? Am I doing something wrong?
Well for one the signature of bar in your example is (string, untyped) and you are only giving the untyped parameter.
But beyond that this really depends on the DSL at hand. For macros that take untyped parameters (seemingly like buildHtml) template evaluation will not necessarily be done inside the AST of the parameters. Since I don't know about karax I can't say for certain this is happening, but if this is the case, you have a few options:
template foo(body: untyped): untyped {.component.} =
buildHtml:
tdiv:
h1: text "foo"
body
template bar(b: string, body: untyped): untyped {.component.} =
buildHtml:
tdiv:
h1: text "bar"
body
proc render*: VNode =
buildHtmlCustomComponents:
foo:
bar:
p: text "Spam"
# becomes
proc render*: VNode =
macro temp(): untyped =
let tmp1 = quote do:
p:
text "Spam"
let tmp2 = getAst(bar(tmp1))
let tmp3 = getAst(foo(tmp2))
result = quote do:
buildHtml:
`tmp3`
tmp()
Well for one the signature of bar in your example is (string, untyped) and you are only giving the untyped parameter.
That's a typo, sorry.
But beyond that this really depends on the DSL at hand.
Thanks for the detailed response!