mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
remove diff, add subtract to replace it and work with iters, add lt, gt, ltoe, gtoe for < > <= >=
This commit is contained in:
parent
79660c1976
commit
db59a1e92e
0
examples/00_Hello_World.mers
Normal file → Executable file
0
examples/00_Hello_World.mers
Normal file → Executable file
0
examples/01_Hello_Name.mers
Normal file → Executable file
0
examples/01_Hello_Name.mers
Normal file → Executable file
0
examples/02_Calc_Sum.mers
Normal file → Executable file
0
examples/02_Calc_Sum.mers
Normal file → Executable file
0
examples/03_Basic_Calculator.mers
Normal file → Executable file
0
examples/03_Basic_Calculator.mers
Normal file → Executable file
0
examples/04_Greatest_Common_Divisor.mers
Normal file → Executable file
0
examples/04_Greatest_Common_Divisor.mers
Normal file → Executable file
0
examples/05_Matrix_Multiplicator.mers
Normal file → Executable file
0
examples/05_Matrix_Multiplicator.mers
Normal file → Executable file
0
examples/fib.mers
Normal file → Executable file
0
examples/fib.mers
Normal file → Executable file
0
examples/iter.mers
Normal file → Executable file
0
examples/iter.mers
Normal file → Executable file
0
examples/try.mers
Normal file → Executable file
0
examples/try.mers
Normal file → Executable file
@ -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);
|
||||
|
@ -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::<data::tuple::Tuple>() {
|
||||
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::<data::int::Int>(), left.downcast_ref::<data::float::Float>(),
|
||||
right.downcast_ref::<data::int::Int>(), right.downcast_ref::<data::float::Float>()
|
||||
) {
|
||||
(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::<data::int::IntT>().is_some())
|
||||
{
|
||||
ints = true;
|
||||
} else if i.types.iter().all(|t| {
|
||||
t.as_any().downcast_ref::<data::int::IntT>().is_some()
|
||||
|| t.as_any().downcast_ref::<data::float::FloatT>().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::<data::int::Int>() {
|
||||
if first {
|
||||
sumi = i.0;
|
||||
} else {
|
||||
sumi -= i.0;
|
||||
}
|
||||
} else if let Some(i) =
|
||||
val.get().as_any().downcast_ref::<data::float::Float>()
|
||||
{
|
||||
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, CheckError> {
|
||||
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),
|
||||
}
|
||||
|
0
mers_lib/src/program/configs/with_string.rs
Normal file → Executable file
0
mers_lib/src/program/configs/with_string.rs
Normal file → Executable file
Loading…
Reference in New Issue
Block a user