diff --git a/mers/Cargo.toml b/mers/Cargo.toml index 3e4c49c..25bfb4f 100644 --- a/mers/Cargo.toml +++ b/mers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mers" -version = "0.8.8" +version = "0.8.9" 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.8.8" +mers_lib = "0.8.9" # 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 e3740c3..7af83a1 100755 --- a/mers/src/main.rs +++ b/mers/src/main.rs @@ -122,7 +122,10 @@ fn main() { exit(255); } Ok(_) => { - compiled.run(&mut i2); + if let Err(e) = compiled.run(&mut i2) { + eprintln!("Error while running: {}", e); + std::process::exit(1); + } } }, } @@ -145,7 +148,10 @@ fn main() { exit(255); } Ok(compiled) => { - compiled.run(&mut i2); + if let Err(e) = compiled.run(&mut i2) { + eprintln!("Error while running: {}", e); + std::process::exit(1); + } } } } diff --git a/mers_lib/Cargo.toml b/mers_lib/Cargo.toml index 2b7d6c4..de20780 100755 --- a/mers_lib/Cargo.toml +++ b/mers_lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mers_lib" -version = "0.8.8" +version = "0.8.9" edition = "2021" license = "MIT OR Apache-2.0" description = "library to use the mers language in other projects" diff --git a/mers_lib/examples/00_parse_compile_check_run.rs b/mers_lib/examples/00_parse_compile_check_run.rs index 15d3f48..8f779a7 100644 --- a/mers_lib/examples/00_parse_compile_check_run.rs +++ b/mers_lib/examples/00_parse_compile_check_run.rs @@ -43,7 +43,7 @@ fn parse_compile_check_run(src: String) -> Result<(Type, Data), CheckError> { // check (this step is optional, but if it is skipped when it would have returned an error, `run` will likely panic) let output_type = compiled.check(&mut i3, None)?; // run - let output_value = compiled.run(&mut i2); + let output_value = compiled.run(&mut i2)?; // check that the predicted output type was correct assert!(output_value.get().as_type().is_included_in(&output_type)); // return the produced value diff --git a/mers_lib/examples/01_user_scripts.rs b/mers_lib/examples/01_user_scripts.rs index 5735bc6..a696819 100644 --- a/mers_lib/examples/01_user_scripts.rs +++ b/mers_lib/examples/01_user_scripts.rs @@ -23,7 +23,7 @@ fn main() -> Result<(), CheckError> { // use the function to decorate these 3 test strings for input in ["my test string", "Main Menu", "O.o"] { - let result = func.run(Data::new(data::string::String(input.to_owned()))); + let result = func.run(Data::new(data::string::String(input.to_owned())))?; let result = result.get(); let result = &result .as_any() @@ -44,6 +44,6 @@ fn parse_compile_check_run(src: String) -> Result<(Type, Data), CheckError> { let (mut i1, mut i2, mut i3) = Config::new().bundle_std().infos(); let compiled = parsed.compile(&mut i1, CompInfo::default())?; let output_type = compiled.check(&mut i3, None)?; - let output_value = compiled.run(&mut i2); + let output_value = compiled.run(&mut i2)?; Ok((output_type, output_value)) } diff --git a/mers_lib/examples/02_own_variable.rs b/mers_lib/examples/02_own_variable.rs index 8ba4e02..b5edf89 100644 --- a/mers_lib/examples/02_own_variable.rs +++ b/mers_lib/examples/02_own_variable.rs @@ -48,7 +48,7 @@ fn run(src: String) -> Result<(), CheckError> { .downcast_ref::() .unwrap() .0; - Data::new(data::string::String(arg.chars().rev().collect())) + Ok(Data::new(data::string::String(arg.chars().rev().collect()))) }, )), ) @@ -56,6 +56,6 @@ fn run(src: String) -> Result<(), CheckError> { let compiled = parsed.compile(&mut i1, CompInfo::default())?; compiled.check(&mut i3, None)?; - compiled.run(&mut i2); + compiled.run(&mut i2)?; Ok(()) } diff --git a/mers_lib/src/data/function.rs b/mers_lib/src/data/function.rs index b699e68..a6a1a7a 100755 --- a/mers_lib/src/data/function.rs +++ b/mers_lib/src/data/function.rs @@ -16,7 +16,8 @@ pub struct Function { pub info: Arc, pub info_check: Arc>, pub out: Arc Result + Send + Sync>, - pub run: Arc Data + Send + Sync>, + pub run: + Arc Result + Send + Sync>, pub inner_statements: Option<( Arc>, Arc>, @@ -25,7 +26,7 @@ pub struct Function { impl Function { pub fn new( out: impl Fn(&Type) -> Result + Send + Sync + 'static, - run: impl Fn(Data) -> Data + Send + Sync + 'static, + run: impl Fn(Data) -> Result + Send + Sync + 'static, ) -> Self { Self { info: Arc::new(crate::info::Info::neverused()), @@ -56,7 +57,7 @@ impl Function { drop(lock); (self.out)(arg, &mut info) } - pub fn run(&self, arg: Data) -> Data { + pub fn run(&self, arg: Data) -> Result { (self.run)(arg, &mut self.info.as_ref().clone()) } pub fn get_as_type(&self) -> FunctionT { @@ -72,10 +73,19 @@ impl Function { } impl MersData for Function { - fn iterable(&self) -> Option>> { + fn iterable(&self) -> Option>>> { let s = Clone::clone(self); Some(Box::new(std::iter::from_fn(move || { - s.run(Data::empty_tuple()).one_tuple_content() + match s.run(Data::empty_tuple()) { + Err(e) => Some(Err(e)), + Ok(v) => { + if let Some(v) = v.one_tuple_content() { + Some(Ok(v)) + } else { + None + } + } + } }))) } fn is_eq(&self, _other: &dyn MersData) -> bool { diff --git a/mers_lib/src/data/mod.rs b/mers_lib/src/data/mod.rs index 16ab49b..45ca992 100755 --- a/mers_lib/src/data/mod.rs +++ b/mers_lib/src/data/mod.rs @@ -4,6 +4,8 @@ use std::{ sync::{atomic::AtomicUsize, Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}, }; +use crate::errors::CheckError; + pub mod bool; pub mod byte; pub mod float; @@ -17,12 +19,12 @@ pub mod tuple; pub mod defs; pub trait MersData: Any + Debug + Display + Send + Sync { - fn iterable(&self) -> Option>> { + fn iterable(&self) -> Option>>> { None } /// By default, uses `iterable` to get an iterator and `nth` to retrieve the nth element. /// Should have a custom implementation for better performance on most types - fn get(&self, i: usize) -> Option { + fn get(&self, i: usize) -> Option> { self.iterable()?.nth(i) } /// If self and other are different types (`other.as_any().downcast_ref::().is_none()`), diff --git a/mers_lib/src/data/tuple.rs b/mers_lib/src/data/tuple.rs index 9719936..1c28936 100755 --- a/mers_lib/src/data/tuple.rs +++ b/mers_lib/src/data/tuple.rs @@ -1,5 +1,7 @@ use std::{any::Any, fmt::Display, sync::Arc}; +use crate::errors::CheckError; + use super::{Data, MersData, MersType, Type}; #[derive(Debug, Clone)] @@ -22,8 +24,8 @@ impl MersData for Tuple { false } } - fn iterable(&self) -> Option>> { - Some(Box::new(self.0.clone().into_iter())) + fn iterable(&self) -> Option>>> { + Some(Box::new(self.0.clone().into_iter().map(Ok))) } fn clone(&self) -> Box { Box::new(Clone::clone(self)) diff --git a/mers_lib/src/errors/mod.rs b/mers_lib/src/errors/mod.rs index b4642c0..9b98e8f 100644 --- a/mers_lib/src/errors/mod.rs +++ b/mers_lib/src/errors/mod.rs @@ -395,6 +395,11 @@ impl From for CheckError { Self::new().msg(value) } } +impl From<&str> for CheckError { + fn from(value: &str) -> Self { + Self::new().msg(value.to_owned()) + } +} impl Debug for CheckError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{self}") diff --git a/mers_lib/src/program/configs/util.rs b/mers_lib/src/program/configs/util.rs index d3932df..3c31001 100644 --- a/mers_lib/src/program/configs/util.rs +++ b/mers_lib/src/program/configs/util.rs @@ -8,7 +8,7 @@ use crate::{ pub fn to_mers_func( out: impl Fn(&Type) -> Result + Send + Sync + 'static, - run: impl Fn(Data) -> Data + Send + Sync + 'static, + run: impl Fn(Data) -> Result + Send + Sync + 'static, ) -> data::function::Function { data::function::Function { info: Arc::new(Info::neverused()), @@ -22,7 +22,7 @@ pub fn to_mers_func( pub fn to_mers_func_with_in_type( in_type: Type, out: impl Fn(&Type) -> Result + Send + Sync + 'static, - run: impl Fn(Data) -> Data + Send + Sync + 'static, + run: impl Fn(Data) -> Result + Send + Sync + 'static, ) -> data::function::Function { to_mers_func( move |a| { @@ -39,7 +39,7 @@ pub fn to_mers_func_with_in_type( pub fn to_mers_func_with_in_out_types( in_type: Type, out_type: Type, - run: impl Fn(Data) -> Data + Send + Sync + 'static, + run: impl Fn(Data) -> Result + Send + Sync + 'static, ) -> data::function::Function { to_mers_func( move |a| { @@ -55,7 +55,7 @@ pub fn to_mers_func_with_in_out_types( pub fn to_mers_func_concrete_string_to_any( out_type: Type, - f: impl Fn(&str) -> Data + Send + Sync + 'static, + f: impl Fn(&str) -> Result + Send + Sync + 'static, ) -> data::function::Function { to_mers_func_with_in_out_types(Type::new(data::string::StringT), out_type, move |a| { f(a.get() @@ -70,13 +70,13 @@ pub fn to_mers_func_concrete_string_to_string( f: impl Fn(&str) -> String + Send + Sync + 'static, ) -> data::function::Function { to_mers_func_concrete_string_to_any(Type::new(data::string::StringT), move |a| { - Data::new(data::string::String(f(a))) + Ok(Data::new(data::string::String(f(a)))) }) } pub fn to_mers_func_concrete_string_string_to_any( out_type: Type, - f: impl Fn(&str, &str) -> Data + Send + Sync + 'static, + f: impl Fn(&str, &str) -> Result + Send + Sync + 'static, ) -> data::function::Function { to_mers_func_with_in_out_types( Type::new(data::tuple::TupleT(vec![ @@ -109,13 +109,13 @@ pub fn to_mers_func_concrete_string_string_to_opt_int( ) -> data::function::Function { to_mers_func_concrete_string_string_to_any( Type::newm(vec![ + Arc::new(data::tuple::TupleT(vec![Type::new(data::int::IntT)])), Arc::new(data::tuple::TupleT(vec![])), - Arc::new(data::int::IntT), ]), move |a, b| { - f(a, b) - .map(|v| Data::new(data::int::Int(v))) - .unwrap_or_else(|| Data::empty_tuple()) + Ok(f(a, b) + .map(|v| Data::one_tuple(Data::new(data::int::Int(v)))) + .unwrap_or_else(|| Data::empty_tuple())) }, ) } @@ -123,7 +123,7 @@ pub fn to_mers_func_concrete_string_string_to_bool( f: impl Fn(&str, &str) -> bool + Send + Sync + 'static, ) -> data::function::Function { to_mers_func_concrete_string_string_to_any(Type::new(data::bool::BoolT), move |a, b| { - Data::new(data::bool::Bool(f(a, b))) + Ok(Data::new(data::bool::Bool(f(a, b)))) }) } pub fn to_mers_func_concrete_string_string_to_opt_string_string( @@ -138,14 +138,14 @@ pub fn to_mers_func_concrete_string_string_to_opt_string_string( ])), ]), move |a, b| { - f(a, b) + Ok(f(a, b) .map(|(a, b)| { Data::new(data::tuple::Tuple(vec![ Data::new(data::string::String(a)), Data::new(data::string::String(b)), ])) }) - .unwrap_or_else(|| Data::empty_tuple()) + .unwrap_or_else(|| Data::empty_tuple())) }, ) } diff --git a/mers_lib/src/program/configs/with_base.rs b/mers_lib/src/program/configs/with_base.rs index a80596d..012426d 100755 --- a/mers_lib/src/program/configs/with_base.rs +++ b/mers_lib/src/program/configs/with_base.rs @@ -70,10 +70,10 @@ impl Config { let mut arg = arg_ref.0.write().unwrap(); let func = a.0[1].get(); let func = func.as_any().downcast_ref::().unwrap(); - *arg = func.run(arg.clone()); - Data::empty_tuple() + *arg = func.run(arg.clone())?; + Ok(Data::empty_tuple()) }), - inner_statements: None, + inner_statements: None, })) .add_var("sleep".to_string(), Data::new(data::function::Function { info: Arc::new(Info::neverused()), @@ -95,11 +95,11 @@ impl Config { } else { unreachable!("sleep called on non-int/non-float") }); - Data::empty_tuple() + Ok(Data::empty_tuple()) }), inner_statements: None, })) - .add_var("panic".to_string(), Data::new(data::function::Function { + .add_var("exit".to_string(), Data::new(data::function::Function { info: Arc::new(Info::neverused()), info_check: Arc::new(Mutex::new(CheckInfo::neverused())), out: Arc::new(|a, _i| if a.is_included_in_single(&data::int::IntT) { @@ -111,6 +111,26 @@ impl Config { std::process::exit(a.get().as_any().downcast_ref::().map(|i| i.0 as _).unwrap_or(1)); }), inner_statements: None, + })) + .add_var("panic".to_string(), Data::new(data::function::Function { + info: Arc::new(Info::neverused()), + info_check: Arc::new(Mutex::new(CheckInfo::neverused())), + out: Arc::new(|a, _i| if a.is_included_in_single(&data::string::StringT) { + Ok(Type::empty()) + } else { + Err(format!("cannot call panic with non-string argument").into()) + }), + run: Arc::new(|a, _i| { + Err( + a + .get() + .as_any() + .downcast_ref::() + .map(|i| i.0.to_owned()) + .unwrap_or_else(String::new).into() + ) + }), + inner_statements: None, })) .add_var( "len".to_string(), @@ -126,7 +146,7 @@ impl Config { Ok(Type::new(data::int::IntT)) }), run: Arc::new(|a, _i| { - Data::new(data::int::Int(if let Some(t) = a.get().as_any().downcast_ref::() { + Ok(Data::new(data::int::Int(if let Some(t) = a.get().as_any().downcast_ref::() { t.0.len() as _ } else if let Some(s) = a.get().as_any().downcast_ref::() { s.0.len() as _ @@ -135,7 +155,7 @@ impl Config { i.take(isize::MAX as usize + 1).count() as isize } else { unreachable!("called len on {a:?}, which isn't a tuple or a string") - })) + }))) }), inner_statements: None, }), @@ -154,10 +174,12 @@ impl Config { Ok(Type::new(data::bool::BoolT)) }), run: Arc::new(|a, _i| { - Data::new(data::bool::Bool(if let Some(mut i) = a.get().iterable() { + Ok(Data::new(data::bool::Bool(if let Some(mut i) = a.get().iterable() { if let Some(f) = i.next() { + let f = f?; let mut o = true; for el in i { + let el = el?; if el != f { o = false; break; @@ -169,7 +191,7 @@ impl Config { } } else { false - })) + }))) }), inner_statements: None, }), @@ -181,7 +203,7 @@ impl Config { info_check: Arc::new(Mutex::new(CheckInfo::neverused())), out: Arc::new(|a, _i| Ok(Type::new(data::reference::ReferenceT(a.clone())))), run: Arc::new(|a, _i| { - Data::new(data::reference::Reference(Arc::new(RwLock::new(a.clone())))) + Ok(Data::new(data::reference::Reference(Arc::new(RwLock::new(a.clone()))))) }), inner_statements: None, }), @@ -199,9 +221,9 @@ impl Config { .as_any() .downcast_ref::() { - r.0.write().unwrap().clone() + Ok(r.0.write().unwrap().clone()) } else { - unreachable!("called deref on non-reference") + Err("called deref on non-reference".into()) } }), inner_statements: None, diff --git a/mers_lib/src/program/configs/with_command_running.rs b/mers_lib/src/program/configs/with_command_running.rs index 2eb11b7..6bcbb82 100755 --- a/mers_lib/src/program/configs/with_command_running.rs +++ b/mers_lib/src/program/configs/with_command_running.rs @@ -7,6 +7,7 @@ use std::{ use crate::{ data::{self, Data, MersData, MersType, Type}, + errors::CheckError, program::{self, run::CheckInfo}, }; @@ -51,8 +52,9 @@ impl Config { cmd.as_any().downcast_ref::().unwrap(), args.get().iterable().unwrap(), ); + let args = args.map(|v| v.map(|v| v.get().to_string())).collect::, _>>()?; match Command::new(&cmd.0) - .args(args.map(|v| v.get().to_string())) + .args(args) .output() { Ok(output) => { @@ -65,13 +67,13 @@ impl Config { String::from_utf8_lossy(&output.stdout).into_owned(); let stderr = String::from_utf8_lossy(&output.stderr).into_owned(); - Data::new(data::tuple::Tuple(vec![ + Ok(Data::new(data::tuple::Tuple(vec![ status, Data::new(data::string::String(stdout)), Data::new(data::string::String(stderr)), - ])) + ]))) } - Err(e) => Data::new(data::object::Object(vec![("run_command_error".to_owned(), Data::new(data::string::String(e.to_string())))])), + Err(e) => Ok(Data::new(data::object::Object(vec![("run_command_error".to_owned(), Data::new(data::string::String(e.to_string())))]))), } }), inner_statements: None, @@ -101,8 +103,9 @@ impl Config { cmd.as_any().downcast_ref::().unwrap(), args.get().iterable().unwrap(), ); + let args = args.map(|v| v.map(|v| v.get().to_string())).collect::, _>>()?; match Command::new(&cmd.0) - .args(args.map(|v| v.get().to_string())) + .args(args) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) @@ -112,9 +115,9 @@ impl Config { let a = Some(child.stdin.take().unwrap()); let b = BufReader::new(child.stdout.take().unwrap()); let c = BufReader::new(child.stderr.take().unwrap()); - Data::new(ChildProcess(Arc::new(Mutex::new((child, a, b, c))))) + Ok(Data::new(ChildProcess(Arc::new(Mutex::new((child, a, b, c)))))) } - Err(e) => Data::new(data::object::Object(vec![("run_command_error".to_owned(), Data::new(data::string::String(e.to_string())))])), + Err(e) => Ok(Data::new(data::object::Object(vec![("run_command_error".to_owned(), Data::new(data::string::String(e.to_string())))]))), } }), inner_statements: None, @@ -139,11 +142,11 @@ impl Config { let a = a.get(); let child = a.as_any().downcast_ref::().unwrap(); let mut child = child.0.lock().unwrap(); - match child.0.try_wait() { + Ok(match child.0.try_wait() { Ok(Some(_)) => Data::one_tuple(Data::new(data::bool::Bool(true))), Ok(None) => Data::one_tuple(Data::new(data::bool::Bool(false))), Err(_) => Data::empty_tuple(), - } + }) }), inner_statements: None, }), @@ -169,14 +172,14 @@ impl Config { let child = a.as_any().downcast_ref::().unwrap(); let mut child = child.0.lock().unwrap(); drop(child.1.take()); - match child.0.wait() { + Ok(match child.0.wait() { Ok(s) => if let Some(s) = s.code() { Data::new(data::int::Int(s as _)) } else { Data::new(data::bool::Bool(s.success())) } Err(_) => Data::empty_tuple(), - } + }) }), inner_statements: None, }), @@ -200,12 +203,12 @@ impl Config { let bytes = tuple.0[1].get(); let child = child.as_any().downcast_ref::().unwrap(); let mut child = child.0.lock().unwrap(); - let buf = bytes.iterable().unwrap().map(|v| v.get().as_any().downcast_ref::().unwrap().0).collect::>(); - if child.1.as_mut().is_some_and(|v| v.write_all(&buf).is_ok() && v.flush().is_ok()) { + let buf = bytes.iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::().unwrap().0)).collect::, _>>()?; + Ok(if child.1.as_mut().is_some_and(|v| v.write_all(&buf).is_ok() && v.flush().is_ok()) { Data::new(data::bool::Bool(true)) } else { Data::new(data::bool::Bool(false)) - } + }) }), inner_statements: None, }), @@ -230,11 +233,11 @@ impl Config { let child = child.as_any().downcast_ref::().unwrap(); let mut child = child.0.lock().unwrap(); let buf = string.as_any().downcast_ref::().unwrap().0.as_bytes(); - if child.1.as_mut().is_some_and(|v| v.write_all(buf).is_ok() && v.flush().is_ok()) { + Ok(if child.1.as_mut().is_some_and(|v| v.write_all(buf).is_ok() && v.flush().is_ok()) { Data::new(data::bool::Bool(true)) } else { Data::new(data::bool::Bool(false)) - } + }) }), inner_statements: None, }), @@ -259,11 +262,11 @@ impl Config { let child = a.as_any().downcast_ref::().unwrap(); let mut child = child.0.lock().unwrap(); let mut buf = [0]; - if child.2.read_exact(&mut buf).is_ok() { + Ok(if child.2.read_exact(&mut buf).is_ok() { Data::one_tuple(Data::new(data::byte::Byte(buf[0]))) } else { Data::empty_tuple() - } + }) }), inner_statements: None, }), @@ -288,11 +291,11 @@ impl Config { let child = a.as_any().downcast_ref::().unwrap(); let mut child = child.0.lock().unwrap(); let mut buf = [0]; - if child.3.read_exact(&mut buf).is_ok() { + Ok(if child.3.read_exact(&mut buf).is_ok() { Data::one_tuple(Data::new(data::byte::Byte(buf[0]))) } else { Data::empty_tuple() - } + }) }), inner_statements: None, }), @@ -317,11 +320,11 @@ impl Config { let child = a.as_any().downcast_ref::().unwrap(); let mut child = child.0.lock().unwrap(); let mut buf = String::new(); - if child.2.read_line(&mut buf).is_ok() { + Ok(if child.2.read_line(&mut buf).is_ok() { Data::one_tuple(Data::new(data::string::String(buf))) } else { Data::empty_tuple() - } + }) }), inner_statements: None, }), @@ -346,11 +349,11 @@ impl Config { let child = a.as_any().downcast_ref::().unwrap(); let mut child = child.0.lock().unwrap(); let mut buf = String::new(); - if child.3.read_line(&mut buf).is_ok() { + Ok(if child.3.read_line(&mut buf).is_ok() { Data::one_tuple(Data::new(data::string::String(buf))) } else { Data::empty_tuple() - } + }) }), inner_statements: None, }), @@ -372,10 +375,10 @@ pub struct ChildProcess( #[derive(Clone, Debug)] pub struct ChildProcessT; impl MersData for ChildProcess { - fn iterable(&self) -> Option>> { + fn iterable(&self) -> Option>>> { None } - fn get(&self, _i: usize) -> Option { + fn get(&self, _i: usize) -> Option> { None } fn is_eq(&self, other: &dyn MersData) -> bool { diff --git a/mers_lib/src/program/configs/with_get.rs b/mers_lib/src/program/configs/with_get.rs index c547707..9ccc9f9 100755 --- a/mers_lib/src/program/configs/with_get.rs +++ b/mers_lib/src/program/configs/with_get.rs @@ -49,21 +49,24 @@ impl Config { run: Arc::new(|a, _i| { let a = a.get(); if let (Some(v), Some(i)) = (a.get(0), a.get(1)) { - if let Some(i) = i.get().as_any().downcast_ref::() { - if let Ok(i) = i.0.try_into() { + let (v, i2) = (v?, i?); + let o = if let Some(i3) = i2.get().as_any().downcast_ref::() + { + if let Ok(i) = i3.0.try_into() { if let Some(v) = v.get().get(i) { - Data::one_tuple(v) + Ok(Data::one_tuple(v?)) } else { - Data::empty_tuple() + Ok(Data::empty_tuple()) } } else { - Data::empty_tuple() + Ok(Data::empty_tuple()) } } else { - unreachable!("get called with non-int index") - } + Err("get called with non-int index".into()) + }; + o } else { - unreachable!("get called with less than 2 args") + Err("get called with less than 2 args".into()) } }), inner_statements: None, diff --git a/mers_lib/src/program/configs/with_iters.rs b/mers_lib/src/program/configs/with_iters.rs index 8ebf0e8..c8d3a58 100755 --- a/mers_lib/src/program/configs/with_iters.rs +++ b/mers_lib/src/program/configs/with_iters.rs @@ -29,10 +29,20 @@ impl Config { pub fn with_iters(self) -> Self { self .add_var("any".to_string(), Data::new(genfunc_iter_in_val_out("all".to_string(), data::bool::BoolT, Type::new(data::bool::BoolT), |a, _i| { - Data::new(data::bool::Bool(a.get().iterable().unwrap().any(|v| v.get().as_any().downcast_ref::().is_some_and(|v| v.0)))) + for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::().is_some_and(|v| v.0))) { + if v? { + return Ok(Data::new(data::bool::Bool(true))); + } + } + Ok(Data::new(data::bool::Bool(false))) }))) .add_var("all".to_string(), Data::new(genfunc_iter_in_val_out("all".to_string(), data::bool::BoolT, Type::new(data::bool::BoolT), |a, _i| { - Data::new(data::bool::Bool(a.get().iterable().unwrap().all(|v| v.get().as_any().downcast_ref::().is_some_and(|v| v.0)))) + for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::().is_some_and(|v| v.0))) { + if !v? { + return Ok(Data::new(data::bool::Bool(false))); + } + } + Ok(Data::new(data::bool::Bool(true))) }))) .add_var( "for_each".to_string(), @@ -83,9 +93,9 @@ impl Config { f.get().as_any().downcast_ref::(), ) { for v in iter { - f.run(v); + f.run(v?)?; } - Data::empty_tuple() + Ok(Data::empty_tuple()) } else { unreachable!( "for_each called on tuple not containing iterable and function" @@ -133,7 +143,7 @@ impl Config { }; Ok(Type::new(IterT::new(ItersT::Enumerate, data)?)) }), - run: Arc::new(|a, _i| Data::new(Iter(Iters::Enumerate, a.clone()))), + run: Arc::new(|a, _i| Ok(Data::new(Iter(Iters::Enumerate, a.clone())))), inner_statements: None, }), ) @@ -150,7 +160,7 @@ impl Config { }; Ok(Type::new(IterT::new(ItersT::Chained, data)?)) }), - run: Arc::new(|a, _i| Data::new(Iter(Iters::Chained, a.clone()))), + run: Arc::new(|a, _i| Ok(Data::new(Iter(Iters::Chained, a.clone())))), inner_statements: None, }), ) @@ -211,7 +221,7 @@ fn genfunc_iter_and_arg( if let Some(tuple) = a.get().as_any().downcast_ref::() { if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) { if let Some(f) = f.get().as_any().downcast_ref::() { - Data::new(Iter(fd(f), v.clone())) + Ok(Data::new(Iter(fd(f), v.clone()))) } else { unreachable!("{name} called on tuple not containing function") } @@ -254,55 +264,76 @@ impl MersData for Iter { fn is_eq(&self, _other: &dyn MersData) -> bool { false } - fn iterable(&self) -> Option>> { + fn iterable(&self) -> Option>>> { Some(match &self.0 { Iters::Map(f) => { let f = Clone::clone(f); - Box::new(self.1.get().iterable()?.map(move |v| f.run(v))) + Box::new(self.1.get().iterable()?.map(move |v| f.run(v?))) } Iters::Filter(f) => { let f = Clone::clone(f); - Box::new(self.1.get().iterable()?.filter(move |v| { - f.run(v.clone()) - .get() - .as_any() - .downcast_ref::() - .is_some_and(|b| b.0) + Box::new(self.1.get().iterable()?.filter_map(move |v| { + match v { + Ok(v) => match f.run(v.clone()) { + Ok(f) => { + if f.get() + .as_any() + .downcast_ref::() + .is_some_and(|b| b.0) + { + Some(Ok(v)) + } else { + None + } + } + Err(e) => Some(Err(e)), + }, + Err(e) => Some(Err(e)), + } })) } Iters::FilterMap(f) => { let f = Clone::clone(f); - Box::new( - self.1 - .get() - .iterable()? - .filter_map(move |v| f.run(v).one_tuple_content()), - ) + Box::new(self.1.get().iterable()?.filter_map(move |v| match v { + Ok(v) => match f.run(v) { + Ok(r) => Some(Ok(r.one_tuple_content()?)), + Err(e) => Some(Err(e)), + }, + Err(e) => Some(Err(e)), + })) } Iters::MapWhile(f) => { let f = Clone::clone(f); - Box::new( - self.1 - .get() - .iterable()? - .map_while(move |v| f.run(v).one_tuple_content()), - ) + Box::new(self.1.get().iterable()?.map_while(move |v| match v { + Ok(v) => match f.run(v) { + Ok(r) => Some(Ok(r.one_tuple_content()?)), + Err(e) => Some(Err(e)), + }, + Err(e) => Some(Err(e)), + })) } Iters::Take(limit) => Box::new(self.1.get().iterable()?.take(*limit)), - Iters::Enumerate => Box::new(self.1.get().iterable()?.enumerate().map(|(i, v)| { - Data::new(data::tuple::Tuple(vec![ - Data::new(data::int::Int(i as _)), - v, - ])) - })), + Iters::Enumerate => { + Box::new(self.1.get().iterable()?.enumerate().map(|(i, v)| match v { + Ok(v) => Ok(Data::new(data::tuple::Tuple(vec![ + Data::new(data::int::Int(i as _)), + v, + ]))), + Err(e) => Err(e), + })) + } Iters::Chained => { - let iters = self + match self .1 .get() .iterable()? - .map(|v| v.get().iterable()) - .collect::>>()?; - Box::new(iters.into_iter().flatten()) + .map(|v| Ok(v?.get().iterable())) + .collect::>, CheckError>>() + { + Ok(Some(iters)) => Box::new(iters.into_iter().flatten()), + Ok(None) => return None, + Err(e) => Box::new([Err(e)].into_iter()), + } } }) } @@ -433,7 +464,10 @@ fn genfunc_iter_in_val_out( name: String, iter_type: impl MersType + 'static, out_type: Type, - run: impl Fn(Data, &mut crate::info::Info) -> Data + Send + Sync + 'static, + run: impl Fn(Data, &mut crate::info::Info) -> Result + + Send + + Sync + + 'static, ) -> Function { Function { info: Arc::new(crate::info::Info::neverused()), diff --git a/mers_lib/src/program/configs/with_list.rs b/mers_lib/src/program/configs/with_list.rs index ada337a..182f913 100755 --- a/mers_lib/src/program/configs/with_list.rs +++ b/mers_lib/src/program/configs/with_list.rs @@ -5,6 +5,7 @@ use std::{ use crate::{ data::{self, Data, MersData, MersType, Type}, + errors::CheckError, parsing::{statements::to_string_literal, Source}, program::{self, run::CheckInfo}, }; @@ -93,7 +94,7 @@ impl Config { } None => Data::empty_tuple(), }; - o + Ok(o) }), inner_statements: None, })) @@ -123,7 +124,7 @@ impl Config { } }), run: Arc::new(|a, _i| { - match a + Ok(match a .get() .as_any() .downcast_ref::() @@ -140,7 +141,7 @@ impl Config { { Some(data) => Data::one_tuple(data.read().unwrap().clone()), None => Data::empty_tuple(), - } + }) }), inner_statements: None, }), @@ -203,7 +204,7 @@ impl Config { .unwrap() .0 .push(Arc::new(RwLock::new(tuple.0[1].clone()))); - Data::empty_tuple() + Ok(Data::empty_tuple()) }), inner_statements: None, }), @@ -224,9 +225,9 @@ impl Config { }), run: Arc::new(|a, _i| { if let Some(i) = a.get().iterable() { - Data::new(List(i.map(|v| Arc::new(RwLock::new(v))).collect())) + Ok(Data::new(List(i.map(|v| Ok::<_, CheckError>(Arc::new(RwLock::new(v?)))).collect::>()?))) } else { - unreachable!("as_list called on non-iterable") + Err("as_list called on non-iterable".into()) } }), inner_statements: None, @@ -262,12 +263,12 @@ impl MersData for List { false } } - fn iterable(&self) -> Option>> { + fn iterable(&self) -> Option>>> { Some(Box::new( self.0 .clone() .into_iter() - .map(|v| v.read().unwrap().clone()), + .map(|v| Ok(v.read().unwrap().clone())), )) } fn clone(&self) -> Box { diff --git a/mers_lib/src/program/configs/with_math.rs b/mers_lib/src/program/configs/with_math.rs index 07a1f66..a67ef6e 100755 --- a/mers_lib/src/program/configs/with_math.rs +++ b/mers_lib/src/program/configs/with_math.rs @@ -72,11 +72,11 @@ impl Config { } }), run: Arc::new(|a, _i| { - if let Ok(n) = a.get().as_any().downcast_ref::().unwrap().0.parse() { + Ok(if let Ok(n) = a.get().as_any().downcast_ref::().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 { @@ -95,11 +95,11 @@ impl Config { } }), run: Arc::new(|a, _i| { - if let Ok(n) = a.get().as_any().downcast_ref::().unwrap().0.parse() { + Ok(if let Ok(n) = a.get().as_any().downcast_ref::().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 { @@ -113,7 +113,7 @@ impl Config { } }), run: Arc::new(|a, _i| { - Data::new(data::int::Int(if let Some(n) = a.get().as_any().downcast_ref::() { + Ok(Data::new(data::int::Int(if let Some(n) = a.get().as_any().downcast_ref::() { n.0.signum() } else if let Some(n) = a.get().as_any().downcast_ref::() { @@ -123,7 +123,7 @@ impl Config { -1 } else { 0 } - } else { unreachable!("called signum on non-number type")})) + } else { unreachable!("called signum on non-number type")}))) }), inner_statements: None, })) .add_var("div".to_string(), Data::new(data::function::Function { @@ -137,10 +137,10 @@ impl Config { match (left.downcast_ref::(), left.downcast_ref::(), right.downcast_ref::(), right.downcast_ref::() ) { - (Some(data::int::Int(l)), None, Some(data::int::Int(r)), None) => Data::new(data::int::Int(l / r)), - (Some(data::int::Int(l)), None, None, Some(data::float::Float(r))) => Data::new(data::float::Float(*l as f64 / r)), - (None, Some(data::float::Float(l)), Some(data::int::Int(r)), None) => Data::new(data::float::Float(l / *r as f64)), - (None, Some(data::float::Float(l)), None, Some(data::float::Float(r))) => Data::new(data::float::Float(l / r)), + (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))), _ => unreachable!(), } } else { unreachable!() }), @@ -156,10 +156,10 @@ impl Config { match (left.downcast_ref::(), left.downcast_ref::(), right.downcast_ref::(), right.downcast_ref::() ) { - (Some(data::int::Int(l)), None, Some(data::int::Int(r)), None) => Data::new(data::int::Int(l % r)), - (Some(data::int::Int(l)), None, None, Some(data::float::Float(r))) => Data::new(data::float::Float(*l as f64 % r)), - (None, Some(data::float::Float(l)), Some(data::int::Int(r)), None) => Data::new(data::float::Float(l % *r as f64)), - (None, Some(data::float::Float(l)), None, Some(data::float::Float(r))) => Data::new(data::float::Float(l % r)), + (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))), _ => unreachable!(), } } else { unreachable!() }), @@ -206,20 +206,22 @@ impl Config { let mut sumf = 0.0; let mut usef = false; for val in i { - if let Some(i) = val.get().as_any().downcast_ref::() { + let val = val?; + let o = if let Some(i) = val.get().as_any().downcast_ref::() { sumi += i.0; } else if let Some(i) = val.get().as_any().downcast_ref::() { sumf += i.0; usef = true; - } + }; + o } - if usef { + Ok(if usef { Data::new(data::float::Float(sumi as f64 + sumf)) } else { Data::new(data::int::Int(sumi)) - } + }) } else { unreachable!("sum called on non-tuple") } @@ -269,6 +271,7 @@ impl Config { 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::() { if first { sumi = i.0; @@ -289,11 +292,11 @@ impl Config { first = false; } } - if usef { + Ok(if usef { Data::new(data::float::Float(sumi as f64 + sumf)) } else { Data::new(data::int::Int(sumi)) - } + }) } else { unreachable!("sum called on non-tuple") } @@ -342,20 +345,22 @@ impl Config { let mut prodf = 1.0; let mut usef = false; for val in i { - if let Some(i) = val.get().as_any().downcast_ref::() { + let val = val?; + let o = if let Some(i) = val.get().as_any().downcast_ref::() { prodi *= i.0; } else if let Some(i) = val.get().as_any().downcast_ref::() { prodf *= i.0; usef = true; - } + }; + o } - if usef { + Ok(if usef { Data::new(data::float::Float(prodi as f64 * prodf)) } else { Data::new(data::int::Int(prodi)) - } + }) } else { unreachable!("product called on non-tuple") } @@ -424,6 +429,7 @@ fn ltgtoe_function( run: Arc::new(move |a, _i| { let mut prev = IntOrFloatOrNothing::Nothing; for item in a.get().iterable().unwrap() { + let item = item?; let item = item.get(); let new = if let Some(data::int::Int(v)) = item.as_any().downcast_ref() { IntOrFloatOrNothing::Int(*v) @@ -435,10 +441,10 @@ fn ltgtoe_function( if op(prev, new) { prev = new; } else { - return Data::new(data::bool::Bool(false)); + return Ok(Data::new(data::bool::Bool(false))); } } - Data::new(data::bool::Bool(true)) + Ok(Data::new(data::bool::Bool(true))) }), inner_statements: None, } diff --git a/mers_lib/src/program/configs/with_multithreading.rs b/mers_lib/src/program/configs/with_multithreading.rs index 2dbee37..62ac4a9 100755 --- a/mers_lib/src/program/configs/with_multithreading.rs +++ b/mers_lib/src/program/configs/with_multithreading.rs @@ -53,9 +53,9 @@ impl Config { .downcast_ref::() .cloned() { - Data::new(Thread(Arc::new(Mutex::new(Ok(std::thread::spawn( + Ok(Data::new(Thread(Arc::new(Mutex::new(Ok(std::thread::spawn( move || f.run(Data::empty_tuple()), - )))))) + ))))))) } else { unreachable!("thread called, but arg wasn't a function"); } @@ -77,10 +77,10 @@ impl Config { run: Arc::new(|a, _i| { let a = a.get(); let t = a.as_any().downcast_ref::().unwrap().0.lock().unwrap(); - Data::new(data::bool::Bool(match &*t { + Ok(Data::new(data::bool::Bool(match &*t { Ok(t) => t.is_finished(), Err(_d) => true, - })) + }))) }), inner_statements: None, })) @@ -101,7 +101,7 @@ impl Config { run: Arc::new(|a, _i| { let a = a.get(); let mut t = a.as_any().downcast_ref::().unwrap().0.lock().unwrap(); - let d = match std::mem::replace(&mut *t, Err(Data::empty_tuple())) { + let d = match std::mem::replace(&mut *t, Err(Err(CheckError::new()))) { Ok(t) => t.join().unwrap(), Err(d) => d, }; @@ -114,7 +114,9 @@ impl Config { } #[derive(Clone)] -pub struct Thread(pub Arc, Data>>>); +pub struct Thread( + pub Arc>, Result>>>, +); #[derive(Debug, Clone)] pub struct ThreadT(pub Type); diff --git a/mers_lib/src/program/configs/with_stdio.rs b/mers_lib/src/program/configs/with_stdio.rs index 93a1377..22ffbf5 100755 --- a/mers_lib/src/program/configs/with_stdio.rs +++ b/mers_lib/src/program/configs/with_stdio.rs @@ -41,11 +41,11 @@ impl Config { } }), run: Arc::new(|_a, _i| { - if let Some(Ok(line)) = std::io::stdin().lines().next() { + Ok(if let Some(Ok(line)) = std::io::stdin().lines().next() { Data::one_tuple(Data::new(data::string::String(line))) } else { Data::empty_tuple() - } + }) }), inner_statements: None, }), @@ -60,7 +60,7 @@ impl Config { let a2 = a.get(); eprintln!("{} :: {}", a2.as_type(), a2); drop(a2); - a + Ok(a) }), inner_statements: None, }), @@ -74,7 +74,7 @@ impl Config { run: Arc::new(|a, _i| { eprint!("{}", a.get()); _ = std::io::stderr().lock().flush(); - Data::empty_tuple() + Ok(Data::empty_tuple()) }), inner_statements: None, }), @@ -87,7 +87,7 @@ impl Config { out: Arc::new(|_a, _i| Ok(Type::empty_tuple())), run: Arc::new(|a, _i| { eprintln!("{}", a.get()); - Data::empty_tuple() + Ok(Data::empty_tuple()) }), inner_statements: None, }), @@ -101,7 +101,7 @@ impl Config { run: Arc::new(|a, _i| { print!("{}", a.get()); _ = std::io::stdout().lock().flush(); - Data::empty_tuple() + Ok(Data::empty_tuple()) }), inner_statements: None, }), @@ -114,7 +114,7 @@ impl Config { out: Arc::new(|_a, _i| Ok(Type::empty_tuple())), run: Arc::new(|a, _i| { println!("{}", a.get()); - Data::empty_tuple() + Ok(Data::empty_tuple()) }), inner_statements: None, }), diff --git a/mers_lib/src/program/configs/with_string.rs b/mers_lib/src/program/configs/with_string.rs index 67b9eae..371017e 100755 --- a/mers_lib/src/program/configs/with_string.rs +++ b/mers_lib/src/program/configs/with_string.rs @@ -25,17 +25,17 @@ impl Config { .add_var("ends_with".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_bool(|v, p| v.ends_with(p)))) .add_var("str_split_once".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_opt_string_string(|v, p| v.split_once(p).map(|(a, b)| (a.to_owned(), b.to_owned()))))) .add_var("str_split_once_rev".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_opt_string_string(|v, p| v.rsplit_once(p).map(|(a, b)| (a.to_owned(), b.to_owned()))))) - .add_var("str_split".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_any(Type::new(super::with_list::ListT(Type::new(data::string::StringT))), |v, p| Data::new(super::with_list::List(v.split(p).map(|v| Arc::new(RwLock::new(Data::new(data::string::String(v.to_owned()))))).collect()))))) + .add_var("str_split".to_string(), Data::new(util::to_mers_func_concrete_string_string_to_any(Type::new(super::with_list::ListT(Type::new(data::string::StringT))), |v, p| Ok(Data::new(super::with_list::List(v.split(p).map(|v| Arc::new(RwLock::new(Data::new(data::string::String(v.to_owned()))))).collect())))))) .add_var("concat".to_string(), Data::new(util::to_mers_func( |a| if a.iterable().is_some() { Ok(Type::new(data::string::StringT)) } else { Err(format!("concat called on non-iterable type {a}").into()) }, - |a| Data::new(data::string::String(a.get().iterable().unwrap().map(|v| v.get().to_string()).collect()))), + |a| Ok(Data::new(data::string::String(a.get().iterable().unwrap().map(|v| v.map(|v| v.get().to_string())).collect::>()?)))), )) .add_var("to_string".to_string(), Data::new(util::to_mers_func(|_a| Ok(Type::new(data::string::StringT)), - |a| Data::new(data::string::String(a.get().to_string())) + |a| Ok(Data::new(data::string::String(a.get().to_string()))) ))) .add_var("substring".to_string(), Data::new(util::to_mers_func( |a| { @@ -79,9 +79,9 @@ impl Config { .unwrap_or(usize::MAX); let end = end.min(s.len()); if end < start { - return Data::new(data::string::String(String::new())); + return Ok(Data::new(data::string::String(String::new()))); } - Data::new(data::string::String(s[start..end].to_owned())) + Ok(Data::new(data::string::String(s[start..end].to_owned()))) }) )) } diff --git a/mers_lib/src/program/parsed/function.rs b/mers_lib/src/program/parsed/function.rs index 759960f..2b39661 100755 --- a/mers_lib/src/program/parsed/function.rs +++ b/mers_lib/src/program/parsed/function.rs @@ -43,7 +43,7 @@ impl MersStatement for Function { Ok(run2.check(i, None)?) }), run: Arc::new(move |arg, info| { - data::defs::assign(&arg, &arg_target.run(info)); + data::defs::assign(&arg, &arg_target.run(info)?); run.run(info) }), inner_statements: Some((arg3, run3)), diff --git a/mers_lib/src/program/run/as_type.rs b/mers_lib/src/program/run/as_type.rs index f59abb3..c1d79dc 100644 --- a/mers_lib/src/program/run/as_type.rs +++ b/mers_lib/src/program/run/as_type.rs @@ -66,7 +66,7 @@ impl MersStatement for AsType { return_type }) } - fn run_custom(&self, info: &mut super::Info) -> Data { + fn run_custom(&self, info: &mut super::Info) -> Result { self.statement.run(info) } fn has_scope(&self) -> bool { diff --git a/mers_lib/src/program/run/assign_to.rs b/mers_lib/src/program/run/assign_to.rs index 0ed67f8..6f4cb3f 100755 --- a/mers_lib/src/program/run/assign_to.rs +++ b/mers_lib/src/program/run/assign_to.rs @@ -77,11 +77,11 @@ impl MersStatement for AssignTo { } Ok(Type::empty_tuple()) } - fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { - let source = self.source.run(info); - let target = self.target.run(info); + fn run_custom(&self, info: &mut super::Info) -> Result { + let source = self.source.run(info)?; + let target = self.target.run(info)?; data::defs::assign(&source, &target); - Data::empty_tuple() + Ok(Data::empty_tuple()) } fn has_scope(&self) -> bool { false diff --git a/mers_lib/src/program/run/block.rs b/mers_lib/src/program/run/block.rs index c73a43d..22ba127 100755 --- a/mers_lib/src/program/run/block.rs +++ b/mers_lib/src/program/run/block.rs @@ -1,5 +1,5 @@ use crate::{ - data::Type, + data::{self, Data, Type}, errors::{CheckError, SourceRange}, }; @@ -25,12 +25,12 @@ impl MersStatement for Block { } Ok(o) } - fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { + fn run_custom(&self, info: &mut super::Info) -> Result { self.statements .iter() .map(|s| s.run(info)) .last() - .unwrap_or_else(|| crate::data::Data::new(crate::data::tuple::Tuple(vec![]))) + .unwrap_or_else(|| Ok(Data::new(data::tuple::Tuple(vec![])))) } fn has_scope(&self) -> bool { true diff --git a/mers_lib/src/program/run/chain.rs b/mers_lib/src/program/run/chain.rs index 92ff676..f6b3c45 100755 --- a/mers_lib/src/program/run/chain.rs +++ b/mers_lib/src/program/run/chain.rs @@ -88,12 +88,42 @@ impl MersStatement for Chain { } Ok(o) } - fn run_custom(&self, info: &mut super::Info) -> Data { - let f = self.first.run(info); - let c = self.chained.run(info); + fn run_custom(&self, info: &mut super::Info) -> Result { + let f = self.first.run(info)?; + let c = self.chained.run(info)?; let c = c.get(); if let Some(func) = c.as_any().downcast_ref::() { - func.run(f) + 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) + } 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) + }), + } } else { todo!("err: not a function"); } diff --git a/mers_lib/src/program/run/custom_type.rs b/mers_lib/src/program/run/custom_type.rs index 3963e2e..910f8d4 100644 --- a/mers_lib/src/program/run/custom_type.rs +++ b/mers_lib/src/program/run/custom_type.rs @@ -56,8 +56,8 @@ impl MersStatement for CustomType { } Ok(Type::empty_tuple()) } - fn run_custom(&self, _info: &mut Info) -> Data { - Data::empty_tuple() + fn run_custom(&self, _info: &mut Info) -> Result { + Ok(Data::empty_tuple()) } fn has_scope(&self) -> bool { false diff --git a/mers_lib/src/program/run/function.rs b/mers_lib/src/program/run/function.rs index 090a9f7..67e6254 100755 --- a/mers_lib/src/program/run/function.rs +++ b/mers_lib/src/program/run/function.rs @@ -25,8 +25,10 @@ impl MersStatement for Function { self.func_no_info.with_info_check(info.clone()); Ok(self.func_no_info.as_type()) } - fn run_custom(&self, info: &mut super::Info) -> Data { - Data::new(self.func_no_info.with_info_run(Arc::new(info.clone()))) + fn run_custom(&self, info: &mut super::Info) -> Result { + Ok(Data::new( + self.func_no_info.with_info_run(Arc::new(info.clone())), + )) } fn has_scope(&self) -> bool { true diff --git a/mers_lib/src/program/run/if.rs b/mers_lib/src/program/run/if.rs index b436428..019f919 100755 --- a/mers_lib/src/program/run/if.rs +++ b/mers_lib/src/program/run/if.rs @@ -52,20 +52,22 @@ impl MersStatement for If { } Ok(t) } - fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { - if let Some(data::bool::Bool(true)) = self - .condition - .run(info) - .get() - .as_any() - .downcast_ref::() - { - self.on_true.run(info) - } else if let Some(on_false) = &self.on_false { - on_false.run(info) - } else { - Data::empty_tuple() - } + fn run_custom(&self, info: &mut super::Info) -> Result { + Ok( + if let Some(data::bool::Bool(true)) = self + .condition + .run(info)? + .get() + .as_any() + .downcast_ref::() + { + self.on_true.run(info)? + } else if let Some(on_false) = &self.on_false { + on_false.run(info)? + } else { + Data::empty_tuple() + }, + ) } fn has_scope(&self) -> bool { true diff --git a/mers_lib/src/program/run/loop.rs b/mers_lib/src/program/run/loop.rs index 97b5387..8b1befe 100644 --- a/mers_lib/src/program/run/loop.rs +++ b/mers_lib/src/program/run/loop.rs @@ -47,10 +47,10 @@ impl MersStatement for Loop { } Ok(t) } - fn run_custom(&self, info: &mut Info) -> Data { + fn run_custom(&self, info: &mut Info) -> Result { loop { - if let Some(v) = self.inner.run(info).one_tuple_content() { - return v; + if let Some(v) = self.inner.run(info)?.one_tuple_content() { + return Ok(v); } } } diff --git a/mers_lib/src/program/run/mod.rs b/mers_lib/src/program/run/mod.rs index 289612f..9a8acef 100755 --- a/mers_lib/src/program/run/mod.rs +++ b/mers_lib/src/program/run/mod.rs @@ -43,7 +43,7 @@ pub trait MersStatement: Debug + Send + Sync { info: &mut CheckInfo, init_to: Option<&Type>, ) -> Result; - fn run_custom(&self, info: &mut Info) -> Data; + fn run_custom(&self, info: &mut Info) -> Result; /// if true, local variables etc. will be contained inside their own scope. fn has_scope(&self) -> bool; fn check(&self, info: &mut CheckInfo, init_to: Option<&Type>) -> Result { @@ -93,7 +93,7 @@ pub trait MersStatement: Debug + Send + Sync { info.global.depth -= 1; o } - fn run(&self, info: &mut Info) -> Data { + fn run(&self, info: &mut Info) -> Result { if self.has_scope() { info.create_scope(); } diff --git a/mers_lib/src/program/run/object.rs b/mers_lib/src/program/run/object.rs index ab15d06..6671944 100644 --- a/mers_lib/src/program/run/object.rs +++ b/mers_lib/src/program/run/object.rs @@ -119,13 +119,13 @@ impl MersStatement for Object { .collect::>()?, ))) } - fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { - Data::new(data::object::Object( + fn run_custom(&self, info: &mut super::Info) -> Result { + Ok(Data::new(data::object::Object( self.elems .iter() - .map(|(n, s)| (n.clone(), s.run(info))) - .collect(), - )) + .map(|(n, s)| Ok::<_, CheckError>((n.clone(), s.run(info)?))) + .collect::>()?, + ))) } fn has_scope(&self) -> bool { false diff --git a/mers_lib/src/program/run/try.rs b/mers_lib/src/program/run/try.rs index c424e44..0df64e8 100644 --- a/mers_lib/src/program/run/try.rs +++ b/mers_lib/src/program/run/try.rs @@ -103,8 +103,8 @@ impl MersStatement for Try { } Ok(t) } - fn run_custom(&self, info: &mut Info) -> Data { - let arg = self.arg.run(info); + fn run_custom(&self, info: &mut Info) -> Result { + let arg = self.arg.run(info)?; let ar = arg.get(); let a = ar.as_ref(); let arg_type = a.as_type(); @@ -112,14 +112,16 @@ impl MersStatement for Try { .funcs .iter() .map(|v| { - v.run(info) - .get() - .as_any() - .downcast_ref::() - .unwrap() - .clone() + Ok::<_, CheckError>( + v.run(info)? + .get() + .as_any() + .downcast_ref::() + .unwrap() + .clone(), + ) }) - .collect::>(); + .collect::, _>>()?; let mut found = None; for (i, func) in functions.iter().enumerate() { match func.get_as_type().o(&arg_type) { diff --git a/mers_lib/src/program/run/tuple.rs b/mers_lib/src/program/run/tuple.rs index 8387b30..9120fdd 100755 --- a/mers_lib/src/program/run/tuple.rs +++ b/mers_lib/src/program/run/tuple.rs @@ -4,7 +4,7 @@ use colored::Colorize; use crate::{ data::{self, tuple::TupleT, Data, Type}, - errors::{error_colors, SourceRange}, + errors::{error_colors, CheckError, SourceRange}, }; use super::MersStatement; @@ -82,10 +82,13 @@ impl MersStatement for Tuple { .collect::>()?, ))) } - fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { - Data::new(data::tuple::Tuple( - self.elems.iter().map(|s| s.run(info)).collect(), - )) + fn run_custom(&self, info: &mut super::Info) -> Result { + Ok(Data::new(data::tuple::Tuple( + self.elems + .iter() + .map(|s| Ok(s.run(info)?)) + .collect::>()?, + ))) } fn has_scope(&self) -> bool { false diff --git a/mers_lib/src/program/run/value.rs b/mers_lib/src/program/run/value.rs index 166e809..f1fa243 100755 --- a/mers_lib/src/program/run/value.rs +++ b/mers_lib/src/program/run/value.rs @@ -1,6 +1,6 @@ use crate::{ data::{Data, Type}, - errors::SourceRange, + errors::{CheckError, SourceRange}, }; use super::{CheckInfo, MersStatement}; @@ -25,8 +25,8 @@ impl MersStatement for Value { } Ok(self.val.get().as_type()) } - fn run_custom(&self, _info: &mut super::Info) -> Data { - self.val.clone() + fn run_custom(&self, _info: &mut super::Info) -> Result { + Ok(self.val.clone()) } fn source_range(&self) -> SourceRange { self.pos_in_src.clone() diff --git a/mers_lib/src/program/run/variable.rs b/mers_lib/src/program/run/variable.rs index c8c5922..a38f86c 100755 --- a/mers_lib/src/program/run/variable.rs +++ b/mers_lib/src/program/run/variable.rs @@ -2,7 +2,7 @@ use std::sync::{Arc, RwLock}; use crate::{ data::{self, Data, Type}, - errors::SourceRange, + errors::{CheckError, SourceRange}, }; use super::MersStatement; @@ -50,7 +50,7 @@ impl MersStatement for Variable { }; Ok(val) } - fn run_custom(&self, info: &mut super::Info) -> Data { + fn run_custom(&self, info: &mut super::Info) -> Result { if self.is_init { if self.is_ref_not_ignore { let nothing = Arc::new(RwLock::new(Data::new(data::bool::Bool(false)))); @@ -60,12 +60,12 @@ impl MersStatement for Variable { info.scopes[self.var.0].vars[self.var.1] = nothing; } else { // (reference to) data which will never be referenced again - return Data::new(data::reference::Reference(Arc::new(RwLock::new( - Data::empty_tuple(), + return Ok(Data::new(data::reference::Reference(Arc::new( + RwLock::new(Data::empty_tuple()), )))); } } - if self.is_ref_not_ignore { + Ok(if self.is_ref_not_ignore { let v = &info.scopes[self.var.0].vars[self.var.1]; Data::new(data::reference::Reference(Arc::clone(v))) } else { @@ -73,7 +73,7 @@ impl MersStatement for Variable { .write() .unwrap() .clone() - } + }) } fn source_range(&self) -> SourceRange { self.pos_in_src.clone()