1 use crate::result::FResult; 2 use crate::value::Expr; 3 use crate::value::Ident; 4 use crate::value::Scope; 5 use crate::FendError; 6 use crate::{Deserialize, Serialize}; 7 use std::{fmt, io}; 8 9 use std::sync::Arc; 10 11 use crate::value::Value; 12 13 #[derive(Copy, Clone, Eq, PartialEq, Debug)] 14 pub(crate) enum BuiltInFunction { 15 Approximately, 16 Abs, 17 Sin, 18 Cos, 19 Tan, 20 Asin, 21 Acos, 22 Atan, 23 Sinh, 24 Cosh, 25 Tanh, 26 Asinh, 27 Acosh, 28 Atanh, 29 Ln, 30 Log2, 31 Log10, 32 Base, 33 Sample, 34 Mean, 35 Not, 36 Conjugate, 37 Real, 38 Imag, 39 Arg, 40 Floor, 41 Ceil, 42 Round, 43 } 44 45 impl BuiltInFunction { wrap_with_expr( self, lazy_fn: impl FnOnce(Box<Expr>) -> Expr, scope: Option<Arc<Scope>>, ) -> Value46 pub(crate) fn wrap_with_expr( 47 self, 48 lazy_fn: impl FnOnce(Box<Expr>) -> Expr, 49 scope: Option<Arc<Scope>>, 50 ) -> Value { 51 Value::Fn( 52 Ident::new_str("x"), 53 Box::new(lazy_fn(Box::new(Expr::ApplyFunctionCall( 54 Box::new(Expr::Ident(Ident::new_str(self.as_str()))), 55 Box::new(Expr::Ident(Ident::new_str("x"))), 56 )))), 57 scope, 58 ) 59 } 60 invert(self) -> FResult<Value>61 pub(crate) fn invert(self) -> FResult<Value> { 62 Ok(match self { 63 Self::Sin => Value::BuiltInFunction(Self::Asin), 64 Self::Cos => Value::BuiltInFunction(Self::Acos), 65 Self::Tan => Value::BuiltInFunction(Self::Atan), 66 Self::Asin => Value::BuiltInFunction(Self::Sin), 67 Self::Acos => Value::BuiltInFunction(Self::Cos), 68 Self::Atan => Value::BuiltInFunction(Self::Tan), 69 Self::Sinh => Value::BuiltInFunction(Self::Asinh), 70 Self::Cosh => Value::BuiltInFunction(Self::Acosh), 71 Self::Tanh => Value::BuiltInFunction(Self::Atanh), 72 Self::Asinh => Value::BuiltInFunction(Self::Sinh), 73 Self::Acosh => Value::BuiltInFunction(Self::Cosh), 74 Self::Atanh => Value::BuiltInFunction(Self::Tanh), 75 _ => return Err(FendError::UnableToInvertFunction(self.as_str())), 76 }) 77 } 78 as_str(self) -> &'static str79 pub(crate) const fn as_str(self) -> &'static str { 80 match self { 81 Self::Approximately => "approximately", 82 Self::Abs => "abs", 83 Self::Sin => "sin", 84 Self::Cos => "cos", 85 Self::Tan => "tan", 86 Self::Asin => "asin", 87 Self::Acos => "acos", 88 Self::Atan => "atan", 89 Self::Sinh => "sinh", 90 Self::Cosh => "cosh", 91 Self::Tanh => "tanh", 92 Self::Asinh => "asinh", 93 Self::Acosh => "acosh", 94 Self::Atanh => "atanh", 95 Self::Ln => "ln", 96 Self::Log2 => "log2", 97 Self::Log10 => "log10", 98 Self::Base => "base", 99 Self::Sample => "sample", 100 Self::Mean => "mean", 101 Self::Not => "not", 102 Self::Conjugate => "conjugate", 103 Self::Real => "real", 104 Self::Imag => "imag", 105 Self::Arg => "arg", 106 Self::Floor => "floor", 107 Self::Ceil => "ceil", 108 Self::Round => "round", 109 } 110 } 111 try_from_str(s: &str) -> FResult<Self>112 fn try_from_str(s: &str) -> FResult<Self> { 113 Ok(match s { 114 "approximately" => Self::Approximately, 115 "abs" => Self::Abs, 116 "sin" => Self::Sin, 117 "cos" => Self::Cos, 118 "tan" => Self::Tan, 119 "asin" => Self::Asin, 120 "acos" => Self::Acos, 121 "atan" => Self::Atan, 122 "sinh" => Self::Sinh, 123 "cosh" => Self::Cosh, 124 "tanh" => Self::Tanh, 125 "asinh" => Self::Asinh, 126 "acosh" => Self::Acosh, 127 "atanh" => Self::Atanh, 128 "ln" => Self::Ln, 129 "log2" => Self::Log2, 130 "log10" => Self::Log10, 131 "base" => Self::Base, 132 "sample" => Self::Sample, 133 "not" => Self::Not, 134 "conjugate" => Self::Conjugate, 135 "real" => Self::Real, 136 "imag" => Self::Imag, 137 _ => return Err(FendError::DeserializationError), 138 }) 139 } 140 serialize(self, write: &mut impl io::Write) -> FResult<()>141 pub(crate) fn serialize(self, write: &mut impl io::Write) -> FResult<()> { 142 self.as_str().serialize(write) 143 } 144 deserialize(read: &mut impl io::Read) -> FResult<Self>145 pub(crate) fn deserialize(read: &mut impl io::Read) -> FResult<Self> { 146 Self::try_from_str(String::deserialize(read)?.as_str()) 147 } 148 } 149 150 impl fmt::Display for BuiltInFunction { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 152 write!(f, "{}", self.as_str()) 153 } 154 } 155