From 8690263b1cf8fc4ebb8f4b05499d644a41c331d6 Mon Sep 17 00:00:00 2001 From: Mark <> Date: Fri, 22 Mar 2024 15:38:09 +0100 Subject: [PATCH] V7: Make `.try` a language feature, this makes try_allow_unused unnecessary. remove try and try_... functions. --- mers/Cargo.toml | 4 +- mers/src/main.rs | 16 +- mers_lib/Cargo.toml | 2 +- mers_lib/src/data/function.rs | 4 +- mers_lib/src/errors/mod.rs | 23 ++ mers_lib/src/info/mod.rs | 2 +- mers_lib/src/lib.rs | 5 +- mers_lib/src/parsing/mod.rs | 72 ++++- mers_lib/src/parsing/statements.rs | 68 +++-- mers_lib/src/program/configs/with_base.rs | 339 +++++++++++----------- mers_lib/src/program/parsed/mod.rs | 2 + mers_lib/src/program/run/loop.rs | 2 +- mers_lib/src/program/run/mod.rs | 3 + 13 files changed, 334 insertions(+), 208 deletions(-) diff --git a/mers/Cargo.toml b/mers/Cargo.toml index bcb5df7..10fdf82 100644 --- a/mers/Cargo.toml +++ b/mers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mers" -version = "0.6.0" +version = "0.7.0" edition = "2021" license = "MIT OR Apache-2.0" 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 [dependencies] -mers_lib = "0.6.0" +mers_lib = "0.7.0" # mers_lib = { path = "../mers_lib" } clap = { version = "4.3.19", features = ["derive"] } colored = "2.1.0" diff --git a/mers/src/main.rs b/mers/src/main.rs index bce92dd..e3740c3 100755 --- a/mers/src/main.rs +++ b/mers/src/main.rs @@ -84,13 +84,13 @@ fn main() { exit(20); } Ok(parsed) => { - let (mut i1, _, mut i3) = config.infos(); - match parsed.compile(&mut i1, CompInfo::default()) { + let (i1, _, i3) = config.infos(); + match compile(&*parsed, i1) { Err(e) => { eprintln!("{e}"); exit(24); } - Ok(compiled) => match compiled.check(&mut i3, None) { + Ok(compiled) => match check(&*compiled, i3) { Err(e) => { eprintln!("{e}"); exit(28); @@ -110,13 +110,13 @@ fn main() { exit(255); } Ok(parsed) => { - let (mut i1, mut i2, mut i3) = config.infos(); - match parsed.compile(&mut i1, CompInfo::default()) { + let (i1, mut i2, i3) = config.infos(); + match compile(&*parsed, i1) { Err(e) => { eprintln!("{e}"); exit(255); } - Ok(compiled) => match compiled.check(&mut i3, None) { + Ok(compiled) => match check(&*compiled, i3) { Err(e) => { eprintln!("{e}"); exit(255); @@ -138,8 +138,8 @@ fn main() { exit(255); } Ok(parsed) => { - let (mut i1, mut i2, _) = config.infos(); - match parsed.compile(&mut i1, CompInfo::default()) { + let (i1, mut i2, _) = config.infos(); + match compile(&*parsed, i1) { Err(e) => { eprintln!("{e}"); exit(255); diff --git a/mers_lib/Cargo.toml b/mers_lib/Cargo.toml index 018c209..0dbe4f4 100755 --- a/mers_lib/Cargo.toml +++ b/mers_lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mers_lib" -version = "0.6.1" +version = "0.7.0" edition = "2021" license = "MIT OR Apache-2.0" description = "library to use the mers language in other projects" diff --git a/mers_lib/src/data/function.rs b/mers_lib/src/data/function.rs index 311ff09..09bd76e 100755 --- a/mers_lib/src/data/function.rs +++ b/mers_lib/src/data/function.rs @@ -18,8 +18,8 @@ pub struct Function { pub out: Arc Result + Send + Sync>, pub run: Arc Data + Send + Sync>, pub inner_statements: Option<( - Arc>, - Arc>, + Arc>, + Arc>, )>, } impl Function { diff --git a/mers_lib/src/errors/mod.rs b/mers_lib/src/errors/mod.rs index 67f5963..b39395f 100644 --- a/mers_lib/src/errors/mod.rs +++ b/mers_lib/src/errors/mod.rs @@ -81,6 +81,12 @@ pub mod error_colors { pub const BadCharInFunctionType: Color = Color::Red; pub const BadTypeFromParsed: 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)] pub enum CheckErrorComponent { @@ -125,6 +131,7 @@ impl Display for CheckErrorDisplay<'_> { ) } } +#[allow(unused)] impl CheckError { pub fn new() -> Self { CheckError(vec![]) @@ -133,18 +140,34 @@ impl CheckError { self.0.push(v); self } + fn add_mut(&mut self, v: CheckErrorComponent) -> &mut Self { + self.0.push(v); + self + } pub(crate) fn msg(self, s: String) -> Self { 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 { 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 { 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)>) -> Self { self.add(CheckErrorComponent::Source(s)) } + pub(crate) fn src_mut(&mut self, s: Vec<(SourceRange, Option)>) -> &mut Self { + self.add_mut(CheckErrorComponent::Source(s)) + } #[cfg(feature = "parse")] pub fn display<'a>(&'a self) -> CheckErrorDisplay<'a> { CheckErrorDisplay { diff --git a/mers_lib/src/info/mod.rs b/mers_lib/src/info/mod.rs index ac625d0..bf91b85 100755 --- a/mers_lib/src/info/mod.rs +++ b/mers_lib/src/info/mod.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; #[derive(Clone, Debug)] pub struct Info { pub scopes: Vec, - pub global: L::Global, + pub(crate) global: L::Global, } impl Info { diff --git a/mers_lib/src/lib.rs b/mers_lib/src/lib.rs index f327245..e4fe1f5 100755 --- a/mers_lib/src/lib.rs +++ b/mers_lib/src/lib.rs @@ -11,11 +11,12 @@ pub mod program; #[cfg(feature = "parse")] pub mod prelude_compile { + pub use crate::parsing::check; + pub use crate::parsing::compile; pub use crate::parsing::parse; pub use crate::parsing::Source; pub use crate::program::configs::Config; - pub use crate::program::parsed::{CompInfo, MersStatement as ParsedMersStatement}; - pub use crate::program::run::MersStatement as RunMersStatement; + pub use crate::program::parsed::CompInfo; } /// can be used to extend the mers config. diff --git a/mers_lib/src/parsing/mod.rs b/mers_lib/src/parsing/mod.rs index e69770d..dd96571 100755 --- a/mers_lib/src/parsing/mod.rs +++ b/mers_lib/src/parsing/mod.rs @@ -3,8 +3,12 @@ use std::{fmt::Debug, path::PathBuf, sync::Arc}; use line_span::{LineSpan, LineSpanExt}; use crate::{ - errors::{CheckError, SourcePos}, - program::{self, parsed::block::Block}, + data::Type, + errors::{error_colors, CheckError, SourcePos}, + program::{ + self, + parsed::{block::Block, CompInfo}, + }, }; pub mod statements; @@ -22,6 +26,70 @@ pub fn parse( }; Ok(Box::new(block)) } +pub fn compile( + statement: &(impl program::parsed::MersStatement + ?Sized), + mut info: crate::program::parsed::Info, +) -> Result, CheckError> { + statement.compile(&mut info, CompInfo::default()) +} +pub fn check( + statement: &(impl program::run::MersStatement + ?Sized), + mut info: crate::program::run::CheckInfo, +) -> Result { + 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::>(); + 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 { src_from: SourceFrom, diff --git a/mers_lib/src/parsing/statements.rs b/mers_lib/src/parsing/statements.rs index 2326a89..5ead923 100755 --- a/mers_lib/src/parsing/statements.rs +++ b/mers_lib/src/parsing/statements.rs @@ -168,30 +168,52 @@ 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, srca) { - Ok(Some(v)) => v, - Ok(None) => { + 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() - .src(vec![((dot_in_src, src.get_pos(), srca).into(), None)]) - .msg(format!("EOF after `.`"))) + .msg(format!("Expected `(` after `.try`")) + .src(vec![( + (dot_in_src, src.get_pos(), srca).into(), + Some(error_colors::TryBadSyntax), + )])); } - Err(e) => return Err(e), - }; - // 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, srca, ")")?; - first = Box::new(program::parsed::tuple::Tuple { + } else { + 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(), srca).into(), None)]) + .msg(format!("EOF after `.`"))) + } + Err(e) => return Err(e), + }; + // 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, srca, ")")?; + first = Box::new(program::parsed::tuple::Tuple { + 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(), srca).into(), - elems: [first].into_iter().chain(elems).collect(), + first, + chained, }); + pos_after_first = src.get_pos(); } - first = Box::new(program::parsed::chain::Chain { - pos_in_src: (first.source_range().start(), src.get_pos(), srca).into(), - first, - chained, - }); - pos_after_first = src.get_pos(); } else { src.set_pos(pos_after_first); break; @@ -203,6 +225,12 @@ pub fn parse( } Ok(Some(first)) } +pub fn parse_tuple_without_open( + src: &mut Source, + srca: &Arc, +) -> Result>, CheckError> { + parse_multiple(src, srca, ")") +} pub fn parse_multiple( src: &mut Source, srca: &Arc, @@ -374,7 +402,7 @@ pub fn parse_no_chain( Some('(') => { let pos_in_src = src.get_pos(); 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 { pos_in_src: (pos_in_src, src.get_pos(), srca).into(), elems, diff --git a/mers_lib/src/program/configs/with_base.rs b/mers_lib/src/program/configs/with_base.rs index abab867..12c11c8 100755 --- a/mers_lib/src/program/configs/with_base.rs +++ b/mers_lib/src/program/configs/with_base.rs @@ -22,8 +22,9 @@ impl Config { /// `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) pub fn with_base(self) -> Self { - self.add_var("try".to_string(), get_try(false)) - .add_var("try_allow_unused".to_string(), get_try(true)) + self + // .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 { info: Arc::new(Info::neverused()), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), @@ -196,170 +197,170 @@ impl Config { } } -fn get_try(allow_unused_functions: bool) -> Data { - Data::new(data::function::Function { - info: Arc::new(Info::neverused()), - info_check: Arc::new(Mutex::new(CheckInfo::neverused())), - out: Arc::new(move |a, _i| { - let mut out = Type::empty(); - for t in a.types.iter() { - if let Some(outer_tuple) = t.as_any().downcast_ref::() { - 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 = &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 (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::() { - // f1, f2, f3, ..., fn - let mut func_errors = vec![]; - 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 (fvi, ft) in ft.types.iter().enumerate() { - if let Some(ft) = - ft.as_any().downcast_ref::() - { - 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.o(&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) - } - 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()); - } - } - // found a function that won't fail for this arg_type! - if !func_fallible { - tuple_fallible = false; - if tuple_possible { - skip_checks = true; - } - } - } - if tuple_fallible || !tuple_possible { - // 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 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)) - .err(err); - } - } - return Err(e); - } - } else { - return Err(format!( - "try: argument must be (arg, (f1, f2, f3, ..., fn))" - ) - .into()); - } - } - } - // check for unused functions - if !allow_unused_functions { - 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. (use `try_allow_unused` to avoid this error){}", - 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()); - } - } - Ok(out) - }), - run: Arc::new(|a, _i| { - let tuple = a.get(); - let tuple = tuple - .as_any() - .downcast_ref::() - .expect("try: not a tuple"); - let arg = &tuple.0[0]; - let funcs = tuple.0[1].get(); - let funcs = funcs.as_any().downcast_ref::().unwrap(); - for func in funcs.0.iter() { - let func = func.get(); - let func = func - .as_any() - .downcast_ref::() - .unwrap(); - if func.check(&arg.get().as_type()).is_ok() { - return func.run(arg.clone()); - } - } - unreachable!("try: no function found") - }), - inner_statements: None, - }) -} +// fn get_try(allow_unused_functions: bool) -> Data { +// Data::new(data::function::Function { +// info: Arc::new(Info::neverused()), +// info_check: Arc::new(Mutex::new(CheckInfo::neverused())), +// out: Arc::new(move |a, _i| { +// let mut out = Type::empty(); +// for t in a.types.iter() { +// if let Some(outer_tuple) = t.as_any().downcast_ref::() { +// 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 = &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 (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::() { +// // f1, f2, f3, ..., fn +// let mut func_errors = vec![]; +// 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 (fvi, ft) in ft.types.iter().enumerate() { +// if let Some(ft) = +// ft.as_any().downcast_ref::() +// { +// 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.o(&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) +// } +// 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()); +// } +// } +// // found a function that won't fail for this arg_type! +// if !func_fallible { +// tuple_fallible = false; +// if tuple_possible { +// skip_checks = true; +// } +// } +// } +// if tuple_fallible || !tuple_possible { +// // 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 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)) +// .err(err); +// } +// } +// return Err(e); +// } +// } else { +// return Err(format!( +// "try: argument must be (arg, (f1, f2, f3, ..., fn))" +// ) +// .into()); +// } +// } +// } +// // check for unused functions +// if !allow_unused_functions { +// 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. (use `try_allow_unused` to avoid this error){}", +// 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()); +// } +// } +// Ok(out) +// }), +// run: Arc::new(|a, _i| { +// let tuple = a.get(); +// let tuple = tuple +// .as_any() +// .downcast_ref::() +// .expect("try: not a tuple"); +// let arg = &tuple.0[0]; +// let funcs = tuple.0[1].get(); +// let funcs = funcs.as_any().downcast_ref::().unwrap(); +// for func in funcs.0.iter() { +// let func = func.get(); +// let func = func +// .as_any() +// .downcast_ref::() +// .unwrap(); +// if func.check(&arg.get().as_type()).is_ok() { +// return func.run(arg.clone()); +// } +// } +// unreachable!("try: no function found") +// }), +// inner_statements: None, +// }) +// } diff --git a/mers_lib/src/program/parsed/mod.rs b/mers_lib/src/program/parsed/mod.rs index 46f4530..433d914 100755 --- a/mers_lib/src/program/parsed/mod.rs +++ b/mers_lib/src/program/parsed/mod.rs @@ -32,6 +32,8 @@ pub mod r#loop; #[cfg(feature = "parse")] pub mod object; #[cfg(feature = "parse")] +pub mod r#try; +#[cfg(feature = "parse")] pub mod tuple; #[cfg(feature = "parse")] pub mod value; diff --git a/mers_lib/src/program/run/loop.rs b/mers_lib/src/program/run/loop.rs index 6750757..97b5387 100644 --- a/mers_lib/src/program/run/loop.rs +++ b/mers_lib/src/program/run/loop.rs @@ -20,7 +20,7 @@ impl MersStatement for Loop { init_to: Option<&Type>, ) -> Result { 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 inner_return_type = self.inner.check(info, None)?; diff --git a/mers_lib/src/program/run/mod.rs b/mers_lib/src/program/run/mod.rs index bc9e163..67dd7ac 100755 --- a/mers_lib/src/program/run/mod.rs +++ b/mers_lib/src/program/run/mod.rs @@ -29,6 +29,8 @@ pub mod r#loop; #[cfg(feature = "run")] pub mod object; #[cfg(feature = "run")] +pub mod r#try; +#[cfg(feature = "run")] pub mod tuple; #[cfg(feature = "run")] pub mod value; @@ -140,6 +142,7 @@ pub struct CheckLocalGlobalInfo { )>, >, >, + pub unused_try_statements: Arc>)>>>, } impl Debug for CheckLocal { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {