Skip to main content

tensorism_gen/
lib.rs

1//! Macro for handling arrays with multiple indexes.
2//!
3//! This crate should not be used directly. Instead, use the `tensorism` crate.
4//! It re-exports the items defined here and provides additional functionality.
5extern crate proc_macro;
6#[macro_use]
7extern crate quote;
8
9use proc_macro2::{Literal, TokenStream, TokenTree};
10
11mod analysis;
12mod model;
13mod production;
14mod unification;
15
16use quote::ToTokens;
17
18use crate::analysis::{inspection::inspect, top_group};
19
20fn simplify(text: &str) -> String {
21    let mut result = String::new();
22    text.split('\n').map(|s| s.trim()).for_each(|s| {
23        result.push_str(s);
24        result.push(' ')
25    });
26    result
27}
28
29/// Macro that generate a new `ndarray::Array` by evaluating a special domain-specific language used for its argument.
30/// See the `tensorism` crate for documentation and examples.
31#[proc_macro]
32pub fn new_ndarray(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
33    match syn::parse2::<crate::model::lambda::RicciGroup>(input.into()) {
34        Err(error) => {
35            let message = format!("Failed to parse input: {}", error);
36            quote! { compile_error!(#message) }.into()
37        }
38        Ok(group) => match inspect(group) {
39            Err(error) => {
40                let message = format!("Index issues: {}", error);
41                quote! { compile_error!(#message) }.into()
42            }
43            Ok((top_group, mapping)) => production::produce(top_group, mapping).into(),
44        },
45    }
46}
47
48#[doc(hidden)]
49#[proc_macro]
50pub fn format_new_ndarray(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
51    match syn::parse2::<crate::model::lambda::RicciGroup>(input.into()) {
52        Err(error) => {
53            let message = format!("Failed to parse input: {}", error);
54            quote! { compile_error!(#message) }.into()
55        }
56        Ok(group) => match inspect(group) {
57            Err(error) => {
58                let message = format!("Index issues: {}", error);
59                quote! { compile_error!(#message) }.into()
60            }
61            Ok((top_group, mapping)) => {
62                let output = production::produce(top_group, mapping);
63                let string = simplify(&output.to_string());
64                let mut output = TokenStream::new();
65                TokenTree::Literal(Literal::string(string.as_str())).to_tokens(&mut output);
66                output.into()
67            }
68        },
69    }
70}