fix todo!()s in with_iters

This commit is contained in:
Mark 2023-10-27 17:09:48 +02:00
parent 36e0f69d0c
commit cb52c961a2
4 changed files with 137 additions and 20 deletions

View File

@ -36,6 +36,16 @@ impl Function {
pub fn run(&self, arg: Data) -> Data { pub fn run(&self, arg: Data) -> Data {
(self.run)(arg, &mut self.info.as_ref().clone()) (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 { impl MersData for Function {
@ -52,14 +62,7 @@ impl MersData for Function {
Box::new(Clone::clone(self)) Box::new(Clone::clone(self))
} }
fn as_type(&self) -> Type { fn as_type(&self) -> Type {
let out = Arc::clone(&self.out); Type::new(self.get_as_type())
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)
})))
} }
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self

View File

@ -265,6 +265,27 @@ impl Type {
} }
Some(o) Some(o)
} }
/// Returns `Some(d)` if self is `()/(d)`
pub fn one_tuple_possible_content(&self) -> Option<Type> {
let mut o = Self::empty();
let mut nothing = true;
for t in &self.types {
if let Some(t) = t
.as_any()
.downcast_ref::<crate::data::tuple::TupleT>()
.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<dyn MersType>) { pub fn add(&mut self, new: Arc<dyn MersType>) {
let n = new.as_any(); let n = new.as_any();
if let Some(s) = n.downcast_ref::<Self>() { if let Some(s) = n.downcast_ref::<Self>() {

View File

@ -4,8 +4,11 @@ use std::{
}; };
use crate::{ use crate::{
data::{self, Data, MersData, MersType, Type}, data::{self, function::FunctionT, Data, MersData, MersType, Type},
program::{self, run::CheckInfo}, program::{
self,
run::{CheckError, CheckInfo},
},
}; };
use super::Config; use super::Config;
@ -23,7 +26,7 @@ impl Config {
Data::new(data::function::Function { 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| {
for a in &a.types { for a in &a.types {
if let Some(tuple) = a.as_any().downcast_ref::<data::tuple::TupleT>() { if let Some(tuple) = a.as_any().downcast_ref::<data::tuple::TupleT>() {
if let (Some(v), Some(f)) = (tuple.0.get(0), tuple.0.get(1)) { 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 { 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| todo!()), out: Arc::new(|a, _i| {
iter_out(a, "map", |f| ItersT::Map(f.clone()))
}),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() { 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(v), Some(f)) = (tuple.get(0), tuple.get(1)) {
@ -114,7 +119,9 @@ impl Config {
Data::new(data::function::Function { 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| todo!()), out: Arc::new(|a, _i| {
iter_out(a, "filter", |f| ItersT::Filter(f.clone()))
}),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() { 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(v), Some(f)) = (tuple.get(0), tuple.get(1)) {
@ -139,7 +146,9 @@ impl Config {
Data::new(data::function::Function { 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| todo!()), out: Arc::new(|a, _i| {
iter_out(a, "filter_map", |f| ItersT::FilterMap(f.clone()))
}),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() { 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(v), Some(f)) = (tuple.get(0), tuple.get(1)) {
@ -164,13 +173,46 @@ impl Config {
Data::new(data::function::Function { 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| 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()))), 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<Type, CheckError> {
let mut out = Type::empty();
for t in a.types.iter() {
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
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::<data::function::FunctionT>() {
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)] #[derive(Clone, Debug)]
pub enum Iters { pub enum Iters {
Map(data::function::Function), Map(data::function::Function),
@ -179,9 +221,16 @@ pub enum Iters {
Enumerate, Enumerate,
} }
#[derive(Clone, Debug)] #[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); pub struct Iter(Iters, Data);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct IterT(Iters); pub struct IterT(ItersT, Type, Type);
impl MersData for Iter { impl MersData for Iter {
fn is_eq(&self, _other: &dyn MersData) -> bool { fn is_eq(&self, _other: &dyn MersData) -> bool {
false false
@ -223,7 +272,7 @@ impl MersData for Iter {
Box::new(Clone::clone(self)) Box::new(Clone::clone(self))
} }
fn as_type(&self) -> data::Type { 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 { fn as_any(&self) -> &dyn std::any::Any {
self self
@ -235,6 +284,37 @@ impl MersData for Iter {
Box::new(self) Box::new(self)
} }
} }
impl IterT {
pub fn new(iter: ItersT, data: Type) -> Result<Self, CheckError> {
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 { impl MersType for IterT {
fn is_same_type_as(&self, other: &dyn MersType) -> bool { fn is_same_type_as(&self, other: &dyn MersType) -> bool {
false false
@ -247,6 +327,9 @@ impl MersType for IterT {
false false
} }
} }
fn iterable(&self) -> Option<Type> {
Some(self.2.clone())
}
fn subtypes(&self, acc: &mut Type) { fn subtypes(&self, acc: &mut Type) {
// NOTE: This might not be good enough // NOTE: This might not be good enough
acc.add(Arc::new(self.clone())); acc.add(Arc::new(self.clone()));
@ -268,6 +351,16 @@ impl Display for Iter {
} }
impl Display for IterT { impl Display for IterT {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "<Iter>") write!(f, "<Iter: {}>", 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,
}
} }
} }

View File

@ -74,9 +74,9 @@ impl From<(SourcePos, SourcePos)> for SourceRange {
} }
} }
} }
#[derive(Clone)] #[derive(Clone, Debug)]
pub struct CheckError(Vec<CheckErrorComponent>); pub struct CheckError(Vec<CheckErrorComponent>);
#[derive(Clone)] #[derive(Clone, Debug)]
enum CheckErrorComponent { enum CheckErrorComponent {
Message(String), Message(String),
Error(CheckError), Error(CheckError),