1use crate::{Analyzer, TypeContext};
6use source_map_node::Node;
7use std::env::current_dir;
8use swamp_semantic::err::ErrorKind;
9use swamp_semantic::prelude::Error;
10use swamp_semantic::{EnumLiteralExpressions, ExpressionKind};
11use swamp_semantic::{Expression, Fp};
12use swamp_types::prelude::*;
13use tracing::{error, warn};
14
15impl Analyzer<'_> {
16 #[allow(clippy::too_many_lines)]
21 pub fn analyze_complex_literal_to_expression(
22 &mut self,
23 ast_expression: &swamp_ast::Expression,
24 ast_literal_kind: &swamp_ast::LiteralKind,
25 context: &TypeContext,
26 ) -> Expression {
27 let ast_node = &ast_expression.node;
28 let (lit_kind, literal_type) = match &ast_literal_kind {
29 swamp_ast::LiteralKind::InternalInitializerList(items) => {
30 let (collection_type, resolved_items) =
31 self.analyze_internal_initializer_list(ast_node, items, context);
32
33 (
34 ExpressionKind::InitializerList(collection_type.clone(), resolved_items),
35 collection_type,
36 )
37 }
38
39 swamp_ast::LiteralKind::InternalInitializerPairList(entries) => {
40 let (collection_type, resolved_items) =
41 self.analyze_internal_initializer_pair_list(ast_node, entries, context);
42
43 (
44 ExpressionKind::InitializerPairList(collection_type.clone(), resolved_items),
45 collection_type,
46 )
47 }
48
49 _ => return self.analyze_literal(ast_node, ast_literal_kind, context),
50 };
51
52 self.create_expr(lit_kind, literal_type, ast_node)
53 }
54
55 #[allow(clippy::too_many_lines)]
56 pub(crate) fn analyze_literal(
57 &mut self,
58 ast_node: &swamp_ast::Node,
59 ast_literal_kind: &swamp_ast::LiteralKind,
60 context: &TypeContext,
61 ) -> Expression {
62 let node_text = self.get_text(ast_node);
63 let (expression_kind, ty) = match &ast_literal_kind {
64 swamp_ast::LiteralKind::Int => match Self::str_to_int(node_text) {
65 Err(int_err) => {
66 return self.create_err(ErrorKind::IntConversionError(int_err), ast_node);
67 }
68 Ok(int_value) => (
69 ExpressionKind::IntLiteral(int_value),
70 self.shared.state.types.int(),
71 ),
72 },
73 swamp_ast::LiteralKind::Float => match Self::str_to_float(node_text) {
74 Err(float_err) => {
75 return self.create_err(ErrorKind::FloatConversionError(float_err), ast_node);
76 }
77 Ok(float_value) => (
78 ExpressionKind::FloatLiteral(Fp::from(float_value)),
79 self.shared.state.types.float(),
80 ),
81 },
82 swamp_ast::LiteralKind::String(processed_string) => (
83 ExpressionKind::StringLiteral(processed_string.to_string()),
84 self.shared.state.types.string(),
85 ),
86 swamp_ast::LiteralKind::Bool => match Self::str_to_bool(node_text) {
87 Err(_bool_err) => return self.create_err(ErrorKind::BoolConversionError, ast_node),
88 Ok(bool_value) => (
89 ExpressionKind::BoolLiteral(bool_value),
90 self.shared.state.types.bool(),
91 ),
92 },
93 swamp_ast::LiteralKind::EnumVariant(enum_literal) => {
94 let (enum_name, variant_name_node) = match enum_literal {
95 swamp_ast::EnumVariantLiteral::Simple(enum_name, variant_name) => {
96 (enum_name, variant_name)
97 }
98 swamp_ast::EnumVariantLiteral::Tuple(enum_name, variant_name, _) => {
99 (enum_name, variant_name)
100 }
101 swamp_ast::EnumVariantLiteral::Struct(enum_name, variant_name, _, _) => {
102 (enum_name, variant_name)
103 }
104 };
105
106 let variant_name_text = self.get_text(&variant_name_node.0).to_string();
108
109 let found_enum_type = {
111 let Some((symbol_table, name)) = self.get_symbol_table_and_name(enum_name)
112 else {
113 self.add_err(ErrorKind::UnknownModule, &enum_name.name.0);
114 return self.create_err(ErrorKind::UnknownEnumVariantType, ast_node);
115 };
116 let Some(found_enum_type) = symbol_table.get_type(&name) else {
117 return self.create_err(ErrorKind::UnknownEnumType, ast_node);
118 };
119 found_enum_type.clone()
120 };
121
122 let TypeKind::Enum(enum_type) = &*found_enum_type.kind else {
123 return self.create_err(ErrorKind::UnknownEnumType, ast_node);
124 };
125 let variant_name = &variant_name_text;
126 let Some(variant_ref) = enum_type.get_variant(variant_name) else {
128 return self
129 .create_err(ErrorKind::UnknownEnumVariantType, &variant_name_node.0);
130 };
131
132 let resolved_data = match enum_literal {
133 swamp_ast::EnumVariantLiteral::Simple(_, _) => EnumLiteralExpressions::Nothing,
134 swamp_ast::EnumVariantLiteral::Tuple(_node, _variant, ast_expressions) => {
135 if let TypeKind::Tuple(tuple_field_types) = &*variant_ref.payload_type.kind
136 {
137 if tuple_field_types.len() != ast_expressions.len() {
139 return self.create_err(
140 ErrorKind::WrongNumberOfArguments(
141 tuple_field_types.len(),
142 ast_expressions.len(),
143 ),
144 ast_node,
145 );
146 }
147
148 let resolved_expression = tuple_field_types
149 .iter()
150 .zip(ast_expressions)
151 .map(|(expected_type, ast_expression)| {
152 let ctx = context.argument(expected_type);
153 self.analyze_expression(ast_expression, &ctx)
154 })
155 .collect();
156
157 EnumLiteralExpressions::Tuple(resolved_expression)
158 } else {
159 if ast_expressions.len() != 1 {
161 return self.create_err(
162 ErrorKind::WrongNumberOfArguments(1, ast_expressions.len()),
163 ast_node,
164 );
165 }
166
167 let ctx = context.argument(&variant_ref.payload_type);
168 let resolved_expression =
169 self.analyze_expression(&ast_expressions[0], &ctx);
170
171 EnumLiteralExpressions::Tuple(vec![resolved_expression])
172 }
173 }
174 swamp_ast::EnumVariantLiteral::Struct(
175 _qualified_type_identifier,
176 variant,
177 anonym_struct_field_and_expressions,
178 detected_rest,
179 ) => {
180 let TypeKind::AnonymousStruct(anon_payload) =
181 &*variant_ref.payload_type.kind
182 else {
183 return self.create_err(
184 ErrorKind::WrongEnumVariantContainer(variant_ref.clone()),
185 ast_node,
186 );
187 };
188
189 if anonym_struct_field_and_expressions.len()
190 != anon_payload.field_name_sorted_fields.len()
191 {
192 return self.create_err(
193 ErrorKind::WrongNumberOfArguments(
194 anonym_struct_field_and_expressions.len(),
195 anon_payload.field_name_sorted_fields.len(),
196 ),
197 &variant.0,
198 );
199 }
200
201 let resolved_fields = self.analyze_anon_struct_instantiation(
202 &variant.0.clone(),
203 anon_payload,
204 anonym_struct_field_and_expressions,
205 *detected_rest,
206 );
207
208 EnumLiteralExpressions::Struct(resolved_fields)
209 }
210 };
211
212 (
213 ExpressionKind::EnumVariantLiteral(variant_ref.clone(), resolved_data),
214 found_enum_type.clone(),
215 )
216 }
217
218 swamp_ast::LiteralKind::Tuple(expressions) => {
219 let (tuple_type_ref, resolved_items) =
220 self.analyze_tuple_literal(expressions, context);
221 let tuple_type = self.shared.state.types.tuple(tuple_type_ref);
222 (ExpressionKind::TupleLiteral(resolved_items), tuple_type)
223 }
224 swamp_ast::LiteralKind::None => {
225 if let Some(found_expected_type) = context.expected_type {
226 let underlying = found_expected_type;
227 if let TypeKind::Optional(_some_type) = &*underlying.kind {
228 (ExpressionKind::NoneLiteral, underlying.clone())
229 } else {
230 return self.create_err(ErrorKind::NoneNeedsExpectedTypeHint, ast_node);
231 }
232 } else {
233 return self.create_err(ErrorKind::NoneNeedsExpectedTypeHint, ast_node);
234 }
235 }
236 &&swamp_ast::LiteralKind::InternalInitializerList(_)
237 | &swamp_ast::LiteralKind::InternalInitializerPairList(_) => {
238 panic!("initializer lists are not basic literals")
239 }
240 };
241
242 self.create_expr(expression_kind, ty, ast_node)
243 }
244
245 fn analyze_tuple_literal(
246 &mut self,
247 items: &[swamp_ast::Expression],
248 context: &TypeContext,
249 ) -> (Vec<TypeRef>, Vec<Expression>) {
250 let expressions = self.analyze_argument_expressions(None, context, items);
251 let mut tuple_types = Vec::new();
252 for expr in &expressions {
253 let item_type = expr.ty.clone();
254 tuple_types.push(item_type);
255 }
256
257 (tuple_types, expressions)
258 }
259
260 fn analyze_tuple_type(
261 &mut self,
262 node: &swamp_ast::Node,
263 expected_types: &[TypeRef],
264 ast_expressions: &Vec<swamp_ast::Expression>,
265 ) -> Vec<Expression> {
266 if ast_expressions.len() != expected_types.len() {
267 return vec![self.create_err(
268 ErrorKind::WrongNumberOfArguments(expected_types.len(), ast_expressions.len()),
269 node,
270 )];
271 }
272
273 let mut expressions = Vec::new();
274 for (expected_type, expr) in expected_types.iter().zip(ast_expressions) {
275 let context = TypeContext::new_argument(
276 expected_type,
277 expected_type.collection_view_that_needs_explicit_storage(),
278 );
279 let resolved_expr = self.analyze_expression(expr, &context);
280 expressions.push(resolved_expr);
281 }
282
283 expressions
284 }
285
286 pub fn add_err(&mut self, kind: ErrorKind, ast_node: &swamp_ast::Node) {
287 self.add_err_resolved(kind, &self.to_node(ast_node));
288 }
289 pub(crate) fn add_hint(&mut self, kind: ErrorKind, ast_node: &swamp_ast::Node) {
290 self.add_hint_resolved(kind, &self.to_node(ast_node));
291 }
292
293 pub(crate) fn add_hint_resolved(&mut self, kind: ErrorKind, node: &Node) {
294 warn!(?kind, "add error");
295 let err = Error {
296 node: node.clone(),
297 kind,
298 };
299 let line_info = self
300 .shared
301 .source_map
302 .get_line(&node.span, ¤t_dir().unwrap());
303
304 eprintln!("{}:{} {}", line_info.row, line_info.col, line_info.line);
305 self.shared.state.hints.push(err);
306 }
307
308 pub(crate) fn add_err_resolved(&mut self, kind: ErrorKind, node: &Node) {
309 error!(?kind, "add error");
310 let err = Error {
311 node: node.clone(),
312 kind,
313 };
314 let line_info = self
315 .shared
316 .source_map
317 .get_line(&node.span, ¤t_dir().unwrap());
318
319 eprintln!("{}:{} {}", line_info.row, line_info.col, line_info.line);
320 self.shared.state.errors.push(err);
321 }
322
323 #[must_use]
324 pub fn create_err_vec(
325 &mut self,
326 kind: ErrorKind,
327 ast_node: &swamp_ast::Node,
328 ) -> Vec<Expression> {
329 vec![self.create_err(kind, ast_node)]
330 }
331
332 #[must_use]
333 pub fn create_err(&mut self, kind: ErrorKind, ast_node: &swamp_ast::Node) -> Expression {
334 self.add_err(kind.clone(), ast_node);
335
336 Expression {
337 ty: self.types().unit(),
338 node: self.to_node(ast_node),
339 kind: ExpressionKind::Error(kind),
340 }
341 }
342 #[must_use]
343 pub fn create_err_resolved(&mut self, kind: ErrorKind, resolved_node: &Node) -> Expression {
344 self.add_err_resolved(kind.clone(), resolved_node);
345
346 Expression {
347 ty: self.types().unit(),
348 node: resolved_node.clone(),
349 kind: ExpressionKind::Error(kind),
350 }
351 }
352}