use std::fmt;
use super::{implementation, Result};
use crate::data_type::{value::Value, DataType};
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Function {
Opposite,
Not,
Plus,
Minus,
Multiply,
Divide,
Modulo,
StringConcat,
Gt,
Lt,
GtEq,
LtEq,
Eq,
NotEq,
And,
Or,
Xor,
BitwiseOr,
BitwiseAnd,
BitwiseXor,
InList,
Exp,
Ln,
Log,
Abs,
Sin,
Cos,
Sqrt,
Pow,
Case,
Concat(usize),
CharLength,
Lower,
Upper,
Md5,
Position,
Random(usize),
CastAsText,
CastAsFloat,
CastAsInteger,
CastAsDateTime,
Least,
Greatest,
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Style {
UnaryOperator,
BinaryOperator,
Function,
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Arity {
Unary,
Nary(usize),
Varying,
}
impl Function {
pub fn style(self) -> Style {
match self {
Function::Opposite | Function::Not => Style::UnaryOperator,
Function::Plus
| Function::Minus
| Function::Multiply
| Function::Divide
| Function::Modulo
| Function::StringConcat
| Function::Gt
| Function::Lt
| Function::GtEq
| Function::LtEq
| Function::Eq
| Function::NotEq
| Function::And
| Function::Or
| Function::Xor
| Function::BitwiseOr
| Function::BitwiseAnd
| Function::BitwiseXor
| Function::InList => Style::BinaryOperator,
Function::Random(_)
| Function::Exp
| Function::Ln
| Function::Log
| Function::Abs
| Function::Sin
| Function::Cos
| Function::Sqrt
| Function::CharLength
| Function::Lower
| Function::Upper
| Function::Md5
| Function::CastAsText
| Function::CastAsFloat
| Function::CastAsInteger
| Function::CastAsDateTime
| Function::Pow
| Function::Position
| Function::Least
| Function::Greatest
| Function::Case
| Function::Concat(_) => Style::Function,
}
}
pub fn arity(self) -> Arity {
match self {
Function::Opposite | Function::Not => Arity::Unary,
Function::Plus
| Function::Minus
| Function::Multiply
| Function::Divide
| Function::Modulo
| Function::StringConcat
| Function::Gt
| Function::Lt
| Function::GtEq
| Function::LtEq
| Function::Eq
| Function::NotEq
| Function::And
| Function::Or
| Function::Xor
| Function::BitwiseOr
| Function::BitwiseAnd
| Function::BitwiseXor
| Function::InList => Arity::Nary(2),
Function::Random(_) => Arity::Nary(0),
Function::Exp
| Function::Ln
| Function::Log
| Function::Abs
| Function::Sin
| Function::Cos
| Function::Sqrt
| Function::CharLength
| Function::Lower
| Function::Upper
| Function::Md5
| Function::CastAsText
| Function::CastAsFloat
| Function::CastAsInteger
| Function::CastAsDateTime => Arity::Unary,
Function::Pow | Function::Position | Function::Least | Function::Greatest => {
Arity::Nary(2)
}
Function::Case => Arity::Nary(3),
Function::Concat(_) => Arity::Varying,
}
}
pub fn super_image(self, sets: &[DataType]) -> Result<DataType> {
let set = match self.arity() {
Arity::Unary => sets.as_ref()[0].clone(),
Arity::Nary(n) => DataType::structured_from_data_types(&sets[0..n]),
Arity::Varying => DataType::structured_from_data_types(sets),
};
Ok(implementation::function(self).super_image(&set)?)
}
pub fn value(self, args: &[Value]) -> Result<Value> {
let arg = match self.arity() {
Arity::Unary => args.as_ref()[0].clone(),
Arity::Nary(n) => Value::structured_from_values(&args[0..n]),
Arity::Varying => Value::structured_from_values(&args),
};
Ok(implementation::function(self).value(&arg)?)
}
}
impl fmt::Display for Function {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Function::Opposite => "-",
Function::Not => "not",
Function::Plus => "+",
Function::Minus => "-",
Function::Multiply => "*",
Function::Divide => "/",
Function::Modulo => "%",
Function::StringConcat => "||",
Function::Gt => ">",
Function::Lt => "<",
Function::GtEq => ">=",
Function::LtEq => "<=",
Function::Eq => "=",
Function::NotEq => "<>",
Function::And => "and",
Function::Or => "or",
Function::Xor => "xor",
Function::BitwiseOr => "|",
Function::BitwiseAnd => "&",
Function::BitwiseXor => "^",
Function::InList => "in",
Function::Random(_) => "random",
Function::Exp => "exp",
Function::Ln => "ln",
Function::Log => "log",
Function::Abs => "abs",
Function::Sin => "sin",
Function::Cos => "cos",
Function::Sqrt => "sqrt",
Function::CharLength => "char_length",
Function::Lower => "lower",
Function::Upper => "upper",
Function::Md5 => "md5",
Function::CastAsText => "cast_as_text",
Function::CastAsInteger => "cast_as_integer",
Function::CastAsFloat => "cast_as_float",
Function::CastAsDateTime => "cast_as_date_time",
Function::Pow => "pow",
Function::Position => "position",
Function::Least => "least",
Function::Greatest => "greatest",
Function::Case => "case",
Function::Concat(_) => "concat",
})
}
}