use crate::data_structures::OrderedMap;
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub(crate) struct DVar {
pub name: syn::Ident,
}
impl DVar {
pub fn new(name: syn::Ident) -> Self {
Self { name: name }
}
}
#[derive(Debug)]
pub(crate) struct DVarTuple {
pub vars: Vec<DVar>,
}
impl DVarTuple {
pub fn new(args: Vec<syn::Ident>) -> Self {
Self {
vars: args.into_iter().map(|ident| DVar::new(ident)).collect(),
}
}
}
#[derive(Debug)]
pub(crate) struct DVarKeyVal {
pub key: Vec<DVar>,
pub value: Vec<DVar>,
}
#[derive(Debug)]
pub(crate) enum DVars {
Tuple(DVarTuple),
KeyVal(DVarKeyVal),
}
impl DVars {
pub fn new_tuple(args: Vec<syn::Ident>) -> Self {
DVars::Tuple(DVarTuple::new(args))
}
pub fn new_key_val(key: Vec<syn::Ident>, value: Vec<syn::Ident>) -> Self {
DVars::KeyVal(DVarKeyVal {
key: key.into_iter().map(|ident| DVar::new(ident)).collect(),
value: value.into_iter().map(|ident| DVar::new(ident)).collect(),
})
}
}
#[derive(Debug)]
pub(crate) enum DVarTypes {
Tuple(Vec<syn::Type>),
KeyVal {
key: Vec<syn::Type>,
value: Vec<syn::Type>,
},
}
impl std::convert::From<Vec<syn::Type>> for DVarTypes {
fn from(types: Vec<syn::Type>) -> Self {
DVarTypes::Tuple(types)
}
}
#[derive(Debug)]
pub(crate) struct RelationDecl {
pub var: Variable,
pub typ: Vec<syn::Type>,
}
#[derive(Debug)]
pub(crate) struct VariableDecl {
pub var: Variable,
pub typ: DVarTypes,
pub is_output: bool,
}
#[derive(Debug, Clone)]
pub(crate) struct Variable {
pub name: syn::Ident,
}
impl Variable {
pub fn with_counter(&self, counter: usize) -> Self {
Self {
name: syn::Ident::new(
&format!("{}_{}", self.name, counter),
proc_macro2::Span::call_site(),
),
}
}
}
#[derive(Debug)]
pub(crate) struct ReorderOp {
pub output: Variable,
pub input: Variable,
pub input_vars: DVars,
pub output_vars: DVars,
}
#[derive(Debug)]
pub(crate) struct BindVarOp {
pub output: Variable,
pub input: Variable,
pub vars: DVarTuple,
pub expr: syn::Expr,
}
#[derive(Debug)]
pub(crate) struct JoinOp {
pub output: Variable,
pub input_first: Variable,
pub input_second: Variable,
pub key: DVarTuple,
pub value_first: DVarTuple,
pub value_second: DVarTuple,
}
#[derive(Debug)]
pub(crate) struct AntiJoinOp {
pub output: Variable,
pub input_variable: Variable,
pub input_relation: Variable,
pub key: DVarTuple,
pub value: DVarTuple,
}
#[derive(Debug)]
pub(crate) struct FilterOp {
pub variable: Variable,
pub vars: DVars,
pub expr: syn::Expr,
}
#[derive(Debug)]
pub(crate) struct InsertOp {
pub variable: Variable,
pub relation: Variable,
}
#[derive(Debug)]
pub(crate) enum Operation {
Reorder(ReorderOp),
Join(JoinOp),
AntiJoin(AntiJoinOp),
Insert(InsertOp),
}
#[derive(Debug)]
pub(crate) struct Iteration {
relation_variables: HashMap<syn::Ident, syn::Ident>,
pub relations: OrderedMap<syn::Ident, RelationDecl>,
pub variables: OrderedMap<syn::Ident, VariableDecl>,
pub pre_operations: Vec<Operation>,
pub body_operations: Vec<Operation>,
pub post_operations: Vec<Operation>,
}
impl Iteration {
pub fn new(relations: Vec<RelationDecl>, variables: Vec<VariableDecl>) -> Self {
Self {
relation_variables: HashMap::new(),
relations: relations
.into_iter()
.map(|decl| (decl.var.name.clone(), decl))
.collect(),
variables: variables
.into_iter()
.map(|decl| (decl.var.name.clone(), decl))
.collect(),
pre_operations: Vec::new(),
body_operations: Vec::new(),
post_operations: Vec::new(),
}
}
pub fn convert_relation_to_variable(&mut self, variable: &Variable) -> Variable {
if let Some(name) = self.relation_variables.get(&variable.name) {
return self.variables[name].var.clone();
}
let decl = &self.relations[&variable.name];
let variable_decl = VariableDecl {
var: decl.var.with_counter(self.variables.len()),
typ: decl.typ.clone().into(),
is_output: false,
};
let new_variable = variable_decl.var.clone();
self.relation_variables
.insert(variable.name.clone(), new_variable.name.clone());
self.variables
.insert(new_variable.name.clone(), variable_decl);
self.pre_operations.push(Operation::Insert(InsertOp {
variable: new_variable.clone(),
relation: decl.var.clone(),
}));
new_variable
}
pub fn get_or_convert_variable(&mut self, predicate: &syn::Ident) -> Variable {
if let Some(variable) = self.get_relation_var(predicate) {
self.convert_relation_to_variable(&variable)
} else {
self.get_variable(predicate)
}
}
pub fn get_relation_var(&self, variable_name: &syn::Ident) -> Option<Variable> {
self.relations
.get(variable_name)
.map(|decl| decl.var.clone())
}
pub fn get_variable(&self, variable_name: &syn::Ident) -> Variable {
self.variables[variable_name].var.clone()
}
pub fn add_operation(&mut self, operation: Operation) {
self.body_operations.push(operation);
}
pub fn get_variable_tuple_types(&self, variable: &Variable) -> Vec<syn::Type> {
let decl = &self.variables[&variable.name];
match &decl.typ {
DVarTypes::Tuple(types) => types.clone(),
DVarTypes::KeyVal { .. } => unreachable!(),
}
}
pub fn create_key_val_variable(
&mut self,
variable: &Variable,
key: Vec<syn::Type>,
value: Vec<syn::Type>,
) -> Variable {
self.create_variable(variable, DVarTypes::KeyVal { key, value })
}
pub fn create_tuple_variable(
&mut self,
variable: &Variable,
types: Vec<syn::Type>,
) -> Variable {
self.create_variable(variable, DVarTypes::Tuple(types))
}
pub fn create_variable(&mut self, variable: &Variable, typ: DVarTypes) -> Variable {
let variable_decl = VariableDecl {
var: variable.with_counter(self.variables.len()),
typ: typ,
is_output: false,
};
let new_variable = variable_decl.var.clone();
self.variables
.insert(new_variable.name.clone(), variable_decl);
new_variable
}
}