use crate::{definite::types::Types, defs};
use alloc::{borrow::ToOwned, boxed::Box, format, string::String, vec::Vec};
use enum_as_inner::EnumAsInner;
use serde::{Deserialize, Serialize};
use super::types::class_instance::ClassInstance;
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct ArrayType {
pub rtype: Box<DefinerCollecting>,
pub has_size: bool,
pub size: Option<Box<Types>>,
pub pos: defs::Cursor,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct GenericParameter {
pub value: DefinerCollecting,
pub pos: defs::Cursor,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct ParentGenericType {
pub rtype: String,
pub parent_pos: defs::Cursor,
pub generics: Vec<GenericParameter>,
pub hash: usize,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct GenericType {
pub rtype: String,
pub pos: defs::Cursor,
pub hash: usize,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct FunctionType {
pub params: Vec<DefinerCollecting>,
pub returning: Box<DefinerCollecting>,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct CloakType {
pub rtype: Vec<DefinerCollecting>,
pub pos: defs::Cursor,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct CollectiveType {
pub key: Box<DefinerCollecting>,
pub value: Box<DefinerCollecting>,
pub pos: defs::Cursor,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct NullableType {
pub pos: defs::Cursor,
pub value: Box<DefinerCollecting>,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub enum EnumFieldData {
NoData,
Data(Box<DefinerCollecting>),
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct EnumField {
pub field_name: String,
pub field_data: EnumFieldData,
pub name: String,
pub hash: usize,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize, EnumAsInner)]
pub enum DefinerCollecting {
Array(ArrayType),
Generic(GenericType),
ParentGeneric(ParentGenericType),
Function(FunctionType),
Cloak(CloakType),
Collective(CollectiveType),
Nullable(NullableType),
EnumField(EnumField),
ClassInstance(ClassInstance),
Dynamic,
}
impl DefinerCollecting {
pub fn to_string(&self) -> String {
match self {
DefinerCollecting::Array(_) => "array".to_owned(),
DefinerCollecting::Generic(generic) => generic.rtype.to_owned(),
DefinerCollecting::ParentGeneric(parent_generic) => format!(
"{}<{}>",
parent_generic.rtype,
parent_generic
.generics
.iter()
.map(|g| g.value.to_string())
.collect::<Vec<String>>()
.join(", ")
),
DefinerCollecting::Function(function) => format!(
"Fn({}):{}",
function
.params
.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(","),
function.returning.to_string()
),
DefinerCollecting::Cloak(_) => "cloak".to_owned(),
DefinerCollecting::Collective(_) => "collective".to_owned(),
DefinerCollecting::Nullable(_) => "nullAble".to_owned(),
DefinerCollecting::Dynamic => "dyn".to_owned(),
DefinerCollecting::EnumField(e) => match &e.field_data {
EnumFieldData::NoData => format!("{}.{}", e.name, e.field_name),
EnumFieldData::Data(inner_def) => {
inner_def.to_string()
}
},
DefinerCollecting::ClassInstance(e) => {
format!("Object<{}>", e.class_name)
}
}
}
pub fn same_as(&self, other: DefinerCollecting) -> bool {
if matches!(&other, DefinerCollecting::Generic(generic) if generic.rtype == "dyn")
|| matches!(&self, DefinerCollecting::Generic(generic) if generic.rtype == "dyn")
{
return true;
}
match self {
DefinerCollecting::Array(data) => {
if let DefinerCollecting::Array(other_data) = other {
other_data.size == data.size && other_data.rtype.same_as(*data.rtype.clone())
} else { DefinerCollecting::Dynamic == other }
}
DefinerCollecting::Generic(generic) => {
if let DefinerCollecting::Generic(other_generic) = other {
(other_generic.rtype == generic.rtype && other_generic.hash == generic.hash)
|| (other_generic.rtype == "dyn" || generic.rtype == "dyn")
} else { DefinerCollecting::Dynamic == other }
}
DefinerCollecting::ParentGeneric(parent_generic) => {
if let DefinerCollecting::ParentGeneric(other_parent_generic) = other {
other_parent_generic.rtype == parent_generic.rtype
&& other_parent_generic.hash == parent_generic.hash
&& other_parent_generic.generics.len() == parent_generic.generics.len()
&& other_parent_generic
.generics
.iter()
.zip(parent_generic.generics.iter())
.all(|(a, b)| a.value.same_as(b.value.clone()))
} else {
false
}
}
DefinerCollecting::Function(e) => {
if let DefinerCollecting::Function(other_e) = other {
e.params.len() == other_e.params.len()
&& e.params
.iter()
.zip(other_e.params.iter())
.all(|(a, b)| a.same_as(b.clone()))
&& e.returning.same_as(*other_e.returning.clone())
} else {
false
}
}
DefinerCollecting::Cloak(cloak) => {
if let DefinerCollecting::Cloak(other_cloak) = other {
cloak.rtype.len() == other_cloak.rtype.len()
&& cloak
.rtype
.iter()
.zip(other_cloak.rtype.iter())
.all(|(a, b)| a.same_as(b.clone()))
} else {
false
}
}
DefinerCollecting::Collective(e) => {
if let DefinerCollecting::Collective(other_e) = other {
e.key.same_as(*other_e.key.clone()) && e.value.same_as(*other_e.value.clone())
} else {
false
}
}
DefinerCollecting::Nullable(e) => {
if let DefinerCollecting::Nullable(other_e) = other {
e.value.same_as(*other_e.value.clone())
} else {
false
}
}
DefinerCollecting::EnumField(e) => {
if let DefinerCollecting::EnumField(other_e) = other {
e.name == other_e.name && e.field_name == other_e.field_name
} else {
false
}
}
DefinerCollecting::ClassInstance(_) => todo!(),
DefinerCollecting::Dynamic => unreachable!(),
}
}
pub fn convert_generic(&mut self, generic_hash: usize, replacement_generic: DefinerCollecting) {
match self {
DefinerCollecting::Array(array) => {
array
.rtype
.convert_generic(generic_hash, replacement_generic);
}
DefinerCollecting::Generic(generic) => {
if generic.hash == generic_hash {
*self = replacement_generic;
}
}
DefinerCollecting::ParentGeneric(parrent_generic) => {
if parrent_generic.hash == generic_hash {
*self = replacement_generic;
} else {
parrent_generic.generics.iter_mut().for_each(|g| {
g.value
.convert_generic(generic_hash, replacement_generic.clone())
});
}
}
DefinerCollecting::Function(function) => {
function
.params
.iter_mut()
.for_each(|param: &mut DefinerCollecting| {
param.convert_generic(generic_hash, replacement_generic.clone())
});
function
.returning
.convert_generic(generic_hash, replacement_generic.clone());
}
DefinerCollecting::Cloak(cloak) => {
cloak
.rtype
.iter_mut()
.for_each(|r| r.convert_generic(generic_hash, replacement_generic.clone()));
}
DefinerCollecting::Collective(collective) => {
collective
.key
.convert_generic(generic_hash, replacement_generic.clone());
collective
.value
.convert_generic(generic_hash, replacement_generic);
}
DefinerCollecting::Nullable(nullable) => {
nullable
.value
.convert_generic(generic_hash, replacement_generic);
}
DefinerCollecting::EnumField(enum_field) => match &mut enum_field.field_data {
EnumFieldData::NoData => (),
EnumFieldData::Data(enum_field_data) => {
enum_field_data.convert_generic(generic_hash, replacement_generic)
}
},
DefinerCollecting::Dynamic => (),
DefinerCollecting::ClassInstance(_) => (),
}
}
}