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]
|
[package]
|
||||||
name = "mers"
|
name = "mers"
|
||||||
version = "0.9.1"
|
version = "0.9.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
description = "dynamically typed but type-checked programming language"
|
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"]
|
colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# mers_lib = "0.9.1"
|
mers_lib = "0.9.2"
|
||||||
mers_lib = { path = "../mers_lib" }
|
# mers_lib = { path = "../mers_lib" }
|
||||||
clap = { version = "4.3.19", features = ["derive"] }
|
clap = { version = "4.3.19", features = ["derive"] }
|
||||||
colored = { version = "2.1.0", optional = true }
|
colored = { version = "2.1.0", optional = true }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mers_lib"
|
name = "mers_lib"
|
||||||
version = "0.9.1"
|
version = "0.9.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
description = "library to use the mers language in other projects"
|
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> {
|
fn is_reference_to(&self) -> Option<&Type> {
|
||||||
None
|
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)]
|
#[derive(Debug)]
|
||||||
@ -380,6 +417,38 @@ impl Type {
|
|||||||
}
|
}
|
||||||
Some(o)
|
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 {
|
impl Display for Type {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
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> {
|
fn to_any(self) -> Box<dyn std::any::Any> {
|
||||||
Box::new(self)
|
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 {
|
impl Display for Object {
|
||||||
|
@ -90,6 +90,14 @@ impl MersType for TupleT {
|
|||||||
fn to_any(self) -> Box<dyn Any> {
|
fn to_any(self) -> Box<dyn Any> {
|
||||||
Box::new(self)
|
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 {
|
impl Display for Tuple {
|
||||||
|
@ -320,6 +320,9 @@ impl MersType for ListT {
|
|||||||
fn to_any(self) -> Box<dyn std::any::Any> {
|
fn to_any(self) -> Box<dyn std::any::Any> {
|
||||||
Box::new(self)
|
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 {
|
impl Display for List {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
@ -50,10 +50,13 @@ impl MersStatement for AsType {
|
|||||||
])
|
])
|
||||||
.msg(vec![
|
.msg(vec![
|
||||||
("Type must be included in ".to_owned(), None),
|
("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),
|
(", but the actual type ".to_owned(), None),
|
||||||
(
|
(
|
||||||
return_type.to_string(),
|
return_type.simplified_as_string(info),
|
||||||
Some(EColor::AsTypeStatementWithTooBroadType),
|
Some(EColor::AsTypeStatementWithTooBroadType),
|
||||||
),
|
),
|
||||||
(" isn't.".to_owned(), None),
|
(" isn't.".to_owned(), None),
|
||||||
|
@ -53,11 +53,11 @@ impl MersStatement for AssignTo {
|
|||||||
])
|
])
|
||||||
.msg(vec![
|
.msg(vec![
|
||||||
("can't assign ".to_owned(), None),
|
("can't assign ".to_owned(), None),
|
||||||
(source.to_string(), Some(EColor::AssignFrom)),
|
(source.simplified_as_string(info), Some(EColor::AssignFrom)),
|
||||||
(" to ".to_owned(), None),
|
(" 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),
|
(" because it isn't included in ".to_owned(), None),
|
||||||
(t.to_string(), None),
|
(t.simplified_as_string(info), None),
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -57,7 +57,10 @@ impl MersStatement for Chain {
|
|||||||
("Can't call ".to_owned(), None),
|
("Can't call ".to_owned(), None),
|
||||||
("this function".to_owned(), Some(EColor::Function)),
|
("this function".to_owned(), Some(EColor::Function)),
|
||||||
(" with an argument of type ".to_owned(), None),
|
(" 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),
|
(":".to_owned(), None),
|
||||||
])
|
])
|
||||||
.err(e)
|
.err(e)
|
||||||
@ -75,7 +78,10 @@ impl MersStatement for Chain {
|
|||||||
])
|
])
|
||||||
.msg(vec![
|
.msg(vec![
|
||||||
("cannot chain with a non-function (".to_owned(), None),
|
("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),
|
(")".to_owned(), None),
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ impl MersStatement for If {
|
|||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
cond_return_type.to_string(),
|
cond_return_type.simplified_as_string(info),
|
||||||
Some(EColor::IfConditionNotBool),
|
Some(EColor::IfConditionNotBool),
|
||||||
),
|
),
|
||||||
]));
|
]));
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{self, object::ObjectT, Data, Type},
|
data::{self, object::ObjectT, Data, MersType, Type},
|
||||||
errors::{CheckError, EColor, SourceRange},
|
errors::{CheckError, EColor, SourceRange},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -33,14 +33,14 @@ impl MersStatement for Object {
|
|||||||
("can't init an ".to_owned(), None),
|
("can't init an ".to_owned(), None),
|
||||||
("object".to_owned(), Some(EColor::InitTo)),
|
("object".to_owned(), Some(EColor::InitTo)),
|
||||||
(" with type ".to_owned(), None),
|
(" with type ".to_owned(), None),
|
||||||
(t.to_string(), Some(EColor::InitFrom)),
|
(t.simplified_as_string(info), Some(EColor::InitFrom)),
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
(", which is part of ".to_owned(), None)
|
(", which is part of ".to_owned(), None)
|
||||||
} else {
|
} else {
|
||||||
(String::new(), None)
|
(String::new(), None)
|
||||||
},
|
},
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
(init_to.to_string(), Some(EColor::InitFrom))
|
(init_to.simplified_as_string(info), Some(EColor::InitFrom))
|
||||||
} else {
|
} else {
|
||||||
(String::new(), None)
|
(String::new(), None)
|
||||||
},
|
},
|
||||||
@ -57,14 +57,14 @@ impl MersStatement for Object {
|
|||||||
("can't init an ".to_owned(), None),
|
("can't init an ".to_owned(), None),
|
||||||
("object".to_owned(), Some(EColor::InitTo)),
|
("object".to_owned(), Some(EColor::InitTo)),
|
||||||
(" with type ".to_owned(), None),
|
(" with type ".to_owned(), None),
|
||||||
(t.to_string(), Some(EColor::InitFrom)),
|
(t.simplified_as_string(info), Some(EColor::InitFrom)),
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
(", which is part of ".to_owned(), None)
|
(", which is part of ".to_owned(), None)
|
||||||
} else {
|
} else {
|
||||||
(format!(""), None)
|
(format!(""), None)
|
||||||
},
|
},
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
(init_to.to_string(), Some(EColor::InitFrom))
|
(init_to.simplified_as_string(info), Some(EColor::InitFrom))
|
||||||
} else {
|
} else {
|
||||||
(format!(""), None)
|
(format!(""), None)
|
||||||
},
|
},
|
||||||
@ -83,7 +83,7 @@ impl MersStatement for Object {
|
|||||||
format!(", {n}: _")
|
format!(", {n}: _")
|
||||||
})
|
})
|
||||||
.collect::<String>(),
|
.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)
|
}, None)
|
||||||
]));
|
]));
|
||||||
@ -93,14 +93,14 @@ impl MersStatement for Object {
|
|||||||
("can't init an ".to_owned(), None),
|
("can't init an ".to_owned(), None),
|
||||||
("object".to_owned(), Some(EColor::InitTo)),
|
("object".to_owned(), Some(EColor::InitTo)),
|
||||||
(" with type ".to_owned(), None),
|
(" with type ".to_owned(), None),
|
||||||
(t.to_string(), Some(EColor::InitFrom)),
|
(t.simplified_as_string(info), Some(EColor::InitFrom)),
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
(", which is part of ".to_owned(), None)
|
(", which is part of ".to_owned(), None)
|
||||||
} else {
|
} else {
|
||||||
(format!(""), None)
|
(format!(""), None)
|
||||||
},
|
},
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
(init_to.to_string(), Some(EColor::InitFrom))
|
(init_to.simplified_as_string(info), Some(EColor::InitFrom))
|
||||||
} else {
|
} else {
|
||||||
(format!(""), None)
|
(format!(""), None)
|
||||||
},
|
},
|
||||||
|
@ -63,8 +63,10 @@ impl MersStatement for Try {
|
|||||||
} else {
|
} else {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.msg_str(format!(
|
.msg_str(format!(
|
||||||
"try: #{} is not a function, type is {ft} within {func}.",
|
"try: #{} is not a function, type is {} within {}.",
|
||||||
i + 1
|
i + 1,
|
||||||
|
ft.simplified_as_string(info),
|
||||||
|
func.simplify_for_display(info),
|
||||||
))
|
))
|
||||||
.src(vec![
|
.src(vec![
|
||||||
(self.source_range(), None),
|
(self.source_range(), None),
|
||||||
@ -86,7 +88,8 @@ impl MersStatement for Try {
|
|||||||
if !found {
|
if !found {
|
||||||
let mut err = CheckError::new()
|
let mut err = CheckError::new()
|
||||||
.msg_str(format!(
|
.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![(
|
.src(vec![(
|
||||||
self.pos_in_src.clone(),
|
self.pos_in_src.clone(),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{self, tuple::TupleT, Data, Type},
|
data::{self, tuple::TupleT, Data, MersType, Type},
|
||||||
errors::{CheckError, EColor, SourceRange},
|
errors::{CheckError, EColor, SourceRange},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ impl MersStatement for Tuple {
|
|||||||
("can't init a ".to_owned(), None),
|
("can't init a ".to_owned(), None),
|
||||||
("tuple".to_owned(), Some(EColor::InitTo)),
|
("tuple".to_owned(), Some(EColor::InitTo)),
|
||||||
(" with type ".to_owned(), None),
|
(" with type ".to_owned(), None),
|
||||||
(t.to_string(), Some(EColor::InitFrom)),
|
(t.simplified_as_string(info), Some(EColor::InitFrom)),
|
||||||
(
|
(
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
", which is part of ".to_owned()
|
", which is part of ".to_owned()
|
||||||
@ -44,7 +44,7 @@ impl MersStatement for Tuple {
|
|||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
(init_to.to_string(), Some(EColor::InitFrom))
|
(init_to.simplified_as_string(info), Some(EColor::InitFrom))
|
||||||
} else {
|
} else {
|
||||||
(String::new(), None)
|
(String::new(), None)
|
||||||
},
|
},
|
||||||
@ -62,7 +62,7 @@ impl MersStatement for Tuple {
|
|||||||
("can't init a ".to_owned(), None),
|
("can't init a ".to_owned(), None),
|
||||||
("tuple".to_owned(), Some(EColor::InitTo)),
|
("tuple".to_owned(), Some(EColor::InitTo)),
|
||||||
(" with type ".to_owned(), None),
|
(" with type ".to_owned(), None),
|
||||||
(t.to_string(), Some(EColor::InitFrom)),
|
(t.simplified_as_string(info), Some(EColor::InitFrom)),
|
||||||
(
|
(
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
", which is part of ".to_owned()
|
", which is part of ".to_owned()
|
||||||
@ -72,7 +72,7 @@ impl MersStatement for Tuple {
|
|||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
(init_to.to_string(), Some(EColor::InitFrom))
|
(init_to.simplified_as_string(info), Some(EColor::InitFrom))
|
||||||
} else {
|
} else {
|
||||||
(String::new(), None)
|
(String::new(), None)
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user