Added the concept of subtypes ...

... which `try` now uses to avoid some problems with inner types
This commit is contained in:
Mark 2023-10-24 09:31:49 +02:00
parent ea95a16c30
commit 5e20f92849
13 changed files with 111 additions and 13 deletions

View File

@ -1,4 +1,4 @@
use std::{any::Any, fmt::Display}; use std::{any::Any, fmt::Display, sync::Arc};
use super::{MersData, MersType, Type}; use super::{MersData, MersType, Type};
@ -30,7 +30,7 @@ impl MersData for Bool {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct BoolT; pub struct BoolT;
impl MersType for BoolT { impl MersType for BoolT {
fn is_same_type_as(&self, other: &dyn MersType) -> bool { fn is_same_type_as(&self, other: &dyn MersType) -> bool {
@ -39,6 +39,9 @@ impl MersType for BoolT {
fn is_included_in_single(&self, target: &dyn MersType) -> bool { fn is_included_in_single(&self, target: &dyn MersType) -> bool {
self.is_same_type_as(target) self.is_same_type_as(target)
} }
fn subtypes(&self, acc: &mut Type) {
acc.add(Arc::new(self.clone()));
}
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
} }

View File

@ -1,4 +1,4 @@
use std::{any::Any, fmt::Display}; use std::{any::Any, fmt::Display, sync::Arc};
use super::{MersData, MersType, Type}; use super::{MersData, MersType, Type};
@ -30,7 +30,7 @@ impl MersData for Float {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct FloatT; pub struct FloatT;
impl MersType for FloatT { impl MersType for FloatT {
fn is_same_type_as(&self, other: &dyn MersType) -> bool { fn is_same_type_as(&self, other: &dyn MersType) -> bool {
@ -39,6 +39,9 @@ impl MersType for FloatT {
fn is_included_in_single(&self, target: &dyn MersType) -> bool { fn is_included_in_single(&self, target: &dyn MersType) -> bool {
self.is_same_type_as(target) self.is_same_type_as(target)
} }
fn subtypes(&self, acc: &mut Type) {
acc.add(Arc::new(self.clone()));
}
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
} }

View File

@ -72,6 +72,7 @@ impl MersData for Function {
} }
} }
#[derive(Clone)]
pub struct FunctionT(pub Arc<dyn Fn(&Type) -> Result<Type, CheckError> + Send + Sync>); pub struct FunctionT(pub Arc<dyn Fn(&Type) -> Result<Type, CheckError> + Send + Sync>);
impl MersType for FunctionT { impl MersType for FunctionT {
fn iterable(&self) -> Option<Type> { fn iterable(&self) -> Option<Type> {
@ -100,6 +101,9 @@ impl MersType for FunctionT {
fn is_included_in_single(&self, _target: &dyn MersType) -> bool { fn is_included_in_single(&self, _target: &dyn MersType) -> bool {
false false
} }
fn subtypes(&self, acc: &mut Type) {
acc.add(Arc::new(self.clone()));
}
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
} }

View File

@ -1,4 +1,4 @@
use std::{any::Any, fmt::Display}; use std::{any::Any, fmt::Display, sync::Arc};
use super::{MersData, MersType, Type}; use super::{MersData, MersType, Type};
@ -30,7 +30,7 @@ impl MersData for Int {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct IntT; pub struct IntT;
impl MersType for IntT { impl MersType for IntT {
fn is_same_type_as(&self, other: &dyn MersType) -> bool { fn is_same_type_as(&self, other: &dyn MersType) -> bool {
@ -39,6 +39,9 @@ impl MersType for IntT {
fn is_included_in_single(&self, target: &dyn MersType) -> bool { fn is_included_in_single(&self, target: &dyn MersType) -> bool {
self.is_same_type_as(target) self.is_same_type_as(target)
} }
fn subtypes(&self, acc: &mut Type) {
acc.add(Arc::new(self.clone()));
}
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
} }

View File

@ -59,6 +59,20 @@ pub trait MersType: Any + Debug + Display + Send + Sync {
self.is_included_in_single(target) self.is_included_in_single(target)
} }
} }
/// Returns all types that can result from the use of this type.
/// Usually, this is just `acc.add(Arc::new(self.clone()))`
/// but if there exists one or more inner types, this becomes interesting:
/// Using `(int/string)` will end up being either `(int)` or `(string)`,
/// so this function should add `(int)` and `(string)`.
/// Since `(int/string)` can't exist at runtime, we don't need to list `self`.
/// note also: `subtypes` has to be called recursively, i.e. you would have to call `.substring` on `int` and `string`.
fn subtypes(&self, acc: &mut Type);
/// like `subtypes`, but returns the accumulator
fn subtypes_type(&self) -> Type {
let mut acc = Type::empty();
self.subtypes(&mut acc);
acc
}
fn as_any(&self) -> &dyn Any; fn as_any(&self) -> &dyn Any;
fn mut_any(&mut self) -> &mut dyn Any; fn mut_any(&mut self) -> &mut dyn Any;
fn to_any(self) -> Box<dyn Any>; fn to_any(self) -> Box<dyn Any>;
@ -293,6 +307,11 @@ 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 subtypes(&self, acc: &mut Type) {
for t in &self.types {
t.subtypes(acc);
}
}
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
} }

View File

@ -34,7 +34,7 @@ impl MersData for Reference {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct ReferenceT(pub Type); pub struct ReferenceT(pub Type);
impl MersType for ReferenceT { impl MersType for ReferenceT {
fn is_same_type_as(&self, other: &dyn MersType) -> bool { fn is_same_type_as(&self, other: &dyn MersType) -> bool {
@ -48,6 +48,11 @@ impl MersType for ReferenceT {
// &int isn't included in &(int/float), otherwise we could assign a float to it // &int isn't included in &(int/float), otherwise we could assign a float to it
self.is_same_type_as(target) self.is_same_type_as(target)
} }
fn subtypes(&self, acc: &mut Type) {
// we don't call subtypes because (int/string) must stay that so we can assign either
// NOTE: this might not be right...?
acc.add(Arc::new(self.clone()));
}
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
} }

View File

@ -1,4 +1,4 @@
use std::{any::Any, fmt::Display}; use std::{any::Any, fmt::Display, sync::Arc};
use super::{MersData, MersType, Type}; use super::{MersData, MersType, Type};
@ -30,7 +30,7 @@ impl MersData for String {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct StringT; pub struct StringT;
impl MersType for StringT { impl MersType for StringT {
fn is_same_type_as(&self, other: &dyn MersType) -> bool { fn is_same_type_as(&self, other: &dyn MersType) -> bool {
@ -39,6 +39,9 @@ impl MersType for StringT {
fn is_included_in_single(&self, target: &dyn MersType) -> bool { fn is_included_in_single(&self, target: &dyn MersType) -> bool {
self.is_same_type_as(target) self.is_same_type_as(target)
} }
fn subtypes(&self, acc: &mut Type) {
acc.add(Arc::new(self.clone()));
}
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
} }

View File

@ -53,10 +53,31 @@ impl MersType for TupleT {
Some(o) Some(o)
} }
fn is_same_type_as(&self, other: &dyn MersType) -> bool { fn is_same_type_as(&self, other: &dyn MersType) -> bool {
other.as_any().downcast_ref::<Self>().is_some() if let Some(other) = other.as_any().downcast_ref::<Self>() {
self.0.len() == other.0.len()
&& self
.0
.iter()
.zip(other.0.iter())
.all(|(s, o)| s.is_same_type_as(o))
} else {
false
}
} }
fn is_included_in_single(&self, target: &dyn MersType) -> bool { fn is_included_in_single(&self, target: &dyn MersType) -> bool {
self.is_same_type_as(target) if let Some(target) = target.as_any().downcast_ref::<Self>() {
self.0.len() == target.0.len()
&& self
.0
.iter()
.zip(target.0.iter())
.all(|(s, t)| s.is_included_in(t))
} else {
false
}
}
fn subtypes(&self, acc: &mut Type) {
self.gen_subtypes_recursively(acc, &mut Vec::with_capacity(self.0.len()));
} }
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
@ -95,3 +116,23 @@ impl Display for TupleT {
Ok(()) Ok(())
} }
} }
impl TupleT {
pub fn gen_subtypes_recursively(&self, acc: &mut Type, types: &mut Vec<Arc<dyn MersType>>) {
if types.len() >= self.0.len() {
let nt = Self(
types
.iter()
.map(|v| Type::newm(vec![Arc::clone(v)]))
.collect(),
);
acc.add(Arc::new(nt));
} else {
for t in self.0[types.len()].subtypes_type().types {
types.push(t);
self.gen_subtypes_recursively(acc, types);
types.pop();
}
}
}
}

View File

@ -28,7 +28,7 @@ impl Config {
} }
let arg_type = &t.0[0]; let arg_type = &t.0[0];
let functions = &t.0[1]; let functions = &t.0[1];
for arg_type in arg_type.types.iter() { for arg_type in arg_type.subtypes_type().types.iter() {
let arg_type = Type::newm(vec![arg_type.clone()]); let arg_type = Type::newm(vec![arg_type.clone()]);
// possibilities for the tuple (f1, f2, f3, ..., fn) // possibilities for the tuple (f1, f2, f3, ..., fn)
for ft in functions.types.iter() { for ft in functions.types.iter() {

View File

@ -83,7 +83,7 @@ impl Config {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct RunCommandError(String); pub struct RunCommandError(String);
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct RunCommandErrorT; pub struct RunCommandErrorT;
impl MersData for RunCommandError { impl MersData for RunCommandError {
fn is_eq(&self, other: &dyn MersData) -> bool { fn is_eq(&self, other: &dyn MersData) -> bool {
@ -116,6 +116,9 @@ impl MersType for RunCommandErrorT {
fn is_included_in_single(&self, target: &dyn MersType) -> bool { fn is_included_in_single(&self, target: &dyn MersType) -> bool {
self.is_same_type_as(target) self.is_same_type_as(target)
} }
fn subtypes(&self, acc: &mut Type) {
acc.add(Arc::new(self.clone()));
}
fn as_any(&self) -> &dyn std::any::Any { fn as_any(&self) -> &dyn std::any::Any {
self self
} }

View File

@ -247,6 +247,10 @@ impl MersType for IterT {
false false
} }
} }
fn subtypes(&self, acc: &mut Type) {
// NOTE: This might not be good enough
acc.add(Arc::new(self.clone()));
}
fn as_any(&self) -> &dyn std::any::Any { fn as_any(&self) -> &dyn std::any::Any {
self self
} }

View File

@ -201,6 +201,11 @@ impl MersType for ListT {
fn is_included_in_single(&self, target: &dyn MersType) -> bool { fn is_included_in_single(&self, target: &dyn MersType) -> bool {
self.is_same_type_as(target) self.is_same_type_as(target)
} }
fn subtypes(&self, acc: &mut Type) {
for t in self.0.subtypes_type().types {
acc.add(Arc::new(Self(Type::newm(vec![t]))));
}
}
fn as_any(&self) -> &dyn std::any::Any { fn as_any(&self) -> &dyn std::any::Any {
self self
} }

View File

@ -127,6 +127,11 @@ impl MersType for ThreadT {
false false
} }
} }
fn subtypes(&self, acc: &mut Type) {
for t in self.0.subtypes_type().types {
acc.add(Arc::new(Self(Type::newm(vec![t]))));
}
}
fn as_any(&self) -> &dyn std::any::Any { fn as_any(&self) -> &dyn std::any::Any {
self self
} }