mirror of
https://github.com/Dummi26/mers.git
synced 2025-07-19 22:37:46 +02:00
improve .try resolving types, removes subtypes methods
Some checks failed
Rust / build (push) Has been cancelled
Some checks failed
Rust / build (push) Has been cancelled
This commit is contained in:
parent
ac6b405a3c
commit
35efae75ac
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mers"
|
||||
version = "0.9.22"
|
||||
version = "0.9.23"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "dynamically typed but type-checked programming language"
|
||||
@ -15,7 +15,7 @@ default = ["colored-output"]
|
||||
colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"]
|
||||
|
||||
[dependencies]
|
||||
mers_lib = "0.9.22"
|
||||
mers_lib = "0.9.23"
|
||||
# mers_lib = { path = "../mers_lib" }
|
||||
clap = { version = "4.3.19", features = ["derive"] }
|
||||
colored = { version = "2.1.0", optional = true }
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mers_lib"
|
||||
version = "0.9.22"
|
||||
version = "0.9.23"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "library to use the mers language in other projects"
|
||||
|
@ -61,8 +61,12 @@ impl MersType for TrueT {
|
||||
fn is_included_in(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
acc.add(Arc::new(self.clone()));
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
if self.is_included_in(remove) {
|
||||
Some(Type::empty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
@ -88,8 +92,12 @@ impl MersType for FalseT {
|
||||
fn is_included_in(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
acc.add(Arc::new(self.clone()));
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
if self.is_included_in(remove) {
|
||||
Some(Type::empty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::{any::Any, fmt::Display, sync::Arc};
|
||||
use std::{any::Any, fmt::Display};
|
||||
|
||||
use crate::info::DisplayInfo;
|
||||
|
||||
@ -51,8 +51,12 @@ impl MersType for ByteT {
|
||||
fn is_included_in(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
acc.add(Arc::new(self.clone()));
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
if self.is_included_in(remove) {
|
||||
Some(Type::empty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::{any::Any, fmt::Display, sync::Arc};
|
||||
use std::{any::Any, fmt::Display};
|
||||
|
||||
use crate::info::DisplayInfo;
|
||||
|
||||
@ -51,8 +51,12 @@ impl MersType for FloatT {
|
||||
fn is_included_in(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
acc.add(Arc::new(self.clone()));
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
if self.is_included_in(remove) {
|
||||
Some(Type::empty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
|
@ -7,6 +7,7 @@ use std::{
|
||||
use crate::{
|
||||
errors::CheckError,
|
||||
info::DisplayInfo,
|
||||
parsing::types::ParsedType,
|
||||
program::run::{CheckInfo, Info},
|
||||
};
|
||||
|
||||
@ -15,6 +16,8 @@ use super::{Data, MersData, MersType, Type};
|
||||
pub struct Function {
|
||||
pub info: Info,
|
||||
pub info_check: Arc<Mutex<CheckInfo>>,
|
||||
pub fixed_type: Option<Vec<(Vec<ParsedType>, Option<Vec<ParsedType>>)>>,
|
||||
pub fixed_type_out: Arc<Mutex<Option<Result<Arc<Vec<(Type, Type)>>, CheckError>>>>,
|
||||
pub out: Result<
|
||||
Arc<dyn Fn(&Type, &mut CheckInfo) -> Result<Type, CheckError> + Send + Sync>,
|
||||
Arc<Vec<(Type, Type)>>,
|
||||
@ -31,6 +34,8 @@ impl Clone for Function {
|
||||
Self {
|
||||
info: self.info.duplicate(),
|
||||
info_check: self.info_check.clone(),
|
||||
fixed_type: self.fixed_type.clone(),
|
||||
fixed_type_out: self.fixed_type_out.clone(),
|
||||
out: self.out.clone(),
|
||||
run: self.run.clone(),
|
||||
inner_statements: self.inner_statements.clone(),
|
||||
@ -45,6 +50,8 @@ impl Function {
|
||||
Self {
|
||||
info: crate::info::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(crate::info::Info::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Err(Arc::new(out)),
|
||||
run: Arc::new(run),
|
||||
inner_statements: None,
|
||||
@ -57,6 +64,8 @@ impl Function {
|
||||
Self {
|
||||
info: crate::info::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(crate::info::Info::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(move |a, i| out(a, i))),
|
||||
run: Arc::new(run),
|
||||
inner_statements: None,
|
||||
@ -66,6 +75,8 @@ impl Function {
|
||||
Self {
|
||||
info,
|
||||
info_check: Arc::clone(&self.info_check),
|
||||
fixed_type: self.fixed_type.clone(),
|
||||
fixed_type_out: self.fixed_type_out.clone(),
|
||||
out: self.out.clone(),
|
||||
run: Arc::clone(&self.run),
|
||||
inner_statements: self
|
||||
@ -75,11 +86,56 @@ impl Function {
|
||||
}
|
||||
}
|
||||
pub fn with_info_check(&self, check: CheckInfo) {
|
||||
if let Some(fixed_type) = &self.fixed_type {
|
||||
if let Ok(out_func) = &self.out {
|
||||
let mut nout = Ok(Vec::with_capacity(fixed_type.len()));
|
||||
for (in_type, out_type) in fixed_type {
|
||||
if let Ok(new_out) = &mut nout {
|
||||
let in_type = crate::parsing::types::type_from_parsed(in_type, &check)
|
||||
.expect("failed to get intype from parsed type");
|
||||
let out_type_want = out_type.as_ref().map(|out_type| {
|
||||
crate::parsing::types::type_from_parsed(out_type, &check)
|
||||
.expect("failed to get intype from parsed type")
|
||||
});
|
||||
let mut out_type = match out_func(&in_type, &mut check.clone()) {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
nout = Err(e);
|
||||
break;
|
||||
}
|
||||
};
|
||||
if let Some(out_type_want) = out_type_want {
|
||||
if out_type.is_included_in(&out_type_want) {
|
||||
out_type = out_type_want;
|
||||
} else {
|
||||
nout = Err(format!(
|
||||
"function must return {} for input {} because of its definition, but it returns {}.",
|
||||
out_type_want.with_info(&check),
|
||||
in_type.with_info(&check),
|
||||
out_type.with_info(&check),
|
||||
)
|
||||
.into());
|
||||
break;
|
||||
}
|
||||
}
|
||||
new_out.push((in_type, out_type));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*self.fixed_type_out.lock().unwrap() = Some(nout.map(Arc::new));
|
||||
}
|
||||
}
|
||||
*self.info_check.lock().unwrap() = check;
|
||||
}
|
||||
pub fn check(&self, arg: &Type) -> Result<Type, CheckError> {
|
||||
// TODO: this should require a CheckInfo and call `with_info_check`.
|
||||
self.get_as_type().o(arg)
|
||||
}
|
||||
pub fn check_try(&self, arg: &Type) -> Result<Type, (CheckError, Vec<(Type, Type)>)> {
|
||||
// TODO: this should require a CheckInfo and call `with_info_check`.
|
||||
self.get_as_type().o_try(arg)
|
||||
}
|
||||
pub fn run_mut(
|
||||
&mut self,
|
||||
arg: Data,
|
||||
@ -102,6 +158,19 @@ impl Function {
|
||||
}
|
||||
pub fn get_as_type(&self) -> FunctionT {
|
||||
let info = self.info_check.lock().unwrap().clone();
|
||||
if self.fixed_type.is_some() {
|
||||
match &*self.fixed_type_out.lock().unwrap() {
|
||||
Some(Ok(types)) => return FunctionT(Err(types.clone()), info),
|
||||
Some(Err(e)) => {
|
||||
let e = e.clone();
|
||||
return FunctionT(
|
||||
Ok(Arc::new(move |_, _| Err(e.clone()))),
|
||||
crate::info::Info::neverused(),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
match &self.out {
|
||||
Ok(out) => {
|
||||
let out = Arc::clone(out);
|
||||
@ -189,13 +258,26 @@ pub struct FunctionT(
|
||||
impl FunctionT {
|
||||
/// get output type
|
||||
pub fn o(&self, i: &Type) -> Result<Type, CheckError> {
|
||||
self.o_try(i).map_err(|(e, _)| e)
|
||||
}
|
||||
/// get output type
|
||||
pub fn o_try(&self, i: &Type) -> Result<Type, (CheckError, Vec<(Type, Type)>)> {
|
||||
match &self.0 {
|
||||
Ok(f) => f(i, &self.1),
|
||||
Ok(f) => f(i, &self.1).map_err(|e| (e, vec![])),
|
||||
Err(v) => v
|
||||
.iter()
|
||||
.find(|(a, _)| i.is_included_in(a))
|
||||
.map(|(_, o)| o.clone())
|
||||
.ok_or_else(|| format!("This function, which was defined with an explicit type, cannot be called with an argument of type {}.", i.with_info(&self.1)).into()),
|
||||
.ok_or_else(||
|
||||
(
|
||||
format!("This function, which was defined with an explicit type, cannot be called with an argument of type {}.", i.with_info(&self.1)).into(),
|
||||
v.iter()
|
||||
.filter(|(a, _)| i.types.iter().any(|i| a.types.iter().any(|a|
|
||||
i.without(a.as_ref()).is_some())))
|
||||
.map(|(a, o)| (a.clone(), o.clone()))
|
||||
.collect()
|
||||
)
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -280,8 +362,12 @@ impl MersType for FunctionT {
|
||||
false
|
||||
}
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
acc.add(Arc::new(self.clone()));
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
if self.is_included_in(remove) {
|
||||
Some(Type::empty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
|
@ -96,27 +96,35 @@ impl MersType for IntT {
|
||||
false
|
||||
}
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
// INT_MIN .. INT32U_MIN .. INT32S_MIN .. -128 .. -1 .. 0 .. 1 .. 127 .. 255 .. 65535 .. INT32S_MAX .. INT32U_MAX .. INT_MAX
|
||||
let mut add_range = |min, max| {
|
||||
// the range is non-empty, self starts before or where the range ends, and self ends after or where the range starts.
|
||||
if min <= max && self.0 <= max && min <= self.1 {
|
||||
acc.add(Arc::new(IntT(self.0.max(min), self.1.min(max))));
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
if self.is_included_in(remove) {
|
||||
Some(Type::empty())
|
||||
} else if let Some(remove) = remove.as_any().downcast_ref::<Self>() {
|
||||
if remove.0 <= self.0 && self.1 <= remove.1 {
|
||||
Some(Type::empty())
|
||||
} else if remove.0 <= self.0 && self.0 <= remove.1 && remove.1 <= self.1 {
|
||||
if remove.1 + 1 <= self.1 {
|
||||
Some(Type::new(Self(remove.1 + 1, self.1)))
|
||||
} else {
|
||||
Some(Type::empty())
|
||||
}
|
||||
} else if self.0 <= remove.0 && remove.0 <= self.1 && self.1 <= remove.1 {
|
||||
if self.0 <= remove.0 + 1 {
|
||||
Some(Type::new(Self(self.0, remove.0 - 1)))
|
||||
} else {
|
||||
Some(Type::empty())
|
||||
}
|
||||
} else if self.0 < remove.0 && remove.0 <= remove.1 && remove.1 < self.1 {
|
||||
Some(Type::newm(vec![
|
||||
Arc::new(Self(self.0, remove.0 - 1)),
|
||||
Arc::new(Self(remove.1 + 1, self.1)),
|
||||
]))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
add_range(INT_MIN, INT32U_MIN.saturating_sub(1));
|
||||
add_range(INT32U_MIN, INT32S_MIN.saturating_sub(1));
|
||||
add_range(INT32S_MIN, -129);
|
||||
add_range(-128, -2);
|
||||
add_range(-1, -1);
|
||||
add_range(0, 0);
|
||||
add_range(1, 1);
|
||||
add_range(2, 127);
|
||||
add_range(128, 255);
|
||||
add_range(256, 65535);
|
||||
add_range(65536, INT32S_MAX);
|
||||
add_range(INT32S_MAX.saturating_add(1), INT32U_MAX);
|
||||
add_range(INT32U_MAX.saturating_add(1), INT_MAX);
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
|
@ -142,20 +142,10 @@ pub trait MersType: Any + Debug + Send + Sync {
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool;
|
||||
/// This doesn't handle the case where target is Type (Type::is_included_in handles it)
|
||||
fn is_included_in(&self, target: &dyn MersType) -> bool;
|
||||
/// Returns all types that can result from the use of this type.
|
||||
/// Usually, this is just `acc.add(Arc::new(self.clone()))`
|
||||
/// but if there exists one or more inner types, this becomes interesting:
|
||||
/// Using `(int/string)` will end up being either `(int)` or `(string)`,
|
||||
/// so this function should add `(int)` and `(string)`.
|
||||
/// Since `(int/string)` can't exist at runtime, we don't need to list `self`.
|
||||
/// note also: `subtypes` has to be called recursively, i.e. you would have to call `.substring` on `int` and `string`.
|
||||
fn subtypes(&self, acc: &mut Type);
|
||||
/// like `subtypes`, but returns the accumulator
|
||||
fn subtypes_type(&self) -> Type {
|
||||
let mut acc = Type::empty();
|
||||
self.subtypes(&mut acc);
|
||||
acc
|
||||
}
|
||||
/// Returns `self` with `remove` removed, if it is different from `self`.
|
||||
/// This must, at least, return `Some(Type::empty())` if `self.is_included_in(remove)`.
|
||||
/// For example, `(Int<1..9>).remove(Int<4..6>)` would return `Some(Int<1..3>/Int<7..9>)`.
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type>;
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn mut_any(&mut self) -> &mut dyn Any;
|
||||
fn to_any(self) -> Box<dyn Any>;
|
||||
@ -189,8 +179,8 @@ impl MersType for TypeWithOnlyName {
|
||||
fn is_included_in(&self, _target: &dyn MersType) -> bool {
|
||||
false
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
acc.add(Arc::new(self.clone()))
|
||||
fn without(&self, _remove: &dyn MersType) -> Option<Type> {
|
||||
None
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
@ -478,6 +468,29 @@ impl Type {
|
||||
self.add(Arc::clone(t));
|
||||
}
|
||||
}
|
||||
pub fn without_in_place(&mut self, remove: &dyn MersType) {
|
||||
let mut rm = vec![];
|
||||
let mut add = vec![];
|
||||
for (i, t) in self.types.iter_mut().enumerate() {
|
||||
if t.is_included_in(remove) {
|
||||
rm.push(i);
|
||||
} else if let Some(without) = t.without(remove) {
|
||||
rm.push(i);
|
||||
add.push(without);
|
||||
}
|
||||
}
|
||||
for i in rm.into_iter().rev() {
|
||||
self.types.swap_remove(i);
|
||||
}
|
||||
for t in add {
|
||||
self.add_all(&t);
|
||||
}
|
||||
}
|
||||
pub fn without_in_place_all(&mut self, remove: &Self) {
|
||||
for t in &remove.types {
|
||||
self.without_in_place(t.as_ref());
|
||||
}
|
||||
}
|
||||
pub fn dereference(&self) -> Option<Self> {
|
||||
let mut o = Self::empty();
|
||||
for t in &self.types {
|
||||
@ -514,17 +527,6 @@ impl Type {
|
||||
pub fn is_included_in_single(&self, target: &dyn MersType) -> bool {
|
||||
self.types.iter().all(|s| s.is_included_in(target))
|
||||
}
|
||||
pub fn subtypes(&self, acc: &mut Type) {
|
||||
for t in &self.types {
|
||||
t.subtypes(acc);
|
||||
}
|
||||
}
|
||||
pub fn subtypes_type(&self) -> Type {
|
||||
let mut acc = Type::empty();
|
||||
acc.smart_type_simplification = false;
|
||||
self.subtypes(&mut acc);
|
||||
acc
|
||||
}
|
||||
pub fn iterable(&self) -> Option<Type> {
|
||||
let mut o = Self::empty();
|
||||
for t in self.types.iter() {
|
||||
|
@ -128,8 +128,62 @@ impl MersType for ObjectT {
|
||||
})
|
||||
})
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
self.gen_subtypes_recursively(acc, &mut Vec::with_capacity(self.len()));
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
let m = self.0.len();
|
||||
if let Some(remove) = remove
|
||||
.as_any()
|
||||
.downcast_ref::<Self>()
|
||||
.filter(|r| r.0.len() <= m)
|
||||
{
|
||||
let mut out = Type::empty();
|
||||
for i1 in 0usize.. {
|
||||
let mut self_tuple = Vec::with_capacity(m);
|
||||
let mut i1 = i1;
|
||||
for j in 0..m {
|
||||
let mm = self.0[j].1.types.len();
|
||||
self_tuple.push((self.0[j].0, &self.0[j].1.types[i1 % mm]));
|
||||
i1 /= mm;
|
||||
}
|
||||
if i1 != 0 {
|
||||
break;
|
||||
}
|
||||
let mut covered = false;
|
||||
for i2 in 0usize.. {
|
||||
let mut remove_tuple = Vec::with_capacity(m);
|
||||
let mut i2 = i2;
|
||||
for j in 0..remove.0.len() {
|
||||
let mm = remove.0[j].1.types.len();
|
||||
remove_tuple.push((remove.0[j].0, &remove.0[j].1.types[i2 % mm]));
|
||||
i2 /= mm;
|
||||
}
|
||||
if i2 != 0 {
|
||||
break;
|
||||
}
|
||||
if (0..m).all(|j| {
|
||||
remove_tuple
|
||||
.iter()
|
||||
.find(|(v, _)| *v == self_tuple[j].0)
|
||||
.is_none_or(|(_, r)| {
|
||||
self_tuple[j].1.as_ref().is_included_in(r.as_ref())
|
||||
})
|
||||
}) {
|
||||
covered = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !covered {
|
||||
out.add(Arc::new(Self(
|
||||
self_tuple
|
||||
.iter()
|
||||
.map(|(vi, v)| (*vi, Type::newm(vec![Arc::clone(v)])))
|
||||
.collect(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
Some(out)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
@ -150,30 +204,6 @@ impl MersType for ObjectT {
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectT {
|
||||
pub fn gen_subtypes_recursively(
|
||||
&self,
|
||||
acc: &mut Type,
|
||||
types: &mut Vec<(usize, Arc<dyn MersType>)>,
|
||||
) {
|
||||
if types.len() >= self.len() {
|
||||
let nt = Self(
|
||||
types
|
||||
.iter()
|
||||
.map(|(s, v)| (s.clone(), Type::newm(vec![Arc::clone(v)])))
|
||||
.collect(),
|
||||
);
|
||||
acc.add(Arc::new(nt));
|
||||
} else {
|
||||
for t in self.0[types.len()].1.subtypes_type().types {
|
||||
types.push((self.0[types.len()].0.clone(), t));
|
||||
self.gen_subtypes_recursively(acc, types);
|
||||
types.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ObjectFieldsMap {
|
||||
fn get_or_add_field(&self, field: &str) -> usize;
|
||||
}
|
||||
|
@ -155,16 +155,11 @@ impl MersType for ReferenceT {
|
||||
// &int isn't included in &(int/float), otherwise we could assign a float to it
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
// // we don't call subtypes because (int/string) must stay that so we can assign either
|
||||
// // NOTE: this might not be right...?
|
||||
// acc.add(Arc::new(self.clone()));
|
||||
// FOR NOW (until we can put the compile-time type in ReferenceT), add all these types, too
|
||||
// TODO: Figure out how to fix
|
||||
// x := if true 1 else 0.5
|
||||
// &x.debug // prints &Int instead of &{Int/Float} at runtime :(
|
||||
for t in self.0.subtypes_type().types {
|
||||
acc.add(Arc::new(Self(Type::newm(vec![t]))));
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
if self.is_included_in(remove) {
|
||||
Some(Type::empty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::{any::Any, fmt::Display, sync::Arc};
|
||||
use std::{any::Any, fmt::Display};
|
||||
|
||||
use crate::info::DisplayInfo;
|
||||
|
||||
@ -51,8 +51,12 @@ impl MersType for StringT {
|
||||
fn is_included_in(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
acc.add(Arc::new(self.clone()));
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
if self.is_included_in(remove) {
|
||||
Some(Type::empty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
|
@ -107,8 +107,59 @@ impl MersType for TupleT {
|
||||
false
|
||||
}
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
self.gen_subtypes_recursively(acc, &mut Vec::with_capacity(self.0.len()));
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
let m = self.0.len();
|
||||
if let Some(remove) = remove
|
||||
.as_any()
|
||||
.downcast_ref::<Self>()
|
||||
.filter(|r| r.0.len() == m)
|
||||
{
|
||||
let mut out = Type::empty();
|
||||
for i1 in 0usize.. {
|
||||
let mut self_tuple = Vec::with_capacity(m);
|
||||
let mut i1 = i1;
|
||||
for j in 0..m {
|
||||
let mm = self.0[j].types.len();
|
||||
self_tuple.push(&self.0[j].types[i1 % mm]);
|
||||
i1 /= mm;
|
||||
}
|
||||
if i1 != 0 {
|
||||
break;
|
||||
}
|
||||
let mut covered = false;
|
||||
for i2 in 0usize.. {
|
||||
let mut remove_tuple = Vec::with_capacity(m);
|
||||
let mut i2 = i2;
|
||||
for j in 0..m {
|
||||
let mm = remove.0[j].types.len();
|
||||
remove_tuple.push(&remove.0[j].types[i2 % mm]);
|
||||
i2 /= mm;
|
||||
}
|
||||
if i2 != 0 {
|
||||
break;
|
||||
}
|
||||
if (0..m).all(|j| {
|
||||
self_tuple[j]
|
||||
.as_ref()
|
||||
.is_included_in(remove_tuple[j].as_ref())
|
||||
}) {
|
||||
covered = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !covered {
|
||||
out.add(Arc::new(Self(
|
||||
self_tuple
|
||||
.iter()
|
||||
.map(|v| Type::newm(vec![Arc::clone(v)]))
|
||||
.collect(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
Some(out)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
@ -128,23 +179,3 @@ impl MersType for TupleT {
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl TupleT {
|
||||
pub fn gen_subtypes_recursively(&self, acc: &mut Type, types: &mut Vec<Arc<dyn MersType>>) {
|
||||
if types.len() >= self.0.len() {
|
||||
let nt = Self(
|
||||
types
|
||||
.iter()
|
||||
.map(|v| Type::newm(vec![Arc::clone(v)]))
|
||||
.collect(),
|
||||
);
|
||||
acc.add(Arc::new(nt));
|
||||
} else {
|
||||
for t in self.0[types.len()].subtypes_type().types {
|
||||
types.push(t);
|
||||
self.gen_subtypes_recursively(acc, types);
|
||||
types.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +114,68 @@ pub fn parse(
|
||||
let mut pos_after_first = src.get_pos();
|
||||
loop {
|
||||
src.skip_whitespace();
|
||||
// check for `arg [types] -> expr` function syntax
|
||||
if let Some('[') = src.peek_char() {
|
||||
let reset_no_func_pos = src.get_pos();
|
||||
let _ = src.next_char();
|
||||
let mut fixed_type = Vec::new();
|
||||
loop {
|
||||
src.skip_whitespace();
|
||||
if let Ok(ty) = super::types::parse_type(src, srca) {
|
||||
src.skip_whitespace();
|
||||
if src.peek_word() == "->" {
|
||||
src.next_word();
|
||||
if let Ok(ot) = super::types::parse_type(src, srca) {
|
||||
fixed_type.push((ty, Some(ot)));
|
||||
} else {
|
||||
fixed_type.clear();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fixed_type.push((ty, None));
|
||||
}
|
||||
} else {
|
||||
fixed_type.clear();
|
||||
break;
|
||||
}
|
||||
src.skip_whitespace();
|
||||
match src.next_char() {
|
||||
Some(']') => break,
|
||||
Some(',') => continue,
|
||||
_ => {
|
||||
fixed_type.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if fixed_type.is_empty() {
|
||||
src.set_pos(reset_no_func_pos);
|
||||
} else {
|
||||
src.skip_whitespace();
|
||||
let pos_in_src = src.get_pos();
|
||||
if src.next_word() != "->" {
|
||||
src.set_pos(reset_no_func_pos);
|
||||
} else {
|
||||
src.skip_whitespace();
|
||||
let run = match parse(src, srca) {
|
||||
Ok(Some(v)) => v,
|
||||
Ok(None) => {
|
||||
return Err(CheckError::new()
|
||||
.src(vec![((pos_in_src, src.get_pos(), srca).into(), None)])
|
||||
.msg_str(format!("EOF after `->`")))
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
first = Box::new(program::parsed::function::Function {
|
||||
pos_in_src: (first.source_range().start(), src.get_pos(), srca).into(),
|
||||
arg: first,
|
||||
run,
|
||||
fixed_type: Some(fixed_type),
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
match src.peek_word_allow_colon() {
|
||||
":=" => {
|
||||
let pos_in_src = src.get_pos();
|
||||
@ -164,6 +226,7 @@ pub fn parse(
|
||||
pos_in_src: (first.source_range().start(), src.get_pos(), srca).into(),
|
||||
arg: first,
|
||||
run,
|
||||
fixed_type: None,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ pub fn to_mers_func(
|
||||
data::function::Function {
|
||||
info: Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(Info::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(move |a, i| out(a, i))),
|
||||
run: Arc::new(move |a, i| run(a, i)),
|
||||
inner_statements: None,
|
||||
|
@ -30,6 +30,8 @@ impl Config {
|
||||
.add_var("lock_update", data::function::Function {
|
||||
info: Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
for t in a.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
@ -95,6 +97,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
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() {
|
||||
@ -122,6 +126,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
for t in &a.types {
|
||||
if t.iterable().is_none() {
|
||||
@ -158,6 +164,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, _i| Ok(Type::new(data::reference::ReferenceT(a.clone()))))),
|
||||
run: Arc::new(|a, _i| {
|
||||
Ok(Data::new(data::reference::Reference(Arc::new(RwLock::new(a.clone())))))
|
||||
@ -170,6 +178,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
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| {
|
||||
|
@ -34,6 +34,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
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![
|
||||
@ -89,6 +91,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
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![
|
||||
@ -133,6 +137,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.is_included_in_single(&ChildProcessT) {
|
||||
Ok(Type::newm(vec![
|
||||
@ -161,6 +167,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.is_included_in_single(&ChildProcessT) {
|
||||
Ok(Type::newm(vec![
|
||||
@ -195,6 +203,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
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())
|
||||
@ -224,6 +234,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
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())
|
||||
@ -253,6 +265,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.is_included_in_single(&ChildProcessT) {
|
||||
Ok(Type::newm(vec![
|
||||
@ -282,6 +296,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.is_included_in_single(&ChildProcessT) {
|
||||
Ok(Type::newm(vec![
|
||||
@ -311,6 +327,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.is_included_in_single(&ChildProcessT) {
|
||||
Ok(Type::newm(vec![
|
||||
@ -340,6 +358,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new( CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if a.is_included_in_single(&ChildProcessT) {
|
||||
Ok(Type::newm(vec![
|
||||
@ -431,8 +451,12 @@ impl MersType for ChildProcessT {
|
||||
fn is_included_in(&self, target: &dyn MersType) -> bool {
|
||||
target.as_any().is::<Self>()
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
acc.add(Arc::new(self.clone()));
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
if self.is_included_in(remove) {
|
||||
Some(Type::empty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
|
@ -15,6 +15,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
let mut out = Type::empty();
|
||||
for a in a.types.iter() {
|
||||
|
@ -144,6 +144,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
for a in &a.types {
|
||||
if let Some(tuple) = a.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
@ -229,6 +231,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
let data = if let Some(a) = a.iterable() {
|
||||
a
|
||||
@ -246,6 +250,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
let data = if let Some(a) = a.iterable() {
|
||||
a
|
||||
@ -301,6 +307,8 @@ fn genfunc_iter_and_func(
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
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>() {
|
||||
@ -359,6 +367,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())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(move |a, i| {
|
||||
iter_out_arg(a, i, name, |f: &T| ft(f), type_sample)
|
||||
})),
|
||||
@ -607,13 +617,16 @@ impl MersType for IterT {
|
||||
false
|
||||
}
|
||||
}
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
if self.is_included_in(remove) {
|
||||
Some(Type::empty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn iterable(&self) -> Option<Type> {
|
||||
Some(self.2.clone())
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
// NOTE: This might not be good enough
|
||||
acc.add(Arc::new(self.clone()));
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
@ -655,6 +668,8 @@ fn genfunc_iter_in_val_out(
|
||||
Function {
|
||||
info: crate::info::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(crate::info::Info::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(move |a, i| {
|
||||
if let Some(iter_over) = a.iterable() {
|
||||
if iter_over.is_included_in(&iter_type) {
|
||||
@ -748,8 +763,12 @@ impl MersType for RangeT {
|
||||
self.is_empty() || (!target.is_empty() && self.0 >= target.0 && self.1 <= target.1)
|
||||
})
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
acc.add(Arc::new(Clone::clone(self)))
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
if self.is_included_in(remove) {
|
||||
Some(Type::empty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
|
@ -37,6 +37,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if let Some(a) = a.dereference() {
|
||||
let mut out = Type::empty();
|
||||
@ -85,6 +87,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
for t in a.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
@ -148,6 +152,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
for t in a.types.iter() {
|
||||
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
|
||||
@ -221,6 +227,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
let mut o = Type::empty();
|
||||
for t in a.types.iter() {
|
||||
@ -298,6 +306,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
let mut o = Type::empty();
|
||||
for t in a.types.iter() {
|
||||
@ -369,6 +379,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
if let Some(v) = a.iterable() {
|
||||
Ok(Type::new(ListT(v)))
|
||||
@ -464,12 +476,11 @@ impl MersType for ListT {
|
||||
.downcast_ref::<Self>()
|
||||
.is_some_and(|v| self.0.is_included_in(&v.0))
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
// The type of an empty list is a list where the items are `<unreachable>`
|
||||
acc.add(Arc::new(Self(Type::empty())));
|
||||
// All possible list types
|
||||
for t in self.0.subtypes_type().types {
|
||||
acc.add(Arc::new(Self(Type::newm(vec![t]))));
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
if self.is_included_in(remove) {
|
||||
Some(Type::empty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
|
@ -33,6 +33,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, _i| {
|
||||
let mut out = Type::empty();
|
||||
for t in a.types.iter() {
|
||||
@ -59,6 +61,8 @@ impl Config {
|
||||
.add_var("thread_finished", data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
for t in a.types.iter() {
|
||||
if !t.as_any().is::<ThreadT>() {
|
||||
@ -80,6 +84,8 @@ impl Config {
|
||||
.add_var("thread_await", data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, i| {
|
||||
let mut out = Type::empty();
|
||||
for t in a.types.iter() {
|
||||
@ -162,9 +168,11 @@ impl MersType for ThreadT {
|
||||
false
|
||||
}
|
||||
}
|
||||
fn subtypes(&self, acc: &mut Type) {
|
||||
for t in self.0.subtypes_type().types {
|
||||
acc.add(Arc::new(Self(Type::newm(vec![t]))));
|
||||
fn without(&self, remove: &dyn MersType) -> Option<Type> {
|
||||
if self.is_included_in(remove) {
|
||||
Some(Type::empty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
|
@ -91,6 +91,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|a, _i| Ok(a.clone()))),
|
||||
run: Arc::new(|a, i| {
|
||||
let a2 = a.get();
|
||||
@ -114,6 +116,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
|
||||
run: Arc::new(|a, i| {
|
||||
if let Some((_, stderr)) = &mut *i.global.stdout.lock().unwrap() {
|
||||
@ -133,6 +137,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
|
||||
run: Arc::new(|a, i| {
|
||||
if let Some((_, stderr)) = &mut *i.global.stdout.lock().unwrap() {
|
||||
@ -151,6 +157,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
|
||||
run: Arc::new(|a, i| {
|
||||
if let Some((stdout, _)) = &mut *i.global.stdout.lock().unwrap() {
|
||||
@ -170,6 +178,8 @@ impl Config {
|
||||
data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(|_a, _i| Ok(Type::empty_tuple()))),
|
||||
run: Arc::new(|a, i| {
|
||||
if let Some((stdout, _)) = &mut *i.global.stdout.lock().unwrap() {
|
||||
|
@ -3,6 +3,7 @@ use std::sync::{Arc, Mutex};
|
||||
use crate::{
|
||||
data,
|
||||
errors::{CheckError, SourceRange},
|
||||
parsing::types::ParsedType,
|
||||
program::{self, run::CheckInfo},
|
||||
};
|
||||
|
||||
@ -13,6 +14,7 @@ pub struct Function {
|
||||
pub pos_in_src: SourceRange,
|
||||
pub arg: Box<dyn MersStatement>,
|
||||
pub run: Box<dyn MersStatement>,
|
||||
pub fixed_type: Option<Vec<(Vec<ParsedType>, Option<Vec<ParsedType>>)>>,
|
||||
}
|
||||
|
||||
impl MersStatement for Function {
|
||||
@ -38,6 +40,8 @@ impl MersStatement for Function {
|
||||
func_no_info: data::function::Function {
|
||||
info: program::run::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
fixed_type: self.fixed_type.clone(),
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(move |a, i| {
|
||||
arg2.check(i, Some(a))?;
|
||||
Ok(run2.check(i, None)?)
|
||||
|
@ -56,6 +56,8 @@ impl MersStatement for IncludeMers {
|
||||
func_no_info: data::function::Function {
|
||||
info: info::Info::neverused(),
|
||||
info_check: Arc::new(Mutex::new(info::Info::neverused())),
|
||||
fixed_type: None,
|
||||
fixed_type_out: Arc::new(Mutex::new(None)),
|
||||
out: Ok(Arc::new(move |_, i| {
|
||||
compiled.check(&mut i.duplicate(), None)
|
||||
})),
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::{
|
||||
data::{self, Data, Type},
|
||||
@ -25,7 +25,7 @@ impl MersStatement for Try {
|
||||
return Err("can't init to statement type Try".to_string().into());
|
||||
}
|
||||
let mut t = Type::empty();
|
||||
let arg = self.arg.check(info, init_to)?;
|
||||
let mut arg = self.arg.check(info, init_to)?;
|
||||
let funcs = self
|
||||
.funcs
|
||||
.iter()
|
||||
@ -46,62 +46,75 @@ impl MersStatement for Try {
|
||||
};
|
||||
drop(unused_try_statements_lock);
|
||||
drop(index_lock);
|
||||
for arg in arg.subtypes_type().types.iter() {
|
||||
let mut found = false;
|
||||
let mut errs = vec![];
|
||||
for (i, func) in funcs.iter().enumerate() {
|
||||
let mut func_res = Type::empty();
|
||||
let mut func_err = None;
|
||||
for ft in func.types.iter() {
|
||||
if let Some(ft) = ft.executable() {
|
||||
match ft.o(&Type::newm(vec![Arc::clone(arg)])) {
|
||||
Ok(res) => {
|
||||
func_res.add_all(&res);
|
||||
}
|
||||
Err(e) => func_err = Some(e),
|
||||
'func_options: for (i, func) in funcs.iter().enumerate() {
|
||||
// TODO! handle the case where a function is a one-of-multiple type...
|
||||
if func.types.len() != 1 {
|
||||
return Err(format!(
|
||||
"Try-statement requires clearly defined functions, but got type {}",
|
||||
func.with_info(info)
|
||||
)
|
||||
.into());
|
||||
}
|
||||
for ft in func.types.iter() {
|
||||
if let Some(ft) = ft.executable() {
|
||||
let using_func = |t: &mut Type, func_res: &Type| {
|
||||
// found the function to use
|
||||
info.global.unused_try_statements.lock().unwrap()[my_index].1[i] = None;
|
||||
t.add_all(func_res);
|
||||
};
|
||||
match ft.o_try(&arg) {
|
||||
Ok(res) => {
|
||||
using_func(&mut t, &res);
|
||||
arg = Type::empty();
|
||||
break 'func_options;
|
||||
}
|
||||
Err((_, covered)) => {
|
||||
for (t_in, t_out) in &covered {
|
||||
arg.without_in_place_all(t_in);
|
||||
using_func(&mut t, t_out);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(CheckError::new()
|
||||
.msg_str(format!(
|
||||
"try: #{} is not a function, type is {} within {}.",
|
||||
i + 1,
|
||||
ft.simplified_as_string(info),
|
||||
func.simplify_for_display(info).with_info(info),
|
||||
))
|
||||
.src(vec![
|
||||
(self.source_range(), None),
|
||||
(self.funcs[i].source_range(), Some(EColor::TryNotAFunction)),
|
||||
]));
|
||||
}
|
||||
}
|
||||
if let Some(err) = func_err {
|
||||
// can't use this function for this argument
|
||||
errs.push(err);
|
||||
} else {
|
||||
// found the function to use
|
||||
info.global.unused_try_statements.lock().unwrap()[my_index].1[i] = None;
|
||||
found = true;
|
||||
t.add_all(&func_res);
|
||||
break;
|
||||
return Err(CheckError::new()
|
||||
.msg_str(format!(
|
||||
"try: #{} is not a function, type is {} within {}.",
|
||||
i + 1,
|
||||
ft.simplified_as_string(info),
|
||||
func.simplify_for_display(info).with_info(info),
|
||||
))
|
||||
.src(vec![
|
||||
(self.source_range(), None),
|
||||
(self.funcs[i].source_range(), Some(EColor::TryNotAFunction)),
|
||||
]));
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
let mut err = CheckError::new()
|
||||
.msg_str(format!(
|
||||
"try: no function found for argument of type {}.",
|
||||
arg.simplified_as_string(info)
|
||||
))
|
||||
.src(vec![(
|
||||
self.pos_in_src.clone(),
|
||||
Some(EColor::TryNoFunctionFound),
|
||||
)]);
|
||||
for (i, e) in errs.into_iter().enumerate() {
|
||||
err = err
|
||||
.msg_str(format!("Error for function #{}:", i + 1))
|
||||
.err(e);
|
||||
}
|
||||
if !arg.types.is_empty() {
|
||||
let mut err = CheckError::new()
|
||||
.msg_str(format!(
|
||||
"try: uncovered argument type {}.",
|
||||
arg.simplified_as_string(info)
|
||||
))
|
||||
.src(vec![(
|
||||
self.pos_in_src.clone(),
|
||||
Some(EColor::TryNoFunctionFound),
|
||||
)]);
|
||||
for (i, func) in funcs.iter().enumerate() {
|
||||
err = err.msg_str(format!(
|
||||
"Error for function #{} {}:",
|
||||
i + 1,
|
||||
func.with_info(info)
|
||||
));
|
||||
for e in func
|
||||
.types
|
||||
.iter()
|
||||
.filter_map(|t| t.executable().unwrap().o(&arg).err())
|
||||
{
|
||||
err = err.err(e);
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
Ok(t)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user