use proc_macro2::TokenStream;
use quote::quote;
use crate::parser::{DataType, Program, Relation};
use crate::codegen::user_tuple_tokens;
use super::user_struct_ident;
pub(crate) fn gen_public_rel_module(program: &Program) -> TokenStream {
let aliases: Vec<TokenStream> = collect_user_rels(program)
.into_iter()
.map(gen_type_alias)
.collect();
quote! {
pub mod rel {
#(#aliases)*
}
}
}
pub(crate) fn collect_user_rels(program: &Program) -> Vec<&Relation> {
let mut seen: Vec<&Relation> = Vec::new();
for rel in program.edbs().into_iter().chain(program.output_idbs()) {
if rel.arity() == 0 {
continue;
}
if !seen.iter().any(|r| r.name() == rel.name()) {
seen.push(rel);
}
}
seen
}
fn gen_type_alias(rel: &Relation) -> TokenStream {
let ident = user_struct_ident(rel);
let tuple_ty = user_tuple_tokens(&rel.data_type());
quote! { pub type #ident = #tuple_ty; }
}
pub(crate) fn user_to_tuple_expr(
dt: &DataType,
string_intern: bool,
src: TokenStream,
) -> TokenStream {
match *dt {
DataType::Float32 | DataType::Float64 => quote! { OrderedFloat(#src) },
DataType::String if string_intern => quote! { intern(&#src) },
_ => src,
}
}
pub(crate) fn tuple_to_user_expr(
dt: &DataType,
string_intern: bool,
src: TokenStream,
) -> TokenStream {
match *dt {
DataType::Float32 | DataType::Float64 => quote! { (#src).into_inner() },
DataType::String if string_intern => quote! { resolve_out(#src).to_string() },
_ => src,
}
}