alice_lol_macro/lib.rs
1//! ALICE-LOL `proc_macro`: LOL DSL → `SdfNode` construction code
2//!
3//! # Syntax (v0.5)
4//!
5//! ```ignore
6//! lol! {
7//! field SceneName {
8//! smooth_union(0.2,
9//! sphere(1.0),
10//! translate(2.0, 0.0, 0.0,
11//! box3d(0.5, 0.5, 0.5)
12//! )
13//! )
14//! }
15//! }
16//! ```
17//!
18//! Also supports bare expressions without the `field` wrapper:
19//! ```ignore
20//! lol! { sphere(1.0) }
21//! ```
22//!
23//! Runtime variable capture with `{expr}` in numeric positions:
24//! ```ignore
25//! let r = 1.5_f32;
26//! lol! { sphere({r}) }
27//! lol! { translate({x}, {y}, 0.0, sphere({r * 2.0})) }
28//! ```
29//!
30//! # Module 構成 (private)
31//!
32//! - `ast` — LOL Internal AST (`Expr` enum + variants)
33//! - `parser` — Parser (LOL DSL → `Expr` AST)
34//! - `codegen` — Codegen (`Expr` → Rust `TokenStream`)
35//!
36//! `proc_macro` crate は 1 entry point (`lol!`) のみ export、
37//! backward compat 用の re-export は不要 (macro invocation は変わらない)
38
39#![allow(
40 clippy::wildcard_imports,
41 clippy::type_complexity,
42 clippy::many_single_char_names
43)]
44
45mod ast;
46mod codegen;
47mod parser;
48
49use crate::codegen::codegen;
50use crate::parser::LolInput;
51use proc_macro::TokenStream;
52
53/// LOL (Law-Oriented Language) `proc_macro`.
54///
55/// Parses LOL DSL and generates Rust code that constructs an `SdfNode` tree.
56///
57/// # Usage
58///
59/// ```ignore
60/// use alice_lol::lol;
61///
62/// // With field wrapper
63/// let node = lol! {
64/// field MyScene {
65/// smooth_union(0.2,
66/// sphere(1.0),
67/// translate(2.0, 0.0, 0.0, box3d(0.5, 0.5, 0.5))
68/// )
69/// }
70/// };
71///
72/// // Bare expression
73/// let node = lol! { sphere(1.0) };
74///
75/// // Variable capture with {expr}
76/// let r = 1.5_f32;
77/// let node = lol! { sphere({r}) };
78/// let node = lol! { translate({x}, {y}, 0.0, sphere({r * 2.0})) };
79/// ```
80#[proc_macro]
81pub fn lol(input: TokenStream) -> TokenStream {
82 let scene = syn::parse_macro_input!(input as LolInput);
83 let node_code = codegen(&scene.body);
84 node_code.into()
85}