use alloc::{borrow::ToOwned, boxed::Box, vec, vec::Vec};
use ellie_core::definite::Converter;
use ellie_core::{error, utils::generate_hash_usize};
use ellie_tokenizer::{
processors::{items::Processors, types::Processors as TypeProcessor},
syntax::{
items::{
constructor::Constructor, constructor_parameter::ConstructorParameter,
setter_call::SetterCall,
},
types::{
operator_type::AssignmentOperators,
reference_type::{Chain, ReferenceType, ReferenceTypeCollector},
variable_type::{VariableType, VariableTypeCollector},
},
},
tokenizer::PageType,
};
impl super::ItemParserProcessor for Constructor {
fn process(&self, options: &mut super::ItemParserProcessorOptions) -> bool {
let class_body_page = options
.parser
.pages
.nth(options.page_idx)
.unwrap_or_else(|| panic!("Failed to find page"))
.clone();
let path = class_body_page.path.clone();
let page = options.parser.pages.nth(options.page_idx).unwrap().clone();
let class_page_type = match page.page_type {
PageType::ClassBody(e) => e,
_ => unreachable!(),
};
let class_instance_element = class_body_page
.items
.iter()
.find_map(|item| match item {
ellie_tokenizer::processors::items::Processors::ClassInstance(e) => Some(e),
_ => None,
})
.unwrap_or_else(|| panic!("Failed to find self"));
let class_page = options
.parser
.find_page(class_instance_element.class_page)
.unwrap_or_else(|| panic!("Failed to class page"))
.clone();
let class_element = class_page
.items
.iter()
.find_map(|item| match item {
ellie_tokenizer::processors::items::Processors::Class(e) => {
if e.hash == class_instance_element.class_hash {
Some(e)
} else {
None
}
}
_ => None,
})
.unwrap_or_else(|| panic!("Failed to find class"));
let mut dependencies = vec![ellie_tokenizer::tokenizer::Dependency {
hash: page.hash,
processed: false,
module: None,
deep_link: Some(page.hash),
public: false,
}];
dependencies.extend(page.dependencies);
let mut items = Vec::new();
let mut parameters = Vec::new();
items.push(
ellie_tokenizer::processors::items::Processors::ConstructorParameter(
ConstructorParameter {
name: "self".to_owned(),
rtype: ellie_core::definite::definers::DefinerCollecting::Generic(
ellie_core::definite::definers::GenericType {
rtype: "self".to_owned(),
pos: class_page_type.pos,
hash: class_page_type.hash,
},
),
hash: generate_hash_usize(),
pos: self.pos,
},
),
);
parameters.push(
ellie_core::definite::items::constructor::ConstructorParameter {
name: "self".to_owned(),
pos: self.pos,
},
);
for (index, parameter) in self.parameters.clone().iter().enumerate() {
if class_element.name == parameter.name {
let mut err = error::error_list::ERROR_S24.clone().build_with_path(
vec![],
alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()),
path.clone(),
parameter.pos,
);
err.reference_block = Some((class_element.pos, path.clone()));
"Prime is here".clone_into(&mut err.reference_message);
err.semi_assist = true;
options.parser.informations.push(&err);
return false;
}
if let Some(other_index) = self
.parameters
.iter()
.position(|g| g.name == parameter.name)
{
if other_index < index {
let mut err = error::error_list::ERROR_S10.clone().build_with_path(
vec![],
alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()),
path.clone(),
parameter.pos,
);
err.reference_block = Some((self.parameters[other_index].pos, path.clone()));
"Prime is here".clone_into(&mut err.reference_message);
err.semi_assist = true;
options.parser.informations.push(&err);
}
}
let mut found_param = None;
let page = options.parser.find_page(options.page_hash).unwrap();
for item in page.items.iter() {
match item {
Processors::Variable(e) => {
found_param = Some(e.clone());
}
_ => (),
}
}
if found_param.is_none() && !parameter.body_element_defiener {
let mut err = error::error_list::ERROR_S34.clone().build_with_path(
vec![error::ErrorBuildField {
key: "token".to_owned(),
value: parameter.name.clone(),
}],
alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()),
path.clone(),
parameter.pos,
);
err.reference_block = Some((class_element.pos, class_page.path.clone()));
"Class body is here".clone_into(&mut err.reference_message);
options.parser.informations.push(&err);
}
if let Some(data) = &found_param {
if data.data.constant {
options.parser.informations.push(
&error::error_list::ERROR_S18.clone().build_with_path(
vec![],
alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()),
class_body_page.path.clone(),
parameter.pos,
),
);
}
}
let targeted_variable = class_element
.body
.iter()
.find_map(|item| match item {
Processors::Variable(e) => {
if e.data.name == parameter.name {
Some(e)
} else {
None
}
}
_ => None,
})
.unwrap_or_else(|| panic!("Failed to find variable"));
let self_setter = Processors::SetterCall(SetterCall {
target: TypeProcessor::Reference(ReferenceTypeCollector {
data: ReferenceType {
reference: Box::new(TypeProcessor::Variable(VariableTypeCollector {
data: VariableType {
value: "self".to_owned(),
..Default::default()
},
..Default::default()
})),
chain: vec![Chain {
value: targeted_variable.data.name.clone(),
..Default::default()
}],
..Default::default()
},
..Default::default()
}),
value: if targeted_variable.data.has_value {
targeted_variable.data.value.clone()
} else {
TypeProcessor::Variable(VariableTypeCollector {
data: VariableType {
value: targeted_variable.data.name.clone(),
..Default::default()
},
..Default::default()
})
},
operator: AssignmentOperators::Assignment,
hash: generate_hash_usize(),
..Default::default()
});
items.push(self_setter);
parameters.push(
ellie_core::definite::items::constructor::ConstructorParameter {
name: parameter.name.clone(),
pos: targeted_variable.data.pos,
},
);
items.push(
ellie_tokenizer::processors::items::Processors::ConstructorParameter(
ConstructorParameter {
name: parameter.name.clone(),
rtype: targeted_variable
.data
.rtype
.clone()
.definer_type
.to_definite(),
hash: generate_hash_usize(),
pos: targeted_variable.data.pos,
},
),
);
}
items.extend(self.inside_code.clone());
let inner_page_id: usize = ellie_core::utils::generate_hash_usize();
let inner = ellie_tokenizer::tokenizer::Page {
hash: inner_page_id,
inner: Some(class_body_page.hash),
path: class_body_page.path.clone(),
items,
page_type: PageType::ConstructorBody,
dependents: vec![],
dependencies,
..Default::default()
};
options.parser.pages.push_page(inner);
let processed = ellie_core::definite::items::Collecting::Constructor(
ellie_core::definite::items::constructor::Constructor {
parameters,
name_pos: self.name_pos,
parameters_pos: self.parameters_pos,
pos: self.pos,
inner_page_id,
class_hash: class_element.hash,
},
);
options
.parser
.processed_pages
.nth_mut(options.processed_page_idx)
.unwrap()
.items
.push(processed);
true
}
}