mirror of
https://github.com/Dummi26/mers.git
synced 2025-12-29 01:16:53 +01:00
make objects work better, especially destructuring
This commit is contained in:
@@ -58,8 +58,12 @@ pub trait StaticMersFunc: Sized + 'static + Send + Sync {
|
||||
Some(Err(e)) => Err(e),
|
||||
None => Err(CheckError::from(format!(
|
||||
"unexpected argument of type {}, expected {}",
|
||||
a.get().as_type(),
|
||||
Type::new(data::function::FunctionT(Err(Arc::new(Self::types()))))
|
||||
a.get().as_type().with_info(i),
|
||||
Type::new(data::function::FunctionT(
|
||||
Err(Arc::new(Self::types())),
|
||||
crate::info::Info::neverused()
|
||||
))
|
||||
.with_info(i)
|
||||
))),
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
data::{self, Data, MersData, Type},
|
||||
errors::CheckError,
|
||||
info::Local,
|
||||
program::run::CheckInfo,
|
||||
program::run::{CheckInfo, CheckLocalGlobalInfo, RunLocalGlobalInfo},
|
||||
};
|
||||
|
||||
pub mod gen;
|
||||
@@ -63,7 +63,15 @@ impl Config {
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
let mut info_check: CheckInfo = Default::default();
|
||||
let info_parsed = crate::program::parsed::Info::new(
|
||||
crate::program::parsed::LocalGlobalInfo::new(Arc::new(Default::default())),
|
||||
);
|
||||
let mut info_check = CheckInfo::new(CheckLocalGlobalInfo::new(Arc::clone(
|
||||
&info_parsed.global.object_fields,
|
||||
)));
|
||||
let info_run = crate::program::run::Info::new(RunLocalGlobalInfo::new(Arc::clone(
|
||||
&info_parsed.global.object_fields,
|
||||
)));
|
||||
macro_rules! init_d {
|
||||
($e:expr) => {
|
||||
let t = $e;
|
||||
@@ -89,8 +97,8 @@ impl Config {
|
||||
init_d!(data::string::StringT);
|
||||
Self {
|
||||
globals: 0,
|
||||
info_parsed: Default::default(),
|
||||
info_run: Default::default(),
|
||||
info_parsed,
|
||||
info_run,
|
||||
info_check,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,29 +7,46 @@ use crate::{
|
||||
};
|
||||
|
||||
pub fn to_mers_func(
|
||||
out: impl Fn(&Type) -> Result<Type, CheckError> + Send + Sync + 'static,
|
||||
run: impl Fn(Data) -> Result<Data, CheckError> + Send + Sync + 'static,
|
||||
out: impl Fn(&Type, &mut crate::program::run::CheckInfo) -> Result<Type, CheckError>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
run: impl Fn(Data, &mut crate::program::run::Info) -> Result<Data, CheckError>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
) -> data::function::Function {
|
||||
data::function::Function {
|
||||
info: Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(Info::neverused())),
|
||||
out: Ok(Arc::new(move |a, _| out(a))),
|
||||
run: Arc::new(move |a, _| run(a)),
|
||||
out: Ok(Arc::new(move |a, i| out(a, i))),
|
||||
run: Arc::new(move |a, i| run(a, i)),
|
||||
inner_statements: None,
|
||||
}
|
||||
}
|
||||
|
||||
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) -> Result<Data, CheckError> + Send + Sync + 'static,
|
||||
out: impl Fn(&Type, &mut crate::program::run::CheckInfo) -> Result<Type, CheckError>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
run: impl Fn(Data, &mut crate::program::run::Info) -> Result<Data, CheckError>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
) -> data::function::Function {
|
||||
to_mers_func(
|
||||
move |a| {
|
||||
move |a, i| {
|
||||
if a.is_included_in(&in_type) {
|
||||
out(a)
|
||||
out(a, i)
|
||||
} else {
|
||||
Err(format!("Function argument must be {in_type}, but was {a}.").into())
|
||||
Err(format!(
|
||||
"Function argument must be {}, but was {}.",
|
||||
in_type.with_info(i),
|
||||
a.with_info(i)
|
||||
)
|
||||
.into())
|
||||
}
|
||||
},
|
||||
run,
|
||||
@@ -39,16 +56,19 @@ 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) -> Result<Data, CheckError> + Send + Sync + 'static,
|
||||
run: impl Fn(Data, &mut crate::program::run::Info) -> Result<Data, CheckError>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
) -> data::function::Function {
|
||||
data::function::Function::new_static(vec![(in_type, out_type)], move |a, _| run(a))
|
||||
data::function::Function::new_static(vec![(in_type, out_type)], move |a, i| run(a, i))
|
||||
}
|
||||
|
||||
pub fn to_mers_func_concrete_string_to_any(
|
||||
out_type: Type,
|
||||
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| {
|
||||
to_mers_func_with_in_out_types(Type::new(data::string::StringT), out_type, move |a, _| {
|
||||
f(a.get()
|
||||
.as_any()
|
||||
.downcast_ref::<data::string::String>()
|
||||
@@ -75,7 +95,7 @@ pub fn to_mers_func_concrete_string_string_to_any(
|
||||
Type::new(data::string::StringT),
|
||||
])),
|
||||
out_type,
|
||||
move |a| {
|
||||
move |a, _| {
|
||||
let a = a.get();
|
||||
let a = &a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap().0;
|
||||
let l = a[0].get();
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
data::{self, bool::bool_type, Data, Type},
|
||||
data::{self, bool::bool_type, Data, MersTypeWInfo, Type},
|
||||
errors::CheckError,
|
||||
program::run::{CheckInfo, Info},
|
||||
};
|
||||
@@ -30,7 +30,7 @@ impl Config {
|
||||
.add_var("lock_update", data::function::Function {
|
||||
info: Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
for t in a.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
if t.0.len() == 2 {
|
||||
@@ -42,23 +42,23 @@ impl Config {
|
||||
match f.o(&arg) {
|
||||
Ok(out) => {
|
||||
if !out.is_included_in(&arg) {
|
||||
return Err(format!("Function returns a value of type {out}, which isn't included in the type of the reference, {arg}.").into());
|
||||
return Err(format!("Function returns a value of type {}, which isn't included in the type of the reference, {}.", out.with_info(i), arg.with_info(i)).into());
|
||||
}
|
||||
},
|
||||
Err(e) => return Err(CheckError::new().msg_str(format!("Invalid argument type {arg} for function")).err(e)),
|
||||
Err(e) => return Err(CheckError::new().msg_str(format!("Invalid argument type {} for function", arg.with_info(i))).err(e)),
|
||||
}
|
||||
} else {
|
||||
return Err(format!("Arguments must be (reference, function)").into());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(format!("Arguments must be (reference, function), but {arg_ref} isn't a reference").into());
|
||||
return Err(format!("Arguments must be (reference, function), but {} isn't a reference", arg_ref.with_info(i)).into());
|
||||
}
|
||||
} else {
|
||||
return Err(format!("Can't call lock_update on tuple type {t} with length != 2, which is part of the argument type {a}.").into());
|
||||
return Err(format!("Can't call lock_update on tuple type {} with length != 2, which is part of the argument type {}.", t.with_info(i), a.with_info(i)).into());
|
||||
}
|
||||
} else {
|
||||
return Err(format!("Can't call lock_update on non-tuple type {t}, which is part of the argument type {a}.").into());
|
||||
return Err(format!("Can't call lock_update on non-tuple type {}, which is part of the argument type {}.", t.with_info(i), a.with_info(i)).into());
|
||||
}
|
||||
}
|
||||
Ok(Type::empty_tuple())
|
||||
@@ -98,10 +98,10 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
for t in &a.types {
|
||||
if t.as_any().downcast_ref::<data::string::StringT>().is_none() && t.as_any().downcast_ref::<data::tuple::TupleT>().is_none() && t.iterable().is_none() {
|
||||
return Err(format!("cannot get length of {t} (must be a tuple, string or iterable)").into());
|
||||
return Err(format!("cannot get length of {} (must be a tuple, string or iterable)", t.with_info(i)).into());
|
||||
}
|
||||
}
|
||||
Ok(Type::new(data::int::IntT))
|
||||
@@ -174,7 +174,7 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| if let Some(v) = a.dereference() { Ok(v) } else { Err(format!("cannot dereference type {a}").into())
|
||||
out: Ok(Arc::new(|a, i| if let Some(v) = a.dereference() { Ok(v) } else { Err(format!("cannot dereference type {}", a.with_info(i)).into())
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
if let Some(r) = a
|
||||
|
||||
@@ -6,8 +6,9 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
data::{self, Data, MersData, MersType, Type},
|
||||
data::{self, object::ObjectFieldsMap, Data, MersData, MersDataWInfo, MersType, Type},
|
||||
errors::CheckError,
|
||||
info::DisplayInfo,
|
||||
program::{self, run::CheckInfo},
|
||||
};
|
||||
|
||||
@@ -29,7 +30,7 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.types.iter().all(|t| t.as_any().downcast_ref::<data::tuple::TupleT>().is_some_and(|t| t.0.len() == 2 && t.0[0].is_included_in_single(&data::string::StringT) && t.0[1].iterable().is_some_and(|t| t.is_included_in_single(&data::string::StringT)))) {
|
||||
Ok(Type::newm(vec![
|
||||
Arc::new(data::tuple::TupleT(vec![
|
||||
@@ -37,13 +38,13 @@ impl Config {
|
||||
Type::new(data::string::StringT),
|
||||
Type::new(data::string::StringT),
|
||||
])),
|
||||
Arc::new(data::object::ObjectT(vec![("run_command_error".to_owned(), Type::new(data::string::StringT))]))
|
||||
Arc::new(data::object::ObjectT::new(vec![(i.global.object_fields.get_or_add_field("run_command_error"), Type::new(data::string::StringT))]))
|
||||
]))
|
||||
} else {
|
||||
return Err(format!("run_command called with invalid arguments (must be (String, Iter<String>))").into());
|
||||
}
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
run: Arc::new(|a, i| {
|
||||
let a = a.get();
|
||||
let cmd = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
|
||||
let (cmd, args) = (&cmd.0[0], &cmd.0[1]);
|
||||
@@ -52,7 +53,7 @@ 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<_>, _>>()?;
|
||||
let args = args.map(|v| v.map(|v| v.get().with_info(i).to_string())).collect::<Result<Vec<_>, _>>()?;
|
||||
match Command::new(&cmd.0)
|
||||
.args(args)
|
||||
.output()
|
||||
@@ -73,7 +74,7 @@ impl Config {
|
||||
Data::new(data::string::String(stderr)),
|
||||
])))
|
||||
}
|
||||
Err(e) => Ok(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::new(vec![(i.global.object_fields.get_or_add_field("run_command_error"), Data::new(data::string::String(e.to_string())))]))),
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
@@ -84,17 +85,17 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.types.iter().all(|t| t.as_any().downcast_ref::<data::tuple::TupleT>().is_some_and(|t| t.0.len() == 2 && t.0[0].is_included_in_single(&data::string::StringT) && t.0[1].iterable().is_some_and(|t| t.is_included_in_single(&data::string::StringT)))) {
|
||||
Ok(Type::newm(vec![
|
||||
Arc::new(ChildProcessT),
|
||||
Arc::new(data::object::ObjectT(vec![("run_command_error".to_owned(), Type::new(data::string::StringT))]))
|
||||
Arc::new(data::object::ObjectT::new(vec![(i.global.object_fields.get_or_add_field("run_command_error"), Type::new(data::string::StringT))]))
|
||||
]))
|
||||
} else {
|
||||
return Err(format!("spawn_command called with invalid arguments (must be (String, Iter<String>))").into());
|
||||
}
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
run: Arc::new(|a, i| {
|
||||
let a = a.get();
|
||||
let cmd = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
|
||||
let (cmd, args) = (&cmd.0[0], &cmd.0[1]);
|
||||
@@ -103,7 +104,7 @@ 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<_>, _>>()?;
|
||||
let args = args.map(|v| v.map(|v| v.get().with_info(i).to_string())).collect::<Result<Vec<_>, _>>()?;
|
||||
match Command::new(&cmd.0)
|
||||
.args(args)
|
||||
.stdin(Stdio::piped())
|
||||
@@ -117,7 +118,7 @@ impl Config {
|
||||
let c = BufReader::new(child.stderr.take().unwrap());
|
||||
Ok(Data::new(ChildProcess(Arc::new(Mutex::new((child, a, b, c))))))
|
||||
}
|
||||
Err(e) => Ok(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::new(vec![(i.global.object_fields.get_or_add_field("run_command_error"), Data::new(data::string::String(e.to_string())))]))),
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
@@ -128,14 +129,14 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.is_included_in_single(&ChildProcessT) {
|
||||
Ok(Type::newm(vec![
|
||||
Arc::new(data::tuple::TupleT(vec![data::bool::bool_type()])),
|
||||
Arc::new(data::tuple::TupleT(vec![])),
|
||||
]))
|
||||
} else {
|
||||
return Err(format!("childproc_exited called on non-ChildProcess type {a}").into());
|
||||
return Err(format!("childproc_exited called on non-ChildProcess type {}", a.with_info(i)).into());
|
||||
}
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
@@ -156,7 +157,7 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.is_included_in_single(&ChildProcessT) {
|
||||
Ok(Type::newm(vec![
|
||||
Arc::new(data::int::IntT),
|
||||
@@ -165,7 +166,7 @@ impl Config {
|
||||
Arc::new(data::tuple::TupleT(vec![])),
|
||||
]))
|
||||
} else {
|
||||
return Err(format!("childproc_await called on non-ChildProcess type {a}").into());
|
||||
return Err(format!("childproc_await called on non-ChildProcess type {}", a.with_info(i)).into());
|
||||
}
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
@@ -190,11 +191,11 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.types.iter().all(|a| a.as_any().downcast_ref::<data::tuple::TupleT>().is_some_and(|t| t.0.len() == 2 && t.0[0].is_included_in_single(&ChildProcessT) && t.0[1].iterable().is_some_and(|i| i.is_included_in_single(&data::byte::ByteT)))) {
|
||||
Ok(data::bool::bool_type())
|
||||
} else {
|
||||
return Err(format!("childproc_write_bytes called on non-`(ChildProcess, Iter<Byte>)` type {a}").into());
|
||||
return Err(format!("childproc_write_bytes called on non-`(ChildProcess, Iter<Byte>)` type {}", a.with_info(i)).into());
|
||||
}
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
@@ -219,11 +220,11 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.is_included_in_single(&data::tuple::TupleT(vec![Type::new(ChildProcessT), Type::new(data::string::StringT)])) {
|
||||
Ok(data::bool::bool_type())
|
||||
} else {
|
||||
return Err(format!("childproc_write_string called on non-`(ChildProcess, String)` type {a}").into());
|
||||
return Err(format!("childproc_write_string called on non-`(ChildProcess, String)` type {}", a.with_info(i)).into());
|
||||
}
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
@@ -248,14 +249,14 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.is_included_in_single(&ChildProcessT) {
|
||||
Ok(Type::newm(vec![
|
||||
Arc::new(data::tuple::TupleT(vec![Type::new(data::byte::ByteT)])),
|
||||
Arc::new(data::tuple::TupleT(vec![])),
|
||||
]))
|
||||
} else {
|
||||
return Err(format!("childproc_read_byte called on non-ChildProcess type {a}").into());
|
||||
return Err(format!("childproc_read_byte called on non-ChildProcess type {}", a.with_info(i)).into());
|
||||
}
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
@@ -277,14 +278,14 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.is_included_in_single(&ChildProcessT) {
|
||||
Ok(Type::newm(vec![
|
||||
Arc::new(data::tuple::TupleT(vec![Type::new(data::byte::ByteT)])),
|
||||
Arc::new(data::tuple::TupleT(vec![])),
|
||||
]))
|
||||
} else {
|
||||
return Err(format!("childproc_readerr_byte called on non-ChildProcess type {a}").into());
|
||||
return Err(format!("childproc_readerr_byte called on non-ChildProcess type {}", a.with_info(i)).into());
|
||||
}
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
@@ -306,14 +307,14 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.is_included_in_single(&ChildProcessT) {
|
||||
Ok(Type::newm(vec![
|
||||
Arc::new(data::tuple::TupleT(vec![Type::new(data::string::StringT)])),
|
||||
Arc::new(data::tuple::TupleT(vec![])),
|
||||
]))
|
||||
} else {
|
||||
return Err(format!("childproc_read_line called on non-ChildProcess type {a}").into());
|
||||
return Err(format!("childproc_read_line called on non-ChildProcess type {}", a.with_info(i)).into());
|
||||
}
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
@@ -335,14 +336,14 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.is_included_in_single(&ChildProcessT) {
|
||||
Ok(Type::newm(vec![
|
||||
Arc::new(data::tuple::TupleT(vec![Type::new(data::string::StringT)])),
|
||||
Arc::new(data::tuple::TupleT(vec![])),
|
||||
]))
|
||||
} else {
|
||||
return Err(format!("childproc_read_line called on non-ChildProcess type {a}").into());
|
||||
return Err(format!("childproc_read_line called on non-ChildProcess type {}", a.with_info(i)).into());
|
||||
}
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
@@ -376,6 +377,9 @@ pub struct ChildProcess(
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ChildProcessT;
|
||||
impl MersData for ChildProcess {
|
||||
fn display(&self, _info: &DisplayInfo<'_>, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
|
||||
None
|
||||
}
|
||||
@@ -410,6 +414,13 @@ impl Display for ChildProcess {
|
||||
}
|
||||
}
|
||||
impl MersType for ChildProcessT {
|
||||
fn display(
|
||||
&self,
|
||||
_info: &crate::info::DisplayInfo<'_>,
|
||||
f: &mut std::fmt::Formatter,
|
||||
) -> std::fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
fn iterable(&self) -> Option<Type> {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::{
|
||||
data::{self, Data, Type},
|
||||
data::{self, Data, MersTypeWInfo, Type},
|
||||
program::{self, run::CheckInfo},
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
let mut out = Type::empty();
|
||||
for a in a.types.iter() {
|
||||
if let Some(t) = a.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
@@ -25,7 +25,7 @@ impl Config {
|
||||
if !t.0[1].is_included_in_single(&data::int::IntT) {
|
||||
return Err(format!(
|
||||
"called get with non-int index of type {}",
|
||||
t.0[1]
|
||||
t.0[1].with_info(i)
|
||||
)
|
||||
.into());
|
||||
}
|
||||
@@ -33,12 +33,16 @@ impl Config {
|
||||
out.add_all(&v);
|
||||
} else {
|
||||
return Err(format!(
|
||||
"called get on non-gettable type {t}, part of {a}"
|
||||
"called get on non-gettable type {}, part of {}",
|
||||
t.with_info(i),
|
||||
a.with_info(i)
|
||||
)
|
||||
.into());
|
||||
}
|
||||
} else {
|
||||
return Err(format!("called get on non-tuple type {a}").into());
|
||||
return Err(
|
||||
format!("called get on non-tuple type {}", a.with_info(i)).into()
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(Type::newm(vec![
|
||||
|
||||
@@ -7,9 +7,10 @@ use crate::{
|
||||
data::{
|
||||
self,
|
||||
function::{Function, FunctionT},
|
||||
Data, MersData, MersType, Type,
|
||||
Data, MersData, MersType, MersTypeWInfo, Type,
|
||||
},
|
||||
errors::CheckError,
|
||||
info::DisplayInfo,
|
||||
program::{self, run::CheckInfo},
|
||||
};
|
||||
|
||||
@@ -49,7 +50,7 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
for a in &a.types {
|
||||
if let Some(tuple) = a.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
if let (Some(v), Some(f)) = (tuple.0.get(0), tuple.0.get(1)) {
|
||||
@@ -70,7 +71,8 @@ impl Config {
|
||||
}
|
||||
} else {
|
||||
return Err(format!(
|
||||
"for_each called on tuple not containing iterable and function: {v} is {}",
|
||||
"for_each called on tuple not containing iterable and function: {} is {}",
|
||||
v.with_info(i),
|
||||
if v.iterable().is_some() { "iterable" } else { "not iterable" },
|
||||
).into());
|
||||
}
|
||||
@@ -133,13 +135,13 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
let data = if let Some(a) = a.iterable() {
|
||||
a
|
||||
} else {
|
||||
return Err(format!("cannot call enumerate on non-iterable type {a}.").into());
|
||||
return Err(format!("cannot call enumerate on non-iterable type {}.", a.with_info(i)).into());
|
||||
};
|
||||
Ok(Type::new(IterT::new(ItersT::Enumerate, data)?))
|
||||
Ok(Type::new(IterT::new(ItersT::Enumerate, data, i)?))
|
||||
})),
|
||||
run: Arc::new(|a, _i| Ok(Data::new(Iter(Iters::Enumerate, a.clone())))),
|
||||
inner_statements: None,
|
||||
@@ -150,13 +152,13 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
let data = if let Some(a) = a.iterable() {
|
||||
a
|
||||
} else {
|
||||
return Err(format!("cannot call chain on non-iterable type {a}.").into());
|
||||
return Err(format!("cannot call chain on non-iterable type {}.", a.with_info(i)).into());
|
||||
};
|
||||
Ok(Type::new(IterT::new(ItersT::Chained, data)?))
|
||||
Ok(Type::new(IterT::new(ItersT::Chained, data, i)?))
|
||||
})),
|
||||
run: Arc::new(|a, _i| Ok(Data::new(Iter(Iters::Chained, a.clone())))),
|
||||
inner_statements: None,
|
||||
@@ -172,6 +174,7 @@ fn genfunc_iter_and_func(
|
||||
) -> data::function::Function {
|
||||
fn iter_out_arg(
|
||||
a: &Type,
|
||||
i: &mut CheckInfo,
|
||||
name: &str,
|
||||
func: impl Fn(FunctionT) -> ItersT + Sync + Send,
|
||||
) -> Result<Type, CheckError> {
|
||||
@@ -184,14 +187,16 @@ fn genfunc_iter_and_func(
|
||||
if let Some(v) = t.0[0].iterable() {
|
||||
for f in t.0[1].types.iter() {
|
||||
if let Some(f) = f.executable() {
|
||||
out.add(Arc::new(IterT::new(func(f), v.clone())?));
|
||||
out.add(Arc::new(IterT::new(func(f), v.clone(), i)?));
|
||||
} else {
|
||||
return Err(format!("cannot call {name} on tuple that isn't (_, function): got {} instead of function as part of {a}", t.0[1]).into());
|
||||
return Err(format!("cannot call {name} on tuple that isn't (_, function): got {} instead of function as part of {}", t.0[1].with_info(i), a.with_info(i)).into());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(format!(
|
||||
"cannot call {name} on non-iterable type {t}, which is part of {a}."
|
||||
"cannot call {name} on non-iterable type {}, which is part of {}.",
|
||||
t.with_info(i),
|
||||
a.with_info(i)
|
||||
)
|
||||
.into());
|
||||
}
|
||||
@@ -202,7 +207,7 @@ fn genfunc_iter_and_func(
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(move |a, _i| iter_out_arg(a, name, |f| ft(f)))),
|
||||
out: Ok(Arc::new(move |a, i| iter_out_arg(a, i, name, |f| ft(f)))),
|
||||
run: Arc::new(move |a, _i| {
|
||||
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)) {
|
||||
@@ -225,10 +230,12 @@ fn genfunc_iter_and_arg<T: MersType, D: MersData>(
|
||||
) -> data::function::Function {
|
||||
fn iter_out_arg<T: MersType>(
|
||||
a: &Type,
|
||||
i: &mut CheckInfo,
|
||||
name: &str,
|
||||
func: impl Fn(&T) -> ItersT + Sync + Send,
|
||||
type_sample: &T,
|
||||
) -> Result<Type, CheckError> {
|
||||
let type_sample = type_sample.with_info(i);
|
||||
let mut out = Type::empty();
|
||||
for t in a.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
@@ -238,14 +245,16 @@ fn genfunc_iter_and_arg<T: MersType, D: MersData>(
|
||||
if let Some(v) = t.0[0].iterable() {
|
||||
for f in t.0[1].types.iter() {
|
||||
if let Some(f) = f.as_any().downcast_ref::<T>() {
|
||||
out.add(Arc::new(IterT::new(func(f), v.clone())?));
|
||||
out.add(Arc::new(IterT::new(func(f), v.clone(), i)?));
|
||||
} else {
|
||||
return Err(format!("cannot call {name} on tuple that isn't (_, {type_sample}): got {} instead of {type_sample} as part of {a}", t.0[1]).into());
|
||||
return Err(format!("cannot call {name} on tuple that isn't (_, {type_sample}): got {} instead of {type_sample} as part of {}", t.0[1].with_info(i), a.with_info(i)).into());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(format!(
|
||||
"cannot call {name} on non-iterable type {t}, which is part of {a}."
|
||||
"cannot call {name} on non-iterable type {}, which is part of {}.",
|
||||
t.with_info(i),
|
||||
a.with_info(i)
|
||||
)
|
||||
.into());
|
||||
}
|
||||
@@ -256,8 +265,8 @@ fn genfunc_iter_and_arg<T: MersType, D: MersData>(
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(move |a, _i| {
|
||||
iter_out_arg(a, name, |f: &T| ft(f), type_sample)
|
||||
out: Ok(Arc::new(move |a, i| {
|
||||
iter_out_arg(a, i, name, |f: &T| ft(f), type_sample)
|
||||
})),
|
||||
run: Arc::new(move |a, _i| {
|
||||
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
|
||||
@@ -303,6 +312,9 @@ pub struct Iter(pub Iters, pub Data);
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct IterT(pub ItersT, pub Type, pub Type);
|
||||
impl MersData for Iter {
|
||||
fn display(&self, _info: &DisplayInfo<'_>, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
fn is_eq(&self, _other: &dyn MersData) -> bool {
|
||||
false
|
||||
}
|
||||
@@ -396,7 +408,14 @@ impl MersData for Iter {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
fn as_type(&self) -> data::Type {
|
||||
Type::new(IterT::new(self.0.as_type(), self.1.get().as_type()).unwrap())
|
||||
Type::new(
|
||||
IterT::new(
|
||||
self.0.as_type(),
|
||||
self.1.get().as_type(),
|
||||
&crate::info::Info::neverused(),
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
@@ -409,7 +428,8 @@ impl MersData for Iter {
|
||||
}
|
||||
}
|
||||
impl IterT {
|
||||
pub fn new(iter: ItersT, data: Type) -> Result<Self, CheckError> {
|
||||
/// `i` is only used for errors (this is important for `as_type()`)
|
||||
pub fn new(iter: ItersT, data: Type, i: &CheckInfo) -> Result<Self, CheckError> {
|
||||
let t = match &iter {
|
||||
ItersT::Map(f) => f.o(&data)?,
|
||||
ItersT::Filter(f) => {
|
||||
@@ -417,7 +437,8 @@ impl IterT {
|
||||
data.clone()
|
||||
} else {
|
||||
return Err(format!(
|
||||
"Iter:Filter, but function doesn't return bool for argument {data}."
|
||||
"Iter:Filter, but function doesn't return bool for argument {}.",
|
||||
data.with_info(&i)
|
||||
)
|
||||
.into());
|
||||
}
|
||||
@@ -450,7 +471,8 @@ impl IterT {
|
||||
out
|
||||
} else {
|
||||
return Err(format!(
|
||||
"Cannot create a chain from an iterator over the non-iterator type {data}."
|
||||
"Cannot create a chain from an iterator over the non-iterator type {}.",
|
||||
data.with_info(i)
|
||||
)
|
||||
.into());
|
||||
}
|
||||
@@ -460,6 +482,13 @@ impl IterT {
|
||||
}
|
||||
}
|
||||
impl MersType for IterT {
|
||||
fn display(
|
||||
&self,
|
||||
info: &crate::info::DisplayInfo<'_>,
|
||||
f: &mut std::fmt::Formatter,
|
||||
) -> std::fmt::Result {
|
||||
write!(f, "<Iter: {}>", self.2.with_display(info))
|
||||
}
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||
if let Some(other) = other.as_any().downcast_ref::<Self>() {
|
||||
self.2.is_same_type_as(&other.2)
|
||||
@@ -496,11 +525,6 @@ impl Display for Iter {
|
||||
write!(f, "<Iter>")
|
||||
}
|
||||
}
|
||||
impl Display for IterT {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "<Iter: {}>", self.2)
|
||||
}
|
||||
}
|
||||
impl Iters {
|
||||
fn as_type(&self) -> ItersT {
|
||||
match self {
|
||||
@@ -527,15 +551,24 @@ fn genfunc_iter_in_val_out(
|
||||
Function {
|
||||
info: crate::info::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(crate::info::Info::neverused())),
|
||||
out: Ok(Arc::new(move |a, _i| {
|
||||
out: Ok(Arc::new(move |a, i| {
|
||||
if let Some(iter_over) = a.iterable() {
|
||||
if iter_over.is_included_in(&iter_type) {
|
||||
Ok(out_type.clone())
|
||||
} else {
|
||||
Err(format!("Cannot call function {name} on iterator over type {a}, which isn't {iter_type}.").into())
|
||||
Err(format!(
|
||||
"Cannot call function {name} on iterator over type {}, which isn't {}.",
|
||||
a.with_info(i),
|
||||
iter_type.with_info(i)
|
||||
)
|
||||
.into())
|
||||
}
|
||||
} else {
|
||||
Err(format!("Cannot call function {name} on non-iterable type {a}.").into())
|
||||
Err(format!(
|
||||
"Cannot call function {name} on non-iterable type {}.",
|
||||
a.with_info(i)
|
||||
)
|
||||
.into())
|
||||
}
|
||||
})),
|
||||
run: Arc::new(run),
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
use std::{
|
||||
fmt::Display,
|
||||
sync::{Arc, Mutex, RwLock},
|
||||
};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
||||
use crate::{
|
||||
data::{self, Data, MersData, MersType, Type},
|
||||
data::{self, Data, MersData, MersType, MersTypeWInfo, Type},
|
||||
errors::CheckError,
|
||||
info::DisplayInfo,
|
||||
parsing::{statements::to_string_literal, Source},
|
||||
program::{self, run::CheckInfo},
|
||||
};
|
||||
@@ -34,7 +32,7 @@ impl Config {
|
||||
.add_var("get_mut", data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
let mut out = Type::empty_tuple();
|
||||
for t in a.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
@@ -50,18 +48,18 @@ impl Config {
|
||||
out.add(Arc::new(data::tuple::TupleT(vec![Type::new(data::reference::ReferenceT(t.0.clone()))])));
|
||||
} else {
|
||||
return Err(format!(
|
||||
"get_mut: first argument in tuple {t} isn't `&List<_>`."
|
||||
"get_mut: first argument in tuple {} isn't `&List<_>`.", t.with_info(i)
|
||||
).into());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(format!(
|
||||
"get_mut: first type in tuple {t} isn't a reference."
|
||||
"get_mut: first type in tuple {} isn't a reference.", t.with_info(i)
|
||||
).into());
|
||||
}
|
||||
} else {
|
||||
return Err(format!(
|
||||
"get_mut: Second type in tuple {t} wasn't `Int`."
|
||||
"get_mut: Second type in tuple {} wasn't `Int`.", t.with_info(i)
|
||||
).into());
|
||||
}
|
||||
} else {
|
||||
@@ -103,7 +101,7 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if let Some(a) = a.dereference() {
|
||||
let mut out = Type::empty();
|
||||
for t in a.types.iter() {
|
||||
@@ -111,7 +109,7 @@ impl Config {
|
||||
out.add_all(&t.0);
|
||||
} else {
|
||||
return Err(format!(
|
||||
"pop: found a reference to {t}, which is not a list"
|
||||
"pop: found a reference to {}, which is not a list", t.with_info(i)
|
||||
).into());
|
||||
}
|
||||
}
|
||||
@@ -120,7 +118,7 @@ impl Config {
|
||||
Arc::new(data::tuple::TupleT(vec![]))
|
||||
]))
|
||||
} else {
|
||||
return Err(format!("pop: not a reference: {a}").into());
|
||||
return Err(format!("pop: not a reference: {}", a.with_info(i)).into());
|
||||
}
|
||||
})),
|
||||
run: Arc::new(|a, _i| {
|
||||
@@ -151,7 +149,7 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
for t in a.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
if t.0.len() != 2 {
|
||||
@@ -166,22 +164,22 @@ impl Config {
|
||||
if let Some(t) = t.as_any().downcast_ref::<ListT>() {
|
||||
if !new.is_included_in(&t.0) {
|
||||
return Err(format!(
|
||||
"push: found a reference to {t}, which is a list which can't contain elements of type {new}"
|
||||
"push: found a reference to {}, which is a list which can't contain elements of type {}", t.with_info(i), new.with_info(i)
|
||||
).into());
|
||||
}
|
||||
} else {
|
||||
return Err(format!(
|
||||
"push: found a reference to {t}, which is not a list"
|
||||
"push: found a reference to {}, which is not a list", t.with_info(i)
|
||||
).into());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(format!(
|
||||
"push: first element in tuple not a reference: {a}"
|
||||
"push: first element in tuple not a reference: {}", a.with_info(i)
|
||||
).into());
|
||||
}
|
||||
} else {
|
||||
return Err(format!("push: not a tuple: {t}")
|
||||
return Err(format!("push: not a tuple: {}", t.with_info(i))
|
||||
.into());
|
||||
}
|
||||
}
|
||||
@@ -214,12 +212,12 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if let Some(v) = a.iterable() {
|
||||
Ok(Type::new(ListT(v)))
|
||||
} else {
|
||||
Err(format!(
|
||||
"cannot iterate over type {a}"
|
||||
"cannot iterate over type {}", a.with_info(i)
|
||||
).into())
|
||||
}
|
||||
})),
|
||||
@@ -251,6 +249,17 @@ impl Clone for List {
|
||||
#[derive(Debug)]
|
||||
pub struct ListT(pub Type);
|
||||
impl MersData for List {
|
||||
fn display(&self, info: &DisplayInfo<'_>, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "[")?;
|
||||
for (i, c) in self.0.iter().enumerate() {
|
||||
if i > 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
c.read().unwrap().get().display(info, f)?;
|
||||
}
|
||||
write!(f, "]")?;
|
||||
Ok(())
|
||||
}
|
||||
fn is_eq(&self, other: &dyn MersData) -> bool {
|
||||
if let Some(other) = other.as_any().downcast_ref::<Self>() {
|
||||
other.0.len() == self.0.len()
|
||||
@@ -288,6 +297,17 @@ impl MersData for List {
|
||||
}
|
||||
}
|
||||
impl MersType for ListT {
|
||||
fn display(
|
||||
&self,
|
||||
info: &crate::info::DisplayInfo<'_>,
|
||||
f: &mut std::fmt::Formatter,
|
||||
) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"List<{}>",
|
||||
to_string_literal(&self.0.with_display(info).to_string(), '>')
|
||||
)
|
||||
}
|
||||
fn iterable(&self) -> Option<Type> {
|
||||
Some(self.0.clone())
|
||||
}
|
||||
@@ -324,25 +344,6 @@ impl MersType for ListT {
|
||||
Some(Type::new(Self(self.0.simplify_for_display(info))))
|
||||
}
|
||||
}
|
||||
impl Display for List {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "[")?;
|
||||
for (i, c) in self.0.iter().enumerate() {
|
||||
if i > 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
write!(f, "{}", c.read().unwrap().get())?;
|
||||
}
|
||||
write!(f, "]")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl Display for ListT {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "List<{}>", to_string_literal(&self.0.to_string(), '>'))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl List {
|
||||
pub fn inner_type(&self) -> Type {
|
||||
let mut t = Type::empty();
|
||||
|
||||
@@ -326,7 +326,7 @@ fn num_iter_to_num(
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(move |a, _i| {
|
||||
out: Ok(Arc::new(move |a, i| {
|
||||
if let Some(a) = a.iterable() {
|
||||
let int_type = Type::new(data::int::IntT);
|
||||
if a.is_included_in(&int_type) {
|
||||
@@ -343,7 +343,7 @@ fn num_iter_to_num(
|
||||
if a.is_included_in(&int_float_type) {
|
||||
Ok(int_float_type)
|
||||
} else {
|
||||
Err(format!("argument passed to {func_name} must be an iterator over values of type Int/String, but was an iterator over values of type {a}.").into())
|
||||
Err(format!("argument passed to {func_name} must be an iterator over values of type Int/String, but was an iterator over values of type {}.", a.with_info(i)).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,9 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
data::{self, Data, MersData, MersType, Type},
|
||||
data::{self, Data, MersData, MersType, MersTypeWInfo, Type},
|
||||
errors::CheckError,
|
||||
info::DisplayInfo,
|
||||
parsing::{statements::to_string_literal, Source},
|
||||
program::{self, run::CheckInfo},
|
||||
};
|
||||
@@ -57,10 +58,10 @@ impl Config {
|
||||
.add_var("thread_finished", data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
for t in a.types.iter() {
|
||||
if !t.as_any().is::<ThreadT>() {
|
||||
return Err(CheckError::new().msg_str(format!("Cannot call thread_finished on a value of type {t}, which isn't a thread but part of the argument {a}.")));
|
||||
return Err(CheckError::new().msg_str(format!("Cannot call thread_finished on a value of type {}, which isn't a thread but part of the argument {}.", t.with_info(i), a.with_info(i))));
|
||||
}
|
||||
}
|
||||
Ok(data::bool::bool_type())
|
||||
@@ -78,13 +79,13 @@ impl Config {
|
||||
.add_var("thread_await", data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
let mut out = Type::empty();
|
||||
for t in a.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<ThreadT>() {
|
||||
out.add_all(&t.0);
|
||||
} else {
|
||||
return Err(CheckError::new().msg_str(format!("Cannot call thread_await on a value of type {t}, which isn't a thread but part of the argument {a}.")));
|
||||
return Err(CheckError::new().msg_str(format!("Cannot call thread_await on a value of type {}, which isn't a thread but part of the argument {}.", t.with_info(i), a.with_info(i))));
|
||||
}
|
||||
}
|
||||
Ok(out)
|
||||
@@ -112,6 +113,9 @@ pub struct Thread(
|
||||
pub struct ThreadT(pub Type);
|
||||
|
||||
impl MersData for Thread {
|
||||
fn display(&self, _info: &DisplayInfo<'_>, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
fn is_eq(&self, _other: &dyn MersData) -> bool {
|
||||
false
|
||||
}
|
||||
@@ -132,6 +136,17 @@ impl MersData for Thread {
|
||||
}
|
||||
}
|
||||
impl MersType for ThreadT {
|
||||
fn display(
|
||||
&self,
|
||||
info: &crate::info::DisplayInfo<'_>,
|
||||
f: &mut std::fmt::Formatter,
|
||||
) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Thread<{}>",
|
||||
to_string_literal(&self.0.with_display(info).to_string(), '>')
|
||||
)
|
||||
}
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||
if let Some(other) = other.as_any().downcast_ref::<Self>() {
|
||||
self.0.is_same_type_as(&other.0)
|
||||
@@ -172,8 +187,3 @@ impl Display for Thread {
|
||||
write!(f, "<Thread>")
|
||||
}
|
||||
}
|
||||
impl Display for ThreadT {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Thread<{}>", to_string_literal(&self.0.to_string(), '>'))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
data::{self, Data, Type},
|
||||
data::{self, Data, MersDataWInfo, Type},
|
||||
program::{self, run::CheckInfo},
|
||||
};
|
||||
|
||||
@@ -66,9 +66,9 @@ impl Config {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|a, _i| Ok(a.clone()))),
|
||||
run: Arc::new(|a, _i| {
|
||||
run: Arc::new(|a, i| {
|
||||
let a2 = a.get();
|
||||
eprintln!("{} :: {}", a2.as_type(), a2);
|
||||
eprintln!("{} :: {}", a2.as_type().with_info(i), a2.with_info(i));
|
||||
drop(a2);
|
||||
Ok(a)
|
||||
}),
|
||||
@@ -81,8 +81,8 @@ impl Config {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
|
||||
run: Arc::new(|a, _i| {
|
||||
eprint!("{}", a.get());
|
||||
run: Arc::new(|a, i| {
|
||||
eprint!("{}", a.get().with_info(i));
|
||||
_ = std::io::stderr().lock().flush();
|
||||
Ok(Data::empty_tuple())
|
||||
}),
|
||||
@@ -95,8 +95,8 @@ impl Config {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
|
||||
run: Arc::new(|a, _i| {
|
||||
eprintln!("{}", a.get());
|
||||
run: Arc::new(|a, i| {
|
||||
eprintln!("{}", a.get().with_info(i));
|
||||
Ok(Data::empty_tuple())
|
||||
}),
|
||||
inner_statements: None,
|
||||
@@ -108,8 +108,8 @@ impl Config {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
|
||||
run: Arc::new(|a, _i| {
|
||||
print!("{}", a.get());
|
||||
run: Arc::new(|a, i| {
|
||||
print!("{}", a.get().with_info(i));
|
||||
_ = std::io::stdout().lock().flush();
|
||||
Ok(Data::empty_tuple())
|
||||
}),
|
||||
@@ -122,8 +122,8 @@ impl Config {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
|
||||
run: Arc::new(|a, _i| {
|
||||
println!("{}", a.get());
|
||||
run: Arc::new(|a, i| {
|
||||
println!("{}", a.get().with_info(i));
|
||||
Ok(Data::empty_tuple())
|
||||
}),
|
||||
inner_statements: None,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::data::{self, Data, Type};
|
||||
use crate::data::{self, Data, MersDataWInfo, Type};
|
||||
|
||||
use super::{
|
||||
gen::{function::func, AnyOrNone, IterToList, OneOf, OneOrNone},
|
||||
@@ -58,19 +58,22 @@ impl Config {
|
||||
.add_var(
|
||||
"concat",
|
||||
util::to_mers_func(
|
||||
|a| {
|
||||
|a, i| {
|
||||
if a.iterable().is_some() {
|
||||
Ok(Type::new(data::string::StringT))
|
||||
} else {
|
||||
Err(format!("concat called on non-iterable type {a}").into())
|
||||
Err(
|
||||
format!("concat called on non-iterable type {}", a.with_info(i))
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
},
|
||||
|a| {
|
||||
|a, i| {
|
||||
Ok(Data::new(data::string::String(
|
||||
a.get()
|
||||
.iterable()
|
||||
.unwrap()
|
||||
.map(|v| v.map(|v| v.get().to_string()))
|
||||
.map(|v| v.map(|v| v.get().with_info(i).to_string()))
|
||||
.collect::<Result<_, _>>()?,
|
||||
)))
|
||||
},
|
||||
@@ -79,8 +82,12 @@ impl Config {
|
||||
.add_var(
|
||||
"to_string",
|
||||
util::to_mers_func(
|
||||
|_a| Ok(Type::new(data::string::StringT)),
|
||||
|a| Ok(Data::new(data::string::String(a.get().to_string()))),
|
||||
|_a, _| Ok(Type::new(data::string::StringT)),
|
||||
|a, i| {
|
||||
Ok(Data::new(data::string::String(
|
||||
a.get().with_info(i).to_string(),
|
||||
)))
|
||||
},
|
||||
),
|
||||
)
|
||||
.add_var(
|
||||
|
||||
@@ -3,9 +3,9 @@ use std::sync::{Arc, Mutex};
|
||||
use crate::{
|
||||
data::{self, Data},
|
||||
errors::{CheckError, EColor, SourceRange},
|
||||
info::{self, Local},
|
||||
info,
|
||||
parsing::Source,
|
||||
program::{self},
|
||||
program,
|
||||
};
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::{
|
||||
|
||||
use crate::{
|
||||
errors::{CheckError, SourceRange},
|
||||
info,
|
||||
info::{self, DisplayInfo},
|
||||
};
|
||||
|
||||
#[cfg(feature = "parse")]
|
||||
@@ -113,7 +113,7 @@ pub struct Local {
|
||||
pub vars: HashMap<String, (usize, usize)>,
|
||||
pub vars_count: usize,
|
||||
}
|
||||
#[derive(Clone, Debug, Default)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct LocalGlobalInfo {
|
||||
pub depth: usize,
|
||||
pub enable_hooks: bool,
|
||||
@@ -129,11 +129,33 @@ pub struct LocalGlobalInfo {
|
||||
)>,
|
||||
>,
|
||||
>,
|
||||
pub object_fields: Arc<Mutex<HashMap<String, usize>>>,
|
||||
pub object_fields_rev: Arc<Mutex<Vec<String>>>,
|
||||
}
|
||||
impl LocalGlobalInfo {
|
||||
pub fn new(object_fields: Arc<Mutex<HashMap<String, usize>>>) -> Self {
|
||||
Self {
|
||||
depth: 0,
|
||||
enable_hooks: false,
|
||||
save_info_at: Default::default(),
|
||||
object_fields,
|
||||
object_fields_rev: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl info::Local for Local {
|
||||
type VariableIdentifier = String;
|
||||
type VariableData = (usize, usize);
|
||||
type Global = LocalGlobalInfo;
|
||||
fn neverused_global() -> Self::Global {
|
||||
Self::Global {
|
||||
depth: 0,
|
||||
enable_hooks: false,
|
||||
save_info_at: Default::default(),
|
||||
object_fields: Default::default(),
|
||||
object_fields_rev: Default::default(),
|
||||
}
|
||||
}
|
||||
fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) {
|
||||
self.vars_count += 1;
|
||||
self.vars.insert(id, value);
|
||||
@@ -147,4 +169,10 @@ impl info::Local for Local {
|
||||
fn duplicate(&self) -> Self {
|
||||
self.clone()
|
||||
}
|
||||
fn display_info<'a>(global: &'a Self::Global) -> DisplayInfo<'a> {
|
||||
DisplayInfo {
|
||||
object_fields: &global.object_fields,
|
||||
object_fields_rev: &global.object_fields_rev,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
data::object::ObjectFieldsMap,
|
||||
errors::{CheckError, SourceRange},
|
||||
info,
|
||||
program::{self},
|
||||
info, program,
|
||||
};
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
@@ -22,10 +22,15 @@ impl MersStatement for Object {
|
||||
) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
|
||||
Ok(Box::new(program::run::object::Object {
|
||||
pos_in_src: self.pos_in_src.clone(),
|
||||
elems: self
|
||||
fields: self
|
||||
.elems
|
||||
.iter()
|
||||
.map(|(n, v)| -> Result<_, CheckError> { Ok((n.clone(), v.compile(info, comp)?)) })
|
||||
.map(|(n, v)| -> Result<_, CheckError> {
|
||||
Ok((
|
||||
info.global.object_fields.get_or_add_field(n),
|
||||
v.compile(info, comp)?,
|
||||
))
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
errors::{CheckError, EColor, SourceRange},
|
||||
info::Local,
|
||||
program::{self},
|
||||
program,
|
||||
};
|
||||
|
||||
use super::{CompInfo, MersStatement};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
data::{self, Data, MersData, Type},
|
||||
errors::{CheckError, SourceRange},
|
||||
info::Local,
|
||||
};
|
||||
|
||||
use super::MersStatement;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
data::{self, Data, Type},
|
||||
data::{self, Data, MersTypeWInfo, Type},
|
||||
errors::{CheckError, SourceRange},
|
||||
};
|
||||
|
||||
@@ -28,7 +28,7 @@ impl MersStatement for Loop {
|
||||
if let Some(i) = i.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
if i.0.len() > 1 {
|
||||
return Err(format!(
|
||||
"Loop: Inner statement must return ()/(T), not {t} (because of {i}, a tuple of length > 1)."
|
||||
"Loop: Inner statement must return ()/(T), not {} (because of {}, a tuple of length > 1).", t.with_info(info), i.with_info(info)
|
||||
)
|
||||
.into());
|
||||
} else {
|
||||
@@ -40,7 +40,7 @@ impl MersStatement for Loop {
|
||||
}
|
||||
} else {
|
||||
return Err(format!(
|
||||
"Loop: Inner statement must return ()/(T), not {t} (because of {i}, which isn't a tuple)."
|
||||
"Loop: Inner statement must return ()/(T), not {} (because of {}, which isn't a tuple).", t.with_info(info), i.with_info(info)
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::{
|
||||
use crate::{
|
||||
data::{self, Data, Type},
|
||||
errors::{CheckError, EColor, SourceRange},
|
||||
info,
|
||||
info::{self, DisplayInfo},
|
||||
};
|
||||
|
||||
#[cfg(feature = "run")]
|
||||
@@ -126,10 +126,21 @@ pub type CheckInfo = info::Info<CheckLocal>;
|
||||
pub struct RunLocal {
|
||||
pub vars: Vec<Arc<RwLock<Data>>>,
|
||||
}
|
||||
#[derive(Default, Clone, Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RunLocalGlobalInfo {
|
||||
/// if set, if `Instant::now()` is equal to or after the set `Instant`, stop the program with an error.
|
||||
pub limit_runtime: Option<Instant>,
|
||||
pub object_fields: Arc<Mutex<HashMap<String, usize>>>,
|
||||
pub object_fields_rev: Arc<Mutex<Vec<String>>>,
|
||||
}
|
||||
impl RunLocalGlobalInfo {
|
||||
pub fn new(object_fields: Arc<Mutex<HashMap<String, usize>>>) -> Self {
|
||||
Self {
|
||||
limit_runtime: None,
|
||||
object_fields,
|
||||
object_fields_rev: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Default, Clone)]
|
||||
pub struct CheckLocal {
|
||||
@@ -142,7 +153,7 @@ pub struct CheckLocal {
|
||||
>,
|
||||
>,
|
||||
}
|
||||
#[derive(Clone, Default)]
|
||||
#[derive(Clone)]
|
||||
pub struct CheckLocalGlobalInfo {
|
||||
pub depth: usize,
|
||||
pub enable_hooks: bool,
|
||||
@@ -160,6 +171,8 @@ pub struct CheckLocalGlobalInfo {
|
||||
>,
|
||||
>,
|
||||
pub unused_try_statements: Arc<Mutex<Vec<(SourceRange, Vec<Option<SourceRange>>)>>>,
|
||||
pub object_fields: Arc<Mutex<HashMap<String, usize>>>,
|
||||
pub object_fields_rev: Arc<Mutex<Vec<String>>>,
|
||||
}
|
||||
impl CheckLocalGlobalInfo {
|
||||
pub fn show_warnings_to_stderr(&mut self) {
|
||||
@@ -171,6 +184,18 @@ impl CheckLocalGlobalInfo {
|
||||
eprintln!("{}", e.display(theme));
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn new(object_fields: Arc<Mutex<HashMap<String, usize>>>) -> Self {
|
||||
Self {
|
||||
depth: 0,
|
||||
enable_hooks: false,
|
||||
show_warnings: None,
|
||||
save_info_at: Default::default(),
|
||||
unused_try_statements: Default::default(),
|
||||
object_fields,
|
||||
object_fields_rev: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Debug for CheckLocalGlobalInfo {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
@@ -186,6 +211,13 @@ impl info::Local for RunLocal {
|
||||
type VariableIdentifier = usize;
|
||||
type VariableData = Arc<RwLock<Data>>;
|
||||
type Global = RunLocalGlobalInfo;
|
||||
fn neverused_global() -> Self::Global {
|
||||
Self::Global {
|
||||
limit_runtime: None,
|
||||
object_fields: Default::default(),
|
||||
object_fields_rev: Default::default(),
|
||||
}
|
||||
}
|
||||
fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) {
|
||||
let nothing = Arc::new(RwLock::new(Data::new(data::bool::Bool(false))));
|
||||
while self.vars.len() <= id {
|
||||
@@ -214,11 +246,28 @@ impl info::Local for RunLocal {
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
fn display_info<'a>(global: &'a Self::Global) -> DisplayInfo<'a> {
|
||||
DisplayInfo {
|
||||
object_fields: &global.object_fields,
|
||||
object_fields_rev: &global.object_fields_rev,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl info::Local for CheckLocal {
|
||||
type VariableIdentifier = usize;
|
||||
type VariableData = Type;
|
||||
type Global = CheckLocalGlobalInfo;
|
||||
fn neverused_global() -> Self::Global {
|
||||
Self::Global {
|
||||
depth: 0,
|
||||
enable_hooks: false,
|
||||
show_warnings: None,
|
||||
save_info_at: Default::default(),
|
||||
unused_try_statements: Default::default(),
|
||||
object_fields: Default::default(),
|
||||
object_fields_rev: Default::default(),
|
||||
}
|
||||
}
|
||||
fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) {
|
||||
while self.vars.len() <= id {
|
||||
self.vars.push(Type::empty());
|
||||
@@ -240,4 +289,10 @@ impl info::Local for CheckLocal {
|
||||
fn duplicate(&self) -> Self {
|
||||
self.clone()
|
||||
}
|
||||
fn display_info<'a>(global: &'a Self::Global) -> DisplayInfo<'a> {
|
||||
DisplayInfo {
|
||||
object_fields: &global.object_fields,
|
||||
object_fields_rev: &global.object_fields_rev,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
data::{self, object::ObjectT, Data, MersType, Type},
|
||||
data::{self, object::ObjectT, Data, Type},
|
||||
errors::{CheckError, EColor, SourceRange},
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ use super::MersStatement;
|
||||
#[derive(Debug)]
|
||||
pub struct Object {
|
||||
pub pos_in_src: SourceRange,
|
||||
pub elems: Vec<(String, Box<dyn MersStatement>)>,
|
||||
pub fields: Vec<(usize, Box<dyn MersStatement>)>,
|
||||
}
|
||||
impl MersStatement for Object {
|
||||
fn check_custom(
|
||||
@@ -18,75 +18,16 @@ impl MersStatement for Object {
|
||||
info: &mut super::CheckInfo,
|
||||
init_to: Option<&Type>,
|
||||
) -> Result<data::Type, super::CheckError> {
|
||||
let mut assign_types = if let Some(init_to) = init_to {
|
||||
let mut acc = (0..self.elems.len())
|
||||
.map(|_| Type::empty())
|
||||
.collect::<VecDeque<_>>();
|
||||
let mut init_fields = if let Some(init_to) = init_to {
|
||||
let print_is_part_of = init_to.types.len() > 1;
|
||||
let mut init_fields = HashMap::new();
|
||||
for t in init_to.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<ObjectT>() {
|
||||
if self.elems.len() == t.0.len() {
|
||||
for (i, ((sn, _), (tn, t))) in self.elems.iter().zip(t.0.iter()).enumerate()
|
||||
{
|
||||
if sn != tn {
|
||||
return Err(CheckError::new().msg(vec![
|
||||
("can't init an ".to_owned(), None),
|
||||
("object".to_owned(), Some(EColor::InitTo)),
|
||||
(" with type ".to_owned(), None),
|
||||
(t.simplified_as_string(info), Some(EColor::InitFrom)),
|
||||
if print_is_part_of {
|
||||
(", which is part of ".to_owned(), None)
|
||||
} else {
|
||||
(String::new(), None)
|
||||
},
|
||||
if print_is_part_of {
|
||||
(init_to.simplified_as_string(info), Some(EColor::InitFrom))
|
||||
} else {
|
||||
(String::new(), None)
|
||||
},
|
||||
(" - field mismatch: ".to_owned(), None),
|
||||
(sn.to_owned(), None),
|
||||
(" != ".to_owned(), None),
|
||||
(tn.to_owned(), None),
|
||||
]));
|
||||
}
|
||||
acc[i].add_all(&t);
|
||||
}
|
||||
} else {
|
||||
return Err(CheckError::new().msg(vec![
|
||||
("can't init an ".to_owned(), None),
|
||||
("object".to_owned(), Some(EColor::InitTo)),
|
||||
(" with type ".to_owned(), None),
|
||||
(t.simplified_as_string(info), Some(EColor::InitFrom)),
|
||||
if print_is_part_of {
|
||||
(", which is part of ".to_owned(), None)
|
||||
} else {
|
||||
(format!(""), None)
|
||||
},
|
||||
if print_is_part_of {
|
||||
(init_to.simplified_as_string(info), Some(EColor::InitFrom))
|
||||
} else {
|
||||
(format!(""), None)
|
||||
},
|
||||
(" - source has ".to_owned(), None),
|
||||
(if self.elems.len() > t.0.len() {
|
||||
format!("less fields ({}, not {})", t.0.len(), self.elems.len())
|
||||
} else {
|
||||
format!(
|
||||
"more fields. Either ignore those fields (`{}`) - or remove them from the type (`... := [{}] ...`)",
|
||||
t.0.iter()
|
||||
.skip(self.elems.len())
|
||||
.enumerate()
|
||||
.map(|(i, (n, _))| if i == 0 {
|
||||
format!("{n}: _")
|
||||
} else {
|
||||
format!(", {n}: _")
|
||||
})
|
||||
.collect::<String>(),
|
||||
data::object::ObjectT(t.0.iter().take(self.elems.len()).cloned().collect()).simplified_as_string(info)
|
||||
)
|
||||
}, None)
|
||||
]));
|
||||
for (field, t) in t.iter() {
|
||||
init_fields
|
||||
.entry(*field)
|
||||
.or_insert_with(Type::empty)
|
||||
.add_all(t);
|
||||
}
|
||||
} else {
|
||||
return Err(CheckError::new().msg(vec![
|
||||
@@ -111,20 +52,39 @@ impl MersStatement for Object {
|
||||
]));
|
||||
}
|
||||
}
|
||||
Some(acc)
|
||||
Some(init_fields)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Type::new(data::object::ObjectT(
|
||||
self.elems
|
||||
Ok(Type::new(data::object::ObjectT::new(
|
||||
self.fields
|
||||
.iter()
|
||||
.map(|(n, v)| -> Result<_, CheckError> {
|
||||
.map(|(field, v)| -> Result<_, CheckError> {
|
||||
Ok((
|
||||
n.clone(),
|
||||
*field,
|
||||
v.check(
|
||||
info,
|
||||
if let Some(it) = &mut assign_types {
|
||||
Some(it.pop_front().unwrap())
|
||||
if let Some(f) = &mut init_fields {
|
||||
Some(if let Some(s) = f.remove(field) {
|
||||
s
|
||||
} else {
|
||||
return Err(CheckError::new().msg(vec![
|
||||
("can't init an ".to_owned(), None),
|
||||
("object".to_owned(), Some(EColor::InitTo)),
|
||||
(" with type ".to_owned(), None),
|
||||
(
|
||||
init_to.as_ref().unwrap().simplified_as_string(info),
|
||||
Some(EColor::InitFrom),
|
||||
),
|
||||
(
|
||||
format!(
|
||||
" - field {} is missing",
|
||||
info.display_info().get_object_field_name(*field)
|
||||
),
|
||||
None,
|
||||
),
|
||||
]));
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -136,8 +96,8 @@ impl MersStatement for Object {
|
||||
)))
|
||||
}
|
||||
fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
|
||||
Ok(Data::new(data::object::Object(
|
||||
self.elems
|
||||
Ok(Data::new(data::object::Object::new(
|
||||
self.fields
|
||||
.iter()
|
||||
.map(|(n, s)| Ok::<_, CheckError>((n.clone(), s.run(info)?)))
|
||||
.collect::<Result<_, _>>()?,
|
||||
@@ -150,7 +110,7 @@ impl MersStatement for Object {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
self.elems.iter().map(|(_, s)| s.as_ref()).collect()
|
||||
self.fields.iter().map(|(_, s)| s.as_ref()).collect()
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
|
||||
@@ -66,7 +66,7 @@ impl MersStatement for Try {
|
||||
"try: #{} is not a function, type is {} within {}.",
|
||||
i + 1,
|
||||
ft.simplified_as_string(info),
|
||||
func.simplify_for_display(info),
|
||||
func.simplify_for_display(info).with_info(info),
|
||||
))
|
||||
.src(vec![
|
||||
(self.source_range(), None),
|
||||
|
||||
Reference in New Issue
Block a user