1pub mod access;
6pub mod call;
7pub mod constant;
8pub mod def;
9pub mod err;
10pub mod literal;
11pub mod operator;
12pub mod pattern;
13pub mod prelude;
14mod structure;
15pub mod types;
16pub mod variable;
17
18use crate::call::MaybeBorrowMutRefExpression;
19use crate::err::{Error, ErrorKind};
20use seq_map::SeqMap;
21use source_map_cache::SourceMap;
22use source_map_node::{FileId, Node, Span};
23use std::mem::take;
24use std::num::{ParseFloatError, ParseIntError};
25use std::ops::Deref;
26use swamp_modules::prelude::*;
27use swamp_modules::symtbl::{SymbolTableRef, TypeGeneratorKind};
28use swamp_semantic::instantiator::TypeVariableScope;
29use swamp_semantic::prelude::*;
30use swamp_semantic::type_var_stack::SemanticContext;
31use swamp_semantic::{
32 BlockScope, BlockScopeMode, FunctionScopeState, InternalMainExpression, LocationAccess,
33 LocationAccessKind, MutRefOrImmutableExpression, MutableReferenceKind, NormalPattern, Postfix,
34 PostfixKind, SingleLocationExpression, TargetAssignmentLocation, TypeWithMut, WhenBinding,
35};
36use swamp_types::all_types_are_concrete_or_unit;
37use swamp_types::prelude::*;
38use tracing::info;
39
40#[derive(Copy, Clone, Eq, PartialEq, Debug)]
41pub enum LocationSide {
42 Lhs,
43 Rhs,
44}
45
46#[derive(Debug)]
47pub struct Program {
48 pub state: ProgramState,
49 pub modules: Modules,
50 pub default_symbol_table: SymbolTable,
51}
52
53impl Default for Program {
54 fn default() -> Self {
55 Self::new(ProgramState::new(), Modules::new(), SymbolTable::new(&[]))
56 }
57}
58
59impl Program {
60 #[must_use]
61 pub const fn new(
62 state: ProgramState,
63 modules: Modules,
64 default_symbol_table: SymbolTable,
65 ) -> Self {
66 Self {
67 state,
68 modules,
69 default_symbol_table,
70 }
71 }
72}
73
74#[must_use]
75pub const fn convert_span(without: &swamp_ast::SpanWithoutFileId, file_id: FileId) -> Span {
76 Span {
77 file_id,
78 offset: without.offset,
79 length: without.length,
80 }
81}
82
83#[derive(Debug, Clone)]
85pub struct TypeContext<'a> {
86 pub expected_type: Option<&'a Type>,
88}
89
90impl<'a> TypeContext<'a> {
91 #[must_use]
92 pub const fn new(expected_type: Option<&'a Type>) -> Self {
93 Self { expected_type }
94 }
95
96 #[must_use]
97 pub const fn new_argument(required_type: &'a Type) -> Self {
98 Self {
99 expected_type: Some(required_type),
100 }
101 }
102
103 #[must_use]
104 pub const fn new_unsure_argument(expected_type: Option<&'a Type>) -> Self {
105 Self { expected_type }
106 }
107
108 #[must_use]
109 pub const fn new_anything_argument() -> Self {
110 Self {
111 expected_type: None,
112 }
113 }
114
115 #[must_use]
116 pub const fn new_function(required_type: &'a Type) -> Self {
117 Self {
118 expected_type: Some(required_type),
119 }
120 }
121
122 #[must_use]
123 pub const fn with_expected_type(&self, expected_type: Option<&'a Type>) -> Self {
124 Self { expected_type }
125 }
126
127 pub(crate) const fn we_know_expected_type(&self, found_type: &'a Type) -> Self {
128 self.with_expected_type(Some(found_type))
129 }
130}
131
132pub struct SharedState<'a> {
133 pub state: &'a mut ProgramState,
134 pub lookup_table: SymbolTable,
135 pub definition_table: SymbolTable,
136 pub modules: &'a Modules,
137 pub source_map: &'a SourceMap,
138 pub file_id: FileId,
139 pub core_symbol_table: SymbolTableRef,
140 pub type_variables: SemanticContext,
141}
142
143impl<'a> SharedState<'a> {
144 #[must_use]
145 pub fn get_symbol_table(&'a self, path: &[String]) -> Option<&'a SymbolTable> {
146 if path.is_empty() {
147 return Some(&self.lookup_table);
148 }
149 self.get_module(path).map(|module| &module.symbol_table)
150 }
151
152 #[must_use]
153 pub fn get_module(&'a self, path: &[String]) -> Option<&'a ModuleRef> {
154 let resolved_path = {
155 self.lookup_table.get_package_version(&path[0]).map_or_else(
156 || path.to_vec(),
157 |found_version| {
158 let mut new_path = path.to_vec();
159 let complete_name = format!("{}-{found_version}", path[0]);
160 new_path[0] = complete_name;
161 new_path
162 },
164 )
165 };
166
167 if path.len() == 1 {
168 if let Some(module_ref) = self.lookup_table.get_module_link(&path[0]) {
169 return Some(module_ref);
170 }
171 }
172
173 if let Some(x) = self.modules.get(&resolved_path) {
174 return Some(x);
175 }
176
177 None
178 }
179}
180
181pub struct Analyzer<'a> {
182 pub shared: SharedState<'a>,
183 scope: FunctionScopeState,
184 function_variables: Vec<VariableRef>,
185 global: FunctionScopeState,
186 module_path: Vec<String>,
187}
188
189impl Analyzer<'_> {
190 #[must_use]
191 pub const fn scopes(&self) -> &FunctionScopeState {
192 &self.scope
193 }
194}
195
196impl<'a> Analyzer<'a> {
197 pub fn new(
198 state: &'a mut ProgramState,
199 modules: &'a Modules,
200 core_symbol_table: SymbolTableRef,
201 source_map: &'a SourceMap,
202 module_path: &[String],
203 file_id: FileId,
204 ) -> Self {
205 let shared = SharedState {
206 state,
207 lookup_table: SymbolTable::new(&[]),
208 definition_table: SymbolTable::new(module_path),
209 modules,
210 core_symbol_table,
211 source_map,
212 file_id,
213 type_variables: SemanticContext::default(),
214 };
215 Self {
216 scope: FunctionScopeState::new(),
217 global: FunctionScopeState::new(),
218 shared,
219 module_path: module_path.to_vec(),
220 function_variables: Vec::new(),
221 }
222 }
223
224 fn start_function(&mut self) {
225 self.global.block_scope_stack = take(&mut self.scope.block_scope_stack);
226 self.scope = FunctionScopeState::new();
227 self.function_variables.clear();
228 }
229
230 fn stop_function(&mut self) {
231 self.scope.block_scope_stack = take(&mut self.global.block_scope_stack);
232 self.function_variables.clear();
233 }
234
235 fn analyze_if_expression(
236 &mut self,
237 condition: &swamp_ast::Expression,
238 true_expression: &swamp_ast::Expression,
239 maybe_false_expression: Option<&swamp_ast::Expression>,
240 context: &TypeContext,
241 ) -> Result<Expression, Error> {
242 let resolved_condition = self.analyze_bool_argument_expression(condition)?;
243
244 let branch_context = context;
245
246 let true_expr = self.analyze_expression(true_expression, branch_context)?;
247 let resolved_true = Box::new(true_expr);
248
249 let mut detected = context.expected_type.cloned();
250 if detected.is_none() && !matches!(resolved_true.ty, Type::Never) {
251 detected = Some(resolved_true.ty.clone());
252 }
253
254 let else_statements = if let Some(false_expression) = maybe_false_expression {
256 let else_context = branch_context.with_expected_type(detected.as_ref());
257 let else_expr = self.analyze_expression(false_expression, &else_context)?;
258 if detected.is_none() && !matches!(else_expr.ty, Type::Never) {
259 detected = Some(else_expr.ty.clone());
260 }
261
262 Some(Box::new(else_expr))
263 } else {
264 None
265 };
266
267 Ok(self.create_expr(
268 ExpressionKind::If(resolved_condition, resolved_true, else_statements),
269 detected.unwrap(),
270 &condition.node,
271 ))
272 }
273
274 fn get_text(&self, ast_node: &swamp_ast::Node) -> &str {
275 let span = Span {
276 file_id: self.shared.file_id,
277 offset: ast_node.span.offset,
278 length: ast_node.span.length,
279 };
280 self.shared.source_map.get_span_source(
281 self.shared.file_id,
282 span.offset as usize,
283 span.length as usize,
284 )
285 }
286
287 fn get_text_resolved(&self, resolved_node: &Node) -> &str {
288 let span = Span {
289 file_id: self.shared.file_id,
290 offset: resolved_node.span.offset,
291 length: resolved_node.span.length,
292 };
293 self.shared.source_map.get_span_source(
294 self.shared.file_id,
295 span.offset as usize,
296 span.length as usize,
297 )
298 }
299
300 fn get_path(&self, ident: &swamp_ast::QualifiedTypeIdentifier) -> (Vec<String>, String) {
301 let path = ident
302 .module_path
303 .as_ref()
304 .map_or_else(Vec::new, |found_path| {
305 let mut v = Vec::new();
306 for p in &found_path.0 {
307 v.push(self.get_text(p).to_string());
308 }
309 v
310 });
311 (path, self.get_text(&ident.name.0).to_string())
312 }
313
314 fn analyze_return_type(&mut self, function: &swamp_ast::Function) -> Result<Type, Error> {
315 let ast_return_type = match function {
316 swamp_ast::Function::Internal(x) => &x.declaration.return_type,
317 swamp_ast::Function::External(x) => &x.return_type,
318 };
319
320 let resolved_return_type = match ast_return_type {
321 None => Type::Unit,
322 Some(x) => self.analyze_type(x)?,
323 };
324
325 Ok(resolved_return_type)
326 }
327
328 fn analyze_function_body_expression(
329 &mut self,
330 expression: &swamp_ast::Expression,
331 return_type: &Type,
332 ) -> Result<Expression, Error> {
333 let context = TypeContext::new_function(return_type);
334 let resolved_statement = self.analyze_expression(expression, &context)?;
335
336 Ok(resolved_statement)
337 }
338
339 fn analyze_maybe_type(&mut self, maybe_type: Option<&swamp_ast::Type>) -> Result<Type, Error> {
340 let found_type = match maybe_type {
341 None => Type::Unit,
342 Some(ast_type) => self.analyze_type(ast_type)?,
343 };
344 Ok(found_type)
345 }
346
347 fn analyze_for_pattern(
348 &mut self,
349 pattern: &swamp_ast::ForPattern,
350 key_type: Option<&Type>,
351 value_type: &Type,
352 ) -> Result<ForPattern, Error> {
353 match pattern {
354 swamp_ast::ForPattern::Single(var) => {
355 let variable_ref = self.create_local_variable(
356 &var.identifier,
357 Option::from(&var.is_mut),
358 value_type,
359 )?;
360 Ok(ForPattern::Single(variable_ref))
361 }
362 swamp_ast::ForPattern::Pair(first, second) => {
363 let found_key = key_type.unwrap();
364 let first_var_ref = self.create_local_variable(
365 &first.identifier,
366 Option::from(&first.is_mut),
367 found_key,
368 )?;
369 let second_var_ref = self.create_local_variable(
370 &second.identifier,
371 Option::from(&second.is_mut),
372 value_type,
373 )?;
374 Ok(ForPattern::Pair(first_var_ref, second_var_ref))
375 }
376 }
377 }
378
379 fn analyze_parameters(
380 &mut self,
381 parameters: &Vec<swamp_ast::Parameter>,
382 ) -> Result<Vec<TypeForParameter>, Error> {
383 let mut resolved_parameters = Vec::new();
384 for parameter in parameters {
385 let param_type = self.analyze_type(¶meter.param_type)?;
386 resolved_parameters.push(TypeForParameter {
387 name: self.get_text(¶meter.variable.name).to_string(),
388 resolved_type: param_type,
389 is_mutable: parameter.variable.is_mutable.is_some(),
390 node: Some(ParameterNode {
391 is_mutable: self.to_node_option(Option::from(¶meter.variable.is_mutable)),
392 name: self.to_node(¶meter.variable.name),
393 }),
394 });
395 }
396 Ok(resolved_parameters)
397 }
398
399 pub fn analyze_start_chain_expression_get_mutability(
402 &mut self,
403 ast_expression: &swamp_ast::Expression,
404 expected_type: Option<&Type>,
405 ) -> Result<(Expression, bool), Error> {
406 let any_parameter_context = TypeContext::new_unsure_argument(expected_type);
407 let resolved = self.analyze_expression(ast_expression, &any_parameter_context)?;
408 let mutability = match resolved.kind {
409 ExpressionKind::VariableAccess(ref resolved_variable) => resolved_variable.is_mutable(),
410 _ => false,
411 };
412
413 Ok((resolved, mutability))
414 }
415
416 pub fn debug_expression(&self, expr: &swamp_ast::Expression) {
417 let (line, _col) = self
418 .shared
419 .source_map
420 .get_span_location_utf8(self.shared.file_id, expr.node.span.offset as usize);
421 let _source_line = self
422 .shared
423 .source_map
424 .get_source_line(self.shared.file_id, line);
425 }
426
427 pub fn analyze_main_expression(
430 &mut self,
431 ast_expression: &swamp_ast::Expression,
432 ) -> Result<InternalMainExpression, Error> {
433 self.start_function();
434
435 let context = TypeContext::new_anything_argument();
436 let analyzed_expr = self.analyze_expression(ast_expression, &context)?;
437 let main_expr = InternalMainExpression {
438 expression: analyzed_expr,
439 function_scope_state: self.function_variables.clone(),
440 program_unique_id: self.shared.state.allocate_internal_function_id(),
441 };
442
443 self.stop_function();
444
445 Ok(main_expr)
446 }
447
448 fn analyze_maybe_ref_expression(
449 &mut self,
450 ast_expr: &swamp_ast::Expression,
451 ) -> Result<MaybeBorrowMutRefExpression, Error> {
452 if let swamp_ast::ExpressionKind::UnaryOp(found_unary, ast_inner_expression) =
453 &ast_expr.kind
454 {
455 if let swamp_ast::UnaryOperator::BorrowMutRef(node) = found_unary {
456 let resolved_node = self.to_node(node);
458 return Ok(MaybeBorrowMutRefExpression {
459 ast_expression: *ast_inner_expression.clone(),
460 has_borrow_mutable_reference: Some(resolved_node),
461 });
462 }
463 }
464
465 Ok(MaybeBorrowMutRefExpression {
466 ast_expression: ast_expr.clone(),
467 has_borrow_mutable_reference: None,
468 })
469 }
470
471 #[allow(clippy::too_many_lines)]
474 pub fn analyze_expression(
475 &mut self,
476 ast_expression: &swamp_ast::Expression,
477 context: &TypeContext,
478 ) -> Result<Expression, Error> {
479 let expr = self.analyze_expression_internal(ast_expression, context)?;
480
481 let encountered_type = expr.ty.clone();
482
483 if let Some(found_expected_type) = context.expected_type {
484 if found_expected_type.compatible_with(&encountered_type) {
485 return Ok(expr);
486 }
487
488 let result = self.types_did_not_match_try_late_coerce_expression(
489 expr,
490 found_expected_type,
491 &encountered_type,
492 &ast_expression.node,
493 )?;
494
495 return Ok(result);
496 }
497
498 Ok(expr)
499 }
500
501 #[allow(clippy::too_many_lines)]
504 pub fn analyze_expression_internal(
505 &mut self,
506 ast_expression: &swamp_ast::Expression,
507 context: &TypeContext,
508 ) -> Result<Expression, Error> {
509 let expression = match &ast_expression.kind {
510 swamp_ast::ExpressionKind::PostfixChain(postfix_chain) => {
512 self.analyze_postfix_chain(postfix_chain)?
513 }
514
515 swamp_ast::ExpressionKind::VariableDefinition(
516 variable,
517 maybe_annotation,
518 source_expression,
519 ) => self.analyze_create_variable(
520 variable,
521 Option::from(maybe_annotation),
522 source_expression,
523 )?,
524
525 swamp_ast::ExpressionKind::VariableAssignment(variable, source_expression) => {
526 self.analyze_variable_assignment(variable, source_expression)?
527 }
528
529 swamp_ast::ExpressionKind::DestructuringAssignment(variables, expression) => {
530 self.analyze_destructuring(&ast_expression.node, variables, expression)?
531 }
532
533 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
534 self.analyze_identifier(qualified_identifier)?
535 }
536
537 swamp_ast::ExpressionKind::VariableReference(variable) => {
538 self.analyze_variable_reference(&variable.name)?
539 }
540
541 swamp_ast::ExpressionKind::StaticMemberFunctionReference(
542 type_identifier,
543 member_name,
544 ) => self.analyze_static_member_access(type_identifier, member_name)?,
545
546 swamp_ast::ExpressionKind::ConstantReference(constant_identifier) => {
547 self.analyze_constant_access(constant_identifier)?
548 }
549
550 swamp_ast::ExpressionKind::Assignment(location, source) => {
551 self.analyze_assignment(location, source)?
552 }
553
554 swamp_ast::ExpressionKind::CompoundAssignment(target, op, source) => {
555 self.analyze_assignment_compound(target, op, source)?
556 }
557
558 swamp_ast::ExpressionKind::BinaryOp(resolved_a, operator, resolved_b) => {
560 let (resolved_op, result_type) =
561 self.analyze_binary_op(resolved_a, operator, resolved_b)?;
562
563 self.create_expr(
564 ExpressionKind::BinaryOp(resolved_op),
565 result_type,
566 &ast_expression.node,
567 )
568 }
569
570 swamp_ast::ExpressionKind::UnaryOp(operator, expression) => {
571 let (resolved_op, result_type) = self.analyze_unary_op(operator, expression)?;
572 self.create_expr(
573 ExpressionKind::UnaryOp(resolved_op),
574 result_type,
575 &ast_expression.node,
576 )
577 }
578
579 swamp_ast::ExpressionKind::Block(expressions) => {
580 let (block, resulting_type) =
581 self.analyze_block(&ast_expression.node, context, expressions)?;
582 self.create_expr(
583 ExpressionKind::Block(block),
584 resulting_type,
585 &ast_expression.node,
586 )
587 }
588
589 swamp_ast::ExpressionKind::With(variable_bindings, expression) => {
590 self.analyze_with_expr(context, variable_bindings, expression)?
591 }
592
593 swamp_ast::ExpressionKind::When(variable_bindings, true_expr, else_expr) => {
594 self.analyze_when_expr(context, variable_bindings, true_expr, else_expr.as_deref())?
595 }
596
597 swamp_ast::ExpressionKind::InterpolatedString(string_parts) => {
598 let kind = ExpressionKind::InterpolatedString(
599 self.analyze_interpolated_string(string_parts)?,
600 );
601
602 self.create_expr(kind, Type::String, &ast_expression.node)
603 }
604
605 swamp_ast::ExpressionKind::NamedStructLiteral(struct_identifier, fields, has_rest) => {
607 self.analyze_struct_instantiation(struct_identifier, fields, *has_rest)?
608 }
609
610 swamp_ast::ExpressionKind::AnonymousStructLiteral(fields, rest_was_specified) => self
611 .analyze_anonymous_struct_literal(
612 &ast_expression.node,
613 fields,
614 *rest_was_specified,
615 context,
616 )?,
617
618 swamp_ast::ExpressionKind::Range(min_value, max_value, range_mode) => {
619 self.analyze_range(min_value, max_value, range_mode, &ast_expression.node)?
620 }
621
622 swamp_ast::ExpressionKind::Literal(literal) => {
623 self.analyze_complex_literal_to_expression(&ast_expression.node, literal, context)?
624 }
625
626 swamp_ast::ExpressionKind::ForLoop(
627 pattern,
628 iterable_expression,
629 guard_expr,
630 statements,
631 ) => {
632 let _analyzed_guard = if let Some(found_guard) = guard_expr {
633 Some(self.analyze_bool_argument_expression(found_guard)?)
635 } else {
636 None
637 };
638
639 let resolved_iterator =
640 self.analyze_iterable(pattern.any_mut(), &iterable_expression.expression)?;
641
642 self.push_block_scope("for_loop");
643 let pattern = self.analyze_for_pattern(
644 pattern,
645 resolved_iterator.key_type.as_ref(),
646 &resolved_iterator.value_type,
647 )?;
648 let resolved_statements = self.analyze_expression(statements, context)?;
649 self.pop_block_scope("for_loop");
650 let resolved_type = resolved_statements.ty.clone();
651 self.create_expr(
652 ExpressionKind::ForLoop(
653 pattern,
654 resolved_iterator,
655 Box::from(resolved_statements),
656 ),
657 resolved_type,
658 &ast_expression.node,
659 )
660 }
661
662 swamp_ast::ExpressionKind::WhileLoop(expression, statements) => {
663 let condition = self.analyze_bool_argument_expression(expression)?;
664 let resolved_statements = self.analyze_expression(statements, context)?;
666 let resolved_type = resolved_statements.ty.clone();
667 self.create_expr(
670 ExpressionKind::WhileLoop(condition, Box::from(resolved_statements)),
671 resolved_type,
672 &ast_expression.node,
673 )
674 }
675
676 swamp_ast::ExpressionKind::If(expression, true_expression, maybe_false_expression) => {
677 self.analyze_if_expression(
678 expression,
679 true_expression,
680 maybe_false_expression.as_deref(),
681 context,
682 )?
683 }
684
685 swamp_ast::ExpressionKind::Match(expression, arms) => {
686 let (match_expr, return_type) = self.analyze_match(expression, context, arms)?;
687 self.create_expr(
688 ExpressionKind::Match(match_expr),
689 return_type,
690 &ast_expression.node,
691 )
692 }
693 swamp_ast::ExpressionKind::Guard(guard_expressions) => {
694 self.analyze_guard(&ast_expression.node, context, guard_expressions)?
695 }
696
697 swamp_ast::ExpressionKind::Lambda(variables, expression) => {
698 self.analyze_lambda(&ast_expression.node, variables, expression, context)?
699 }
700 };
701
702 Ok(expression)
705 }
706
707 fn get_struct_type(
708 &mut self,
709 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
710 ) -> Result<NamedStructType, Error> {
711 let maybe_struct_type = self.analyze_named_type(qualified_type_identifier)?;
712 match maybe_struct_type {
713 Type::NamedStruct(struct_type) => Ok(struct_type),
714 _ => Err(self.create_err(
715 ErrorKind::UnknownStructTypeReference,
717 &qualified_type_identifier.name.0,
718 )),
719 }
720 }
721
722 pub(crate) fn analyze_named_type(
723 &mut self,
724 type_name_to_find: &swamp_ast::QualifiedTypeIdentifier,
725 ) -> Result<Type, Error> {
726 let (path, name) = self.get_path(type_name_to_find);
727
728 if path.is_empty() {
729 if let Some(found_type) = self.shared.type_variables.resolve_type_variable(&name) {
731 return Ok(found_type);
732 }
733 }
734
735 let symbol = {
736 let maybe_symbol_table = self.shared.get_symbol_table(&path);
737 let symbol_table = maybe_symbol_table.ok_or_else(|| {
738 self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)
739 })?;
740 symbol_table
741 .get_symbol(&name)
742 .ok_or_else(|| {
743 self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)
744 })?
745 .clone()
746 };
747
748 let mut analyzed_type_parameters = Vec::new();
749
750 for analyzed_type in &type_name_to_find.generic_params {
751 let ty = self.analyze_type(analyzed_type)?;
752
753 analyzed_type_parameters.push(ty);
754 }
755
756 let result_type = if analyzed_type_parameters.is_empty() {
757 match &symbol {
758 Symbol::Type(base_type) => base_type.clone(),
759 Symbol::Alias(alias_type) => alias_type.referenced_type.clone(),
760 _ => {
761 return Err(
762 self.create_err(ErrorKind::UnexpectedType, &type_name_to_find.name.0)
763 );
764 }
765 }
766 } else {
767 self.analyze_generic_type(
768 &symbol,
769 &analyzed_type_parameters,
770 &type_name_to_find.name.0,
771 )?
772 };
773
774 Ok(result_type)
775 }
776
777 fn create_default_value_for_type(
778 &mut self,
779 node: &swamp_ast::Node,
780 field_type: &Type,
781 ) -> Result<Expression, Error> {
782 let kind = match field_type {
783 Type::Bool => ExpressionKind::Literal(Literal::BoolLiteral(false)),
784 Type::Int => ExpressionKind::Literal(Literal::IntLiteral(0)),
785 Type::Float => ExpressionKind::Literal(Literal::FloatLiteral(Fp::zero())),
786 Type::String => ExpressionKind::Literal(Literal::StringLiteral(String::new())),
787 Type::Tuple(tuple_type_ref) => {
788 let mut expressions = Vec::new();
789 for resolved_type in tuple_type_ref {
790 let expr = self.create_default_value_for_type(node, resolved_type)?;
791 expressions.push(expr);
792 }
793 ExpressionKind::Literal(Literal::TupleLiteral(tuple_type_ref.clone(), expressions))
794 }
795 Type::Optional(_optional_type) => ExpressionKind::Literal(Literal::NoneLiteral),
796
797 Type::NamedStruct(struct_ref) => {
798 self.create_default_static_call(node, &Type::NamedStruct(struct_ref.clone()))?
799 }
800 _ => {
801 return Err(
802 self.create_err(ErrorKind::NoDefaultImplemented(field_type.clone()), node)
803 );
804 }
805 };
806
807 let expr = self.create_expr(kind, field_type.clone(), node);
808 Ok(expr)
809 }
810
811 fn create_static_call(
812 &mut self,
813 function_name: &str,
814 arguments: &[MutRefOrImmutableExpression],
815 node: &swamp_ast::Node,
816 ty: &Type,
817 ) -> Result<ExpressionKind, Error> {
818 self.lookup_associated_function(ty, function_name)
819 .map_or_else(
820 || {
821 Err(self.create_err(
822 ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
823 node,
824 ))
825 },
826 |function| {
827 let kind = match &*function {
828 Function::Internal(internal_function) => {
829 ExpressionKind::InternalFunctionAccess(internal_function.clone())
830 }
831 Function::External(external_function) => {
832 ExpressionKind::ExternalFunctionAccess(external_function.clone())
833 }
834 };
835
836 let base_expr =
837 self.create_expr(kind, Type::Function(function.signature().clone()), node);
838
839 let empty_call_postfix = Postfix {
840 node: self.to_node(node),
841 ty: *function.signature().return_type.clone(),
842 kind: PostfixKind::FunctionCall(arguments.to_vec()),
843 };
844
845 let kind =
846 ExpressionKind::PostfixChain(Box::new(base_expr), vec![empty_call_postfix]);
847
848 Ok(kind)
849 },
850 )
851 }
852
853 fn create_default_static_call(
854 &mut self,
855 node: &swamp_ast::Node,
856 ty: &Type,
857 ) -> Result<ExpressionKind, Error> {
858 self.create_static_call("default", &[], node, ty)
859 }
860
861 fn add_postfix(
862 &mut self,
863 vec: &mut Vec<Postfix>,
864 kind: PostfixKind,
865 ty: Type,
866 node: &swamp_ast::Node,
867 ) {
868 let resolved_node = self.to_node(node);
869 let postfix = Postfix {
870 node: resolved_node,
871 ty,
872 kind,
873 };
874
875 vec.push(postfix);
876 }
877
878 pub fn analyze_struct_field(
883 &mut self,
884 field_name: &swamp_ast::Node,
885 tv: &Type,
886 ) -> Result<(AnonymousStructType, usize, Type), Error> {
887 let field_name_str = self.get_text(field_name).to_string();
888
889 let anon_struct_ref = match &tv {
890 Type::NamedStruct(struct_type) => struct_type.anon_struct_type.clone(),
891 Type::AnonymousStruct(anon_struct) => anon_struct.clone(),
892 _ => return Err(self.create_err(ErrorKind::UnknownStructField, field_name)),
893 };
894
895 if let Some(found_field) = anon_struct_ref
896 .field_name_sorted_fields
897 .get(&field_name_str)
898 {
899 let index = anon_struct_ref
900 .field_name_sorted_fields
901 .get_index(&field_name_str)
902 .expect("checked earlier");
903
904 return Ok((
905 anon_struct_ref.clone(),
906 index,
907 found_field.field_type.clone(),
908 ));
909 }
910
911 Err(self.create_err(ErrorKind::UnknownStructField, field_name))
912 }
913
914 #[allow(clippy::too_many_lines)]
915 fn analyze_postfix_chain(
916 &mut self,
917 chain: &swamp_ast::PostfixChain,
918 ) -> Result<Expression, Error> {
919 let (start, is_mutable) =
920 self.analyze_start_chain_expression_get_mutability(&chain.base, None)?;
921
922 if let ExpressionKind::IntrinsicFunctionAccess(some_access) = &start.kind {
923 assert_eq!(chain.postfixes.len(), 1);
924 let call_postifx = &chain.postfixes[0];
925 if let swamp_ast::Postfix::FunctionCall(_member, _generic_arguments, arguments) =
926 &call_postifx
927 {
928 let resolved_arguments = self.analyze_and_verify_parameters(
929 &start.node,
930 &some_access.signature.parameters,
931 arguments,
932 )?;
933
934 return Ok(self.create_expr(
935 ExpressionKind::IntrinsicCallEx(
936 some_access.intrinsic.clone(),
937 resolved_arguments,
938 ),
939 *some_access.signature.return_type.clone(),
940 &chain.base.node,
941 ));
942 }
943 panic!("not sure here");
944 }
945
946 let mut tv = TypeWithMut {
947 resolved_type: start.ty.clone(),
948 is_mutable,
949 };
950
951 let mut uncertain = false;
952
953 let mut suffixes = Vec::new();
954
955 for item in &chain.postfixes {
956 match item {
957 swamp_ast::Postfix::FieldAccess(field_name) => {
958 let (struct_type_ref, index, return_type) =
959 self.analyze_struct_field(&field_name.clone(), &tv.resolved_type)?;
960 self.add_postfix(
961 &mut suffixes,
962 PostfixKind::StructField(struct_type_ref.clone(), index),
963 return_type.clone(),
964 field_name,
965 );
966
967 tv.resolved_type = return_type.clone();
968 }
970 swamp_ast::Postfix::MemberCall(member_name, generic_arguments, ast_arguments) => {
971 let member_name_str = self.get_text(member_name).to_string();
972
973 if let Some(_found_member) = self
974 .shared
975 .state
976 .instantiator
977 .associated_impls
978 .get_member_function(&tv.resolved_type, &member_name_str)
979 {
980 let return_type = self.analyze_postfix_member_call(
981 &tv.resolved_type,
982 tv.is_mutable,
983 member_name,
984 generic_arguments.clone(),
985 ast_arguments,
986 &mut suffixes,
987 )?;
988
989 tv.resolved_type = return_type.clone();
991 tv.is_mutable = false;
992 } else {
993 return Err(self.create_err(ErrorKind::UnknownMemberFunction, member_name));
994 }
995 }
996 swamp_ast::Postfix::FunctionCall(node, _generic_arguments, arguments) => {
997 if let Type::Function(signature) = &tv.resolved_type {
998 let resolved_node = self.to_node(node);
999 let resolved_arguments = self.analyze_and_verify_parameters(
1000 &resolved_node,
1001 &signature.parameters,
1002 arguments,
1003 )?;
1004
1005 let call_kind = PostfixKind::FunctionCall(resolved_arguments);
1006
1007 self.add_postfix(
1008 &mut suffixes,
1009 call_kind,
1010 *signature.return_type.clone(),
1011 node,
1012 );
1013
1014 tv.resolved_type = *signature.return_type.clone();
1015 tv.is_mutable = false;
1016 } else {
1017 panic!("{}", &format!("what is this type {:?} ", tv.resolved_type))
1018 }
1019 }
1020
1021 swamp_ast::Postfix::Subscript(index_expr) => {
1022 let _collection_type = tv.resolved_type.clone();
1023
1024 let temp_lookup_context = TypeContext::new_anything_argument();
1025 let temp_analyzed_expr =
1026 self.analyze_expression(index_expr, &temp_lookup_context)?;
1027
1028 let mut subscript_function_name = "subscript";
1029
1030 if let Type::NamedStruct(named_struct) = temp_analyzed_expr.ty {
1031 if named_struct.assigned_name == "Range"
1032 && named_struct.module_path == vec!["core-0.0.0".to_string()]
1033 {
1034 subscript_function_name = "subscript_range";
1035 }
1036 };
1037
1038 if let Some(found) = self
1039 .shared
1040 .state
1041 .instantiator
1042 .associated_impls
1043 .get_member_function(&tv.resolved_type, subscript_function_name)
1044 .cloned()
1045 {
1046 let cloned = found.clone();
1047 let required_type = &found.signature().parameters[1].resolved_type;
1048 let subscript_lookup_context = TypeContext::new_argument(&required_type);
1049 let analyzed_expr =
1050 self.analyze_expression(index_expr, &subscript_lookup_context)?;
1051
1052 let return_type = *found.signature().return_type.clone();
1053
1054 let argument = MutRefOrImmutableExpression::Expression(analyzed_expr);
1055 self.add_postfix(
1056 &mut suffixes,
1057 PostfixKind::MemberCall(cloned, vec![argument]),
1058 return_type.clone(),
1059 &index_expr.node,
1060 );
1061 tv.resolved_type = return_type.clone();
1062 } else {
1063 return Err(
1064 self.create_err(ErrorKind::MissingSubscriptMember, &index_expr.node)
1065 );
1066 }
1067 }
1068
1069 swamp_ast::Postfix::NoneCoalescingOperator(default_expr) => {
1070 let unwrapped_type = if let Type::Optional(unwrapped_type) = &tv.resolved_type {
1071 unwrapped_type
1072 } else if uncertain {
1073 &tv.resolved_type
1074 } else {
1075 return Err(
1076 self.create_err(ErrorKind::CanNotNoneCoalesce, &default_expr.node)
1077 );
1078 };
1079
1080 let unwrapped_type_context = TypeContext::new_argument(unwrapped_type);
1081 let resolved_default_expr =
1082 self.analyze_expression(default_expr, &unwrapped_type_context)?;
1083 self.add_postfix(
1084 &mut suffixes,
1085 PostfixKind::NoneCoalescingOperator(resolved_default_expr),
1086 unwrapped_type.clone(),
1087 &default_expr.node,
1088 );
1089 tv.resolved_type = unwrapped_type.clone();
1090 uncertain = false; }
1092
1093 swamp_ast::Postfix::OptionalChainingOperator(option_node) => {
1094 if let Type::Optional(unwrapped_type) = &tv.resolved_type {
1095 uncertain = true;
1096 self.add_postfix(
1097 &mut suffixes,
1098 PostfixKind::OptionalChainingOperator,
1099 *unwrapped_type.clone(),
1100 option_node,
1101 );
1102 tv.resolved_type = *unwrapped_type.clone();
1103 } else {
1104 return Err(self.create_err(ErrorKind::ExpectedOptional, option_node));
1105 }
1106 }
1107 }
1108 }
1109
1110 if uncertain {
1111 if let Type::Optional(_) = tv.resolved_type {
1112 } else {
1113 tv.resolved_type = Type::Optional(Box::from(tv.resolved_type.clone()));
1114 }
1115 }
1116
1117 Ok(self.create_expr(
1118 ExpressionKind::PostfixChain(Box::new(start), suffixes),
1119 tv.resolved_type,
1120 &chain.base.node,
1121 ))
1122 }
1123
1124 fn analyze_bool_argument_expression(
1125 &mut self,
1126 expression: &swamp_ast::Expression,
1127 ) -> Result<BooleanExpression, Error> {
1128 let bool_context = TypeContext::new_argument(&Type::Bool);
1129 let resolved_expression = self.analyze_expression(expression, &bool_context)?;
1130 let expr_type = resolved_expression.ty.clone();
1131
1132 let bool_expression = match expr_type {
1133 Type::Bool => resolved_expression,
1134 Type::Optional(_) => self.create_expr(
1135 ExpressionKind::CoerceOptionToBool(Box::new(resolved_expression)),
1136 Type::Bool,
1137 &expression.node,
1138 ),
1139 _ => {
1140 return Err(self.create_err(ErrorKind::ExpectedBooleanExpression, &expression.node));
1141 }
1142 };
1143
1144 Ok(BooleanExpression {
1145 expression: Box::from(bool_expression),
1146 })
1147 }
1148
1149 fn analyze_iterable(
1150 &mut self,
1151 force_mut: Option<swamp_ast::Node>,
1152 expression: &swamp_ast::Expression,
1153 ) -> Result<Iterable, Error> {
1154 let any_context = TypeContext::new_anything_argument();
1155 let resolved_expression: MutRefOrImmutableExpression = if force_mut.is_some() {
1156 let resolved_node = self.to_node(&force_mut.unwrap());
1157 MutRefOrImmutableExpression::Location(self.analyze_to_location(
1158 &expression,
1159 &any_context,
1160 LocationSide::Rhs,
1161 )?)
1162 } else {
1163 self.analyze_mut_or_immutable_expression(expression, &any_context, LocationSide::Rhs)?
1164 };
1165
1166 let resolved_type = &resolved_expression.ty().clone();
1167 let (key_type, value_type): (Option<Type>, Type) = match resolved_type {
1168 Type::String => (Some(Type::Int), Type::String),
1169
1170 _ => {
1171 if let Some(found_iter_fn) = self
1172 .shared
1173 .state
1174 .instantiator
1175 .associated_impls
1176 .get_internal_member_function(resolved_type, "iter")
1177 {
1178 let ret_type = found_iter_fn.signature.signature.return_type.clone();
1179 match *ret_type {
1180 Type::Tuple(tuple_items) => {
1181 (Some(tuple_items[0].clone()), tuple_items[1].clone())
1182 }
1183 _ => {
1184 return Err(self.create_err(ErrorKind::NotAnIterator, &expression.node));
1185 }
1186 }
1187 } else {
1188 return Err(self.create_err(ErrorKind::NotAnIterator, &expression.node));
1189 }
1190 }
1191 };
1192
1193 Ok(Iterable {
1194 key_type,
1195 value_type,
1196 resolved_expression: Box::new(resolved_expression),
1197 })
1198 }
1199
1200 fn analyze_argument_expressions(
1201 &mut self,
1202 expected_type: Option<&Type>,
1203 ast_expressions: &[swamp_ast::Expression],
1204 ) -> Result<Vec<Expression>, Error> {
1205 let mut resolved_expressions = Vec::new();
1206 let argument_expressions_context = TypeContext::new_unsure_argument(expected_type);
1207 for expression in ast_expressions {
1208 resolved_expressions
1209 .push(self.analyze_expression(expression, &argument_expressions_context)?);
1210 }
1211 Ok(resolved_expressions)
1212 }
1213
1214 fn analyze_block(
1215 &mut self,
1216 _node: &swamp_ast::Node,
1217 context: &TypeContext,
1218 ast_expressions: &[swamp_ast::Expression],
1219 ) -> Result<(Vec<Expression>, Type), Error> {
1220 if ast_expressions.is_empty() {
1221 return Ok((vec![], Type::Unit));
1222 }
1223
1224 self.push_block_scope("block");
1225
1226 let mut resolved_expressions = Vec::with_capacity(ast_expressions.len());
1227
1228 for expression in &ast_expressions[..ast_expressions.len() - 1] {
1229 let stmt_context = context.with_expected_type(Some(&Type::Unit));
1230 let expr = self.analyze_expression(expression, &stmt_context)?;
1231
1232 if matches!(expr.ty, Type::Never) {
1233 resolved_expressions.push(expr);
1234 return Ok((resolved_expressions, Type::Never));
1235 }
1236
1237 resolved_expressions.push(expr);
1238 }
1239
1240 let last_expr =
1242 self.analyze_expression(&ast_expressions[ast_expressions.len() - 1], context)?;
1243 let last_type = last_expr.ty.clone();
1244 resolved_expressions.push(last_expr);
1245
1246 self.pop_block_scope("block");
1247
1248 Ok((resolved_expressions, last_type))
1249 }
1250
1251 fn analyze_interpolated_string(
1252 &mut self,
1253 string_parts: &[swamp_ast::StringPart],
1254 ) -> Result<Vec<StringPart>, Error> {
1255 let mut resolved_parts = Vec::new();
1256 for part in string_parts {
1257 let resolved_string_part = match part {
1258 swamp_ast::StringPart::Literal(string_node, processed_string) => {
1259 StringPart::Literal(self.to_node(string_node), processed_string.to_string())
1260 }
1261 swamp_ast::StringPart::Interpolation(expression, format_specifier) => {
1262 let any_context = TypeContext::new_anything_argument();
1263 let expr = self.analyze_expression(expression, &any_context)?;
1264 let resolved_format_specifier =
1265 self.analyze_format_specifier(Option::from(format_specifier));
1266 StringPart::Interpolation(expr, resolved_format_specifier)
1267 }
1268 };
1269
1270 resolved_parts.push(resolved_string_part);
1271 }
1272
1273 Ok(resolved_parts)
1274 }
1275
1276 pub(crate) fn analyze_identifier(
1277 &self,
1278 qualified_func_name: &swamp_ast::QualifiedIdentifier,
1279 ) -> Result<Expression, Error> {
1280 if qualified_func_name.module_path.is_none()
1283 && qualified_func_name.generic_params.is_empty()
1284 {
1285 if let Some(found_variable) = self.try_find_variable(&qualified_func_name.name) {
1286 return Ok(self.create_expr(
1287 ExpressionKind::VariableAccess(found_variable.clone()),
1288 found_variable.resolved_type.clone(),
1289 &qualified_func_name.name,
1290 ));
1291 }
1292 }
1293
1294 let path = self.get_module_path(qualified_func_name.module_path.as_ref());
1295 let function_name = self.get_text(&qualified_func_name.name);
1296
1297 if let Some(found_table) = self.shared.get_symbol_table(&path) {
1298 if let Some(found_func) = found_table.get_function(function_name) {
1299 let (kind, signature) = match found_func {
1300 FuncDef::Internal(internal_fn) => (
1301 ExpressionKind::InternalFunctionAccess(internal_fn.clone()),
1302 &internal_fn.signature.signature,
1303 ),
1304 FuncDef::External(external_fn) => (
1305 ExpressionKind::ExternalFunctionAccess(external_fn.clone()),
1306 &external_fn.signature,
1307 ),
1308 FuncDef::Intrinsic(intrinsic_fn) => (
1310 ExpressionKind::IntrinsicFunctionAccess(intrinsic_fn.clone()),
1311 &intrinsic_fn.signature,
1312 ),
1313 };
1314
1315 return Ok(self.create_expr(
1316 kind,
1317 Type::Function(signature.clone()),
1318 &qualified_func_name.name,
1319 ));
1320 }
1321 }
1322 Err(self.create_err(
1323 ErrorKind::UnknownIdentifier(function_name.to_string()),
1324 &qualified_func_name.name,
1325 ))
1326 }
1327
1328 fn analyze_variable_reference(&self, var_node: &swamp_ast::Node) -> Result<Expression, Error> {
1330 if let Some(found_variable) = self.try_find_variable(var_node) {
1331 return Ok(self.create_expr(
1332 ExpressionKind::VariableAccess(found_variable.clone()),
1333 found_variable.resolved_type.clone(),
1334 var_node,
1335 ));
1336 }
1337 let text = self.get_text(var_node);
1338 Err(self.create_err(ErrorKind::UnknownIdentifier(text.to_string()), var_node))
1339 }
1340
1341 fn analyze_slice_type_helper(
1342 &mut self,
1343 _node: &swamp_ast::Node,
1344 items: &[swamp_ast::Expression],
1345 ) -> Result<(Type, Vec<Expression>), Error> {
1346 let expressions = self.analyze_argument_expressions(None, items)?;
1347 let element_type = if expressions.is_empty() {
1348 Type::Unit
1349 } else {
1350 expressions[0].ty.clone()
1351 };
1352
1353 Ok((element_type, expressions))
1354 }
1355
1356 fn push_block_scope(&mut self, _debug_str: &str) {
1357 self.scope.block_scope_stack.push(BlockScope {
1358 mode: BlockScopeMode::Open,
1359 variables: SeqMap::default(),
1360 });
1361 }
1362
1363 fn pop_block_scope(&mut self, _debug_str: &str) {
1364 self.scope.block_scope_stack.pop();
1365 }
1366
1367 fn push_closed_block_scope(&mut self) {
1368 self.scope.block_scope_stack.push(BlockScope {
1369 mode: BlockScopeMode::Closed,
1370 variables: SeqMap::default(),
1371 });
1372 }
1373
1374 fn pop_closed_block_scope(&mut self) {
1375 self.scope.block_scope_stack.pop();
1376 }
1377
1378 fn analyze_enum_variant_ref(
1379 &self,
1380 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
1381 variant_name: &swamp_ast::LocalTypeIdentifier,
1382 ) -> Result<EnumVariantType, Error> {
1383 let variant_name_string = self.get_text(&variant_name.0).to_string();
1384 self.get_enum_variant_type(qualified_type_identifier, &variant_name_string)
1385 }
1386
1387 fn analyze_match(
1388 &mut self,
1389 scrutinee: &swamp_ast::Expression,
1390 default_context: &TypeContext,
1391 arms: &Vec<swamp_ast::MatchArm>,
1392 ) -> Result<(Match, Type), Error> {
1393 let mut known_type = default_context.expected_type.cloned();
1394 let own_context = default_context.clone();
1395 let scrutinee_context = TypeContext::new_anything_argument();
1397 let resolved_scrutinee = self.analyze_mut_or_immutable_expression(
1398 scrutinee,
1399 &scrutinee_context,
1400 LocationSide::Rhs,
1401 )?;
1402 let scrutinee_type = resolved_scrutinee.ty().clone();
1403
1404 if arms.is_empty() {
1406 return Err(self.create_err(ErrorKind::EmptyMatch, &scrutinee.node));
1407 }
1408
1409 let mut resolved_arms = Vec::with_capacity(arms.len());
1410
1411 for arm in arms {
1412 let (resolved_arm, _anyone_wants_mutable) = self.analyze_arm(
1413 arm,
1414 &resolved_scrutinee,
1415 &own_context.with_expected_type(known_type.as_ref()),
1416 &scrutinee_type,
1417 )?;
1418
1419 if known_type.is_none() && !matches!(resolved_arm.expression.ty, Type::Never) {
1420 known_type = Some(resolved_arm.expression.ty.clone());
1421 }
1422 resolved_arms.push(resolved_arm);
1423 }
1424
1425 known_type.map_or_else(
1426 || Err(self.create_err(ErrorKind::MatchArmsMustHaveTypes, &scrutinee.node)),
1427 |encountered_type| {
1428 if matches!(encountered_type, Type::Never) {
1429 Err(self.create_err(
1430 ErrorKind::IncompatibleTypes {
1431 expected: Type::Never,
1432 found: encountered_type,
1433 },
1434 &scrutinee.node,
1435 ))
1436 } else {
1437 Ok((
1438 Match {
1439 expression: Box::new(resolved_scrutinee),
1440 arms: resolved_arms,
1441 },
1442 encountered_type,
1443 ))
1444 }
1445 },
1446 )
1447 }
1448
1449 fn analyze_arm(
1450 &mut self,
1451 arm: &swamp_ast::MatchArm,
1452 _expression: &MutRefOrImmutableExpression,
1453 type_context: &TypeContext,
1454 expected_condition_type: &Type,
1455 ) -> Result<(MatchArm, bool), Error> {
1456 let (resolved_pattern, scope_was_pushed, anyone_wants_mutable) =
1457 self.analyze_pattern(&arm.pattern, expected_condition_type)?;
1458
1459 let resolved_expression = self.analyze_expression(&arm.expression, type_context)?;
1460 if scope_was_pushed {
1461 self.pop_block_scope("analyze_arm");
1462 }
1463
1464 let resolved_type = resolved_expression.ty.clone();
1465
1466 Ok((
1467 MatchArm {
1468 pattern: resolved_pattern,
1469 expression: Box::from(resolved_expression),
1470 expression_type: resolved_type,
1471 },
1472 anyone_wants_mutable,
1473 ))
1474 }
1475
1476 fn str_to_int(text: &str) -> Result<i32, ParseIntError> {
1477 let text = text.replace('_', "");
1478 text.strip_prefix("0x").map_or_else(
1479 || {
1480 text.strip_prefix("-0x").map_or_else(
1481 || text.parse::<i32>(),
1482 |rest| i32::from_str_radix(rest, 16).map(|x| -x),
1483 )
1484 },
1485 |rest| i32::from_str_radix(rest, 16),
1486 )
1487 }
1488
1489 fn str_to_float(text: &str) -> Result<f32, ParseFloatError> {
1490 text.parse::<f32>()
1491 }
1492
1493 fn analyze_pattern_literal(
1494 &mut self,
1495 node: &swamp_ast::Node,
1496 ast_literal: &swamp_ast::LiteralKind,
1497 expected_condition_type: &Type,
1498 ) -> Result<NormalPattern, Error> {
1499 let required_condition_type_context = TypeContext::new_argument(expected_condition_type);
1500 let (literal, ty) =
1501 self.analyze_literal(node, ast_literal, &required_condition_type_context)?;
1502
1503 if !ty.compatible_with(expected_condition_type) {
1504 return Err(self.create_err(
1505 ErrorKind::IncompatibleTypes {
1506 expected: expected_condition_type.clone(),
1507 found: ty,
1508 },
1509 node,
1510 ));
1511 }
1512
1513 Ok(NormalPattern::Literal(literal))
1514 }
1515
1516 const fn to_node(&self, node: &swamp_ast::Node) -> Node {
1517 Node {
1518 span: Span {
1519 file_id: self.shared.file_id,
1520 offset: node.span.offset,
1521 length: node.span.length,
1522 },
1523 }
1524 }
1525
1526 fn get_module_path(&self, module_path: Option<&swamp_ast::ModulePath>) -> Vec<String> {
1527 module_path.as_ref().map_or_else(Vec::new, |found| {
1528 let mut strings = Vec::new();
1529 for path_item in &found.0 {
1530 strings.push(self.get_text(path_item).to_string());
1531 }
1532 strings
1533 })
1534 }
1535
1536 fn get_enum_variant_type(
1537 &self,
1538 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
1539 variant_name: &str,
1540 ) -> Result<EnumVariantType, Error> {
1541 let (symbol_table, enum_name) =
1542 self.get_symbol_table_and_name(qualified_type_identifier)?;
1543 symbol_table
1544 .get_enum_variant_type(&enum_name, variant_name)
1545 .ok_or_else(|| {
1546 self.create_err(
1547 ErrorKind::UnknownEnumVariantType,
1548 &qualified_type_identifier.name.0,
1549 )
1550 })
1551 }
1552
1553 pub(crate) fn get_symbol_table_and_name(
1554 &self,
1555 type_identifier: &swamp_ast::QualifiedTypeIdentifier,
1556 ) -> Result<(&SymbolTable, String), Error> {
1557 let path = self.get_module_path(type_identifier.module_path.as_ref());
1558 let name = self.get_text(&type_identifier.name.0).to_string();
1559
1560 let maybe_symbol_table = self.shared.get_symbol_table(&path);
1561 maybe_symbol_table.map_or_else(
1562 || Err(self.create_err(ErrorKind::UnknownModule, &type_identifier.name.0)),
1563 |symbol_table| Ok((symbol_table, name)),
1564 )
1565 }
1566
1567 const fn analyze_compound_operator(
1568 &self,
1569 ast_operator: &swamp_ast::CompoundOperator,
1570 ) -> CompoundOperator {
1571 let resolved_node = self.to_node(&ast_operator.node);
1572 let resolved_kind = match ast_operator.kind {
1573 swamp_ast::CompoundOperatorKind::Add => CompoundOperatorKind::Add,
1574 swamp_ast::CompoundOperatorKind::Sub => CompoundOperatorKind::Sub,
1575 swamp_ast::CompoundOperatorKind::Mul => CompoundOperatorKind::Mul,
1576 swamp_ast::CompoundOperatorKind::Div => CompoundOperatorKind::Div,
1577 swamp_ast::CompoundOperatorKind::Modulo => CompoundOperatorKind::Modulo,
1578 };
1579
1580 CompoundOperator {
1581 node: resolved_node,
1582 kind: resolved_kind,
1583 }
1584 }
1585
1586 const fn to_node_option(&self, maybe_node: Option<&swamp_ast::Node>) -> Option<Node> {
1587 match maybe_node {
1588 None => None,
1589 Some(node) => Some(self.to_node(node)),
1590 }
1591 }
1592
1593 const fn analyze_format_specifier(
1594 &self,
1595 ast_format_specifier: Option<&swamp_ast::FormatSpecifier>,
1596 ) -> Option<FormatSpecifier> {
1597 let f = match ast_format_specifier {
1598 None => return None,
1599 Some(ast_format) => match ast_format {
1600 swamp_ast::FormatSpecifier::LowerHex(node) => FormatSpecifier {
1601 node: self.to_node(node),
1602 kind: FormatSpecifierKind::LowerHex,
1603 },
1604 swamp_ast::FormatSpecifier::UpperHex(node) => FormatSpecifier {
1605 node: self.to_node(node),
1606 kind: FormatSpecifierKind::UpperHex,
1607 },
1608 swamp_ast::FormatSpecifier::Binary(node) => FormatSpecifier {
1609 node: self.to_node(node),
1610 kind: FormatSpecifierKind::Binary,
1611 },
1612 swamp_ast::FormatSpecifier::Float(node) => FormatSpecifier {
1613 node: self.to_node(node),
1614 kind: FormatSpecifierKind::Float,
1615 },
1616 swamp_ast::FormatSpecifier::Precision(value, node, x) => {
1617 let (precision_type, precision_node) = match x {
1618 swamp_ast::PrecisionType::Float(node) => {
1619 (PrecisionType::Float, self.to_node(node))
1620 }
1621 swamp_ast::PrecisionType::String(node) => {
1622 (PrecisionType::String, self.to_node(node))
1623 }
1624 };
1625 FormatSpecifier {
1626 node: self.to_node(node),
1627 kind: FormatSpecifierKind::Precision(
1628 *value,
1629 precision_node,
1630 precision_type,
1631 ),
1632 }
1633 }
1634 },
1635 };
1636
1637 Some(f)
1638 }
1639
1640 fn analyze_with_expr(
1641 &mut self,
1642 context: &TypeContext,
1643 variables: &[swamp_ast::VariableBinding],
1644 expression: &swamp_ast::Expression,
1645 ) -> Result<Expression, Error> {
1646 let mut variable_expressions = Vec::new();
1647
1648 for variable in variables {
1649 let any_context = TypeContext::new_anything_argument();
1650
1651 let must_have_expression = if let Some(x) = &variable.expression {
1656 x
1657 } else {
1658 &swamp_ast::Expression {
1659 kind: swamp_ast::ExpressionKind::VariableReference(variable.variable.clone()),
1660 node: variable.variable.name.clone(),
1661 }
1662
1663 };
1665
1666 let var = self.analyze_mut_or_immutable_expression(
1667 &must_have_expression,
1668 &any_context,
1669 LocationSide::Rhs,
1670 )?;
1671
1672 variable_expressions.push(var);
1673 }
1674
1675 self.push_closed_block_scope();
1676 let mut expressions = Vec::new();
1677 for (variable_binding, resolved_expression) in variables.iter().zip(variable_expressions) {
1678 let initialize_variable_expression = self.create_variable_binding_for_with(
1679 &variable_binding.variable,
1680 resolved_expression,
1681 )?;
1682 expressions.push(initialize_variable_expression);
1683 }
1684
1685 let resolved_expression = self.analyze_expression(expression, context)?;
1686 let block_type = resolved_expression.ty.clone();
1687 expressions.push(resolved_expression);
1688
1689 let block_expression_kind = ExpressionKind::Block(expressions);
1690 self.pop_closed_block_scope();
1691
1692 let block_expr = self.create_expr(block_expression_kind, block_type, &expression.node);
1693 Ok(block_expr)
1694 }
1695
1696 fn analyze_when_expr(
1697 &mut self,
1698 context: &TypeContext,
1699 variables: &[swamp_ast::VariableBinding],
1700 true_expr: &swamp_ast::Expression,
1701 else_expr: Option<&swamp_ast::Expression>,
1702 ) -> Result<Expression, Error> {
1703 self.push_block_scope("when");
1705 let mut bindings = Vec::new();
1706 for variable_binding in variables {
1707 let mut_expr = if let Some(found_expr) = &variable_binding.expression {
1708 let any_context = TypeContext::new_anything_argument();
1709 self.analyze_mut_or_immutable_expression(
1710 found_expr,
1711 &any_context,
1712 LocationSide::Rhs,
1713 )?
1714 } else {
1715 let same_var = self.find_variable(&variable_binding.variable)?;
1716
1717 let argument_expression = if same_var.is_mutable() {
1718 let loc = SingleLocationExpression {
1719 kind: MutableReferenceKind::MutVariableRef,
1720 node: self.to_node(&variable_binding.variable.name),
1721 ty: Type::MutableReference(Box::from(same_var.resolved_type.clone())),
1722 starting_variable: same_var,
1723 access_chain: vec![],
1724 };
1725 MutRefOrImmutableExpression::Location(loc)
1726 } else {
1727 let generated_expr_kind = ExpressionKind::VariableAccess(same_var.clone());
1728 let generated_expression = self.create_expr(
1729 generated_expr_kind,
1730 same_var.resolved_type.clone(),
1731 &variable_binding.variable.name,
1732 );
1733 MutRefOrImmutableExpression::Expression(generated_expression)
1734 };
1735
1736 argument_expression
1737 };
1738
1739 let ty = mut_expr.ty();
1740
1741 if let Type::Optional(found_ty) = ty {
1742 let variable_ref = self.create_variable(&variable_binding.variable, &found_ty)?;
1743
1744 let binding = WhenBinding {
1745 variable: variable_ref,
1746 expr: mut_expr,
1747 };
1748 bindings.push(binding);
1749 } else {
1750 return Err(self.create_err(ErrorKind::ExpectedOptional, &true_expr.node));
1751 }
1752 }
1753
1754 let resolved_true = self.analyze_expression(true_expr, context)?;
1755 let block_type = resolved_true.ty.clone();
1756
1757 self.pop_block_scope("when");
1758
1759 let maybe_resolved_else = if let Some(found_else) = else_expr {
1760 let block_type_for_true_context = context.we_know_expected_type(&block_type);
1761 Some(Box::new(self.analyze_expression(
1762 found_else,
1763 &block_type_for_true_context,
1764 )?))
1765 } else {
1766 None
1767 };
1768
1769 let when_kind =
1770 ExpressionKind::When(bindings, Box::from(resolved_true), maybe_resolved_else);
1771
1772 let block_expr = self.create_expr(when_kind, block_type, &true_expr.node);
1773 Ok(block_expr)
1774 }
1775
1776 fn analyze_guard(
1777 &mut self,
1778 node: &swamp_ast::Node,
1779 context: &TypeContext,
1780 guard_expressions: &Vec<swamp_ast::GuardExpr>,
1781 ) -> Result<Expression, Error> {
1782 let mut guards = Vec::new();
1783 let mut found_wildcard = None;
1784 let mut detected_type = context.expected_type.cloned();
1785
1786 for guard in guard_expressions {
1787 let resolved_condition = match &guard.clause {
1788 swamp_ast::GuardClause::Wildcard(x) => {
1789 if found_wildcard.is_some() {
1790 return Err(
1791 self.create_err(ErrorKind::GuardCanNotHaveMultipleWildcards, node)
1792 );
1793 }
1794 found_wildcard = Some(x);
1795 None
1796 }
1797 swamp_ast::GuardClause::Expression(clause_expr) => {
1798 if found_wildcard.is_some() {
1799 return Err(self.create_err(ErrorKind::WildcardMustBeLastInGuard, node));
1800 }
1801 Some(self.analyze_bool_argument_expression(clause_expr)?)
1802 }
1803 };
1804
1805 let resolved_result = self.analyze_expression(
1806 &guard.result,
1807 &context.with_expected_type(detected_type.as_ref()),
1808 )?;
1809 let ty = resolved_result.ty.clone();
1810 if detected_type.is_none() && !matches!(ty, Type::Never) {
1811 detected_type = Some(ty.clone());
1812 }
1813
1814 guards.push(Guard {
1815 condition: resolved_condition,
1816 result: resolved_result,
1817 });
1818 }
1819
1820 if found_wildcard.is_none() {
1821 return Err(self.create_err(ErrorKind::GuardMustHaveWildcard, node));
1822 }
1823
1824 let kind = ExpressionKind::Guard(guards);
1825
1826 detected_type.map_or_else(
1827 || Err(self.create_err(ErrorKind::GuardHasNoType, node)),
1828 |found_expecting_type| {
1829 let expr = self.create_expr(kind, found_expecting_type, node);
1830 Ok(expr)
1831 },
1832 )
1833 }
1834
1835 fn analyze_lambda(
1836 &mut self,
1837 node: &swamp_ast::Node,
1838 variables: &[swamp_ast::Variable],
1839 ast_expr: &swamp_ast::Expression,
1840 context: &TypeContext,
1841 ) -> Result<Expression, Error> {
1842 let Type::Function(signature) = &context.expected_type.unwrap() else {
1843 return Err(self.create_err(ErrorKind::ExpectedLambda, node));
1844 };
1845
1846 let return_block_type = TypeContext::new_argument(&signature.return_type);
1847
1848 self.push_block_scope("lambda");
1849
1850 let arity_required = signature.parameters.len();
1851 let variable_types_to_create = if variables.len() == arity_required {
1852 &signature.parameters
1853 } else if variables.len() + 1 == arity_required {
1854 &signature.parameters[1..].to_vec()
1855 } else {
1856 return Err(self.create_err(ErrorKind::WrongNumberOfArguments(0, 0), node));
1857 };
1858
1859 let mut resolved_variables = Vec::new();
1860 for (variable, variable_type) in variables.iter().zip(variable_types_to_create) {
1861 let variable_ref = self.create_local_variable(
1862 &variable.name,
1863 Some(node),
1864 &variable_type.resolved_type,
1865 )?;
1866 resolved_variables.push(variable_ref);
1867 }
1868
1869 let analyzed_expression = self.analyze_expression(ast_expr, &return_block_type)?;
1870
1871 self.pop_block_scope("lambda");
1872
1873 Ok(self.create_expr(
1874 ExpressionKind::Lambda(resolved_variables, Box::new(analyzed_expression)),
1875 Type::Function(signature.clone()),
1876 node,
1877 ))
1878 }
1879
1880 pub fn analyze_variable_assignment(
1883 &mut self,
1884 variable: &swamp_ast::Variable,
1885 source_expression: &swamp_ast::Expression,
1886 ) -> Result<Expression, Error> {
1887 let maybe_found_variable = self.try_find_variable(&variable.name);
1888
1889 let required_type = maybe_found_variable
1890 .as_ref()
1891 .map(|found_variable| found_variable.resolved_type.clone());
1892
1893 let context = TypeContext::new_unsure_argument(required_type.as_ref());
1894
1895 let source_expr = self.analyze_expression(source_expression, &context)?;
1896 let ty = source_expr.ty.clone();
1897 if !ty.is_concrete() {
1898 return Err(self.create_err(ErrorKind::VariableTypeMustBeConcrete, &variable.name));
1899 }
1900
1901 let kind: ExpressionKind = if let Some(found_var) = maybe_found_variable {
1902 if !found_var.is_mutable() {
1903 return Err(self.create_err(ErrorKind::VariableIsNotMutable, &variable.name));
1904 }
1905 if !found_var.resolved_type.assignable_type(&ty) {
1906 return Err(self.create_err(
1907 ErrorKind::IncompatibleTypes {
1908 expected: ty,
1909 found: found_var.resolved_type.clone(),
1910 },
1911 &variable.name,
1912 ));
1913 }
1914 ExpressionKind::VariableReassignment(found_var, Box::from(source_expr))
1915 } else {
1916 let new_var = self.create_variable(variable, &ty)?;
1917 ExpressionKind::VariableDefinition(new_var, Box::from(source_expr))
1918 };
1919
1920 Ok(self.create_expr(kind, Type::Unit, &variable.name))
1921 }
1922
1923 fn analyze_create_variable(
1924 &mut self,
1925 var: &swamp_ast::Variable,
1926 annotation_type: Option<&swamp_ast::Type>,
1927 source_expression: &swamp_ast::Expression,
1928 ) -> Result<Expression, Error> {
1929 let ty = if let Some(found_ast_type) = annotation_type {
1930 Some(self.analyze_type(found_ast_type)?)
1931 } else {
1932 None
1933 };
1934
1935 let unsure_arg_context = TypeContext::new_unsure_argument(ty.as_ref());
1936
1937 let resolved_source = self.analyze_expression(source_expression, &unsure_arg_context)?;
1938
1939 let var_ref = self.create_local_variable(
1940 &var.name,
1941 Option::from(&var.is_mutable),
1942 &resolved_source.ty,
1943 )?;
1944
1945 let resolved_type = resolved_source.ty.clone();
1946 assert_ne!(resolved_type, Type::Unit);
1947 let kind = ExpressionKind::VariableDefinition(var_ref, Box::from(resolved_source));
1948
1949 let resolved_expr = self.create_expr(kind, Type::Unit, &var.name);
1950
1951 Ok(resolved_expr)
1952 }
1953
1954 fn add_location_item(
1955 &mut self,
1956 vec: &mut Vec<LocationAccess>,
1957 kind: LocationAccessKind,
1958 ty: Type,
1959 ast_node: &swamp_ast::Node,
1960 ) {
1961 let resolved_node = self.to_node(ast_node);
1962 let postfix = LocationAccess {
1963 node: resolved_node,
1964 ty,
1965 kind,
1966 };
1967
1968 vec.push(postfix);
1969 }
1970
1971 fn extract_single_intrinsic_call(body: &Expression) -> Option<IntrinsicFunction> {
1972 match &body.kind {
1973 ExpressionKind::Block(expressions) => {
1974 let first_kind = &expressions[0].kind;
1975 if let ExpressionKind::IntrinsicCallEx(intrinsic_fn, _args) = first_kind {
1976 return Some(intrinsic_fn.clone());
1977 }
1978 }
1979 _ => {}
1980 }
1981 None
1982 }
1983
1984 #[allow(clippy::too_many_lines)]
1985 fn analyze_chain_to_location(
1986 &mut self,
1987 chain: &swamp_ast::PostfixChain,
1988 context: &TypeContext,
1989 location_side: LocationSide,
1990 ) -> Result<SingleLocationExpression, Error> {
1991 let mut items = Vec::new();
1992
1993 let nothing_context = TypeContext::new(None);
1994
1995 let base_expr = self.analyze_expression(&chain.base, ¬hing_context)?;
1996 let ExpressionKind::VariableAccess(start_variable) = base_expr.kind else {
1997 return Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, &chain.base.node));
1998 };
1999
2000 if !start_variable.is_mutable() {
2001 return Err(self.create_err(ErrorKind::VariableIsNotMutable, &chain.base.node));
2002 }
2003
2004 let mut ty = start_variable.resolved_type.clone();
2005 for (i, item) in chain.postfixes.iter().enumerate() {
2006 match &item {
2007 swamp_ast::Postfix::FieldAccess(field_name_node) => {
2008 let (struct_type_ref, index, return_type) =
2010 self.analyze_struct_field(field_name_node, &ty)?;
2011 self.add_location_item(
2012 &mut items,
2013 LocationAccessKind::FieldIndex(struct_type_ref.clone(), index),
2014 return_type.clone(),
2015 field_name_node,
2016 );
2017
2018 ty = return_type.clone();
2019 }
2020 swamp_ast::Postfix::Subscript(key_expression) => {
2021 let is_last_in_chain = i == chain.postfixes.len() - 1;
2022 let create_if_not_exists =
2023 is_last_in_chain && location_side == LocationSide::Lhs;
2024
2025 let subscript_member_function_name = if create_if_not_exists {
2026 "subscript_mut_create_if_needed"
2027 } else {
2028 "subscript_mut"
2029 };
2030
2031 if let Some(found) = self
2032 .shared
2033 .state
2034 .instantiator
2035 .associated_impls
2036 .get_internal_member_function(&ty, subscript_member_function_name)
2037 .cloned()
2038 {
2039 let intrinsic_to_call =
2040 Self::extract_single_intrinsic_call(&found.body).expect("must exist");
2041
2042 let create_if_not_exists_bool_expr = self.create_expr(
2043 ExpressionKind::Literal(Literal::BoolLiteral(create_if_not_exists)),
2044 Type::Bool,
2045 &chain.base.node,
2046 );
2047
2048 let required_type = &found.signature.signature.parameters[1].resolved_type;
2049 let subscript_lookup_context = TypeContext::new_argument(required_type);
2050 let analyzed_key_expression =
2051 self.analyze_expression(key_expression, &subscript_lookup_context)?;
2052 let return_type = *found.signature.signature.return_type.clone();
2053 ty = return_type.clone();
2054 self.add_location_item(
2056 &mut items,
2057 LocationAccessKind::IntrinsicCallMut(
2058 intrinsic_to_call,
2059 vec![analyzed_key_expression, create_if_not_exists_bool_expr],
2060 ),
2061 return_type,
2062 &key_expression.node,
2063 );
2064 } else {
2065 return Err(self
2066 .create_err(ErrorKind::MissingSubscriptMember, &key_expression.node));
2067 }
2068 }
2069
2070 swamp_ast::Postfix::MemberCall(node, _generic_arguments, _regular_args) => {
2071 return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
2072 }
2073
2074 swamp_ast::Postfix::FunctionCall(node, _generic_arguments, _regular_args) => {
2075 return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
2076 }
2077 swamp_ast::Postfix::OptionalChainingOperator(node) => {
2078 return Err(self.create_err(ErrorKind::UnwrapCanNotBePartOfChain, node));
2079 }
2080 swamp_ast::Postfix::NoneCoalescingOperator(expr) => {
2081 return Err(
2082 self.create_err(ErrorKind::NoneCoalesceCanNotBePartOfChain, &expr.node)
2083 );
2084 }
2085 }
2086 }
2087
2088 if let Some(found_expected_type) = context.expected_type {
2089 if !ty.compatible_with(found_expected_type) {
2090 return Err(self.create_err(
2091 ErrorKind::IncompatibleTypes {
2092 expected: found_expected_type.clone(),
2093 found: ty,
2094 },
2095 &chain.base.node,
2096 ));
2097 }
2098 }
2099
2100 let location = SingleLocationExpression {
2101 kind: MutableReferenceKind::MutVariableRef,
2102 node: self.to_node(&chain.base.node),
2103 ty,
2104 starting_variable: start_variable,
2105 access_chain: items,
2106 };
2107 Ok(location)
2108 }
2109
2110 fn analyze_to_location(
2111 &mut self,
2112 expr: &swamp_ast::Expression,
2113 context: &TypeContext,
2114 location_type: LocationSide,
2115 ) -> Result<SingleLocationExpression, Error> {
2116 match &expr.kind {
2117 swamp_ast::ExpressionKind::PostfixChain(chain) => {
2118 self.analyze_chain_to_location(chain, context, location_type)
2119 }
2120 swamp_ast::ExpressionKind::VariableReference(variable) => {
2121 let var = self.find_variable(variable)?;
2122 if var.is_mutable() {
2123 Ok(SingleLocationExpression {
2124 kind: MutableReferenceKind::MutVariableRef,
2125 node: self.to_node(&variable.name),
2126 ty: Type::MutableReference(Box::from(var.resolved_type.clone())),
2127 starting_variable: var,
2128 access_chain: vec![],
2129 })
2130 } else {
2131 Err(self.create_err(ErrorKind::VariableIsNotMutable, &expr.node))
2132 }
2133 }
2134 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
2135 let generated_var = swamp_ast::Variable {
2136 name: qualified_identifier.name.clone(),
2137 is_mutable: None,
2138 };
2139 let var = self.find_variable(&generated_var)?;
2140 if var.is_mutable() {
2141 Ok(SingleLocationExpression {
2142 kind: MutableReferenceKind::MutVariableRef,
2143 node: self.to_node(&generated_var.name),
2144 ty: Type::MutableReference(Box::from(var.resolved_type.clone())),
2145 starting_variable: var,
2146 access_chain: vec![],
2147 })
2148 } else {
2149 Err(self.create_err(ErrorKind::VariableIsNotMutable, &expr.node))
2150 }
2151 }
2152 _ => Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, &expr.node)),
2153 }
2154 }
2155
2156 fn analyze_assignment_compound(
2157 &mut self,
2158 target_expression: &swamp_ast::Expression,
2159 ast_op: &swamp_ast::CompoundOperator,
2160 ast_source_expression: &swamp_ast::Expression,
2161 ) -> Result<Expression, Error> {
2162 let resolved_op = self.analyze_compound_operator(ast_op);
2163 let any_argument_context = TypeContext::new_anything_argument();
2164 let source_expr = self.analyze_expression(ast_source_expression, &any_argument_context)?;
2165 let source_expr_type_context = TypeContext::new_argument(&source_expr.ty);
2166
2167 let resolved_location = TargetAssignmentLocation(self.analyze_to_location(
2168 target_expression,
2169 &source_expr_type_context,
2170 LocationSide::Rhs,
2171 )?);
2172
2173 let kind = ExpressionKind::CompoundAssignment(
2174 resolved_location,
2175 resolved_op.kind,
2176 Box::from(source_expr),
2177 );
2178
2179 let expr = self.create_expr(kind, Type::Unit, &target_expression.node);
2180
2181 Ok(expr)
2182 }
2183
2184 fn analyze_assignment(
2185 &mut self,
2186 target_location: &swamp_ast::Expression,
2187 ast_source_expression: &swamp_ast::Expression,
2188 ) -> Result<Expression, Error> {
2189 let any_argument_context = TypeContext::new_anything_argument();
2190 let resolved_location =
2191 self.analyze_to_location(target_location, &any_argument_context, LocationSide::Lhs)?;
2192
2193 let ty = resolved_location.ty.clone();
2194 assert!(ty.is_concrete());
2195
2196 let lhs_argument_context = TypeContext::new_argument(&ty);
2197 let source_expr = self.analyze_expression(ast_source_expression, &lhs_argument_context)?;
2198
2199 let mut_location = TargetAssignmentLocation(resolved_location);
2200
2201 let kind = ExpressionKind::Assignment(Box::from(mut_location), Box::from(source_expr));
2202
2203 let expr = self.create_expr(kind, Type::Unit, &target_location.node); Ok(expr)
2206 }
2207
2208 #[must_use]
2209 pub const fn create_expr(
2210 &self,
2211 kind: ExpressionKind,
2212 ty: Type,
2213 ast_node: &swamp_ast::Node,
2214 ) -> Expression {
2215 Expression {
2217 kind,
2218 ty,
2219 node: self.to_node(ast_node),
2220 }
2221 }
2222
2223 #[must_use]
2224 pub fn create_expr_resolved(
2225 &self,
2226 kind: ExpressionKind,
2227 ty: Type,
2228 ast_node: &Node,
2229 ) -> Expression {
2230 Expression {
2231 kind,
2232 ty,
2233 node: ast_node.clone(),
2234 }
2235 }
2236
2237 fn analyze_destructuring(
2238 &mut self,
2239 node: &swamp_ast::Node,
2240 target_ast_variables: &[swamp_ast::Variable],
2241 tuple_expression: &swamp_ast::Expression,
2242 ) -> Result<Expression, Error> {
2243 let any_context = TypeContext::new_anything_argument();
2244 let tuple_resolved = self.analyze_expression(tuple_expression, &any_context)?;
2245 let tuple_expr_type = &tuple_resolved.ty;
2246
2247 let mut variable_refs = Vec::new();
2248 if let Type::Tuple(tuple) = tuple_expr_type.clone() {
2249 if target_ast_variables.len() > tuple.len() {
2250 return Err(self.create_err(ErrorKind::TooManyDestructureVariables, node));
2251 }
2252 for (ast_variable, tuple_type) in target_ast_variables.iter().zip(tuple.clone()) {
2253 let variable_ref = self.create_local_variable(
2254 &ast_variable.name,
2255 ast_variable.is_mutable.as_ref(),
2256 &tuple_type,
2257 )?;
2258 variable_refs.push(variable_ref);
2259 }
2260 let expr_kind =
2261 ExpressionKind::TupleDestructuring(variable_refs, tuple, Box::from(tuple_resolved));
2262
2263 Ok(self.create_expr(expr_kind, Type::Unit, node))
2264 } else {
2265 Err(self.create_err(ErrorKind::CanNotDestructure, node))
2266 }
2267 }
2268
2269 fn analyze_postfix_member_call(
2270 &mut self,
2271 type_that_member_is_on: &Type,
2272 is_mutable: bool,
2273 member_name: &swamp_ast::Node,
2274 ast_maybe_generic_arguments: Option<Vec<swamp_ast::Type>>,
2275 arguments: &[swamp_ast::Expression],
2276 suffixes: &mut Vec<Postfix>,
2277 ) -> Result<Type, Error> {
2278 let field_name_str = self.get_text(member_name).to_string();
2279
2280 let resolved_node = self.to_node(member_name);
2281
2282 let generic_arguments = if let Some(ast_generic_arguments) = ast_maybe_generic_arguments {
2283 let mut resolved_types = Vec::new();
2284 for ast_type in ast_generic_arguments {
2285 resolved_types.push(self.analyze_type(&ast_type)?);
2286 }
2287 resolved_types
2288 } else {
2289 vec![]
2290 };
2291
2292 let maybe_function = self
2293 .shared
2294 .state
2295 .instantiator
2296 .associated_impls
2297 .get_member_function(type_that_member_is_on, &field_name_str)
2298 .cloned();
2299
2300 let Some(found_function) = maybe_function else {
2301 return Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, member_name));
2302 };
2303
2304 let (maybe_generic, alternative_signature) = found_function.signatures();
2305
2306 let signature = if let Some(found_generic) = maybe_generic {
2307 let mut seq_map = SeqMap::new();
2308 if generic_arguments.len() != found_generic.generic_type_variables.len() {
2309 return Err(self
2310 .create_err_resolved(ErrorKind::WrongNumberOfArguments(0, 0), &resolved_node));
2311 }
2312 for (variable, generic_argument_type) in found_generic
2313 .generic_type_variables
2314 .iter()
2315 .zip(generic_arguments)
2316 {
2317 info!(?variable, ?generic_argument_type, "SETTING VAR");
2318 seq_map
2319 .insert(variable.0.to_string(), generic_argument_type.clone())
2320 .unwrap();
2321 }
2322 let scope = TypeVariableScope::new(seq_map);
2323 let instantiated_signature = self
2324 .shared
2325 .state
2326 .instantiator
2327 .instantiate_generic_signature(type_that_member_is_on, found_generic, &scope)?
2328 .clone();
2329
2330 &instantiated_signature.clone()
2331 } else {
2332 alternative_signature
2333 };
2334
2335 let self_type = &signature.parameters[0];
2336 if !self_type
2337 .resolved_type
2338 .compatible_with(type_that_member_is_on)
2339 || self_type.is_mutable && !is_mutable
2340 {
2341 return Err(self.create_err_resolved(ErrorKind::SelfNotCorrectType, &resolved_node));
2342 }
2343
2344 let resolved_arguments = self.analyze_and_verify_parameters(
2345 &resolved_node,
2346 &signature.parameters[1..],
2347 arguments,
2348 )?;
2349
2350 let kind = PostfixKind::MemberCall(found_function.clone(), resolved_arguments);
2351
2352 let postfix = Postfix {
2353 node: resolved_node.clone(),
2354 ty: *signature.return_type.clone(),
2355 kind,
2356 };
2357
2358 let last_type = postfix.ty.clone();
2359 suffixes.push(postfix);
2360
2361 Ok(last_type)
2362 }
2363
2364 fn types_did_not_match_try_late_coerce_expression(
2365 &self,
2366 expr: Expression,
2367 expected_type: &Type,
2368 encountered_type: &Type,
2369 node: &swamp_ast::Node,
2370 ) -> Result<Expression, Error> {
2371 if let Type::Optional(expected_inner_type) = expected_type {
2372 assert!(
2375 expected_inner_type
2376 .inner_optional_mut_or_immutable()
2377 .is_none()
2378 );
2379
2380 if encountered_type.inner_optional_mut_or_immutable().is_none() {
2382 if expected_inner_type.compatible_ignore_mutability_of(encountered_type) {
2384 let wrapped = self.create_expr(
2386 ExpressionKind::Option(Option::from(Box::new(expr))),
2387 expected_type.clone(),
2388 node,
2389 );
2390 return Ok(wrapped);
2391 }
2392 }
2393 } else if matches!(expected_type, &Type::Bool) {
2394 if encountered_type.inner_optional_mut_or_immutable().is_some() {
2396 let wrapped = self.create_expr(
2397 ExpressionKind::CoerceOptionToBool(Box::from(expr)),
2398 Type::Bool,
2399 node,
2400 );
2401 return Ok(wrapped);
2402 }
2403 }
2404
2405 Err(self.create_err(
2406 ErrorKind::IncompatibleTypes {
2407 expected: expected_type.clone(),
2408 found: encountered_type.clone(),
2409 },
2410 node,
2411 ))
2412 }
2413
2414 #[allow(clippy::too_many_lines)]
2415 fn analyze_generic_type(
2416 &mut self,
2417 symbol: &Symbol,
2418 analyzed_type_parameters: &[Type],
2419 node: &swamp_ast::Node,
2420 ) -> Result<Type, Error> {
2421 let ty = match symbol {
2422 Symbol::Blueprint(blueprint) => {
2425 if all_types_are_concrete_or_unit(analyzed_type_parameters) {
2426 self.shared
2427 .state
2428 .instantiator
2429 .instantiate_blueprint_and_members(blueprint, analyzed_type_parameters)?
2430 } else {
2431 Type::Generic(blueprint.clone(), analyzed_type_parameters.to_vec())
2432 }
2433 }
2434 Symbol::TypeGenerator(type_gen) => match type_gen.kind {
2435 TypeGeneratorKind::Slice => {
2436 Type::Slice(Box::new(analyzed_type_parameters[0].clone()))
2438 }
2439 TypeGeneratorKind::SlicePair => {
2440 Type::SlicePair(
2443 Box::new(analyzed_type_parameters[0].clone()),
2444 Box::new(analyzed_type_parameters[1].clone()),
2445 )
2446 }
2447 },
2448 _ => return Err(self.create_err(ErrorKind::UnknownSymbol, node)),
2449 };
2450
2451 Ok(ty)
2452 }
2453}