mers/mers_lib/src/program/run/assign_to.rs
Mark a78367f27c 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.
2024-06-26 01:02:19 +02:00

102 lines
3.5 KiB
Rust
Executable File

use crate::{
data::{self, Data, Type},
errors::{CheckError, EColor, SourceRange},
};
use super::{CheckInfo, MersStatement};
#[derive(Debug)]
pub struct AssignTo {
pub pos_in_src: SourceRange,
pub is_init: bool,
pub target: Box<dyn MersStatement>,
pub source: Box<dyn MersStatement>,
}
impl MersStatement for AssignTo {
fn check_custom(
&self,
info: &mut CheckInfo,
init_to: Option<&Type>,
) -> Result<Type, CheckError> {
if init_to.is_some() {
return Err("can't init to statement type AssignTo".to_string().into());
}
let source = self.source.check(info, None)?;
let target = match self
.target
.check(info, if self.is_init { Some(&source) } else { None })
{
Ok(v) => v,
Err(e) => {
if !self.is_init {
return Err(e);
}
return Err(CheckError::new()
.src(vec![
(self.pos_in_src.clone(), None),
(self.target.source_range(), Some(EColor::InitTo)),
(self.source.source_range(), Some(EColor::InitFrom)),
])
.msg_str(format!("Cannot initialize:"))
.err(e));
}
};
if !self.is_init {
if let Some(t) = target.dereference() {
if !source.is_included_in(&t) {
return Err(CheckError::new()
.src(vec![
(self.pos_in_src.clone(), None),
(self.target.source_range(), Some(EColor::AssignTo)),
(self.source.source_range(), Some(EColor::AssignFrom)),
])
.msg(vec![
("can't assign ".to_owned(), None),
(source.to_string(), Some(EColor::AssignFrom)),
(" to ".to_owned(), None),
(target.to_string(), Some(EColor::AssignTo)),
(" because it isn't included in ".to_owned(), None),
(t.to_string(), None),
]));
}
} else {
return Err(CheckError::new()
.src(vec![
(self.pos_in_src.clone(), None),
(
self.target.source_range(),
Some(EColor::AssignTargetNonReference),
),
])
.msg(vec![
("can't assign to ".to_owned(), None),
(
"non-reference!".to_owned(),
Some(EColor::AssignTargetNonReference),
),
]));
}
}
Ok(Type::empty_tuple())
}
fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
let source = self.source.run(info)?;
let target = self.target.run(info)?;
data::defs::assign(&source, &target);
Ok(Data::empty_tuple())
}
fn has_scope(&self) -> bool {
false
}
fn source_range(&self) -> SourceRange {
self.pos_in_src.clone()
}
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
vec![self.target.as_ref(), self.source.as_ref()]
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}