mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
add support for custom theming in mers errors
this also includes support for the NoTheme, a theme which doesn't add any color to mers' output. If you compile mers with --no-default-features, the `colored` dependency will disappear and mers_lib will fall back to NoTheme.
This commit is contained in:
parent
f055d2089f
commit
a78367f27c
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mers"
|
name = "mers"
|
||||||
version = "0.8.13"
|
version = "0.8.14"
|
||||||
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"
|
||||||
@ -10,8 +10,12 @@ repository = "https://github.com/Dummi26/mers"
|
|||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["colored-output"]
|
||||||
|
colored-output = ["mers_lib/ecolor-term", "dep:colored"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
mers_lib = "0.8.13"
|
# mers_lib = "0.8.14"
|
||||||
# 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 = "2.1.0"
|
colored = { version = "2.1.0", optional = true }
|
||||||
|
@ -3,6 +3,7 @@ use mers_lib::prelude_compile::*;
|
|||||||
use std::{path::PathBuf, process::exit, sync::Arc};
|
use std::{path::PathBuf, process::exit, sync::Arc};
|
||||||
|
|
||||||
mod cfg_globals;
|
mod cfg_globals;
|
||||||
|
#[cfg(feature = "colored-output")]
|
||||||
mod pretty_print;
|
mod pretty_print;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
@ -35,7 +36,14 @@ enum Command {
|
|||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
source: From,
|
source: From,
|
||||||
},
|
},
|
||||||
|
/// Not available, because the colored-output default feature was disabled when building mers!
|
||||||
|
#[cfg(not(feature = "colored-output"))]
|
||||||
|
PrettyPrint {
|
||||||
|
#[command(subcommand)]
|
||||||
|
source: From,
|
||||||
|
},
|
||||||
/// Add syntax highlighting to the code
|
/// Add syntax highlighting to the code
|
||||||
|
#[cfg(feature = "colored-output")]
|
||||||
PrettyPrint {
|
PrettyPrint {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
source: From,
|
source: From,
|
||||||
@ -82,19 +90,19 @@ fn main() {
|
|||||||
let srca = Arc::new(src.clone());
|
let srca = Arc::new(src.clone());
|
||||||
match parse(&mut src, &srca) {
|
match parse(&mut src, &srca) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{e}");
|
eprintln!("{e:?}");
|
||||||
exit(20);
|
exit(20);
|
||||||
}
|
}
|
||||||
Ok(parsed) => {
|
Ok(parsed) => {
|
||||||
let (i1, _, i3) = config.infos();
|
let (i1, _, i3) = config.infos();
|
||||||
match compile(&*parsed, i1) {
|
match compile(&*parsed, i1) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{e}");
|
eprintln!("{e:?}");
|
||||||
exit(24);
|
exit(24);
|
||||||
}
|
}
|
||||||
Ok(compiled) => match check(&*compiled, i3) {
|
Ok(compiled) => match check(&*compiled, i3) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{e}");
|
eprintln!("{e:?}");
|
||||||
exit(28);
|
exit(28);
|
||||||
}
|
}
|
||||||
Ok(output_type) => eprintln!("{output_type}"),
|
Ok(output_type) => eprintln!("{output_type}"),
|
||||||
@ -108,24 +116,24 @@ fn main() {
|
|||||||
let srca = Arc::new(src.clone());
|
let srca = Arc::new(src.clone());
|
||||||
match parse(&mut src, &srca) {
|
match parse(&mut src, &srca) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{e}");
|
eprintln!("{e:?}");
|
||||||
exit(255);
|
exit(255);
|
||||||
}
|
}
|
||||||
Ok(parsed) => {
|
Ok(parsed) => {
|
||||||
let (i1, mut i2, i3) = config.infos();
|
let (i1, mut i2, i3) = config.infos();
|
||||||
match compile(&*parsed, i1) {
|
match compile(&*parsed, i1) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{e}");
|
eprintln!("{e:?}");
|
||||||
exit(255);
|
exit(255);
|
||||||
}
|
}
|
||||||
Ok(compiled) => match check(&*compiled, i3) {
|
Ok(compiled) => match check(&*compiled, i3) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{e}");
|
eprintln!("{e:?}");
|
||||||
exit(255);
|
exit(255);
|
||||||
}
|
}
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
if let Err(e) = compiled.run(&mut i2) {
|
if let Err(e) = compiled.run(&mut i2) {
|
||||||
eprintln!("Error while running:\n{e}");
|
eprintln!("Error while running:\n{e:?}");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,19 +147,19 @@ fn main() {
|
|||||||
let srca = Arc::new(src.clone());
|
let srca = Arc::new(src.clone());
|
||||||
match parse(&mut src, &srca) {
|
match parse(&mut src, &srca) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{e}");
|
eprintln!("{e:?}");
|
||||||
exit(255);
|
exit(255);
|
||||||
}
|
}
|
||||||
Ok(parsed) => {
|
Ok(parsed) => {
|
||||||
let (i1, mut i2, _) = config.infos();
|
let (i1, mut i2, _) = config.infos();
|
||||||
match compile(&*parsed, i1) {
|
match compile(&*parsed, i1) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{e}");
|
eprintln!("{e:?}");
|
||||||
exit(255);
|
exit(255);
|
||||||
}
|
}
|
||||||
Ok(compiled) => {
|
Ok(compiled) => {
|
||||||
if let Err(e) = compiled.run(&mut i2) {
|
if let Err(e) = compiled.run(&mut i2) {
|
||||||
eprintln!("Error while running:\n{e}");
|
eprintln!("Error while running:\n{e:?}");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,8 +167,14 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "colored-output")]
|
||||||
Command::PrettyPrint { source } => {
|
Command::PrettyPrint { source } => {
|
||||||
pretty_print::pretty_print(get_source(source));
|
pretty_print::pretty_print(get_source(source));
|
||||||
}
|
}
|
||||||
|
#[cfg(not(feature = "colored-output"))]
|
||||||
|
Command::PrettyPrint { source: _ } => {
|
||||||
|
eprintln!("feature colored-output must be enabled when compiling mers if you want to use pretty-print!");
|
||||||
|
std::process::exit(180);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ pub fn pretty_print(mut src: Source) {
|
|||||||
let srca = Arc::new(src.clone());
|
let srca = Arc::new(src.clone());
|
||||||
match parse(&mut src, &srca) {
|
match parse(&mut src, &srca) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{e}");
|
eprintln!("{e:?}");
|
||||||
exit(28);
|
exit(28);
|
||||||
}
|
}
|
||||||
Ok(parsed) => {
|
Ok(parsed) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mers_lib"
|
name = "mers_lib"
|
||||||
version = "0.8.13"
|
version = "0.8.14"
|
||||||
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"
|
||||||
@ -10,9 +10,14 @@ repository = "https://github.com/Dummi26/mers"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["parse"]
|
default = ["parse"]
|
||||||
|
|
||||||
|
# for parsing and running mers code (for most situations: just enable parse)
|
||||||
parse = ["run"]
|
parse = ["run"]
|
||||||
run = []
|
run = []
|
||||||
|
|
||||||
|
# color features are used when formatting error messages.
|
||||||
|
ecolor-term = ["dep:colored"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
colored = "2.0.4"
|
colored = { version = "2.0.4", optional = true }
|
||||||
line-span = "0.1.5"
|
line-span = "0.1.5"
|
||||||
|
@ -24,7 +24,7 @@ fn show(src: String) {
|
|||||||
);
|
);
|
||||||
eprintln!("{src}");
|
eprintln!("{src}");
|
||||||
match parse_compile_check_run(src) {
|
match parse_compile_check_run(src) {
|
||||||
Err(e) => eprintln!("{e}"),
|
Err(e) => eprintln!("{e:?}"),
|
||||||
Ok((t, v)) => eprintln!("Returned `{}` :: `{t}`", v.get()),
|
Ok((t, v)) => eprintln!("Returned `{}` :: `{t}`", v.get()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ fn main() {
|
|||||||
|
|
||||||
eprintln!("This is not:");
|
eprintln!("This is not:");
|
||||||
let e = run("5.rust_func".to_owned()).err().unwrap();
|
let e = run("5.rust_func".to_owned()).err().unwrap();
|
||||||
eprintln!("{e}");
|
eprintln!("{e:?}");
|
||||||
}
|
}
|
||||||
fn run(src: String) -> Result<(), CheckError> {
|
fn run(src: String) -> Result<(), CheckError> {
|
||||||
let mut source = Source::new_from_string(src);
|
let mut source = Source::new_from_string(src);
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
sync::{atomic::AtomicUsize, Arc},
|
sync::{atomic::AtomicU32, Arc},
|
||||||
};
|
};
|
||||||
|
|
||||||
use colored::{ColoredString, Colorize};
|
|
||||||
use line_span::LineSpans;
|
use line_span::LineSpans;
|
||||||
|
|
||||||
#[cfg(feature = "parse")]
|
#[cfg(feature = "parse")]
|
||||||
@ -44,65 +43,169 @@ impl SourceRange {
|
|||||||
&self.in_file
|
&self.in_file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// To `Display` this, use one of the `display` methods to get a struct with some configuration options.
|
||||||
|
/// The `Debug` impl of this is the same as `Display`ing `this.display_term()` or `this.display_notheme()`, depending on if the `ecolor-term` feature is enabled or not.
|
||||||
|
/// Since this may use ansi color codes, it should only be used when printing to a terminal, which is why `CheckError` itself has no `Display` implementation, only this one for `Debug`.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CheckError(pub Vec<CheckErrorComponent>);
|
pub struct CheckError(pub Vec<CheckErrorComponent>);
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
pub mod error_colors {
|
|
||||||
use colored::Color;
|
|
||||||
|
|
||||||
pub const UnknownVariable: Color = Color::Red;
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum EColor {
|
||||||
|
Indent(u32),
|
||||||
|
|
||||||
pub const WhitespaceAfterHashtag: Color = Color::Red;
|
UnknownVariable,
|
||||||
pub const HashUnknown: Color = Color::Red;
|
WhitespaceAfterHashtag,
|
||||||
pub const HashIncludeCantLoadFile: Color = Color::Red;
|
HashUnknown,
|
||||||
pub const HashIncludeNotAString: Color = Color::Red;
|
HashIncludeCantLoadFile,
|
||||||
pub const HashIncludeErrorInIncludedFile: Color = Color::Red;
|
HashIncludeNotAString,
|
||||||
|
HashIncludeErrorInIncludedFile,
|
||||||
|
BackslashEscapeUnknown,
|
||||||
|
BackslashEscapeEOF,
|
||||||
|
StringEOF,
|
||||||
|
IfConditionNotBool,
|
||||||
|
ChainWithNonFunction,
|
||||||
|
Function,
|
||||||
|
FunctionArgument,
|
||||||
|
InitFrom,
|
||||||
|
InitTo,
|
||||||
|
AssignFrom,
|
||||||
|
AssignTo,
|
||||||
|
AssignTargetNonReference,
|
||||||
|
AsTypeStatementWithTooBroadType,
|
||||||
|
AsTypeTypeAnnotation,
|
||||||
|
BadCharInTupleType,
|
||||||
|
BadCharInFunctionType,
|
||||||
|
BadTypeFromParsed,
|
||||||
|
TypeAnnotationNoClosingBracket,
|
||||||
|
TryBadSyntax,
|
||||||
|
TryNoFunctionFound,
|
||||||
|
TryNotAFunction,
|
||||||
|
TryUnusedFunction1,
|
||||||
|
TryUnusedFunction2,
|
||||||
|
CustomTypeTestFailed,
|
||||||
|
|
||||||
pub const BackslashEscapeUnknown: Color = Color::Red;
|
StacktraceDescend,
|
||||||
pub const BackslashEscapeEOF: Color = Color::Red;
|
StacktraceDescendHashInclude,
|
||||||
pub const StringEOF: Color = Color::Red;
|
|
||||||
|
|
||||||
pub const IfConditionNotBool: Color = Color::Red;
|
MaximumRuntimeExceeded,
|
||||||
pub const ChainWithNonFunction: Color = Color::Yellow;
|
|
||||||
|
|
||||||
pub const Function: Color = Color::BrightMagenta;
|
InCodePositionLine,
|
||||||
pub const FunctionArgument: Color = Color::BrightBlue;
|
}
|
||||||
|
|
||||||
pub const InitFrom: Color = Color::BrightCyan;
|
pub trait Theme<T> {
|
||||||
pub const InitTo: Color = Color::Green;
|
fn color(&self, text: &str, color: EColor, t: &mut T);
|
||||||
pub const AssignFrom: Color = InitFrom;
|
}
|
||||||
pub const AssignTo: Color = InitTo;
|
pub trait ThemeTo<T>: Theme<T> {
|
||||||
pub const AssignTargetNonReference: Color = Color::BrightYellow;
|
fn color_to(&self, text: &str, color: EColor) -> T;
|
||||||
|
}
|
||||||
|
impl<T: Theme<String> + ?Sized> ThemeTo<String> for T {
|
||||||
|
fn color_to(&self, text: &str, color: EColor) -> String {
|
||||||
|
let mut t = String::new();
|
||||||
|
self.color(text, color, &mut t);
|
||||||
|
t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn colorize_str(
|
||||||
|
message: &Vec<(String, Option<EColor>)>,
|
||||||
|
theme: &(impl Theme<String> + ?Sized),
|
||||||
|
) -> String {
|
||||||
|
let mut t = String::new();
|
||||||
|
colorize_gen(message, &mut t, |t, a| a.push_str(t), theme);
|
||||||
|
t
|
||||||
|
}
|
||||||
|
pub fn colorize_gen<T>(
|
||||||
|
message: &Vec<(String, Option<EColor>)>,
|
||||||
|
t: &mut T,
|
||||||
|
direct: impl Fn(&str, &mut T),
|
||||||
|
theme: &(impl Theme<T> + ?Sized),
|
||||||
|
) {
|
||||||
|
for (text, color) in message {
|
||||||
|
if let Some(color) = *color {
|
||||||
|
theme.color(text, color, t)
|
||||||
|
} else {
|
||||||
|
direct(text, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const AsTypeStatementWithTooBroadType: Color = InitFrom;
|
pub struct NoTheme;
|
||||||
pub const AsTypeTypeAnnotation: Color = InitTo;
|
impl Theme<String> for NoTheme {
|
||||||
|
fn color(&self, text: &str, _color: EColor, t: &mut String) {
|
||||||
|
t.push_str(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const BadCharInTupleType: Color = Color::Red;
|
#[cfg(feature = "ecolor-term")]
|
||||||
pub const BadCharInFunctionType: Color = Color::Red;
|
pub struct TermDefaultTheme;
|
||||||
pub const BadTypeFromParsed: Color = Color::Blue;
|
#[cfg(feature = "ecolor-term")]
|
||||||
pub const TypeAnnotationNoClosingBracket: Color = Color::Blue;
|
impl Theme<String> for TermDefaultTheme {
|
||||||
|
fn color(&self, text: &str, color: EColor, t: &mut String) {
|
||||||
|
use colored::{Color, Colorize};
|
||||||
|
t.push_str(&text.color(match color {
|
||||||
|
EColor::Indent(n) => match n % 6 {
|
||||||
|
0 => Color::Red,
|
||||||
|
1 => Color::Green,
|
||||||
|
2 => Color::Yellow,
|
||||||
|
3 => Color::Blue,
|
||||||
|
4 => Color::Magenta,
|
||||||
|
_ => Color::Cyan,
|
||||||
|
},
|
||||||
|
|
||||||
pub const TryBadSyntax: Color = Color::Red;
|
EColor::UnknownVariable => Color::Red,
|
||||||
pub const TryNoFunctionFound: Color = Color::Red;
|
|
||||||
pub const TryNotAFunction: Color = Color::Red;
|
|
||||||
pub const TryUnusedFunction1: Color = Color::Red;
|
|
||||||
pub const TryUnusedFunction2: Color = Color::BrightRed;
|
|
||||||
|
|
||||||
pub const StacktraceDescend: Color = Color::Yellow;
|
EColor::WhitespaceAfterHashtag => Color::Red,
|
||||||
pub const StacktraceDescendHashInclude: Color = Color::Red;
|
EColor::HashUnknown => Color::Red,
|
||||||
|
EColor::HashIncludeCantLoadFile => Color::Red,
|
||||||
|
EColor::HashIncludeNotAString => Color::Red,
|
||||||
|
EColor::HashIncludeErrorInIncludedFile => Color::Red,
|
||||||
|
|
||||||
pub const MaximumRuntimeExceeded: Color = Color::BrightYellow;
|
EColor::BackslashEscapeUnknown => Color::Red,
|
||||||
|
EColor::BackslashEscapeEOF => Color::Red,
|
||||||
|
EColor::StringEOF => Color::Red,
|
||||||
|
|
||||||
|
EColor::IfConditionNotBool => Color::Red,
|
||||||
|
EColor::ChainWithNonFunction => Color::Yellow,
|
||||||
|
|
||||||
|
EColor::Function => Color::BrightMagenta,
|
||||||
|
EColor::FunctionArgument => Color::BrightBlue,
|
||||||
|
|
||||||
|
EColor::InitFrom | EColor::AssignFrom | EColor::AsTypeStatementWithTooBroadType => {
|
||||||
|
Color::BrightCyan
|
||||||
|
}
|
||||||
|
EColor::InitTo | EColor::AssignTo | EColor::AsTypeTypeAnnotation => Color::Green,
|
||||||
|
EColor::AssignTargetNonReference => Color::BrightYellow,
|
||||||
|
|
||||||
|
EColor::BadCharInTupleType => Color::Red,
|
||||||
|
EColor::BadCharInFunctionType => Color::Red,
|
||||||
|
EColor::BadTypeFromParsed => Color::Blue,
|
||||||
|
EColor::TypeAnnotationNoClosingBracket => Color::Blue,
|
||||||
|
|
||||||
|
EColor::TryBadSyntax => Color::Red,
|
||||||
|
EColor::TryNoFunctionFound => Color::Red,
|
||||||
|
EColor::TryNotAFunction => Color::Red,
|
||||||
|
EColor::TryUnusedFunction1 => Color::Red,
|
||||||
|
EColor::TryUnusedFunction2 => Color::BrightRed,
|
||||||
|
EColor::CustomTypeTestFailed => Color::BrightRed,
|
||||||
|
|
||||||
|
EColor::StacktraceDescend => Color::Yellow,
|
||||||
|
EColor::StacktraceDescendHashInclude => Color::Red,
|
||||||
|
EColor::MaximumRuntimeExceeded => Color::BrightYellow,
|
||||||
|
|
||||||
|
EColor::InCodePositionLine => Color::BrightBlack,
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum CheckErrorComponent {
|
pub enum CheckErrorComponent {
|
||||||
Message(String),
|
Message(Vec<(String, Option<EColor>)>),
|
||||||
Error(CheckError),
|
Error(CheckError),
|
||||||
ErrorWithDifferentSource(CheckError),
|
ErrorWithDifferentSource(CheckError),
|
||||||
Source(Vec<(SourceRange, Option<colored::Color>)>),
|
Source(Vec<(SourceRange, Option<EColor>)>),
|
||||||
}
|
}
|
||||||
pub struct CheckErrorHRConfig {
|
pub struct CheckErrorHRConfig {
|
||||||
color_index_ptr: Rc<AtomicUsize>,
|
color_index_ptr: Rc<AtomicU32>,
|
||||||
color_index: usize,
|
color_index: u32,
|
||||||
|
theme: Rc<dyn Theme<String>>,
|
||||||
is_inner: bool,
|
is_inner: bool,
|
||||||
style: u8,
|
style: u8,
|
||||||
idt_start: String,
|
idt_start: String,
|
||||||
@ -113,7 +216,7 @@ pub struct CheckErrorHRConfig {
|
|||||||
show_comments: bool,
|
show_comments: bool,
|
||||||
}
|
}
|
||||||
type BorderCharsSet = [[&'static str; 4]; 3];
|
type BorderCharsSet = [[&'static str; 4]; 3];
|
||||||
pub struct IndentStr<'a>(&'a str, ColoredString);
|
pub struct IndentStr<'a>(&'a str, String);
|
||||||
impl Display for IndentStr<'_> {
|
impl Display for IndentStr<'_> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}{}", self.0, self.1)
|
write!(f, "{}{}", self.0, self.1)
|
||||||
@ -143,17 +246,11 @@ impl CheckErrorHRConfig {
|
|||||||
["╩", "╙", "╜", "╨"],
|
["╩", "╙", "╜", "╨"],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
fn color(&self, s: &str) -> ColoredString {
|
fn color(&self, s: &str) -> String {
|
||||||
match self.color_index % 8 {
|
let mut t = String::new();
|
||||||
0 => s.bright_white(),
|
self.theme
|
||||||
1 => s.bright_green(),
|
.color(s, EColor::Indent(self.color_index), &mut t);
|
||||||
2 => s.bright_purple(),
|
return t;
|
||||||
3 => s.bright_cyan(),
|
|
||||||
4 => s.bright_red(),
|
|
||||||
5 => s.bright_yellow(),
|
|
||||||
6 => s.bright_magenta(),
|
|
||||||
_ => s.bright_blue(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn indent_start(&self, right: bool) -> IndentStr {
|
pub fn indent_start(&self, right: bool) -> IndentStr {
|
||||||
IndentStr(
|
IndentStr(
|
||||||
@ -202,6 +299,7 @@ impl CheckErrorHRConfig {
|
|||||||
Self {
|
Self {
|
||||||
color_index_ptr: self.color_index_ptr.clone(),
|
color_index_ptr: self.color_index_ptr.clone(),
|
||||||
color_index,
|
color_index,
|
||||||
|
theme: Rc::clone(&self.theme),
|
||||||
is_inner: true,
|
is_inner: true,
|
||||||
style,
|
style,
|
||||||
idt_start: if is_first {
|
idt_start: if is_first {
|
||||||
@ -231,6 +329,7 @@ impl CheckErrorHRConfig {
|
|||||||
#[cfg(feature = "parse")]
|
#[cfg(feature = "parse")]
|
||||||
pub struct CheckErrorDisplay<'a> {
|
pub struct CheckErrorDisplay<'a> {
|
||||||
e: &'a CheckError,
|
e: &'a CheckError,
|
||||||
|
theme: Rc<dyn Theme<String>>,
|
||||||
pub show_comments: bool,
|
pub show_comments: bool,
|
||||||
}
|
}
|
||||||
#[cfg(feature = "parse")]
|
#[cfg(feature = "parse")]
|
||||||
@ -247,7 +346,8 @@ impl Display for CheckErrorDisplay<'_> {
|
|||||||
f,
|
f,
|
||||||
&CheckErrorHRConfig {
|
&CheckErrorHRConfig {
|
||||||
color_index: 0,
|
color_index: 0,
|
||||||
color_index_ptr: Rc::new(AtomicUsize::new(1)),
|
color_index_ptr: Rc::new(AtomicU32::new(1)),
|
||||||
|
theme: Rc::clone(&self.theme),
|
||||||
is_inner: false,
|
is_inner: false,
|
||||||
style: CheckErrorHRConfig::STYLE_DEFAULT,
|
style: CheckErrorHRConfig::STYLE_DEFAULT,
|
||||||
idt_start: String::new(),
|
idt_start: String::new(),
|
||||||
@ -272,10 +372,16 @@ impl CheckError {
|
|||||||
self.0.push(v);
|
self.0.push(v);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub(crate) fn msg(self, s: String) -> Self {
|
pub(crate) fn msg_str(self, s: String) -> Self {
|
||||||
|
self.add(CheckErrorComponent::Message(vec![(s, None)]))
|
||||||
|
}
|
||||||
|
pub(crate) fn msg_mut_str(&mut self, s: String) -> &mut Self {
|
||||||
|
self.add_mut(CheckErrorComponent::Message(vec![(s, None)]))
|
||||||
|
}
|
||||||
|
pub(crate) fn msg(self, s: Vec<(String, Option<EColor>)>) -> Self {
|
||||||
self.add(CheckErrorComponent::Message(s))
|
self.add(CheckErrorComponent::Message(s))
|
||||||
}
|
}
|
||||||
pub(crate) fn msg_mut(&mut self, s: String) -> &mut Self {
|
pub(crate) fn msg_mut(&mut self, s: Vec<(String, Option<EColor>)>) -> &mut Self {
|
||||||
self.add_mut(CheckErrorComponent::Message(s))
|
self.add_mut(CheckErrorComponent::Message(s))
|
||||||
}
|
}
|
||||||
pub(crate) fn err(self, e: Self) -> Self {
|
pub(crate) fn err(self, e: Self) -> Self {
|
||||||
@ -290,19 +396,31 @@ impl CheckError {
|
|||||||
pub(crate) fn err_with_diff_src_mut(&mut self, e: CheckError) -> &mut Self {
|
pub(crate) fn err_with_diff_src_mut(&mut self, e: CheckError) -> &mut Self {
|
||||||
self.add_mut(CheckErrorComponent::ErrorWithDifferentSource(e))
|
self.add_mut(CheckErrorComponent::ErrorWithDifferentSource(e))
|
||||||
}
|
}
|
||||||
pub(crate) fn src(self, s: Vec<(SourceRange, Option<colored::Color>)>) -> Self {
|
pub(crate) fn src(self, s: Vec<(SourceRange, Option<EColor>)>) -> Self {
|
||||||
self.add(CheckErrorComponent::Source(s))
|
self.add(CheckErrorComponent::Source(s))
|
||||||
}
|
}
|
||||||
pub(crate) fn src_mut(&mut self, s: Vec<(SourceRange, Option<colored::Color>)>) -> &mut Self {
|
pub(crate) fn src_mut(&mut self, s: Vec<(SourceRange, Option<EColor>)>) -> &mut Self {
|
||||||
self.add_mut(CheckErrorComponent::Source(s))
|
self.add_mut(CheckErrorComponent::Source(s))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "parse")]
|
#[cfg(feature = "parse")]
|
||||||
pub fn display<'a>(&'a self) -> CheckErrorDisplay<'a> {
|
pub fn display<'a>(&'a self, theme: impl Theme<String> + 'static) -> CheckErrorDisplay<'a> {
|
||||||
CheckErrorDisplay {
|
CheckErrorDisplay {
|
||||||
e: self,
|
e: self,
|
||||||
|
theme: Rc::new(theme),
|
||||||
show_comments: true,
|
show_comments: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Like `display`, but doesn't use any theme (doesn't colorize its output)
|
||||||
|
#[cfg(feature = "parse")]
|
||||||
|
pub fn display_notheme<'a>(&'a self) -> CheckErrorDisplay<'a> {
|
||||||
|
self.display(NoTheme)
|
||||||
|
}
|
||||||
|
/// Like `display`, but uses the default terminal theme
|
||||||
|
#[cfg(feature = "parse")]
|
||||||
|
#[cfg(feature = "ecolor-term")]
|
||||||
|
pub fn display_term<'a>(&'a self) -> CheckErrorDisplay<'a> {
|
||||||
|
self.display(TermDefaultTheme)
|
||||||
|
}
|
||||||
/// will, unless empty, end in a newline
|
/// will, unless empty, end in a newline
|
||||||
#[cfg(feature = "parse")]
|
#[cfg(feature = "parse")]
|
||||||
fn human_readable(
|
fn human_readable(
|
||||||
@ -330,6 +448,7 @@ impl CheckError {
|
|||||||
}
|
}
|
||||||
match component {
|
match component {
|
||||||
CheckErrorComponent::Message(msg) => {
|
CheckErrorComponent::Message(msg) => {
|
||||||
|
let msg = colorize_str(msg, cfg.theme.as_ref());
|
||||||
let lines = msg.lines().collect::<Vec<_>>();
|
let lines = msg.lines().collect::<Vec<_>>();
|
||||||
let lc = lines.len();
|
let lc = lines.len();
|
||||||
for (i, line) in lines.into_iter().enumerate() {
|
for (i, line) in lines.into_iter().enumerate() {
|
||||||
@ -403,26 +522,30 @@ impl CheckError {
|
|||||||
f,
|
f,
|
||||||
"{}{}",
|
"{}{}",
|
||||||
indent!(true, false, ADD_RIGHT_BITS),
|
indent!(true, false, ADD_RIGHT_BITS),
|
||||||
format!(
|
cfg.theme.color_to(
|
||||||
"Line {first_line_nr} ({}..{}){}",
|
&format!(
|
||||||
start_with_comments + 1 - first_line_start,
|
"Line {first_line_nr} ({}..{}){}",
|
||||||
end_with_comments - last_line_start,
|
start_with_comments + 1 - first_line_start,
|
||||||
src_from,
|
end_with_comments - last_line_start,
|
||||||
|
src_from,
|
||||||
|
),
|
||||||
|
EColor::InCodePositionLine
|
||||||
)
|
)
|
||||||
.bright_black()
|
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
writeln!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
"{}{}",
|
"{}{}",
|
||||||
indent!(true, false, ADD_RIGHT_BITS),
|
indent!(true, false, ADD_RIGHT_BITS),
|
||||||
format!(
|
cfg.theme.color_to(
|
||||||
"Lines {first_line_nr}-{last_line_nr} ({}..{}){}",
|
&format!(
|
||||||
start_with_comments + 1 - first_line_start,
|
"Lines {first_line_nr}-{last_line_nr} ({}..{}){}",
|
||||||
end_with_comments - last_line_start,
|
start_with_comments + 1 - first_line_start,
|
||||||
src_from,
|
end_with_comments - last_line_start,
|
||||||
|
src_from,
|
||||||
|
),
|
||||||
|
EColor::InCodePositionLine
|
||||||
)
|
)
|
||||||
.bright_black()
|
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
let lines = if cfg.show_comments {
|
let lines = if cfg.show_comments {
|
||||||
@ -441,7 +564,7 @@ impl CheckError {
|
|||||||
for (highlight_index, (highlight_pos, color)) in
|
for (highlight_index, (highlight_pos, color)) in
|
||||||
highlights.iter().enumerate()
|
highlights.iter().enumerate()
|
||||||
{
|
{
|
||||||
if let Some(color) = color {
|
if let Some(color) = *color {
|
||||||
let (highlight_start, highlight_end) = if cfg.show_comments
|
let (highlight_start, highlight_end) = if cfg.show_comments
|
||||||
{
|
{
|
||||||
(
|
(
|
||||||
@ -515,7 +638,7 @@ impl CheckError {
|
|||||||
f,
|
f,
|
||||||
"{}{}",
|
"{}{}",
|
||||||
" ".repeat(hl_space),
|
" ".repeat(hl_space),
|
||||||
"~".repeat(hl_len).color(*color)
|
&cfg.theme.color_to(&"~".repeat(hl_len), color)
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -538,21 +661,20 @@ impl CheckError {
|
|||||||
}
|
}
|
||||||
impl From<String> for CheckError {
|
impl From<String> for CheckError {
|
||||||
fn from(value: String) -> Self {
|
fn from(value: String) -> Self {
|
||||||
Self::new().msg(value)
|
Self::new().msg_str(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<&str> for CheckError {
|
impl From<&str> for CheckError {
|
||||||
fn from(value: &str) -> Self {
|
fn from(value: &str) -> Self {
|
||||||
Self::new().msg(value.to_owned())
|
value.to_owned().into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Debug for CheckError {
|
impl Debug for CheckError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{self}")
|
#[cfg(feature = "ecolor-term")]
|
||||||
}
|
let e = self.display_term();
|
||||||
}
|
#[cfg(not(feature = "ecolor-term"))]
|
||||||
impl Display for CheckError {
|
let e = self.display_notheme();
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
write!(f, "{e}")
|
||||||
write!(f, "{}", self.display())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use line_span::{LineSpan, LineSpanExt};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::Type,
|
data::Type,
|
||||||
errors::{error_colors, CheckError, SourcePos},
|
errors::{CheckError, EColor, SourcePos},
|
||||||
program::{
|
program::{
|
||||||
self,
|
self,
|
||||||
parsed::{block::Block, CompInfo},
|
parsed::{block::Block, CompInfo},
|
||||||
@ -53,7 +53,7 @@ pub fn check_mut(
|
|||||||
for (try_stmt, used) in info.global.unused_try_statements.lock().unwrap().iter() {
|
for (try_stmt, used) in info.global.unused_try_statements.lock().unwrap().iter() {
|
||||||
if used.iter().any(|v| v.is_some()) {
|
if used.iter().any(|v| v.is_some()) {
|
||||||
let err = err.get_or_insert_with(|| {
|
let err = err.get_or_insert_with(|| {
|
||||||
CheckError::new().msg(format!(
|
CheckError::from(format!(
|
||||||
"There are `.try` statements with unused functions!"
|
"There are `.try` statements with unused functions!"
|
||||||
))
|
))
|
||||||
});
|
});
|
||||||
@ -62,7 +62,7 @@ pub fn check_mut(
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|v| Some((v.0, v.1.clone()?)))
|
.filter_map(|v| Some((v.0, v.1.clone()?)))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
err.msg_mut(format!(
|
err.msg_mut_str(format!(
|
||||||
"Here, {}function{} {} {} unused:",
|
"Here, {}function{} {} {} unused:",
|
||||||
if unused.len() == 1 { "the " } else { "" },
|
if unused.len() == 1 { "the " } else { "" },
|
||||||
if unused.len() == 1 { "" } else { "s" },
|
if unused.len() == 1 { "" } else { "s" },
|
||||||
@ -87,9 +87,9 @@ pub fn check_mut(
|
|||||||
src.push((
|
src.push((
|
||||||
src_range,
|
src_range,
|
||||||
Some(if i % 2 == 0 {
|
Some(if i % 2 == 0 {
|
||||||
error_colors::TryUnusedFunction1
|
EColor::TryUnusedFunction1
|
||||||
} else {
|
} else {
|
||||||
error_colors::TryUnusedFunction2
|
EColor::TryUnusedFunction2
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use std::{path::PathBuf, sync::Arc};
|
|||||||
use super::{Source, SourceFrom, SourcePos};
|
use super::{Source, SourceFrom, SourcePos};
|
||||||
use crate::{
|
use crate::{
|
||||||
data::Data,
|
data::Data,
|
||||||
errors::{error_colors, CheckError},
|
errors::{CheckError, EColor},
|
||||||
program::{
|
program::{
|
||||||
self,
|
self,
|
||||||
parsed::{as_type::AsType, MersStatement},
|
parsed::{as_type::AsType, MersStatement},
|
||||||
@ -30,9 +30,9 @@ pub fn parse(
|
|||||||
let name = name.trim().to_owned();
|
let name = name.trim().to_owned();
|
||||||
src.skip_whitespace();
|
src.skip_whitespace();
|
||||||
if !matches!(src.next_char(), Some(']')) {
|
if !matches!(src.next_char(), Some(']')) {
|
||||||
return Err(
|
return Err(CheckError::from(format!(
|
||||||
CheckError::new().msg(format!("Expected ']' after type name in [[type_name]]"))
|
"Expected ']' after type name in [[type_name]]"
|
||||||
);
|
)));
|
||||||
}
|
}
|
||||||
src.skip_whitespace();
|
src.skip_whitespace();
|
||||||
if src.peek_word_allow_colon() == ":=" {
|
if src.peek_word_allow_colon() == ":=" {
|
||||||
@ -43,12 +43,12 @@ pub fn parse(
|
|||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
||||||
.msg(format!("EOF after `[[...] := ...]` type definition")))
|
.msg_str(format!("EOF after `[[...] := ...]` type definition")))
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
if !matches!(src.next_char(), Some(']')) {
|
if !matches!(src.next_char(), Some(']')) {
|
||||||
return Err(CheckError::new().msg(format!(
|
return Err(CheckError::new().msg_str(format!(
|
||||||
"Expected ']' after statement in [[type_name] := statement]"
|
"Expected ']' after statement in [[type_name] := statement]"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ pub fn parse(
|
|||||||
let as_type = super::types::parse_type(src, srca)?;
|
let as_type = super::types::parse_type(src, srca)?;
|
||||||
src.skip_whitespace();
|
src.skip_whitespace();
|
||||||
if !matches!(src.next_char(), Some(']')) {
|
if !matches!(src.next_char(), Some(']')) {
|
||||||
return Err(CheckError::new().msg(format!(
|
return Err(CheckError::new().msg_str(format!(
|
||||||
"Expected ']' after type definition in [[type_name] type_definition]"
|
"Expected ']' after type definition in [[type_name] type_definition]"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -84,16 +84,16 @@ pub fn parse(
|
|||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![(
|
.src(vec![(
|
||||||
(pos_in_src, src.get_pos(), srca).into(),
|
(pos_in_src, src.get_pos(), srca).into(),
|
||||||
Some(error_colors::TypeAnnotationNoClosingBracket),
|
Some(EColor::TypeAnnotationNoClosingBracket),
|
||||||
)])
|
)])
|
||||||
.msg(format!("Missing closing bracket ']' after type annotation")));
|
.msg_str(format!("Missing closing bracket ']' after type annotation")));
|
||||||
}
|
}
|
||||||
let statement = match parse(src, srca) {
|
let statement = match parse(src, srca) {
|
||||||
Ok(Some(v)) => v,
|
Ok(Some(v)) => v,
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
||||||
.msg(format!("EOF after `[...]` type annotation")))
|
.msg_str(format!("EOF after `[...]` type annotation")))
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
@ -120,7 +120,7 @@ pub fn parse(
|
|||||||
let source = parse(src, srca)?.ok_or_else(|| {
|
let source = parse(src, srca)?.ok_or_else(|| {
|
||||||
CheckError::new()
|
CheckError::new()
|
||||||
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
||||||
.msg(format!("EOF after `:=`"))
|
.msg_str(format!("EOF after `:=`"))
|
||||||
})?;
|
})?;
|
||||||
first = Box::new(program::parsed::init_to::InitTo {
|
first = Box::new(program::parsed::init_to::InitTo {
|
||||||
pos_in_src: (first.source_range().start(), src.get_pos(), srca).into(),
|
pos_in_src: (first.source_range().start(), src.get_pos(), srca).into(),
|
||||||
@ -137,7 +137,7 @@ pub fn parse(
|
|||||||
(first.source_range().start(), src.get_pos(), srca).into(),
|
(first.source_range().start(), src.get_pos(), srca).into(),
|
||||||
None,
|
None,
|
||||||
)])
|
)])
|
||||||
.msg(format!("EOF after `=`"))
|
.msg_str(format!("EOF after `=`"))
|
||||||
})?;
|
})?;
|
||||||
first = Box::new(program::parsed::assign_to::AssignTo {
|
first = Box::new(program::parsed::assign_to::AssignTo {
|
||||||
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
|
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
|
||||||
@ -153,7 +153,7 @@ pub fn parse(
|
|||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
||||||
.msg(format!("EOF after `->`")))
|
.msg_str(format!("EOF after `->`")))
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
@ -182,10 +182,10 @@ pub fn parse(
|
|||||||
pos_after_first = src.get_pos();
|
pos_after_first = src.get_pos();
|
||||||
} else {
|
} else {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.msg(format!("Expected `(` after `.try`"))
|
.msg_str(format!("Expected `(` after `.try`"))
|
||||||
.src(vec![(
|
.src(vec![(
|
||||||
(dot_in_src, src.get_pos(), srca).into(),
|
(dot_in_src, src.get_pos(), srca).into(),
|
||||||
Some(error_colors::TryBadSyntax),
|
Some(EColor::TryBadSyntax),
|
||||||
)]));
|
)]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -194,7 +194,7 @@ pub fn parse(
|
|||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![((dot_in_src, src.get_pos(), srca).into(), None)])
|
.src(vec![((dot_in_src, src.get_pos(), srca).into(), None)])
|
||||||
.msg(format!("EOF after `.`")))
|
.msg_str(format!("EOF after `.`")))
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
@ -265,16 +265,16 @@ pub fn parse_no_chain(
|
|||||||
if src.peek_char().is_none() {
|
if src.peek_char().is_none() {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
||||||
.msg(format!("EOF after #")));
|
.msg_str(format!("EOF after #")));
|
||||||
}
|
}
|
||||||
if src.peek_char().is_some_and(|ch| ch.is_whitespace()) {
|
if src.peek_char().is_some_and(|ch| ch.is_whitespace()) {
|
||||||
src.skip_whitespace();
|
src.skip_whitespace();
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![(
|
.src(vec![(
|
||||||
(pos_in_src, src.get_pos(), srca).into(),
|
(pos_in_src, src.get_pos(), srca).into(),
|
||||||
Some(error_colors::WhitespaceAfterHashtag),
|
Some(EColor::WhitespaceAfterHashtag),
|
||||||
)])
|
)])
|
||||||
.msg(format!("Whitespace after #")));
|
.msg_str(format!("Whitespace after #")));
|
||||||
}
|
}
|
||||||
match src.next_word() {
|
match src.next_word() {
|
||||||
"include" => {
|
"include" => {
|
||||||
@ -313,19 +313,19 @@ pub fn parse_no_chain(
|
|||||||
((pos_in_src, end_in_src, srca).into(), None),
|
((pos_in_src, end_in_src, srca).into(), None),
|
||||||
(
|
(
|
||||||
(string_in_src, src.get_pos(), srca).into(),
|
(string_in_src, src.get_pos(), srca).into(),
|
||||||
Some(error_colors::HashIncludeCantLoadFile),
|
Some(EColor::HashIncludeCantLoadFile),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
.msg(format!("Can't load file '{file_path_str}': {e}")));
|
.msg_str(format!("Can't load file '{file_path_str}': {e}")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![
|
.src(vec![
|
||||||
((pos_in_src, end_in_src, srca).into(), None),
|
((pos_in_src, end_in_src, srca).into(), None),
|
||||||
((string_in_src, src.get_pos(), srca).into(), Some(error_colors::HashIncludeNotAString)),
|
((string_in_src, src.get_pos(), srca).into(), Some(EColor::HashIncludeNotAString)),
|
||||||
])
|
])
|
||||||
.msg(format!(
|
.msg_str(format!(
|
||||||
"#include must be followed by a string literal like \"file.mers\" (\" expected)."
|
"#include must be followed by a string literal like \"file.mers\" (\" expected)."
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -335,9 +335,9 @@ pub fn parse_no_chain(
|
|||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![(
|
.src(vec![(
|
||||||
(pos_in_src, src.get_pos(), srca).into(),
|
(pos_in_src, src.get_pos(), srca).into(),
|
||||||
Some(error_colors::HashUnknown),
|
Some(EColor::HashUnknown),
|
||||||
)])
|
)])
|
||||||
.msg(msg));
|
.msg_str(msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -371,7 +371,7 @@ pub fn parse_no_chain(
|
|||||||
(pos_in_src, src.get_pos(), srca).into(),
|
(pos_in_src, src.get_pos(), srca).into(),
|
||||||
None,
|
None,
|
||||||
)])
|
)])
|
||||||
.msg(format!("EOF after `:` in object")))
|
.msg_str(format!("EOF after `:` in object")))
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
@ -379,7 +379,9 @@ pub fn parse_no_chain(
|
|||||||
(pos_in_src, src.get_pos(), srca).into(),
|
(pos_in_src, src.get_pos(), srca).into(),
|
||||||
None,
|
None,
|
||||||
)])
|
)])
|
||||||
.msg(format!("Error in statement after `:` in object"))
|
.msg_str(format!(
|
||||||
|
"Error in statement after `:` in object"
|
||||||
|
))
|
||||||
.err(e))
|
.err(e))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -430,7 +432,7 @@ pub fn parse_no_chain(
|
|||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
||||||
.msg(format!("EOF in `if`")))
|
.msg_str(format!("EOF in `if`")))
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
@ -439,7 +441,7 @@ pub fn parse_no_chain(
|
|||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
||||||
.msg(format!("EOF after `if <condition>`")))
|
.msg_str(format!("EOF after `if <condition>`")))
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
@ -453,7 +455,7 @@ pub fn parse_no_chain(
|
|||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
||||||
.msg(format!("EOF after `else`")))
|
.msg_str(format!("EOF after `else`")))
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
})
|
})
|
||||||
@ -476,7 +478,7 @@ pub fn parse_no_chain(
|
|||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
||||||
.msg(format!("EOF after `loop`")))
|
.msg_str(format!("EOF after `loop`")))
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
@ -578,17 +580,17 @@ pub fn parse_string_custom_end(
|
|||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![(
|
.src(vec![(
|
||||||
(backslash_in_src, src.get_pos(), srca).into(),
|
(backslash_in_src, src.get_pos(), srca).into(),
|
||||||
Some(error_colors::BackslashEscapeUnknown),
|
Some(EColor::BackslashEscapeUnknown),
|
||||||
)])
|
)])
|
||||||
.msg(format!("unknown backslash escape '\\{o}'")));
|
.msg_str(format!("unknown backslash escape '\\{o}'")));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![(
|
.src(vec![(
|
||||||
(backslash_in_src, src.get_pos(), srca).into(),
|
(backslash_in_src, src.get_pos(), srca).into(),
|
||||||
Some(error_colors::BackslashEscapeEOF),
|
Some(EColor::BackslashEscapeEOF),
|
||||||
)])
|
)])
|
||||||
.msg(format!("EOF in backslash escape")));
|
.msg_str(format!("EOF in backslash escape")));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if ch == closing_char {
|
} else if ch == closing_char {
|
||||||
@ -600,9 +602,9 @@ pub fn parse_string_custom_end(
|
|||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![(
|
.src(vec![(
|
||||||
(opening, src.get_pos(), srca).into(),
|
(opening, src.get_pos(), srca).into(),
|
||||||
Some(error_colors::StringEOF),
|
Some(EColor::StringEOF),
|
||||||
)])
|
)])
|
||||||
.msg(format!(
|
.msg_str(format!(
|
||||||
"EOF in string literal{}",
|
"EOF in string literal{}",
|
||||||
if closing_char != '"' {
|
if closing_char != '"' {
|
||||||
format!(
|
format!(
|
||||||
|
@ -2,7 +2,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{self, Type},
|
data::{self, Type},
|
||||||
errors::{error_colors, CheckError},
|
errors::{CheckError, EColor},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Source;
|
use super::Source;
|
||||||
@ -35,7 +35,7 @@ pub fn parse_single_type(src: &mut Source, srca: &Arc<Source>) -> Result<ParsedT
|
|||||||
} else {
|
} else {
|
||||||
format!("EOF")
|
format!("EOF")
|
||||||
};
|
};
|
||||||
return Err(CheckError::new().msg(format!(
|
return Err(CheckError::new().msg_str(format!(
|
||||||
"No closing ] in reference type with opening [! Found {nc} instead"
|
"No closing ] in reference type with opening [! Found {nc} instead"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -75,10 +75,10 @@ pub fn parse_single_type(src: &mut Source, srca: &Arc<Source>) -> Result<ParsedT
|
|||||||
((pos_in_src, src.get_pos(), srca).into(), None),
|
((pos_in_src, src.get_pos(), srca).into(), None),
|
||||||
(
|
(
|
||||||
(pos1, src.get_pos(), srca).into(),
|
(pos1, src.get_pos(), srca).into(),
|
||||||
Some(error_colors::BadCharInFunctionType),
|
Some(EColor::BadCharInFunctionType),
|
||||||
),
|
),
|
||||||
]).msg(format!("Unexpected character in function type, expected arrow `->` but found `,`."))
|
]).msg_str(format!("Unexpected character in function type, expected arrow `->` but found `,`."))
|
||||||
.msg(format!("If you wanted this to be a tuple type instead, you may have used `Input -> Output` instead of `(Input -> Output)` for a function type somewhere.")));
|
.msg_str(format!("If you wanted this to be a tuple type instead, you may have used `Input -> Output` instead of `(Input -> Output)` for a function type somewhere.")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some('-') if src.peek_word() == "->" => {
|
Some('-') if src.peek_word() == "->" => {
|
||||||
@ -92,8 +92,8 @@ pub fn parse_single_type(src: &mut Source, srca: &Arc<Source>) -> Result<ParsedT
|
|||||||
Some(')') => break,
|
Some(')') => break,
|
||||||
_ => return Err(CheckError::new().src(vec![
|
_ => return Err(CheckError::new().src(vec![
|
||||||
((pos_in_src, src.get_pos(), srca).into(), None),
|
((pos_in_src, src.get_pos(), srca).into(), None),
|
||||||
((pos2, src.get_pos(), srca).into(), Some(error_colors::BadCharInFunctionType)),
|
((pos2, src.get_pos(), srca).into(), Some(EColor::BadCharInFunctionType)),
|
||||||
]).msg(format!("Expected comma `,` after `In -> Out` part of function type")))
|
]).msg_str(format!("Expected comma `,` after `In -> Out` part of function type")))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let pos1 = src.get_pos();
|
let pos1 = src.get_pos();
|
||||||
@ -102,10 +102,10 @@ pub fn parse_single_type(src: &mut Source, srca: &Arc<Source>) -> Result<ParsedT
|
|||||||
((pos_in_src, src.get_pos(), srca).into(), None),
|
((pos_in_src, src.get_pos(), srca).into(), None),
|
||||||
(
|
(
|
||||||
(pos1, src.get_pos(), srca).into(),
|
(pos1, src.get_pos(), srca).into(),
|
||||||
Some(error_colors::BadCharInTupleType),
|
Some(EColor::BadCharInTupleType),
|
||||||
),
|
),
|
||||||
]).msg(format!("Unexpected character in tuple type, expected comma `,` but found arrow `->`."))
|
]).msg_str(format!("Unexpected character in tuple type, expected comma `,` but found arrow `->`."))
|
||||||
.msg(format!("If you wanted to write a function type, use `(Input -> Output)` instead of `Input -> Output`.")));
|
.msg_str(format!("If you wanted to write a function type, use `(Input -> Output)` instead of `Input -> Output`.")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@ -116,10 +116,10 @@ pub fn parse_single_type(src: &mut Source, srca: &Arc<Source>) -> Result<ParsedT
|
|||||||
((pos_in_src, src.get_pos(), srca).into(), None),
|
((pos_in_src, src.get_pos(), srca).into(), None),
|
||||||
(
|
(
|
||||||
(ppos, src.get_pos(), srca).into(),
|
(ppos, src.get_pos(), srca).into(),
|
||||||
Some(error_colors::BadCharInTupleType),
|
Some(EColor::BadCharInTupleType),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
.msg(format!(
|
.msg_str(format!(
|
||||||
"Unexpected character in tuple type, expected comma ',' or ')'."
|
"Unexpected character in tuple type, expected comma ',' or ')'."
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ pub fn parse_single_type(src: &mut Source, srca: &Arc<Source>) -> Result<ParsedT
|
|||||||
if src.next_char() != Some(':') {
|
if src.next_char() != Some(':') {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
||||||
.msg(format!("Expected colon ':' in object type")));
|
.msg_str(format!("Expected colon ':' in object type")));
|
||||||
}
|
}
|
||||||
src.skip_whitespace();
|
src.skip_whitespace();
|
||||||
inner.push((field, parse_type(src, srca)?));
|
inner.push((field, parse_type(src, srca)?));
|
||||||
@ -236,11 +236,11 @@ pub fn type_from_parsed(
|
|||||||
{
|
{
|
||||||
Some(Ok(t)) => as_type.add_all(&*t),
|
Some(Ok(t)) => as_type.add_all(&*t),
|
||||||
Some(Err(_)) => {
|
Some(Err(_)) => {
|
||||||
return Err(CheckError::new().msg(format!(
|
return Err(CheckError::new().msg_str(format!(
|
||||||
"Type: specified type without info, but type needs additional info"
|
"Type: specified type without info, but type needs additional info"
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
None => return Err(CheckError::new().msg(format!("Unknown type '{name}'"))),
|
None => return Err(CheckError::new().msg_str(format!("Unknown type '{name}'"))),
|
||||||
},
|
},
|
||||||
ParsedType::TypeWithInfo(name, additional_info) => match info
|
ParsedType::TypeWithInfo(name, additional_info) => match info
|
||||||
.scopes
|
.scopes
|
||||||
@ -248,12 +248,12 @@ pub fn type_from_parsed(
|
|||||||
.find_map(|scope| scope.types.iter().find(|v| v.0 == name).map(|(_, v)| v))
|
.find_map(|scope| scope.types.iter().find(|v| v.0 == name).map(|(_, v)| v))
|
||||||
{
|
{
|
||||||
Some(Ok(t)) => {
|
Some(Ok(t)) => {
|
||||||
return Err(CheckError::new().msg(format!(
|
return Err(CheckError::new().msg_str(format!(
|
||||||
"Type: specified type with info, but type {t} doesn't need it"
|
"Type: specified type with info, but type {t} doesn't need it"
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
Some(Err(f)) => as_type.add_all(&*f(&additional_info, info)?),
|
Some(Err(f)) => as_type.add_all(&*f(&additional_info, info)?),
|
||||||
None => return Err(CheckError::new().msg(format!("Unknown type '{name}'"))),
|
None => return Err(CheckError::new().msg_str(format!("Unknown type '{name}'"))),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ impl Config {
|
|||||||
return Err(format!("Function returns a value of type {out}, which isn't included in the type of the reference, {arg}.").into());
|
return Err(format!("Function returns a value of type {out}, which isn't included in the type of the reference, {arg}.").into());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => return Err(CheckError::new().msg(format!("Invalid argument type {arg} for function")).err(e)),
|
Err(e) => return Err(CheckError::new().msg_str(format!("Invalid argument type {arg} for function")).err(e)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(format!("Arguments must be (reference, function)").into());
|
return Err(format!("Arguments must be (reference, function)").into());
|
||||||
|
@ -38,7 +38,7 @@ impl Config {
|
|||||||
if let Some(f) = t.as_any().downcast_ref::<data::function::FunctionT>() {
|
if let Some(f) = t.as_any().downcast_ref::<data::function::FunctionT>() {
|
||||||
match f.o(&Type::empty_tuple()) {
|
match f.o(&Type::empty_tuple()) {
|
||||||
Ok(t) => out.add_all(&t),
|
Ok(t) => out.add_all(&t),
|
||||||
Err(e) => return Err(CheckError::new().msg(format!("Can't call thread on a function which can't be called on an empty tuple: ")).err(e))
|
Err(e) => return Err(CheckError::new().msg_str(format!("Can't call thread on a function which can't be called on an empty tuple: ")).err(e))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(format!("thread: argument wasn't a function").into());
|
return Err(format!("thread: argument wasn't a function").into());
|
||||||
@ -69,7 +69,7 @@ impl Config {
|
|||||||
out: Arc::new(|a, _i| {
|
out: Arc::new(|a, _i| {
|
||||||
for t in a.types.iter() {
|
for t in a.types.iter() {
|
||||||
if !t.as_any().is::<ThreadT>() {
|
if !t.as_any().is::<ThreadT>() {
|
||||||
return Err(CheckError::new().msg(format!("Cannot call thread_finished on a value of type {t}, which isn't a thread but part of the argument {a}.")));
|
return Err(CheckError::new().msg_str(format!("Cannot call thread_finished on a value of type {t}, which isn't a thread but part of the argument {a}.")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Type::new(data::bool::BoolT))
|
Ok(Type::new(data::bool::BoolT))
|
||||||
@ -93,7 +93,7 @@ impl Config {
|
|||||||
if let Some(t) = t.as_any().downcast_ref::<ThreadT>() {
|
if let Some(t) = t.as_any().downcast_ref::<ThreadT>() {
|
||||||
out.add_all(&t.0);
|
out.add_all(&t.0);
|
||||||
} else {
|
} else {
|
||||||
return Err(CheckError::new().msg(format!("Cannot call thread_await on a value of type {t}, which isn't a thread but part of the argument {a}.")));
|
return Err(CheckError::new().msg_str(format!("Cannot call thread_await on a value of type {t}, which isn't a thread but part of the argument {a}.")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(out)
|
Ok(out)
|
||||||
|
@ -3,11 +3,9 @@ use std::{
|
|||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use colored::Colorize;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{self, Data, Type},
|
data::{self, Data, Type},
|
||||||
errors::error_colors,
|
errors::{CheckError, EColor},
|
||||||
program::{self, run::CheckInfo},
|
program::{self, run::CheckInfo},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -33,11 +31,10 @@ impl Config {
|
|||||||
Arc::new(data::tuple::TupleT(vec![])),
|
Arc::new(data::tuple::TupleT(vec![])),
|
||||||
]))
|
]))
|
||||||
} else {
|
} else {
|
||||||
Err(format!(
|
Err(CheckError::new().msg(vec![
|
||||||
"expected (), got {}",
|
("expected (), got ".to_owned(), None),
|
||||||
a.to_string().color(error_colors::FunctionArgument)
|
(a.to_string(), Some(EColor::FunctionArgument)),
|
||||||
)
|
]))
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
run: Arc::new(|_a, _i| {
|
run: Arc::new(|_a, _i| {
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use colored::Colorize;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{self, Data},
|
data::{self, Data},
|
||||||
errors::{error_colors, CheckError, SourceRange},
|
errors::{CheckError, EColor, SourceRange},
|
||||||
info::{self, Local},
|
info::{self, Local},
|
||||||
parsing::Source,
|
parsing::Source,
|
||||||
program::{self},
|
program::{self},
|
||||||
@ -36,13 +34,13 @@ impl MersStatement for IncludeMers {
|
|||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![(
|
.src(vec![(
|
||||||
self.pos_in_src.clone(),
|
self.pos_in_src.clone(),
|
||||||
Some(error_colors::HashIncludeErrorInIncludedFile),
|
Some(EColor::HashIncludeErrorInIncludedFile),
|
||||||
)])
|
)])
|
||||||
.msg(
|
.msg(vec![(
|
||||||
"Error in #include! (note: inner errors may refer to a different file)"
|
"Error in #include! (note: inner errors may refer to a different file)"
|
||||||
.color(error_colors::HashIncludeErrorInIncludedFile)
|
.to_owned(),
|
||||||
.to_string(),
|
Some(EColor::HashIncludeErrorInIncludedFile),
|
||||||
)
|
)])
|
||||||
.err_with_diff_src(e))
|
.err_with_diff_src(e))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::{error_colors, CheckError, SourceRange},
|
errors::{CheckError, EColor, SourceRange},
|
||||||
info::Local,
|
info::Local,
|
||||||
program::{self},
|
program::{self},
|
||||||
};
|
};
|
||||||
@ -50,9 +50,9 @@ impl MersStatement for Variable {
|
|||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![(
|
.src(vec![(
|
||||||
self.pos_in_src.clone(),
|
self.pos_in_src.clone(),
|
||||||
Some(error_colors::UnknownVariable),
|
Some(EColor::UnknownVariable),
|
||||||
)])
|
)])
|
||||||
.msg(format!("No variable named '{}' found!", self.var)));
|
.msg_str(format!("No variable named '{}' found!", self.var)));
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
use colored::Colorize;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{Data, Type},
|
data::{Data, Type},
|
||||||
errors::{error_colors, CheckError, SourceRange},
|
errors::{CheckError, EColor, SourceRange},
|
||||||
parsing::types::ParsedType,
|
parsing::types::ParsedType,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -33,7 +31,7 @@ impl MersStatement for AsType {
|
|||||||
CheckError::new()
|
CheckError::new()
|
||||||
.src(vec![(
|
.src(vec![(
|
||||||
self.type_pos_in_src.clone(),
|
self.type_pos_in_src.clone(),
|
||||||
Some(error_colors::BadTypeFromParsed),
|
Some(EColor::BadTypeFromParsed),
|
||||||
)])
|
)])
|
||||||
.err(e)
|
.err(e)
|
||||||
})?;
|
})?;
|
||||||
@ -43,22 +41,23 @@ impl MersStatement for AsType {
|
|||||||
(self.pos_in_src.clone(), None),
|
(self.pos_in_src.clone(), None),
|
||||||
(
|
(
|
||||||
self.type_pos_in_src.clone(),
|
self.type_pos_in_src.clone(),
|
||||||
Some(error_colors::AsTypeTypeAnnotation),
|
Some(EColor::AsTypeTypeAnnotation),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
self.statement.source_range(),
|
self.statement.source_range(),
|
||||||
Some(error_colors::AsTypeStatementWithTooBroadType),
|
Some(EColor::AsTypeStatementWithTooBroadType),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
.msg(format!(
|
.msg(vec![
|
||||||
"Type must be included in {}, but the actual type {} isn't.",
|
("Type must be included in ".to_owned(), None),
|
||||||
as_type
|
(as_type.to_string(), Some(EColor::AsTypeTypeAnnotation)),
|
||||||
.to_string()
|
(", but the actual type ".to_owned(), None),
|
||||||
.color(error_colors::AsTypeTypeAnnotation),
|
(
|
||||||
return_type
|
return_type.to_string(),
|
||||||
.to_string()
|
Some(EColor::AsTypeStatementWithTooBroadType),
|
||||||
.color(error_colors::AsTypeStatementWithTooBroadType)
|
),
|
||||||
)));
|
(" isn't.".to_owned(), None),
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
Ok(if self.expand_type {
|
Ok(if self.expand_type {
|
||||||
as_type.clone()
|
as_type.clone()
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
use colored::Colorize;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{self, Data, Type},
|
data::{self, Data, Type},
|
||||||
errors::{error_colors, CheckError, SourceRange},
|
errors::{CheckError, EColor, SourceRange},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{CheckInfo, MersStatement};
|
use super::{CheckInfo, MersStatement};
|
||||||
@ -37,10 +35,10 @@ impl MersStatement for AssignTo {
|
|||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![
|
.src(vec![
|
||||||
(self.pos_in_src.clone(), None),
|
(self.pos_in_src.clone(), None),
|
||||||
(self.target.source_range(), Some(error_colors::InitTo)),
|
(self.target.source_range(), Some(EColor::InitTo)),
|
||||||
(self.source.source_range(), Some(error_colors::InitFrom)),
|
(self.source.source_range(), Some(EColor::InitFrom)),
|
||||||
])
|
])
|
||||||
.msg(format!("Cannot initialize:"))
|
.msg_str(format!("Cannot initialize:"))
|
||||||
.err(e));
|
.err(e));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -50,15 +48,17 @@ impl MersStatement for AssignTo {
|
|||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.src(vec![
|
.src(vec![
|
||||||
(self.pos_in_src.clone(), None),
|
(self.pos_in_src.clone(), None),
|
||||||
(self.target.source_range(), Some(error_colors::AssignTo)),
|
(self.target.source_range(), Some(EColor::AssignTo)),
|
||||||
(self.source.source_range(), Some(error_colors::AssignFrom)),
|
(self.source.source_range(), Some(EColor::AssignFrom)),
|
||||||
])
|
])
|
||||||
.msg(format!(
|
.msg(vec![
|
||||||
"can't assign {} to {} because it isn't included in {}",
|
("can't assign ".to_owned(), None),
|
||||||
source.to_string().color(error_colors::AssignFrom),
|
(source.to_string(), Some(EColor::AssignFrom)),
|
||||||
target.to_string().color(error_colors::AssignTo),
|
(" to ".to_owned(), None),
|
||||||
t
|
(target.to_string(), Some(EColor::AssignTo)),
|
||||||
)));
|
(" because it isn't included in ".to_owned(), None),
|
||||||
|
(t.to_string(), None),
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
@ -66,13 +66,16 @@ impl MersStatement for AssignTo {
|
|||||||
(self.pos_in_src.clone(), None),
|
(self.pos_in_src.clone(), None),
|
||||||
(
|
(
|
||||||
self.target.source_range(),
|
self.target.source_range(),
|
||||||
Some(error_colors::AssignTargetNonReference),
|
Some(EColor::AssignTargetNonReference),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
.msg(format!(
|
.msg(vec![
|
||||||
"can't assign to {}",
|
("can't assign to ".to_owned(), None),
|
||||||
"non-reference!".color(error_colors::AssignTargetNonReference)
|
(
|
||||||
)));
|
"non-reference!".to_owned(),
|
||||||
|
Some(EColor::AssignTargetNonReference),
|
||||||
|
),
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
use colored::Colorize;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{Data, Type},
|
data::{Data, Type},
|
||||||
errors::{error_colors, CheckError, SourceRange},
|
errors::{CheckError, EColor, SourceRange},
|
||||||
parsing::Source,
|
parsing::Source,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -44,29 +42,27 @@ impl MersStatement for Chain {
|
|||||||
CheckError::new()
|
CheckError::new()
|
||||||
.src(vec![(
|
.src(vec![(
|
||||||
self.pos_in_src.clone(),
|
self.pos_in_src.clone(),
|
||||||
Some(error_colors::HashIncludeErrorInIncludedFile),
|
Some(EColor::HashIncludeErrorInIncludedFile),
|
||||||
|
)])
|
||||||
|
.msg(vec![(
|
||||||
|
"Error in #include:".to_owned(),
|
||||||
|
Some(EColor::HashIncludeErrorInIncludedFile),
|
||||||
)])
|
)])
|
||||||
.msg(
|
|
||||||
"Error in #include:"
|
|
||||||
.color(error_colors::HashIncludeErrorInIncludedFile)
|
|
||||||
.to_string(),
|
|
||||||
)
|
|
||||||
.err_with_diff_src(e)
|
.err_with_diff_src(e)
|
||||||
} else {
|
} else {
|
||||||
CheckError::new()
|
CheckError::new()
|
||||||
.src(vec![
|
.src(vec![
|
||||||
(self.pos_in_src.clone(), None),
|
(self.pos_in_src.clone(), None),
|
||||||
(
|
(self.first.source_range(), Some(EColor::FunctionArgument)),
|
||||||
self.first.source_range(),
|
(self.chained.source_range(), Some(EColor::Function)),
|
||||||
Some(error_colors::FunctionArgument),
|
])
|
||||||
),
|
.msg(vec![
|
||||||
(self.chained.source_range(), Some(error_colors::Function)),
|
("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)),
|
||||||
|
(":".to_owned(), None),
|
||||||
])
|
])
|
||||||
.msg(format!(
|
|
||||||
"Can't call {} with an argument of type {}:",
|
|
||||||
"this function".color(error_colors::Function),
|
|
||||||
arg.to_string().color(error_colors::FunctionArgument)
|
|
||||||
))
|
|
||||||
.err(e)
|
.err(e)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -77,13 +73,14 @@ impl MersStatement for Chain {
|
|||||||
(self.pos_in_src.clone(), None),
|
(self.pos_in_src.clone(), None),
|
||||||
(
|
(
|
||||||
self.chained.source_range(),
|
self.chained.source_range(),
|
||||||
Some(error_colors::ChainWithNonFunction),
|
Some(EColor::ChainWithNonFunction),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
.msg(format!(
|
.msg(vec![
|
||||||
"cannot chain with a non-function ({})",
|
("cannot chain with a non-function (".to_owned(), None),
|
||||||
func.to_string().color(error_colors::ChainWithNonFunction)
|
(func.to_string(), Some(EColor::ChainWithNonFunction)),
|
||||||
)));
|
(")".to_owned(), None),
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(o)
|
Ok(o)
|
||||||
@ -98,12 +95,12 @@ impl MersStatement for Chain {
|
|||||||
Err(e) => Err(if let Some(_) = &self.as_part_of_include {
|
Err(e) => Err(if let Some(_) = &self.as_part_of_include {
|
||||||
CheckError::new().err_with_diff_src(e).src(vec![(
|
CheckError::new().err_with_diff_src(e).src(vec![(
|
||||||
self.pos_in_src.clone(),
|
self.pos_in_src.clone(),
|
||||||
Some(error_colors::StacktraceDescendHashInclude),
|
Some(EColor::StacktraceDescendHashInclude),
|
||||||
)])
|
)])
|
||||||
} else {
|
} else {
|
||||||
CheckError::new().err(e).src(vec![
|
CheckError::new().err(e).src(vec![
|
||||||
(self.pos_in_src.clone(), None),
|
(self.pos_in_src.clone(), None),
|
||||||
(self.source_range(), Some(error_colors::StacktraceDescend)),
|
(self.source_range(), Some(EColor::StacktraceDescend)),
|
||||||
])
|
])
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
use std::{fmt::Debug, sync::Arc};
|
use std::{fmt::Debug, sync::Arc};
|
||||||
|
|
||||||
use colored::Colorize;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{Data, Type},
|
data::{Data, Type},
|
||||||
errors::{CheckError, SourceRange},
|
errors::{CheckError, EColor, SourceRange},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{CheckInfo, Info, MersStatement};
|
use super::{CheckInfo, Info, MersStatement};
|
||||||
@ -45,12 +43,17 @@ impl MersStatement for CustomType {
|
|||||||
} else {
|
} else {
|
||||||
if let Err(e) = t {
|
if let Err(e) = t {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.msg(format!(
|
.msg(vec![
|
||||||
" {} {} {} (`[[_] := ...]` indicates that `...` must be type-correct)",
|
(
|
||||||
"<<".bright_red(),
|
" << Custom type-test failed! >>".to_owned(),
|
||||||
"Custom type-test failed!".bright_red(),
|
Some(EColor::CustomTypeTestFailed),
|
||||||
">>".bright_red(),
|
),
|
||||||
))
|
(
|
||||||
|
" (`[[_] := ...]` indicates that `...` must be type-correct)"
|
||||||
|
.to_owned(),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
])
|
||||||
.err(e));
|
.err(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use colored::Colorize;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{self, tuple::TupleT, Data, Type},
|
data::{self, tuple::TupleT, Data, Type},
|
||||||
errors::{error_colors, CheckError, SourceRange},
|
errors::{CheckError, EColor, SourceRange},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::MersStatement;
|
use super::MersStatement;
|
||||||
@ -33,16 +31,21 @@ impl MersStatement for If {
|
|||||||
(self.pos_in_src.clone(), None),
|
(self.pos_in_src.clone(), None),
|
||||||
(
|
(
|
||||||
self.condition.source_range(),
|
self.condition.source_range(),
|
||||||
Some(error_colors::IfConditionNotBool),
|
Some(EColor::IfConditionNotBool),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
.msg(format!(
|
.msg(vec![
|
||||||
"The {} in an if-statement must return bool, not {}",
|
("The ".to_owned(), None),
|
||||||
"condition".color(error_colors::IfConditionNotBool),
|
("condition".to_owned(), Some(EColor::IfConditionNotBool)),
|
||||||
cond_return_type
|
(
|
||||||
.to_string()
|
" in an if-statement must return bool, not ".to_owned(),
|
||||||
.color(error_colors::IfConditionNotBool),
|
None,
|
||||||
)));
|
),
|
||||||
|
(
|
||||||
|
cond_return_type.to_string(),
|
||||||
|
Some(EColor::IfConditionNotBool),
|
||||||
|
),
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
let mut t = self.on_true.check(info, None)?;
|
let mut t = self.on_true.check(info, None)?;
|
||||||
if let Some(f) = &self.on_false {
|
if let Some(f) = &self.on_false {
|
||||||
|
@ -7,7 +7,7 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{self, Data, Type},
|
data::{self, Data, Type},
|
||||||
errors::{error_colors, CheckError, SourceRange},
|
errors::{CheckError, EColor, SourceRange},
|
||||||
info,
|
info,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -98,10 +98,10 @@ pub trait MersStatement: Debug + Send + Sync {
|
|||||||
if let Some(cutoff) = info.global.limit_runtime {
|
if let Some(cutoff) = info.global.limit_runtime {
|
||||||
if Instant::now() >= cutoff {
|
if Instant::now() >= cutoff {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.msg("maximum runtime exceeded".to_owned())
|
.msg_str("maximum runtime exceeded".to_owned())
|
||||||
.src(vec![(
|
.src(vec![(
|
||||||
self.source_range(),
|
self.source_range(),
|
||||||
Some(error_colors::MaximumRuntimeExceeded),
|
Some(EColor::MaximumRuntimeExceeded),
|
||||||
)]));
|
)]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use colored::Colorize;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{self, object::ObjectT, Data, Type},
|
data::{self, object::ObjectT, Data, Type},
|
||||||
errors::{error_colors, CheckError, SourceRange},
|
errors::{CheckError, EColor, SourceRange},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::MersStatement;
|
use super::MersStatement;
|
||||||
@ -31,34 +29,47 @@ impl MersStatement for Object {
|
|||||||
for (i, ((sn, _), (tn, t))) in self.elems.iter().zip(t.0.iter()).enumerate()
|
for (i, ((sn, _), (tn, t))) in self.elems.iter().zip(t.0.iter()).enumerate()
|
||||||
{
|
{
|
||||||
if sn != tn {
|
if sn != tn {
|
||||||
return Err(format!("can't init an {} with type {}{} - field mismatch: {sn} != {tn}", "object".color(error_colors::InitTo),
|
return Err(CheckError::new().msg(vec![
|
||||||
t.to_string().color(error_colors::InitFrom),
|
("can't init an ".to_owned(), None),
|
||||||
if print_is_part_of {
|
("object".to_owned(), Some(EColor::InitTo)),
|
||||||
format!(
|
(" with type ".to_owned(), None),
|
||||||
", which is part of {}",
|
(t.to_string(), Some(EColor::InitFrom)),
|
||||||
init_to.to_string().color(error_colors::InitFrom)
|
if print_is_part_of {
|
||||||
)
|
(", which is part of ".to_owned(), None)
|
||||||
} else {
|
} else {
|
||||||
format!("")
|
(String::new(), None)
|
||||||
}
|
},
|
||||||
).into());
|
if print_is_part_of {
|
||||||
|
(init_to.to_string(), Some(EColor::InitFrom))
|
||||||
|
} else {
|
||||||
|
(String::new(), None)
|
||||||
|
},
|
||||||
|
(" - field mismatch: ".to_owned(), None),
|
||||||
|
(sn.to_owned(), None),
|
||||||
|
(" != ".to_owned(), None),
|
||||||
|
(tn.to_owned(), None),
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
acc[i].add_all(&t);
|
acc[i].add_all(&t);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(format!(
|
return Err(CheckError::new().msg(vec![
|
||||||
"can't init an {} with type {}{} - source has {}",
|
("can't init an ".to_owned(), None),
|
||||||
"object".color(error_colors::InitTo),
|
("object".to_owned(), Some(EColor::InitTo)),
|
||||||
t.to_string().color(error_colors::InitFrom),
|
(" with type ".to_owned(), None),
|
||||||
|
(t.to_string(), Some(EColor::InitFrom)),
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
format!(
|
(", which is part of ".to_owned(), None)
|
||||||
", which is part of {}",
|
|
||||||
init_to.to_string().color(error_colors::InitFrom)
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
format!("")
|
(format!(""), None)
|
||||||
},
|
},
|
||||||
if self.elems.len() > t.0.len() {
|
if print_is_part_of {
|
||||||
|
(init_to.to_string(), Some(EColor::InitFrom))
|
||||||
|
} else {
|
||||||
|
(format!(""), None)
|
||||||
|
},
|
||||||
|
(" - source has ".to_owned(), None),
|
||||||
|
(if self.elems.len() > t.0.len() {
|
||||||
format!("less fields ({}, not {})", t.0.len(), self.elems.len())
|
format!("less fields ({}, not {})", t.0.len(), self.elems.len())
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
@ -74,25 +85,30 @@ impl MersStatement for Object {
|
|||||||
.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())
|
||||||
)
|
)
|
||||||
}
|
}, None)
|
||||||
)
|
]));
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(format!(
|
return Err(CheckError::new().msg(vec![
|
||||||
"can't init an {} with type {}{} - only objects can be assigned to objects",
|
("can't init an ".to_owned(), None),
|
||||||
"object".color(error_colors::InitTo),
|
("object".to_owned(), Some(EColor::InitTo)),
|
||||||
t.to_string().color(error_colors::InitFrom),
|
(" with type ".to_owned(), None),
|
||||||
|
(t.to_string(), Some(EColor::InitFrom)),
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
format!(
|
(", which is part of ".to_owned(), None)
|
||||||
", which is part of {}",
|
|
||||||
init_to.to_string().color(error_colors::InitFrom)
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
format!("")
|
(format!(""), None)
|
||||||
}
|
},
|
||||||
)
|
if print_is_part_of {
|
||||||
.into());
|
(init_to.to_string(), Some(EColor::InitFrom))
|
||||||
|
} else {
|
||||||
|
(format!(""), None)
|
||||||
|
},
|
||||||
|
(
|
||||||
|
" - only objects can be assigned to objects".to_owned(),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(acc)
|
Some(acc)
|
||||||
|
@ -2,7 +2,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{self, Data, Type},
|
data::{self, Data, Type},
|
||||||
errors::{error_colors, CheckError, SourceRange},
|
errors::{CheckError, EColor, SourceRange},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Info, MersStatement};
|
use super::{Info, MersStatement};
|
||||||
@ -62,16 +62,13 @@ impl MersStatement for Try {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(CheckError::new()
|
return Err(CheckError::new()
|
||||||
.msg(format!(
|
.msg_str(format!(
|
||||||
"try: #{} is not a function, type is {ft} within {func}.",
|
"try: #{} is not a function, type is {ft} within {func}.",
|
||||||
i + 1
|
i + 1
|
||||||
))
|
))
|
||||||
.src(vec![
|
.src(vec![
|
||||||
(self.source_range(), None),
|
(self.source_range(), None),
|
||||||
(
|
(self.funcs[i].source_range(), Some(EColor::TryNotAFunction)),
|
||||||
self.funcs[i].source_range(),
|
|
||||||
Some(error_colors::TryNotAFunction),
|
|
||||||
),
|
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,15 +85,17 @@ impl MersStatement for Try {
|
|||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
let mut err = CheckError::new()
|
let mut err = CheckError::new()
|
||||||
.msg(format!(
|
.msg_str(format!(
|
||||||
"try: no function found for argument of type {arg}."
|
"try: no function found for argument of type {arg}."
|
||||||
))
|
))
|
||||||
.src(vec![(
|
.src(vec![(
|
||||||
self.pos_in_src.clone(),
|
self.pos_in_src.clone(),
|
||||||
Some(error_colors::TryNoFunctionFound),
|
Some(EColor::TryNoFunctionFound),
|
||||||
)]);
|
)]);
|
||||||
for (i, e) in errs.into_iter().enumerate() {
|
for (i, e) in errs.into_iter().enumerate() {
|
||||||
err = err.msg(format!("Error for function #{}:", i + 1)).err(e);
|
err = err
|
||||||
|
.msg_str(format!("Error for function #{}:", i + 1))
|
||||||
|
.err(e);
|
||||||
}
|
}
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use colored::Colorize;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{self, tuple::TupleT, Data, Type},
|
data::{self, tuple::TupleT, Data, Type},
|
||||||
errors::{error_colors, CheckError, SourceRange},
|
errors::{CheckError, EColor, SourceRange},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::MersStatement;
|
use super::MersStatement;
|
||||||
@ -32,33 +30,54 @@ impl MersStatement for Tuple {
|
|||||||
vec[i].add_all(&e);
|
vec[i].add_all(&e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(
|
return Err(CheckError::new().msg(vec![
|
||||||
format!("can't init a {} with type {}{} - only tuples with the same length ({}) can be assigned.",
|
("can't init a ".to_owned(), None),
|
||||||
"tuple".color(error_colors::InitTo),
|
("tuple".to_owned(), Some(EColor::InitTo)),
|
||||||
t.to_string().color(error_colors::InitFrom),
|
(" with type ".to_owned(), None),
|
||||||
|
(t.to_string(), Some(EColor::InitFrom)),
|
||||||
|
(
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
format!(", which is part of {}", init_to.to_string().color(error_colors::InitFrom))
|
", which is part of ".to_owned()
|
||||||
} else {
|
} else {
|
||||||
format!("")
|
String::new()
|
||||||
},
|
},
|
||||||
self.elems.len()
|
None,
|
||||||
).into());
|
),
|
||||||
|
if print_is_part_of {
|
||||||
|
(init_to.to_string(), Some(EColor::InitFrom))
|
||||||
|
} else {
|
||||||
|
(String::new(), None)
|
||||||
|
},
|
||||||
|
(
|
||||||
|
format!(
|
||||||
|
" - only tuples with the same length ({}) can be assigned",
|
||||||
|
self.elems.len()
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(format!(
|
return Err(CheckError::new().msg(vec![
|
||||||
"can't init a {} with type {}{} - only tuples can be assigned to tuples",
|
("can't init a ".to_owned(), None),
|
||||||
"tuple".color(error_colors::InitTo),
|
("tuple".to_owned(), Some(EColor::InitTo)),
|
||||||
t.to_string().color(error_colors::InitFrom),
|
(" with type ".to_owned(), None),
|
||||||
|
(t.to_string(), Some(EColor::InitFrom)),
|
||||||
|
(
|
||||||
|
if print_is_part_of {
|
||||||
|
", which is part of ".to_owned()
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
),
|
||||||
if print_is_part_of {
|
if print_is_part_of {
|
||||||
format!(
|
(init_to.to_string(), Some(EColor::InitFrom))
|
||||||
", which is part of {}",
|
|
||||||
init_to.to_string().color(error_colors::InitFrom)
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
format!("")
|
(String::new(), None)
|
||||||
}
|
},
|
||||||
)
|
(" - only tuples can be assigned to tuples".to_owned(), None),
|
||||||
.into());
|
]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(vec)
|
Some(vec)
|
||||||
|
Loading…
Reference in New Issue
Block a user