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