mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 05:43:53 +01:00
show custom type names in error messages
This commit is contained in:
parent
817ed25f96
commit
062f100d40
@ -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 }
|
||||
|
@ -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"
|
||||
|
@ -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<Type> {
|
||||
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<dyn Any> {
|
||||
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 {
|
||||
|
@ -73,6 +73,14 @@ impl MersType for ObjectT {
|
||||
fn to_any(self) -> Box<dyn std::any::Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
fn simplify_for_display(&self, info: &crate::program::run::CheckInfo) -> Option<Type> {
|
||||
Some(Type::new(Self(
|
||||
self.0
|
||||
.iter()
|
||||
.map(|(n, t)| (n.clone(), t.simplify_for_display(info)))
|
||||
.collect(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Object {
|
||||
|
@ -90,6 +90,14 @@ impl MersType for TupleT {
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
fn simplify_for_display(&self, info: &crate::program::run::CheckInfo) -> Option<Type> {
|
||||
Some(Type::new(Self(
|
||||
self.0
|
||||
.iter()
|
||||
.map(|v| v.simplify_for_display(info))
|
||||
.collect(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Tuple {
|
||||
|
@ -320,6 +320,9 @@ impl MersType for ListT {
|
||||
fn to_any(self) -> Box<dyn std::any::Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
fn simplify_for_display(&self, info: &crate::program::run::CheckInfo) -> Option<Type> {
|
||||
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 {
|
||||
|
@ -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),
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
]));
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ impl MersStatement for If {
|
||||
None,
|
||||
),
|
||||
(
|
||||
cond_return_type.to_string(),
|
||||
cond_return_type.simplified_as_string(info),
|
||||
Some(EColor::IfConditionNotBool),
|
||||
),
|
||||
]));
|
||||
|
@ -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::<String>(),
|
||||
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)
|
||||
},
|
||||
|
@ -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(),
|
||||
|
@ -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)
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user