use proc_macro2::TokenStream;
use quote::{quote, quote_spanned};
use super::term::{Term, TermId, TermType};
use super::types::{Reference, TermIdent, TermOper, expand_type};
pub fn expand_trav(term: &TermId) -> Vec<TokenStream> {
let mut ops = Vec::new();
if term.trav_up {
match &term.up_ident {
Some(ident) => match ident {
TermIdent::Local(ident) => ops.push(quote! { .up_id(#ident) }),
TermIdent::Type(ty) => ops.push(quote! { .up_id(id::<#ty>()) }),
_ => ops
.push(quote_spanned!(term.span => ; compile_error!("Invalid up traversal.") )),
},
None => ops.push(quote! { .up() }),
}
}
if term.trav_cascade {
match &term.cascade_ident {
Some(ident) => match ident {
TermIdent::Local(ident) => ops.push(quote! { .cascade_id(#ident) }),
TermIdent::Type(ty) => ops.push(quote! { .cascade_id(id::<#ty>()) }),
_ => ops.push(
quote_spanned!(term.span => ; compile_error!("Invalid cascade traversal.") ),
),
},
None => ops.push(quote! { .cascade() }),
}
}
if term.trav_desc {
ops.push(quote! { .desc() });
}
if term.trav_self {
ops.push(quote! { .self_() });
}
ops
}
pub fn expand_term_type(term: &Term) -> Option<TokenStream> {
let ty = match &term.ty {
TermType::Pair(first, second) => {
let first = first.ident.as_ref()?;
let second = second.ident.as_ref()?;
let first = expand_type(first)?;
let second = expand_type(second)?;
quote! { (#first, #second) }
}
TermType::Component(id) => {
let id = id.ident.as_ref()?;
expand_type(id)?
}
TermType::Equality(_) => {
return None;
}
TermType::Scope(_) => {
return None;
}
};
let access_type = match term.reference {
Reference::Mut => quote! { &mut #ty },
Reference::Ref => quote! { & #ty },
Reference::None => return None,
};
match &term.oper {
TermOper::Optional => Some(quote! { Option<#access_type> }),
TermOper::And => Some(quote! { #access_type }),
_ => None,
}
}
pub fn expand_dsl(terms: &mut [Term]) -> (TokenStream, Vec<TokenStream>) {
super::builder::build_query_components(terms)
}