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