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