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::VariableDefinition(
672 variable,
673 coerce_type,
674 source_expression,
675 ) => self.analyze_create_variable(
676 variable,
677 Option::from(coerce_type),
678 source_expression,
679 )?,
680
681 swamp_script_ast::ExpressionKind::VariableAssignment(variable, source_expression) => {
682 self.analyze_variable_assignment(variable, source_expression)?
683 }
684 swamp_script_ast::ExpressionKind::DestructuringAssignment(variables, expression) => {
685 self.analyze_destructuring(&ast_expression.node, variables, expression)?
686 }
687
688 swamp_script_ast::ExpressionKind::StaticFunctionReference(qualified_identifier) => {
689 self.analyze_static_function_access(qualified_identifier)?
690 }
691 swamp_script_ast::ExpressionKind::IdentifierReference(variable) => {
692 self.analyze_identifier_reference(&variable.name)?
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::Assignment(location, source) => {
705 self.analyze_assignment(location, source)?
706 }
707 swamp_script_ast::ExpressionKind::CompoundAssignment(target, op, source) => {
708 self.analyze_assignment_compound(target, op, source)?
709 }
710
711 swamp_script_ast::ExpressionKind::BinaryOp(resolved_a, operator, resolved_b) => {
713 let (resolved_op, result_type) =
714 self.analyze_binary_op(resolved_a, operator, resolved_b)?;
715
716 self.create_expr(
717 ExpressionKind::BinaryOp(resolved_op),
718 result_type,
719 &ast_expression.node,
720 )
721 }
722 swamp_script_ast::ExpressionKind::UnaryOp(operator, expression) => {
723 let (resolved_op, result_type) = self.analyze_unary_op(operator, expression)?;
724 self.create_expr(
725 ExpressionKind::UnaryOp(resolved_op),
726 result_type,
727 &ast_expression.node,
728 )
729 }
730
731 swamp_script_ast::ExpressionKind::Block(expressions) => {
732 let (block, resulting_type) =
733 self.analyze_block(&ast_expression.node, context, expressions)?;
734 self.create_expr(
735 ExpressionKind::Block(block),
736 resulting_type,
737 &ast_expression.node,
738 )
739 }
740
741 swamp_script_ast::ExpressionKind::With(variable_bindings, expression) => {
742 self.analyze_with_expr(context, variable_bindings, expression)?
743 }
744
745 swamp_script_ast::ExpressionKind::When(variable_bindings, true_expr, else_expr) => {
746 self.analyze_when_expr(context, variable_bindings, true_expr, else_expr.as_deref())?
747 }
748
749 swamp_script_ast::ExpressionKind::InterpolatedString(string_parts) => {
750 let kind = ExpressionKind::InterpolatedString(
751 self.analyze_interpolated_string(string_parts)?,
752 );
753
754 self.create_expr(kind, Type::String, &ast_expression.node)
755 }
756
757 swamp_script_ast::ExpressionKind::StructLiteral(
759 struct_identifier,
760 fields,
761 has_rest,
762 ) => self.analyze_struct_instantiation(struct_identifier, fields, *has_rest)?,
763
764 swamp_script_ast::ExpressionKind::AnonymousStructLiteral(
765 fields,
766 rest_was_specified,
767 ) => self.analyze_anonymous_struct_literal(
768 &ast_expression.node,
769 fields,
770 *rest_was_specified,
771 context,
772 )?,
773
774 swamp_script_ast::ExpressionKind::Range(min_value, max_value, range_mode) => {
775 let range = self.analyze_range(min_value, max_value, range_mode)?;
776 self.create_expr(
777 ExpressionKind::Range(Box::from(range.min), Box::from(range.max), range.mode),
778 Type::Iterable(Box::from(Type::Int)),
779 &ast_expression.node,
780 )
781 }
782
783 swamp_script_ast::ExpressionKind::Literal(literal) => {
784 let (literal, resolved_type) =
785 self.analyze_literal(&ast_expression.node, literal, context)?;
786 self.create_expr(
787 ExpressionKind::Literal(literal),
788 resolved_type,
789 &ast_expression.node,
790 )
791 }
792
793 swamp_script_ast::ExpressionKind::ForLoop(pattern, iterable_expression, statements) => {
794 let resolved_iterator =
795 self.analyze_iterable(pattern.any_mut(), &iterable_expression.expression)?;
796
797 self.push_block_scope("for_loop");
798 let pattern = self.analyze_for_pattern(
799 pattern,
800 resolved_iterator.key_type.as_ref(),
801 &resolved_iterator.value_type,
802 )?;
803 let resolved_statements =
804 self.analyze_expression(statements, &context.enter_loop())?;
805 self.pop_block_scope("for_loop");
806 let resolved_type = resolved_statements.ty.clone();
807 self.create_expr(
808 ExpressionKind::ForLoop(
809 pattern,
810 resolved_iterator,
811 Box::from(resolved_statements),
812 ),
813 resolved_type,
814 &ast_expression.node,
815 )
816 }
817 swamp_script_ast::ExpressionKind::WhileLoop(expression, statements) => {
818 let condition = self.analyze_bool_argument_expression(expression)?;
819 let resolved_statements =
821 self.analyze_expression(statements, &context.enter_loop())?;
822 let resolved_type = resolved_statements.ty.clone();
823 self.create_expr(
826 ExpressionKind::WhileLoop(condition, Box::from(resolved_statements)),
827 resolved_type,
828 &ast_expression.node,
829 )
830 }
831
832 swamp_script_ast::ExpressionKind::If(
833 expression,
834 true_expression,
835 maybe_false_expression,
836 ) => self.analyze_if_expression(
837 expression,
838 true_expression,
839 maybe_false_expression.as_deref(),
840 context,
841 )?,
842
843 swamp_script_ast::ExpressionKind::Match(expression, arms) => {
844 let (match_expr, return_type) = self.analyze_match(expression, context, arms)?;
845 self.create_expr(
846 ExpressionKind::Match(match_expr),
847 return_type,
848 &ast_expression.node,
849 )
850 }
851 swamp_script_ast::ExpressionKind::Guard(guard_expressions) => {
852 self.analyze_guard(&ast_expression.node, context, guard_expressions)?
853 }
854 };
855
856 Ok(expression)
859 }
860
861 fn get_struct_type(
862 &mut self,
863 qualified_type_identifier: &swamp_script_ast::QualifiedTypeIdentifier,
864 ) -> Result<StructTypeRef, Error> {
865 let maybe_struct_type = self.analyze_named_type(qualified_type_identifier)?;
866 match maybe_struct_type {
867 Type::NamedStruct(struct_type) => Ok(struct_type),
868 _ => Err(self.create_err(
869 ErrorKind::UnknownStructTypeReference,
871 &qualified_type_identifier.name.0,
872 )),
873 }
874 }
875
876 #[must_use]
878 pub fn check_built_in_type(s: &str) -> Option<Type> {
879 let found = match s {
880 "Int" => Type::Int,
881 "Float" => Type::Float,
882 "Bool" => Type::Bool,
883 "String" => Type::String,
884 _ => return None,
885 };
886 Some(found)
887 }
888
889 pub(crate) fn analyze_named_type(
890 &mut self,
891 type_name_to_find: &swamp_script_ast::QualifiedTypeIdentifier,
892 ) -> Result<Type, Error> {
893 let (path, name) = self.get_path(type_name_to_find);
894 if let Some(ty) = Self::check_built_in_type(&name) {
896 return Ok(ty);
897 }
898
899 let symbol = {
900 let maybe_symbol_table = self.shared.get_symbol_table(&path);
901 let symbol_table = maybe_symbol_table.ok_or_else(|| {
902 self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)
903 })?;
904 symbol_table
905 .get_symbol(&name)
906 .ok_or_else(|| {
907 self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)
908 })?
909 .clone()
910 };
911
912 let mut analyzed_types = Vec::new();
913
914 for analyzed_type in &type_name_to_find.generic_params {
915 let ty = self.analyze_type(analyzed_type)?;
916
917 analyzed_types.push(ty);
918 }
919
920 let result_type = match symbol {
921 Symbol::Type(base_type) => base_type,
922 Symbol::Alias(alias_type) => alias_type.referenced_type.clone(),
923 _ => return Err(self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)),
924 };
925
926 Ok(result_type)
927 }
928
929 fn create_default_value_for_type(
930 &mut self,
931 node: &swamp_script_ast::Node,
932 field_type: &Type,
933 ) -> Result<Expression, Error> {
934 let kind = match field_type {
935 Type::Bool => ExpressionKind::Literal(Literal::BoolLiteral(false)),
936 Type::Int => ExpressionKind::Literal(Literal::IntLiteral(0)),
937 Type::Float => ExpressionKind::Literal(Literal::FloatLiteral(Fp::zero())),
938 Type::String => ExpressionKind::Literal(Literal::StringLiteral(String::new())),
939 Type::Array(array_type_ref) => {
940 ExpressionKind::Literal(Literal::Array(array_type_ref.clone(), vec![]))
941 }
942 Type::Tuple(tuple_type_ref) => {
943 let mut expressions = Vec::new();
944 for resolved_type in &tuple_type_ref.0 {
945 let expr = self.create_default_value_for_type(node, resolved_type)?;
946 expressions.push(expr);
947 }
948 ExpressionKind::Literal(Literal::TupleLiteral(tuple_type_ref.clone(), expressions))
949 }
950 Type::Map(map_type_ref) => {
951 ExpressionKind::Literal(Literal::Map(map_type_ref.clone(), vec![]))
952 }
953 Type::Optional(_optional_type) => ExpressionKind::Literal(Literal::NoneLiteral),
954
955 Type::NamedStruct(struct_ref) => {
956 self.create_default_static_call(node, &Type::NamedStruct(struct_ref.clone()))?
957 }
958 _ => {
959 return Err(
960 self.create_err(ErrorKind::NoDefaultImplemented(field_type.clone()), node)
961 );
962 }
963 };
964
965 let expr = self.create_expr(kind, field_type.clone(), node);
966 Ok(expr)
967 }
968
969 fn create_default_static_call(
970 &mut self,
971 node: &swamp_script_ast::Node,
972 ty: &Type,
973 ) -> Result<ExpressionKind, Error> {
974 self.lookup_associated_function(ty, "default").map_or_else(
975 || Err(self.create_err(ErrorKind::NoDefaultImplementedForType(ty.clone()), node)),
976 |function| {
977 let kind = match &*function {
978 Function::Internal(internal_function) => {
979 ExpressionKind::InternalFunctionAccess(internal_function.clone())
980 }
981 Function::External(external_function) => {
982 ExpressionKind::ExternalFunctionAccess(external_function.clone())
983 }
984 };
985
986 let base_expr =
987 self.create_expr(kind, Type::Function(function.signature().clone()), node);
988
989 let empty_call_postfix = Postfix {
990 node: self.to_node(node),
991 ty: *function.signature().return_type.clone(),
992 kind: PostfixKind::FunctionCall(vec![]),
993 };
994
995 let kind =
996 ExpressionKind::PostfixChain(Box::new(base_expr), vec![empty_call_postfix]);
997
998 Ok(kind)
999 },
1000 )
1001 }
1002
1003 fn add_postfix(
1004 &mut self,
1005 vec: &mut Vec<Postfix>,
1006 kind: PostfixKind,
1007 ty: Type,
1008 node: &swamp_script_ast::Node,
1009 ) {
1010 let resolved_node = self.to_node(node);
1011 let postfix = Postfix {
1012 node: resolved_node,
1013 ty,
1014 kind,
1015 };
1016
1017 vec.push(postfix);
1018 }
1019
1020 pub fn analyze_struct_field(
1025 &mut self,
1026 field_name: &swamp_script_ast::Node,
1027 tv: Type,
1028 ) -> Result<(AnonymousStructType, usize, Type), Error> {
1029 let field_name_str = self.get_text(field_name).to_string();
1030
1031 let anon_struct_ref = match &tv {
1032 Type::NamedStruct(struct_type) => struct_type.borrow().anon_struct_type.clone(),
1033 Type::AnonymousStruct(anon_struct) => anon_struct.clone(),
1034 _ => return Err(self.create_err(ErrorKind::UnknownStructField, field_name)),
1035 };
1036
1037 if let Some(found_field) = anon_struct_ref
1038 .field_name_sorted_fields
1039 .get(&field_name_str)
1040 {
1041 let index = anon_struct_ref
1042 .field_name_sorted_fields
1043 .get_index(&field_name_str)
1044 .expect("checked earlier");
1045
1046 return Ok((
1047 anon_struct_ref.clone(),
1048 index,
1049 found_field.field_type.clone(),
1050 ));
1051 }
1052
1053 Err(self.create_err(ErrorKind::UnknownStructField, field_name))
1054 }
1055
1056 #[allow(clippy::too_many_lines)]
1057 fn analyze_postfix_chain(
1058 &mut self,
1059 chain: &swamp_script_ast::PostfixChain,
1060 ) -> Result<Expression, Error> {
1061 if let swamp_script_ast::ExpressionKind::StaticMemberFunctionReference(
1062 qualified_type_reference,
1063 member_name,
1064 ) = &chain.base.kind
1065 {
1066 if let Some(found_expr) =
1067 self.check_for_internal_static_call(qualified_type_reference, member_name, &[])?
1068 {
1069 return Ok(found_expr);
1070 }
1071 }
1072
1073 let (start, is_mutable) =
1074 self.analyze_start_chain_expression_get_mutability(&chain.base, None)?;
1075
1076 let mut tv = TypeWithMut {
1077 resolved_type: start.ty.clone(),
1078 is_mutable,
1079 };
1080
1081 let mut uncertain = false;
1082
1083 let mut suffixes = Vec::new();
1084
1085 for item in &chain.postfixes {
1086 match item {
1087 swamp_script_ast::Postfix::FieldAccess(field_name) => {
1088 let (struct_type_ref, index, return_type) =
1089 self.analyze_struct_field(&field_name.clone(), tv.resolved_type)?;
1090 self.add_postfix(
1091 &mut suffixes,
1092 PostfixKind::StructField(struct_type_ref.clone(), index),
1093 return_type.clone(),
1094 field_name,
1095 );
1096
1097 tv.resolved_type = return_type.clone();
1098 }
1100 swamp_script_ast::Postfix::MemberCall(member_name, ast_arguments) => {
1101 let dereference = ast_arguments
1102 .iter()
1103 .map(|x| &x.expression)
1104 .collect::<Vec<_>>();
1105 if let Some(found_internal) = self.check_for_internal_member_call(
1106 &tv.resolved_type,
1107 tv.is_mutable,
1108 member_name,
1109 &dereference,
1110 )? {
1111 tv.resolved_type = found_internal.ty.clone();
1112 tv.is_mutable = false;
1113 suffixes.push(found_internal);
1114 } else {
1115 let member_name_str = self.get_text(member_name).to_string();
1116
1117 if let Some(found_member) = self
1118 .shared
1119 .state
1120 .associated_impls
1121 .get_member_function(&tv.resolved_type, &member_name_str)
1122 {
1123 let return_type = self.analyze_postfix_member_call(
1124 &tv.resolved_type,
1125 tv.is_mutable,
1126 member_name,
1127 ast_arguments,
1128 &mut suffixes,
1129 )?;
1130
1131 tv.resolved_type = return_type.clone();
1133 tv.is_mutable = false;
1134 } else {
1135 return Err(
1136 self.create_err(ErrorKind::UnknownMemberFunction, member_name)
1137 );
1138 }
1139 }
1140 }
1141 swamp_script_ast::Postfix::FunctionCall(node, arguments) => {
1142 if let Type::Function(signature) = &tv.resolved_type {
1143 let resolved_node = self.to_node(node);
1144 let resolved_arguments = self.analyze_and_verify_parameters(
1145 &resolved_node,
1146 &signature.parameters,
1147 arguments,
1148 )?;
1149 self.add_postfix(
1150 &mut suffixes,
1151 PostfixKind::FunctionCall(resolved_arguments),
1152 *signature.return_type.clone(),
1153 node,
1154 );
1155
1156 tv.resolved_type = *signature.return_type.clone();
1157 tv.is_mutable = false;
1158 } else {
1159 panic!("{}", &format!("what is this type {:?} ", tv.resolved_type))
1160 }
1161 }
1162
1163 swamp_script_ast::Postfix::Subscript(index_expr) => {
1164 let collection_type = tv.resolved_type.clone();
1165 match &collection_type {
1166 Type::String => {
1167 if let swamp_script_ast::ExpressionKind::Range(min, max, mode) =
1168 &index_expr.kind
1169 {
1170 let range = self.analyze_range(min, max, mode)?;
1171
1172 self.add_postfix(
1173 &mut suffixes,
1174 PostfixKind::StringRangeIndex(range),
1175 collection_type.clone(),
1176 &index_expr.node,
1177 );
1178
1179 tv.resolved_type = Type::String;
1180 } else {
1181 let int_argument_context = TypeContext::new_argument(&Type::Int);
1182 let resolved_index_expr =
1183 self.analyze_expression(index_expr, &int_argument_context)?;
1184 self.add_postfix(
1185 &mut suffixes,
1186 PostfixKind::StringIndex(resolved_index_expr),
1187 Type::String,
1188 &index_expr.node,
1189 );
1190 }
1191 tv.resolved_type = Type::String;
1192 tv.is_mutable = false;
1193 }
1194
1195 Type::Array(array_type_ref) => {
1196 if let swamp_script_ast::ExpressionKind::Range(
1197 min_expr,
1198 max_expr,
1199 mode,
1200 ) = &index_expr.kind
1201 {
1202 let range = self.analyze_range(min_expr, max_expr, mode)?;
1203
1204 self.add_postfix(
1205 &mut suffixes,
1206 PostfixKind::ArrayRangeIndex(array_type_ref.clone(), range),
1207 collection_type.clone(),
1208 &index_expr.node,
1209 );
1210
1211 tv.resolved_type = collection_type.clone();
1212 } else {
1213 let int_argument_context = TypeContext::new_argument(&Type::Int);
1214 let resolved_index_expr =
1215 self.analyze_expression(index_expr, &int_argument_context)?;
1216 self.add_postfix(
1217 &mut suffixes,
1218 PostfixKind::ArrayIndex(
1219 array_type_ref.clone(),
1220 resolved_index_expr,
1221 ),
1222 array_type_ref.item_type.clone(),
1223 &index_expr.node,
1224 );
1225
1226 tv.resolved_type = array_type_ref.item_type.clone();
1227 }
1228
1229 tv.is_mutable = false;
1230 }
1231
1232 Type::Map(map_type_ref) => {
1233 let key_type_context =
1234 TypeContext::new_argument(&map_type_ref.key_type);
1235 let resolved_key_expr =
1236 self.analyze_expression(index_expr, &key_type_context)?;
1237 let return_type =
1238 Type::Optional(Box::from(map_type_ref.value_type.clone()));
1239 self.add_postfix(
1240 &mut suffixes,
1241 PostfixKind::MapIndex(map_type_ref.clone(), resolved_key_expr),
1242 return_type.clone(),
1243 &index_expr.node,
1244 );
1245
1246 tv.resolved_type = return_type;
1247 tv.is_mutable = false;
1248 }
1249
1250 Type::Generic(base, generic_type_parameters) => match &**base {
1251 Type::External(found_rust_type) => {
1252 if found_rust_type.number == SPARSE_TYPE_ID {
1253 let sparse_id = self
1254 .shared
1255 .lookup_table
1256 .get_external_type("SparseId")
1257 .expect("SparseId is missing");
1258 let binding = Type::External(sparse_id.clone());
1259 let sparse_id_context = TypeContext::new_argument(&binding);
1260 let contained_type = &generic_type_parameters[0];
1261 let resolved_key =
1262 self.analyze_expression(index_expr, &sparse_id_context)?;
1263
1264 let return_type =
1265 Type::Optional(Box::new(contained_type.clone()));
1266
1267 self.add_postfix(
1268 &mut suffixes,
1269 PostfixKind::ExternalTypeIndexRef(
1270 found_rust_type.clone(),
1271 resolved_key,
1272 ),
1273 return_type.clone(),
1274 &index_expr.node,
1275 );
1276
1277 tv.resolved_type = return_type;
1278 tv.is_mutable = false;
1279 } else {
1280 panic!("unknown generic type lookup")
1281 }
1282 }
1283 _ => panic!("not supported"),
1284 },
1285 _ => {
1286 return Err(self.create_err(
1287 ErrorKind::ExpectedArray(collection_type),
1288 &index_expr.node,
1289 ));
1290 }
1291 }
1292 }
1293
1294 swamp_script_ast::Postfix::NoneCoalesce(default_expr) => {
1295 let unwrapped_type = if let Type::Optional(unwrapped_type) = &tv.resolved_type {
1296 unwrapped_type
1297 } else if uncertain {
1298 &tv.resolved_type
1299 } else {
1300 return Err(
1301 self.create_err(ErrorKind::CanNotNoneCoalesce, &default_expr.node)
1302 );
1303 };
1304
1305 let unwrapped_type_context = TypeContext::new_argument(unwrapped_type);
1306 let resolved_default_expr =
1307 self.analyze_expression(default_expr, &unwrapped_type_context)?;
1308 self.add_postfix(
1309 &mut suffixes,
1310 PostfixKind::NoneCoalesce(resolved_default_expr),
1311 unwrapped_type.clone(),
1312 &default_expr.node,
1313 );
1314 tv.resolved_type = unwrapped_type.clone();
1315 uncertain = false; }
1317
1318 swamp_script_ast::Postfix::OptionUnwrap(option_node) => {
1319 if let Type::Optional(unwrapped_type) = &tv.resolved_type {
1320 uncertain = true;
1321 self.add_postfix(
1322 &mut suffixes,
1323 PostfixKind::OptionUnwrap,
1324 *unwrapped_type.clone(),
1325 option_node,
1326 );
1327 tv.resolved_type = *unwrapped_type.clone();
1328 } else {
1329 return Err(self.create_err(ErrorKind::ExpectedOptional, option_node));
1330 }
1331 }
1332 }
1333 }
1334
1335 if uncertain {
1336 if let Type::Optional(_) = tv.resolved_type {
1337 } else {
1338 tv.resolved_type = Type::Optional(Box::from(tv.resolved_type.clone()));
1339 }
1340 }
1341
1342 Ok(self.create_expr(
1343 ExpressionKind::PostfixChain(Box::new(start), suffixes),
1344 tv.resolved_type,
1345 &chain.base.node,
1346 ))
1347 }
1348
1349 fn analyze_bool_argument_expression(
1350 &mut self,
1351 expression: &swamp_script_ast::Expression,
1352 ) -> Result<BooleanExpression, Error> {
1353 let bool_context = TypeContext::new_argument(&Type::Bool);
1354 let resolved_expression = self.analyze_expression(expression, &bool_context)?;
1355 let expr_type = resolved_expression.ty.clone();
1356
1357 let bool_expression = match expr_type {
1358 Type::Bool => resolved_expression,
1359 Type::Optional(_) => self.create_expr(
1360 ExpressionKind::CoerceOptionToBool(Box::new(resolved_expression)),
1361 Type::Bool,
1362 &expression.node,
1363 ),
1364 _ => {
1365 return Err(self.create_err(ErrorKind::ExpectedBooleanExpression, &expression.node));
1366 }
1367 };
1368
1369 Ok(BooleanExpression {
1370 expression: Box::from(bool_expression),
1371 })
1372 }
1373
1374 fn analyze_iterable(
1375 &mut self,
1376 force_mut: Option<swamp_script_ast::Node>,
1377 expression: &swamp_script_ast::MutableOrImmutableExpression,
1378 ) -> Result<Iterable, Error> {
1379 let any_context = TypeContext::new_anything_argument();
1380 let resolved_expression: MutOrImmutableExpression = if force_mut.is_some() {
1381 let resolved_node = self.to_node(&force_mut.unwrap());
1382 MutOrImmutableExpression {
1383 expression_or_location: ArgumentExpressionOrLocation::Location(
1384 self.analyze_to_location(
1385 &expression.expression,
1386 &any_context,
1387 LocationSide::Rhs,
1388 )?,
1389 ),
1390 is_mutable: Some(resolved_node),
1391 }
1392 } else {
1393 self.analyze_mut_or_immutable_expression(expression, &any_context, LocationSide::Rhs)?
1394 };
1395
1396 let resolved_type = &resolved_expression.ty().clone();
1397 let (key_type, value_type): (Option<Type>, Type) = match resolved_type {
1398 Type::Array(array_type) => (Some(Type::Int), array_type.item_type.clone()),
1399 Type::Map(map_type_ref) => (
1400 Some(map_type_ref.key_type.clone()),
1401 map_type_ref.value_type.clone(),
1402 ),
1403 Type::String => (Some(Type::Int), Type::String),
1404 Type::Iterable(item_type) => (None, *item_type.clone()),
1405 Type::Generic(_base_type, params) => {
1406 let rust_type_ref_for_id = self
1410 .shared
1411 .lookup_table
1412 .get_external_type("SparseId")
1413 .expect("SparseId was missing");
1414 let rust_id_type = Type::External(rust_type_ref_for_id.clone());
1415 (Some(rust_id_type), params[0].clone())
1416 }
1417 _ => return Err(self.create_err(ErrorKind::NotAnIterator, &expression.expression.node)),
1418 };
1419
1420 Ok(Iterable {
1421 key_type,
1422 value_type,
1423 resolved_expression: Box::new(resolved_expression),
1424 })
1425 }
1426
1427 fn analyze_argument_expressions(
1428 &mut self,
1429 expected_type: Option<&Type>,
1430 ast_expressions: &[swamp_script_ast::Expression],
1431 ) -> Result<Vec<Expression>, Error> {
1432 let mut resolved_expressions = Vec::new();
1433 let argument_expressions_context = TypeContext::new_unsure_argument(expected_type);
1434 for expression in ast_expressions {
1435 resolved_expressions
1436 .push(self.analyze_expression(expression, &argument_expressions_context)?);
1437 }
1438 Ok(resolved_expressions)
1439 }
1440
1441 fn analyze_block(
1442 &mut self,
1443 _node: &swamp_script_ast::Node,
1444 context: &TypeContext,
1445 ast_expressions: &[swamp_script_ast::Expression],
1446 ) -> Result<(Vec<Expression>, Type), Error> {
1447 if ast_expressions.is_empty() {
1448 return Ok((vec![], Type::Unit));
1449 }
1450
1451 self.push_block_scope("block");
1452
1453 let mut resolved_expressions = Vec::with_capacity(ast_expressions.len());
1454
1455 for expression in &ast_expressions[..ast_expressions.len() - 1] {
1456 let stmt_context = context.with_expected_type(Some(&Type::Unit));
1457 let expr = self.analyze_expression(expression, &stmt_context)?;
1458
1459 if matches!(expr.ty, Type::Never) {
1460 resolved_expressions.push(expr);
1461 return Ok((resolved_expressions, Type::Never));
1462 }
1463
1464 resolved_expressions.push(expr);
1465 }
1466
1467 let last_expr =
1469 self.analyze_expression(&ast_expressions[ast_expressions.len() - 1], context)?;
1470 let last_type = last_expr.ty.clone();
1471 resolved_expressions.push(last_expr);
1472
1473 self.pop_block_scope("block");
1474
1475 Ok((resolved_expressions, last_type))
1476 }
1477
1478 fn analyze_interpolated_string(
1479 &mut self,
1480 string_parts: &[swamp_script_ast::StringPart],
1481 ) -> Result<Vec<StringPart>, Error> {
1482 let mut resolved_parts = Vec::new();
1483 for part in string_parts {
1484 let resolved_string_part = match part {
1485 swamp_script_ast::StringPart::Literal(string_node, processed_string) => {
1486 StringPart::Literal(self.to_node(string_node), processed_string.to_string())
1487 }
1488 swamp_script_ast::StringPart::Interpolation(expression, format_specifier) => {
1489 let any_context = TypeContext::new_anything_argument();
1490 let expr = self.analyze_expression(expression, &any_context)?;
1491 let resolved_format_specifier =
1492 self.analyze_format_specifier(Option::from(format_specifier));
1493 StringPart::Interpolation(expr, resolved_format_specifier)
1494 }
1495 };
1496
1497 resolved_parts.push(resolved_string_part);
1498 }
1499
1500 Ok(resolved_parts)
1501 }
1502
1503 pub(crate) fn analyze_static_function_access(
1504 &self,
1505 qualified_func_name: &swamp_script_ast::QualifiedIdentifier,
1506 ) -> Result<Expression, Error> {
1507 let path = self.get_module_path(qualified_func_name.module_path.as_ref());
1508 let function_name = self.get_text(&qualified_func_name.name);
1509
1510 if let Some(found_table) = self.shared.get_symbol_table(&path) {
1511 if let Some(found_func) = found_table.get_function(function_name) {
1512 let (kind, signature) = match found_func {
1513 FuncDef::Internal(internal_fn) => (
1514 ExpressionKind::InternalFunctionAccess(internal_fn.clone()),
1515 &internal_fn.signature,
1516 ),
1517 FuncDef::External(external_fn) => (
1518 ExpressionKind::ExternalFunctionAccess(external_fn.clone()),
1519 &external_fn.signature,
1520 ),
1521 FuncDef::Intrinsic(_) => {
1523 return Err(
1524 self.create_err(ErrorKind::UnknownFunction, &qualified_func_name.name)
1525 );
1526 }
1527 };
1528
1529 return Ok(self.create_expr(
1530 kind,
1531 Type::Function(signature.clone()),
1532 &qualified_func_name.name,
1533 ));
1534 }
1535 }
1536 Err(self.create_err(ErrorKind::UnknownFunction, &qualified_func_name.name))
1537 }
1538
1539 fn analyze_identifier_reference(
1541 &self,
1542 var_node: &swamp_script_ast::Node,
1543 ) -> Result<Expression, Error> {
1544 let text = self.get_text(var_node);
1545
1546 if let Some(found_variable) = self.try_find_variable(var_node) {
1549 return Ok(self.create_expr(
1550 ExpressionKind::VariableAccess(found_variable.clone()),
1551 found_variable.resolved_type.clone(),
1552 var_node,
1553 ));
1554 }
1555
1556 if let Some(found_symbol) = self.shared.lookup_table.get_symbol(text) {
1557 let expr = match found_symbol {
1558 Symbol::FunctionDefinition(func) => match func {
1559 FuncDef::External(found_external_function) => self.create_expr(
1560 ExpressionKind::ExternalFunctionAccess(found_external_function.clone()),
1561 Type::Function(found_external_function.signature.clone()),
1562 var_node,
1563 ),
1564 FuncDef::Internal(found_internal_function) => self.create_expr(
1565 ExpressionKind::InternalFunctionAccess(found_internal_function.clone()),
1566 Type::Function(found_internal_function.signature.clone()),
1567 var_node,
1568 ),
1569 FuncDef::Intrinsic(_) => todo!(),
1570 },
1571
1572 _ => {
1573 return Err(self.create_err(ErrorKind::UnknownIdentifier, var_node));
1574 }
1575 };
1576 return Ok(expr);
1577 }
1578
1579 Err(self.create_err(ErrorKind::UnknownIdentifier, var_node))
1580 }
1581 fn analyze_usize_index(
1582 &mut self,
1583 usize_expression: &swamp_script_ast::Expression,
1584 ) -> Result<Expression, Error> {
1585 let int_context = TypeContext::new_argument(&Type::Int);
1586 let lookup_expression = self.analyze_expression(usize_expression, &int_context)?;
1587 let lookup_resolution = lookup_expression.ty.clone();
1588
1589 match &lookup_resolution {
1590 Type::Int => {}
1591 _ => Err(self.create_err(
1592 ErrorKind::ArrayIndexMustBeInt(lookup_resolution),
1593 &usize_expression.node,
1594 ))?,
1595 }
1596
1597 Ok(lookup_expression)
1598 }
1599
1600 fn analyze_array_type_helper(
1601 &mut self,
1602 node: &swamp_script_ast::Node,
1603 items: &[swamp_script_ast::Expression],
1604 expected_type: Option<&Type>,
1605 ) -> Result<(ArrayTypeRef, Vec<Expression>), Error> {
1606 let expressions = self.analyze_argument_expressions(None, items)?;
1607 let item_type = if expressions.is_empty() {
1608 if let Some(found_expected_type) = expected_type {
1609 info!(?found_expected_type, "found array type");
1610 if let Type::Array(found) = found_expected_type {
1611 found.item_type.clone()
1612 } else {
1613 return Err(self.create_err(ErrorKind::NotAnArray, node));
1614 }
1615 } else {
1616 return Err(self.create_err(ErrorKind::NotAnArray, node));
1617 }
1618 } else {
1619 expressions[0].ty.clone()
1620 };
1621
1622 let array_type = ArrayType { item_type };
1623
1624 let array_type_ref = Rc::new(array_type);
1625
1626 Ok((array_type_ref, expressions))
1627 }
1628
1629 fn push_block_scope(&mut self, _debug_str: &str) {
1630 self.scope.block_scope_stack.push(BlockScope {
1631 mode: BlockScopeMode::Open,
1632 variables: SeqMap::default(),
1633 });
1634 }
1635
1636 fn pop_block_scope(&mut self, _debug_str: &str) {
1637 self.scope.block_scope_stack.pop();
1638 }
1639
1640 fn push_closed_block_scope(&mut self) {
1641 self.scope.block_scope_stack.push(BlockScope {
1642 mode: BlockScopeMode::Closed,
1643 variables: SeqMap::default(),
1644 });
1645 }
1646
1647 fn pop_closed_block_scope(&mut self) {
1648 self.scope.block_scope_stack.pop();
1649 }
1650
1651 fn analyze_enum_variant_ref(
1652 &self,
1653 qualified_type_identifier: &swamp_script_ast::QualifiedTypeIdentifier,
1654 variant_name: &swamp_script_ast::LocalTypeIdentifier,
1655 ) -> Result<EnumVariantTypeRef, Error> {
1656 let variant_name_string = self.get_text(&variant_name.0).to_string();
1657 self.get_enum_variant_type(qualified_type_identifier, &variant_name_string)
1658 }
1659
1660 fn analyze_match(
1661 &mut self,
1662 scrutinee: &swamp_script_ast::MutableOrImmutableExpression,
1663 default_context: &TypeContext,
1664 arms: &Vec<swamp_script_ast::MatchArm>,
1665 ) -> Result<(Match, Type), Error> {
1666 let mut known_type = default_context.expected_type.cloned();
1667 let own_context = default_context.clone();
1668 let scrutinee_context = TypeContext::new_anything_argument();
1670 let resolved_scrutinee = self.analyze_mut_or_immutable_expression(
1671 scrutinee,
1672 &scrutinee_context,
1673 LocationSide::Rhs,
1674 )?;
1675 let scrutinee_type = resolved_scrutinee.ty().clone();
1676
1677 if arms.is_empty() {
1679 return Err(self.create_err(ErrorKind::EmptyMatch, &scrutinee.expression.node));
1680 }
1681
1682 let mut resolved_arms = Vec::with_capacity(arms.len());
1683
1684 for arm in arms {
1685 let (resolved_arm, _anyone_wants_mutable) = self.analyze_arm(
1686 arm,
1687 &resolved_scrutinee,
1688 &own_context.with_expected_type(known_type.as_ref()),
1689 &scrutinee_type,
1690 )?;
1691
1692 if known_type.is_none() && !matches!(resolved_arm.expression.ty, Type::Never) {
1693 known_type = Some(resolved_arm.expression.ty.clone());
1694 }
1695 resolved_arms.push(resolved_arm);
1696 }
1697
1698 known_type.map_or_else(
1699 || {
1700 Err(self.create_err(
1701 ErrorKind::MatchArmsMustHaveTypes,
1702 &scrutinee.expression.node,
1703 ))
1704 },
1705 |encountered_type| {
1706 if matches!(encountered_type, Type::Never) {
1707 Err(self.create_err(
1708 ErrorKind::IncompatibleTypes(encountered_type.clone(), encountered_type),
1709 &scrutinee.expression.node,
1710 ))
1711 } else {
1712 Ok((
1713 Match {
1714 expression: Box::new(resolved_scrutinee),
1715 arms: resolved_arms,
1716 },
1717 encountered_type,
1718 ))
1719 }
1720 },
1721 )
1722 }
1723
1724 fn analyze_arm(
1725 &mut self,
1726 arm: &swamp_script_ast::MatchArm,
1727 _expression: &MutOrImmutableExpression,
1728 type_context: &TypeContext,
1729 expected_condition_type: &Type,
1730 ) -> Result<(MatchArm, bool), Error> {
1731 let (resolved_pattern, scope_was_pushed, anyone_wants_mutable) =
1732 self.analyze_pattern(&arm.pattern, expected_condition_type)?;
1733
1734 let resolved_expression = self.analyze_expression(&arm.expression, type_context)?;
1735 if scope_was_pushed {
1736 self.pop_block_scope("analyze_arm");
1737 }
1738
1739 let resolved_type = resolved_expression.ty.clone();
1740
1741 Ok((
1742 MatchArm {
1743 pattern: resolved_pattern,
1744 expression: Box::from(resolved_expression),
1745 expression_type: resolved_type,
1746 },
1747 anyone_wants_mutable,
1748 ))
1749 }
1750
1751 fn str_to_int(text: &str) -> Result<i32, ParseIntError> {
1752 text.parse::<i32>()
1753 }
1754
1755 fn str_to_float(text: &str) -> Result<f32, ParseFloatError> {
1756 text.parse::<f32>()
1757 }
1758
1759 fn analyze_pattern_literal(
1760 &mut self,
1761 node: &swamp_script_ast::Node,
1762 ast_literal: &swamp_script_ast::LiteralKind,
1763 expected_condition_type: &Type,
1764 ) -> Result<NormalPattern, Error> {
1765 let required_condition_type_context = TypeContext::new_argument(expected_condition_type);
1766 let (resolved_literal, literal_type) =
1767 self.analyze_literal(node, ast_literal, &required_condition_type_context)?;
1768
1769 if !literal_type.compatible_with(expected_condition_type) {
1770 return Err(self.create_err(
1771 ErrorKind::IncompatibleTypes(literal_type, expected_condition_type.clone()),
1772 node,
1773 ));
1774 }
1775
1776 Ok(NormalPattern::Literal(resolved_literal))
1777 }
1778
1779 const fn to_node(&self, node: &swamp_script_ast::Node) -> Node {
1780 Node {
1781 span: Span {
1782 file_id: self.shared.file_id,
1783 offset: node.span.offset,
1784 length: node.span.length,
1785 },
1786 }
1787 }
1788
1789 fn get_module_path(&self, module_path: Option<&swamp_script_ast::ModulePath>) -> Vec<String> {
1790 module_path.as_ref().map_or_else(Vec::new, |found| {
1791 let mut strings = Vec::new();
1792 for path_item in &found.0 {
1793 strings.push(self.get_text(path_item).to_string());
1794 }
1795 strings
1796 })
1797 }
1798
1799 fn get_enum_variant_type(
1800 &self,
1801 qualified_type_identifier: &swamp_script_ast::QualifiedTypeIdentifier,
1802 variant_name: &str,
1803 ) -> Result<EnumVariantTypeRef, Error> {
1804 let (symbol_table, enum_name) =
1805 self.get_symbol_table_and_name(qualified_type_identifier)?;
1806 symbol_table
1807 .get_enum_variant_type(&enum_name, variant_name)
1808 .ok_or_else(|| {
1809 self.create_err(
1810 ErrorKind::UnknownEnumVariantType,
1811 &qualified_type_identifier.name.0,
1812 )
1813 })
1814 }
1815
1816 pub(crate) fn get_symbol_table_and_name(
1817 &self,
1818 type_identifier: &swamp_script_ast::QualifiedTypeIdentifier,
1819 ) -> Result<(&SymbolTable, String), Error> {
1820 let path = self.get_module_path(type_identifier.module_path.as_ref());
1821 let name = self.get_text(&type_identifier.name.0).to_string();
1822
1823 let maybe_symbol_table = self.shared.get_symbol_table(&path);
1824 maybe_symbol_table.map_or_else(
1825 || Err(self.create_err(ErrorKind::UnknownModule, &type_identifier.name.0)),
1826 |symbol_table| Ok((symbol_table, name)),
1827 )
1828 }
1829
1830 const fn analyze_compound_operator(
1831 &self,
1832 ast_operator: &swamp_script_ast::CompoundOperator,
1833 ) -> CompoundOperator {
1834 let resolved_node = self.to_node(&ast_operator.node);
1835 let resolved_kind = match ast_operator.kind {
1836 swamp_script_ast::CompoundOperatorKind::Add => CompoundOperatorKind::Add,
1837 swamp_script_ast::CompoundOperatorKind::Sub => CompoundOperatorKind::Sub,
1838 swamp_script_ast::CompoundOperatorKind::Mul => CompoundOperatorKind::Mul,
1839 swamp_script_ast::CompoundOperatorKind::Div => CompoundOperatorKind::Div,
1840 swamp_script_ast::CompoundOperatorKind::Modulo => CompoundOperatorKind::Modulo,
1841 };
1842
1843 CompoundOperator {
1844 node: resolved_node,
1845 kind: resolved_kind,
1846 }
1847 }
1848
1849 const fn to_node_option(&self, maybe_node: Option<&swamp_script_ast::Node>) -> Option<Node> {
1850 match maybe_node {
1851 None => None,
1852 Some(node) => Some(self.to_node(node)),
1853 }
1854 }
1855
1856 const fn analyze_format_specifier(
1857 &self,
1858 ast_format_specifier: Option<&swamp_script_ast::FormatSpecifier>,
1859 ) -> Option<FormatSpecifier> {
1860 let f = match ast_format_specifier {
1861 None => return None,
1862 Some(ast_format) => match ast_format {
1863 swamp_script_ast::FormatSpecifier::LowerHex(node) => FormatSpecifier {
1864 node: self.to_node(node),
1865 kind: FormatSpecifierKind::LowerHex,
1866 },
1867 swamp_script_ast::FormatSpecifier::UpperHex(node) => FormatSpecifier {
1868 node: self.to_node(node),
1869 kind: FormatSpecifierKind::UpperHex,
1870 },
1871 swamp_script_ast::FormatSpecifier::Binary(node) => FormatSpecifier {
1872 node: self.to_node(node),
1873 kind: FormatSpecifierKind::Binary,
1874 },
1875 swamp_script_ast::FormatSpecifier::Float(node) => FormatSpecifier {
1876 node: self.to_node(node),
1877 kind: FormatSpecifierKind::Float,
1878 },
1879 swamp_script_ast::FormatSpecifier::Precision(value, node, x) => {
1880 let (precision_type, precision_node) = match x {
1881 swamp_script_ast::PrecisionType::Float(node) => {
1882 (PrecisionType::Float, self.to_node(node))
1883 }
1884 swamp_script_ast::PrecisionType::String(node) => {
1885 (PrecisionType::String, self.to_node(node))
1886 }
1887 };
1888 FormatSpecifier {
1889 node: self.to_node(node),
1890 kind: FormatSpecifierKind::Precision(
1891 *value,
1892 precision_node,
1893 precision_type,
1894 ),
1895 }
1896 }
1897 },
1898 };
1899
1900 Some(f)
1901 }
1902
1903 fn analyze_with_expr(
1904 &mut self,
1905 context: &TypeContext,
1906 variables: &[swamp_script_ast::VariableBinding],
1907 expression: &swamp_script_ast::Expression,
1908 ) -> Result<Expression, Error> {
1909 let mut variable_expressions = Vec::new();
1910
1911 for variable in variables {
1912 let any_context = TypeContext::new_anything_argument();
1913 let var = self.analyze_mut_or_immutable_expression(
1914 &variable.expression,
1915 &any_context,
1916 LocationSide::Rhs,
1917 )?;
1918 variable_expressions.push(var);
1919 }
1920
1921 self.push_closed_block_scope();
1922 let mut expressions = Vec::new();
1923 for (variable_binding, resolved_expression) in variables.iter().zip(variable_expressions) {
1924 let initialize_variable_expression = self.create_variable_binding_for_with(
1925 &variable_binding.variable,
1926 resolved_expression,
1927 )?;
1928 expressions.push(initialize_variable_expression);
1929 }
1930
1931 let resolved_expression = self.analyze_expression(expression, context)?;
1932 let block_type = resolved_expression.ty.clone();
1933 expressions.push(resolved_expression);
1934
1935 let block_expression_kind = ExpressionKind::Block(expressions);
1936 self.pop_closed_block_scope();
1937
1938 let block_expr = self.create_expr(block_expression_kind, block_type, &expression.node);
1939 Ok(block_expr)
1940 }
1941
1942 fn analyze_when_expr(
1943 &mut self,
1944 context: &TypeContext,
1945 variables: &[swamp_script_ast::WhenBinding],
1946 true_expr: &swamp_script_ast::Expression,
1947 else_expr: Option<&swamp_script_ast::Expression>,
1948 ) -> Result<Expression, Error> {
1949 self.push_block_scope("when");
1951 let mut bindings = Vec::new();
1952 for variable_binding in variables {
1953 let mut_expr = if let Some(found_expr) = &variable_binding.expression {
1954 let any_context = TypeContext::new_anything_argument();
1955 self.analyze_mut_or_immutable_expression(
1956 found_expr,
1957 &any_context,
1958 LocationSide::Rhs,
1959 )?
1960 } else {
1961 let same_var = self.find_variable(&variable_binding.variable)?;
1962
1963 let is_mutable = same_var.mutable_node.clone();
1964 let argument_expression = if same_var.is_mutable() {
1965 let loc = SingleLocationExpression {
1966 kind: SingleLocationExpressionKind::MutVariableRef,
1967 node: self.to_node(&variable_binding.variable.name),
1968 ty: same_var.resolved_type.clone(),
1969 starting_variable: same_var,
1970 access_chain: vec![],
1971 };
1972 ArgumentExpressionOrLocation::Location(loc)
1973 } else {
1974 let generated_expr_kind = ExpressionKind::VariableAccess(same_var.clone());
1975 let generated_expression = self.create_expr(
1976 generated_expr_kind,
1977 same_var.resolved_type.clone(),
1978 &variable_binding.variable.name,
1979 );
1980 ArgumentExpressionOrLocation::Expression(generated_expression)
1981 };
1982
1983 MutOrImmutableExpression {
1984 expression_or_location: argument_expression,
1985 is_mutable,
1986 }
1987 };
1988
1989 let ty = mut_expr.ty();
1990
1991 if let Type::Optional(found_ty) = ty {
1992 let variable_ref = self.create_variable(&variable_binding.variable, found_ty)?;
1993
1994 let binding = WhenBinding {
1995 variable: variable_ref,
1996 expr: mut_expr,
1997 };
1998 bindings.push(binding);
1999 } else {
2000 return Err(self.create_err(ErrorKind::ExpectedOptional, &true_expr.node));
2001 }
2002 }
2003
2004 let resolved_true = self.analyze_expression(true_expr, context)?;
2005 let block_type = resolved_true.ty.clone();
2006
2007 self.pop_block_scope("when");
2008
2009 let maybe_resolved_else = if let Some(found_else) = else_expr {
2010 let block_type_for_true_context = context.we_know_expected_type(&block_type);
2011 Some(Box::new(self.analyze_expression(
2012 found_else,
2013 &block_type_for_true_context,
2014 )?))
2015 } else {
2016 None
2017 };
2018
2019 let when_kind =
2020 ExpressionKind::When(bindings, Box::from(resolved_true), maybe_resolved_else);
2021
2022 let block_expr = self.create_expr(when_kind, block_type, &true_expr.node);
2023 Ok(block_expr)
2024 }
2025
2026 fn analyze_guard(
2027 &mut self,
2028 node: &swamp_script_ast::Node,
2029 context: &TypeContext,
2030 guard_expressions: &Vec<swamp_script_ast::GuardExpr>,
2031 ) -> Result<Expression, Error> {
2032 let mut guards = Vec::new();
2033 let mut found_wildcard = None;
2034 let mut detected_type = context.expected_type.cloned();
2035
2036 for guard in guard_expressions {
2037 let resolved_condition = match &guard.clause {
2038 swamp_script_ast::GuardClause::Wildcard(x) => {
2039 if found_wildcard.is_some() {
2040 return Err(
2041 self.create_err(ErrorKind::GuardCanNotHaveMultipleWildcards, node)
2042 );
2043 }
2044 found_wildcard = Some(x);
2045 None
2046 }
2047 swamp_script_ast::GuardClause::Expression(clause_expr) => {
2048 if found_wildcard.is_some() {
2049 return Err(self.create_err(ErrorKind::WildcardMustBeLastInGuard, node));
2050 }
2051 Some(self.analyze_bool_argument_expression(clause_expr)?)
2052 }
2053 };
2054
2055 let resolved_result = self.analyze_expression(
2056 &guard.result,
2057 &context.with_expected_type(detected_type.as_ref()),
2058 )?;
2059 let ty = resolved_result.ty.clone();
2060 if detected_type.is_none() && !matches!(ty, Type::Never) {
2061 detected_type = Some(ty.clone());
2062 }
2063
2064 guards.push(Guard {
2065 condition: resolved_condition,
2066 result: resolved_result,
2067 });
2068 }
2069
2070 if found_wildcard.is_none() {
2071 return Err(self.create_err(ErrorKind::GuardMustHaveWildcard, node));
2072 }
2073
2074 let kind = ExpressionKind::Guard(guards);
2075
2076 detected_type.map_or_else(
2077 || Err(self.create_err(ErrorKind::GuardHasNoType, node)),
2078 |found_expecting_type| {
2079 let expr = self.create_expr(kind, found_expecting_type, node);
2080 Ok(expr)
2081 },
2082 )
2083 }
2084
2085 pub fn analyze_variable_assignment(
2088 &mut self,
2089 variable: &swamp_script_ast::Variable,
2090 source_expression: &swamp_script_ast::MutableOrImmutableExpression,
2091 ) -> Result<Expression, Error> {
2092 let any_argument_context = TypeContext::new_anything_argument();
2093 let source_expr = self.analyze_mut_or_immutable_expression(
2094 source_expression,
2095 &any_argument_context,
2096 LocationSide::Rhs,
2097 )?;
2098 let ty = source_expr.ty().clone();
2099 if !ty.is_concrete() {
2100 return Err(self.create_err(ErrorKind::VariableTypeMustBeConcrete, &variable.name));
2101 }
2102
2103 let maybe_found_variable = self.try_find_variable(&variable.name);
2104
2105 let kind: ExpressionKind = if let Some(found_var) = maybe_found_variable {
2106 if !found_var.is_mutable() {
2107 return Err(self.create_err(ErrorKind::VariableIsNotMutable, &variable.name));
2108 }
2109 if !found_var.resolved_type.assignable_type(&ty) {
2110 return Err(self.create_err(
2111 ErrorKind::IncompatibleTypes(found_var.resolved_type.clone(), ty.clone()),
2112 &variable.name,
2113 ));
2114 }
2115 ExpressionKind::VariableReassignment(found_var, Box::from(source_expr))
2116 } else {
2117 let new_var = self.create_variable(variable, &ty)?;
2118 ExpressionKind::VariableDefinition(new_var, Box::from(source_expr))
2119 };
2120
2121 Ok(self.create_expr(kind, Type::Unit, &variable.name))
2122 }
2123
2124 fn analyze_create_variable(
2125 &mut self,
2126 var: &swamp_script_ast::Variable,
2127 annotation_type: Option<&swamp_script_ast::Type>,
2128 source_expression: &swamp_script_ast::MutableOrImmutableExpression,
2129 ) -> Result<Expression, Error> {
2130 let ty = if let Some(found_ast_type) = annotation_type {
2131 Some(self.analyze_type(found_ast_type)?)
2132 } else {
2133 None
2134 };
2135
2136 let unsure_arg_context = TypeContext::new_unsure_argument(ty.as_ref());
2137
2138 let resolved_source = self.analyze_mut_or_immutable_expression(
2139 source_expression,
2140 &unsure_arg_context,
2141 LocationSide::Rhs,
2142 )?;
2143
2144 let var_ref = self.create_local_variable(
2145 &var.name,
2146 Option::from(&var.is_mutable),
2147 &resolved_source.ty(),
2148 )?;
2149
2150 let resolved_type = resolved_source.ty().clone();
2151 assert_ne!(resolved_type, Type::Unit);
2152 let kind = ExpressionKind::VariableDefinition(var_ref, Box::from(resolved_source));
2153
2154 let resolved_expr = self.create_expr(kind, Type::Unit, &var.name);
2155
2156 Ok(resolved_expr)
2157 }
2158
2159 fn add_location_item(
2160 &mut self,
2161 vec: &mut Vec<LocationAccess>,
2162 kind: LocationAccessKind,
2163 ty: Type,
2164 ast_node: &swamp_script_ast::Node,
2165 ) {
2166 let resolved_node = self.to_node(ast_node);
2167 let postfix = LocationAccess {
2168 node: resolved_node.clone(),
2169 ty,
2170 kind,
2171 };
2172
2173 vec.push(postfix);
2174 }
2175
2176 #[allow(clippy::too_many_lines)]
2177 fn analyze_chain_to_location(
2178 &mut self,
2179 chain: &swamp_script_ast::PostfixChain,
2180 context: &TypeContext,
2181 location_side: LocationSide,
2182 ) -> Result<SingleLocationExpression, Error> {
2183 let mut items = Vec::new();
2184
2185 let nothing_context =
2186 TypeContext::new(None, None, TypeContextScope::ArgumentOrOutsideFunction);
2187
2188 let base_expr = self.analyze_expression(&chain.base, ¬hing_context)?;
2189 let ExpressionKind::VariableAccess(start_variable) = base_expr.kind else {
2190 return Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, &chain.base.node));
2191 };
2192
2193 if !start_variable.is_mutable() {
2194 return Err(self.create_err(ErrorKind::VariableIsNotMutable, &chain.base.node));
2195 }
2196
2197 let mut ty = start_variable.resolved_type.clone();
2198 for (i, item) in chain.postfixes.iter().enumerate() {
2199 match &item {
2200 swamp_script_ast::Postfix::FieldAccess(field_name_node) => {
2201 let (struct_type_ref, index, return_type) =
2203 self.analyze_struct_field(field_name_node, ty)?;
2204 self.add_location_item(
2205 &mut items,
2206 LocationAccessKind::FieldIndex(struct_type_ref.clone(), index),
2207 return_type.clone(),
2208 field_name_node,
2209 );
2210
2211 ty = return_type.clone();
2212 }
2213 swamp_script_ast::Postfix::Subscript(lookup_expr) => {
2214 let is_range = if let swamp_script_ast::ExpressionKind::Range(min, max, mode) =
2215 &lookup_expr.kind
2216 {
2217 Some(self.analyze_range(min, max, mode)?)
2218 } else {
2219 None
2220 };
2221 match &ty {
2222 Type::String => {
2223 if let Some(range) = is_range {
2224 self.add_location_item(
2225 &mut items,
2226 LocationAccessKind::StringRange(range),
2227 Type::String,
2228 &lookup_expr.node,
2229 );
2230 } else {
2231 let index_expr_context = TypeContext::new_argument(&Type::Int);
2232 let index_expr =
2233 self.analyze_expression(lookup_expr, &index_expr_context)?; self.add_location_item(
2235 &mut items,
2236 LocationAccessKind::StringIndex(index_expr),
2237 Type::String,
2238 &lookup_expr.node,
2239 );
2240 }
2241 ty = Type::String;
2242 }
2243
2244 Type::Array(array_type) => {
2245 let int_argument_context = TypeContext::new_argument(&Type::Int);
2246 let index_expr =
2247 self.analyze_expression(lookup_expr, &int_argument_context)?; self.add_location_item(
2249 &mut items,
2250 LocationAccessKind::ArrayIndex(array_type.clone(), index_expr),
2251 array_type.item_type.clone(),
2252 &lookup_expr.node,
2253 );
2254 ty = array_type.item_type.clone();
2255 }
2256
2257 Type::Map(map_type) => {
2258 let key_type_argument_context =
2259 TypeContext::new_argument(&map_type.key_type);
2260 let key_expr =
2261 self.analyze_expression(lookup_expr, &key_type_argument_context)?;
2262 let is_last = i == chain.postfixes.len() - 1;
2263 let allow_auto_insert = is_last && location_side == LocationSide::Lhs;
2264 let (kind, lookup_type) = if allow_auto_insert {
2265 (
2268 LocationAccessKind::MapIndexInsertIfNonExisting(
2269 map_type.clone(),
2270 key_expr,
2271 ),
2272 map_type.value_type.clone(),
2273 )
2274 } else {
2275 let optional_value_type =
2276 Type::Optional(Box::from(map_type.value_type.clone()));
2277 (
2278 LocationAccessKind::MapIndex(map_type.clone(), key_expr),
2279 optional_value_type,
2280 )
2281 };
2282
2283 self.add_location_item(
2284 &mut items,
2285 kind,
2286 lookup_type.clone(),
2287 &lookup_expr.node,
2288 );
2289 ty = lookup_type;
2290 }
2291
2292 Type::Generic(collection_type, generic_params) => {
2293 if let Type::External(rust_type) = &**collection_type {
2294 let val_type = generic_params[0].clone();
2295 if rust_type.number == SPARSE_TYPE_ID {
2296 let sparse_id_type = self
2297 .shared
2298 .lookup_table
2299 .get_external_type("SparseId")
2300 .expect("should have SparseId");
2301
2302 let key_type = Type::External(sparse_id_type.clone());
2303 let key_type_context = TypeContext::new_argument(&key_type);
2304
2305 let key_expr =
2306 self.analyze_expression(lookup_expr, &key_type_context)?;
2307
2308 self.add_location_item(
2309 &mut items,
2310 LocationAccessKind::ExternalTypeIndex(
2311 rust_type.clone(),
2312 key_expr,
2313 ),
2314 key_type.clone(),
2315 &lookup_expr.node,
2316 );
2317
2318 ty = Type::Optional(Box::from(val_type.clone()));
2319 }
2320 }
2321 }
2322
2323 _ => {
2324 return Err(
2325 self.create_err(ErrorKind::IllegalIndexInChain, &lookup_expr.node)
2326 );
2327 }
2328 }
2329 }
2330
2331 swamp_script_ast::Postfix::MemberCall(node, _) => {
2332 return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
2333 }
2334
2335 swamp_script_ast::Postfix::FunctionCall(node, _) => {
2336 return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
2337 }
2338 swamp_script_ast::Postfix::OptionUnwrap(node) => {
2339 return Err(self.create_err(ErrorKind::UnwrapCanNotBePartOfChain, node));
2340 }
2341 swamp_script_ast::Postfix::NoneCoalesce(expr) => {
2342 return Err(
2343 self.create_err(ErrorKind::NoneCoalesceCanNotBePartOfChain, &expr.node)
2344 );
2345 }
2346 }
2347 }
2348
2349 if let Some(found_expected_type) = context.expected_type {
2350 if !ty.compatible_with(found_expected_type) {
2351 return Err(self.create_err(
2352 ErrorKind::IncompatibleTypes(ty, found_expected_type.clone()),
2353 &chain.base.node,
2354 ));
2355 }
2356 }
2357
2358 let location = SingleLocationExpression {
2359 kind: SingleLocationExpressionKind::MutVariableRef,
2360 node: self.to_node(&chain.base.node),
2361 ty: ty.clone(),
2362 starting_variable: start_variable,
2363 access_chain: items,
2364 };
2365 Ok(location)
2366 }
2367
2368 fn analyze_to_location(
2369 &mut self,
2370 expr: &swamp_script_ast::Expression,
2371 context: &TypeContext,
2372 location_type: LocationSide,
2373 ) -> Result<SingleLocationExpression, Error> {
2374 match &expr.kind {
2375 swamp_script_ast::ExpressionKind::PostfixChain(chain) => {
2376 self.analyze_chain_to_location(chain, context, location_type)
2377 }
2378 swamp_script_ast::ExpressionKind::IdentifierReference(variable) => {
2379 let var = self.find_variable(variable)?;
2380 if var.is_mutable() {
2381 Ok(SingleLocationExpression {
2382 kind: SingleLocationExpressionKind::MutVariableRef,
2383 node: self.to_node(&variable.name),
2384 ty: var.resolved_type.clone(),
2385 starting_variable: var,
2386 access_chain: vec![],
2387 })
2388 } else {
2389 Err(self.create_err(ErrorKind::VariableIsNotMutable, &expr.node))
2390 }
2391 }
2392 _ => Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, &expr.node)),
2393 }
2394 }
2395
2396 #[allow(clippy::single_match)]
2397 fn check_special_assignment_compound(
2398 &mut self,
2399 target_expression: &swamp_script_ast::Expression,
2400 target_type: &Type,
2401 op: &CompoundOperatorKind,
2402 source: &swamp_script_ast::Expression,
2403 source_type: &Type,
2404 ) -> Result<Option<ExpressionKind>, Error> {
2405 match &target_type {
2406 Type::Array(array_type) => {
2407 let target_type_context = TypeContext::new_argument(target_type);
2408 let source_type_context = TypeContext::new_argument(source_type);
2409 if *op == CompoundOperatorKind::Add
2410 && source_type.compatible_with(&array_type.item_type)
2411 {
2412 let target_location = SingleMutLocationExpression(self.analyze_to_location(
2414 target_expression,
2415 &target_type_context,
2416 LocationSide::Rhs,
2417 )?);
2418 let resolved_source = self.analyze_expression(source, &source_type_context)?;
2419 return Ok(Option::from(ExpressionKind::IntrinsicCallMut(
2420 IntrinsicFunction::VecSelfPush,
2421 target_location,
2422 vec![resolved_source],
2423 )));
2424 } else if *op == CompoundOperatorKind::Add
2425 && source_type.compatible_with(target_type)
2426 {
2427 let target_location = SingleMutLocationExpression(self.analyze_to_location(
2429 target_expression,
2430 &target_type_context,
2431 LocationSide::Rhs,
2432 )?);
2433 let resolved_source = self.analyze_expression(source, &source_type_context)?;
2434 return Ok(Option::from(ExpressionKind::IntrinsicCallMut(
2435 IntrinsicFunction::VecSelfExtend,
2436 target_location,
2437 vec![resolved_source],
2438 )));
2439 }
2440 }
2441 _ => {}
2442 }
2443
2444 Ok(None)
2445 }
2446
2447 fn analyze_assignment_compound(
2448 &mut self,
2449 target_expression: &swamp_script_ast::Expression,
2450 ast_op: &swamp_script_ast::CompoundOperator,
2451 ast_source_expression: &swamp_script_ast::Expression,
2452 ) -> Result<Expression, Error> {
2453 let resolved_op = self.analyze_compound_operator(ast_op);
2454 let any_argument_context = TypeContext::new_anything_argument();
2455 let source_expr = self.analyze_expression(ast_source_expression, &any_argument_context)?;
2456 let source_expr_type_context = TypeContext::new_argument(&source_expr.ty);
2457
2458 let resolved_location = SingleMutLocationExpression(self.analyze_to_location(
2459 target_expression,
2460 &source_expr_type_context,
2461 LocationSide::Rhs,
2462 )?);
2463
2464 let kind = if let Some(found_special) = self.check_special_assignment_compound(
2465 target_expression,
2466 &resolved_location.0.ty,
2467 &resolved_op.kind,
2468 ast_source_expression,
2469 &source_expr.ty,
2470 )? {
2471 found_special
2472 } else {
2473 ExpressionKind::CompoundAssignment(
2474 resolved_location,
2475 resolved_op.kind,
2476 Box::from(source_expr),
2477 )
2478 };
2479
2480 let expr = self.create_expr(kind, Type::Unit, &target_expression.node);
2481
2482 Ok(expr)
2483 }
2484
2485 fn analyze_assignment(
2486 &mut self,
2487 target_location: &swamp_script_ast::Expression,
2488 ast_source_expression: &swamp_script_ast::Expression,
2489 ) -> Result<Expression, Error> {
2490 let any_argument_context = TypeContext::new_anything_argument();
2491 let resolved_location =
2492 self.analyze_to_location(target_location, &any_argument_context, LocationSide::Lhs)?;
2493
2494 let ty = resolved_location.ty.clone();
2495 if ty == Type::Unit {
2496 error!(?ast_source_expression, "unit problem");
2497 }
2498
2499 let lhs_argument_context = TypeContext::new_argument(&ty);
2500 let source_expr = self.analyze_expression(ast_source_expression, &lhs_argument_context)?;
2501
2502 let mut_location = SingleMutLocationExpression(resolved_location);
2503
2504 let kind = ExpressionKind::Assignment(Box::from(mut_location), Box::from(source_expr));
2505
2506 let expr = self.create_expr(kind, Type::Unit, &target_location.node); Ok(expr)
2509 }
2510
2511 #[must_use]
2512 pub fn create_mut_single_location_expr(
2513 &self,
2514 kind: SingleLocationExpressionKind,
2515 ty: Type,
2516 ast_node: &swamp_script_ast::Node,
2517 ) -> SingleMutLocationExpression {
2518 SingleMutLocationExpression(SingleLocationExpression {
2519 kind,
2520 ty,
2521 starting_variable: Rc::new(Variable {
2522 name: Node::default(),
2523 resolved_type: Type::Int,
2524 mutable_node: None,
2525 scope_index: 0,
2526 variable_index: 0,
2527 }),
2528 node: self.to_node(ast_node),
2529 access_chain: vec![],
2530 })
2531 }
2532
2533 #[must_use]
2534 pub fn create_single_location_expr(
2535 &self,
2536 kind: SingleLocationExpressionKind,
2537 ty: Type,
2538 ast_node: &swamp_script_ast::Node,
2539 ) -> SingleLocationExpression {
2540 SingleLocationExpression {
2541 kind,
2542 ty,
2543 starting_variable: Rc::new(Variable {
2544 name: Node::default(),
2545 resolved_type: Type::Int,
2546 mutable_node: None,
2547 scope_index: 0,
2548 variable_index: 0,
2549 }),
2550 node: self.to_node(ast_node),
2551 access_chain: vec![],
2552 }
2553 }
2554
2555 #[must_use]
2556 pub fn create_single_location_expr_resolved(
2557 &self,
2558 kind: SingleLocationExpressionKind,
2559 ty: Type,
2560 node: &Node,
2561 ) -> SingleLocationExpression {
2562 SingleLocationExpression {
2563 kind,
2564 ty,
2565 starting_variable: Rc::new(Variable {
2566 name: Node::default(),
2567 resolved_type: Type::Int,
2568 mutable_node: None,
2569 scope_index: 0,
2570 variable_index: 0,
2571 }),
2572 node: node.clone(),
2573 access_chain: vec![],
2574 }
2575 }
2576 #[must_use]
2577 pub fn create_mut_single_location_expr_resolved(
2578 &self,
2579 kind: SingleLocationExpressionKind,
2580 ty: Type,
2581 node: &Node,
2582 ) -> SingleMutLocationExpression {
2583 SingleMutLocationExpression(SingleLocationExpression {
2584 kind,
2585 ty,
2586 starting_variable: Rc::new(Variable {
2587 name: Node::default(),
2588 resolved_type: Type::Int,
2589 mutable_node: None,
2590 scope_index: 0,
2591 variable_index: 0,
2592 }),
2593 node: node.clone(),
2594 access_chain: vec![],
2595 })
2596 }
2597
2598 #[must_use]
2599 pub const fn create_expr(
2600 &self,
2601 kind: ExpressionKind,
2602 ty: Type,
2603 ast_node: &swamp_script_ast::Node,
2604 ) -> Expression {
2605 Expression {
2607 kind,
2608 ty,
2609 node: self.to_node(ast_node),
2610 }
2611 }
2612
2613 #[must_use]
2614 pub fn create_expr_resolved(
2615 &self,
2616 kind: ExpressionKind,
2617 ty: Type,
2618 ast_node: &Node,
2619 ) -> Expression {
2620 Expression {
2621 kind,
2622 ty,
2623 node: ast_node.clone(),
2624 }
2625 }
2626
2627 fn analyze_destructuring(
2628 &mut self,
2629 node: &swamp_script_ast::Node,
2630 target_ast_variables: &[swamp_script_ast::Variable],
2631 tuple_expression: &swamp_script_ast::Expression,
2632 ) -> Result<Expression, Error> {
2633 let any_context = TypeContext::new_anything_argument();
2634 let tuple_resolved = self.analyze_expression(tuple_expression, &any_context)?;
2635 let tuple_expr_type = &tuple_resolved.ty;
2636
2637 let mut variable_refs = Vec::new();
2638 if let Type::Tuple(tuple) = tuple_expr_type.clone() {
2639 if target_ast_variables.len() > tuple.0.len() {
2640 return Err(self.create_err(ErrorKind::TooManyDestructureVariables, node));
2641 }
2642 for (variable_ref, tuple_type) in target_ast_variables.iter().zip(tuple.0.clone()) {
2643 let (variable_ref, _is_reassignment) =
2644 self.set_or_overwrite_variable_with_type(variable_ref, &tuple_type)?;
2645 variable_refs.push(variable_ref);
2646 }
2647 let expr_kind =
2648 ExpressionKind::TupleDestructuring(variable_refs, tuple, Box::from(tuple_resolved));
2649
2650 Ok(self.create_expr(expr_kind, Type::Unit, node))
2651 } else {
2652 Err(self.create_err(ErrorKind::CanNotDestructure, node))
2653 }
2654 }
2655
2656 fn analyze_postfix_member_func_call(
2657 &mut self,
2658 resolved_node: &Node,
2659 found_function: &FunctionRef,
2660 encountered_self_type: &Type,
2661 is_mutable: bool,
2662 arguments: &[swamp_script_ast::MutableOrImmutableExpression],
2663 ) -> Result<Postfix, Error> {
2664 let signature = found_function.signature();
2665
2666 let self_type = &signature.parameters[0];
2667 if !self_type
2668 .resolved_type
2669 .compatible_with(&encountered_self_type)
2670 || self_type.is_mutable && !is_mutable
2671 {
2672 return Err(self.create_err_resolved(ErrorKind::SelfNotCorrectType, resolved_node));
2673 }
2674
2675 let resolved_arguments = self.analyze_and_verify_parameters(
2676 resolved_node,
2677 &signature.parameters[1..],
2678 arguments,
2679 )?;
2680
2681 let kind = PostfixKind::MemberCall(found_function.clone(), resolved_arguments);
2682 let postfix = Postfix {
2683 node: resolved_node.clone(),
2684 ty: *signature.return_type.clone(),
2685 kind,
2686 };
2687
2688 Ok(postfix)
2689 }
2690
2691 fn analyze_postfix_field_call(
2692 &mut self,
2693 resolved_node: &Node,
2694 struct_type: &StructTypeRef,
2695 field: &StructTypeField,
2696 index: usize,
2697 signature: &Signature,
2698 arguments: &[swamp_script_ast::MutableOrImmutableExpression],
2699 ) -> Result<Vec<Postfix>, Error> {
2700 let mut suffixes = Vec::new();
2701 let struct_field_kind =
2703 PostfixKind::StructField(struct_type.borrow().anon_struct_type.clone(), index);
2704
2705 let struct_field_postfix = Postfix {
2706 node: resolved_node.clone(),
2707 ty: field.field_type.clone(),
2708 kind: struct_field_kind,
2709 };
2710
2711 suffixes.push(struct_field_postfix);
2712
2713 let resolved_arguments =
2714 self.analyze_and_verify_parameters(resolved_node, &signature.parameters, arguments)?;
2715
2716 let call_kind = PostfixKind::FunctionCall(resolved_arguments);
2717
2718 let call_postfix = Postfix {
2719 node: resolved_node.clone(),
2720 ty: *signature.return_type.clone(),
2721 kind: call_kind,
2722 };
2723 suffixes.push(call_postfix);
2724
2725 Ok(suffixes)
2726 }
2727
2728 fn analyze_postfix_member_call(
2729 &mut self,
2730 type_that_member_is_on: &Type,
2731 is_mutable: bool,
2732 member_name: &swamp_script_ast::Node,
2733 arguments: &[swamp_script_ast::MutableOrImmutableExpression],
2734 suffixes: &mut Vec<Postfix>,
2735 ) -> Result<Type, Error> {
2736 let field_name_str = self.get_text(member_name).to_string();
2737
2738 let resolved_node = self.to_node(member_name);
2739
2740 let maybe_function = self
2741 .shared
2742 .state
2743 .associated_impls
2744 .get_member_function(&type_that_member_is_on, &field_name_str)
2745 .cloned();
2746
2747 let postfixes = match maybe_function {
2748 Some(found_function_member) => {
2749 let postfix = self.analyze_postfix_member_func_call(
2750 &resolved_node,
2751 &found_function_member,
2752 type_that_member_is_on,
2753 is_mutable,
2754 arguments,
2755 )?;
2756 vec![postfix]
2757 }
2758 _ => {
2759 return Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, member_name));
2760 } };
2800
2801 let last_type = postfixes.last().unwrap().ty.clone();
2802 suffixes.extend(postfixes);
2803
2804 Ok(last_type)
2805 }
2806
2807 fn analyze_break(
2823 &self,
2824 context: &TypeContext,
2825 node: &swamp_script_ast::Node,
2826 ) -> Result<Expression, Error> {
2827 if !context.allows_break() {
2828 return Err(self.create_err(ErrorKind::BreakOutsideLoop, node));
2829 }
2830
2831 Ok(Expression {
2832 kind: ExpressionKind::Break,
2833 ty: Type::Never,
2834 node: self.to_node(node),
2835 })
2836 }
2837
2838 fn analyze_return(
2839 &mut self,
2840 context: &TypeContext,
2841 optional_expression: Option<&swamp_script_ast::Expression>,
2842 node: &swamp_script_ast::Node,
2843 ) -> Result<Expression, Error> {
2844 if !context.allows_return() {
2845 return Err(self.create_err(ErrorKind::ReturnOutsideCompare, node));
2846 }
2847
2848 let return_context = context.for_return();
2849 let inner = if let Some(expr) = optional_expression {
2850 Some(Box::new(self.analyze_expression(expr, &return_context)?))
2851 } else {
2852 None
2854 };
2855
2856 Ok(self.create_expr(ExpressionKind::Return(inner), Type::Never, node))
2857 }
2858
2859 fn analyze_continue(
2860 &self,
2861 context: &TypeContext,
2862 node: &swamp_script_ast::Node,
2863 ) -> Result<Expression, Error> {
2864 if !context.allows_continue() {
2865 return Err(self.create_err(ErrorKind::ContinueOutsideLoop, node));
2866 }
2867 Ok(self.create_expr(ExpressionKind::Continue, Type::Never, node))
2868 }
2869
2870 fn coerce_expression(
2871 &self,
2872 expr: Expression,
2873 expected_type: &Type,
2874 encountered_type: &Type,
2875 node: &swamp_script_ast::Node,
2876 ) -> Result<Expression, Error> {
2877 if !matches!(encountered_type, Type::Optional(_)) {
2878 if let Type::Optional(expected_inner_type) = expected_type {
2880 if encountered_type.compatible_with(expected_inner_type) {
2881 let wrapped = self.create_expr(
2882 ExpressionKind::Option(Option::from(Box::new(expr))),
2883 expected_type.clone(),
2884 node,
2885 );
2886 return Ok(wrapped);
2887 }
2888 }
2889 } else if matches!(expected_type, &Type::Bool) {
2890 if let Type::Optional(_inner_type) = encountered_type {
2891 let wrapped = self.create_expr(
2892 ExpressionKind::CoerceOptionToBool(Box::from(expr)),
2893 Type::Bool,
2894 node,
2895 );
2896 return Ok(wrapped);
2897 }
2898 }
2899
2900 error!(?expr, "expr");
2901 error!(?expected_type, ?encountered_type, "incompatible types");
2902
2903 Err(self.create_err(
2904 ErrorKind::IncompatibleTypes(expected_type.clone(), encountered_type.clone()),
2905 node,
2906 ))
2907 }
2908}