swamp_analyzer/
types.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use crate::Analyzer;
6use swamp_types::TypeRef;
7use swamp_types::prelude::{Signature, TypeForParameter};
8
9#[derive(Default)]
10pub(crate) struct TypeAnalyzeContext {
11    pub is_analyzing_type_in_parameter_context: bool,
12}
13
14impl TypeAnalyzeContext {
15    pub(crate) const fn new_parameter_context() -> Self {
16        Self {
17            is_analyzing_type_in_parameter_context: true,
18        }
19    }
20
21    pub const fn is_analyzing_a_parameter_type(&self) -> bool {
22        self.is_analyzing_type_in_parameter_context
23    }
24}
25
26impl Analyzer<'_> {
27    /// # Errors
28    ///
29    pub fn analyze_map_type(
30        &mut self,
31        ast_key_type: &swamp_ast::Type,
32        ast_value_type: &swamp_ast::Type,
33    ) -> (TypeRef, TypeRef) {
34        let key_type = self.analyze_type(ast_key_type, &TypeAnalyzeContext::default());
35        let value_type = self.analyze_type(ast_value_type, &TypeAnalyzeContext::default());
36
37        // Using TypeCache to ensure proper type comparison and creation
38        (key_type, value_type)
39    }
40
41    /// # Errors
42    ///
43    pub fn analyze_key_and_value_type(
44        &mut self,
45        ast_key_type: &swamp_ast::Type,
46        ast_value_type: &swamp_ast::Type,
47    ) -> (TypeRef, TypeRef) {
48        let key_type = self.analyze_type(ast_key_type, &TypeAnalyzeContext::default());
49        let value_type = self.analyze_type(ast_value_type, &TypeAnalyzeContext::default());
50
51        // Using TypeCache to ensure proper type comparison and creation
52        (key_type, value_type)
53    }
54
55    /// # Errors
56    ///
57    /// # Panics
58    pub fn analyze_type(
59        &mut self,
60        ast_type: &swamp_ast::Type,
61        ctx: &TypeAnalyzeContext,
62    ) -> TypeRef {
63        match ast_type {
64            swamp_ast::Type::AnonymousStruct(ast_struct) => {
65                let struct_ref = self.analyze_anonymous_struct_type(ast_struct, ctx);
66                // Use TypeCache to create the anonymous struct type
67                let anon_struct_type = self.shared.state.types.anonymous_struct(struct_ref);
68
69                // Generate default functions for the new anonymous struct type
70                let default_node = swamp_ast::Node::default();
71                self.add_default_functions(&anon_struct_type, &default_node);
72
73                anon_struct_type
74            }
75            swamp_ast::Type::FixedCapacityArray(ast_type, fixed_size) => {
76                let element_type = self.analyze_type(ast_type, &TypeAnalyzeContext::default());
77                let int_str = self.get_text(fixed_size);
78                let int_value = Self::str_to_unsigned_int(int_str).unwrap() as usize;
79
80                // Use TypeCache for fixed array creation
81                let array_type = self
82                    .shared
83                    .state
84                    .types
85                    .fixed_array(&element_type, int_value);
86
87                // Generate default functions for the new array type
88                self.add_default_functions(&array_type, fixed_size);
89
90                array_type
91            }
92            swamp_ast::Type::Slice(ast_type) => {
93                let element_type = self.analyze_type(ast_type, &TypeAnalyzeContext::default());
94                // Use TypeCache for slice view creation
95                let slice_type = self.shared.state.types.slice_view(&element_type);
96
97                // Generate default functions for the new slice type
98                let default_node = swamp_ast::Node::default();
99                self.add_default_functions(&slice_type, &default_node);
100
101                slice_type
102            }
103
104            swamp_ast::Type::FixedCapacityMap(ast_key_type, ast_value_type, fixed_size) => {
105                let (key_type, value_type) =
106                    self.analyze_key_and_value_type(ast_key_type, ast_value_type);
107
108                let int_str = self.get_text(fixed_size);
109                let int_value = Self::str_to_unsigned_int(int_str).unwrap() as usize;
110
111                // Use TypeCache for map storage creation
112                let map_type =
113                    self.shared
114                        .state
115                        .types
116                        .map_storage(&key_type, &value_type, int_value);
117
118                // Generate default functions for the new map type
119                self.add_default_functions(&map_type, fixed_size);
120
121                map_type
122            }
123            swamp_ast::Type::DynamicLengthMap(ast_key_type, ast_value_type) => {
124                let (key_type, value_type) =
125                    self.analyze_key_and_value_type(ast_key_type, ast_value_type);
126
127                // Use TypeCache for dynamic map view creation
128                let map_view_type = self
129                    .shared
130                    .state
131                    .types
132                    .dynamic_map_view(&key_type, &value_type);
133
134                // Generate default functions for the new map view type
135                let default_node = swamp_ast::Node::default();
136                self.add_default_functions(&map_view_type, &default_node);
137
138                map_view_type
139            }
140
141            swamp_ast::Type::Tuple(types) => {
142                let analyzed_types = self.analyze_types(types, &TypeAnalyzeContext::default());
143                // Use TypeCache for tuple creation
144                let tuple_type = self.shared.state.types.tuple(analyzed_types);
145
146                // Generate default functions for the new tuple type
147                let default_node = swamp_ast::Node::default();
148                self.add_default_functions(&tuple_type, &default_node);
149
150                tuple_type
151            }
152            swamp_ast::Type::Named(ast_type_reference) => {
153                // Named types need to be analyzed through the TypeCache as well
154                self.analyze_named_type(ast_type_reference)
155            }
156            swamp_ast::Type::Unit => self.shared.state.types.unit(),
157            swamp_ast::Type::Never => self.shared.state.types.never(),
158            swamp_ast::Type::Optional(inner_type_ast, _node) => {
159                let inner_resolved_type =
160                    self.analyze_type(inner_type_ast, &TypeAnalyzeContext::default());
161                // Use TypeCache for optional type creation
162                let optional_type = self.shared.state.types.optional(&inner_resolved_type);
163
164                // Generate default functions for the new optional type
165                let default_node = swamp_ast::Node::default();
166                self.add_default_functions(&optional_type, &default_node);
167
168                optional_type
169            }
170            swamp_ast::Type::Function(parameters, return_type) => {
171                let parameter_types = self.analyze_param_types(parameters);
172
173                let resolved_return_type = self.analyze_type(return_type, ctx);
174                let signature = Signature {
175                    parameters: parameter_types,
176                    return_type: resolved_return_type,
177                };
178                // Use TypeCache for function type creation
179                self.shared.state.types.function(signature)
180            }
181        }
182    }
183
184    pub(crate) fn analyze_types(
185        &mut self,
186        types: &[swamp_ast::Type],
187        ctx: &TypeAnalyzeContext,
188    ) -> Vec<TypeRef> {
189        let mut resolved_types = Vec::new();
190        for some_type in types {
191            resolved_types.push(self.analyze_type(some_type, ctx));
192        }
193        resolved_types
194    }
195
196    fn analyze_param_types(
197        &mut self,
198        type_for_parameters: &Vec<swamp_ast::TypeForParameter>,
199    ) -> Vec<TypeForParameter> {
200        let mut vec = Vec::new();
201        for x in type_for_parameters {
202            vec.push(TypeForParameter {
203                name: String::new(),
204                // Use TypeCache to ensure the resolved type is properly created
205                resolved_type: self.analyze_type(&x.ast_type, &TypeAnalyzeContext::default()),
206                is_mutable: x.is_mutable,
207                node: None,
208            });
209        }
210
211        vec
212    }
213}