mirror of
https://github.com/Dummi26/mers.git
synced 2025-12-13 19:06:16 +01:00
improve error messages
- fix bug where `thread` function wouldn't error when being called on a non-function - add compile error when a function in `try` is never used, because this is almost certainly a mistake and will cause mers to unexpectedly go down the "wrong" code path. - some small changes so mers_lib can be used in another project
This commit is contained in:
@@ -84,11 +84,19 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_var(mut self, name: String, val: Data) -> Self {
|
||||
pub fn add_var(self, name: String, val: Data) -> Self {
|
||||
let t = val.get().as_type();
|
||||
self.add_var_arc(name, Arc::new(RwLock::new(val)), t)
|
||||
}
|
||||
pub fn add_var_arc(
|
||||
mut self,
|
||||
name: String,
|
||||
val: Arc<RwLock<Data>>,
|
||||
val_type: crate::data::Type,
|
||||
) -> Self {
|
||||
self.info_parsed.scopes[0].init_var(name, (0, self.globals));
|
||||
self.info_run.scopes[0].init_var(self.globals, Arc::new(RwLock::new(val)));
|
||||
self.info_check.scopes[0].init_var(self.globals, t);
|
||||
self.info_run.scopes[0].init_var(self.globals, val);
|
||||
self.info_check.scopes[0].init_var(self.globals, val_type);
|
||||
self.globals += 1;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -28,39 +28,56 @@ impl Config {
|
||||
out: Arc::new(|a, _i| {
|
||||
let mut out = Type::empty();
|
||||
for t in a.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
if t.0.len() != 2 {
|
||||
return Err(format!("cannot use try with tuple argument where len != 2 (got len {})", t.0.len()).into());
|
||||
if let Some(outer_tuple) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
if outer_tuple.0.len() != 2 {
|
||||
return Err(format!("cannot use try with tuple argument where len != 2 (got len {})", outer_tuple.0.len()).into());
|
||||
}
|
||||
let arg_type = &t.0[0];
|
||||
let functions = &t.0[1];
|
||||
let arg_type = &outer_tuple.0[0];
|
||||
let functions = &outer_tuple.0[1];
|
||||
let mut used_functions_and_errors = vec![];
|
||||
for arg_type in arg_type.subtypes_type().types.iter() {
|
||||
let arg_type = Type::newm(vec![arg_type.clone()]);
|
||||
// possibilities for the tuple (f1, f2, f3, ..., fn)
|
||||
for ft in functions.types.iter() {
|
||||
for (fti, ft) in functions.types.iter().enumerate() {
|
||||
if used_functions_and_errors.len() <= fti {
|
||||
used_functions_and_errors.push(vec![]);
|
||||
}
|
||||
let mut tuple_fallible = true;
|
||||
let mut tuple_possible = false;
|
||||
if let Some(ft) = ft.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
// f1, f2, f3, ..., fn
|
||||
let mut func_errors = vec![];
|
||||
for ft in ft.0.iter() {
|
||||
let mut skip_checks = false;
|
||||
for (fi, ft) in ft.0.iter().enumerate() {
|
||||
if used_functions_and_errors[fti].len() <= fi {
|
||||
used_functions_and_errors[fti].push(vec![]);
|
||||
}
|
||||
let mut func_fallible = false;
|
||||
// possibilities for f_
|
||||
for ft in ft.types.iter() {
|
||||
for (fvi, ft) in ft.types.iter().enumerate() {
|
||||
if let Some(ft) = ft.as_any().downcast_ref::<data::function::FunctionT>() {
|
||||
func_errors.push(match ft.0(&arg_type) {
|
||||
Err(e) => {
|
||||
func_fallible = true;
|
||||
Some(e)
|
||||
}
|
||||
Ok(o) => {
|
||||
tuple_possible = true;
|
||||
for t in o.types {
|
||||
out.add(t);
|
||||
if used_functions_and_errors[fti][fi].len() <= fvi {
|
||||
used_functions_and_errors[fti][fi].push(Some(vec![]));
|
||||
}
|
||||
if !skip_checks {
|
||||
func_errors.push((fvi, match ft.0(&arg_type) {
|
||||
Err(e) => {
|
||||
func_fallible = true;
|
||||
if let Some(errs) = &mut used_functions_and_errors[fti][fi][fvi] {
|
||||
errs.push(e.clone());
|
||||
}
|
||||
Some(e)
|
||||
}
|
||||
None
|
||||
},
|
||||
});
|
||||
Ok(o) => {
|
||||
used_functions_and_errors[fti][fi][fvi] = None;
|
||||
tuple_possible = true;
|
||||
for t in o.types {
|
||||
out.add(t);
|
||||
}
|
||||
None
|
||||
},
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
return Err(format!("try: arguments f1-fn must be functions").into());
|
||||
}
|
||||
@@ -69,7 +86,7 @@ impl Config {
|
||||
if !func_fallible {
|
||||
tuple_fallible = false;
|
||||
if tuple_possible {
|
||||
break;
|
||||
skip_checks = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,8 +94,8 @@ impl Config {
|
||||
// if the argument is {arg_type}, there is no infallible function. add a fallback function to handle this case!
|
||||
let mut e = CheckError::new()
|
||||
.msg(format!("if the argument is {arg_type}, there is no infallible function."))
|
||||
.msg(format!("Add a fallback function to handle this case!"));
|
||||
for (i, err) in func_errors.into_iter().enumerate() {
|
||||
.msg(format!("Add a function to handle this case!"));
|
||||
for (i, err) in func_errors.into_iter() {
|
||||
if let Some(err) = err {
|
||||
e = e
|
||||
.msg(format!("Error for function #{}:", i + 1))
|
||||
@@ -92,6 +109,26 @@ impl Config {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (functions_posibility_index, functions_possibility) in used_functions_and_errors.into_iter().enumerate() {
|
||||
for (func_index, func_possibilities) in functions_possibility.into_iter().enumerate() {
|
||||
for (func_possibility_index, errors_if_unused) in func_possibilities.into_iter().enumerate() {
|
||||
if let Some(errs) = errors_if_unused {
|
||||
let mut e = CheckError::new().msg(format!("try: For the argument {t}:\nFunction #{}{} is never used.{}",
|
||||
func_index + 1,
|
||||
if functions_posibility_index != 0 || func_possibility_index != 0 {
|
||||
format!(" (func-tuple possibility {}, function possibility {})", functions_posibility_index + 1, func_possibility_index + 1)
|
||||
} else {
|
||||
format!("")
|
||||
},
|
||||
if errs.is_empty() { "" } else { " Errors:" }));
|
||||
for err in errs {
|
||||
e = e.err(err);
|
||||
}
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(format!("cannot use try with non-tuple argument").into());
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ impl Config {
|
||||
Ok(t) => out.add(Arc::new(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))
|
||||
}
|
||||
} else {
|
||||
return Err(format!("thread: argument wasn't a function").into());
|
||||
}
|
||||
}
|
||||
Ok(Type::new(ThreadT(out)))
|
||||
|
||||
Reference in New Issue
Block a user