replace Bool type with Bool=True/False + bugfix

Bool is a type alias for True/False

Bugfix:

[[T] String]
{
  [[T] Int]
  // this would use the outer T (String),
  // but now it correctly uses the inner T (Int).
  [T] 1
}
This commit is contained in:
Mark 2024-08-29 15:04:32 +02:00
parent 7f318d9e1c
commit 385019e43c
11 changed files with 81 additions and 76 deletions

View File

@ -15,7 +15,7 @@ default = ["colored-output"]
colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"] colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"]
[dependencies] [dependencies]
mers_lib = "0.9.1" # mers_lib = "0.9.1"
# mers_lib = { path = "../mers_lib" } mers_lib = { path = "../mers_lib" }
clap = { version = "4.3.19", features = ["derive"] } clap = { version = "4.3.19", features = ["derive"] }
colored = { version = "2.1.0", optional = true } colored = { version = "2.1.0", optional = true }

View File

@ -17,7 +17,11 @@ impl MersData for Bool {
Box::new(Clone::clone(self)) Box::new(Clone::clone(self))
} }
fn as_type(&self) -> super::Type { fn as_type(&self) -> super::Type {
Type::new(BoolT) if self.0 {
Type::new(TrueT)
} else {
Type::new(FalseT)
}
} }
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
@ -31,8 +35,34 @@ impl MersData for Bool {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct BoolT; pub struct TrueT;
impl MersType for BoolT { #[derive(Debug, Clone)]
pub struct FalseT;
/// Returns the type `True/False`.
pub fn bool_type() -> Type {
Type::newm(vec![Arc::new(TrueT), Arc::new(FalseT)])
}
impl MersType for TrueT {
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
other.as_any().downcast_ref::<Self>().is_some()
}
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 as_any(&self) -> &dyn Any {
self
}
fn mut_any(&mut self) -> &mut dyn Any {
self
}
fn to_any(self) -> Box<dyn Any> {
Box::new(self)
}
}
impl MersType for FalseT {
fn is_same_type_as(&self, other: &dyn MersType) -> bool { fn is_same_type_as(&self, other: &dyn MersType) -> bool {
other.as_any().downcast_ref::<Self>().is_some() other.as_any().downcast_ref::<Self>().is_some()
} }
@ -58,8 +88,13 @@ impl Display for Bool {
write!(f, "{}", self.0) write!(f, "{}", self.0)
} }
} }
impl Display for BoolT { impl Display for TrueT {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Bool") write!(f, "True")
}
}
impl Display for FalseT {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "False")
} }
} }

View File

@ -256,6 +256,7 @@ pub fn type_from_parsed(
ParsedType::Type(name) => match info ParsedType::Type(name) => match info
.scopes .scopes
.iter() .iter()
.rev()
.find_map(|scope| scope.types.iter().find(|v| v.0 == name).map(|(_, v)| v)) .find_map(|scope| scope.types.iter().find(|v| v.0 == name).map(|(_, v)| v))
{ {
Some(Ok(t)) => as_type.add_all(&*t), Some(Ok(t)) => as_type.add_all(&*t),

View File

@ -2,7 +2,7 @@ pub mod function;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use crate::data::{self, Data, MersData, Type}; use crate::data::{self, bool::bool_type, Data, MersData, Type};
pub trait FromMersData: Sized { pub trait FromMersData: Sized {
fn as_type_from() -> Type; fn as_type_from() -> Type;
@ -336,7 +336,7 @@ impl FromMersData for bool {
Self::as_type_to() Self::as_type_to()
} }
fn can_represent(t: &Type) -> bool { fn can_represent(t: &Type) -> bool {
t.is_included_in(&Type::new(data::bool::BoolT)) t.is_included_in(&bool_type())
} }
fn try_represent<O, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O { fn try_represent<O, F: FnOnce(Option<Self>) -> O>(d: &(impl MersData + ?Sized), f: F) -> O {
if let Some(v) = d.as_any().downcast_ref::<data::bool::Bool>() { if let Some(v) = d.as_any().downcast_ref::<data::bool::Bool>() {
@ -348,7 +348,7 @@ impl FromMersData for bool {
} }
impl ToMersData for bool { impl ToMersData for bool {
fn as_type_to() -> Type { fn as_type_to() -> Type {
Type::new(data::bool::BoolT) bool_type()
} }
fn represent(self) -> Data { fn represent(self) -> Data {
Data::new(data::bool::Bool(self)) Data::new(data::bool::Bool(self))

View File

@ -75,7 +75,14 @@ impl Config {
.insert(t.to_string(), Ok(Arc::new(data::Type::new(t)))); .insert(t.to_string(), Ok(Arc::new(data::Type::new(t))));
}; };
} }
init_d!(data::bool::BoolT); init_d!(data::bool::TrueT);
init_d!(data::bool::FalseT);
info_check
.scopes
.last_mut()
.unwrap()
.types
.insert("Bool".to_owned(), Ok(Arc::new(data::bool::bool_type())));
init_d!(data::byte::ByteT); init_d!(data::byte::ByteT);
init_d!(data::int::IntT); init_d!(data::int::IntT);
init_d!(data::float::FloatT); init_d!(data::float::FloatT);

View File

@ -95,48 +95,3 @@ pub fn to_mers_func_concrete_string_string_to_any(
}, },
) )
} }
pub fn to_mers_func_concrete_string_string_to_opt_int(
f: impl Fn(&str, &str) -> Option<isize> + Send + Sync + 'static,
) -> data::function::Function {
to_mers_func_concrete_string_string_to_any(
Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![Type::new(data::int::IntT)])),
Arc::new(data::tuple::TupleT(vec![])),
]),
move |a, b| {
Ok(f(a, b)
.map(|v| Data::one_tuple(Data::new(data::int::Int(v))))
.unwrap_or_else(|| Data::empty_tuple()))
},
)
}
pub fn to_mers_func_concrete_string_string_to_bool(
f: impl Fn(&str, &str) -> bool + Send + Sync + 'static,
) -> data::function::Function {
to_mers_func_concrete_string_string_to_any(Type::new(data::bool::BoolT), move |a, b| {
Ok(Data::new(data::bool::Bool(f(a, b))))
})
}
pub fn to_mers_func_concrete_string_string_to_opt_string_string(
f: impl Fn(&str, &str) -> Option<(String, String)> + Send + Sync + 'static,
) -> data::function::Function {
to_mers_func_concrete_string_string_to_any(
Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![])),
Arc::new(data::tuple::TupleT(vec![
Type::new(data::string::StringT),
Type::new(data::string::StringT),
])),
]),
move |a, b| {
Ok(f(a, b)
.map(|(a, b)| {
Data::new(data::tuple::Tuple(vec![
Data::new(data::string::String(a)),
Data::new(data::string::String(b)),
]))
})
.unwrap_or_else(|| Data::empty_tuple()))
},
)
}

View File

@ -4,7 +4,7 @@ use std::{
}; };
use crate::{ use crate::{
data::{self, Data, Type}, data::{self, bool::bool_type, Data, Type},
errors::CheckError, errors::CheckError,
program::run::{CheckInfo, Info}, program::run::{CheckInfo, Info},
}; };
@ -132,7 +132,7 @@ impl Config {
return Err(format!("called eq on non-iterable").into()) return Err(format!("called eq on non-iterable").into())
} }
} }
Ok(Type::new(data::bool::BoolT)) Ok(bool_type())
})), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
Ok(Data::new(data::bool::Bool(if let Some(mut i) = a.get().iterable() { Ok(Data::new(data::bool::Bool(if let Some(mut i) = a.get().iterable() {

View File

@ -33,7 +33,7 @@ impl Config {
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)))) { 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![ Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![ Arc::new(data::tuple::TupleT(vec![
Type::newm(vec![Arc::new(data::int::IntT), Arc::new(data::bool::BoolT)]), Type::newm(vec![Arc::new(data::int::IntT), Arc::new(data::bool::TrueT), Arc::new(data::bool::FalseT)]),
Type::new(data::string::StringT), Type::new(data::string::StringT),
Type::new(data::string::StringT), Type::new(data::string::StringT),
])), ])),
@ -131,7 +131,7 @@ impl Config {
out: Ok(Arc::new(|a, _i| { out: Ok(Arc::new(|a, _i| {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {
Ok(Type::newm(vec![ Ok(Type::newm(vec![
Arc::new(data::tuple::TupleT(vec![Type::new(data::bool::BoolT)])), Arc::new(data::tuple::TupleT(vec![data::bool::bool_type()])),
Arc::new(data::tuple::TupleT(vec![])), Arc::new(data::tuple::TupleT(vec![])),
])) ]))
} else { } else {
@ -160,7 +160,8 @@ impl Config {
if a.is_included_in_single(&ChildProcessT) { if a.is_included_in_single(&ChildProcessT) {
Ok(Type::newm(vec![ Ok(Type::newm(vec![
Arc::new(data::int::IntT), Arc::new(data::int::IntT),
Arc::new(data::bool::BoolT), Arc::new(data::bool::TrueT),
Arc::new(data::bool::FalseT),
Arc::new(data::tuple::TupleT(vec![])), Arc::new(data::tuple::TupleT(vec![])),
])) ]))
} else { } else {
@ -191,7 +192,7 @@ impl Config {
info_check: Arc::new(Mutex::new( CheckInfo::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)))) { 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(Type::new(data::bool::BoolT)) Ok(data::bool::bool_type())
} else { } 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}").into());
} }
@ -220,7 +221,7 @@ impl Config {
info_check: Arc::new(Mutex::new( CheckInfo::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)])) { if a.is_included_in_single(&data::tuple::TupleT(vec![Type::new(ChildProcessT), Type::new(data::string::StringT)])) {
Ok(Type::new(data::bool::BoolT)) Ok(data::bool::bool_type())
} else { } 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}").into());
} }

View File

@ -28,7 +28,7 @@ impl Config {
/// `all: fn` returns true if all elements of the iterator are true /// `all: fn` returns true if all elements of the iterator are true
pub fn with_iters(self) -> Self { pub fn with_iters(self) -> Self {
self self
.add_var("any", genfunc_iter_in_val_out("all".to_string(), data::bool::BoolT, Type::new(data::bool::BoolT), |a, _i| { .add_var("any", genfunc_iter_in_val_out("all".to_string(), data::bool::bool_type(), data::bool::bool_type(), |a, _i| {
for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().is_some_and(|v| v.0))) { for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().is_some_and(|v| v.0))) {
if v? { if v? {
return Ok(Data::new(data::bool::Bool(true))); return Ok(Data::new(data::bool::Bool(true)));
@ -36,7 +36,7 @@ impl Config {
} }
Ok(Data::new(data::bool::Bool(false))) Ok(Data::new(data::bool::Bool(false)))
})) }))
.add_var("all", genfunc_iter_in_val_out("all".to_string(), data::bool::BoolT, Type::new(data::bool::BoolT), |a, _i| { .add_var("all", genfunc_iter_in_val_out("all".to_string(), data::bool::bool_type(), data::bool::bool_type(), |a, _i| {
for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().is_some_and(|v| v.0))) { for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().is_some_and(|v| v.0))) {
if !v? { if !v? {
return Ok(Data::new(data::bool::Bool(false))); return Ok(Data::new(data::bool::Bool(false)));
@ -413,7 +413,7 @@ impl IterT {
let t = match &iter { let t = match &iter {
ItersT::Map(f) => f.o(&data)?, ItersT::Map(f) => f.o(&data)?,
ItersT::Filter(f) => { ItersT::Filter(f) => {
if f.o(&data)?.is_included_in_single(&data::bool::BoolT) { if f.o(&data)?.is_included_in(&data::bool::bool_type()) {
data.clone() data.clone()
} else { } else {
return Err(format!( return Err(format!(
@ -517,7 +517,7 @@ impl Iters {
fn genfunc_iter_in_val_out( fn genfunc_iter_in_val_out(
name: String, name: String,
iter_type: impl MersType + 'static, iter_type: Type,
out_type: Type, out_type: Type,
run: impl Fn(Data, &mut crate::info::Info<program::run::RunLocal>) -> Result<Data, CheckError> run: impl Fn(Data, &mut crate::info::Info<program::run::RunLocal>) -> Result<Data, CheckError>
+ Send + Send
@ -529,7 +529,7 @@ fn genfunc_iter_in_val_out(
info_check: Arc::new(Mutex::new(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 let Some(iter_over) = a.iterable() {
if iter_over.is_included_in_single(&iter_type) { if iter_over.is_included_in(&iter_type) {
Ok(out_type.clone()) Ok(out_type.clone())
} else { } 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 {a}, which isn't {iter_type}.").into())

View File

@ -63,7 +63,7 @@ impl Config {
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 {t}, which isn't a thread but part of the argument {a}.")));
} }
} }
Ok(Type::new(data::bool::BoolT)) Ok(data::bool::bool_type())
})), })),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();

View File

@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use crate::{ use crate::{
data::{self, tuple::TupleT, Data, Type}, data::{self, tuple::TupleT, Data, MersType, Type},
errors::{CheckError, EColor, SourceRange}, errors::{CheckError, EColor, SourceRange},
}; };
@ -25,7 +25,7 @@ impl MersStatement for If {
return Err("can't init to statement type If".to_string().into()); return Err("can't init to statement type If".to_string().into());
} }
let cond_return_type = self.condition.check(info, None)?; let cond_return_type = self.condition.check(info, None)?;
if !cond_return_type.is_included_in_single(&data::bool::BoolT) { if !cond_return_type.is_included_in(&data::bool::bool_type()) {
return Err(CheckError::new() return Err(CheckError::new()
.src(vec![ .src(vec![
(self.pos_in_src.clone(), None), (self.pos_in_src.clone(), None),
@ -38,7 +38,7 @@ impl MersStatement for If {
("The ".to_owned(), None), ("The ".to_owned(), None),
("condition".to_owned(), Some(EColor::IfConditionNotBool)), ("condition".to_owned(), Some(EColor::IfConditionNotBool)),
( (
" in an if-statement must return bool, not ".to_owned(), " in an if-statement must return Bool, not ".to_owned(),
None, None,
), ),
( (
@ -47,11 +47,17 @@ impl MersStatement for If {
), ),
])); ]));
} }
let mut t = self.on_true.check(info, None)?; let mut t = if Type::new(data::bool::TrueT).is_included_in(&cond_return_type) {
if let Some(f) = &self.on_false { self.on_true.check(info, None)?
t.add_all(&f.check(info, None)?);
} else { } else {
t.add(Arc::new(TupleT(vec![]))); Type::empty()
};
if Type::new(data::bool::FalseT).is_included_in(&cond_return_type) {
if let Some(f) = &self.on_false {
t.add_all(&f.check(info, None)?);
} else {
t.add(Arc::new(TupleT(vec![])));
}
} }
Ok(t) Ok(t)
} }