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 {
|
fn is_included_in_single(&self, target: &dyn MersType) -> bool {
|
||||||
self.types.iter().all(|t| t.is_included_in_single(target))
|
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) {
|
fn subtypes(&self, acc: &mut Type) {
|
||||||
for t in &self.types {
|
for t in &self.types {
|
||||||
t.subtypes(acc);
|
t.subtypes(acc);
|
||||||
|
@ -12,11 +12,15 @@ use super::Config;
|
|||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
/// `sum: fn` returns the sum of all the numbers in the tuple
|
/// `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
|
/// `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.
|
/// `div: fn` returns a / b. Performs integer division if a and b are both integers.
|
||||||
/// `modulo: fn` returns a % b
|
/// `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)
|
/// `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_int: fn` parses a string to an int, returns () on failure
|
||||||
/// `parse_float: fn` parses a string to an int, returns () on failure
|
/// `parse_float: fn` parses a string to an int, returns () on failure
|
||||||
/// TODO!
|
/// TODO!
|
||||||
@ -25,7 +29,36 @@ impl Config {
|
|||||||
/// `ceil: fn` rounds the float [?] and returns an int
|
/// `ceil: fn` rounds the float [?] and returns an int
|
||||||
/// `floor: fn` rounds the float [?] and returns an int
|
/// `floor: fn` rounds the float [?] and returns an int
|
||||||
pub fn with_math(self) -> Self {
|
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: Arc::new(program::run::Info::neverused()),
|
||||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||||
out: Arc::new(|a, _i| {
|
out: Arc::new(|a, _i| {
|
||||||
@ -125,25 +158,6 @@ impl Config {
|
|||||||
}
|
}
|
||||||
} else { unreachable!() }),
|
} 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(
|
.add_var(
|
||||||
"sum".to_string(),
|
"sum".to_string(),
|
||||||
Data::new(data::function::Function {
|
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(
|
.add_var(
|
||||||
"product".to_string(),
|
"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)
|
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