use crate::bmm3::core::bmm_formal_element::BmmFormalElement;
use crate::bmm3::core::entity::bmm_container_type::BmmContainerType;
use crate::bmm3::core::entity::bmm_function_type::BmmFunctionType;
use crate::bmm3::core::entity::bmm_procedure_type::BmmProcedureType;
use crate::bmm3::core::entity::bmm_property_type::BmmPropertyType;
use crate::bmm3::core::entity::bmm_routine_type::BmmRoutineType;
use crate::bmm3::core::entity::bmm_signature::BmmSignature;
use crate::bmm3::core::entity::bmm_tuple_type::BmmTupleType;
use crate::bmm3::core::entity::bmm_type::BmmType;
use crate::bmm3::core::feature::bmm_constant::BmmConstant;
use crate::bmm3::core::feature::bmm_container_property::BmmContainerProperty;
use crate::bmm3::core::feature::bmm_feature::BmmFeature;
use crate::bmm3::core::feature::bmm_function::BmmFunction;
use crate::bmm3::core::feature::bmm_parameter::BmmParameter;
use crate::bmm3::core::feature::bmm_procedure::BmmProcedure;
use crate::bmm3::core::feature::bmm_property::BmmProperty;
use crate::bmm3::core::feature::bmm_routine::BmmRoutine;
use crate::bmm3::core::feature::bmm_singleton::BmmSingleton;
use crate::bmm3::core::feature::bmm_unitary_property::BmmUnitaryProperty;
pub const BOOLEAN_TYPE_NAME: &str = "Boolean";
fn argument_types(parameters: &[BmmParameter]) -> Option<BmmTupleType> {
if parameters.is_empty() {
return None;
}
Some(BmmTupleType {
item_types: parameters
.iter()
.map(|p| (p.name.clone(), p.r#type.clone()))
.collect(),
})
}
fn type_is_boolean(t: &BmmType) -> bool {
matches!(t, BmmType::BmmSimpleType(simple)
if simple.type_name().eq_ignore_ascii_case(BOOLEAN_TYPE_NAME))
}
impl BmmContainerProperty {
#[must_use]
pub fn r#type(&self) -> BmmContainerType {
match self {
Self::BmmIndexedContainerProperty(indexed) => {
BmmContainerType::BmmIndexedContainerType(Box::new(indexed.r#type.clone()))
}
Self::BmmContainerProperty(data) => data.r#type.clone(),
}
}
#[must_use]
pub fn name(&self) -> &str {
match self {
Self::BmmIndexedContainerProperty(indexed) => indexed.name.as_str(),
Self::BmmContainerProperty(data) => data.name.as_str(),
}
}
}
impl BmmProperty {
#[must_use]
pub fn name(&self) -> &str {
match self {
Self::BmmContainerProperty(property) => property.name(),
Self::BmmUnitaryProperty(property) => property.name.as_str(),
}
}
}
impl BmmFeature {
#[must_use]
pub fn name(&self) -> &str {
match self {
Self::BmmConstant(constant) => constant.name.as_str(),
Self::BmmContainerProperty(property) => property.name(),
Self::BmmFunction(function) => function.name.as_str(),
Self::BmmProcedure(procedure) => procedure.name.as_str(),
Self::BmmSingleton(singleton) => singleton.name.as_str(),
Self::BmmUnitaryProperty(property) => property.name.as_str(),
}
}
}
impl BmmFunction {
#[must_use]
pub fn arity(&self) -> i32 {
i32::try_from(self.parameters.as_ref().map_or(0, Vec::len)).unwrap_or(i32::MAX)
}
#[must_use]
pub fn signature(&self) -> BmmFunctionType {
BmmFunctionType {
result_type: self.r#type.clone(),
argument_types: argument_types(self.parameters.as_deref().unwrap_or_default()),
}
}
#[must_use]
pub fn is_boolean(&self) -> bool {
type_is_boolean(&self.r#type)
}
}
impl BmmProcedure {
#[must_use]
pub fn arity(&self) -> i32 {
i32::try_from(self.parameters.as_ref().map_or(0, Vec::len)).unwrap_or(i32::MAX)
}
#[must_use]
pub fn signature(&self) -> BmmProcedureType {
BmmProcedureType {
result_type: Some(self.r#type.clone()),
argument_types: argument_types(self.parameters.as_deref().unwrap_or_default()),
}
}
#[expect(
clippy::unused_self,
reason = "the class definitions declare is_boolean() on BMM_FORMAL_ELEMENT; for a procedure the redefined `type` makes the answer constant"
)]
#[must_use]
pub fn is_boolean(&self) -> bool {
false
}
}
impl BmmRoutine {
#[must_use]
pub fn arity(&self) -> i32 {
match self {
Self::BmmFunction(function) => function.arity(),
Self::BmmProcedure(procedure) => procedure.arity(),
}
}
#[must_use]
pub fn signature(&self) -> BmmRoutineType {
match self {
Self::BmmFunction(function) => BmmRoutineType::BmmFunctionType(function.signature()),
Self::BmmProcedure(procedure) => {
BmmRoutineType::BmmProcedureType(procedure.signature())
}
}
}
#[must_use]
pub fn is_boolean(&self) -> bool {
match self {
Self::BmmFunction(function) => function.is_boolean(),
Self::BmmProcedure(procedure) => procedure.is_boolean(),
}
}
}
impl BmmUnitaryProperty {
#[must_use]
pub fn signature(&self) -> BmmPropertyType {
BmmPropertyType {
result_type: BmmType::from(self.r#type.clone()),
}
}
#[must_use]
pub fn is_boolean(&self) -> bool {
type_is_boolean(&BmmType::from(self.r#type.clone()))
}
}
impl BmmContainerProperty {
#[must_use]
pub fn signature(&self) -> BmmPropertyType {
BmmPropertyType {
result_type: BmmType::BmmContainerType(Box::new(self.r#type())),
}
}
#[expect(
clippy::unused_self,
reason = "the class definitions declare is_boolean() on BMM_FORMAL_ELEMENT; for a container property the redefined `type` makes the answer constant"
)]
#[must_use]
pub fn is_boolean(&self) -> bool {
false
}
}
impl BmmProperty {
#[must_use]
pub fn signature(&self) -> BmmPropertyType {
match self {
Self::BmmContainerProperty(property) => property.signature(),
Self::BmmUnitaryProperty(property) => property.signature(),
}
}
#[must_use]
pub fn is_boolean(&self) -> bool {
match self {
Self::BmmContainerProperty(property) => property.is_boolean(),
Self::BmmUnitaryProperty(property) => property.is_boolean(),
}
}
}
impl BmmConstant {
#[must_use]
pub fn signature(&self) -> BmmPropertyType {
BmmPropertyType {
result_type: self.r#type.clone(),
}
}
#[must_use]
pub fn is_boolean(&self) -> bool {
type_is_boolean(&self.r#type)
}
}
impl BmmSingleton {
#[must_use]
pub fn signature(&self) -> BmmPropertyType {
BmmPropertyType {
result_type: self.r#type.clone(),
}
}
#[must_use]
pub fn is_boolean(&self) -> bool {
type_is_boolean(&self.r#type)
}
}
impl BmmFormalElement {
#[must_use]
pub fn signature(&self) -> BmmSignature {
match self {
Self::BmmConstant(constant) => {
BmmSignature::BmmPropertyType(Box::new(constant.signature()))
}
Self::BmmContainerProperty(property) => {
BmmSignature::BmmPropertyType(Box::new(property.signature()))
}
Self::BmmFunction(function) => BmmSignature::BmmRoutineType(Box::new(
BmmRoutineType::BmmFunctionType(function.signature()),
)),
Self::BmmProcedure(procedure) => BmmSignature::BmmRoutineType(Box::new(
BmmRoutineType::BmmProcedureType(procedure.signature()),
)),
Self::BmmSingleton(singleton) => {
BmmSignature::BmmPropertyType(Box::new(singleton.signature()))
}
Self::BmmUnitaryProperty(property) => {
BmmSignature::BmmPropertyType(Box::new(property.signature()))
}
Self::BmmLocal(local) => BmmSignature::BmmPropertyType(Box::new(BmmPropertyType {
result_type: local.r#type.clone(),
})),
Self::BmmParameter(parameter) => {
BmmSignature::BmmPropertyType(Box::new(BmmPropertyType {
result_type: parameter.r#type.clone(),
}))
}
Self::BmmResult(result) => BmmSignature::BmmPropertyType(Box::new(BmmPropertyType {
result_type: result.r#type.clone(),
})),
Self::BmmSelf(self_variable) => {
BmmSignature::BmmPropertyType(Box::new(BmmPropertyType {
result_type: self_variable.r#type.clone(),
}))
}
}
}
#[must_use]
pub fn is_boolean(&self) -> bool {
match self {
Self::BmmConstant(constant) => constant.is_boolean(),
Self::BmmContainerProperty(property) => property.is_boolean(),
Self::BmmFunction(function) => function.is_boolean(),
Self::BmmProcedure(procedure) => procedure.is_boolean(),
Self::BmmSingleton(singleton) => singleton.is_boolean(),
Self::BmmUnitaryProperty(property) => property.is_boolean(),
Self::BmmLocal(local) => type_is_boolean(&local.r#type),
Self::BmmParameter(parameter) => type_is_boolean(¶meter.r#type),
Self::BmmResult(result) => type_is_boolean(&result.r#type),
Self::BmmSelf(self_variable) => type_is_boolean(&self_variable.r#type),
}
}
}
impl BmmFeature {
#[must_use]
pub fn signature(&self) -> BmmSignature {
match self {
Self::BmmConstant(constant) => {
BmmSignature::BmmPropertyType(Box::new(constant.signature()))
}
Self::BmmContainerProperty(property) => {
BmmSignature::BmmPropertyType(Box::new(property.signature()))
}
Self::BmmFunction(function) => BmmSignature::BmmRoutineType(Box::new(
BmmRoutineType::BmmFunctionType(function.signature()),
)),
Self::BmmProcedure(procedure) => BmmSignature::BmmRoutineType(Box::new(
BmmRoutineType::BmmProcedureType(procedure.signature()),
)),
Self::BmmSingleton(singleton) => {
BmmSignature::BmmPropertyType(Box::new(singleton.signature()))
}
Self::BmmUnitaryProperty(property) => {
BmmSignature::BmmPropertyType(Box::new(property.signature()))
}
}
}
#[must_use]
pub fn is_boolean(&self) -> bool {
match self {
Self::BmmConstant(constant) => constant.is_boolean(),
Self::BmmContainerProperty(property) => property.is_boolean(),
Self::BmmFunction(function) => function.is_boolean(),
Self::BmmProcedure(procedure) => procedure.is_boolean(),
Self::BmmSingleton(singleton) => singleton.is_boolean(),
Self::BmmUnitaryProperty(property) => property.is_boolean(),
}
}
}