mirror of
https://github.com/Dummi26/mers.git
synced 2025-12-14 03:16:15 +01:00
better errors, colors, and fix bug where x := x would panic
This commit is contained in:
@@ -8,8 +8,8 @@ use super::{CompInfo, MersStatement};
|
||||
#[derive(Debug)]
|
||||
pub struct AssignTo {
|
||||
pub pos_in_src: SourceRange,
|
||||
pub target: Box<dyn MersStatement>,
|
||||
pub source: Box<dyn MersStatement>,
|
||||
pub target: Box<dyn MersStatement>,
|
||||
}
|
||||
|
||||
impl MersStatement for AssignTo {
|
||||
@@ -24,8 +24,8 @@ impl MersStatement for AssignTo {
|
||||
Ok(Box::new(program::run::assign_to::AssignTo {
|
||||
pos_in_src: self.pos_in_src,
|
||||
is_init: false,
|
||||
target: self.target.compile(info, comp)?,
|
||||
source: self.source.compile(info, comp)?,
|
||||
target: self.target.compile(info, comp)?,
|
||||
}))
|
||||
}
|
||||
fn source_range(&self) -> SourceRange {
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
info::{self, Local},
|
||||
program::{
|
||||
self,
|
||||
run::{CheckError, SourceRange},
|
||||
run::{error_colors, CheckError, SourceRange},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -31,8 +31,8 @@ impl MersStatement for IncludeMers {
|
||||
Ok(v) => Arc::new(v),
|
||||
Err(e) => {
|
||||
return Err(CheckError::new()
|
||||
.src(vec![(self.pos_in_src, Some(colored::Color::Red))])
|
||||
.msg("Error in inner mers statement! (note: inner errors may refer to a different file)".red().to_string())
|
||||
.src(vec![(self.pos_in_src, Some(error_colors::HashIncludeErrorInIncludedFile))])
|
||||
.msg("Error in inner mers statement! (note: inner errors may refer to a different file)".color(error_colors::HashIncludeErrorInIncludedFile).to_string())
|
||||
.err(e))
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,8 +6,8 @@ use super::{CompInfo, MersStatement};
|
||||
#[derive(Debug)]
|
||||
pub struct InitTo {
|
||||
pub pos_in_src: SourceRange,
|
||||
pub target: Box<dyn MersStatement>,
|
||||
pub source: Box<dyn MersStatement>,
|
||||
pub target: Box<dyn MersStatement>,
|
||||
}
|
||||
|
||||
impl MersStatement for InitTo {
|
||||
@@ -19,15 +19,17 @@ impl MersStatement for InitTo {
|
||||
info: &mut crate::info::Info<super::Local>,
|
||||
mut comp: CompInfo,
|
||||
) -> Result<Box<dyn crate::program::run::MersStatement>, CheckError> {
|
||||
// source must be compiled BEFORE target!
|
||||
comp.is_init = false;
|
||||
let source = self.source.compile(info, comp)?;
|
||||
comp.is_init = true;
|
||||
let target = self.target.compile(info, comp)?;
|
||||
comp.is_init = false;
|
||||
let source = self.source.compile(info, comp)?;
|
||||
Ok(Box::new(program::run::assign_to::AssignTo {
|
||||
pos_in_src: self.pos_in_src,
|
||||
is_init: true,
|
||||
target,
|
||||
source,
|
||||
target,
|
||||
}))
|
||||
}
|
||||
fn source_range(&self) -> SourceRange {
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::{
|
||||
info::Local,
|
||||
program::{
|
||||
self,
|
||||
run::{CheckError, SourceRange},
|
||||
run::{error_colors, CheckError, SourceRange},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -41,7 +41,7 @@ impl MersStatement for Variable {
|
||||
*v
|
||||
} else {
|
||||
return Err(CheckError::new()
|
||||
.src(vec![(self.pos_in_src, Some(colored::Color::Red))])
|
||||
.src(vec![(self.pos_in_src, Some(error_colors::UnknownVariable))])
|
||||
.msg(format!("No variable named '{}' found!", self.var)));
|
||||
},
|
||||
}))
|
||||
|
||||
@@ -2,7 +2,7 @@ use colored::Colorize;
|
||||
|
||||
use crate::data::{self, Data, MersType, Type};
|
||||
|
||||
use super::{CheckError, CheckInfo, MersStatement, SourceRange};
|
||||
use super::{error_colors, CheckError, CheckInfo, MersStatement, SourceRange};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AssignTo {
|
||||
@@ -28,11 +28,8 @@ impl MersStatement for AssignTo {
|
||||
return Err(CheckError::new()
|
||||
.src(vec![
|
||||
(self.pos_in_src, None),
|
||||
(
|
||||
self.target.source_range(),
|
||||
Some(colored::Color::BrightYellow),
|
||||
),
|
||||
(self.source.source_range(), Some(colored::Color::BrightCyan)),
|
||||
(self.target.source_range(), Some(error_colors::InitFrom)),
|
||||
(self.source.source_range(), Some(error_colors::InitTo)),
|
||||
])
|
||||
.msg(format!("Cannot initialize:"))
|
||||
.err(e))
|
||||
@@ -44,16 +41,13 @@ impl MersStatement for AssignTo {
|
||||
return Err(CheckError::new()
|
||||
.src(vec![
|
||||
(self.pos_in_src, None),
|
||||
(
|
||||
self.target.source_range(),
|
||||
Some(colored::Color::BrightYellow),
|
||||
),
|
||||
(self.source.source_range(), Some(colored::Color::BrightCyan)),
|
||||
(self.target.source_range(), Some(error_colors::AssignTo)),
|
||||
(self.source.source_range(), Some(error_colors::AssignFrom)),
|
||||
])
|
||||
.msg(format!(
|
||||
"can't assign {} to {} because it isn't included in {}",
|
||||
source.to_string().bright_cyan(),
|
||||
target.to_string().bright_yellow(),
|
||||
source.to_string().color(error_colors::AssignFrom),
|
||||
target.to_string().color(error_colors::AssignTo),
|
||||
t
|
||||
)));
|
||||
}
|
||||
@@ -61,9 +55,15 @@ impl MersStatement for AssignTo {
|
||||
return Err(CheckError::new()
|
||||
.src(vec![
|
||||
(self.pos_in_src, None),
|
||||
(self.target.source_range(), Some(colored::Color::Red)),
|
||||
(
|
||||
self.target.source_range(),
|
||||
Some(error_colors::AssignTargetNonReference),
|
||||
),
|
||||
])
|
||||
.msg(format!("can't assign to non-reference!")));
|
||||
.msg(format!(
|
||||
"can't assign to {}",
|
||||
"non-reference!".color(error_colors::AssignTargetNonReference)
|
||||
)));
|
||||
}
|
||||
}
|
||||
Ok(Type::empty_tuple())
|
||||
|
||||
@@ -4,7 +4,7 @@ use colored::Colorize;
|
||||
|
||||
use crate::data::{Data, Type};
|
||||
|
||||
use super::{CheckError, MersStatement, SourceRange};
|
||||
use super::{error_colors, CheckError, MersStatement, SourceRange};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Chain {
|
||||
@@ -35,16 +35,16 @@ impl MersStatement for Chain {
|
||||
return Err(CheckError::new()
|
||||
.src(vec![
|
||||
(self.pos_in_src, None),
|
||||
(self.first.source_range(), Some(colored::Color::BrightCyan)),
|
||||
(
|
||||
self.chained.source_range(),
|
||||
Some(colored::Color::BrightMagenta),
|
||||
self.first.source_range(),
|
||||
Some(error_colors::FunctionArgument),
|
||||
),
|
||||
(self.chained.source_range(), Some(error_colors::Function)),
|
||||
])
|
||||
.msg(format!(
|
||||
"Can't call {} with an argument of type {}:",
|
||||
"this function".bright_magenta(),
|
||||
arg.to_string().bright_cyan()
|
||||
"this function".color(error_colors::Function),
|
||||
arg.to_string().color(error_colors::FunctionArgument)
|
||||
))
|
||||
.err(e))
|
||||
}
|
||||
@@ -53,11 +53,14 @@ impl MersStatement for Chain {
|
||||
return Err(CheckError::new()
|
||||
.src(vec![
|
||||
(self.pos_in_src, None),
|
||||
(self.chained.source_range(), Some(colored::Color::BrightRed)),
|
||||
(
|
||||
self.chained.source_range(),
|
||||
Some(error_colors::ChainWithNonFunction),
|
||||
),
|
||||
])
|
||||
.msg(format!(
|
||||
"cannot chain with a non-function ({})",
|
||||
func.to_string().bright_red()
|
||||
func.to_string().color(error_colors::ChainWithNonFunction)
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use colored::Colorize;
|
||||
|
||||
use crate::data::{self, Data, MersType, Type};
|
||||
|
||||
use super::{CheckError, MersStatement, SourceRange};
|
||||
use super::{error_colors, CheckError, MersStatement, SourceRange};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct If {
|
||||
@@ -30,13 +30,15 @@ impl MersStatement for If {
|
||||
(self.pos_in_src, None),
|
||||
(
|
||||
self.condition.source_range(),
|
||||
Some(colored::Color::BrightRed),
|
||||
Some(error_colors::IfConditionNotBool),
|
||||
),
|
||||
])
|
||||
.msg(format!(
|
||||
"The {} in an if-statement must return bool, not {}",
|
||||
"condition".red(),
|
||||
cond_return_type.to_string().bright_red(),
|
||||
"condition".color(error_colors::IfConditionNotBool),
|
||||
cond_return_type
|
||||
.to_string()
|
||||
.color(error_colors::IfConditionNotBool),
|
||||
)));
|
||||
}
|
||||
let mut t = self.on_true.check(info, None)?;
|
||||
|
||||
@@ -84,6 +84,34 @@ impl SourceRange {
|
||||
}
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CheckError(Vec<CheckErrorComponent>);
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub mod error_colors {
|
||||
use colored::Color;
|
||||
|
||||
pub const UnknownVariable: Color = Color::Red;
|
||||
|
||||
pub const WhitespaceAfterHashtag: Color = Color::Red;
|
||||
pub const HashUnknown: Color = Color::Red;
|
||||
pub const HashIncludeCantLoadFile: Color = Color::Red;
|
||||
pub const HashIncludeNotAString: Color = Color::Red;
|
||||
pub const HashIncludeErrorInIncludedFile: Color = Color::Red;
|
||||
|
||||
pub const BackslashEscapeUnknown: Color = Color::Red;
|
||||
pub const BackslashEscapeEOF: Color = Color::Red;
|
||||
pub const StringEOF: Color = Color::Red;
|
||||
|
||||
pub const IfConditionNotBool: Color = Color::Red;
|
||||
pub const ChainWithNonFunction: Color = Color::Yellow;
|
||||
|
||||
pub const Function: Color = Color::BrightMagenta;
|
||||
pub const FunctionArgument: Color = Color::BrightBlue;
|
||||
|
||||
pub const InitFrom: Color = Color::BrightCyan;
|
||||
pub const InitTo: Color = Color::Green;
|
||||
pub const AssignFrom: Color = InitFrom;
|
||||
pub const AssignTo: Color = InitTo;
|
||||
pub const AssignTargetNonReference: Color = Color::BrightYellow;
|
||||
}
|
||||
#[derive(Clone, Debug)]
|
||||
enum CheckErrorComponent {
|
||||
Message(String),
|
||||
|
||||
@@ -4,7 +4,7 @@ use colored::Colorize;
|
||||
|
||||
use crate::data::{self, tuple::TupleT, Data, Type};
|
||||
|
||||
use super::{MersStatement, SourceRange};
|
||||
use super::{error_colors, MersStatement, SourceRange};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Tuple {
|
||||
@@ -21,6 +21,7 @@ impl MersStatement for Tuple {
|
||||
let mut vec = (0..self.elems.len())
|
||||
.map(|_| Type::empty())
|
||||
.collect::<VecDeque<_>>();
|
||||
let print_is_part_of = init_to.types.len() > 1;
|
||||
for t in init_to.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<TupleT>() {
|
||||
if t.0.len() == self.elems.len() {
|
||||
@@ -29,10 +30,19 @@ impl MersStatement for Tuple {
|
||||
}
|
||||
} else {
|
||||
return Err(
|
||||
format!("can't init statement type Tuple with value type {t}, which is part of {init_to} - only tuples with the same length ({}) can be assigned to tuples", self.elems.len()).into());
|
||||
format!("can't init a {} with type {}{} - only tuples with the same length ({}) can be assigned.",
|
||||
"tuple".color(error_colors::InitTo),
|
||||
t.to_string().color(error_colors::InitFrom),
|
||||
if print_is_part_of {
|
||||
format!(", which is part of {}", init_to.to_string().color(error_colors::InitFrom))
|
||||
} else {
|
||||
format!("")
|
||||
},
|
||||
self.elems.len()
|
||||
).into());
|
||||
}
|
||||
} else {
|
||||
return Err(format!("can't init a {} with a value of type {}, which is part of {} - only tuples can be assigned to tuples", "tuple".bright_yellow(), t.to_string().bright_cyan(), init_to.to_string().bright_cyan()).into());
|
||||
return Err(format!("can't init a {} with a value of type {}, which is part of {} - only tuples can be assigned to tuples", "tuple".color(error_colors::InitTo), t.to_string().color(error_colors::InitFrom), init_to.to_string().color(error_colors::InitFrom)).into());
|
||||
}
|
||||
}
|
||||
Some(vec)
|
||||
|
||||
Reference in New Issue
Block a user