nicer errors

This commit is contained in:
Mark
2024-06-21 15:50:41 +02:00
parent b11e4017ed
commit 688e28c171
13 changed files with 833 additions and 397 deletions

View File

@@ -13,6 +13,7 @@ impl Config {
/// `minus: fn` returns the first number minus all the others
/// `product: fn` returns the product of all the numbers in the tuple
/// `div: fn` returns a / b. Performs integer division if a and b are both integers.
/// `pow: fn` returns a^b or a**b.
/// `modulo: fn` returns a % b
/// `signum: fn` returns 1 for positive numbers, -1 for negative ones and 0 for 0 (always returns an Int, even when input is Float)
/// `lt: fn` returns true if the input keeps increasing, that is, for (a, b), a < b, for (a, b, c), a < b < c, and so on.
@@ -27,355 +28,308 @@ impl Config {
/// `ceil: fn` rounds the float [?] and returns an int
/// `floor: fn` rounds the float [?] and returns an int
pub fn with_math(self) -> Self {
self
.add_var("lt".to_string(), Data::new(ltgtoe_function("lt".to_string(), |l, r| match (l, r) {
self.add_var(
"lt".to_string(),
Data::new(ltgtoe_function("lt".to_string(), |l, r| match (l, r) {
(IntOrFloatOrNothing::Nothing, _) | (_, IntOrFloatOrNothing::Nothing) => true,
(IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Int(r)) => l < r,
(IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Float(r)) => (l as f64) < r,
(IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Int(r)) => l < r as f64,
(IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Float(r)) => l < r,
})))
.add_var("gt".to_string(), Data::new(ltgtoe_function("gt".to_string(), |l, r| match (l, r) {
})),
)
.add_var(
"gt".to_string(),
Data::new(ltgtoe_function("gt".to_string(), |l, r| match (l, r) {
(IntOrFloatOrNothing::Nothing, _) | (_, IntOrFloatOrNothing::Nothing) => true,
(IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Int(r)) => l > r,
(IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Float(r)) => (l as f64) > r,
(IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Int(r)) => l > r as f64,
(IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Float(r)) => l > r,
})))
.add_var("ltoe".to_string(), Data::new(ltgtoe_function("ltoe".to_string(), |l, r| match (l, r) {
})),
)
.add_var(
"ltoe".to_string(),
Data::new(ltgtoe_function("ltoe".to_string(), |l, r| match (l, r) {
(IntOrFloatOrNothing::Nothing, _) | (_, IntOrFloatOrNothing::Nothing) => true,
(IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Int(r)) => l <= r,
(IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Float(r)) => (l as f64) <= r,
(IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Int(r)) => l <= r as f64,
(IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Float(r)) => l <= r,
})))
.add_var("gtoe".to_string(), Data::new(ltgtoe_function("gtoe".to_string(), |l, r| match (l, r) {
})),
)
.add_var(
"gtoe".to_string(),
Data::new(ltgtoe_function("gtoe".to_string(), |l, r| match (l, r) {
(IntOrFloatOrNothing::Nothing, _) | (_, IntOrFloatOrNothing::Nothing) => true,
(IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Int(r)) => l >= r,
(IntOrFloatOrNothing::Int(l), IntOrFloatOrNothing::Float(r)) => (l as f64) >= r,
(IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Int(r)) => l >= r as f64,
(IntOrFloatOrNothing::Float(l), IntOrFloatOrNothing::Float(r)) => l >= r,
})))
.add_var("parse_float".to_string(), Data::new(data::function::Function {
info: Arc::new(program::run::Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(|a, _i| {
if a.is_included_in(&Type::new(data::string::StringT)) {
Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![
Type::new(data::float::FloatT),
])),
Arc::new(data::tuple::TupleT(vec![])),
]))
} else {
Err(format!("parse_float called on non-string type").into())
}
}),
run: Arc::new(|a, _i| {
Ok(if let Ok(n) = a.get().as_any().downcast_ref::<data::string::String>().unwrap().0.parse() {
Data::one_tuple(Data::new(data::float::Float(n)))
} else {
Data::empty_tuple()
})
}),
inner_statements: None,
})).add_var("parse_int".to_string(), Data::new(data::function::Function {
info: Arc::new(program::run::Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(|a, _i| {
if a.is_included_in(&Type::new(data::string::StringT)) {
Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![
Type::new(data::int::IntT),
])),
Arc::new(data::tuple::TupleT(vec![])),
]))
} else {
Err(format!("parse_float called on non-string type").into())
}
}),
run: Arc::new(|a, _i| {
Ok(if let Ok(n) = a.get().as_any().downcast_ref::<data::string::String>().unwrap().0.parse() {
Data::one_tuple(Data::new(data::int::Int(n)))
} else {
Data::empty_tuple()
})
}),
inner_statements: None,
})).add_var("signum".to_string(), Data::new(data::function::Function {
info: Arc::new(program::run::Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(|a, _i| {
if a.is_included_in(&Type::newm(vec![Arc::new(data::int::IntT), Arc::new(data::float::FloatT)])) {
Ok(Type::new(data::int::IntT))
} else {
Err(format!("signum called on non-number type").into())
}
}),
run: Arc::new(|a, _i| {
Ok(Data::new(data::int::Int(if let Some(n) = a.get().as_any().downcast_ref::<data::int::Int>() {
n.0.signum()
} else
if let Some(n) = a.get().as_any().downcast_ref::<data::float::Float>() {
if n.0 > 0.0 {
1
} else if n.0 < 0.0 {
-1
} else { 0
}
} else { return Err("called signum on non-number type".into()); })))
}),
inner_statements: None,
})) .add_var("div".to_string(), Data::new(data::function::Function {
})),
)
.add_var(
"parse_float".to_string(),
Data::new(data::function::Function {
info: Arc::new(program::run::Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(|a, _i| two_tuple_to_num(a, "div")),
run: Arc::new(|a, _i| if let Some(t) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
let left = t.0[0].get();
let right = t.0[1].get();
let (left, right) = (left.as_any(), right.as_any());
match (left.downcast_ref::<data::int::Int>(), left.downcast_ref::<data::float::Float>(),
right.downcast_ref::<data::int::Int>(), right.downcast_ref::<data::float::Float>()
) {
(Some(data::int::Int(l)), None, Some(data::int::Int(r)), None) => Ok(Data::new(data::int::Int(l.checked_div(*r).ok_or_else(|| CheckError::from("attempted to divide by zero"))?))),
(Some(data::int::Int(l)), None, None, Some(data::float::Float(r))) => Ok(Data::new(data::float::Float(*l as f64 / r))),
(None, Some(data::float::Float(l)), Some(data::int::Int(r)), None) => Ok(Data::new(data::float::Float(l / *r as f64))),
(None, Some(data::float::Float(l)), None, Some(data::float::Float(r))) => Ok(Data::new(data::float::Float(l / r))),
_ => return Err("at least one of the arguments to div were neither an int nor a float".into()),
out: Arc::new(|a, _i| {
if a.is_included_in(&Type::new(data::string::StringT)) {
Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![Type::new(data::float::FloatT)])),
Arc::new(data::tuple::TupleT(vec![])),
]))
} else {
Err(format!("parse_float called on non-string type").into())
}
} else { return Err("argument to div was not a tuple".into()); }),
}),
run: Arc::new(|a, _i| {
Ok(
if let Ok(n) = a
.get()
.as_any()
.downcast_ref::<data::string::String>()
.unwrap()
.0
.parse()
{
Data::one_tuple(Data::new(data::float::Float(n)))
} else {
Data::empty_tuple()
},
)
}),
inner_statements: None,
})).add_var("modulo".to_string(), Data::new(data::function::Function {
}),
)
.add_var(
"parse_int".to_string(),
Data::new(data::function::Function {
info: Arc::new(program::run::Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(|a, _i| two_tuple_to_num(a, "modulo")),
run: Arc::new(|a, _i| if let Some(t) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
let left = t.0[0].get();
let right = t.0[1].get();
let (left, right) = (left.as_any(), right.as_any());
match (left.downcast_ref::<data::int::Int>(), left.downcast_ref::<data::float::Float>(),
right.downcast_ref::<data::int::Int>(), right.downcast_ref::<data::float::Float>()
) {
(Some(data::int::Int(l)), None, Some(data::int::Int(r)), None) => Ok(Data::new(data::int::Int(l % r))),
(Some(data::int::Int(l)), None, None, Some(data::float::Float(r))) => Ok(Data::new(data::float::Float(*l as f64 % r))),
(None, Some(data::float::Float(l)), Some(data::int::Int(r)), None) => Ok(Data::new(data::float::Float(l % *r as f64))),
(None, Some(data::float::Float(l)), None, Some(data::float::Float(r))) => Ok(Data::new(data::float::Float(l % r))),
_ => return Err("at least one of the arguments to modulo were neither an int nor a float".into()),
out: Arc::new(|a, _i| {
if a.is_included_in(&Type::new(data::string::StringT)) {
Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![Type::new(data::int::IntT)])),
Arc::new(data::tuple::TupleT(vec![])),
]))
} else {
Err(format!("parse_float called on non-string type").into())
}
} else { return Err("argument to modulo was not a tuple".into()) }),
}),
run: Arc::new(|a, _i| {
Ok(
if let Ok(n) = a
.get()
.as_any()
.downcast_ref::<data::string::String>()
.unwrap()
.0
.parse()
{
Data::one_tuple(Data::new(data::int::Int(n)))
} else {
Data::empty_tuple()
},
)
}),
inner_statements: None,
}))
.add_var(
}),
)
.add_var(
"signum".to_string(),
Data::new(data::function::Function {
info: Arc::new(program::run::Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(|a, _i| {
if a.is_included_in(&Type::newm(vec![
Arc::new(data::int::IntT),
Arc::new(data::float::FloatT),
])) {
Ok(Type::new(data::int::IntT))
} else {
Err(format!("signum called on non-number type").into())
}
}),
run: Arc::new(|a, _i| {
Ok(Data::new(data::int::Int(
if let Some(n) = a.get().as_any().downcast_ref::<data::int::Int>() {
n.0.signum()
} else if let Some(n) =
a.get().as_any().downcast_ref::<data::float::Float>()
{
if n.0 > 0.0 {
1
} else if n.0 < 0.0 {
-1
} else {
0
}
} else {
return Err("called signum on non-number type".into());
},
)))
}),
inner_statements: None,
}),
)
.add_var(
"div".to_string(),
Data::new(two_num_tuple_to_num(
"div",
|l, r| {
l.checked_div(r)
.ok_or_else(|| CheckError::from("attempted to divide by zero"))
},
|l, r| Ok(l as f64 / r),
|l, r| Ok(l / r as f64),
|l, r| Ok(l / r),
)),
)
.add_var(
"pow".to_string(),
Data::new(two_num_tuple_to_num(
"pow",
|l, r| Ok(l.pow(r.try_into().unwrap_or(u32::MAX))),
|l, r| Ok((l as f64).powf(r)),
|l, r| {
Ok(if let Ok(r) = r.try_into() {
l.powi(r)
} else {
l.powf(r as f64)
})
},
|l, r| Ok(l.powf(r)),
)),
)
.add_var(
"modulo".to_string(),
Data::new(two_num_tuple_to_num(
"modulo",
|l, r| {
l.checked_rem(r).ok_or_else(|| {
CheckError::from(
"called modulo on two integers, and the second one was zero",
)
})
},
|l, r| Ok(l as f64 % r),
|l, r| Ok(l % r as f64),
|l, r| Ok(l % r),
)),
)
.add_var(
"sum".to_string(),
Data::new(data::function::Function {
info: Arc::new(program::run::Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(|a, _i| {
let mut ints = false;
let mut floats = false;
for a in &a.types {
if let Some(i) = a.iterable() {
if i.types
.iter()
.all(|t| t.as_any().downcast_ref::<data::int::IntT>().is_some())
{
ints = true;
} else if i.types.iter().all(|t| {
t.as_any().downcast_ref::<data::int::IntT>().is_some()
|| t.as_any().downcast_ref::<data::float::FloatT>().is_some()
}) {
floats = true;
} else {
return Err(format!("cannot get sum of iterator over type {i} because it contains types that aren't int/float").into())
}
} else {
return Err(format!(
"cannot get sum of non-iterable type {a}"
).into());
}
}
Ok(match (ints, floats) {
(_, true) => Type::new(data::float::FloatT),
(true, false) => Type::new(data::int::IntT),
(false, false) => Type::empty(),
})
}),
run: Arc::new(|a, _i| {
if let Some(i) = a.get().iterable() {
let mut sumi = 0;
let mut sumf = 0.0;
let mut usef = false;
for val in i {
let val = val?;
let o = if let Some(i) = val.get().as_any().downcast_ref::<data::int::Int>() {
sumi += i.0;
} else if let Some(i) =
val.get().as_any().downcast_ref::<data::float::Float>()
{
sumf += i.0;
usef = true;
};
o
}
Ok(if usef {
Data::new(data::float::Float(sumi as f64 + sumf))
} else {
Data::new(data::int::Int(sumi))
})
} else {
return Err("sum called on non-tuple".into());
}
}),
inner_statements: None,
}),
Data::new(num_iter_to_num("sum", Ok(0), |a, v| match (a, v) {
(Ok(a), Ok(v)) => Ok(a + v),
(Ok(a), Err(v)) => Err(a as f64 + v),
(Err(a), Ok(v)) => Err(a + v as f64),
(Err(a), Err(v)) => Err(a + v),
})),
)
.add_var(
.add_var(
"subtract".to_string(),
Data::new(data::function::Function {
info: Arc::new(program::run::Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(|a, _i| {
let mut ints = false;
let mut floats = false;
for a in &a.types {
if let Some(i) = a.iterable() {
if i.types
.iter()
.all(|t| t.as_any().downcast_ref::<data::int::IntT>().is_some())
{
ints = true;
} else if i.types.iter().all(|t| {
t.as_any().downcast_ref::<data::int::IntT>().is_some()
|| t.as_any().downcast_ref::<data::float::FloatT>().is_some()
}) {
floats = true;
} else {
return Err(format!("cannot subtract on iterator over type {i} because it contains types that aren't int/float").into())
}
} else {
return Err(format!(
"cannot subtract over non-iterable type {a}"
).into());
}
}
Ok(match (ints, floats) {
(_, true) => Type::new(data::float::FloatT),
(true, false) => Type::new(data::int::IntT),
(false, false) => Type::empty(),
})
}),
run: Arc::new(|a, _i| {
if let Some(i) = a.get().iterable() {
let mut first = true;
let mut sumi = 0;
let mut sumf = 0.0;
let mut usef = false;
for val in i {
let val = val?;
if let Some(i) = val.get().as_any().downcast_ref::<data::int::Int>() {
if first {
sumi = i.0;
} else {
sumi -= i.0;
}
} else if let Some(i) =
val.get().as_any().downcast_ref::<data::float::Float>()
{
if first {
sumf = i.0;
} else {
sumf -= i.0;
}
usef = true;
}
if first {
first = false;
}
}
Ok(if usef {
Data::new(data::float::Float(sumi as f64 + sumf))
} else {
Data::new(data::int::Int(sumi))
})
} else {
return Err("sum called on non-tuple".into());
}
}),
inner_statements: None,
}),
Data::new(two_num_tuple_to_num(
"subtract",
|l, r| Ok(l - r),
|l, r| Ok(l as f64 - r),
|l, r| Ok(l - r as f64),
|l, r| Ok(l - r),
)),
)
.add_var(
.add_var(
"product".to_string(),
Data::new(data::function::Function {
info: Arc::new(program::run::Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(|a, _i| {
let mut ints = false;
let mut floats = false;
for a in &a.types {
if let Some(i) = a.iterable() {
if i.types
.iter()
.all(|t| t.as_any().downcast_ref::<data::int::IntT>().is_some())
{
ints = true;
} else if i.types.iter().all(|t| {
t.as_any().downcast_ref::<data::int::IntT>().is_some()
|| t.as_any().downcast_ref::<data::float::FloatT>().is_some()
}) {
floats = true;
} else {
return Err(format!("cannot get product of iterator over type {i} because it contains types that aren't int/float").into())
}
} else {
return Err(format!(
"cannot get product of non-iterable type {a}"
).into());
}
}
Ok(match (ints, floats) {
(_, true) => Type::new(data::float::FloatT),
(true, false) => Type::new(data::int::IntT),
(false, false) => Type::empty(),
})
}),
run: Arc::new(|a, _i| {
if let Some(i) = a.get().iterable() {
let mut prodi = 1;
let mut prodf = 1.0;
let mut usef = false;
for val in i {
let val = val?;
let o = if let Some(i) = val.get().as_any().downcast_ref::<data::int::Int>() {
prodi *= i.0;
} else if let Some(i) =
val.get().as_any().downcast_ref::<data::float::Float>()
{
prodf *= i.0;
usef = true;
};
o
}
Ok(if usef {
Data::new(data::float::Float(prodi as f64 * prodf))
} else {
Data::new(data::int::Int(prodi))
})
} else {
return Err("product called on non-tuple".into());
}
}),
inner_statements: None,
}),
Data::new(num_iter_to_num("sum", Ok(1), |a, v| match (a, v) {
(Ok(a), Ok(v)) => Ok(a * v),
(Ok(a), Err(v)) => Err(a as f64 * v),
(Err(a), Ok(v)) => Err(a * v as f64),
(Err(a), Err(v)) => Err(a * v),
})),
)
}
}
fn num_iter_to_num(
func_name: &'static str,
init: Result<isize, f64>,
func: impl Fn(Result<isize, f64>, Result<isize, f64>) -> Result<isize, f64> + Send + Sync + 'static,
) -> data::function::Function {
data::function::Function {
info: Arc::new(program::run::Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(move |a, _i| {
if let Some(a) = a.iterable() {
let int_type = Type::new(data::int::IntT);
if a.is_included_in(&int_type) {
Ok(int_type)
} else {
let float_type = Type::new(data::float::FloatT);
if a.is_included_in(&float_type) {
Ok(float_type)
} else {
let int_float_type = Type::newm(vec![
Arc::new(data::int::IntT),
Arc::new(data::float::FloatT),
]);
if a.is_included_in(&int_float_type) {
Ok(int_float_type)
} else {
Err(format!("argument passed to {func_name} must be an iterator over values of type Int/String, but was an iterator over values of type {a}.").into())
}
}
}
} else {
Err(format!("argument passed to {func_name} must be an iterator").into())
}
}),
run: Arc::new(move |a, _i| {
let mut out = init;
for v in a.get().iterable().unwrap() {
let v = v?;
let v = v.get();
let v = v.as_any();
let v = v
.downcast_ref::<data::int::Int>()
.map(|v| Ok(v.0))
.unwrap_or_else(|| {
Err(v
.downcast_ref::<data::float::Float>()
.expect("value used in num-iterator function was not a number")
.0)
});
out = func(out, v);
}
Ok(match out {
Ok(v) => Data::new(data::int::Int(v)),
Err(v) => Data::new(data::float::Float(v)),
})
}),
inner_statements: None,
}
}
/// (int, int) -> int
/// (int, float) -> float
/// (float, int) -> float
/// (float, float) -> float
fn two_tuple_to_num(a: &Type, func_name: &str) -> Result<Type, CheckError> {
fn two_num_tuple_to_num(
func_name: &'static str,
func_ii: impl Fn(isize, isize) -> Result<isize, CheckError> + Send + Sync + 'static,
func_if: impl Fn(isize, f64) -> Result<f64, CheckError> + Send + Sync + 'static,
func_fi: impl Fn(f64, isize) -> Result<f64, CheckError> + Send + Sync + 'static,
func_ff: impl Fn(f64, f64) -> Result<f64, CheckError> + Send + Sync + 'static,
) -> data::function::Function {
data::function::Function {
info: Arc::new(program::run::Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(|a, _i| two_tuple_to_num_impl_check(a, func_name)),
run: Arc::new(move |a, _i| {
two_tuple_to_num_impl_run(a, func_name, &func_ii, &func_if, &func_fi, &func_ff)
}),
inner_statements: None,
}
}
fn two_tuple_to_num_impl_check(a: &Type, func_name: &str) -> Result<Type, CheckError> {
let mut float = false;
for t in &a.types {
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
@@ -403,6 +357,49 @@ fn two_tuple_to_num(a: &Type, func_name: &str) -> Result<Type, CheckError> {
Type::new(data::int::IntT)
})
}
fn two_tuple_to_num_impl_run(
a: Data,
func_name: &'static str,
func_ii: &(impl Fn(isize, isize) -> Result<isize, CheckError> + Send + Sync),
func_if: &(impl Fn(isize, f64) -> Result<f64, CheckError> + Send + Sync),
func_fi: &(impl Fn(f64, isize) -> Result<f64, CheckError> + Send + Sync),
func_ff: &(impl Fn(f64, f64) -> Result<f64, CheckError> + Send + Sync),
) -> Result<Data, CheckError> {
if let Some(t) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
let left = t.0[0].get();
let right = t.0[1].get();
let (left, right) = (left.as_any(), right.as_any());
Ok(
match (
left.downcast_ref::<data::int::Int>(),
left.downcast_ref::<data::float::Float>(),
right.downcast_ref::<data::int::Int>(),
right.downcast_ref::<data::float::Float>(),
) {
(Some(data::int::Int(l)), None, Some(data::int::Int(r)), None) => {
Data::new(data::int::Int(func_ii(*l, *r)?))
}
(Some(data::int::Int(l)), None, None, Some(data::float::Float(r))) => {
Data::new(data::float::Float(func_if(*l, *r)?))
}
(None, Some(data::float::Float(l)), Some(data::int::Int(r)), None) => {
Data::new(data::float::Float(func_fi(*l, *r)?))
}
(None, Some(data::float::Float(l)), None, Some(data::float::Float(r))) => {
Data::new(data::float::Float(func_ff(*l, *r)?))
}
_ => {
return Err(format!(
"at least one of the arguments to {func_name} were neither an int nor a float"
)
.into())
}
},
)
} else {
return Err(format!("argument to {func_name} was not a tuple").into());
}
}
fn ltgtoe_function(
func_name: String,

View File

@@ -96,32 +96,15 @@ impl MersStatement for Chain {
match func.run(f) {
Ok(v) => Ok(v),
Err(e) => Err(if let Some(_) = &self.as_part_of_include {
CheckError::new()
.src(vec![(
self.pos_in_src.clone(),
Some(error_colors::HashIncludeErrorInIncludedFile),
)])
.msg(
"Error in #include:"
.color(error_colors::HashIncludeErrorInIncludedFile)
.to_string(),
)
.err_with_diff_src(e)
CheckError::new().err_with_diff_src(e).src(vec![(
self.pos_in_src.clone(),
Some(error_colors::StacktraceDescendHashInclude),
)])
} else {
CheckError::new()
.src(vec![
(self.pos_in_src.clone(), None),
(
self.first.source_range(),
Some(error_colors::FunctionArgument),
),
(self.chained.source_range(), Some(error_colors::Function)),
])
.msg(format!(
"Error in {}:",
"this function".color(error_colors::Function)
))
.err(e)
CheckError::new().err(e).src(vec![
(self.pos_in_src.clone(), None),
(self.source_range(), Some(error_colors::StacktraceDescend)),
])
}),
}
} else {