use crate::Analyzer;
use swamp_types::TypeRef;
use swamp_types::prelude::{Signature, TypeForParameter};
#[derive(Default)]
pub(crate) struct TypeAnalyzeContext {
pub is_analyzing_type_in_parameter_context: bool,
}
impl TypeAnalyzeContext {
pub(crate) const fn new_parameter_context() -> Self {
Self {
is_analyzing_type_in_parameter_context: true,
}
}
pub const fn is_analyzing_a_parameter_type(&self) -> bool {
self.is_analyzing_type_in_parameter_context
}
}
impl Analyzer<'_> {
pub fn analyze_map_type(
&mut self,
ast_key_type: &swamp_ast::Type,
ast_value_type: &swamp_ast::Type,
) -> (TypeRef, TypeRef) {
let key_type = self.analyze_type(ast_key_type, &TypeAnalyzeContext::default());
let value_type = self.analyze_type(ast_value_type, &TypeAnalyzeContext::default());
(key_type, value_type)
}
pub fn analyze_key_and_value_type(
&mut self,
ast_key_type: &swamp_ast::Type,
ast_value_type: &swamp_ast::Type,
) -> (TypeRef, TypeRef) {
let key_type = self.analyze_type(ast_key_type, &TypeAnalyzeContext::default());
let value_type = self.analyze_type(ast_value_type, &TypeAnalyzeContext::default());
(key_type, value_type)
}
pub fn analyze_type(
&mut self,
ast_type: &swamp_ast::Type,
ctx: &TypeAnalyzeContext,
) -> TypeRef {
match ast_type {
swamp_ast::Type::AnonymousStruct(ast_struct) => {
let struct_ref = self.analyze_anonymous_struct_type(ast_struct, ctx);
let anon_struct_type = self.shared.state.types.anonymous_struct(struct_ref);
let default_node = swamp_ast::Node::default();
self.add_default_functions(&anon_struct_type, &default_node);
anon_struct_type
}
swamp_ast::Type::FixedCapacityArray(ast_type, fixed_size) => {
let element_type = self.analyze_type(ast_type, &TypeAnalyzeContext::default());
let int_str = self.get_text(fixed_size);
let int_value = Self::str_to_unsigned_int(int_str).unwrap() as usize;
let array_type = self
.shared
.state
.types
.fixed_array(&element_type, int_value);
self.add_default_functions(&array_type, fixed_size);
array_type
}
swamp_ast::Type::Slice(ast_type) => {
let element_type = self.analyze_type(ast_type, &TypeAnalyzeContext::default());
let slice_type = self.shared.state.types.slice_view(&element_type);
let default_node = swamp_ast::Node::default();
self.add_default_functions(&slice_type, &default_node);
slice_type
}
swamp_ast::Type::FixedCapacityMap(ast_key_type, ast_value_type, fixed_size) => {
let (key_type, value_type) =
self.analyze_key_and_value_type(ast_key_type, ast_value_type);
let int_str = self.get_text(fixed_size);
let int_value = Self::str_to_unsigned_int(int_str).unwrap() as usize;
let map_type =
self.shared
.state
.types
.map_storage(&key_type, &value_type, int_value);
self.add_default_functions(&map_type, fixed_size);
map_type
}
swamp_ast::Type::DynamicLengthMap(ast_key_type, ast_value_type) => {
let (key_type, value_type) =
self.analyze_key_and_value_type(ast_key_type, ast_value_type);
let map_view_type = self
.shared
.state
.types
.dynamic_map_view(&key_type, &value_type);
let default_node = swamp_ast::Node::default();
self.add_default_functions(&map_view_type, &default_node);
map_view_type
}
swamp_ast::Type::Tuple(types) => {
let analyzed_types = self.analyze_types(types, &TypeAnalyzeContext::default());
let tuple_type = self.shared.state.types.tuple(analyzed_types);
let default_node = swamp_ast::Node::default();
self.add_default_functions(&tuple_type, &default_node);
tuple_type
}
swamp_ast::Type::Named(ast_type_reference) => {
self.analyze_named_type(ast_type_reference)
}
swamp_ast::Type::Unit => self.shared.state.types.unit(),
swamp_ast::Type::Never => self.shared.state.types.never(),
swamp_ast::Type::Optional(inner_type_ast, _node) => {
let inner_resolved_type =
self.analyze_type(inner_type_ast, &TypeAnalyzeContext::default());
let optional_type = self.shared.state.types.optional(&inner_resolved_type);
let default_node = swamp_ast::Node::default();
self.add_default_functions(&optional_type, &default_node);
optional_type
}
swamp_ast::Type::Function(parameters, return_type) => {
let parameter_types = self.analyze_param_types(parameters);
let resolved_return_type = self.analyze_type(return_type, ctx);
let signature = Signature {
parameters: parameter_types,
return_type: resolved_return_type,
};
self.shared.state.types.function(signature)
}
}
}
pub(crate) fn analyze_types(
&mut self,
types: &[swamp_ast::Type],
ctx: &TypeAnalyzeContext,
) -> Vec<TypeRef> {
let mut resolved_types = Vec::new();
for some_type in types {
resolved_types.push(self.analyze_type(some_type, ctx));
}
resolved_types
}
fn analyze_param_types(
&mut self,
type_for_parameters: &Vec<swamp_ast::TypeForParameter>,
) -> Vec<TypeForParameter> {
let mut vec = Vec::new();
for x in type_for_parameters {
vec.push(TypeForParameter {
name: String::new(),
resolved_type: self.analyze_type(&x.ast_type, &TypeAnalyzeContext::default()),
is_mutable: x.is_mutable,
node: None,
});
}
vec
}
}