1use crate::err::{Error, ErrorKind};
6use crate::{Analyzer, TypeContext};
7use std::rc::Rc;
8use swamp_script_semantic::{
9 EnumLiteralData, EnumVariantType, Expression, Fp, Literal, MapType, MapTypeRef, Node,
10 TupleType, TupleTypeRef, Type,
11};
12use tracing::error;
13
14impl Analyzer<'_> {
15 #[allow(clippy::too_many_lines)]
16 pub(crate) fn analyze_literal(
17 &mut self,
18 ast_node: &swamp_script_ast::Node,
19 ast_literal_kind: &swamp_script_ast::LiteralKind,
20 context: &TypeContext,
21 ) -> Result<(Literal, Type), Error> {
22 let node_text = self.get_text(ast_node);
23 let resolved_literal = match &ast_literal_kind {
24 swamp_script_ast::LiteralKind::Int => (
25 Literal::IntLiteral(Self::str_to_int(node_text).map_err(|int_conversion_err| {
26 self.create_err(ErrorKind::IntConversionError(int_conversion_err), ast_node)
27 })?),
28 Type::Int,
29 ),
30 swamp_script_ast::LiteralKind::Float => {
31 let float = Self::str_to_float(node_text).map_err(|float_conversion_err| {
32 self.create_err(
33 ErrorKind::FloatConversionError(float_conversion_err),
34 ast_node,
35 )
36 })?;
37 (Literal::FloatLiteral(Fp::from(float)), Type::Float)
38 }
39 swamp_script_ast::LiteralKind::String(processed_string) => (
40 Literal::StringLiteral(processed_string.to_string()),
41 Type::String,
42 ),
43 swamp_script_ast::LiteralKind::Bool => {
44 let bool_val = if node_text == "false" {
45 false
46 } else if node_text == "true" {
47 true
48 } else {
49 return Err(self.create_err(ErrorKind::BoolConversionError, ast_node));
50 };
51 (Literal::BoolLiteral(bool_val), Type::Bool)
52 }
53 swamp_script_ast::LiteralKind::EnumVariant(enum_literal) => {
54 let (enum_name, variant_name) = match enum_literal {
55 swamp_script_ast::EnumVariantLiteral::Simple(enum_name, variant_name) => {
56 (enum_name, variant_name)
57 }
58 swamp_script_ast::EnumVariantLiteral::Tuple(enum_name, variant_name, _) => {
59 (enum_name, variant_name)
60 }
61 swamp_script_ast::EnumVariantLiteral::Struct(enum_name, variant_name, _) => {
62 (enum_name, variant_name)
63 }
64 };
65
66 let (symbol_table, name) = self.get_symbol_table_and_name(enum_name)?;
67 if let Some(enum_type_ref) = symbol_table.get_enum(&name) {
68 let enum_type = Type::Enum(enum_type_ref.clone());
69
70 let variant_ref = self.analyze_enum_variant_ref(enum_name, variant_name)?;
72
73 let resolved_data = match enum_literal {
74 swamp_script_ast::EnumVariantLiteral::Simple(_, _) => {
75 EnumLiteralData::Nothing
76 }
77 swamp_script_ast::EnumVariantLiteral::Tuple(
78 _node,
79 _variant,
80 expressions,
81 ) => {
82 let resolved = self.analyze_argument_expressions(None, expressions)?;
83 EnumLiteralData::Tuple(resolved)
84 }
85 swamp_script_ast::EnumVariantLiteral::Struct(
86 _qualified_type_identifier,
87 variant,
88 anonym_struct_field_and_expressions,
89 ) => {
90 if let EnumVariantType::Struct(resolved_variant_struct_ref) =
91 &*variant_ref
92 {
93 if anonym_struct_field_and_expressions.len()
94 != resolved_variant_struct_ref
95 .anon_struct
96 .field_name_sorted_fields
97 .len()
98 {
99 return Err(self.create_err(
100 ErrorKind::WrongNumberOfArguments(
101 anonym_struct_field_and_expressions.len(),
102 resolved_variant_struct_ref
103 .anon_struct
104 .field_name_sorted_fields
105 .len(),
106 ),
107 &variant.0,
108 ));
109 }
110
111 let resolved = self.analyze_anon_struct_instantiation(
112 &variant.0.clone(),
113 &resolved_variant_struct_ref.anon_struct,
114 anonym_struct_field_and_expressions,
115 false,
116 )?;
117
118 EnumLiteralData::Struct(resolved)
119 } else {
120 return Err(self.create_err(
121 ErrorKind::WrongEnumVariantContainer(variant_ref.clone()),
122 &variant.0,
123 ));
124 }
125 }
126 };
127
128 return Ok((
129 Literal::EnumVariantLiteral(variant_ref, resolved_data),
130 enum_type,
131 ));
132 }
133 return Err(self.create_err(ErrorKind::UnknownEnumType, ast_node));
134 }
135
136 swamp_script_ast::LiteralKind::Array(items) => {
137 if items.len() == 0 {
138 if let Some(found_expected_type) = context.expected_type {
139 match found_expected_type {
140 Type::Map(map_type_ref) => (
141 Literal::Map(map_type_ref.clone(), vec![]),
142 found_expected_type.clone(),
143 ),
144 Type::Array(array_type_ref) => (
145 Literal::Array(array_type_ref.clone(), vec![]),
146 found_expected_type.clone(),
147 ),
148 _ => {
149 return Err(self.create_err(
150 ErrorKind::EmptyArrayCanOnlyBeMapOrArray,
151 ast_node,
152 ));
153 }
154 }
155 } else {
156 return Err(
157 self.create_err(ErrorKind::EmptyArrayCanOnlyBeMapOrArray, ast_node)
158 );
159 }
160 } else {
161 let (array_type_ref, resolved_items) =
162 self.analyze_array_type_helper(ast_node, items, context.expected_type)?;
163 (
164 Literal::Array(array_type_ref.clone(), resolved_items),
165 Type::Array(array_type_ref),
166 )
167 }
168 }
169
170 swamp_script_ast::LiteralKind::Map(entries) => {
171 let (map_literal, map_type_ref) = self.analyze_map_literal(ast_node, &entries)?;
172
173 (map_literal, Type::Map(map_type_ref))
174 }
175
176 swamp_script_ast::LiteralKind::Tuple(expressions) => {
177 let (tuple_type_ref, resolved_items) = self.analyze_tuple_literal(&expressions)?;
178 (
179 Literal::TupleLiteral(tuple_type_ref.clone(), resolved_items),
180 Type::Tuple(tuple_type_ref),
181 )
182 }
183 swamp_script_ast::LiteralKind::None => {
184 if let Some(found_expected_type) = context.expected_type {
185 if let Type::Optional(_some_type) = found_expected_type {
186 return Ok((Literal::NoneLiteral, found_expected_type.clone()));
187 }
188 }
189 return Err(self.create_err(ErrorKind::NoneNeedsExpectedTypeHint, &ast_node));
190 }
191 };
192
193 Ok(resolved_literal)
194 }
195
196 fn analyze_tuple_literal(
197 &mut self,
198 items: &[swamp_script_ast::Expression],
199 ) -> Result<(TupleTypeRef, Vec<Expression>), Error> {
200 let expressions = self.analyze_argument_expressions(None, items)?;
201 let mut tuple_types = Vec::new();
202 for expr in &expressions {
203 let item_type = expr.ty.clone();
204 tuple_types.push(item_type);
205 }
206
207 let tuple_type = TupleType(tuple_types);
208
209 let tuple_type_ref = Rc::new(tuple_type);
210
211 Ok((tuple_type_ref, expressions))
212 }
213
214 fn analyze_map_literal(
215 &mut self,
216 node: &swamp_script_ast::Node,
217 entries: &[(swamp_script_ast::Expression, swamp_script_ast::Expression)],
218 ) -> Result<(Literal, MapTypeRef), Error> {
219 if entries.is_empty() {
220 return Err(self.create_err(ErrorKind::EmptyMapLiteral, node));
221 }
222
223 let (first_key, first_value) = &entries[0];
225 let anything_context = TypeContext::new_anything_argument();
226 let resolved_first_key = self.analyze_expression(first_key, &anything_context)?;
227 let resolved_first_value = self.analyze_expression(first_value, &anything_context)?;
228 let key_type = resolved_first_key.ty.clone();
229 let value_type = resolved_first_value.ty.clone();
230
231 let key_context = TypeContext::new_argument(&key_type);
232 let value_context = TypeContext::new_argument(&value_type);
233
234 let mut resolved_entries = Vec::new();
236 resolved_entries.push((resolved_first_key, resolved_first_value));
237
238 for (key, value) in entries.iter().skip(1) {
239 let resolved_key = self.analyze_expression(key, &key_context)?;
240 let resolved_value = self.analyze_expression(value, &value_context)?;
241
242 if !resolved_key.ty.compatible_with(&key_type) {
243 return Err(self.create_err(
244 ErrorKind::MapKeyTypeMismatch {
245 expected: key_type,
246 found: resolved_key.ty,
247 },
248 node,
249 ));
250 }
251
252 if !resolved_value.ty.compatible_with(&value_type) {
253 return Err(self.create_err(
254 ErrorKind::MapValueTypeMismatch {
255 expected: value_type,
256 found: resolved_value.ty,
257 },
258 node,
259 ));
260 }
261
262 resolved_entries.push((resolved_key, resolved_value));
263 }
264
265 let resolved_map_type = MapType {
266 key_type,
267 value_type,
268 };
269
270 let resolved_map_type_ref = Rc::new(resolved_map_type);
271
272 let literal = Literal::Map(resolved_map_type_ref.clone(), resolved_entries);
273 Ok((literal, resolved_map_type_ref))
274 }
275
276 #[must_use]
277 pub fn create_err(&self, kind: ErrorKind, ast_node: &swamp_script_ast::Node) -> Error {
278 error!(?kind, "error created");
279 Error {
280 node: self.to_node(ast_node),
281 kind,
282 }
283 }
284
285 #[must_use]
286 pub fn create_err_resolved(&self, kind: ErrorKind, resolved_node: &Node) -> Error {
287 Error {
288 node: resolved_node.clone(),
289 kind,
290 }
291 }
292}