Documented

This commit is contained in:
2026-01-31 18:21:46 +01:00
parent 0f5422b66b
commit 73cfc36277
14 changed files with 376 additions and 4 deletions
+9
View File
@@ -1,11 +1,17 @@
//! # RSX Emission
//!
//! Converts parsed RSX AST into Rust code that constructs RSX objects.
use crate::parse::*;
use proc_macro2::TokenStream;
use quote::quote;
/// Emits code for the root RSX
pub fn emit_rsx(root: RsxRoot) -> TokenStream {
emit_rsx_vec(&root.nodes)
}
/// Emits code for a vector of RSX nodes
pub fn emit_rsx_vec(nodes: &Vec<RsxNode>) -> TokenStream {
let nodes = nodes.iter().map(emit_node_scope);
@@ -16,6 +22,7 @@ pub fn emit_rsx_vec(nodes: &Vec<RsxNode>) -> TokenStream {
}}
}
/// Emits variable bindings for dependencies
fn emit_deps(deps: &[Dep]) -> TokenStream {
deps.iter()
.map(|d| {
@@ -29,6 +36,7 @@ fn emit_deps(deps: &[Dep]) -> TokenStream {
.collect()
}
/// Emits a Vec of dependencies as HookDependency trait objects
fn emit_deps_vec(deps: &[Dep]) -> TokenStream {
let deps = deps.iter().map(|d| {
let ident = &d.ident;
@@ -43,6 +51,7 @@ fn emit_deps_vec(deps: &[Dep]) -> TokenStream {
}
}
/// Emits code for a single node within a scope
fn emit_node_scope(node: &RsxNode) -> TokenStream {
match node {
RsxNode::Text(_) => {
+38
View File
@@ -1,3 +1,12 @@
//! # OSUI Macros
//!
//! Procedural macros for OSUI that provide ergonomic syntax for defining components.
//!
//! ## Features
//!
//! - `#[component]` - Transforms a function into a reusable component with props
//! - `rsx!` - Creates RSX (React-like Syntax) for component hierarchies
use proc_macro::TokenStream;
use quote::quote;
use syn::{FnArg, ItemFn, Pat, ReturnType, Type, parse_macro_input};
@@ -5,12 +14,41 @@ use syn::{FnArg, ItemFn, Pat, ReturnType, Type, parse_macro_input};
mod emit;
mod parse;
/// RSX (React-like Syntax) macro for building component hierarchies
///
/// # Example
///
/// ```rust,ignore
/// rsx! {
/// Component {
/// prop: value,
/// }
/// }
/// ```
#[proc_macro]
pub fn rsx(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as parse::RsxRoot);
emit::emit_rsx(ast).into()
}
/// Component attribute macro for defining reusable components
///
/// Transforms a function into a component with automatic prop handling.
/// The first parameter must be `cx: &Arc<Context>`.
/// Remaining parameters become component props.
///
/// # Example
///
/// ```rust,ignore
/// #[component]
/// pub fn Counter(cx: &Arc<Context>, initial: &i32) -> View {
/// let count = use_state(*initial);
///
/// Arc::new(move |ctx| {
/// ctx.draw_text(Point { x: 0, y: 0 }, &format!("Count: {}", count.get_dl()));
/// })
/// }
/// ```
#[proc_macro_attribute]
pub fn component(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as ItemFn);
+26 -1
View File
@@ -1,3 +1,7 @@
//! # RSX Parser
//!
//! Parses RSX syntax into an AST that can be emitted as Rust code.
use syn::braced;
use syn::parse::discouraged::Speculative;
use syn::{
@@ -6,7 +10,9 @@ use syn::{
token::Brace,
};
/// Root of an RSX expression
pub struct RsxRoot {
/// Top-level nodes in the RSX
pub nodes: Vec<RsxNode>,
}
@@ -20,30 +26,49 @@ impl Parse for RsxRoot {
}
}
/// A single prop: `ident: expr`.
/// A single component prop: `name: value`
pub struct RsxProp {
/// Property name
pub name: Ident,
/// Property value expression
pub value: Expr,
}
/// AST node representing different RSX constructs
pub enum RsxNode {
/// String literal: `"text"`
Text(LitStr),
/// Expression node: `{expr}`
Expr(Expr),
/// Component instantiation: `Component { prop: value, ... }`
Component {
/// Component path (e.g., `my_module::MyComponent`)
path: Path,
/// Component properties
props: Vec<RsxProp>,
/// Child nodes
children: Vec<RsxNode>,
},
/// Mount lifecycle: `@mount`
Mount(Ident),
/// Conditional rendering: `@if condition { ... }`
If {
/// Dependencies to track for reactivity
deps: Vec<Dep>,
/// Condition expression
cond: Expr,
/// Child nodes to render if true
children: Vec<RsxNode>,
},
/// Loop rendering: `@for pattern in expr { ... }`
For {
/// Dependencies to track for reactivity
deps: Vec<Dep>,
/// Loop pattern (e.g., `(key, value)`)
pat: Pat,
/// Iterable expression
expr: Expr,
/// Child nodes to render for each iteration
children: Vec<RsxNode>,
},
}