There are so many caveats, but the most simple adding function can now be automatically expressed in Rust!
OVEFU3K2T36H3EMYOIF6U7AYWMJIV5IJYRL56F3PWRCG7EGEZMQAC
GKBSBSDY5XLAT7SDKAVFQI3PHFUHKHTJGGXZH5XWG2E45U7BSU5QC
2N3KOCP74PCK2ETO5PCWBDR5PA57DDNT2KR4JLBPZPQPA56SAR4QC
CQEA2ZDITRMPXKCO5T346QH7JJOOGOPRC66F3MG6VEMEQGLYYUZAC
YKL5NCLHVHFQMBIWC6HW4NFPPYK5DR6XTCKJ5VBHNLVP2RO3H24AC
HEIF2O2ELHA3M7K77CK7AHBZ4656AUS3QW5M4E2DUY7ECOLVWKIAC
Q3IYM4WFHTO2IQLR2ZJ52FIE7U4RYIHQHXTPCK2HENSPVI7CPUZAC
I3NG5A4WXPELEOY3KFQKYBZVKA56VPGLI5R7O7TDCZTQAA7EROTQC
GYTRFADRDO4SYXV6V3PEPGGFIRDHQH5YBTKEJCWFAIZ5CX4P46NAC
BA5Y6VSEHJQBOYBS6R6FE6IZDRNAPNIN5ITJXWK7L46RJVHNI7JAC
BSJYWOYSJRERQ45AD7RN3364RYQ5P3IM76S67262VLFZPFO3B5JQC
ZRGSUUICJKNHKVH2JZHHOKSSIQXNWCNLJX2ICSX524AG2XJKD3VAC
use std::vec;
use syn::{punctuated::Punctuated, token, PathSegment};
use typst::syntax::ast::Params;
use crate::literal_string;
pub fn typst_scope_to_rust(scope: &typst::eval::Scope) -> syn::Item {
let functions = scope
.iter()
.map(|(name, value)| {
if let Ok(value) = value.clone().cast::<typst::eval::Func>() {
typst_func_to_rust(name.as_str(), value)
} else {
todo!()
}
})
.collect::<Vec<_>>();
syn::Item::Mod(syn::ItemMod {
attrs: Vec::new(),
vis: syn::Visibility::Public(token::Pub::default()),
unsafety: None,
mod_token: token::Mod::default(),
ident: syn::Ident::new("test", proc_macro2::Span::call_site()),
content: Some((token::Brace::default(), functions)),
semi: None,
})
}
fn typst_params_to_syn<'a>(params: Params<'a>) -> impl Iterator<Item = syn::FnArg> + 'a {
dbg!(params.children().collect::<Vec<_>>());
params.children().map(|child| {
if let typst::syntax::ast::Param::Pos(typst::syntax::ast::Pattern::Normal(
typst::syntax::ast::Expr::Ident(param),
)) = child
{
syn::FnArg::Typed(syn::PatType {
attrs: Vec::new(),
pat: Box::new(syn::Pat::Ident(syn::PatIdent {
attrs: Vec::new(),
by_ref: None,
mutability: None,
ident: syn::Ident::new(param.as_str(), proc_macro2::Span::call_site()),
subpat: None,
})),
colon_token: token::Colon::default(),
ty: Box::new(syn::Type::Path(syn::TypePath {
qself: None,
path: syn::Path {
leading_colon: None,
segments: Punctuated::from_iter(
vec![
syn::PathSegment {
ident: syn::Ident::new("typst", proc_macro2::Span::call_site()),
arguments: syn::PathArguments::None,
},
syn::PathSegment {
ident: syn::Ident::new("eval", proc_macro2::Span::call_site()),
arguments: syn::PathArguments::None,
},
syn::PathSegment {
ident: syn::Ident::new("Value", proc_macro2::Span::call_site()),
arguments: syn::PathArguments::None,
},
]
.into_iter(),
),
},
})),
})
} else {
dbg!(child);
todo!()
}
})
}
fn typst_op_to_syn(operation: typst::syntax::ast::BinOp) -> syn::BinOp {
match operation {
typst::syntax::ast::BinOp::Add => syn::BinOp::Add(token::Plus::default()),
_ => todo!(),
}
}
fn typst_expr_to_syn(expression: typst::syntax::ast::Expr) -> syn::Expr {
match expression {
typst::syntax::ast::Expr::Binary(binary) => syn::Expr::Call(syn::ExprCall {
attrs: Vec::new(),
func: Box::new(syn::Expr::Path(syn::ExprPath {
attrs: Vec::new(),
qself: None,
path: syn::Path {
leading_colon: None,
segments: Punctuated::from_iter(
vec![
syn::PathSegment {
ident: syn::Ident::new("typst", proc_macro2::Span::call_site()),
arguments: syn::PathArguments::None,
},
syn::PathSegment {
ident: syn::Ident::new("eval", proc_macro2::Span::call_site()),
arguments: syn::PathArguments::None,
},
syn::PathSegment {
ident: syn::Ident::new("ops", proc_macro2::Span::call_site()),
arguments: syn::PathArguments::None,
},
syn::PathSegment {
ident: syn::Ident::new(
match binary.op() {
typst::syntax::ast::BinOp::Add => "add",
_ => todo!(),
},
proc_macro2::Span::call_site(),
),
arguments: syn::PathArguments::None,
},
]
.into_iter(),
),
},
})),
paren_token: token::Paren::default(),
args: Punctuated::from_iter(
vec![
typst_expr_to_syn(binary.lhs()),
typst_expr_to_syn(binary.rhs()),
]
.into_iter(),
),
}),
// syn::Expr::Binary(syn::ExprBinary {
// attrs: Vec::new(),
// left: Box::new(typst_expr_to_syn(binary.lhs())),
// op: typst_op_to_syn(binary.op()),
// right: Box::new(typst_expr_to_syn(binary.rhs())),
// }),
typst::syntax::ast::Expr::Ident(ident) => syn::Expr::Path(syn::ExprPath {
attrs: Vec::new(),
qself: None,
path: syn::Path {
leading_colon: None,
segments: Punctuated::from_iter(
Some(syn::PathSegment {
ident: syn::Ident::new(ident.as_str(), proc_macro2::Span::call_site()),
arguments: syn::PathArguments::None,
})
.into_iter(),
),
},
}),
_ => {
dbg!(expression);
todo!()
}
}
}
pub fn typst_func_to_rust(name: &str, func: typst::eval::Func) -> syn::Item {
syn::Item::Fn(match func.repr {
typst::eval::FuncRepr::Closure(closure) => {
let closure_ast = closure.node.cast::<typst::syntax::ast::Closure>().unwrap();
dbg!(typst_params_to_syn(closure_ast.params()).collect::<Vec<_>>());
syn::ItemFn {
attrs: Vec::new(),
vis: syn::Visibility::Public(token::Pub::default()),
sig: syn::Signature {
constness: None,
asyncness: None,
unsafety: None,
abi: None,
fn_token: token::Fn::default(),
ident: syn::Ident::new(name, proc_macro2::Span::call_site()),
generics: syn::Generics::default(),
paren_token: token::Paren::default(),
inputs: Punctuated::from_iter(typst_params_to_syn(closure_ast.params())),
variadic: None,
output: syn::ReturnType::Type(
token::RArrow::default(),
Box::new(syn::Type::Path(syn::TypePath {
qself: None,
path: syn::Path {
leading_colon: None,
segments: Punctuated::from_iter(
vec![
syn::PathSegment {
ident: syn::Ident::new(
"typst",
proc_macro2::Span::call_site(),
),
arguments: syn::PathArguments::None,
},
syn::PathSegment {
ident: syn::Ident::new(
"diag",
proc_macro2::Span::call_site(),
),
arguments: syn::PathArguments::None,
},
syn::PathSegment {
ident: syn::Ident::new(
"StrResult",
proc_macro2::Span::call_site(),
),
arguments: syn::PathArguments::AngleBracketed(
syn::AngleBracketedGenericArguments {
colon2_token: None,
lt_token: token::Lt::default(),
args: Punctuated::from_iter(
Some(syn::GenericArgument::Type(
syn::Type::Path(syn::TypePath {
qself: None,
path: syn::Path {
leading_colon: None,
segments: Punctuated::from_iter(
vec![
syn::PathSegment {
ident: syn::Ident::new(
"typst",
proc_macro2::Span::call_site(),
),
arguments: syn::PathArguments::None,
},
syn::PathSegment {
ident: syn::Ident::new(
"eval",
proc_macro2::Span::call_site(),
),
arguments: syn::PathArguments::None,
},syn::PathSegment {
ident: syn::Ident::new(
"Value",
proc_macro2::Span::call_site(),
),
arguments: syn::PathArguments::None,
}].into_iter(),
),
},
}),
))
.into_iter(),
),
gt_token: token::Gt::default(),
},
),
},
]
.into_iter(),
),
},
})),
),
},
block: Box::new(syn::Block {
brace_token: token::Brace::default(),
stmts: vec![syn::Stmt::Expr(typst_expr_to_syn(closure_ast.body()), None)],
}),
}
}
_ => todo!(),
})
}
token, AngleBracketedGenericArguments, ExprLit, ExprTuple, GenericArgument,
GenericParam, Generics, Ident, Item, ItemFn, ItemMod, ItemUse, Lit, LitStr, PathArguments,
PathSegment, ReturnType, Signature, Stmt, TraitBound, TraitBoundModifier, TypeImplTrait,
TypeParam, TypeParamBound, TypePath, UseGroup, UseName, UsePath, UseTree, Visibility,
token, AngleBracketedGenericArguments, ExprLit, ExprTuple, GenericArgument, GenericParam,
Generics, Ident, Item, ItemFn, ItemMod, ItemUse, Lit, LitStr, PathArguments, PathSegment,
ReturnType, Signature, Stmt, TraitBound, TraitBoundModifier, TypeImplTrait, TypeParam,
TypeParamBound, TypePath, UseGroup, UseName, UsePath, UseTree, Visibility,
dbg!(typst_ast.scope(), typst_ast.clone().content());
let xilem_expressions = typst_to_xilem(typst_ast.content());
let function = xilem_to_function(&fs_path_to_module_ident(&file), xilem_expressions);
// let xilem_expressions = typst_to_xilem(typst_ast.content());
// let function = xilem_to_function(&fs_path_to_module_ident(&file), xilem_expressions);
let function = scope::typst_scope_to_rust(typst_ast.scope());