diff --git a/mers/Cargo.toml b/mers/Cargo.toml index a994c72..56b276e 100644 --- a/mers/Cargo.toml +++ b/mers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mers" -version = "0.9.1" +version = "0.9.2" edition = "2021" license = "MIT OR Apache-2.0" description = "dynamically typed but type-checked programming language" @@ -15,7 +15,7 @@ default = ["colored-output"] colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"] [dependencies] -# mers_lib = "0.9.1" -mers_lib = { path = "../mers_lib" } +mers_lib = "0.9.2" +# mers_lib = { path = "../mers_lib" } clap = { version = "4.3.19", features = ["derive"] } colored = { version = "2.1.0", optional = true } diff --git a/mers_lib/Cargo.toml b/mers_lib/Cargo.toml index 60eba8b..6122f08 100755 --- a/mers_lib/Cargo.toml +++ b/mers_lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mers_lib" -version = "0.9.1" +version = "0.9.2" edition = "2021" license = "MIT OR Apache-2.0" description = "library to use the mers language in other projects" diff --git a/mers_lib/src/data/mod.rs b/mers_lib/src/data/mod.rs index e40c278..ce3a2c5 100755 --- a/mers_lib/src/data/mod.rs +++ b/mers_lib/src/data/mod.rs @@ -86,6 +86,43 @@ pub trait MersType: Any + Debug + Display + Send + Sync { fn is_reference_to(&self) -> Option<&Type> { None } + /// may mutate `self` to simplify it + #[allow(unused)] + fn simplify_for_display(&self, info: &crate::program::run::CheckInfo) -> Option { + None + } + fn simplified_as_string(&self, info: &crate::program::run::CheckInfo) -> String { + self.simplify_for_display(info) + .map(|s| s.to_string()) + .unwrap_or_else(|| self.to_string()) + } +} +#[derive(Clone, Debug)] +pub(crate) struct TypeWithOnlyName(pub(crate) String); +impl MersType for TypeWithOnlyName { + fn is_same_type_as(&self, _other: &dyn MersType) -> bool { + false + } + fn is_included_in(&self, _target: &dyn MersType) -> bool { + false + } + fn subtypes(&self, acc: &mut Type) { + acc.add(Arc::new(self.clone())) + } + fn as_any(&self) -> &dyn Any { + self + } + fn mut_any(&mut self) -> &mut dyn Any { + self + } + fn to_any(self) -> Box { + Box::new(self) + } +} +impl Display for TypeWithOnlyName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } } #[derive(Debug)] @@ -380,6 +417,38 @@ impl Type { } Some(o) } + pub fn simplify_for_display(&self, info: &crate::program::run::CheckInfo) -> Type { + let mut out = Type::empty(); + 'foreachtype: for ty in &self.types { + // find the outmost type alias that isn't shadowed + for (i, scope) in info.scopes.iter().enumerate() { + if let Some((n, _)) = scope.types.iter().find(|(_, t)| { + t.as_ref() + .is_ok_and(|t| t.is_same_type_as(&Type::newm(vec![Arc::clone(ty)]))) + }) { + if info + .scopes + .iter() + .skip(i + 1) + .all(|scope| !scope.types.contains_key(n)) + { + out.add(Arc::new(TypeWithOnlyName(n.clone()))); + continue 'foreachtype; + } + } + } + // no type alias + if let Some(ty) = ty.simplify_for_display(info) { + out.add_all(&ty); + } else { + out.add(Arc::clone(ty)) + } + } + out + } + pub fn simplified_as_string(&self, info: &crate::program::run::CheckInfo) -> String { + self.simplify_for_display(info).to_string() + } } impl Display for Type { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/mers_lib/src/data/object.rs b/mers_lib/src/data/object.rs index 195dc46..10e0139 100644 --- a/mers_lib/src/data/object.rs +++ b/mers_lib/src/data/object.rs @@ -73,6 +73,14 @@ impl MersType for ObjectT { fn to_any(self) -> Box { Box::new(self) } + fn simplify_for_display(&self, info: &crate::program::run::CheckInfo) -> Option { + Some(Type::new(Self( + self.0 + .iter() + .map(|(n, t)| (n.clone(), t.simplify_for_display(info))) + .collect(), + ))) + } } impl Display for Object { diff --git a/mers_lib/src/data/tuple.rs b/mers_lib/src/data/tuple.rs index 1c28936..353b831 100755 --- a/mers_lib/src/data/tuple.rs +++ b/mers_lib/src/data/tuple.rs @@ -90,6 +90,14 @@ impl MersType for TupleT { fn to_any(self) -> Box { Box::new(self) } + fn simplify_for_display(&self, info: &crate::program::run::CheckInfo) -> Option { + Some(Type::new(Self( + self.0 + .iter() + .map(|v| v.simplify_for_display(info)) + .collect(), + ))) + } } impl Display for Tuple { diff --git a/mers_lib/src/program/configs/with_list.rs b/mers_lib/src/program/configs/with_list.rs index 6184717..9f246e3 100755 --- a/mers_lib/src/program/configs/with_list.rs +++ b/mers_lib/src/program/configs/with_list.rs @@ -320,6 +320,9 @@ impl MersType for ListT { fn to_any(self) -> Box { Box::new(self) } + fn simplify_for_display(&self, info: &crate::program::run::CheckInfo) -> Option { + Some(Type::new(Self(self.0.simplify_for_display(info)))) + } } impl Display for List { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/mers_lib/src/program/run/as_type.rs b/mers_lib/src/program/run/as_type.rs index 7d63219..45ef0a6 100644 --- a/mers_lib/src/program/run/as_type.rs +++ b/mers_lib/src/program/run/as_type.rs @@ -50,10 +50,13 @@ impl MersStatement for AsType { ]) .msg(vec![ ("Type must be included in ".to_owned(), None), - (as_type.to_string(), Some(EColor::AsTypeTypeAnnotation)), + ( + as_type.simplified_as_string(info), + Some(EColor::AsTypeTypeAnnotation), + ), (", but the actual type ".to_owned(), None), ( - return_type.to_string(), + return_type.simplified_as_string(info), Some(EColor::AsTypeStatementWithTooBroadType), ), (" isn't.".to_owned(), None), diff --git a/mers_lib/src/program/run/assign_to.rs b/mers_lib/src/program/run/assign_to.rs index 0295925..06b911f 100755 --- a/mers_lib/src/program/run/assign_to.rs +++ b/mers_lib/src/program/run/assign_to.rs @@ -53,11 +53,11 @@ impl MersStatement for AssignTo { ]) .msg(vec![ ("can't assign ".to_owned(), None), - (source.to_string(), Some(EColor::AssignFrom)), + (source.simplified_as_string(info), Some(EColor::AssignFrom)), (" to ".to_owned(), None), - (target.to_string(), Some(EColor::AssignTo)), + (target.simplified_as_string(info), Some(EColor::AssignTo)), (" because it isn't included in ".to_owned(), None), - (t.to_string(), None), + (t.simplified_as_string(info), None), ])); } } else { diff --git a/mers_lib/src/program/run/chain.rs b/mers_lib/src/program/run/chain.rs index e65cdf5..fbd18b6 100755 --- a/mers_lib/src/program/run/chain.rs +++ b/mers_lib/src/program/run/chain.rs @@ -57,7 +57,10 @@ impl MersStatement for Chain { ("Can't call ".to_owned(), None), ("this function".to_owned(), Some(EColor::Function)), (" with an argument of type ".to_owned(), None), - (arg.to_string(), Some(EColor::FunctionArgument)), + ( + arg.simplified_as_string(info), + Some(EColor::FunctionArgument), + ), (":".to_owned(), None), ]) .err(e) @@ -75,7 +78,10 @@ impl MersStatement for Chain { ]) .msg(vec![ ("cannot chain with a non-function (".to_owned(), None), - (func.to_string(), Some(EColor::ChainWithNonFunction)), + ( + func.simplified_as_string(info), + Some(EColor::ChainWithNonFunction), + ), (")".to_owned(), None), ])); } diff --git a/mers_lib/src/program/run/if.rs b/mers_lib/src/program/run/if.rs index d2ead0a..a89c364 100755 --- a/mers_lib/src/program/run/if.rs +++ b/mers_lib/src/program/run/if.rs @@ -42,7 +42,7 @@ impl MersStatement for If { None, ), ( - cond_return_type.to_string(), + cond_return_type.simplified_as_string(info), Some(EColor::IfConditionNotBool), ), ])); diff --git a/mers_lib/src/program/run/object.rs b/mers_lib/src/program/run/object.rs index b916335..8204f96 100644 --- a/mers_lib/src/program/run/object.rs +++ b/mers_lib/src/program/run/object.rs @@ -1,7 +1,7 @@ use std::collections::VecDeque; use crate::{ - data::{self, object::ObjectT, Data, Type}, + data::{self, object::ObjectT, Data, MersType, Type}, errors::{CheckError, EColor, SourceRange}, }; @@ -33,14 +33,14 @@ impl MersStatement for Object { ("can't init an ".to_owned(), None), ("object".to_owned(), Some(EColor::InitTo)), (" with type ".to_owned(), None), - (t.to_string(), Some(EColor::InitFrom)), + (t.simplified_as_string(info), Some(EColor::InitFrom)), if print_is_part_of { (", which is part of ".to_owned(), None) } else { (String::new(), None) }, if print_is_part_of { - (init_to.to_string(), Some(EColor::InitFrom)) + (init_to.simplified_as_string(info), Some(EColor::InitFrom)) } else { (String::new(), None) }, @@ -57,14 +57,14 @@ impl MersStatement for Object { ("can't init an ".to_owned(), None), ("object".to_owned(), Some(EColor::InitTo)), (" with type ".to_owned(), None), - (t.to_string(), Some(EColor::InitFrom)), + (t.simplified_as_string(info), Some(EColor::InitFrom)), if print_is_part_of { (", which is part of ".to_owned(), None) } else { (format!(""), None) }, if print_is_part_of { - (init_to.to_string(), Some(EColor::InitFrom)) + (init_to.simplified_as_string(info), Some(EColor::InitFrom)) } else { (format!(""), None) }, @@ -83,7 +83,7 @@ impl MersStatement for Object { format!(", {n}: _") }) .collect::(), - data::object::ObjectT(t.0.iter().take(self.elems.len()).cloned().collect()) + data::object::ObjectT(t.0.iter().take(self.elems.len()).cloned().collect()).simplified_as_string(info) ) }, None) ])); @@ -93,14 +93,14 @@ impl MersStatement for Object { ("can't init an ".to_owned(), None), ("object".to_owned(), Some(EColor::InitTo)), (" with type ".to_owned(), None), - (t.to_string(), Some(EColor::InitFrom)), + (t.simplified_as_string(info), Some(EColor::InitFrom)), if print_is_part_of { (", which is part of ".to_owned(), None) } else { (format!(""), None) }, if print_is_part_of { - (init_to.to_string(), Some(EColor::InitFrom)) + (init_to.simplified_as_string(info), Some(EColor::InitFrom)) } else { (format!(""), None) }, diff --git a/mers_lib/src/program/run/try.rs b/mers_lib/src/program/run/try.rs index 31556fb..bcc5dbc 100644 --- a/mers_lib/src/program/run/try.rs +++ b/mers_lib/src/program/run/try.rs @@ -63,8 +63,10 @@ impl MersStatement for Try { } else { return Err(CheckError::new() .msg_str(format!( - "try: #{} is not a function, type is {ft} within {func}.", - i + 1 + "try: #{} is not a function, type is {} within {}.", + i + 1, + ft.simplified_as_string(info), + func.simplify_for_display(info), )) .src(vec![ (self.source_range(), None), @@ -86,7 +88,8 @@ impl MersStatement for Try { if !found { let mut err = CheckError::new() .msg_str(format!( - "try: no function found for argument of type {arg}." + "try: no function found for argument of type {}.", + arg.simplified_as_string(info) )) .src(vec![( self.pos_in_src.clone(), diff --git a/mers_lib/src/program/run/tuple.rs b/mers_lib/src/program/run/tuple.rs index 8a1a7d9..ae19a51 100755 --- a/mers_lib/src/program/run/tuple.rs +++ b/mers_lib/src/program/run/tuple.rs @@ -1,7 +1,7 @@ use std::collections::VecDeque; use crate::{ - data::{self, tuple::TupleT, Data, Type}, + data::{self, tuple::TupleT, Data, MersType, Type}, errors::{CheckError, EColor, SourceRange}, }; @@ -34,7 +34,7 @@ impl MersStatement for Tuple { ("can't init a ".to_owned(), None), ("tuple".to_owned(), Some(EColor::InitTo)), (" with type ".to_owned(), None), - (t.to_string(), Some(EColor::InitFrom)), + (t.simplified_as_string(info), Some(EColor::InitFrom)), ( if print_is_part_of { ", which is part of ".to_owned() @@ -44,7 +44,7 @@ impl MersStatement for Tuple { None, ), if print_is_part_of { - (init_to.to_string(), Some(EColor::InitFrom)) + (init_to.simplified_as_string(info), Some(EColor::InitFrom)) } else { (String::new(), None) }, @@ -62,7 +62,7 @@ impl MersStatement for Tuple { ("can't init a ".to_owned(), None), ("tuple".to_owned(), Some(EColor::InitTo)), (" with type ".to_owned(), None), - (t.to_string(), Some(EColor::InitFrom)), + (t.simplified_as_string(info), Some(EColor::InitFrom)), ( if print_is_part_of { ", which is part of ".to_owned() @@ -72,7 +72,7 @@ impl MersStatement for Tuple { None, ), if print_is_part_of { - (init_to.to_string(), Some(EColor::InitFrom)) + (init_to.simplified_as_string(info), Some(EColor::InitFrom)) } else { (String::new(), None) },