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