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<'a> Analyzer<'a> {
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.anon_struct.defined_fields.len()
95 {
96 return Err(self.create_err(
97 ErrorKind::WrongNumberOfArguments(
98 anonym_struct_field_and_expressions.len(),
99 resolved_variant_struct_ref
100 .anon_struct
101 .defined_fields
102 .len(),
103 ),
104 &variant.0,
105 ));
106 }
107
108 let resolved = self.analyze_anon_struct_instantiation(
109 &variant.0.clone(),
110 &resolved_variant_struct_ref.anon_struct,
111 anonym_struct_field_and_expressions,
112 false,
113 )?;
114
115 EnumLiteralData::Struct(resolved)
116 } else {
117 return Err(self.create_err(
118 ErrorKind::WrongEnumVariantContainer(variant_ref.clone()),
119 &variant.0,
120 ));
121 }
122 }
123 };
124
125 return Ok((
126 Literal::EnumVariantLiteral(variant_ref, resolved_data),
127 enum_type,
128 ));
129 }
130 return Err(self.create_err(ErrorKind::UnknownEnumType, ast_node));
131 }
132
133 swamp_script_ast::LiteralKind::Array(items) => {
134 if items.len() == 0 {
135 if let Some(found_expected_type) = context.expected_type {
136 match found_expected_type {
137 Type::Map(map_type_ref) => (
138 Literal::Map(map_type_ref.clone(), vec![]),
139 found_expected_type.clone(),
140 ),
141 Type::Array(array_type_ref) => (
142 Literal::Array(array_type_ref.clone(), vec![]),
143 found_expected_type.clone(),
144 ),
145 _ => {
146 return Err(self.create_err(
147 ErrorKind::EmptyArrayCanOnlyBeMapOrArray,
148 &ast_node,
149 ));
150 }
151 }
152 } else {
153 return Err(
154 self.create_err(ErrorKind::EmptyArrayCanOnlyBeMapOrArray, ast_node)
155 );
156 }
157 } else {
158 let (array_type_ref, resolved_items) =
159 self.analyze_array_type_helper(ast_node, items, context.expected_type)?;
160 (
161 Literal::Array(array_type_ref.clone(), resolved_items),
162 Type::Array(array_type_ref),
163 )
164 }
165 }
166
167 swamp_script_ast::LiteralKind::Map(entries) => {
168 let (map_literal, map_type_ref) = self.analyze_map_literal(ast_node, &entries)?;
169
170 (map_literal, Type::Map(map_type_ref.clone()))
171 }
172
173 swamp_script_ast::LiteralKind::Tuple(expressions) => {
174 let (tuple_type_ref, resolved_items) = self.analyze_tuple_literal(&expressions)?;
175 (
176 Literal::TupleLiteral(tuple_type_ref.clone(), resolved_items),
177 Type::Tuple(tuple_type_ref.clone()),
178 )
179 }
180 swamp_script_ast::LiteralKind::None => {
181 if let Some(found_expected_type) = context.expected_type {
182 if let Type::Optional(_some_type) = found_expected_type {
183 return Ok((Literal::NoneLiteral, found_expected_type.clone()));
184 }
185 }
186 return Err(self.create_err(ErrorKind::NoneNeedsExpectedTypeHint, &ast_node));
187 }
188 };
189
190 Ok(resolved_literal)
191 }
192
193 fn analyze_tuple_literal(
194 &mut self,
195 items: &[swamp_script_ast::Expression],
196 ) -> Result<(TupleTypeRef, Vec<Expression>), Error> {
197 let expressions = self.analyze_argument_expressions(None, items)?;
198 let mut tuple_types = Vec::new();
199 for expr in &expressions {
200 let item_type = expr.ty.clone();
201 tuple_types.push(item_type);
202 }
203
204 let tuple_type = TupleType(tuple_types);
205
206 let tuple_type_ref = Rc::new(tuple_type);
207
208 Ok((tuple_type_ref, expressions))
209 }
210
211 fn analyze_map_literal(
212 &mut self,
213 node: &swamp_script_ast::Node,
214 entries: &[(swamp_script_ast::Expression, swamp_script_ast::Expression)],
215 ) -> Result<(Literal, MapTypeRef), Error> {
216 if entries.is_empty() {
217 return Err(self.create_err(ErrorKind::EmptyMapLiteral, node));
218 }
219
220 let (first_key, first_value) = &entries[0];
222 let anything_context = TypeContext::new_anything_argument();
223 let resolved_first_key = self.analyze_expression(first_key, &anything_context)?;
224 let resolved_first_value = self.analyze_expression(first_value, &anything_context)?;
225 let key_type = resolved_first_key.ty.clone();
226 let value_type = resolved_first_value.ty.clone();
227
228 let key_context = TypeContext::new_argument(&key_type);
229 let value_context = TypeContext::new_argument(&value_type);
230
231 let mut resolved_entries = Vec::new();
233 resolved_entries.push((resolved_first_key, resolved_first_value));
234
235 for (key, value) in entries.iter().skip(1) {
236 let resolved_key = self.analyze_expression(key, &key_context)?;
237 let resolved_value = self.analyze_expression(value, &value_context)?;
238
239 if !resolved_key.ty.compatible_with(&key_type) {
240 return Err(self.create_err(
241 ErrorKind::MapKeyTypeMismatch {
242 expected: key_type,
243 found: resolved_key.ty.clone(),
244 },
245 node,
246 ));
247 }
248
249 if !resolved_value.ty.compatible_with(&value_type) {
250 return Err(self.create_err(
251 ErrorKind::MapValueTypeMismatch {
252 expected: value_type,
253 found: resolved_value.ty.clone(),
254 },
255 node,
256 ));
257 }
258
259 resolved_entries.push((resolved_key, resolved_value));
260 }
261
262 let resolved_map_type = MapType {
263 key_type,
264 value_type,
265 };
266
267 let resolved_map_type_ref = Rc::new(resolved_map_type);
268
269 let literal = Literal::Map(resolved_map_type_ref.clone(), resolved_entries);
270 Ok((literal, resolved_map_type_ref))
271 }
272
273 #[must_use]
274 pub fn create_err(&self, kind: ErrorKind, ast_node: &swamp_script_ast::Node) -> Error {
275 error!(?kind, "error created");
276 Error {
277 node: self.to_node(ast_node),
278 kind,
279 }
280 }
281
282 #[must_use]
283 pub fn create_err_resolved(&self, kind: ErrorKind, resolved_node: &Node) -> Error {
284 Error {
285 node: resolved_node.clone(),
286 kind,
287 }
288 }
289}