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