diff options
Diffstat (limited to 'modules/morgana_proc/src/lib.rs')
-rw-r--r-- | modules/morgana_proc/src/lib.rs | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/modules/morgana_proc/src/lib.rs b/modules/morgana_proc/src/lib.rs index 8061b1b..7730f6b 100644 --- a/modules/morgana_proc/src/lib.rs +++ b/modules/morgana_proc/src/lib.rs @@ -4,7 +4,9 @@ use unsynn::*; use quote::quote; unsynn! { - struct MorxBlock(Vec<Either<MorxNode, MorxChild, Literal>>); + keyword MorxDocKey = "doctype"; + struct MorxBlock(Vec<Either<MorxDoctype, MorxNode, MorxChild, Literal>>); + struct MorxDoctype(Cons<PunctAny<'!'>, MorxDocKey, Vec<Either<Ident, LiteralString>>, NodeSeparator>); struct MorxNode(Cons<Ident, Either< NodeSeparator, MorxChildren, @@ -27,7 +29,7 @@ pub fn morx(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let child_vec_expr = generate_block(&ast); quote! { - RenderNode::Fragment { + ::morgana::RenderNode::Fragment { children: #child_vec_expr } }.into() @@ -36,10 +38,10 @@ pub fn morx(input: proc_macro::TokenStream) -> proc_macro::TokenStream { fn generate_block(ast: &MorxBlock) -> unsynn::TokenStream { let children: Vec<unsynn::TokenStream> = ast.0.iter().map(|child| { match child { - Either::First(node) => generate_node(node), - Either::Second(child_expression) => generate_expr_node(&child_expression.0.second), - Either::Third(literal) => generate_literal(literal), - _ => unreachable!("Invalid morx block AST"), + Either::First(doctype) => generate_doctype(doctype), + Either::Second(node) => generate_node(node), + Either::Third(child_expression) => generate_expr_node(&child_expression.0.second), + Either::Fourth(literal) => generate_literal(literal), } }).collect(); @@ -50,6 +52,28 @@ fn generate_block(ast: &MorxBlock) -> unsynn::TokenStream { }.into() } +fn generate_doctype(ast: &MorxDoctype) -> unsynn::TokenStream { + let elem_expressions: Vec<unsynn::TokenStream> = ast.0.third.iter().map(|elem| { + match elem { + Either::First(ident) => { + let ident_string = Literal::string(&ident.to_string()).into_token_stream(); + quote! {::morgana::DoctypeElem::Word( #ident_string )} + }, + Either::Second(literal) => { + let literal = literal.clone().into_token_stream(); + quote! {::morgana::DoctypeElem::String( #literal )} + }, + _ => unreachable!("Invalid doctype AST"), + } + }).collect(); + + quote! { + ::morgana::RenderNode::Doctype(vec![ + #(#elem_expressions),* + ]) + } +} + fn generate_node(ast: &MorxNode) -> unsynn::TokenStream { let elem_name = &ast.0.first; let attrs_or_props = match &ast.0.second { @@ -72,7 +96,10 @@ fn generate_node(ast: &MorxNode) -> unsynn::TokenStream { let value = match &attr.1 { Some(Either::First(literal)) => quote!{ format!("{}", #literal) }, Some(Either::Second(ident)) => quote!{ format!("{}", #ident) }, - Some(Either::Third(bracegroup)) => bracegroup.0.stream(), + Some(Either::Third(bracegroup)) => { + let inner = bracegroup.0.stream(); + quote!{ {#inner}.into() } + }, Some(Either::Fourth(_invalid)) => unreachable!("Invalid element attribute type"), None => quote!{ String::new() }, }; @@ -83,9 +110,12 @@ fn generate_node(ast: &MorxNode) -> unsynn::TokenStream { let elem_props = attrs_or_props.iter().map(|attr| { let name = &attr.0; let value = match &attr.1 { - Some(Either::First(literal)) => quote!{ format!("{}", #literal) }, - Some(Either::Second(ident)) => quote!{ #ident }, - Some(Either::Third(bracegroup)) => bracegroup.0.stream(), + Some(Either::First(literal)) => quote!{ {String::from(#literal).into()} }, + Some(Either::Second(ident)) => quote!{ {String::from(#ident).into()} }, + Some(Either::Third(bracegroup)) => { + let inner = bracegroup.0.stream(); + quote!{ {#inner}.into() } + }, Some(Either::Fourth(_invalid)) => unreachable!("Invalid element attribute type"), None => quote!{ true }, }; @@ -107,17 +137,17 @@ fn generate_node(ast: &MorxNode) -> unsynn::TokenStream { if is_component_node { quote! { - RenderNode::Component( + ::morgana::RenderNode::Component( Box::new({ #elem_name { + children: #children, #(#elem_props),* - children: #children } }) ) }.into() } else { let elem_name = Literal::string(&elem_name.to_string()).into_token_stream(); quote! { - RenderNode::Element { + ::morgana::RenderNode::Element { name: #elem_name.to_string(), children: #children, attributes: std::collections::HashMap::from([#(#elem_attrs),*]) @@ -133,7 +163,9 @@ fn generate_expr_node(ast: &Either<Literal, BraceGroup, EndOfStream>) -> unsynn: Either::Second(brace_expr) => { let children = brace_expr.0.stream(); quote! { - RenderNode::Fragment { children: #children } + ::morgana::RenderNode::Fragment { + children: ::morgana::IntoRender::into_render(#children) + } } }, _ => unreachable!("Invalid expr node"), @@ -142,6 +174,6 @@ fn generate_expr_node(ast: &Either<Literal, BraceGroup, EndOfStream>) -> unsynn: fn generate_literal(ast: &Literal) -> unsynn::TokenStream { quote! { - RenderNode::TextNode { content: format!("{}", #ast) } + ::morgana::RenderNode::TextNode { content: format!("{}", #ast) } } } |