V7: Make .try a language feature, this makes try_allow_unused unnecessary. remove try and try_... functions.

This commit is contained in:
Mark 2024-03-22 15:38:09 +01:00
parent 86b6a46d09
commit 8690263b1c
13 changed files with 334 additions and 208 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "mers" name = "mers"
version = "0.6.0" version = "0.7.0"
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"
@ -11,7 +11,7 @@ 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
[dependencies] [dependencies]
mers_lib = "0.6.0" mers_lib = "0.7.0"
# 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 = "2.1.0"

View File

@ -84,13 +84,13 @@ fn main() {
exit(20); exit(20);
} }
Ok(parsed) => { Ok(parsed) => {
let (mut i1, _, mut i3) = config.infos(); let (i1, _, i3) = config.infos();
match parsed.compile(&mut i1, CompInfo::default()) { match compile(&*parsed, i1) {
Err(e) => { Err(e) => {
eprintln!("{e}"); eprintln!("{e}");
exit(24); exit(24);
} }
Ok(compiled) => match compiled.check(&mut i3, None) { Ok(compiled) => match check(&*compiled, i3) {
Err(e) => { Err(e) => {
eprintln!("{e}"); eprintln!("{e}");
exit(28); exit(28);
@ -110,13 +110,13 @@ fn main() {
exit(255); exit(255);
} }
Ok(parsed) => { Ok(parsed) => {
let (mut i1, mut i2, mut i3) = config.infos(); let (i1, mut i2, i3) = config.infos();
match parsed.compile(&mut i1, CompInfo::default()) { match compile(&*parsed, i1) {
Err(e) => { Err(e) => {
eprintln!("{e}"); eprintln!("{e}");
exit(255); exit(255);
} }
Ok(compiled) => match compiled.check(&mut i3, None) { Ok(compiled) => match check(&*compiled, i3) {
Err(e) => { Err(e) => {
eprintln!("{e}"); eprintln!("{e}");
exit(255); exit(255);
@ -138,8 +138,8 @@ fn main() {
exit(255); exit(255);
} }
Ok(parsed) => { Ok(parsed) => {
let (mut i1, mut i2, _) = config.infos(); let (i1, mut i2, _) = config.infos();
match parsed.compile(&mut i1, CompInfo::default()) { match compile(&*parsed, i1) {
Err(e) => { Err(e) => {
eprintln!("{e}"); eprintln!("{e}");
exit(255); exit(255);

View File

@ -1,6 +1,6 @@
[package] [package]
name = "mers_lib" name = "mers_lib"
version = "0.6.1" version = "0.7.0"
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"

View File

@ -18,8 +18,8 @@ pub struct Function {
pub out: Arc<dyn Fn(&Type, &mut CheckInfo) -> Result<Type, CheckError> + Send + Sync>, pub out: Arc<dyn Fn(&Type, &mut CheckInfo) -> Result<Type, CheckError> + Send + Sync>,
pub run: Arc<dyn Fn(Data, &mut crate::program::run::Info) -> Data + Send + Sync>, pub run: Arc<dyn Fn(Data, &mut crate::program::run::Info) -> Data + Send + Sync>,
pub inner_statements: Option<( pub inner_statements: Option<(
Arc<Box<dyn crate::prelude_compile::RunMersStatement>>, Arc<Box<dyn crate::program::run::MersStatement>>,
Arc<Box<dyn crate::prelude_compile::RunMersStatement>>, Arc<Box<dyn crate::program::run::MersStatement>>,
)>, )>,
} }
impl Function { impl Function {

View File

@ -81,6 +81,12 @@ pub mod error_colors {
pub const BadCharInFunctionType: Color = Color::Red; pub const BadCharInFunctionType: Color = Color::Red;
pub const BadTypeFromParsed: Color = Color::Blue; pub const BadTypeFromParsed: Color = Color::Blue;
pub const TypeAnnotationNoClosingBracket: Color = Color::Blue; pub const TypeAnnotationNoClosingBracket: Color = Color::Blue;
pub const TryBadSyntax: Color = 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;
} }
#[derive(Clone)] #[derive(Clone)]
pub enum CheckErrorComponent { pub enum CheckErrorComponent {
@ -125,6 +131,7 @@ impl Display for CheckErrorDisplay<'_> {
) )
} }
} }
#[allow(unused)]
impl CheckError { impl CheckError {
pub fn new() -> Self { pub fn new() -> Self {
CheckError(vec![]) CheckError(vec![])
@ -133,18 +140,34 @@ impl CheckError {
self.0.push(v); self.0.push(v);
self self
} }
fn add_mut(&mut self, v: CheckErrorComponent) -> &mut Self {
self.0.push(v);
self
}
pub(crate) fn msg(self, s: String) -> Self { pub(crate) fn msg(self, s: String) -> Self {
self.add(CheckErrorComponent::Message(s)) self.add(CheckErrorComponent::Message(s))
} }
pub(crate) fn msg_mut(&mut self, s: String) -> &mut Self {
self.add_mut(CheckErrorComponent::Message(s))
}
pub(crate) fn err(self, e: Self) -> Self { pub(crate) fn err(self, e: Self) -> Self {
self.add(CheckErrorComponent::Error(e)) self.add(CheckErrorComponent::Error(e))
} }
pub(crate) fn err_mut(&mut self, e: Self) -> &mut Self {
self.add_mut(CheckErrorComponent::Error(e))
}
pub(crate) fn err_with_diff_src(self, e: CheckError) -> Self { pub(crate) fn err_with_diff_src(self, e: CheckError) -> Self {
self.add(CheckErrorComponent::ErrorWithDifferentSource(e)) self.add(CheckErrorComponent::ErrorWithDifferentSource(e))
} }
pub(crate) fn err_with_diff_src_mut(&mut self, e: CheckError) -> &mut Self {
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<colored::Color>)>) -> 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 {
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) -> CheckErrorDisplay<'a> {
CheckErrorDisplay { CheckErrorDisplay {

View File

@ -3,7 +3,7 @@ use std::fmt::Debug;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Info<L: Local> { pub struct Info<L: Local> {
pub scopes: Vec<L>, pub scopes: Vec<L>,
pub global: L::Global, pub(crate) global: L::Global,
} }
impl<L: Local> Info<L> { impl<L: Local> Info<L> {

View File

@ -11,11 +11,12 @@ pub mod program;
#[cfg(feature = "parse")] #[cfg(feature = "parse")]
pub mod prelude_compile { pub mod prelude_compile {
pub use crate::parsing::check;
pub use crate::parsing::compile;
pub use crate::parsing::parse; pub use crate::parsing::parse;
pub use crate::parsing::Source; pub use crate::parsing::Source;
pub use crate::program::configs::Config; pub use crate::program::configs::Config;
pub use crate::program::parsed::{CompInfo, MersStatement as ParsedMersStatement}; pub use crate::program::parsed::CompInfo;
pub use crate::program::run::MersStatement as RunMersStatement;
} }
/// can be used to extend the mers config. /// can be used to extend the mers config.

View File

@ -3,8 +3,12 @@ use std::{fmt::Debug, path::PathBuf, sync::Arc};
use line_span::{LineSpan, LineSpanExt}; use line_span::{LineSpan, LineSpanExt};
use crate::{ use crate::{
errors::{CheckError, SourcePos}, data::Type,
program::{self, parsed::block::Block}, errors::{error_colors, CheckError, SourcePos},
program::{
self,
parsed::{block::Block, CompInfo},
},
}; };
pub mod statements; pub mod statements;
@ -22,6 +26,70 @@ pub fn parse(
}; };
Ok(Box::new(block)) Ok(Box::new(block))
} }
pub fn compile(
statement: &(impl program::parsed::MersStatement + ?Sized),
mut info: crate::program::parsed::Info,
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
statement.compile(&mut info, CompInfo::default())
}
pub fn check(
statement: &(impl program::run::MersStatement + ?Sized),
mut info: crate::program::run::CheckInfo,
) -> Result<Type, CheckError> {
let o = statement.check(&mut info, None)?;
let mut err = None;
for (try_stmt, used) in info.global.unused_try_statements.lock().unwrap().iter() {
if used.iter().any(|v| v.is_some()) {
let err = err.get_or_insert_with(|| {
CheckError::new().msg(format!(
"There are `.try` statements with unused functions!"
))
});
let unused = used
.into_iter()
.enumerate()
.filter_map(|v| Some((v.0, v.1.clone()?)))
.collect::<Vec<_>>();
err.msg_mut(format!(
"Here, {}function{} {} {} unused:",
if unused.len() == 1 { "the " } else { "" },
if unused.len() == 1 { "" } else { "s" },
unused
.iter()
.enumerate()
.fold(String::new(), |mut a, (i, (v, _))| {
if i > 0 {
a.push_str(", ");
if i == unused.len() - 1 {
a.push_str("and ");
}
}
a.push_str(&format!("#{}", v + 1));
a
}),
if unused.len() == 1 { "is" } else { "are" },
))
.src_mut({
let mut src = vec![(try_stmt.clone(), None)];
for (i, (_, src_range)) in unused.into_iter().enumerate() {
src.push((
src_range,
Some(if i % 2 == 0 {
error_colors::TryUnusedFunction1
} else {
error_colors::TryUnusedFunction2
}),
));
}
src
});
}
}
if let Some(err) = err {
return Err(err);
}
Ok(o)
}
pub struct Source { pub struct Source {
src_from: SourceFrom, src_from: SourceFrom,

View File

@ -168,6 +168,27 @@ pub fn parse(
let dot_in_src = src.get_pos(); let dot_in_src = src.get_pos();
if let Some('.') = src.peek_char() { if let Some('.') = src.peek_char() {
src.next_char(); src.next_char();
src.skip_whitespace();
if src.peek_word() == "try" {
src.next_word();
src.skip_whitespace();
if let Some('(') = src.next_char() {
let funcs = parse_tuple_without_open(src, srca)?;
first = Box::new(program::parsed::r#try::Try {
pos_in_src: (first.source_range().start(), src.get_pos(), srca).into(),
arg: first,
funcs,
});
pos_after_first = src.get_pos();
} else {
return Err(CheckError::new()
.msg(format!("Expected `(` after `.try`"))
.src(vec![(
(dot_in_src, src.get_pos(), srca).into(),
Some(error_colors::TryBadSyntax),
)]));
}
} else {
let chained = match parse_no_chain(src, srca) { let chained = match parse_no_chain(src, srca) {
Ok(Some(v)) => v, Ok(Some(v)) => v,
Ok(None) => { Ok(None) => {
@ -192,6 +213,7 @@ pub fn parse(
chained, chained,
}); });
pos_after_first = src.get_pos(); pos_after_first = src.get_pos();
}
} else { } else {
src.set_pos(pos_after_first); src.set_pos(pos_after_first);
break; break;
@ -203,6 +225,12 @@ pub fn parse(
} }
Ok(Some(first)) Ok(Some(first))
} }
pub fn parse_tuple_without_open(
src: &mut Source,
srca: &Arc<Source>,
) -> Result<Vec<Box<dyn MersStatement>>, CheckError> {
parse_multiple(src, srca, ")")
}
pub fn parse_multiple( pub fn parse_multiple(
src: &mut Source, src: &mut Source,
srca: &Arc<Source>, srca: &Arc<Source>,
@ -374,7 +402,7 @@ pub fn parse_no_chain(
Some('(') => { Some('(') => {
let pos_in_src = src.get_pos(); let pos_in_src = src.get_pos();
src.next_char(); src.next_char();
let elems = parse_multiple(src, srca, ")")?; let elems = parse_tuple_without_open(src, srca)?;
return Ok(Some(Box::new(program::parsed::tuple::Tuple { return Ok(Some(Box::new(program::parsed::tuple::Tuple {
pos_in_src: (pos_in_src, src.get_pos(), srca).into(), pos_in_src: (pos_in_src, src.get_pos(), srca).into(),
elems, elems,

View File

@ -22,8 +22,9 @@ impl Config {
/// `panic: fn` exits the program with the given exit code /// `panic: fn` exits the program with the given exit code
/// `lock_update: fn` locks the value of a reference so you can exclusively modify it: &var.lock_update(v -> (v, 1).sum) /// `lock_update: fn` locks the value of a reference so you can exclusively modify it: &var.lock_update(v -> (v, 1).sum)
pub fn with_base(self) -> Self { pub fn with_base(self) -> Self {
self.add_var("try".to_string(), get_try(false)) self
.add_var("try_allow_unused".to_string(), get_try(true)) // .add_var("try".to_string(), get_try(false))
// .add_var("try_allow_unused".to_string(), get_try(true))
.add_var("lock_update".to_string(), Data::new(data::function::Function { .add_var("lock_update".to_string(), Data::new(data::function::Function {
info: Arc::new(Info::neverused()), info: Arc::new(Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
@ -196,170 +197,170 @@ impl Config {
} }
} }
fn get_try(allow_unused_functions: bool) -> Data { // fn get_try(allow_unused_functions: bool) -> Data {
Data::new(data::function::Function { // Data::new(data::function::Function {
info: Arc::new(Info::neverused()), // info: Arc::new(Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), // info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(move |a, _i| { // out: Arc::new(move |a, _i| {
let mut out = Type::empty(); // let mut out = Type::empty();
for t in a.types.iter() { // for t in a.types.iter() {
if let Some(outer_tuple) = t.as_any().downcast_ref::<data::tuple::TupleT>() { // if let Some(outer_tuple) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
if outer_tuple.0.len() != 2 { // if outer_tuple.0.len() != 2 {
return Err(format!( // return Err(format!(
"cannot use try with tuple argument where len != 2 (got len {})", // "cannot use try with tuple argument where len != 2 (got len {})",
outer_tuple.0.len() // outer_tuple.0.len()
) // )
.into()); // .into());
} // }
let arg_type = &outer_tuple.0[0]; // let arg_type = &outer_tuple.0[0];
let functions = &outer_tuple.0[1]; // let functions = &outer_tuple.0[1];
let mut used_functions_and_errors = vec![]; // let mut used_functions_and_errors = vec![];
for arg_type in arg_type.subtypes_type().types.iter() { // for arg_type in arg_type.subtypes_type().types.iter() {
let arg_type = Type::newm(vec![arg_type.clone()]); // let arg_type = Type::newm(vec![arg_type.clone()]);
// possibilities for the tuple (f1, f2, f3, ..., fn) // // possibilities for the tuple (f1, f2, f3, ..., fn)
for (fti, ft) in functions.types.iter().enumerate() { // for (fti, ft) in functions.types.iter().enumerate() {
if used_functions_and_errors.len() <= fti { // if used_functions_and_errors.len() <= fti {
used_functions_and_errors.push(vec![]); // used_functions_and_errors.push(vec![]);
} // }
let mut tuple_fallible = true; // let mut tuple_fallible = true;
let mut tuple_possible = false; // let mut tuple_possible = false;
if let Some(ft) = ft.as_any().downcast_ref::<data::tuple::TupleT>() { // if let Some(ft) = ft.as_any().downcast_ref::<data::tuple::TupleT>() {
// f1, f2, f3, ..., fn // // f1, f2, f3, ..., fn
let mut func_errors = vec![]; // let mut func_errors = vec![];
let mut skip_checks = false; // let mut skip_checks = false;
for (fi, ft) in ft.0.iter().enumerate() { // for (fi, ft) in ft.0.iter().enumerate() {
if used_functions_and_errors[fti].len() <= fi { // if used_functions_and_errors[fti].len() <= fi {
used_functions_and_errors[fti].push(vec![]); // used_functions_and_errors[fti].push(vec![]);
} // }
let mut func_fallible = false; // let mut func_fallible = false;
// possibilities for f_ // // possibilities for f_
for (fvi, ft) in ft.types.iter().enumerate() { // for (fvi, ft) in ft.types.iter().enumerate() {
if let Some(ft) = // if let Some(ft) =
ft.as_any().downcast_ref::<data::function::FunctionT>() // ft.as_any().downcast_ref::<data::function::FunctionT>()
{ // {
if used_functions_and_errors[fti][fi].len() <= fvi { // if used_functions_and_errors[fti][fi].len() <= fvi {
used_functions_and_errors[fti][fi] // used_functions_and_errors[fti][fi]
.push(Some(vec![])); // .push(Some(vec![]));
} // }
if !skip_checks { // if !skip_checks {
func_errors.push(( // func_errors.push((
fvi, // fvi,
match ft.o(&arg_type) { // match ft.o(&arg_type) {
Err(e) => { // Err(e) => {
func_fallible = true; // func_fallible = true;
if let Some(errs) = // if let Some(errs) =
&mut used_functions_and_errors[fti] // &mut used_functions_and_errors[fti]
[fi][fvi] // [fi][fvi]
{ // {
errs.push(e.clone()); // errs.push(e.clone());
} // }
Some(e) // Some(e)
} // }
Ok(o) => { // Ok(o) => {
used_functions_and_errors[fti][fi] // used_functions_and_errors[fti][fi]
[fvi] = None; // [fvi] = None;
tuple_possible = true; // tuple_possible = true;
for t in o.types { // for t in o.types {
out.add(t); // out.add(t);
} // }
None // None
} // }
}, // },
)); // ));
} // }
} else { // } else {
return Err(format!( // return Err(format!(
"try: arguments f1-fn must be functions" // "try: arguments f1-fn must be functions"
) // )
.into()); // .into());
} // }
} // }
// found a function that won't fail for this arg_type! // // found a function that won't fail for this arg_type!
if !func_fallible { // if !func_fallible {
tuple_fallible = false; // tuple_fallible = false;
if tuple_possible { // if tuple_possible {
skip_checks = true; // skip_checks = true;
} // }
} // }
} // }
if tuple_fallible || !tuple_possible { // if tuple_fallible || !tuple_possible {
// if the argument is {arg_type}, there is no infallible function. add a fallback function to handle this case! // // if the argument is {arg_type}, there is no infallible function. add a fallback function to handle this case!
let mut e = CheckError::new() // let mut e = CheckError::new()
.msg(format!("if the argument is {arg_type}, there is no infallible function.")) // .msg(format!("if the argument is {arg_type}, there is no infallible function."))
.msg(format!("Add a function to handle this case!")); // .msg(format!("Add a function to handle this case!"));
for (i, err) in func_errors.into_iter() { // for (i, err) in func_errors.into_iter() {
if let Some(err) = err { // if let Some(err) = err {
e = e // e = e
.msg(format!("Error for function #{}:", i + 1)) // .msg(format!("Error for function #{}:", i + 1))
.err(err); // .err(err);
} // }
} // }
return Err(e); // return Err(e);
} // }
} else { // } else {
return Err(format!( // return Err(format!(
"try: argument must be (arg, (f1, f2, f3, ..., fn))" // "try: argument must be (arg, (f1, f2, f3, ..., fn))"
) // )
.into()); // .into());
} // }
} // }
} // }
// check for unused functions // // check for unused functions
if !allow_unused_functions { // if !allow_unused_functions {
for (functions_posibility_index, functions_possibility) in // for (functions_posibility_index, functions_possibility) in
used_functions_and_errors.into_iter().enumerate() // used_functions_and_errors.into_iter().enumerate()
{ // {
for (func_index, func_possibilities) in // for (func_index, func_possibilities) in
functions_possibility.into_iter().enumerate() // functions_possibility.into_iter().enumerate()
{ // {
for (func_possibility_index, errors_if_unused) in // for (func_possibility_index, errors_if_unused) in
func_possibilities.into_iter().enumerate() // func_possibilities.into_iter().enumerate()
{ // {
if let Some(errs) = errors_if_unused { // if let Some(errs) = errors_if_unused {
let mut e = CheckError::new().msg(format!("try: For the argument {t}:\nFunction #{}{} is never used. (use `try_allow_unused` to avoid this error){}", // let mut e = CheckError::new().msg(format!("try: For the argument {t}:\nFunction #{}{} is never used. (use `try_allow_unused` to avoid this error){}",
func_index + 1, // func_index + 1,
if functions_posibility_index != 0 || func_possibility_index != 0 { // if functions_posibility_index != 0 || func_possibility_index != 0 {
format!(" (func-tuple possibility {}, function possibility {})", functions_posibility_index + 1, func_possibility_index + 1) // format!(" (func-tuple possibility {}, function possibility {})", functions_posibility_index + 1, func_possibility_index + 1)
} else { // } else {
format!("") // format!("")
}, // },
if errs.is_empty() { "" } else { " Errors:" })); // if errs.is_empty() { "" } else { " Errors:" }));
for err in errs { // for err in errs {
e = e.err(err); // e = e.err(err);
} // }
return Err(e); // return Err(e);
} // }
} // }
} // }
} // }
} // }
} else { // } else {
return Err(format!("cannot use try with non-tuple argument").into()); // return Err(format!("cannot use try with non-tuple argument").into());
} // }
} // }
Ok(out) // Ok(out)
}), // }),
run: Arc::new(|a, _i| { // run: Arc::new(|a, _i| {
let tuple = a.get(); // let tuple = a.get();
let tuple = tuple // let tuple = tuple
.as_any() // .as_any()
.downcast_ref::<data::tuple::Tuple>() // .downcast_ref::<data::tuple::Tuple>()
.expect("try: not a tuple"); // .expect("try: not a tuple");
let arg = &tuple.0[0]; // let arg = &tuple.0[0];
let funcs = tuple.0[1].get(); // let funcs = tuple.0[1].get();
let funcs = funcs.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); // let funcs = funcs.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
for func in funcs.0.iter() { // for func in funcs.0.iter() {
let func = func.get(); // let func = func.get();
let func = func // let func = func
.as_any() // .as_any()
.downcast_ref::<data::function::Function>() // .downcast_ref::<data::function::Function>()
.unwrap(); // .unwrap();
if func.check(&arg.get().as_type()).is_ok() { // if func.check(&arg.get().as_type()).is_ok() {
return func.run(arg.clone()); // return func.run(arg.clone());
} // }
} // }
unreachable!("try: no function found") // unreachable!("try: no function found")
}), // }),
inner_statements: None, // inner_statements: None,
}) // })
} // }

View File

@ -32,6 +32,8 @@ pub mod r#loop;
#[cfg(feature = "parse")] #[cfg(feature = "parse")]
pub mod object; pub mod object;
#[cfg(feature = "parse")] #[cfg(feature = "parse")]
pub mod r#try;
#[cfg(feature = "parse")]
pub mod tuple; pub mod tuple;
#[cfg(feature = "parse")] #[cfg(feature = "parse")]
pub mod value; pub mod value;

View File

@ -20,7 +20,7 @@ impl MersStatement for Loop {
init_to: Option<&Type>, init_to: Option<&Type>,
) -> Result<data::Type, CheckError> { ) -> Result<data::Type, CheckError> {
if init_to.is_some() { if init_to.is_some() {
return Err("can't init to statement type If".to_string().into()); return Err("can't init to statement type Loop".to_string().into());
} }
let mut t = Type::empty(); let mut t = Type::empty();
let inner_return_type = self.inner.check(info, None)?; let inner_return_type = self.inner.check(info, None)?;

View File

@ -29,6 +29,8 @@ pub mod r#loop;
#[cfg(feature = "run")] #[cfg(feature = "run")]
pub mod object; pub mod object;
#[cfg(feature = "run")] #[cfg(feature = "run")]
pub mod r#try;
#[cfg(feature = "run")]
pub mod tuple; pub mod tuple;
#[cfg(feature = "run")] #[cfg(feature = "run")]
pub mod value; pub mod value;
@ -140,6 +142,7 @@ pub struct CheckLocalGlobalInfo {
)>, )>,
>, >,
>, >,
pub unused_try_statements: Arc<Mutex<Vec<(SourceRange, Vec<Option<SourceRange>>)>>>,
} }
impl Debug for CheckLocal { impl Debug for CheckLocal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {