From db59a1e92e1095d52bab4d4930fdcb8cafe89faf Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 7 Nov 2023 18:37:37 +0100 Subject: [PATCH] remove diff, add subtract to replace it and work with iters, add lt, gt, ltoe, gtoe for < > <= >= --- examples/00_Hello_World.mers | 0 examples/01_Hello_Name.mers | 0 examples/02_Calc_Sum.mers | 0 examples/03_Basic_Calculator.mers | 0 examples/04_Greatest_Common_Divisor.mers | 0 examples/05_Matrix_Multiplicator.mers | 0 examples/fib.mers | 0 examples/iter.mers | 0 examples/try.mers | 0 mers_lib/src/data/mod.rs | 3 + mers_lib/src/program/configs/with_math.rs | 179 +++++++++++++++++--- mers_lib/src/program/configs/with_string.rs | 0 12 files changed, 161 insertions(+), 21 deletions(-) mode change 100644 => 100755 examples/00_Hello_World.mers mode change 100644 => 100755 examples/01_Hello_Name.mers mode change 100644 => 100755 examples/02_Calc_Sum.mers mode change 100644 => 100755 examples/03_Basic_Calculator.mers mode change 100644 => 100755 examples/04_Greatest_Common_Divisor.mers mode change 100644 => 100755 examples/05_Matrix_Multiplicator.mers mode change 100644 => 100755 examples/fib.mers mode change 100644 => 100755 examples/iter.mers mode change 100644 => 100755 examples/try.mers mode change 100644 => 100755 mers_lib/src/program/configs/with_string.rs diff --git a/examples/00_Hello_World.mers b/examples/00_Hello_World.mers old mode 100644 new mode 100755 diff --git a/examples/01_Hello_Name.mers b/examples/01_Hello_Name.mers old mode 100644 new mode 100755 diff --git a/examples/02_Calc_Sum.mers b/examples/02_Calc_Sum.mers old mode 100644 new mode 100755 diff --git a/examples/03_Basic_Calculator.mers b/examples/03_Basic_Calculator.mers old mode 100644 new mode 100755 diff --git a/examples/04_Greatest_Common_Divisor.mers b/examples/04_Greatest_Common_Divisor.mers old mode 100644 new mode 100755 diff --git a/examples/05_Matrix_Multiplicator.mers b/examples/05_Matrix_Multiplicator.mers old mode 100644 new mode 100755 diff --git a/examples/fib.mers b/examples/fib.mers old mode 100644 new mode 100755 diff --git a/examples/iter.mers b/examples/iter.mers old mode 100644 new mode 100755 diff --git a/examples/try.mers b/examples/try.mers old mode 100644 new mode 100755 diff --git a/mers_lib/src/data/mod.rs b/mers_lib/src/data/mod.rs index 7b0a744..d4a46de 100755 --- a/mers_lib/src/data/mod.rs +++ b/mers_lib/src/data/mod.rs @@ -329,6 +329,9 @@ impl MersType for Type { fn is_included_in_single(&self, target: &dyn MersType) -> bool { self.types.iter().all(|t| t.is_included_in_single(target)) } + fn is_included_in(&self, target: &dyn MersType) -> bool { + self.types.iter().all(|t| t.is_included_in(target)) + } fn subtypes(&self, acc: &mut Type) { for t in &self.types { t.subtypes(acc); diff --git a/mers_lib/src/program/configs/with_math.rs b/mers_lib/src/program/configs/with_math.rs index afed35b..22d1f15 100755 --- a/mers_lib/src/program/configs/with_math.rs +++ b/mers_lib/src/program/configs/with_math.rs @@ -12,11 +12,15 @@ use super::Config; impl Config { /// `sum: fn` returns the sum of all the numbers in the tuple - /// `diff: fn` returns b - a + /// `minus: fn` returns the first number minus all the others /// `product: fn` returns the product of all the numbers in the tuple /// `div: fn` returns a / b. Performs integer division if a and b are both integers. /// `modulo: fn` returns a % b /// `signum: fn` returns 1 for positive numbers, -1 for negative ones and 0 for 0 (always returns an Int, even when input is Float) + /// `lt: fn` returns true if the input keeps increasing, that is, for (a, b), a < b, for (a, b, c), a < b < c, and so on. + /// `gt: fn` returns true if the input keeps decreasing, that is, for (a, b), a > b, for (a, b, c), a > b > c, and so on. + /// `ltoe: fn` returns true if the input only increases, that is, for (a, b), a <= b, for (a, b, c), a <= b <= c, and so on. + /// `gtoe: fn` returns true if the input only decreases, that is, for (a, b), a >= b, for (a, b, c), a >= b >= c, and so on. /// `parse_int: fn` parses a string to an int, returns () on failure /// `parse_float: fn` parses a string to an int, returns () on failure /// TODO! @@ -25,7 +29,36 @@ impl Config { /// `ceil: fn` rounds the float [?] and returns an int /// `floor: fn` rounds the float [?] and returns an int pub fn with_math(self) -> Self { - self.add_var("parse_float".to_string(), Data::new(data::function::Function { + self + .add_var("lt".to_string(), Data::new(ltgtoe_function("lt".to_string(), |l, r| match (l, r) { + (IntOrFloatOrNothing::Nothing, _) | (_, IntOrFloatOrNothing::Nothing) => true, + (IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Int(r)) => l < r, + (IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Float(r)) => (l as f64) < r, + (IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Int(r)) => l < r as f64, + (IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Float(r)) => l < r, + }))) + .add_var("gt".to_string(), Data::new(ltgtoe_function("gt".to_string(), |l, r| match (l, r) { + (IntOrFloatOrNothing::Nothing, _) | (_, IntOrFloatOrNothing::Nothing) => true, + (IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Int(r)) => l > r, + (IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Float(r)) => (l as f64) > r, + (IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Int(r)) => l > r as f64, + (IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Float(r)) => l > r, + }))) + .add_var("ltoe".to_string(), Data::new(ltgtoe_function("ltoe".to_string(), |l, r| match (l, r) { + (IntOrFloatOrNothing::Nothing, _) | (_, IntOrFloatOrNothing::Nothing) => true, + (IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Int(r)) => l <= r, + (IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Float(r)) => (l as f64) <= r, + (IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Int(r)) => l <= r as f64, + (IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Float(r)) => l <= r, + }))) + .add_var("gtoe".to_string(), Data::new(ltgtoe_function("gtoe".to_string(), |l, r| match (l, r) { + (IntOrFloatOrNothing::Nothing, _) | (_, IntOrFloatOrNothing::Nothing) => true, + (IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Int(r)) => l >= r, + (IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Float(r)) => (l as f64) >= r, + (IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Int(r)) => l >= r as f64, + (IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Float(r)) => l >= r, + }))) + .add_var("parse_float".to_string(), Data::new(data::function::Function { info: Arc::new(program::run::Info::neverused()), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), out: Arc::new(|a, _i| { @@ -125,25 +158,6 @@ impl Config { } } else { unreachable!() }), })) - .add_var("diff".to_string(), Data::new(data::function::Function { - info: Arc::new(program::run::Info::neverused()), - info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(|a, _i| two_tuple_to_num(a, "diff")), - run: Arc::new(|a, _i| if let Some(t) = a.get().as_any().downcast_ref::() { - let left = t.0[0].get(); - let right = t.0[1].get(); - let (left, right) = (left.as_any(), right.as_any()); - match (left.downcast_ref::(), left.downcast_ref::(), - right.downcast_ref::(), right.downcast_ref::() - ) { - (Some(data::int::Int(l)), None, Some(data::int::Int(r)), None) => Data::new(data::int::Int(r - l)), - (Some(data::int::Int(l)), None, None, Some(data::float::Float(r))) => Data::new(data::float::Float(r - *l as f64)), - (None, Some(data::float::Float(l)), Some(data::int::Int(r)), None) => Data::new(data::float::Float(*r as f64 - l)), - (None, Some(data::float::Float(l)), None, Some(data::float::Float(r))) => Data::new(data::float::Float(r - l)), - _ => unreachable!(), - } - } else { unreachable!() }), - })) .add_var( "sum".to_string(), Data::new(data::function::Function { @@ -204,6 +218,79 @@ impl Config { } }), }), + ) + .add_var( + "subtract".to_string(), + Data::new(data::function::Function { + info: Arc::new(program::run::Info::neverused()), + info_check: Arc::new(Mutex::new(CheckInfo::neverused())), + out: Arc::new(|a, _i| { + let mut ints = false; + let mut floats = false; + for a in &a.types { + if let Some(i) = a.iterable() { + if i.types + .iter() + .all(|t| t.as_any().downcast_ref::().is_some()) + { + ints = true; + } else if i.types.iter().all(|t| { + t.as_any().downcast_ref::().is_some() + || t.as_any().downcast_ref::().is_some() + }) { + floats = true; + } else { + return Err(format!("cannot subtract on iterator over type {i} because it contains types that aren't int/float").into()) + } + } else { + return Err(format!( + "cannot subtract over non-iterable type {a}" + ).into()); + } + } + Ok(match (ints, floats) { + (_, true) => Type::new(data::float::FloatT), + (true, false) => Type::new(data::int::IntT), + (false, false) => Type::empty(), + }) + }), + run: Arc::new(|a, _i| { + if let Some(i) = a.get().iterable() { + let mut first = true; + let mut sumi = 0; + let mut sumf = 0.0; + let mut usef = false; + for val in i { + if let Some(i) = val.get().as_any().downcast_ref::() { + if first { + sumi = i.0; + } else { + sumi -= i.0; + } + } else if let Some(i) = + val.get().as_any().downcast_ref::() + { + if first { + sumf = i.0; + } else { + sumf -= i.0; + } + usef = true; + } + if first { + first = false; + } + } + if usef { + Data::new(data::float::Float(sumi as f64 + sumf)) + } else { + Data::new(data::int::Int(sumi)) + } + } else { + unreachable!("sum called on non-tuple") + } + }), + }), ) .add_var( "product".to_string(), @@ -301,3 +388,53 @@ fn two_tuple_to_num(a: &Type, func_name: &str) -> Result { Type::new(data::int::IntT) }) } + +fn ltgtoe_function( + func_name: String, + op: impl Fn(IntOrFloatOrNothing, IntOrFloatOrNothing) -> bool + Send + Sync + 'static, +) -> data::function::Function { + data::function::Function { + info: Arc::new(program::run::Info::neverused()), + info_check: Arc::new(Mutex::new(CheckInfo::neverused())), + out: Arc::new(move |a, _i| { + if let Some(iter_type) = a.iterable() { + let iter_required_type = Type::newm(vec![ + Arc::new(data::int::IntT), + Arc::new(data::float::FloatT), + ]); + if iter_type.is_included_in(&iter_required_type) { + Ok(Type::new(data::bool::BoolT)) + } else { + Err(CheckError::from(format!("Cannot use {func_name} on iterator over type {iter_type} (has to be at most {iter_required_type})."))) + } + } else { + Err(CheckError::from(format!("Cannot use {func_name}"))) + } + }), + run: Arc::new(move |a, _i| { + let mut prev = IntOrFloatOrNothing::Nothing; + for item in a.get().iterable().unwrap() { + let item = item.get(); + let new = if let Some(data::int::Int(v)) = item.as_any().downcast_ref() { + IntOrFloatOrNothing::Int(*v) + } else if let Some(data::float::Float(v)) = item.as_any().downcast_ref() { + IntOrFloatOrNothing::Float(*v) + } else { + unreachable!() + }; + if op(prev, new) { + prev = new; + } else { + return Data::new(data::bool::Bool(false)); + } + } + Data::new(data::bool::Bool(true)) + }), + } +} +#[derive(Clone, Copy)] +enum IntOrFloatOrNothing { + Nothing, + Int(isize), + Float(f64), +} diff --git a/mers_lib/src/program/configs/with_string.rs b/mers_lib/src/program/configs/with_string.rs old mode 100644 new mode 100755