fix bug where error would reference wrong file

This commit is contained in:
Mark 2023-11-24 13:19:38 +01:00
parent 12af47d18a
commit 0a9eea2045
29 changed files with 173 additions and 194 deletions

View File

@ -1,6 +1,6 @@
use clap::{Parser, Subcommand, ValueEnum};
use mers_lib::prelude_compile::*;
use std::{fmt::Display, fs, path::PathBuf, process::exit};
use std::{fmt::Display, path::PathBuf, process::exit, sync::Arc};
mod cfg_globals;
@ -78,10 +78,11 @@ fn main() {
},
Command::Exec { source } => Source::new_from_string(source),
};
let parsed = match parse(&mut source) {
let srca = Arc::new(source.clone());
let parsed = match parse(&mut source, &srca) {
Ok(v) => v,
Err(e) => {
eprintln!("{}", e.display(&source).show_comments(!args.hide_comments));
eprintln!("{}", e.display().show_comments(!args.hide_comments));
exit(20);
}
};
@ -90,7 +91,7 @@ fn main() {
let run = match parsed.compile(&mut info_parsed, Default::default()) {
Ok(v) => v,
Err(e) => {
eprintln!("{}", e.display(&source).show_comments(!args.hide_comments));
eprintln!("{}", e.display().show_comments(!args.hide_comments));
exit(24);
}
};
@ -104,7 +105,7 @@ fn main() {
let return_type = match run.check(&mut info_check, None) {
Ok(v) => v,
Err(e) => {
eprint!("{}", e.display(&source).show_comments(!args.hide_comments));
eprint!("{}", e.display().show_comments(!args.hide_comments));
exit(28);
}
};

View File

@ -1,4 +1,7 @@
use std::fmt::{Debug, Display};
use std::{
fmt::{Debug, Display},
sync::Arc,
};
use colored::Colorize;
use line_span::LineSpans;
@ -14,14 +17,16 @@ impl SourcePos {
}
}
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Debug)]
pub struct SourceRange {
in_file: Arc<Source>,
start: SourcePos,
end: SourcePos,
}
impl From<(SourcePos, SourcePos)> for SourceRange {
fn from(value: (SourcePos, SourcePos)) -> Self {
impl From<(SourcePos, SourcePos, &Arc<Source>)> for SourceRange {
fn from(value: (SourcePos, SourcePos, &Arc<Source>)) -> Self {
SourceRange {
in_file: Arc::clone(value.2),
start: value.0,
end: value.1,
}
@ -74,7 +79,7 @@ pub mod error_colors {
enum CheckErrorComponent {
Message(String),
Error(CheckError),
ErrorWithSrc(CheckErrorWithSrc),
ErrorWithDifferentSource(CheckError),
Source(Vec<(SourceRange, Option<colored::Color>)>),
}
#[derive(Clone)]
@ -88,13 +93,6 @@ pub struct CheckErrorHRConfig {
#[cfg(feature = "parse")]
pub struct CheckErrorDisplay<'a> {
e: &'a CheckError,
src: Option<&'a Source>,
pub show_comments: bool,
}
#[cfg(feature = "parse")]
pub struct CheckErrorWithSrc {
e: CheckError,
src: Source,
pub show_comments: bool,
}
#[cfg(feature = "parse")]
@ -105,33 +103,10 @@ impl<'a> CheckErrorDisplay<'a> {
}
}
#[cfg(feature = "parse")]
impl CheckErrorWithSrc {
pub fn show_comments(mut self, show_comments: bool) -> Self {
self.show_comments = show_comments;
self
}
}
#[cfg(feature = "parse")]
impl Display for CheckErrorDisplay<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.e.human_readable(
f,
self.src,
&CheckErrorHRConfig {
indent_start: String::new(),
indent_default: String::new(),
indent_end: String::new(),
show_comments: self.show_comments,
},
)
}
}
#[cfg(feature = "parse")]
impl Display for CheckErrorWithSrc {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.e.human_readable(
f,
Some(&self.src),
&CheckErrorHRConfig {
indent_start: String::new(),
indent_default: String::new(),
@ -155,29 +130,16 @@ impl CheckError {
pub(crate) fn err(self, e: Self) -> Self {
self.add(CheckErrorComponent::Error(e))
}
pub(crate) fn err_with_src(self, e: CheckError, src: Source) -> Self {
self.add(CheckErrorComponent::ErrorWithSrc(CheckErrorWithSrc {
e,
src,
show_comments: true,
}))
pub(crate) fn err_with_diff_src(self, e: CheckError) -> Self {
self.add(CheckErrorComponent::ErrorWithDifferentSource(e))
}
pub(crate) fn src(self, s: Vec<(SourceRange, Option<colored::Color>)>) -> Self {
self.add(CheckErrorComponent::Source(s))
}
#[cfg(feature = "parse")]
pub fn display<'a>(&'a self, src: &'a Source) -> CheckErrorDisplay<'a> {
pub fn display<'a>(&'a self) -> CheckErrorDisplay<'a> {
CheckErrorDisplay {
e: self,
src: Some(src),
show_comments: true,
}
}
#[cfg(feature = "parse")]
pub fn display_no_src<'a>(&'a self) -> CheckErrorDisplay<'a> {
CheckErrorDisplay {
e: self,
src: None,
show_comments: true,
}
}
@ -186,7 +148,6 @@ impl CheckError {
fn human_readable(
&self,
f: &mut std::fmt::Formatter<'_>,
src: Option<&Source>,
cfg: &CheckErrorHRConfig,
) -> std::fmt::Result {
use crate::parsing::SourceFrom;
@ -211,18 +172,18 @@ impl CheckError {
cfg.indent_start.push_str("");
cfg.indent_default.push_str("");
cfg.indent_end.push_str("");
err.human_readable(f, src, &cfg)?;
err.human_readable(f, &cfg)?;
}
CheckErrorComponent::ErrorWithSrc(err) => {
CheckErrorComponent::ErrorWithDifferentSource(err) => {
let mut cfg = cfg.clone();
cfg.indent_start.push_str(&"".bright_yellow().to_string());
cfg.indent_default
.push_str(&"".bright_yellow().to_string());
cfg.indent_end.push_str(&"".bright_yellow().to_string());
err.e.human_readable(f, Some(&err.src), &cfg)?;
err.human_readable(f, &cfg)?;
}
CheckErrorComponent::Source(highlights) => {
if let Some(src) = src {
if let Some(src) = highlights.first().map(|v| v.0.in_file.as_ref()) {
let start = highlights.iter().map(|v| v.0.start.pos()).min();
let end = highlights.iter().map(|v| v.0.end.pos()).max();
if let (Some(start_in_line), Some(end_in_line)) = (start, end) {
@ -370,6 +331,6 @@ impl Debug for CheckError {
}
impl Display for CheckError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.display_no_src())
write!(f, "{}", self.display())
}
}

View File

@ -8,11 +8,14 @@ use crate::{
pub mod statements;
pub mod types;
pub fn parse(src: &mut Source) -> Result<Box<dyn program::parsed::MersStatement>, CheckError> {
pub fn parse(
src: &mut Source,
srca: &Arc<Source>,
) -> Result<Box<dyn program::parsed::MersStatement>, CheckError> {
let pos_in_src = src.get_pos();
let statements = statements::parse_multiple(src, "")?;
let statements = statements::parse_multiple(src, srca, "")?;
let block = Block {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
statements,
};
Ok(Box::new(block))

View File

@ -1,4 +1,4 @@
use std::path::PathBuf;
use std::{path::PathBuf, sync::Arc};
use super::{Source, SourcePos};
use crate::{
@ -12,6 +12,7 @@ use crate::{
pub fn parse(
src: &mut Source,
srca: &Arc<Source>,
) -> Result<Option<Box<dyn program::parsed::MersStatement>>, CheckError> {
src.section_begin("statement".to_string());
src.skip_whitespace();
@ -37,11 +38,11 @@ pub fn parse(
if src.peek_word() == ":=" {
src.next_word();
// [[name] := statement]
let statement = match parse(src) {
let statement = match parse(src, srca) {
Ok(Some(v)) => v,
Ok(None) => {
return Err(CheckError::new()
.src(vec![((pos_in_src, src.get_pos()).into(), None)])
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("EOF after `[...]` type annotation")))
}
Err(e) => return Err(e),
@ -52,14 +53,14 @@ pub fn parse(
)));
}
Box::new(program::parsed::custom_type::CustomType {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
name,
source: Err(statement),
})
} else {
// [[name] type]
src.skip_whitespace();
let as_type = super::types::parse_type(src)?;
let as_type = super::types::parse_type(src, srca)?;
src.skip_whitespace();
if !matches!(src.next_char(), Some(']')) {
return Err(CheckError::new().msg(format!(
@ -67,7 +68,7 @@ pub fn parse(
)));
}
Box::new(program::parsed::custom_type::CustomType {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
name,
source: Ok(as_type),
})
@ -76,28 +77,28 @@ pub fn parse(
// [type] statement
src.skip_whitespace();
let type_pos_in_src = src.get_pos();
let as_type = super::types::parse_type(src)?;
let type_pos_in_src = (type_pos_in_src, src.get_pos()).into();
let as_type = super::types::parse_type(src, srca)?;
let type_pos_in_src = (type_pos_in_src, src.get_pos(), srca).into();
src.skip_whitespace();
if !matches!(src.next_char(), Some(']')) {
return Err(CheckError::new()
.src(vec![(
(pos_in_src, src.get_pos()).into(),
(pos_in_src, src.get_pos(), srca).into(),
Some(error_colors::TypeAnnotationNoClosingBracket),
)])
.msg(format!("Missing closing bracket ']' after type annotation")));
}
let statement = match parse(src) {
let statement = match parse(src, srca) {
Ok(Some(v)) => v,
Ok(None) => {
return Err(CheckError::new()
.src(vec![((pos_in_src, src.get_pos()).into(), None)])
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("EOF after `[...]` type annotation")))
}
Err(e) => return Err(e),
};
Box::new(AsType {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
statement,
as_type,
type_pos_in_src,
@ -105,7 +106,7 @@ pub fn parse(
})
}));
}
let mut first = if let Some(s) = parse_no_chain(src)? {
let mut first = if let Some(s) = parse_no_chain(src, srca)? {
s
} else {
return Ok(None);
@ -116,13 +117,13 @@ pub fn parse(
":=" => {
let pos_in_src = src.get_pos();
src.next_word();
let source = parse(src)?.ok_or_else(|| {
let source = parse(src, srca)?.ok_or_else(|| {
CheckError::new()
.src(vec![((pos_in_src, src.get_pos()).into(), None)])
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("EOF after `:=`"))
})?;
first = Box::new(program::parsed::init_to::InitTo {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
target: first,
source,
});
@ -130,13 +131,13 @@ pub fn parse(
"=" => {
let pos_in_src = src.get_pos();
src.next_word();
let source = parse(src)?.ok_or_else(|| {
let source = parse(src, srca)?.ok_or_else(|| {
CheckError::new()
.src(vec![((pos_in_src, src.get_pos()).into(), None)])
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("EOF after `=`"))
})?;
first = Box::new(program::parsed::assign_to::AssignTo {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
target: first,
source,
});
@ -144,17 +145,17 @@ pub fn parse(
"->" => {
let pos_in_src = src.get_pos();
src.next_word();
let run = match parse(src) {
let run = match parse(src, srca) {
Ok(Some(v)) => v,
Ok(None) => {
return Err(CheckError::new()
.src(vec![((pos_in_src, src.get_pos()).into(), None)])
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("EOF after `->`")))
}
Err(e) => return Err(e),
};
first = Box::new(program::parsed::function::Function {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
arg: first,
run,
});
@ -164,11 +165,11 @@ pub fn parse(
let dot_in_src = src.get_pos();
if let Some('.') = src.peek_char() {
src.next_char();
let chained = match parse_no_chain(src) {
let chained = match parse_no_chain(src, srca) {
Ok(Some(v)) => v,
Ok(None) => {
return Err(CheckError::new()
.src(vec![((dot_in_src, src.get_pos()).into(), None)])
.src(vec![((dot_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("EOF after `.`")))
}
Err(e) => return Err(e),
@ -176,14 +177,14 @@ pub fn parse(
// allow a.f(b, c) syntax (but not f(a, b, c))
if let Some('(') = src.peek_char() {
src.next_char();
let elems = parse_multiple(src, ")")?;
let elems = parse_multiple(src, srca, ")")?;
first = Box::new(program::parsed::tuple::Tuple {
pos_in_src: (first.source_range().start(), src.get_pos()).into(),
pos_in_src: (first.source_range().start(), src.get_pos(), srca).into(),
elems: [first].into_iter().chain(elems).collect(),
});
}
first = Box::new(program::parsed::chain::Chain {
pos_in_src: (first.source_range().start(), src.get_pos()).into(),
pos_in_src: (first.source_range().start(), src.get_pos(), srca).into(),
first,
chained,
});
@ -201,6 +202,7 @@ pub fn parse(
}
pub fn parse_multiple(
src: &mut Source,
srca: &Arc<Source>,
end: &str,
) -> Result<Vec<Box<dyn MersStatement>>, CheckError> {
src.section_begin("block".to_string());
@ -210,7 +212,7 @@ pub fn parse_multiple(
if src.peek_char().is_some_and(|ch| end.contains(ch)) {
src.next_char();
break;
} else if let Some(s) = parse(src)? {
} else if let Some(s) = parse(src, srca)? {
statements.push(s);
} else {
// EOF
@ -221,6 +223,7 @@ pub fn parse_multiple(
}
pub fn parse_no_chain(
src: &mut Source,
srca: &Arc<Source>,
) -> Result<Option<Box<dyn program::parsed::MersStatement>>, CheckError> {
src.skip_whitespace();
src.section_begin("statement no chain".to_string());
@ -230,14 +233,14 @@ pub fn parse_no_chain(
src.next_char();
if src.peek_char().is_none() {
return Err(CheckError::new()
.src(vec![((pos_in_src, src.get_pos()).into(), None)])
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("EOF after #")));
}
if src.peek_char().is_some_and(|ch| ch.is_whitespace()) {
src.skip_whitespace();
return Err(CheckError::new()
.src(vec![(
(pos_in_src, src.get_pos()).into(),
(pos_in_src, src.get_pos(), srca).into(),
Some(error_colors::WhitespaceAfterHashtag),
)])
.msg(format!("Whitespace after #")));
@ -248,18 +251,17 @@ pub fn parse_no_chain(
src.skip_whitespace();
let string_in_src = src.get_pos();
if src.next_char() == Some('"') {
let file_path = parse_string(src, string_in_src)?;
let file_path = parse_string(src, srca, string_in_src)?;
match Source::new_from_file(PathBuf::from(&file_path)) {
Ok(mut inner_src) => {
let inner_srca = Arc::new(inner_src.clone());
return Ok(Some(Box::new(
program::parsed::include_mers::IncludeMers {
pos_in_src: (pos_in_src, src.get_pos()).into(),
include: match super::parse(&mut inner_src) {
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
include: match super::parse(&mut inner_src, &inner_srca) {
Ok(v) => v,
Err(e) => {
return Err(
CheckError::new().err_with_src(e, inner_src)
)
return Err(CheckError::new().err_with_diff_src(e))
}
},
inner_src,
@ -269,9 +271,9 @@ pub fn parse_no_chain(
Err(e) => {
return Err(CheckError::new()
.src(vec![
((pos_in_src, end_in_src).into(), None),
((pos_in_src, end_in_src, srca).into(), None),
(
(string_in_src, src.get_pos()).into(),
(string_in_src, src.get_pos(), srca).into(),
Some(error_colors::HashIncludeCantLoadFile),
),
])
@ -281,8 +283,8 @@ pub fn parse_no_chain(
} else {
return Err(CheckError::new()
.src(vec![
((pos_in_src, end_in_src).into(), None),
((string_in_src, src.get_pos()).into(), Some(error_colors::HashIncludeNotAString)),
((pos_in_src, end_in_src, srca).into(), None),
((string_in_src, src.get_pos(), srca).into(), Some(error_colors::HashIncludeNotAString)),
])
.msg(format!(
"#include must be followed by a string literal like \"file.mers\" (\" expected)."
@ -293,7 +295,7 @@ pub fn parse_no_chain(
let msg = format!("Unknown #statement: {other}");
return Err(CheckError::new()
.src(vec![(
(pos_in_src, src.get_pos()).into(),
(pos_in_src, src.get_pos(), srca).into(),
Some(error_colors::HashUnknown),
)])
.msg(msg));
@ -303,18 +305,18 @@ pub fn parse_no_chain(
Some('{') => {
let pos_in_src = src.get_pos();
src.next_char();
let statements = parse_multiple(src, "}")?;
let statements = parse_multiple(src, srca, "}")?;
return Ok(Some(Box::new(program::parsed::block::Block {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
statements,
})));
}
Some('(') => {
let pos_in_src = src.get_pos();
src.next_char();
let elems = parse_multiple(src, ")")?;
let elems = parse_multiple(src, srca, ")")?;
return Ok(Some(Box::new(program::parsed::tuple::Tuple {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
elems,
})));
}
@ -322,9 +324,9 @@ pub fn parse_no_chain(
src.section_begin("string literal".to_string());
let pos_in_src = src.get_pos();
src.next_char();
let s = parse_string(src, pos_in_src)?;
let s = parse_string(src, srca, pos_in_src)?;
return Ok(Some(Box::new(program::parsed::value::Value {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
data: Data::new(crate::data::string::String(s)),
})));
}
@ -335,20 +337,20 @@ pub fn parse_no_chain(
"if" => {
src.section_begin("if".to_string());
src.skip_whitespace();
let condition = match parse(src) {
let condition = match parse(src, srca) {
Ok(Some(v)) => v,
Ok(None) => {
return Err(CheckError::new()
.src(vec![((pos_in_src, src.get_pos()).into(), None)])
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("EOF in `if`")))
}
Err(e) => return Err(e),
};
let on_true = match parse(src) {
let on_true = match parse(src, srca) {
Ok(Some(v)) => v,
Ok(None) => {
return Err(CheckError::new()
.src(vec![((pos_in_src, src.get_pos()).into(), None)])
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("EOF after `if <condition>`")))
}
Err(e) => return Err(e),
@ -358,11 +360,11 @@ pub fn parse_no_chain(
if src.peek_word() == "else" {
src.section_begin("else".to_string());
src.next_word();
Some(match parse(src) {
Some(match parse(src, srca) {
Ok(Some(v)) => v,
Ok(None) => {
return Err(CheckError::new()
.src(vec![((pos_in_src, src.get_pos()).into(), None)])
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
.msg(format!("EOF after `else`")))
}
Err(e) => return Err(e),
@ -372,18 +374,18 @@ pub fn parse_no_chain(
}
};
Box::new(program::parsed::r#if::If {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
condition,
on_true,
on_false,
})
}
"true" => Box::new(program::parsed::value::Value {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
data: Data::new(crate::data::bool::Bool(true)),
}),
"false" => Box::new(program::parsed::value::Value {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
data: Data::new(crate::data::bool::Bool(false)),
}),
"" => return Ok(None),
@ -396,32 +398,32 @@ pub fn parse_no_chain(
src.next_char();
if let Ok(num) = format!("{o}.{}", src.next_word()).parse() {
Box::new(program::parsed::value::Value {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
data: Data::new(crate::data::float::Float(num)),
})
} else {
src.set_pos(here);
Box::new(program::parsed::value::Value {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
data: Data::new(crate::data::int::Int(n)),
})
}
} else {
Box::new(program::parsed::value::Value {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
data: Data::new(crate::data::int::Int(n)),
})
}
} else {
if let Some('&') = o.chars().next() {
Box::new(program::parsed::variable::Variable {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
is_ref: true,
var: o[1..].to_string(),
})
} else {
Box::new(program::parsed::variable::Variable {
pos_in_src: (pos_in_src, src.get_pos()).into(),
pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
is_ref: false,
var: o.to_string(),
})
@ -432,11 +434,16 @@ pub fn parse_no_chain(
}
/// expects to be called *after* a " character is consumed from src
pub fn parse_string(src: &mut Source, double_quote: SourcePos) -> Result<String, CheckError> {
parse_string_custom_end(src, double_quote, '"', '"')
pub fn parse_string(
src: &mut Source,
srca: &Arc<Source>,
double_quote: SourcePos,
) -> Result<String, CheckError> {
parse_string_custom_end(src, srca, double_quote, '"', '"')
}
pub fn parse_string_custom_end(
src: &mut Source,
srca: &Arc<Source>,
opening: SourcePos,
opening_char: char,
closing_char: char,
@ -456,7 +463,7 @@ pub fn parse_string_custom_end(
Some(o) => {
return Err(CheckError::new()
.src(vec![(
(backslash_in_src, src.get_pos()).into(),
(backslash_in_src, src.get_pos(), srca).into(),
Some(error_colors::BackslashEscapeUnknown),
)])
.msg(format!("unknown backslash escape '\\{o}'")));
@ -464,7 +471,7 @@ pub fn parse_string_custom_end(
None => {
return Err(CheckError::new()
.src(vec![(
(backslash_in_src, src.get_pos()).into(),
(backslash_in_src, src.get_pos(), srca).into(),
Some(error_colors::BackslashEscapeEOF),
)])
.msg(format!("EOF in backslash escape")));
@ -478,7 +485,7 @@ pub fn parse_string_custom_end(
} else {
return Err(CheckError::new()
.src(vec![(
(opening, src.get_pos()).into(),
(opening, src.get_pos(), srca).into(),
Some(error_colors::StringEOF),
)])
.msg(format!(

View File

@ -16,7 +16,7 @@ pub enum ParsedType {
TypeWithInfo(String, String),
}
pub fn parse_single_type(src: &mut Source) -> Result<ParsedType, CheckError> {
pub fn parse_single_type(src: &mut Source, srca: &Arc<Source>) -> Result<ParsedType, CheckError> {
src.section_begin("parse single type".to_string());
src.skip_whitespace();
Ok(match src.peek_char() {
@ -25,7 +25,7 @@ pub fn parse_single_type(src: &mut Source) -> Result<ParsedType, CheckError> {
src.next_char();
if let Some('{') = src.peek_char() {
src.next_char();
let types = parse_type(src)?;
let types = parse_type(src, srca)?;
let nc = src.next_char();
if !matches!(nc, Some('}')) {
let nc = if let Some(nc) = nc {
@ -39,7 +39,7 @@ pub fn parse_single_type(src: &mut Source) -> Result<ParsedType, CheckError> {
}
ParsedType::Reference(types)
} else {
ParsedType::Reference(vec![parse_single_type(src)?])
ParsedType::Reference(vec![parse_single_type(src, srca)?])
}
}
// Tuple
@ -53,7 +53,7 @@ pub fn parse_single_type(src: &mut Source) -> Result<ParsedType, CheckError> {
// empty tuple, don't even start the loop
} else {
loop {
inner.push(parse_type(src)?);
inner.push(parse_type(src, srca)?);
match src.peek_char() {
Some(')') => {
src.next_char();
@ -67,9 +67,9 @@ pub fn parse_single_type(src: &mut Source) -> Result<ParsedType, CheckError> {
src.next_char();
return Err(CheckError::new()
.src(vec![
((pos_in_src, src.get_pos()).into(), None),
((pos_in_src, src.get_pos(), srca).into(), None),
(
(ppos, src.get_pos()).into(),
(ppos, src.get_pos(), srca).into(),
Some(error_colors::BadCharInTupleType),
),
])
@ -90,7 +90,7 @@ pub fn parse_single_type(src: &mut Source) -> Result<ParsedType, CheckError> {
src.next_char();
ParsedType::TypeWithInfo(
t,
super::statements::parse_string_custom_end(src, pos, '<', '>')?,
super::statements::parse_string_custom_end(src, srca, pos, '<', '>')?,
)
} else {
ParsedType::Type(t)
@ -100,11 +100,11 @@ pub fn parse_single_type(src: &mut Source) -> Result<ParsedType, CheckError> {
})
}
pub fn parse_type(src: &mut Source) -> Result<Vec<ParsedType>, CheckError> {
pub fn parse_type(src: &mut Source, srca: &Arc<Source>) -> Result<Vec<ParsedType>, CheckError> {
src.section_begin("parse single type".to_string());
let mut types = vec![];
loop {
types.push(parse_single_type(src)?);
types.push(parse_single_type(src, srca)?);
src.skip_whitespace();
if let Some('/') = src.peek_char() {
src.next_char();

View File

@ -23,7 +23,9 @@ impl Config {
// TODO: Type with generics
self.add_type("List".to_string(),
Err(Arc::new(|s, i| {
let t = crate::parsing::types::parse_type(&mut Source::new_from_string_raw(s.to_owned()))?;
let mut src = Source::new_from_string_raw(s.to_owned());
let srca = Arc::new(src.clone());
let t = crate::parsing::types::parse_type(&mut src, &srca)?;
Ok(Arc::new(ListT(crate::parsing::types::type_from_parsed(&t, i)?)))})))
.add_var(
"pop".to_string(),

View File

@ -21,7 +21,9 @@ impl Config {
self.add_type(
"Thread".to_string(),
Err(Arc::new(|s, i| {
let t = crate::parsing::types::parse_type(&mut Source::new_from_string_raw(s.to_owned()))?;
let mut src = Source::new_from_string_raw(s.to_owned());
let srca = Arc::new(src.clone());
let t = crate::parsing::types::parse_type(&mut src, &srca)?;
Ok(Arc::new(ThreadT(crate::parsing::types::type_from_parsed(&t, i)?)))
})),
)

View File

@ -25,14 +25,14 @@ impl MersStatement for AsType {
comp: CompInfo,
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
Ok(Box::new(program::run::as_type::AsType {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
statement: self.statement.compile(info, comp)?,
as_type: self.as_type.clone(),
type_pos_in_src: self.type_pos_in_src,
type_pos_in_src: self.type_pos_in_src.clone(),
expand_type: self.expand_type,
}))
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -22,13 +22,13 @@ impl MersStatement for AssignTo {
comp: CompInfo,
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
Ok(Box::new(program::run::assign_to::AssignTo {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
is_init: false,
source: self.source.compile(info, comp)?,
target: self.target.compile(info, comp)?,
}))
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -21,7 +21,7 @@ impl MersStatement for Block {
comp: CompInfo,
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
Ok(Box::new(program::run::block::Block {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
statements: self
.statements
.iter()
@ -30,6 +30,6 @@ impl MersStatement for Block {
}))
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -21,13 +21,13 @@ impl MersStatement for Chain {
comp: CompInfo,
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
Ok(Box::new(program::run::chain::Chain {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
first: self.first.compile(info, comp)?,
chained: self.chained.compile(info, comp)?,
as_part_of_include: None,
}))
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -23,7 +23,7 @@ impl MersStatement for CustomType {
Err(s) => Err(s.compile(info, comp)?),
};
Ok(Box::new(crate::program::run::custom_type::CustomType {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
name: self.name.clone(),
source: Box::new(move |ci| match &src {
Ok(parsed) => Ok(Ok(Arc::new(type_from_parsed(parsed, ci)?))),
@ -35,7 +35,7 @@ impl MersStatement for CustomType {
false
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -32,7 +32,7 @@ impl MersStatement for Function {
let arg2: Arc<Box<dyn crate::program::run::MersStatement>> = Arc::clone(&arg_target);
let run2: Arc<Box<dyn crate::program::run::MersStatement>> = Arc::clone(&run);
Ok(Box::new(program::run::function::Function {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
func_no_info: data::function::Function {
info: Arc::new(program::run::Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
@ -48,6 +48,6 @@ impl MersStatement for Function {
}))
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -23,7 +23,7 @@ impl MersStatement for If {
comp: CompInfo,
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
Ok(Box::new(program::run::r#if::If {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
condition: self.condition.compile(info, comp)?,
on_true: self.on_true.compile(info, comp)?,
on_false: if let Some(v) = &self.on_false {
@ -34,6 +34,6 @@ impl MersStatement for If {
}))
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -33,7 +33,7 @@ impl MersStatement for IncludeMers {
Err(e) => {
return Err(CheckError::new()
.src(vec![(
self.pos_in_src,
self.pos_in_src.clone(),
Some(error_colors::HashIncludeErrorInIncludedFile),
)])
.msg(
@ -41,18 +41,18 @@ impl MersStatement for IncludeMers {
.color(error_colors::HashIncludeErrorInIncludedFile)
.to_string(),
)
.err_with_src(e, self.inner_src.clone()))
.err_with_diff_src(e))
}
};
let compiled2 = Arc::clone(&compiled);
Ok(Box::new(program::run::chain::Chain {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
first: Box::new(program::run::value::Value {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
val: Data::empty_tuple(),
}),
chained: Box::new(program::run::function::Function {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
func_no_info: data::function::Function {
info: Arc::new(info::Info::neverused()),
info_check: Arc::new(Mutex::new(info::Info::neverused())),
@ -64,6 +64,6 @@ impl MersStatement for IncludeMers {
}))
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -28,13 +28,13 @@ impl MersStatement for InitTo {
let target = self.target.compile(info, comp)?;
comp.is_init = false;
Ok(Box::new(program::run::assign_to::AssignTo {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
is_init: true,
source,
target,
}))
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -21,7 +21,7 @@ impl MersStatement for Tuple {
comp: CompInfo,
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
Ok(Box::new(program::run::tuple::Tuple {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
elems: self
.elems
.iter()
@ -30,6 +30,6 @@ impl MersStatement for Tuple {
}))
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -22,11 +22,11 @@ impl MersStatement for Value {
_comp: CompInfo,
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
Ok(Box::new(program::run::value::Value {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
val: self.data.clone(),
}))
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -35,7 +35,7 @@ impl MersStatement for Variable {
}
}
Ok(Box::new(program::run::variable::Variable {
pos_in_src: self.pos_in_src,
pos_in_src: self.pos_in_src.clone(),
is_init: comp.is_init,
is_ref_not_ignore: if comp.is_init {
!init_and_ignore
@ -48,12 +48,15 @@ impl MersStatement for Variable {
*v
} else {
return Err(CheckError::new()
.src(vec![(self.pos_in_src, Some(error_colors::UnknownVariable))])
.src(vec![(
self.pos_in_src.clone(),
Some(error_colors::UnknownVariable),
)])
.msg(format!("No variable named '{}' found!", self.var)));
},
}))
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -32,7 +32,7 @@ impl MersStatement for AsType {
crate::parsing::types::type_from_parsed(&self.as_type, info).map_err(|e| {
CheckError::new()
.src(vec![(
self.type_pos_in_src,
self.type_pos_in_src.clone(),
Some(error_colors::BadTypeFromParsed),
)])
.err(e)
@ -40,9 +40,9 @@ impl MersStatement for AsType {
if !return_type.is_included_in(&as_type) {
return Err(CheckError::new()
.src(vec![
(self.pos_in_src, None),
(self.pos_in_src.clone(), None),
(
self.type_pos_in_src,
self.type_pos_in_src.clone(),
Some(error_colors::AsTypeTypeAnnotation),
),
(
@ -73,6 +73,6 @@ impl MersStatement for AsType {
false
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -30,7 +30,7 @@ impl MersStatement for AssignTo {
Err(e) => {
return Err(CheckError::new()
.src(vec![
(self.pos_in_src, None),
(self.pos_in_src.clone(), None),
(self.target.source_range(), Some(error_colors::InitTo)),
(self.source.source_range(), Some(error_colors::InitFrom)),
])
@ -43,7 +43,7 @@ impl MersStatement for AssignTo {
if !source.is_included_in(&t) {
return Err(CheckError::new()
.src(vec![
(self.pos_in_src, None),
(self.pos_in_src.clone(), None),
(self.target.source_range(), Some(error_colors::AssignTo)),
(self.source.source_range(), Some(error_colors::AssignFrom)),
])
@ -57,7 +57,7 @@ impl MersStatement for AssignTo {
} else {
return Err(CheckError::new()
.src(vec![
(self.pos_in_src, None),
(self.pos_in_src.clone(), None),
(
self.target.source_range(),
Some(error_colors::AssignTargetNonReference),
@ -81,6 +81,6 @@ impl MersStatement for AssignTo {
false
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -36,6 +36,6 @@ impl MersStatement for Block {
true
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -37,10 +37,10 @@ impl MersStatement for Chain {
match (func.0)(&arg) {
Ok(t) => o.add(Arc::new(t)),
Err(e) => {
return Err(if let Some(inner_src) = &self.as_part_of_include {
return Err(if let Some(_) = &self.as_part_of_include {
CheckError::new()
.src(vec![(
self.pos_in_src,
self.pos_in_src.clone(),
Some(error_colors::HashIncludeErrorInIncludedFile),
)])
.msg(
@ -48,11 +48,11 @@ impl MersStatement for Chain {
.color(error_colors::HashIncludeErrorInIncludedFile)
.to_string(),
)
.err_with_src(e, inner_src.clone())
.err_with_diff_src(e)
} else {
CheckError::new()
.src(vec![
(self.pos_in_src, None),
(self.pos_in_src.clone(), None),
(
self.first.source_range(),
Some(error_colors::FunctionArgument),
@ -71,7 +71,7 @@ impl MersStatement for Chain {
} else {
return Err(CheckError::new()
.src(vec![
(self.pos_in_src, None),
(self.pos_in_src.clone(), None),
(
self.chained.source_range(),
Some(error_colors::ChainWithNonFunction),
@ -99,6 +99,6 @@ impl MersStatement for Chain {
false
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -52,7 +52,7 @@ impl MersStatement for CustomType {
false
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -32,6 +32,6 @@ impl MersStatement for Function {
true
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -30,7 +30,7 @@ impl MersStatement for If {
if !cond_return_type.is_included_in(&data::bool::BoolT) {
return Err(CheckError::new()
.src(vec![
(self.pos_in_src, None),
(self.pos_in_src.clone(), None),
(
self.condition.source_range(),
Some(error_colors::IfConditionNotBool),
@ -71,6 +71,6 @@ impl MersStatement for If {
true
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -91,6 +91,6 @@ impl MersStatement for Tuple {
false
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -29,6 +29,6 @@ impl MersStatement for Value {
self.val.clone()
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}

View File

@ -77,6 +77,6 @@ impl MersStatement for Variable {
}
}
fn source_range(&self) -> SourceRange {
self.pos_in_src
self.pos_in_src.clone()
}
}