diff --git a/mers_lib/src/data/function.rs b/mers_lib/src/data/function.rs index e63e69f..bd270dc 100755 --- a/mers_lib/src/data/function.rs +++ b/mers_lib/src/data/function.rs @@ -36,6 +36,16 @@ impl Function { pub fn run(&self, arg: Data) -> Data { (self.run)(arg, &mut self.info.as_ref().clone()) } + pub fn get_as_type(&self) -> FunctionT { + let out = Arc::clone(&self.out); + let info = Arc::clone(&self.info_check); + FunctionT(Arc::new(move |a| { + let lock = info.lock().unwrap(); + let mut info = lock.clone(); + drop(lock); + out(a, &mut info) + })) + } } impl MersData for Function { @@ -52,14 +62,7 @@ impl MersData for Function { Box::new(Clone::clone(self)) } fn as_type(&self) -> Type { - let out = Arc::clone(&self.out); - let info = Arc::clone(&self.info_check); - Type::new(FunctionT(Arc::new(move |a| { - let lock = info.lock().unwrap(); - let mut info = lock.clone(); - drop(lock); - out(a, &mut info) - }))) + Type::new(self.get_as_type()) } fn as_any(&self) -> &dyn Any { self diff --git a/mers_lib/src/data/mod.rs b/mers_lib/src/data/mod.rs index 17084c5..fff0c3c 100755 --- a/mers_lib/src/data/mod.rs +++ b/mers_lib/src/data/mod.rs @@ -265,6 +265,27 @@ impl Type { } Some(o) } + /// Returns `Some(d)` if self is `()/(d)` + pub fn one_tuple_possible_content(&self) -> Option { + let mut o = Self::empty(); + let mut nothing = true; + for t in &self.types { + if let Some(t) = t + .as_any() + .downcast_ref::() + .filter(|v| v.0.len() == 1) + .and_then(|v| v.0.get(0)) + { + nothing = false; + o.add(Arc::new(t.clone())); + } + } + if nothing { + None + } else { + Some(o) + } + } pub fn add(&mut self, new: Arc) { let n = new.as_any(); if let Some(s) = n.downcast_ref::() { diff --git a/mers_lib/src/program/configs/with_iters.rs b/mers_lib/src/program/configs/with_iters.rs index 48cd875..16c6d92 100755 --- a/mers_lib/src/program/configs/with_iters.rs +++ b/mers_lib/src/program/configs/with_iters.rs @@ -4,8 +4,11 @@ use std::{ }; use crate::{ - data::{self, Data, MersData, MersType, Type}, - program::{self, run::CheckInfo}, + data::{self, function::FunctionT, Data, MersData, MersType, Type}, + program::{ + self, + run::{CheckError, CheckInfo}, + }, }; use super::Config; @@ -23,7 +26,7 @@ impl Config { 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| { + out: Arc::new(|a, _i| { for a in &a.types { if let Some(tuple) = a.as_any().downcast_ref::() { if let (Some(v), Some(f)) = (tuple.0.get(0), tuple.0.get(1)) { @@ -89,7 +92,9 @@ impl Config { 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| todo!()), + 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::() { if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) { @@ -114,7 +119,9 @@ impl Config { 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| todo!()), + 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::() { if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) { @@ -139,7 +146,9 @@ impl Config { 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| todo!()), + 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::() { if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) { @@ -164,13 +173,46 @@ impl Config { 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| todo!()), + out: Arc::new(|a, _i| { + let data = if let Some(a) = a.iterable() { + a + } else { + return Err(format!("cannot call enumerate on non-iterable type {a}.").into()); + }; + Ok(Type::new(IterT::new(ItersT::Enumerate, data)?)) + }), run: Arc::new(|a, _i| Data::new(Iter(Iters::Enumerate, a.clone()))), }), ) } } +fn iter_out(a: &Type, name: &str, func: impl Fn(&FunctionT) -> ItersT) -> Result { + let mut out = Type::empty(); + for t in a.types.iter() { + if let Some(t) = t.as_any().downcast_ref::() { + if t.0.len() != 2 { + return Err(format!("cannot call {name} on tuple where len != 2").into()); + } + if let Some(v) = t.0[0].iterable() { + for f in t.0[1].types.iter() { + if let Some(f) = f.as_any().downcast_ref::() { + out.add(Arc::new(IterT::new(func(f), v.clone())?)); + } 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()); + } + } + } else { + return Err(format!( + "cannot call {name} on non-iterable type {t}, which is part of {a}." + ) + .into()); + } + } + } + Ok(out) +} + #[derive(Clone, Debug)] pub enum Iters { Map(data::function::Function), @@ -179,9 +221,16 @@ pub enum Iters { Enumerate, } #[derive(Clone, Debug)] +pub enum ItersT { + Map(data::function::FunctionT), + Filter(data::function::FunctionT), + FilterMap(data::function::FunctionT), + Enumerate, +} +#[derive(Clone, Debug)] pub struct Iter(Iters, Data); #[derive(Clone, Debug)] -pub struct IterT(Iters); +pub struct IterT(ItersT, Type, Type); impl MersData for Iter { fn is_eq(&self, _other: &dyn MersData) -> bool { false @@ -223,7 +272,7 @@ impl MersData for Iter { Box::new(Clone::clone(self)) } fn as_type(&self) -> data::Type { - Type::new(IterT(self.0.clone())) + Type::new(IterT::new(self.0.as_type(), self.1.get().as_type()).unwrap()) } fn as_any(&self) -> &dyn std::any::Any { self @@ -235,6 +284,37 @@ impl MersData for Iter { Box::new(self) } } +impl IterT { + pub fn new(iter: ItersT, data: Type) -> Result { + let t = match &iter { + ItersT::Map(f) => (f.0)(&data)?, + ItersT::Filter(f) => { + if (f.0)(&data)?.is_included_in(&data::bool::BoolT) { + data.clone() + } else { + return Err(format!( + "Iter:Filter, but function doesn't return bool for argument {data}." + ) + .into()); + } + } + ItersT::FilterMap(f) => { + if let Some(v) = (f.0)(&data)?.one_tuple_possible_content() { + v + } else { + return Err( + format!("Iter:FilterMap, but function doesn't return ()/(t).").into(), + ); + } + } + ItersT::Enumerate => Type::new(data::tuple::TupleT(vec![ + Type::new(data::int::IntT), + data.clone(), + ])), + }; + Ok(Self(iter, data, t)) + } +} impl MersType for IterT { fn is_same_type_as(&self, other: &dyn MersType) -> bool { false @@ -247,6 +327,9 @@ impl MersType for IterT { false } } + fn iterable(&self) -> Option { + Some(self.2.clone()) + } fn subtypes(&self, acc: &mut Type) { // NOTE: This might not be good enough acc.add(Arc::new(self.clone())); @@ -268,6 +351,16 @@ impl Display for Iter { } impl Display for IterT { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "") + write!(f, "", self.2) + } +} +impl Iters { + fn as_type(&self) -> ItersT { + match self { + Self::Map(f) => ItersT::Map(f.get_as_type()), + Self::Filter(f) => ItersT::Filter(f.get_as_type()), + Self::FilterMap(f) => ItersT::FilterMap(f.get_as_type()), + Self::Enumerate => ItersT::Enumerate, + } } } diff --git a/mers_lib/src/program/run/mod.rs b/mers_lib/src/program/run/mod.rs index 4253392..1c31ddb 100755 --- a/mers_lib/src/program/run/mod.rs +++ b/mers_lib/src/program/run/mod.rs @@ -74,9 +74,9 @@ impl From<(SourcePos, SourcePos)> for SourceRange { } } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct CheckError(Vec); -#[derive(Clone)] +#[derive(Clone, Debug)] enum CheckErrorComponent { Message(String), Error(CheckError),