mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
more iter functions
This commit is contained in:
parent
6077de8370
commit
a30ba84691
@ -323,7 +323,8 @@ impl Type {
|
|||||||
|
|
||||||
impl MersType for Type {
|
impl MersType for Type {
|
||||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||||
todo!()
|
// TODO! improve
|
||||||
|
self.is_included_in(other) && other.is_included_in(self)
|
||||||
}
|
}
|
||||||
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))
|
||||||
|
@ -4,7 +4,11 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{self, function::FunctionT, Data, MersData, MersType, Type},
|
data::{
|
||||||
|
self,
|
||||||
|
function::{Function, FunctionT},
|
||||||
|
Data, MersData, MersType, Type,
|
||||||
|
},
|
||||||
program::{
|
program::{
|
||||||
self,
|
self,
|
||||||
run::{CheckError, CheckInfo},
|
run::{CheckError, CheckInfo},
|
||||||
@ -19,6 +23,8 @@ impl Config {
|
|||||||
/// `map: fn` maps each value in the iterable to a new one by applying a transformation function
|
/// `map: fn` maps each value in the iterable to a new one by applying a transformation function
|
||||||
/// `filter: fn` filters the iterable by removing all elements where the filter function doesn't return true
|
/// `filter: fn` filters the iterable by removing all elements where the filter function doesn't return true
|
||||||
/// `filter_map: fn` combines filter and map. requires that the function returns ()/(t).
|
/// `filter_map: fn` combines filter and map. requires that the function returns ()/(t).
|
||||||
|
/// `map_while: fn` maps while the map-function returns (d), ends the iterator once () is returned.
|
||||||
|
/// `take: fn` takes at most so many elements from the iterator.
|
||||||
/// `enumerate: fn` transforms an iterator over T into one over (Int, T), where Int is the index of the element
|
/// `enumerate: fn` transforms an iterator over T into one over (Int, T), where Int is the index of the element
|
||||||
pub fn with_iters(self) -> Self {
|
pub fn with_iters(self) -> Self {
|
||||||
self.add_var(
|
self.add_var(
|
||||||
@ -89,85 +95,23 @@ impl Config {
|
|||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"map".to_string(),
|
"map".to_string(),
|
||||||
Data::new(data::function::Function {
|
Data::new(genfunc_iter_and_func("map", ItersT::Map, Iters::Map))
|
||||||
info: Arc::new(program::run::Info::neverused()),
|
|
||||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
|
||||||
out: Arc::new(|a, _i| {
|
|
||||||
iter_out(a, "map", |f| ItersT::Map(f.clone()))
|
|
||||||
}),
|
|
||||||
run: Arc::new(|a, _i| {
|
|
||||||
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
|
|
||||||
if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) {
|
|
||||||
if let Some(f) =
|
|
||||||
f.get().as_any().downcast_ref::<data::function::Function>()
|
|
||||||
{
|
|
||||||
Data::new(Iter(Iters::Map(Clone::clone(f)), v.clone()))
|
|
||||||
} else {
|
|
||||||
unreachable!("iter called on tuple not containing function")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!("iter called on tuple with len < 2")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!("iter called on non-tuple")
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"filter".to_string(),
|
"filter".to_string(),
|
||||||
Data::new(data::function::Function {
|
Data::new(genfunc_iter_and_func("filter", ItersT::Filter, Iters::Filter)),
|
||||||
info: Arc::new(program::run::Info::neverused()),
|
|
||||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
|
||||||
out: Arc::new(|a, _i| {
|
|
||||||
iter_out(a, "filter", |f| ItersT::Filter(f.clone()))
|
|
||||||
}),
|
|
||||||
run: Arc::new(|a, _i| {
|
|
||||||
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
|
|
||||||
if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) {
|
|
||||||
if let Some(f) =
|
|
||||||
f.get().as_any().downcast_ref::<data::function::Function>()
|
|
||||||
{
|
|
||||||
Data::new(Iter(Iters::Filter(Clone::clone(f)), v.clone()))
|
|
||||||
} else {
|
|
||||||
unreachable!("iter called on tuple not containing function")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!("iter called on tuple with len < 2")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!("iter called on non-tuple")
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"filter_map".to_string(),
|
"filter_map".to_string(),
|
||||||
Data::new(data::function::Function {
|
Data::new(genfunc_iter_and_func("filter_map", ItersT::FilterMap, Iters::FilterMap)),
|
||||||
info: Arc::new(program::run::Info::neverused()),
|
|
||||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
|
||||||
out: Arc::new(|a, _i| {
|
|
||||||
iter_out(a, "filter_map", |f| ItersT::FilterMap(f.clone()))
|
|
||||||
}),
|
|
||||||
run: Arc::new(|a, _i| {
|
|
||||||
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
|
|
||||||
if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) {
|
|
||||||
if let Some(f) =
|
|
||||||
f.get().as_any().downcast_ref::<data::function::Function>()
|
|
||||||
{
|
|
||||||
Data::new(Iter(Iters::FilterMap(Clone::clone(f)), v.clone()))
|
|
||||||
} else {
|
|
||||||
unreachable!("iter called on tuple not containing function")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!("iter called on tuple with len < 2")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!("iter called on non-tuple")
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
|
.add_var(
|
||||||
|
"map_while".to_string(),
|
||||||
|
Data::new(genfunc_iter_and_func("map_while", ItersT::MapWhile, Iters::MapWhile)),
|
||||||
|
)
|
||||||
|
.add_var("take".to_string(), Data::new(genfunc_iter_and_arg("take", |_: &data::int::IntT| ItersT::Take, |v: &data::int::Int| {
|
||||||
|
Iters::Take(v.0.max(0) as _)
|
||||||
|
})))
|
||||||
.add_var(
|
.add_var(
|
||||||
"enumerate".to_string(),
|
"enumerate".to_string(),
|
||||||
Data::new(data::function::Function {
|
Data::new(data::function::Function {
|
||||||
@ -187,7 +131,18 @@ impl Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_out(a: &Type, name: &str, func: impl Fn(&FunctionT) -> ItersT) -> Result<Type, CheckError> {
|
fn iter_out(
|
||||||
|
a: &Type,
|
||||||
|
name: &str,
|
||||||
|
func: impl Fn(&FunctionT) -> ItersT + Sync + Send,
|
||||||
|
) -> Result<Type, CheckError> {
|
||||||
|
iter_out_arg(a, name, func)
|
||||||
|
}
|
||||||
|
fn iter_out_arg<T: MersType>(
|
||||||
|
a: &Type,
|
||||||
|
name: &str,
|
||||||
|
func: impl Fn(&T) -> ItersT + Sync + Send,
|
||||||
|
) -> Result<Type, CheckError> {
|
||||||
let mut out = Type::empty();
|
let mut out = Type::empty();
|
||||||
for t in a.types.iter() {
|
for t in a.types.iter() {
|
||||||
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||||
@ -196,7 +151,7 @@ fn iter_out(a: &Type, name: &str, func: impl Fn(&FunctionT) -> ItersT) -> Result
|
|||||||
}
|
}
|
||||||
if let Some(v) = t.0[0].iterable() {
|
if let Some(v) = t.0[0].iterable() {
|
||||||
for f in t.0[1].types.iter() {
|
for f in t.0[1].types.iter() {
|
||||||
if let Some(f) = f.as_any().downcast_ref::<data::function::FunctionT>() {
|
if let Some(f) = f.as_any().downcast_ref::<T>() {
|
||||||
out.add(Arc::new(IterT::new(func(f), v.clone())?));
|
out.add(Arc::new(IterT::new(func(f), v.clone())?));
|
||||||
} else {
|
} else {
|
||||||
return Err(format!("cannot call {name} on tuple that isn't (_, function): got {} instead of function as part of {a}", t.0[1]).into());
|
return Err(format!("cannot call {name} on tuple that isn't (_, function): got {} instead of function as part of {a}", t.0[1]).into());
|
||||||
@ -213,11 +168,51 @@ fn iter_out(a: &Type, name: &str, func: impl Fn(&FunctionT) -> ItersT) -> Result
|
|||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn genfunc_iter_and_func(
|
||||||
|
name: &'static str,
|
||||||
|
ft: impl Fn(FunctionT) -> ItersT + Send + Sync + 'static,
|
||||||
|
fd: impl Fn(Function) -> Iters + Send + Sync + 'static,
|
||||||
|
) -> data::function::Function {
|
||||||
|
genfunc_iter_and_arg(
|
||||||
|
name,
|
||||||
|
move |v| ft(Clone::clone(v)),
|
||||||
|
move |v| fd(Clone::clone(v)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fn genfunc_iter_and_arg<T: MersType, D: MersData>(
|
||||||
|
name: &'static str,
|
||||||
|
ft: impl Fn(&T) -> ItersT + Send + Sync + 'static,
|
||||||
|
fd: impl Fn(&D) -> Iters + 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| iter_out_arg(a, name, |f: &T| ft(f))),
|
||||||
|
run: Arc::new(move |a, _i| {
|
||||||
|
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
|
||||||
|
if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) {
|
||||||
|
if let Some(f) = f.get().as_any().downcast_ref::<D>() {
|
||||||
|
Data::new(Iter(fd(f), v.clone()))
|
||||||
|
} else {
|
||||||
|
unreachable!("{name} called on tuple not containing function")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("{name} called on tuple with len < 2")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("{name} called on non-tuple")
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Iters {
|
pub enum Iters {
|
||||||
Map(data::function::Function),
|
Map(data::function::Function),
|
||||||
Filter(data::function::Function),
|
Filter(data::function::Function),
|
||||||
FilterMap(data::function::Function),
|
FilterMap(data::function::Function),
|
||||||
|
MapWhile(data::function::Function),
|
||||||
|
Take(usize),
|
||||||
Enumerate,
|
Enumerate,
|
||||||
}
|
}
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -225,6 +220,8 @@ pub enum ItersT {
|
|||||||
Map(data::function::FunctionT),
|
Map(data::function::FunctionT),
|
||||||
Filter(data::function::FunctionT),
|
Filter(data::function::FunctionT),
|
||||||
FilterMap(data::function::FunctionT),
|
FilterMap(data::function::FunctionT),
|
||||||
|
MapWhile(data::function::FunctionT),
|
||||||
|
Take,
|
||||||
Enumerate,
|
Enumerate,
|
||||||
}
|
}
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -260,6 +257,16 @@ impl MersData for Iter {
|
|||||||
.filter_map(move |v| f.run(v).one_tuple_content()),
|
.filter_map(move |v| f.run(v).one_tuple_content()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Iters::MapWhile(f) => {
|
||||||
|
let f = Clone::clone(f);
|
||||||
|
Box::new(
|
||||||
|
self.1
|
||||||
|
.get()
|
||||||
|
.iterable()?
|
||||||
|
.map_while(move |v| f.run(v).one_tuple_content()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Iters::Take(limit) => Box::new(self.1.get().iterable()?.take(*limit)),
|
||||||
Iters::Enumerate => Box::new(self.1.get().iterable()?.enumerate().map(|(i, v)| {
|
Iters::Enumerate => Box::new(self.1.get().iterable()?.enumerate().map(|(i, v)| {
|
||||||
Data::new(data::tuple::Tuple(vec![
|
Data::new(data::tuple::Tuple(vec![
|
||||||
Data::new(data::int::Int(i as _)),
|
Data::new(data::int::Int(i as _)),
|
||||||
@ -307,6 +314,16 @@ impl IterT {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ItersT::MapWhile(f) => {
|
||||||
|
if let Some(t) = (f.0)(&data)?.one_tuple_possible_content() {
|
||||||
|
t
|
||||||
|
} else {
|
||||||
|
return Err(
|
||||||
|
format!("Iter:MapWhile, but function doesn't return ()/(t).").into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ItersT::Take => data.clone(),
|
||||||
ItersT::Enumerate => Type::new(data::tuple::TupleT(vec![
|
ItersT::Enumerate => Type::new(data::tuple::TupleT(vec![
|
||||||
Type::new(data::int::IntT),
|
Type::new(data::int::IntT),
|
||||||
data.clone(),
|
data.clone(),
|
||||||
@ -360,6 +377,8 @@ impl Iters {
|
|||||||
Self::Map(f) => ItersT::Map(f.get_as_type()),
|
Self::Map(f) => ItersT::Map(f.get_as_type()),
|
||||||
Self::Filter(f) => ItersT::Filter(f.get_as_type()),
|
Self::Filter(f) => ItersT::Filter(f.get_as_type()),
|
||||||
Self::FilterMap(f) => ItersT::FilterMap(f.get_as_type()),
|
Self::FilterMap(f) => ItersT::FilterMap(f.get_as_type()),
|
||||||
|
Self::MapWhile(f) => ItersT::MapWhile(f.get_as_type()),
|
||||||
|
Self::Take(_) => ItersT::Take,
|
||||||
Self::Enumerate => ItersT::Enumerate,
|
Self::Enumerate => ItersT::Enumerate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user