improve panic function, add stacktrace

This commit is contained in:
Mark 2024-06-19 12:35:23 +02:00
parent 4770e3f939
commit cd21c2171e
35 changed files with 367 additions and 232 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "mers" name = "mers"
version = "0.8.8" version = "0.8.9"
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.8.8" mers_lib = "0.8.9"
# 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

@ -122,7 +122,10 @@ fn main() {
exit(255); exit(255);
} }
Ok(_) => { 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); exit(255);
} }
Ok(compiled) => { Ok(compiled) => {
compiled.run(&mut i2); if let Err(e) = compiled.run(&mut i2) {
eprintln!("Error while running: {}", e);
std::process::exit(1);
}
} }
} }
} }

View File

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

@ -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) // 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)?; let output_type = compiled.check(&mut i3, None)?;
// run // run
let output_value = compiled.run(&mut i2); let output_value = compiled.run(&mut i2)?;
// check that the predicted output type was correct // check that the predicted output type was correct
assert!(output_value.get().as_type().is_included_in(&output_type)); assert!(output_value.get().as_type().is_included_in(&output_type));
// return the produced value // return the produced value

View File

@ -23,7 +23,7 @@ fn main() -> Result<(), CheckError> {
// use the function to decorate these 3 test strings // use the function to decorate these 3 test strings
for input in ["my test string", "Main Menu", "O.o"] { 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.get();
let result = &result let result = &result
.as_any() .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 (mut i1, mut i2, mut i3) = Config::new().bundle_std().infos();
let compiled = parsed.compile(&mut i1, CompInfo::default())?; let compiled = parsed.compile(&mut i1, CompInfo::default())?;
let output_type = compiled.check(&mut i3, None)?; 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)) Ok((output_type, output_value))
} }

View File

@ -48,7 +48,7 @@ fn run(src: String) -> Result<(), CheckError> {
.downcast_ref::<data::string::String>() .downcast_ref::<data::string::String>()
.unwrap() .unwrap()
.0; .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())?; let compiled = parsed.compile(&mut i1, CompInfo::default())?;
compiled.check(&mut i3, None)?; compiled.check(&mut i3, None)?;
compiled.run(&mut i2); compiled.run(&mut i2)?;
Ok(()) Ok(())
} }

View File

@ -16,7 +16,8 @@ pub struct Function {
pub info: Arc<Info>, pub info: Arc<Info>,
pub info_check: Arc<Mutex<CheckInfo>>, pub info_check: Arc<Mutex<CheckInfo>>,
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) -> Result<Data, CheckError> + Send + Sync>,
pub inner_statements: Option<( pub inner_statements: Option<(
Arc<Box<dyn crate::program::run::MersStatement>>, Arc<Box<dyn crate::program::run::MersStatement>>,
Arc<Box<dyn crate::program::run::MersStatement>>, Arc<Box<dyn crate::program::run::MersStatement>>,
@ -25,7 +26,7 @@ pub struct Function {
impl Function { impl Function {
pub fn new( pub fn new(
out: impl Fn(&Type) -> Result<Type, CheckError> + Send + Sync + 'static, out: impl Fn(&Type) -> Result<Type, CheckError> + Send + Sync + 'static,
run: impl Fn(Data) -> Data + Send + Sync + 'static, run: impl Fn(Data) -> Result<Data, CheckError> + Send + Sync + 'static,
) -> Self { ) -> Self {
Self { Self {
info: Arc::new(crate::info::Info::neverused()), info: Arc::new(crate::info::Info::neverused()),
@ -56,7 +57,7 @@ impl Function {
drop(lock); drop(lock);
(self.out)(arg, &mut info) (self.out)(arg, &mut info)
} }
pub fn run(&self, arg: Data) -> Data { pub fn run(&self, arg: Data) -> Result<Data, CheckError> {
(self.run)(arg, &mut self.info.as_ref().clone()) (self.run)(arg, &mut self.info.as_ref().clone())
} }
pub fn get_as_type(&self) -> FunctionT { pub fn get_as_type(&self) -> FunctionT {
@ -72,10 +73,19 @@ impl Function {
} }
impl MersData for Function { impl MersData for Function {
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Data>>> { fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
let s = Clone::clone(self); let s = Clone::clone(self);
Some(Box::new(std::iter::from_fn(move || { 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 { fn is_eq(&self, _other: &dyn MersData) -> bool {

View File

@ -4,6 +4,8 @@ use std::{
sync::{atomic::AtomicUsize, Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}, sync::{atomic::AtomicUsize, Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
}; };
use crate::errors::CheckError;
pub mod bool; pub mod bool;
pub mod byte; pub mod byte;
pub mod float; pub mod float;
@ -17,12 +19,12 @@ pub mod tuple;
pub mod defs; pub mod defs;
pub trait MersData: Any + Debug + Display + Send + Sync { pub trait MersData: Any + Debug + Display + Send + Sync {
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Data>>> { fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
None None
} }
/// By default, uses `iterable` to get an iterator and `nth` to retrieve the nth element. /// 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 /// Should have a custom implementation for better performance on most types
fn get(&self, i: usize) -> Option<Data> { fn get(&self, i: usize) -> Option<Result<Data, CheckError>> {
self.iterable()?.nth(i) self.iterable()?.nth(i)
} }
/// If self and other are different types (`other.as_any().downcast_ref::<Self>().is_none()`), /// If self and other are different types (`other.as_any().downcast_ref::<Self>().is_none()`),

View File

@ -1,5 +1,7 @@
use std::{any::Any, fmt::Display, sync::Arc}; use std::{any::Any, fmt::Display, sync::Arc};
use crate::errors::CheckError;
use super::{Data, MersData, MersType, Type}; use super::{Data, MersData, MersType, Type};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -22,8 +24,8 @@ impl MersData for Tuple {
false false
} }
} }
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Data>>> { fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
Some(Box::new(self.0.clone().into_iter())) Some(Box::new(self.0.clone().into_iter().map(Ok)))
} }
fn clone(&self) -> Box<dyn MersData> { fn clone(&self) -> Box<dyn MersData> {
Box::new(Clone::clone(self)) Box::new(Clone::clone(self))

View File

@ -395,6 +395,11 @@ impl From<String> for CheckError {
Self::new().msg(value) Self::new().msg(value)
} }
} }
impl From<&str> for CheckError {
fn from(value: &str) -> Self {
Self::new().msg(value.to_owned())
}
}
impl Debug for CheckError { impl Debug for CheckError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self}") write!(f, "{self}")

View File

@ -8,7 +8,7 @@ use crate::{
pub fn to_mers_func( pub fn to_mers_func(
out: impl Fn(&Type) -> Result<Type, CheckError> + Send + Sync + 'static, out: impl Fn(&Type) -> Result<Type, CheckError> + Send + Sync + 'static,
run: impl Fn(Data) -> Data + Send + Sync + 'static, run: impl Fn(Data) -> Result<Data, CheckError> + Send + Sync + 'static,
) -> data::function::Function { ) -> data::function::Function {
data::function::Function { data::function::Function {
info: Arc::new(Info::neverused()), info: Arc::new(Info::neverused()),
@ -22,7 +22,7 @@ pub fn to_mers_func(
pub fn to_mers_func_with_in_type( pub fn to_mers_func_with_in_type(
in_type: Type, in_type: Type,
out: impl Fn(&Type) -> Result<Type, CheckError> + Send + Sync + 'static, out: impl Fn(&Type) -> Result<Type, CheckError> + Send + Sync + 'static,
run: impl Fn(Data) -> Data + Send + Sync + 'static, run: impl Fn(Data) -> Result<Data, CheckError> + Send + Sync + 'static,
) -> data::function::Function { ) -> data::function::Function {
to_mers_func( to_mers_func(
move |a| { move |a| {
@ -39,7 +39,7 @@ pub fn to_mers_func_with_in_type(
pub fn to_mers_func_with_in_out_types( pub fn to_mers_func_with_in_out_types(
in_type: Type, in_type: Type,
out_type: Type, out_type: Type,
run: impl Fn(Data) -> Data + Send + Sync + 'static, run: impl Fn(Data) -> Result<Data, CheckError> + Send + Sync + 'static,
) -> data::function::Function { ) -> data::function::Function {
to_mers_func( to_mers_func(
move |a| { move |a| {
@ -55,7 +55,7 @@ pub fn to_mers_func_with_in_out_types(
pub fn to_mers_func_concrete_string_to_any( pub fn to_mers_func_concrete_string_to_any(
out_type: Type, out_type: Type,
f: impl Fn(&str) -> Data + Send + Sync + 'static, f: impl Fn(&str) -> Result<Data, CheckError> + Send + Sync + 'static,
) -> data::function::Function { ) -> data::function::Function {
to_mers_func_with_in_out_types(Type::new(data::string::StringT), out_type, move |a| { to_mers_func_with_in_out_types(Type::new(data::string::StringT), out_type, move |a| {
f(a.get() f(a.get()
@ -70,13 +70,13 @@ pub fn to_mers_func_concrete_string_to_string(
f: impl Fn(&str) -> String + Send + Sync + 'static, f: impl Fn(&str) -> String + Send + Sync + 'static,
) -> data::function::Function { ) -> data::function::Function {
to_mers_func_concrete_string_to_any(Type::new(data::string::StringT), move |a| { 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( pub fn to_mers_func_concrete_string_string_to_any(
out_type: Type, out_type: Type,
f: impl Fn(&str, &str) -> Data + Send + Sync + 'static, f: impl Fn(&str, &str) -> Result<Data, CheckError> + Send + Sync + 'static,
) -> data::function::Function { ) -> data::function::Function {
to_mers_func_with_in_out_types( to_mers_func_with_in_out_types(
Type::new(data::tuple::TupleT(vec![ Type::new(data::tuple::TupleT(vec![
@ -109,13 +109,13 @@ pub fn to_mers_func_concrete_string_string_to_opt_int(
) -> data::function::Function { ) -> data::function::Function {
to_mers_func_concrete_string_string_to_any( to_mers_func_concrete_string_string_to_any(
Type::newm(vec![ Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![Type::new(data::int::IntT)])),
Arc::new(data::tuple::TupleT(vec![])), Arc::new(data::tuple::TupleT(vec![])),
Arc::new(data::int::IntT),
]), ]),
move |a, b| { move |a, b| {
f(a, b) Ok(f(a, b)
.map(|v| Data::new(data::int::Int(v))) .map(|v| Data::one_tuple(Data::new(data::int::Int(v))))
.unwrap_or_else(|| Data::empty_tuple()) .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, f: impl Fn(&str, &str) -> bool + Send + Sync + 'static,
) -> data::function::Function { ) -> data::function::Function {
to_mers_func_concrete_string_string_to_any(Type::new(data::bool::BoolT), move |a, b| { 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( 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| { move |a, b| {
f(a, b) Ok(f(a, b)
.map(|(a, b)| { .map(|(a, b)| {
Data::new(data::tuple::Tuple(vec![ Data::new(data::tuple::Tuple(vec![
Data::new(data::string::String(a)), Data::new(data::string::String(a)),
Data::new(data::string::String(b)), Data::new(data::string::String(b)),
])) ]))
}) })
.unwrap_or_else(|| Data::empty_tuple()) .unwrap_or_else(|| Data::empty_tuple()))
}, },
) )
} }

View File

@ -70,8 +70,8 @@ impl Config {
let mut arg = arg_ref.0.write().unwrap(); let mut arg = arg_ref.0.write().unwrap();
let func = a.0[1].get(); let func = a.0[1].get();
let func = func.as_any().downcast_ref::<data::function::Function>().unwrap(); let func = func.as_any().downcast_ref::<data::function::Function>().unwrap();
*arg = func.run(arg.clone()); *arg = func.run(arg.clone())?;
Data::empty_tuple() Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
})) }))
@ -95,11 +95,11 @@ impl Config {
} else { } else {
unreachable!("sleep called on non-int/non-float") unreachable!("sleep called on non-int/non-float")
}); });
Data::empty_tuple() Ok(Data::empty_tuple())
}), }),
inner_statements: None, 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: Arc::new(Info::neverused()),
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(|a, _i| if a.is_included_in_single(&data::int::IntT) { 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::<data::int::Int>().map(|i| i.0 as _).unwrap_or(1)); std::process::exit(a.get().as_any().downcast_ref::<data::int::Int>().map(|i| i.0 as _).unwrap_or(1));
}), }),
inner_statements: None, 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::<data::string::String>()
.map(|i| i.0.to_owned())
.unwrap_or_else(String::new).into()
)
}),
inner_statements: None,
})) }))
.add_var( .add_var(
"len".to_string(), "len".to_string(),
@ -126,7 +146,7 @@ impl Config {
Ok(Type::new(data::int::IntT)) Ok(Type::new(data::int::IntT))
}), }),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
Data::new(data::int::Int(if let Some(t) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() { Ok(Data::new(data::int::Int(if let Some(t) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
t.0.len() as _ t.0.len() as _
} else if let Some(s) = a.get().as_any().downcast_ref::<data::string::String>() { } else if let Some(s) = a.get().as_any().downcast_ref::<data::string::String>() {
s.0.len() as _ s.0.len() as _
@ -135,7 +155,7 @@ impl Config {
i.take(isize::MAX as usize + 1).count() as isize i.take(isize::MAX as usize + 1).count() as isize
} else { } else {
unreachable!("called len on {a:?}, which isn't a tuple or a string") unreachable!("called len on {a:?}, which isn't a tuple or a string")
})) })))
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -154,10 +174,12 @@ impl Config {
Ok(Type::new(data::bool::BoolT)) Ok(Type::new(data::bool::BoolT))
}), }),
run: Arc::new(|a, _i| { 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() { if let Some(f) = i.next() {
let f = f?;
let mut o = true; let mut o = true;
for el in i { for el in i {
let el = el?;
if el != f { if el != f {
o = false; o = false;
break; break;
@ -169,7 +191,7 @@ impl Config {
} }
} else { } else {
false false
})) })))
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -181,7 +203,7 @@ impl Config {
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(|a, _i| Ok(Type::new(data::reference::ReferenceT(a.clone())))), out: Arc::new(|a, _i| Ok(Type::new(data::reference::ReferenceT(a.clone())))),
run: Arc::new(|a, _i| { 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, inner_statements: None,
}), }),
@ -199,9 +221,9 @@ impl Config {
.as_any() .as_any()
.downcast_ref::<data::reference::Reference>() .downcast_ref::<data::reference::Reference>()
{ {
r.0.write().unwrap().clone() Ok(r.0.write().unwrap().clone())
} else { } else {
unreachable!("called deref on non-reference") Err("called deref on non-reference".into())
} }
}), }),
inner_statements: None, inner_statements: None,

View File

@ -7,6 +7,7 @@ use std::{
use crate::{ use crate::{
data::{self, Data, MersData, MersType, Type}, data::{self, Data, MersData, MersType, Type},
errors::CheckError,
program::{self, run::CheckInfo}, program::{self, run::CheckInfo},
}; };
@ -51,8 +52,9 @@ impl Config {
cmd.as_any().downcast_ref::<data::string::String>().unwrap(), cmd.as_any().downcast_ref::<data::string::String>().unwrap(),
args.get().iterable().unwrap(), args.get().iterable().unwrap(),
); );
let args = args.map(|v| v.map(|v| v.get().to_string())).collect::<Result<Vec<_>, _>>()?;
match Command::new(&cmd.0) match Command::new(&cmd.0)
.args(args.map(|v| v.get().to_string())) .args(args)
.output() .output()
{ {
Ok(output) => { Ok(output) => {
@ -65,13 +67,13 @@ impl Config {
String::from_utf8_lossy(&output.stdout).into_owned(); String::from_utf8_lossy(&output.stdout).into_owned();
let stderr = let stderr =
String::from_utf8_lossy(&output.stderr).into_owned(); String::from_utf8_lossy(&output.stderr).into_owned();
Data::new(data::tuple::Tuple(vec![ Ok(Data::new(data::tuple::Tuple(vec![
status, status,
Data::new(data::string::String(stdout)), Data::new(data::string::String(stdout)),
Data::new(data::string::String(stderr)), 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, inner_statements: None,
@ -101,8 +103,9 @@ impl Config {
cmd.as_any().downcast_ref::<data::string::String>().unwrap(), cmd.as_any().downcast_ref::<data::string::String>().unwrap(),
args.get().iterable().unwrap(), args.get().iterable().unwrap(),
); );
let args = args.map(|v| v.map(|v| v.get().to_string())).collect::<Result<Vec<_>, _>>()?;
match Command::new(&cmd.0) match Command::new(&cmd.0)
.args(args.map(|v| v.get().to_string())) .args(args)
.stdin(Stdio::piped()) .stdin(Stdio::piped())
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())
@ -112,9 +115,9 @@ impl Config {
let a = Some(child.stdin.take().unwrap()); let a = Some(child.stdin.take().unwrap());
let b = BufReader::new(child.stdout.take().unwrap()); let b = BufReader::new(child.stdout.take().unwrap());
let c = BufReader::new(child.stderr.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, inner_statements: None,
@ -139,11 +142,11 @@ impl Config {
let a = a.get(); let a = a.get();
let child = a.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = a.as_any().downcast_ref::<ChildProcess>().unwrap();
let mut child = child.0.lock().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(Some(_)) => Data::one_tuple(Data::new(data::bool::Bool(true))),
Ok(None) => Data::one_tuple(Data::new(data::bool::Bool(false))), Ok(None) => Data::one_tuple(Data::new(data::bool::Bool(false))),
Err(_) => Data::empty_tuple(), Err(_) => Data::empty_tuple(),
} })
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -169,14 +172,14 @@ impl Config {
let child = a.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = a.as_any().downcast_ref::<ChildProcess>().unwrap();
let mut child = child.0.lock().unwrap(); let mut child = child.0.lock().unwrap();
drop(child.1.take()); drop(child.1.take());
match child.0.wait() { Ok(match child.0.wait() {
Ok(s) => if let Some(s) = s.code() { Ok(s) => if let Some(s) = s.code() {
Data::new(data::int::Int(s as _)) Data::new(data::int::Int(s as _))
} else { } else {
Data::new(data::bool::Bool(s.success())) Data::new(data::bool::Bool(s.success()))
} }
Err(_) => Data::empty_tuple(), Err(_) => Data::empty_tuple(),
} })
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -200,12 +203,12 @@ impl Config {
let bytes = tuple.0[1].get(); let bytes = tuple.0[1].get();
let child = child.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = child.as_any().downcast_ref::<ChildProcess>().unwrap();
let mut child = child.0.lock().unwrap(); let mut child = child.0.lock().unwrap();
let buf = bytes.iterable().unwrap().map(|v| v.get().as_any().downcast_ref::<data::byte::Byte>().unwrap().0).collect::<Vec<_>>(); let buf = bytes.iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::byte::Byte>().unwrap().0)).collect::<Result<Vec<_>, _>>()?;
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)) Data::new(data::bool::Bool(true))
} else { } else {
Data::new(data::bool::Bool(false)) Data::new(data::bool::Bool(false))
} })
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -230,11 +233,11 @@ impl Config {
let child = child.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = child.as_any().downcast_ref::<ChildProcess>().unwrap();
let mut child = child.0.lock().unwrap(); let mut child = child.0.lock().unwrap();
let buf = string.as_any().downcast_ref::<data::string::String>().unwrap().0.as_bytes(); let buf = string.as_any().downcast_ref::<data::string::String>().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)) Data::new(data::bool::Bool(true))
} else { } else {
Data::new(data::bool::Bool(false)) Data::new(data::bool::Bool(false))
} })
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -259,11 +262,11 @@ impl Config {
let child = a.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = a.as_any().downcast_ref::<ChildProcess>().unwrap();
let mut child = child.0.lock().unwrap(); let mut child = child.0.lock().unwrap();
let mut buf = [0]; 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]))) Data::one_tuple(Data::new(data::byte::Byte(buf[0])))
} else { } else {
Data::empty_tuple() Data::empty_tuple()
} })
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -288,11 +291,11 @@ impl Config {
let child = a.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = a.as_any().downcast_ref::<ChildProcess>().unwrap();
let mut child = child.0.lock().unwrap(); let mut child = child.0.lock().unwrap();
let mut buf = [0]; 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]))) Data::one_tuple(Data::new(data::byte::Byte(buf[0])))
} else { } else {
Data::empty_tuple() Data::empty_tuple()
} })
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -317,11 +320,11 @@ impl Config {
let child = a.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = a.as_any().downcast_ref::<ChildProcess>().unwrap();
let mut child = child.0.lock().unwrap(); let mut child = child.0.lock().unwrap();
let mut buf = String::new(); 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))) Data::one_tuple(Data::new(data::string::String(buf)))
} else { } else {
Data::empty_tuple() Data::empty_tuple()
} })
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -346,11 +349,11 @@ impl Config {
let child = a.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = a.as_any().downcast_ref::<ChildProcess>().unwrap();
let mut child = child.0.lock().unwrap(); let mut child = child.0.lock().unwrap();
let mut buf = String::new(); 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))) Data::one_tuple(Data::new(data::string::String(buf)))
} else { } else {
Data::empty_tuple() Data::empty_tuple()
} })
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -372,10 +375,10 @@ pub struct ChildProcess(
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct ChildProcessT; pub struct ChildProcessT;
impl MersData for ChildProcess { impl MersData for ChildProcess {
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Data>>> { fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
None None
} }
fn get(&self, _i: usize) -> Option<Data> { fn get(&self, _i: usize) -> Option<Result<Data, CheckError>> {
None None
} }
fn is_eq(&self, other: &dyn MersData) -> bool { fn is_eq(&self, other: &dyn MersData) -> bool {

View File

@ -49,21 +49,24 @@ impl Config {
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
if let (Some(v), Some(i)) = (a.get(0), a.get(1)) { if let (Some(v), Some(i)) = (a.get(0), a.get(1)) {
if let Some(i) = i.get().as_any().downcast_ref::<data::int::Int>() { let (v, i2) = (v?, i?);
if let Ok(i) = i.0.try_into() { let o = if let Some(i3) = i2.get().as_any().downcast_ref::<data::int::Int>()
{
if let Ok(i) = i3.0.try_into() {
if let Some(v) = v.get().get(i) { if let Some(v) = v.get().get(i) {
Data::one_tuple(v) Ok(Data::one_tuple(v?))
} else { } else {
Data::empty_tuple() Ok(Data::empty_tuple())
} }
} else { } else {
Data::empty_tuple() Ok(Data::empty_tuple())
} }
} else { } else {
unreachable!("get called with non-int index") Err("get called with non-int index".into())
} };
o
} else { } else {
unreachable!("get called with less than 2 args") Err("get called with less than 2 args".into())
} }
}), }),
inner_statements: None, inner_statements: None,

View File

@ -29,10 +29,20 @@ impl Config {
pub fn with_iters(self) -> Self { pub fn with_iters(self) -> 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| { .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::<data::bool::Bool>().is_some_and(|v| v.0)))) for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().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| { .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::<data::bool::Bool>().is_some_and(|v| v.0)))) for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().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( .add_var(
"for_each".to_string(), "for_each".to_string(),
@ -83,9 +93,9 @@ impl Config {
f.get().as_any().downcast_ref::<data::function::Function>(), f.get().as_any().downcast_ref::<data::function::Function>(),
) { ) {
for v in iter { for v in iter {
f.run(v); f.run(v?)?;
} }
Data::empty_tuple() Ok(Data::empty_tuple())
} else { } else {
unreachable!( unreachable!(
"for_each called on tuple not containing iterable and function" "for_each called on tuple not containing iterable and function"
@ -133,7 +143,7 @@ impl Config {
}; };
Ok(Type::new(IterT::new(ItersT::Enumerate, data)?)) 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, inner_statements: None,
}), }),
) )
@ -150,7 +160,7 @@ impl Config {
}; };
Ok(Type::new(IterT::new(ItersT::Chained, data)?)) 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, inner_statements: None,
}), }),
) )
@ -211,7 +221,7 @@ fn genfunc_iter_and_arg<T: MersType, D: MersData>(
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() { if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) { if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) {
if let Some(f) = f.get().as_any().downcast_ref::<D>() { if let Some(f) = f.get().as_any().downcast_ref::<D>() {
Data::new(Iter(fd(f), v.clone())) Ok(Data::new(Iter(fd(f), v.clone())))
} else { } else {
unreachable!("{name} called on tuple not containing function") unreachable!("{name} called on tuple not containing function")
} }
@ -254,55 +264,76 @@ impl MersData for Iter {
fn is_eq(&self, _other: &dyn MersData) -> bool { fn is_eq(&self, _other: &dyn MersData) -> bool {
false false
} }
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Data>>> { fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
Some(match &self.0 { Some(match &self.0 {
Iters::Map(f) => { Iters::Map(f) => {
let f = Clone::clone(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) => { Iters::Filter(f) => {
let f = Clone::clone(f); let f = Clone::clone(f);
Box::new(self.1.get().iterable()?.filter(move |v| { Box::new(self.1.get().iterable()?.filter_map(move |v| {
f.run(v.clone()) match v {
.get() Ok(v) => match f.run(v.clone()) {
Ok(f) => {
if f.get()
.as_any() .as_any()
.downcast_ref::<data::bool::Bool>() .downcast_ref::<data::bool::Bool>()
.is_some_and(|b| b.0) .is_some_and(|b| b.0)
{
Some(Ok(v))
} else {
None
}
}
Err(e) => Some(Err(e)),
},
Err(e) => Some(Err(e)),
}
})) }))
} }
Iters::FilterMap(f) => { Iters::FilterMap(f) => {
let f = Clone::clone(f); let f = Clone::clone(f);
Box::new( Box::new(self.1.get().iterable()?.filter_map(move |v| match v {
self.1 Ok(v) => match f.run(v) {
.get() Ok(r) => Some(Ok(r.one_tuple_content()?)),
.iterable()? Err(e) => Some(Err(e)),
.filter_map(move |v| f.run(v).one_tuple_content()), },
) Err(e) => Some(Err(e)),
}))
} }
Iters::MapWhile(f) => { Iters::MapWhile(f) => {
let f = Clone::clone(f); let f = Clone::clone(f);
Box::new( Box::new(self.1.get().iterable()?.map_while(move |v| match v {
self.1 Ok(v) => match f.run(v) {
.get() Ok(r) => Some(Ok(r.one_tuple_content()?)),
.iterable()? Err(e) => Some(Err(e)),
.map_while(move |v| f.run(v).one_tuple_content()), },
) Err(e) => Some(Err(e)),
}))
} }
Iters::Take(limit) => Box::new(self.1.get().iterable()?.take(*limit)), Iters::Take(limit) => Box::new(self.1.get().iterable()?.take(*limit)),
Iters::Enumerate => Box::new(self.1.get().iterable()?.enumerate().map(|(i, v)| { Iters::Enumerate => {
Data::new(data::tuple::Tuple(vec![ 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 _)), Data::new(data::int::Int(i as _)),
v, v,
])) ]))),
})), Err(e) => Err(e),
}))
}
Iters::Chained => { Iters::Chained => {
let iters = self match self
.1 .1
.get() .get()
.iterable()? .iterable()?
.map(|v| v.get().iterable()) .map(|v| Ok(v?.get().iterable()))
.collect::<Option<Vec<_>>>()?; .collect::<Result<Option<Vec<_>>, CheckError>>()
Box::new(iters.into_iter().flatten()) {
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, name: String,
iter_type: impl MersType + 'static, iter_type: impl MersType + 'static,
out_type: Type, out_type: Type,
run: impl Fn(Data, &mut crate::info::Info<program::run::Local>) -> Data + Send + Sync + 'static, run: impl Fn(Data, &mut crate::info::Info<program::run::Local>) -> Result<Data, CheckError>
+ Send
+ Sync
+ 'static,
) -> Function { ) -> Function {
Function { Function {
info: Arc::new(crate::info::Info::neverused()), info: Arc::new(crate::info::Info::neverused()),

View File

@ -5,6 +5,7 @@ use std::{
use crate::{ use crate::{
data::{self, Data, MersData, MersType, Type}, data::{self, Data, MersData, MersType, Type},
errors::CheckError,
parsing::{statements::to_string_literal, Source}, parsing::{statements::to_string_literal, Source},
program::{self, run::CheckInfo}, program::{self, run::CheckInfo},
}; };
@ -93,7 +94,7 @@ impl Config {
} }
None => Data::empty_tuple(), None => Data::empty_tuple(),
}; };
o Ok(o)
}), }),
inner_statements: None, inner_statements: None,
})) }))
@ -123,7 +124,7 @@ impl Config {
} }
}), }),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
match a Ok(match a
.get() .get()
.as_any() .as_any()
.downcast_ref::<data::reference::Reference>() .downcast_ref::<data::reference::Reference>()
@ -140,7 +141,7 @@ impl Config {
{ {
Some(data) => Data::one_tuple(data.read().unwrap().clone()), Some(data) => Data::one_tuple(data.read().unwrap().clone()),
None => Data::empty_tuple(), None => Data::empty_tuple(),
} })
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -203,7 +204,7 @@ impl Config {
.unwrap() .unwrap()
.0 .0
.push(Arc::new(RwLock::new(tuple.0[1].clone()))); .push(Arc::new(RwLock::new(tuple.0[1].clone())));
Data::empty_tuple() Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -224,9 +225,9 @@ impl Config {
}), }),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
if let Some(i) = a.get().iterable() { 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::<Result<_, _>>()?)))
} else { } else {
unreachable!("as_list called on non-iterable") Err("as_list called on non-iterable".into())
} }
}), }),
inner_statements: None, inner_statements: None,
@ -262,12 +263,12 @@ impl MersData for List {
false false
} }
} }
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Data>>> { fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
Some(Box::new( Some(Box::new(
self.0 self.0
.clone() .clone()
.into_iter() .into_iter()
.map(|v| v.read().unwrap().clone()), .map(|v| Ok(v.read().unwrap().clone())),
)) ))
} }
fn clone(&self) -> Box<dyn MersData> { fn clone(&self) -> Box<dyn MersData> {

View File

@ -72,11 +72,11 @@ impl Config {
} }
}), }),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
if let Ok(n) = a.get().as_any().downcast_ref::<data::string::String>().unwrap().0.parse() { Ok(if let Ok(n) = a.get().as_any().downcast_ref::<data::string::String>().unwrap().0.parse() {
Data::one_tuple(Data::new(data::float::Float(n))) Data::one_tuple(Data::new(data::float::Float(n)))
} else { } else {
Data::empty_tuple() Data::empty_tuple()
} })
}), }),
inner_statements: None, inner_statements: None,
})).add_var("parse_int".to_string(), Data::new(data::function::Function { })).add_var("parse_int".to_string(), Data::new(data::function::Function {
@ -95,11 +95,11 @@ impl Config {
} }
}), }),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
if let Ok(n) = a.get().as_any().downcast_ref::<data::string::String>().unwrap().0.parse() { Ok(if let Ok(n) = a.get().as_any().downcast_ref::<data::string::String>().unwrap().0.parse() {
Data::one_tuple(Data::new(data::int::Int(n))) Data::one_tuple(Data::new(data::int::Int(n)))
} else { } else {
Data::empty_tuple() Data::empty_tuple()
} })
}), }),
inner_statements: None, inner_statements: None,
})).add_var("signum".to_string(), Data::new(data::function::Function { })).add_var("signum".to_string(), Data::new(data::function::Function {
@ -113,7 +113,7 @@ impl Config {
} }
}), }),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
Data::new(data::int::Int(if let Some(n) = a.get().as_any().downcast_ref::<data::int::Int>() { Ok(Data::new(data::int::Int(if let Some(n) = a.get().as_any().downcast_ref::<data::int::Int>() {
n.0.signum() n.0.signum()
} else } else
if let Some(n) = a.get().as_any().downcast_ref::<data::float::Float>() { if let Some(n) = a.get().as_any().downcast_ref::<data::float::Float>() {
@ -123,7 +123,7 @@ impl Config {
-1 -1
} else { 0 } else { 0
} }
} else { unreachable!("called signum on non-number type")})) } else { unreachable!("called signum on non-number type")})))
}), }),
inner_statements: None, inner_statements: None,
})) .add_var("div".to_string(), Data::new(data::function::Function { })) .add_var("div".to_string(), Data::new(data::function::Function {
@ -137,10 +137,10 @@ impl Config {
match (left.downcast_ref::<data::int::Int>(), left.downcast_ref::<data::float::Float>(), match (left.downcast_ref::<data::int::Int>(), left.downcast_ref::<data::float::Float>(),
right.downcast_ref::<data::int::Int>(), right.downcast_ref::<data::float::Float>() right.downcast_ref::<data::int::Int>(), right.downcast_ref::<data::float::Float>()
) { ) {
(Some(data::int::Int(l)), None, Some(data::int::Int(r)), None) => Data::new(data::int::Int(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))) => Data::new(data::float::Float(*l as f64 / 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) => Data::new(data::float::Float(l / *r as f64)), (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))) => Data::new(data::float::Float(l / r)), (None, Some(data::float::Float(l)), None, Some(data::float::Float(r))) => Ok(Data::new(data::float::Float(l / r))),
_ => unreachable!(), _ => unreachable!(),
} }
} else { unreachable!() }), } else { unreachable!() }),
@ -156,10 +156,10 @@ impl Config {
match (left.downcast_ref::<data::int::Int>(), left.downcast_ref::<data::float::Float>(), match (left.downcast_ref::<data::int::Int>(), left.downcast_ref::<data::float::Float>(),
right.downcast_ref::<data::int::Int>(), right.downcast_ref::<data::float::Float>() right.downcast_ref::<data::int::Int>(), right.downcast_ref::<data::float::Float>()
) { ) {
(Some(data::int::Int(l)), None, Some(data::int::Int(r)), None) => Data::new(data::int::Int(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))) => Data::new(data::float::Float(*l as f64 % 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) => Data::new(data::float::Float(l % *r as f64)), (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))) => Data::new(data::float::Float(l % r)), (None, Some(data::float::Float(l)), None, Some(data::float::Float(r))) => Ok(Data::new(data::float::Float(l % r))),
_ => unreachable!(), _ => unreachable!(),
} }
} else { unreachable!() }), } else { unreachable!() }),
@ -206,20 +206,22 @@ impl Config {
let mut sumf = 0.0; let mut sumf = 0.0;
let mut usef = false; let mut usef = false;
for val in i { for val in i {
if let Some(i) = val.get().as_any().downcast_ref::<data::int::Int>() { let val = val?;
let o = if let Some(i) = val.get().as_any().downcast_ref::<data::int::Int>() {
sumi += i.0; sumi += i.0;
} else if let Some(i) = } else if let Some(i) =
val.get().as_any().downcast_ref::<data::float::Float>() val.get().as_any().downcast_ref::<data::float::Float>()
{ {
sumf += i.0; sumf += i.0;
usef = true; usef = true;
};
o
} }
} Ok(if usef {
if usef {
Data::new(data::float::Float(sumi as f64 + sumf)) Data::new(data::float::Float(sumi as f64 + sumf))
} else { } else {
Data::new(data::int::Int(sumi)) Data::new(data::int::Int(sumi))
} })
} else { } else {
unreachable!("sum called on non-tuple") unreachable!("sum called on non-tuple")
} }
@ -269,6 +271,7 @@ impl Config {
let mut sumf = 0.0; let mut sumf = 0.0;
let mut usef = false; let mut usef = false;
for val in i { for val in i {
let val = val?;
if let Some(i) = val.get().as_any().downcast_ref::<data::int::Int>() { if let Some(i) = val.get().as_any().downcast_ref::<data::int::Int>() {
if first { if first {
sumi = i.0; sumi = i.0;
@ -289,11 +292,11 @@ impl Config {
first = false; first = false;
} }
} }
if usef { Ok(if usef {
Data::new(data::float::Float(sumi as f64 + sumf)) Data::new(data::float::Float(sumi as f64 + sumf))
} else { } else {
Data::new(data::int::Int(sumi)) Data::new(data::int::Int(sumi))
} })
} else { } else {
unreachable!("sum called on non-tuple") unreachable!("sum called on non-tuple")
} }
@ -342,20 +345,22 @@ impl Config {
let mut prodf = 1.0; let mut prodf = 1.0;
let mut usef = false; let mut usef = false;
for val in i { for val in i {
if let Some(i) = val.get().as_any().downcast_ref::<data::int::Int>() { let val = val?;
let o = if let Some(i) = val.get().as_any().downcast_ref::<data::int::Int>() {
prodi *= i.0; prodi *= i.0;
} else if let Some(i) = } else if let Some(i) =
val.get().as_any().downcast_ref::<data::float::Float>() val.get().as_any().downcast_ref::<data::float::Float>()
{ {
prodf *= i.0; prodf *= i.0;
usef = true; usef = true;
};
o
} }
} Ok(if usef {
if usef {
Data::new(data::float::Float(prodi as f64 * prodf)) Data::new(data::float::Float(prodi as f64 * prodf))
} else { } else {
Data::new(data::int::Int(prodi)) Data::new(data::int::Int(prodi))
} })
} else { } else {
unreachable!("product called on non-tuple") unreachable!("product called on non-tuple")
} }
@ -424,6 +429,7 @@ fn ltgtoe_function(
run: Arc::new(move |a, _i| { run: Arc::new(move |a, _i| {
let mut prev = IntOrFloatOrNothing::Nothing; let mut prev = IntOrFloatOrNothing::Nothing;
for item in a.get().iterable().unwrap() { for item in a.get().iterable().unwrap() {
let item = item?;
let item = item.get(); let item = item.get();
let new = if let Some(data::int::Int(v)) = item.as_any().downcast_ref() { let new = if let Some(data::int::Int(v)) = item.as_any().downcast_ref() {
IntOrFloatOrNothing::Int(*v) IntOrFloatOrNothing::Int(*v)
@ -435,10 +441,10 @@ fn ltgtoe_function(
if op(prev, new) { if op(prev, new) {
prev = new; prev = new;
} else { } 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, inner_statements: None,
} }

View File

@ -53,9 +53,9 @@ impl Config {
.downcast_ref::<data::function::Function>() .downcast_ref::<data::function::Function>()
.cloned() .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()), move || f.run(Data::empty_tuple()),
)))))) )))))))
} else { } else {
unreachable!("thread called, but arg wasn't a function"); unreachable!("thread called, but arg wasn't a function");
} }
@ -77,10 +77,10 @@ impl Config {
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let t = a.as_any().downcast_ref::<Thread>().unwrap().0.lock().unwrap(); let t = a.as_any().downcast_ref::<Thread>().unwrap().0.lock().unwrap();
Data::new(data::bool::Bool(match &*t { Ok(Data::new(data::bool::Bool(match &*t {
Ok(t) => t.is_finished(), Ok(t) => t.is_finished(),
Err(_d) => true, Err(_d) => true,
})) })))
}), }),
inner_statements: None, inner_statements: None,
})) }))
@ -101,7 +101,7 @@ impl Config {
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let mut t = a.as_any().downcast_ref::<Thread>().unwrap().0.lock().unwrap(); let mut t = a.as_any().downcast_ref::<Thread>().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(), Ok(t) => t.join().unwrap(),
Err(d) => d, Err(d) => d,
}; };
@ -114,7 +114,9 @@ impl Config {
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Thread(pub Arc<Mutex<Result<JoinHandle<Data>, Data>>>); pub struct Thread(
pub Arc<Mutex<Result<JoinHandle<Result<Data, CheckError>>, Result<Data, CheckError>>>>,
);
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ThreadT(pub Type); pub struct ThreadT(pub Type);

View File

@ -41,11 +41,11 @@ impl Config {
} }
}), }),
run: Arc::new(|_a, _i| { 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))) Data::one_tuple(Data::new(data::string::String(line)))
} else { } else {
Data::empty_tuple() Data::empty_tuple()
} })
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -60,7 +60,7 @@ impl Config {
let a2 = a.get(); let a2 = a.get();
eprintln!("{} :: {}", a2.as_type(), a2); eprintln!("{} :: {}", a2.as_type(), a2);
drop(a2); drop(a2);
a Ok(a)
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -74,7 +74,7 @@ impl Config {
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
eprint!("{}", a.get()); eprint!("{}", a.get());
_ = std::io::stderr().lock().flush(); _ = std::io::stderr().lock().flush();
Data::empty_tuple() Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -87,7 +87,7 @@ impl Config {
out: Arc::new(|_a, _i| Ok(Type::empty_tuple())), out: Arc::new(|_a, _i| Ok(Type::empty_tuple())),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
eprintln!("{}", a.get()); eprintln!("{}", a.get());
Data::empty_tuple() Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -101,7 +101,7 @@ impl Config {
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
print!("{}", a.get()); print!("{}", a.get());
_ = std::io::stdout().lock().flush(); _ = std::io::stdout().lock().flush();
Data::empty_tuple() Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
}), }),
@ -114,7 +114,7 @@ impl Config {
out: Arc::new(|_a, _i| Ok(Type::empty_tuple())), out: Arc::new(|_a, _i| Ok(Type::empty_tuple())),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
println!("{}", a.get()); println!("{}", a.get());
Data::empty_tuple() Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
}), }),

View File

@ -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("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".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_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( .add_var("concat".to_string(), Data::new(util::to_mers_func(
|a| if a.iterable().is_some() { |a| if a.iterable().is_some() {
Ok(Type::new(data::string::StringT)) Ok(Type::new(data::string::StringT))
} else { } else {
Err(format!("concat called on non-iterable type {a}").into()) 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::<Result<_, _>>()?)))),
)) ))
.add_var("to_string".to_string(), Data::new(util::to_mers_func(|_a| Ok(Type::new(data::string::StringT)), .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( .add_var("substring".to_string(), Data::new(util::to_mers_func(
|a| { |a| {
@ -79,9 +79,9 @@ impl Config {
.unwrap_or(usize::MAX); .unwrap_or(usize::MAX);
let end = end.min(s.len()); let end = end.min(s.len());
if end < start { 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())))
}) })
)) ))
} }

View File

@ -43,7 +43,7 @@ impl MersStatement for Function {
Ok(run2.check(i, None)?) Ok(run2.check(i, None)?)
}), }),
run: Arc::new(move |arg, info| { 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) run.run(info)
}), }),
inner_statements: Some((arg3, run3)), inner_statements: Some((arg3, run3)),

View File

@ -66,7 +66,7 @@ impl MersStatement for AsType {
return_type return_type
}) })
} }
fn run_custom(&self, info: &mut super::Info) -> Data { fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
self.statement.run(info) self.statement.run(info)
} }
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {

View File

@ -77,11 +77,11 @@ impl MersStatement for AssignTo {
} }
Ok(Type::empty_tuple()) Ok(Type::empty_tuple())
} }
fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
let source = self.source.run(info); let source = self.source.run(info)?;
let target = self.target.run(info); let target = self.target.run(info)?;
data::defs::assign(&source, &target); data::defs::assign(&source, &target);
Data::empty_tuple() Ok(Data::empty_tuple())
} }
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {
false false

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
data::Type, data::{self, Data, Type},
errors::{CheckError, SourceRange}, errors::{CheckError, SourceRange},
}; };
@ -25,12 +25,12 @@ impl MersStatement for Block {
} }
Ok(o) Ok(o)
} }
fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
self.statements self.statements
.iter() .iter()
.map(|s| s.run(info)) .map(|s| s.run(info))
.last() .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 { fn has_scope(&self) -> bool {
true true

View File

@ -88,12 +88,42 @@ impl MersStatement for Chain {
} }
Ok(o) Ok(o)
} }
fn run_custom(&self, info: &mut super::Info) -> Data { fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
let f = self.first.run(info); let f = self.first.run(info)?;
let c = self.chained.run(info); let c = self.chained.run(info)?;
let c = c.get(); let c = c.get();
if let Some(func) = c.as_any().downcast_ref::<crate::data::function::Function>() { if let Some(func) = c.as_any().downcast_ref::<crate::data::function::Function>() {
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 { } else {
todo!("err: not a function"); todo!("err: not a function");
} }

View File

@ -56,8 +56,8 @@ impl MersStatement for CustomType {
} }
Ok(Type::empty_tuple()) Ok(Type::empty_tuple())
} }
fn run_custom(&self, _info: &mut Info) -> Data { fn run_custom(&self, _info: &mut Info) -> Result<Data, CheckError> {
Data::empty_tuple() Ok(Data::empty_tuple())
} }
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {
false false

View File

@ -25,8 +25,10 @@ impl MersStatement for Function {
self.func_no_info.with_info_check(info.clone()); self.func_no_info.with_info_check(info.clone());
Ok(self.func_no_info.as_type()) Ok(self.func_no_info.as_type())
} }
fn run_custom(&self, info: &mut super::Info) -> Data { fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
Data::new(self.func_no_info.with_info_run(Arc::new(info.clone()))) Ok(Data::new(
self.func_no_info.with_info_run(Arc::new(info.clone())),
))
} }
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {
true true

View File

@ -52,20 +52,22 @@ impl MersStatement for If {
} }
Ok(t) Ok(t)
} }
fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
Ok(
if let Some(data::bool::Bool(true)) = self if let Some(data::bool::Bool(true)) = self
.condition .condition
.run(info) .run(info)?
.get() .get()
.as_any() .as_any()
.downcast_ref::<data::bool::Bool>() .downcast_ref::<data::bool::Bool>()
{ {
self.on_true.run(info) self.on_true.run(info)?
} else if let Some(on_false) = &self.on_false { } else if let Some(on_false) = &self.on_false {
on_false.run(info) on_false.run(info)?
} else { } else {
Data::empty_tuple() Data::empty_tuple()
} },
)
} }
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {
true true

View File

@ -47,10 +47,10 @@ impl MersStatement for Loop {
} }
Ok(t) Ok(t)
} }
fn run_custom(&self, info: &mut Info) -> Data { fn run_custom(&self, info: &mut Info) -> Result<Data, CheckError> {
loop { loop {
if let Some(v) = self.inner.run(info).one_tuple_content() { if let Some(v) = self.inner.run(info)?.one_tuple_content() {
return v; return Ok(v);
} }
} }
} }

View File

@ -43,7 +43,7 @@ pub trait MersStatement: Debug + Send + Sync {
info: &mut CheckInfo, info: &mut CheckInfo,
init_to: Option<&Type>, init_to: Option<&Type>,
) -> Result<Type, CheckError>; ) -> Result<Type, CheckError>;
fn run_custom(&self, info: &mut Info) -> Data; fn run_custom(&self, info: &mut Info) -> Result<Data, CheckError>;
/// if true, local variables etc. will be contained inside their own scope. /// if true, local variables etc. will be contained inside their own scope.
fn has_scope(&self) -> bool; fn has_scope(&self) -> bool;
fn check(&self, info: &mut CheckInfo, init_to: Option<&Type>) -> Result<Type, CheckError> { fn check(&self, info: &mut CheckInfo, init_to: Option<&Type>) -> Result<Type, CheckError> {
@ -93,7 +93,7 @@ pub trait MersStatement: Debug + Send + Sync {
info.global.depth -= 1; info.global.depth -= 1;
o o
} }
fn run(&self, info: &mut Info) -> Data { fn run(&self, info: &mut Info) -> Result<Data, CheckError> {
if self.has_scope() { if self.has_scope() {
info.create_scope(); info.create_scope();
} }

View File

@ -119,13 +119,13 @@ impl MersStatement for Object {
.collect::<Result<_, _>>()?, .collect::<Result<_, _>>()?,
))) )))
} }
fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
Data::new(data::object::Object( Ok(Data::new(data::object::Object(
self.elems self.elems
.iter() .iter()
.map(|(n, s)| (n.clone(), s.run(info))) .map(|(n, s)| Ok::<_, CheckError>((n.clone(), s.run(info)?)))
.collect(), .collect::<Result<_, _>>()?,
)) )))
} }
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {
false false

View File

@ -103,8 +103,8 @@ impl MersStatement for Try {
} }
Ok(t) Ok(t)
} }
fn run_custom(&self, info: &mut Info) -> Data { fn run_custom(&self, info: &mut Info) -> Result<Data, CheckError> {
let arg = self.arg.run(info); let arg = self.arg.run(info)?;
let ar = arg.get(); let ar = arg.get();
let a = ar.as_ref(); let a = ar.as_ref();
let arg_type = a.as_type(); let arg_type = a.as_type();
@ -112,14 +112,16 @@ impl MersStatement for Try {
.funcs .funcs
.iter() .iter()
.map(|v| { .map(|v| {
v.run(info) Ok::<_, CheckError>(
v.run(info)?
.get() .get()
.as_any() .as_any()
.downcast_ref::<data::function::Function>() .downcast_ref::<data::function::Function>()
.unwrap() .unwrap()
.clone() .clone(),
)
}) })
.collect::<Vec<_>>(); .collect::<Result<Vec<_>, _>>()?;
let mut found = None; let mut found = None;
for (i, func) in functions.iter().enumerate() { for (i, func) in functions.iter().enumerate() {
match func.get_as_type().o(&arg_type) { match func.get_as_type().o(&arg_type) {

View File

@ -4,7 +4,7 @@ use colored::Colorize;
use crate::{ use crate::{
data::{self, tuple::TupleT, Data, Type}, data::{self, tuple::TupleT, Data, Type},
errors::{error_colors, SourceRange}, errors::{error_colors, CheckError, SourceRange},
}; };
use super::MersStatement; use super::MersStatement;
@ -82,10 +82,13 @@ impl MersStatement for Tuple {
.collect::<Result<_, _>>()?, .collect::<Result<_, _>>()?,
))) )))
} }
fn run_custom(&self, info: &mut super::Info) -> crate::data::Data { fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
Data::new(data::tuple::Tuple( Ok(Data::new(data::tuple::Tuple(
self.elems.iter().map(|s| s.run(info)).collect(), self.elems
)) .iter()
.map(|s| Ok(s.run(info)?))
.collect::<Result<_, CheckError>>()?,
)))
} }
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {
false false

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
data::{Data, Type}, data::{Data, Type},
errors::SourceRange, errors::{CheckError, SourceRange},
}; };
use super::{CheckInfo, MersStatement}; use super::{CheckInfo, MersStatement};
@ -25,8 +25,8 @@ impl MersStatement for Value {
} }
Ok(self.val.get().as_type()) Ok(self.val.get().as_type())
} }
fn run_custom(&self, _info: &mut super::Info) -> Data { fn run_custom(&self, _info: &mut super::Info) -> Result<Data, CheckError> {
self.val.clone() Ok(self.val.clone())
} }
fn source_range(&self) -> SourceRange { fn source_range(&self) -> SourceRange {
self.pos_in_src.clone() self.pos_in_src.clone()

View File

@ -2,7 +2,7 @@ use std::sync::{Arc, RwLock};
use crate::{ use crate::{
data::{self, Data, Type}, data::{self, Data, Type},
errors::SourceRange, errors::{CheckError, SourceRange},
}; };
use super::MersStatement; use super::MersStatement;
@ -50,7 +50,7 @@ impl MersStatement for Variable {
}; };
Ok(val) Ok(val)
} }
fn run_custom(&self, info: &mut super::Info) -> Data { fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
if self.is_init { if self.is_init {
if self.is_ref_not_ignore { if self.is_ref_not_ignore {
let nothing = Arc::new(RwLock::new(Data::new(data::bool::Bool(false)))); 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; info.scopes[self.var.0].vars[self.var.1] = nothing;
} else { } else {
// (reference to) data which will never be referenced again // (reference to) data which will never be referenced again
return Data::new(data::reference::Reference(Arc::new(RwLock::new( return Ok(Data::new(data::reference::Reference(Arc::new(
Data::empty_tuple(), 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]; let v = &info.scopes[self.var.0].vars[self.var.1];
Data::new(data::reference::Reference(Arc::clone(v))) Data::new(data::reference::Reference(Arc::clone(v)))
} else { } else {
@ -73,7 +73,7 @@ impl MersStatement for Variable {
.write() .write()
.unwrap() .unwrap()
.clone() .clone()
} })
} }
fn source_range(&self) -> SourceRange { fn source_range(&self) -> SourceRange {
self.pos_in_src.clone() self.pos_in_src.clone()