use std::fmt::{Display, Error, Formatter};
use crate::check::constrain::constraint::builder::VarMapping;
use crate::check::constrain::constraint::expected::Expect::{Access, Function, Type};
use crate::check::constrain::constraint::expected::Expected;
use crate::check::context::{clss, function};
use crate::check::name::Name;
use crate::check::name::string_name::StringName;
pub mod builder;
pub mod expected;
pub mod iterator;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Constraint {
pub is_flag: bool,
pub is_sub: bool,
pub msg: String,
pub parent: Expected,
pub child: Expected,
}
pub(super) trait MapExp {
fn map_exp(&self, var_mapping: &VarMapping, global_var_mapping: &VarMapping) -> Self;
}
impl Display for Constraint {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
write!(f, "{} >= {}", self.parent, self.child)
}
}
impl MapExp for Constraint {
fn map_exp(&self, var_mapping: &VarMapping, global_var_mapping: &VarMapping) -> Self {
let left = self.parent.map_exp(var_mapping, global_var_mapping);
let right = self.child.map_exp(var_mapping, global_var_mapping);
Constraint { parent: left, child: right, ..self.clone() }
}
}
impl Constraint {
pub fn new(msg: &str, parent: &Expected, child: &Expected) -> Constraint {
let (parent, child) = (parent.clone(), child.clone());
Constraint { parent, child, msg: String::from(msg), is_flag: false, is_sub: false }
}
fn flag(&self) -> Constraint { Constraint { is_flag: true, ..self.clone() } }
pub fn stringy(msg: &str, expected: &Expected) -> Constraint {
Self::access(msg, expected, &Name::from(clss::STRING), &StringName::from(function::STR))
}
pub fn truthy(msg: &str, expected: &Expected) -> Constraint {
Self::access(msg, expected, &Name::from(clss::BOOL), &StringName::from(function::TRUTHY))
}
fn access(msg: &str, expected: &Expected, ty_name: &Name, fun_name: &StringName) -> Constraint {
let obj = Expected::new(expected.pos, &Type { name: ty_name.clone() });
let fun = Function { name: fun_name.clone(), args: vec![expected.clone()] };
let access = Access {
entity: Box::from(expected.clone()),
name: Box::new(Expected::new(expected.pos, &fun)),
};
Constraint::new(msg, &obj, &Expected::new(expected.pos, &access))
}
pub fn undefined(msg: &str, expected: &Expected) -> Constraint {
let none = Expected::new(expected.pos, &Type { name: Name::from(clss::NONE) });
Constraint::new(msg, expected, &none)
}
}