diff --git a/packages/core-macro/src/rsxt.rs b/packages/core-macro/src/rsxt.rs index 4c9a7e8d5..f8ee16aca 100644 --- a/packages/core-macro/src/rsxt.rs +++ b/packages/core-macro/src/rsxt.rs @@ -84,7 +84,7 @@ impl Parse for RsxRender { impl ToTokens for RsxRender { fn to_tokens(&self, out_tokens: &mut TokenStream2) { - let new_toks = ToToksCtx::new(&self.el).to_token_stream(); + let new_toks = (&self.el).to_token_stream(); // let new_toks = ToToksCtx::new(&self.kind).to_token_stream(); // create a lazy tree that accepts a bump allocator @@ -114,14 +114,16 @@ enum Node { Element(Element), Text(TextNode), Component(Component), + RawExpr(Expr), } -impl ToTokens for ToToksCtx<&Node> { +impl ToTokens for &Node { fn to_tokens(&self, tokens: &mut TokenStream2) { - match &self.inner { - Node::Element(el) => self.recurse(el).to_tokens(tokens), - Node::Text(txt) => self.recurse(txt).to_tokens(tokens), - Node::Component(c) => self.recurse(c).to_tokens(tokens), + match &self { + Node::Element(el) => el.to_tokens(tokens), + Node::Text(txt) => txt.to_tokens(tokens), + Node::Component(c) => c.to_tokens(tokens), + Node::RawExpr(exp) => exp.to_tokens(tokens), } } } @@ -130,6 +132,7 @@ impl Parse for Node { fn parse(stream: ParseStream) -> Result { let fork1 = stream.fork(); let fork2 = stream.fork(); + let fork3 = stream.fork(); // todo: map issues onto the second fork if any arise // it's unlikely that textnodes or components would fail? @@ -140,7 +143,8 @@ impl Parse for Node { } else if let Ok(element) = fork2.parse::() { stream.advance_to(&fork2); Self::Element(element) - } else if let Ok(comp) = stream.parse::() { + } else if let Ok(comp) = fork3.parse::() { + stream.advance_to(&fork3); Self::Component(comp) } else { return Err(Error::new( @@ -162,24 +166,18 @@ struct Component { name: Ident, body: Vec, // attrs: Vec, - children: MaybeExpr>, + children: Vec, } -impl ToTokens for ToToksCtx<&Component> { +impl ToTokens for &Component { fn to_tokens(&self, tokens: &mut TokenStream2) { - let name = &self.inner.name; - - // let mut toks = quote! {}; - - // for attr in self.inner.attrs.iter() { - // self.recurse(attr).to_tokens(&mut toks); - // } + let name = &self.name; let mut builder = quote! { fc_to_builder(#name) }; - for field in &self.inner.body { + for field in &self.body { builder.append_all(quote! {#field}); } @@ -187,6 +185,12 @@ impl ToTokens for ToToksCtx<&Component> { .build() }); + // let mut toks = quote! {}; + + // for attr in self.inner.attrs.iter() { + // self.recurse(attr).to_tokens(&mut toks); + // } + // panic!("tokens are {:#?}", toks); // no children right now @@ -239,8 +243,6 @@ impl Parse for Component { let mut body: Vec = Vec::new(); let _children: Vec = Vec::new(); - // parse_element_content(content, &mut attrs, &mut children); - 'parsing: loop { // [1] Break if empty if content.is_empty() { @@ -252,19 +254,13 @@ impl Parse for Component { } } - // let body = content.parse()?; - - // eventually we'll parse the attrs - // let mut attrs: Vec = vec![]; + // todo: add support for children let children: Vec = vec![]; - // parse_element_content(content, &mut attrs, &mut children); - - let children = MaybeExpr::Literal(children); + // let children = MaybeExpr::Literal(children); Ok(Self { name, body, - // attrs, children, }) } @@ -307,45 +303,64 @@ impl ToTokens for &ComponentField { // ======================================= // Parse the VNode::Element type // ======================================= -// - [ ] Allow VComponent -// -// struct Element { name: Ident, attrs: Vec, - children: MaybeExpr>, + children: Vec, + // children: MaybeExpr>, } -impl ToTokens for ToToksCtx<&Element> { +impl ToTokens for &Element { fn to_tokens(&self, tokens: &mut TokenStream2) { - let name = &self.inner.name.to_string(); + let name = &self.name.to_string(); tokens.append_all(quote! { dioxus::builder::ElementBuilder::new(ctx, #name) }); - for attr in self.inner.attrs.iter() { - self.recurse(attr).to_tokens(tokens); + for attr in self.attrs.iter() { + attr.to_tokens(tokens); } - match &self.inner.children { - MaybeExpr::Expr(expr) => tokens.append_all(quote! { - .iter_child(#expr) - }), - MaybeExpr::Literal(nodes) => { - let mut children = nodes.iter(); - if let Some(child) = children.next() { - let mut inner_toks = TokenStream2::new(); - self.recurse(child).to_tokens(&mut inner_toks); - while let Some(child) = children.next() { - quote!(,).to_tokens(&mut inner_toks); - self.recurse(child).to_tokens(&mut inner_toks); - } + // match &self.children { + // // MaybeExpr::Expr(expr) => tokens.append_all(quote! { + // // .iter_child(#expr) + // // }), + // MaybeExpr::Literal(nodes) => { + // let mut children = nodes.iter(); + let mut children = self.children.iter(); + while let Some(child) = children.next() { + // if let Some(child) = children.next() { + // let mut inner_toks = TokenStream2::new(); + // child.to_tokens(&mut inner_toks); + // while let Some(child) = children.next() { + match child { + // raw exprs need to be wrapped in a once type? + Node::RawExpr(_) => { + let inner_toks = child.to_token_stream(); tokens.append_all(quote! { - .children([#inner_toks]) - }); + .iter_child(std::iter::once(#inner_toks)) + }) + } + _ => { + let inner_toks = child.to_token_stream(); + tokens.append_all(quote! { + .iter_child(#inner_toks) + }) } } + // quote!(,).to_tokens(&mut inner_toks); + // child.to_tokens(&mut inner_toks); + // } + // while let Some(child) = children.next() { + // quote!(,).to_tokens(&mut inner_toks); + // child.to_tokens(&mut inner_toks); + // } + // tokens.append_all(quote! { + // .iter_child([#inner_toks]) + // }); } + // } + // } tokens.append_all(quote! { .finish() }); @@ -354,8 +369,6 @@ impl ToTokens for ToToksCtx<&Element> { impl Parse for Element { fn parse(s: ParseStream) -> Result { - // TODO: reject anything weird/nonstandard - // we want names *only* let name = Ident::parse_any(s)?; if !crate::util::is_valid_tag(&name.to_string()) { @@ -370,7 +383,7 @@ impl Parse for Element { let mut children: Vec = vec![]; parse_element_content(content, &mut attrs, &mut children)?; - let children = MaybeExpr::Literal(children); + // let children = MaybeExpr::Literal(children); Ok(Self { name, @@ -402,7 +415,7 @@ fn parse_element_content( // [2] Try to consume an attr let fork = stream.fork(); if let Ok(attr) = fork.parse::() { - // make sure to advance or your computer will become a spaceheater :) + // make sure to advance or your computer will become a space heater :) stream.advance_to(&fork); attrs.push(attr); continue 'parsing; @@ -411,7 +424,7 @@ fn parse_element_content( // [3] Try to consume a child node let fork = stream.fork(); if let Ok(node) = fork.parse::() { - // make sure to advance or your computer will become a spaceheater :) + // make sure to advance or your computer will become a space heater :) stream.advance_to(&fork); children.push(node); continue 'parsing; @@ -419,10 +432,22 @@ fn parse_element_content( // [4] TODO: Parsing brackets - if stream.peek(token::Brace) { + let fork = stream.fork(); + if fork.peek(token::Brace) { + // todo!("Add support"); // this can fail (mismatched brackets) - let content; - syn::braced!(content in &stream); + // let content; + // syn::braced!(content in &stream); + match try_parse_bracketed(&fork) { + Ok(tok) => { + children.push(Node::RawExpr(tok)) + // todo!("succeeded") + } + Err(e) => { + todo!("failed {}", e) + } + } + stream.advance_to(&fork); continue 'parsing; // let fork = content.fork(); // stream.advance_to(fork) @@ -437,6 +462,11 @@ fn parse_element_content( } Ok(()) } +fn try_parse_bracketed(stream: &ParseBuffer) -> Result { + let content; + syn::braced!(content in stream); + content.parse() +} /// ======================================= /// Parse a VElement's Attributes @@ -491,7 +521,7 @@ impl Parse for Attr { // MaybeExpr::Literal(LitStr::new(&styles.to_string(), Span::call_site())) // } else { // just parse as an expression - MaybeExpr::Expr(outer.parse()?) + outer.parse()? // } } else { s.parse()? @@ -509,14 +539,14 @@ impl Parse for Attr { } } -impl ToTokens for ToToksCtx<&Attr> { +impl ToTokens for &Attr { + // impl ToTokens for ToToksCtx<&Attr> { fn to_tokens(&self, tokens: &mut TokenStream2) { - let name = self.inner.name.to_string(); - let nameident = &self.inner.name; + let name = self.name.to_string(); + let nameident = &self.name; let _attr_stream = TokenStream2::new(); - match &self.inner.ty { + match &self.ty { AttrType::Value(value) => { - let value = self.recurse(value); tokens.append_all(quote! { .attr(#name, #value) }); @@ -538,7 +568,7 @@ impl ToTokens for ToToksCtx<&Attr> { } enum AttrType { - Value(MaybeExpr), + Value(LitStr), Event(ExprClosure), Tok(Expr), // todo Bool(MaybeExpr) @@ -550,7 +580,8 @@ enum AttrType { // - [ ] Perform formatting automatically // // -struct TextNode(MaybeExpr); +struct TextNode(LitStr); +// struct TextNode(MaybeExpr); impl Parse for TextNode { fn parse(s: ParseStream) -> Result { @@ -558,10 +589,11 @@ impl Parse for TextNode { } } -impl ToTokens for ToToksCtx<&TextNode> { +impl ToTokens for TextNode { + // impl ToTokens for ToToksCtx<&TextNode> { + // self.recurse(&self.inner.0).to_tokens(&mut token_stream); fn to_tokens(&self, tokens: &mut TokenStream2) { - let mut token_stream = TokenStream2::new(); - self.recurse(&self.inner.0).to_tokens(&mut token_stream); + let token_stream = &self.0.to_token_stream(); tokens.append_all(quote! { { use bumpalo::core_alloc::fmt::Write; @@ -573,53 +605,28 @@ impl ToTokens for ToToksCtx<&TextNode> { } } -enum MaybeExpr { - Literal(T), - Expr(Expr), -} +// enum MaybeExpr { +// Literal(T), +// Expr(Expr), +// } -impl Parse for MaybeExpr { - fn parse(s: ParseStream) -> Result { - if s.peek(token::Brace) { - let content; - syn::braced!(content in s); - Ok(MaybeExpr::Expr(content.parse()?)) - } else { - Ok(MaybeExpr::Literal(s.parse()?)) - } - } -} +// impl Parse for MaybeExpr { +// fn parse(s: ParseStream) -> Result { +// if s.peek(token::Brace) { +// let content; +// syn::braced!(content in s); +// Ok(MaybeExpr::Expr(content.parse()?)) +// } else { +// Ok(MaybeExpr::Literal(s.parse()?)) +// } +// } +// } -impl<'a, T> ToTokens for ToToksCtx<&'a MaybeExpr> -where - T: 'a, - ToToksCtx<&'a T>: ToTokens, -{ - fn to_tokens(&self, tokens: &mut TokenStream2) { - match &self.inner { - MaybeExpr::Literal(v) => self.recurse(v).to_tokens(tokens), - MaybeExpr::Expr(expr) => expr.to_tokens(tokens), - } - } -} - -/// ToTokens context -struct ToToksCtx { - inner: T, -} - -impl<'a, T> ToToksCtx { - fn new(inner: T) -> Self { - ToToksCtx { inner } - } - - fn recurse(&self, inner: U) -> ToToksCtx { - ToToksCtx { inner } - } -} - -impl ToTokens for ToToksCtx<&LitStr> { - fn to_tokens(&self, tokens: &mut TokenStream2) { - self.inner.to_tokens(tokens) - } -} +// impl<'a, T: 'a + ToTokens> ToTokens for &'a MaybeExpr { +// fn to_tokens(&self, tokens: &mut TokenStream2) { +// match &self { +// MaybeExpr::Literal(v) => v.to_tokens(tokens), +// MaybeExpr::Expr(expr) => expr.to_tokens(tokens), +// } +// } +// } diff --git a/packages/core/src/nodebuilder.rs b/packages/core/src/nodebuilder.rs index 69483ec4f..d8db0f7fa 100644 --- a/packages/core/src/nodebuilder.rs +++ b/packages/core/src/nodebuilder.rs @@ -479,6 +479,19 @@ impl IntoIterator for DomTree { } } +impl<'a> IntoIterator for VNode<'a> { + type Item = VNode<'a>; + type IntoIter = std::iter::Once; + fn into_iter(self) -> Self::IntoIter { + std::iter::once(self) + } +} +impl<'a> IntoDomTree<'a> for VNode<'a> { + fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a> { + self + } +} + pub trait IntoDomTree<'a> { fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a>; } @@ -547,18 +560,17 @@ where fn test_iterator_of_nodes<'b>() { use crate::prelude::*; - static Example: FC<()> = |ctx, props| { - let g: LazyNodes<_> = rsx! { - div {} - }; + // static Example: FC<()> = |ctx, props| { + // let body = rsx! { + // div {} + // }; - ctx.render(rsx! { - div { - h1 {} - {} - } - }) - }; + // ctx.render(rsx! { + // div { + // h1 {} + // } + // }) + // }; // let p = (0..10).map(|f| { // // diff --git a/packages/docsite/src/main.rs b/packages/docsite/src/main.rs index b6863e76d..350bd5e2c 100644 --- a/packages/docsite/src/main.rs +++ b/packages/docsite/src/main.rs @@ -20,35 +20,28 @@ impl<'a, G> Blah for LazyNodes<'a, G> where G: for<'b> FnOnce(&'b NodeCtx<'a>) - static App: FC = |ctx, props| { // - let body = match props.route { - Routes::Homepage => ctx.render(rsx!( - div { - Homepage {} - } - )), - Routes::ExampleList => ctx.render(rsx!( - div { - ExampleList {} - } - )), + let body = rsx! { + div {} + }; + + let top = rsx! { + div {} }; ctx.render(rsx!( div { Header {} {body} - { - } - Footer {} + {top} + {rsx!{ + div { + "you ugl" + } + }} } )) }; -#[derive(Debug, PartialEq, Props)] -struct HeaderProp { - selected: Routes, -} - static Header: FC<()> = |ctx, _| { ctx.render(rsx! { div { @@ -56,27 +49,3 @@ static Header: FC<()> = |ctx, _| { } }) }; - -static Footer: FC<()> = |ctx, _| { - ctx.render(rsx! { - div { - - } - }) -}; - -static Homepage: FC<()> = |ctx, _| { - ctx.render(rsx! { - div { - - } - }) -}; - -static ExampleList: FC<()> = |ctx, _| { - ctx.render(rsx! { - div { - - } - }) -};