use crate::planner::TransformationArgument;
use crate::catalog::{ArithmeticPos, FactorPos};
use crate::parser::{ArithmeticOperator, ConstType};
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) enum FactorArgument {
Var(TransformationArgument),
Const(ConstType),
FnCall {
name: String,
args: Vec<ArithmeticArgument>,
},
}
impl FactorArgument {
pub(crate) fn transformation_arguments(&self) -> Vec<&TransformationArgument> {
match self {
Self::Var(arg) => vec![arg],
Self::Const(_) => vec![],
Self::FnCall { args, .. } => args
.iter()
.flat_map(|a| a.transformation_arguments())
.collect(),
}
}
}
impl fmt::Display for FactorArgument {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Var(transformation_arg) => write!(f, "{}", transformation_arg),
Self::Const(constant) => write!(f, "{}", constant),
Self::FnCall { name, args } => {
let args_str = args
.iter()
.map(|a| a.to_string())
.collect::<Vec<_>>()
.join(", ");
write!(f, "{name}({args_str})")
}
}
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub(crate) struct ArithmeticArgument {
pub(crate) init: FactorArgument,
pub(crate) rest: Vec<(ArithmeticOperator, FactorArgument)>,
}
impl ArithmeticArgument {
pub(crate) fn from_arithmeticpos(
arithmetic: &ArithmeticPos,
var_arguments: &[TransformationArgument],
) -> Self {
fn map_factor(
factor: &FactorPos,
var_arguments: &[TransformationArgument],
var_id: &mut usize,
) -> FactorArgument {
match factor {
FactorPos::Var(_) => {
let var_signature = &var_arguments[*var_id];
*var_id += 1;
FactorArgument::Var(*var_signature)
}
FactorPos::Const(constant) => FactorArgument::Const(constant.clone()),
FactorPos::FnCall { name, args } => {
let fn_args = args
.iter()
.map(|arg| {
let num_vars = arg.signatures().len();
let sub_args = &var_arguments[*var_id..*var_id + num_vars];
*var_id += num_vars;
ArithmeticArgument::from_arithmeticpos(arg, sub_args)
})
.collect();
FactorArgument::FnCall {
name: name.clone(),
args: fn_args,
}
}
}
}
let mut var_id = 0;
let init = map_factor(arithmetic.init(), var_arguments, &mut var_id);
let rest = arithmetic
.rest()
.iter()
.map(|(op, factor)| (op.clone(), map_factor(factor, var_arguments, &mut var_id)))
.collect();
Self { init, rest }
}
pub(crate) fn init(&self) -> &FactorArgument {
&self.init
}
pub(crate) fn rest(&self) -> &[(ArithmeticOperator, FactorArgument)] {
&self.rest
}
pub(crate) fn transformation_arguments(&self) -> Vec<&TransformationArgument> {
let mut args = self.init.transformation_arguments();
for (_, factor) in &self.rest {
args.extend(factor.transformation_arguments());
}
args
}
}
impl fmt::Display for ArithmeticArgument {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.init)?;
for (op, factor) in &self.rest {
write!(f, " {} {}", op, factor)?;
}
Ok(())
}
}