diff --git a/examples/simple_example.rs b/examples/simple_example.rs index fc453ff..dbd0ca1 100644 --- a/examples/simple_example.rs +++ b/examples/simple_example.rs @@ -17,5 +17,9 @@ fn App(cx: &Arc) -> View { #[component] fn MyComponent(cx: &Arc, children: &Rsx) -> View { - children.view(&cx) + rsx! { + "Simple" + @{children} + } + .view(&cx) } diff --git a/macros/src/emit.rs b/macros/src/emit.rs index 96a277f..6595c93 100644 --- a/macros/src/emit.rs +++ b/macros/src/emit.rs @@ -118,6 +118,10 @@ fn emit_node_scope(node: &RsxNode) -> TokenStream { } } } + + RsxNode::Expr(expr) => quote! { + r.child(#expr); + }, } } @@ -169,5 +173,9 @@ fn emit_node(node: &RsxNode) -> TokenStream { RsxNode::If { .. } => panic!("Invalid if statement"), RsxNode::For { .. } => panic!("Invalid for loop"), + + RsxNode::Expr(expr) => quote! { + r.child(#expr); + }, } } diff --git a/macros/src/parse.rs b/macros/src/parse.rs index ec49e72..29a8d9a 100644 --- a/macros/src/parse.rs +++ b/macros/src/parse.rs @@ -27,7 +27,7 @@ pub struct RsxProp { pub enum RsxNode { Text(LitStr), - /// Component with optional props and children: `Path { prop: expr, "child", ... }` or bare `Path`. + Expr(Expr), Component { path: Path, props: Vec, @@ -82,6 +82,18 @@ fn parse_deps(input: ParseStream) -> Result> { impl Parse for RsxNode { fn parse(input: ParseStream) -> Result { + // --- @{ expr } --- + if input.peek(Token![@]) { + input.parse::()?; + + let content; + braced!(content in input); + + let expr: Expr = content.parse()?; + return Ok(RsxNode::Expr(expr)); + } + + // --- existing code --- if input.peek(Token![!]) { input.parse::()?; let mount: Ident = input.parse()?; @@ -93,10 +105,8 @@ impl Parse for RsxNode { if input.peek(Token![if]) { input.parse::()?; let cond: Expr = input.parse()?; - let content; braced!(content in input); - let children = parse_children(&content)?; return Ok(RsxNode::If { deps, @@ -107,14 +117,11 @@ impl Parse for RsxNode { if input.peek(Token![for]) { input.parse::()?; - // Parse a possibly multi-pattern (e.g. with `|`) for the `for` binding. let pat: Pat = Pat::parse_multi(input)?; input.parse::()?; let expr: Expr = input.parse()?; - let content; braced!(content in input); - let children = parse_children(&content)?; return Ok(RsxNode::For { deps, @@ -128,7 +135,6 @@ impl Parse for RsxNode { return Ok(RsxNode::Text(input.parse()?)); } - // Component: Path or Path { props, children } parse_component_invocation(input) } } diff --git a/src/frontend.rs b/src/frontend.rs index 11a10f2..23c2124 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -6,15 +6,21 @@ use crate::{ View, }; +pub trait ToRsx { + fn to_rsx(&self) -> Rsx; +} + +#[derive(Clone)] pub enum RsxScope { - Static(Box) + Send + Sync>), + Static(Arc) + Send + Sync>), Dynamic( Arc) + Send + Sync>, - Vec>, + Vec>, ), Child(Rsx), } +#[derive(Clone)] pub struct Rsx(Vec); impl Rsx { @@ -23,18 +29,22 @@ impl Rsx { } pub fn static_scope) + Send + Sync + 'static>(&mut self, scope: F) { - self.0.push(RsxScope::Static(Box::new(scope))); + self.0.push(RsxScope::Static(Arc::new(scope))); } pub fn dynamic_scope) + Send + Sync + 'static>( &mut self, drawer: F, - dependencies: Vec>, + dependencies: Vec>, ) { self.0 .push(RsxScope::Dynamic(Arc::new(drawer), dependencies)); } + pub fn child(&mut self, child: R) { + self.0.push(RsxScope::Child(child.to_rsx())); + } + pub fn generate_children(&self, context: &Arc) { let executor = context.get_executor(); @@ -69,3 +79,9 @@ impl Rsx { }) } } + +impl ToRsx for &Rsx { + fn to_rsx(&self) -> Rsx { + Rsx(self.0.clone()) + } +}