mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
improve panic function, add stacktrace
This commit is contained in:
parent
4770e3f939
commit
cd21c2171e
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ fn run(src: String) -> Result<(), CheckError> {
|
||||
.downcast_ref::<data::string::String>()
|
||||
.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(())
|
||||
}
|
||||
|
@ -16,7 +16,8 @@ pub struct Function {
|
||||
pub info: Arc<Info>,
|
||||
pub info_check: Arc<Mutex<CheckInfo>>,
|
||||
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<(
|
||||
Arc<Box<dyn crate::program::run::MersStatement>>,
|
||||
Arc<Box<dyn crate::program::run::MersStatement>>,
|
||||
@ -25,7 +26,7 @@ pub struct Function {
|
||||
impl Function {
|
||||
pub fn new(
|
||||
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 {
|
||||
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<Data, CheckError> {
|
||||
(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<Box<dyn Iterator<Item = Data>>> {
|
||||
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
|
||||
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 {
|
||||
|
@ -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<Box<dyn Iterator<Item = Data>>> {
|
||||
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
|
||||
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<Data> {
|
||||
fn get(&self, i: usize) -> Option<Result<Data, CheckError>> {
|
||||
self.iterable()?.nth(i)
|
||||
}
|
||||
/// If self and other are different types (`other.as_any().downcast_ref::<Self>().is_none()`),
|
||||
|
@ -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<Box<dyn Iterator<Item = Data>>> {
|
||||
Some(Box::new(self.0.clone().into_iter()))
|
||||
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
|
||||
Some(Box::new(self.0.clone().into_iter().map(Ok)))
|
||||
}
|
||||
fn clone(&self) -> Box<dyn MersData> {
|
||||
Box::new(Clone::clone(self))
|
||||
|
@ -395,6 +395,11 @@ impl From<String> 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}")
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
|
||||
pub fn to_mers_func(
|
||||
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 {
|
||||
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<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 {
|
||||
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<Data, CheckError> + 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<Data, CheckError> + 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<Data, CheckError> + 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()))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -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::<data::function::Function>().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::<data::int::Int>().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::<data::string::String>()
|
||||
.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::<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 _
|
||||
} else if let Some(s) = a.get().as_any().downcast_ref::<data::string::String>() {
|
||||
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::<data::reference::Reference>()
|
||||
{
|
||||
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,
|
||||
|
@ -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::<data::string::String>().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)
|
||||
.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::<data::string::String>().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)
|
||||
.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::<ChildProcess>().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::<ChildProcess>().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::<ChildProcess>().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<_>>();
|
||||
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::<data::byte::Byte>().unwrap().0)).collect::<Result<Vec<_>, _>>()?;
|
||||
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::<ChildProcess>().unwrap();
|
||||
let mut child = child.0.lock().unwrap();
|
||||
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))
|
||||
} else {
|
||||
Data::new(data::bool::Bool(false))
|
||||
}
|
||||
})
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
@ -259,11 +262,11 @@ impl Config {
|
||||
let child = a.as_any().downcast_ref::<ChildProcess>().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::<ChildProcess>().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::<ChildProcess>().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::<ChildProcess>().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<Box<dyn Iterator<Item = Data>>> {
|
||||
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
|
||||
None
|
||||
}
|
||||
fn get(&self, _i: usize) -> Option<Data> {
|
||||
fn get(&self, _i: usize) -> Option<Result<Data, CheckError>> {
|
||||
None
|
||||
}
|
||||
fn is_eq(&self, other: &dyn MersData) -> bool {
|
||||
|
@ -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::<data::int::Int>() {
|
||||
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::<data::int::Int>()
|
||||
{
|
||||
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,
|
||||
|
@ -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::<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| {
|
||||
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(
|
||||
"for_each".to_string(),
|
||||
@ -83,9 +93,9 @@ impl Config {
|
||||
f.get().as_any().downcast_ref::<data::function::Function>(),
|
||||
) {
|
||||
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<T: MersType, D: MersData>(
|
||||
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(f) = f.get().as_any().downcast_ref::<D>() {
|
||||
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<Box<dyn Iterator<Item = Data>>> {
|
||||
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
|
||||
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::<data::bool::Bool>()
|
||||
.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::<data::bool::Bool>()
|
||||
.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::<Option<Vec<_>>>()?;
|
||||
Box::new(iters.into_iter().flatten())
|
||||
.map(|v| Ok(v?.get().iterable()))
|
||||
.collect::<Result<Option<Vec<_>>, 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<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 {
|
||||
info: Arc::new(crate::info::Info::neverused()),
|
||||
|
@ -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::<data::reference::Reference>()
|
||||
@ -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::<Result<_, _>>()?)))
|
||||
} 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<Box<dyn Iterator<Item = Data>>> {
|
||||
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
|
||||
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<dyn MersData> {
|
||||
|
@ -72,11 +72,11 @@ impl Config {
|
||||
}
|
||||
}),
|
||||
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)))
|
||||
} 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::<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)))
|
||||
} 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::<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()
|
||||
} else
|
||||
if let Some(n) = a.get().as_any().downcast_ref::<data::float::Float>() {
|
||||
@ -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::<data::int::Int>(), left.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, 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::<data::int::Int>(), left.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, 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::<data::int::Int>() {
|
||||
let val = val?;
|
||||
let o = if let Some(i) = val.get().as_any().downcast_ref::<data::int::Int>() {
|
||||
sumi += i.0;
|
||||
} else if let Some(i) =
|
||||
val.get().as_any().downcast_ref::<data::float::Float>()
|
||||
{
|
||||
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::<data::int::Int>() {
|
||||
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::<data::int::Int>() {
|
||||
let val = val?;
|
||||
let o = if let Some(i) = val.get().as_any().downcast_ref::<data::int::Int>() {
|
||||
prodi *= i.0;
|
||||
} else if let Some(i) =
|
||||
val.get().as_any().downcast_ref::<data::float::Float>()
|
||||
{
|
||||
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,
|
||||
}
|
||||
|
@ -53,9 +53,9 @@ impl Config {
|
||||
.downcast_ref::<data::function::Function>()
|
||||
.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::<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(),
|
||||
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::<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(),
|
||||
Err(d) => d,
|
||||
};
|
||||
@ -114,7 +114,9 @@ impl Config {
|
||||
}
|
||||
|
||||
#[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)]
|
||||
pub struct ThreadT(pub Type);
|
||||
|
||||
|
@ -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,
|
||||
}),
|
||||
|
@ -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::<Result<_, _>>()?)))),
|
||||
))
|
||||
.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())))
|
||||
})
|
||||
))
|
||||
}
|
||||
|
@ -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)),
|
||||
|
@ -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<Data, CheckError> {
|
||||
self.statement.run(info)
|
||||
}
|
||||
fn has_scope(&self) -> bool {
|
||||
|
@ -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<Data, CheckError> {
|
||||
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
|
||||
|
@ -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<Data, CheckError> {
|
||||
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
|
||||
|
@ -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<Data, CheckError> {
|
||||
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::<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 {
|
||||
todo!("err: not a function");
|
||||
}
|
||||
|
@ -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<Data, CheckError> {
|
||||
Ok(Data::empty_tuple())
|
||||
}
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
|
@ -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<Data, CheckError> {
|
||||
Ok(Data::new(
|
||||
self.func_no_info.with_info_run(Arc::new(info.clone())),
|
||||
))
|
||||
}
|
||||
fn has_scope(&self) -> bool {
|
||||
true
|
||||
|
@ -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::<data::bool::Bool>()
|
||||
{
|
||||
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<Data, CheckError> {
|
||||
Ok(
|
||||
if let Some(data::bool::Bool(true)) = self
|
||||
.condition
|
||||
.run(info)?
|
||||
.get()
|
||||
.as_any()
|
||||
.downcast_ref::<data::bool::Bool>()
|
||||
{
|
||||
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
|
||||
|
@ -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<Data, CheckError> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ pub trait MersStatement: Debug + Send + Sync {
|
||||
info: &mut CheckInfo,
|
||||
init_to: Option<&Type>,
|
||||
) -> 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.
|
||||
fn has_scope(&self) -> bool;
|
||||
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;
|
||||
o
|
||||
}
|
||||
fn run(&self, info: &mut Info) -> Data {
|
||||
fn run(&self, info: &mut Info) -> Result<Data, CheckError> {
|
||||
if self.has_scope() {
|
||||
info.create_scope();
|
||||
}
|
||||
|
@ -119,13 +119,13 @@ impl MersStatement for Object {
|
||||
.collect::<Result<_, _>>()?,
|
||||
)))
|
||||
}
|
||||
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<Data, CheckError> {
|
||||
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::<Result<_, _>>()?,
|
||||
)))
|
||||
}
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
|
@ -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<Data, CheckError> {
|
||||
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::<data::function::Function>()
|
||||
.unwrap()
|
||||
.clone()
|
||||
Ok::<_, CheckError>(
|
||||
v.run(info)?
|
||||
.get()
|
||||
.as_any()
|
||||
.downcast_ref::<data::function::Function>()
|
||||
.unwrap()
|
||||
.clone(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let mut found = None;
|
||||
for (i, func) in functions.iter().enumerate() {
|
||||
match func.get_as_type().o(&arg_type) {
|
||||
|
@ -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::<Result<_, _>>()?,
|
||||
)))
|
||||
}
|
||||
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<Data, CheckError> {
|
||||
Ok(Data::new(data::tuple::Tuple(
|
||||
self.elems
|
||||
.iter()
|
||||
.map(|s| Ok(s.run(info)?))
|
||||
.collect::<Result<_, CheckError>>()?,
|
||||
)))
|
||||
}
|
||||
fn has_scope(&self) -> bool {
|
||||
false
|
||||
|
@ -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<Data, CheckError> {
|
||||
Ok(self.val.clone())
|
||||
}
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
|
@ -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<Data, CheckError> {
|
||||
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()
|
||||
|
Loading…
Reference in New Issue
Block a user