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_node::{FileId, Node, Span};
24use swamp_script_semantic::modules::ModuleRef;
25use swamp_script_semantic::prelude::*;
26use swamp_script_semantic::symtbl::{FuncDef, Symbol, SymbolTable, SymbolTableRef};
27use swamp_script_semantic::{
28 ArgumentExpressionOrLocation, LocationAccess, LocationAccessKind, MutOrImmutableExpression,
29 NormalPattern, Postfix, PostfixKind, RangeMode, SingleLocationExpression,
30 SingleLocationExpressionKind, SingleMutLocationExpression, TypeWithMut, WhenBinding,
31};
32use swamp_script_source_map::SourceMap;
33use swamp_script_types::prelude::*;
34use tracing::error;
35use tracing::info;
36
37#[must_use]
38pub fn convert_range_mode(range_mode: &swamp_script_ast::RangeMode) -> RangeMode {
39 match range_mode {
40 swamp_script_ast::RangeMode::Inclusive => RangeMode::Inclusive,
41 swamp_script_ast::RangeMode::Exclusive => RangeMode::Exclusive,
42 }
43}
44
45#[derive(Copy, Clone, Eq, PartialEq, Debug)]
46pub enum LocationSide {
47 Lhs,
48 Rhs,
49}
50
51#[derive(Debug)]
52pub struct AutoUseModules {
53 pub modules: Vec<SymbolTableRef>,
54}
55
56#[derive(Debug)]
57pub struct Program {
58 pub state: ProgramState,
59 pub modules: Modules,
60 pub auto_use_modules: AutoUseModules,
61}
62
63impl Default for Program {
64 fn default() -> Self {
65 Self::new()
66 }
67}
68
69impl Program {
70 #[must_use]
71 pub fn new() -> Self {
72 Self {
73 state: ProgramState::new(),
74 modules: Modules::new(),
75 auto_use_modules: AutoUseModules {
76 modules: Vec::new(),
77 },
78 }
79 }
80}
81
82#[must_use]
83pub const fn convert_span(without: &swamp_script_ast::SpanWithoutFileId, file_id: FileId) -> Span {
84 Span {
85 file_id,
86 offset: without.offset,
87 length: without.length,
88 }
89}
90
91pub const SPARSE_TYPE_ID: TypeNumber = 999;
92pub const SPARSE_ID_TYPE_ID: TypeNumber = 998;
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq)]
95pub enum TypeContextScope {
96 InsideFunction, InsideLoop, InsideBothFunctionAndLoop,
101 ArgumentOrOutsideFunction, }
103
104impl TypeContextScope {
105 #[must_use]
107 pub fn allows_return(&self) -> bool {
108 matches!(self, Self::InsideFunction | Self::InsideBothFunctionAndLoop)
109 }
110
111 #[must_use]
113 pub fn allows_break(&self) -> bool {
114 matches!(self, Self::InsideLoop | Self::InsideBothFunctionAndLoop)
115 }
116
117 #[must_use]
119 pub fn allows_continue(&self) -> bool {
120 self.allows_break() }
122
123 #[must_use]
125 pub fn enter_function(&self) -> Self {
126 match self {
127 Self::ArgumentOrOutsideFunction => Self::InsideFunction,
128 Self::InsideLoop => Self::InsideBothFunctionAndLoop,
129 _ => *self,
130 }
131 }
132
133 #[must_use]
135 pub fn enter_loop(&self) -> Self {
136 match self {
137 Self::ArgumentOrOutsideFunction => Self::InsideLoop,
138 Self::InsideFunction => Self::InsideBothFunctionAndLoop,
139 _ => *self,
140 }
141 }
142}
143
144#[derive(Debug, Clone)]
146pub struct TypeContext<'a> {
147 pub expected_type: Option<&'a Type>,
149
150 pub return_type: Option<&'a Type>,
152
153 pub scope: TypeContextScope,
154
155 pub is_in_compare_like: bool,
156}
157
158impl TypeContext<'_> {
159 pub(crate) fn allows_continue(&self) -> bool {
160 self.scope.allows_continue() && self.is_in_compare_like
161 }
162}
163
164impl TypeContext<'_> {
165 pub(crate) fn allows_return(&self) -> bool {
166 self.scope.allows_return() && self.is_in_compare_like
167 }
168}
169
170impl TypeContext<'_> {
171 pub(crate) fn allows_break(&self) -> bool {
172 self.scope.allows_break()
173 }
174}
175
176impl<'a> TypeContext<'a> {
177 #[must_use]
178 pub const fn new(
179 expected_type: Option<&'a Type>,
180 return_type: Option<&'a Type>,
181 scope: TypeContextScope,
182 ) -> Self {
183 Self {
184 expected_type,
185 return_type,
186 scope,
187 is_in_compare_like: false,
188 }
189 }
190
191 #[must_use]
192 pub const fn new_argument(required_type: &'a Type) -> Self {
193 Self {
194 expected_type: Some(required_type),
195 return_type: None,
196 scope: TypeContextScope::ArgumentOrOutsideFunction,
197 is_in_compare_like: false,
198 }
199 }
200
201 #[must_use]
202 pub const fn new_unsure_argument(expected_type: Option<&'a Type>) -> Self {
203 Self {
204 expected_type,
205 return_type: None,
206 scope: TypeContextScope::ArgumentOrOutsideFunction,
207 is_in_compare_like: false,
208 }
209 }
210
211 #[must_use]
212 pub const fn new_anything_argument() -> Self {
213 Self {
214 expected_type: None,
215 return_type: None,
216 scope: TypeContextScope::ArgumentOrOutsideFunction,
217 is_in_compare_like: false,
218 }
219 }
220
221 #[must_use]
222 pub const fn new_function(required_type: &'a Type) -> Self {
223 Self {
224 expected_type: Some(required_type),
225 return_type: Some(required_type),
226 scope: TypeContextScope::InsideFunction,
227 is_in_compare_like: false,
228 }
229 }
230
231 #[must_use]
232 pub const fn with_expected_type(&self, expected_type: Option<&'a Type>) -> Self {
233 Self {
234 expected_type,
235 return_type: self.return_type,
236 scope: self.scope,
237 is_in_compare_like: self.is_in_compare_like,
238 }
239 }
240
241 pub(crate) const fn we_know_expected_type(&self, found_type: &'a Type) -> Self {
242 self.with_expected_type(Some(found_type))
243 }
244
245 #[must_use]
248 pub const fn for_return(&self) -> Self {
249 Self {
250 expected_type: Some(self.return_type.unwrap()),
251 return_type: Some(self.return_type.unwrap()),
252 scope: TypeContextScope::ArgumentOrOutsideFunction,
253 is_in_compare_like: false,
254 }
255 }
256
257 #[must_use]
258 pub fn enter_function(&self, required_type: &'a Type) -> Self {
259 Self {
260 expected_type: Some(required_type),
261 return_type: Some(required_type),
262 scope: self.scope.enter_function(),
263 is_in_compare_like: false,
264 }
265 }
266
267 #[must_use]
269 pub fn enter_loop(&self) -> Self {
270 Self {
271 expected_type: self.expected_type,
272 return_type: self.return_type,
273 scope: self.scope.enter_loop(),
274 is_in_compare_like: self.is_in_compare_like,
275 }
276 }
277
278 #[must_use]
280 pub fn enter_compare(&self) -> Self {
281 Self {
282 expected_type: self.expected_type,
283 return_type: self.return_type,
284 scope: self.scope.enter_loop(),
285 is_in_compare_like: true,
286 }
287 }
288}
289
290#[derive(Debug, Eq, PartialEq)]
291pub enum BlockScopeMode {
292 Open,
293 Closed,
294}
295
296#[derive(Debug)]
297pub struct BlockScope {
298 mode: BlockScopeMode,
299 variables: SeqMap<String, VariableRef>,
300}
301
302impl Default for BlockScope {
303 fn default() -> Self {
304 Self::new()
305 }
306}
307
308impl BlockScope {
309 #[must_use]
310 pub fn new() -> Self {
311 Self {
312 mode: BlockScopeMode::Open,
313 variables: SeqMap::new(),
314 }
315 }
316}
317
318pub struct SharedState<'a> {
319 pub state: &'a mut ProgramState,
320 pub lookup_table: SymbolTable,
321 pub definition_table: SymbolTable,
322 pub modules: &'a Modules,
323 pub source_map: &'a SourceMap,
324 pub file_id: FileId,
325}
326
327impl<'a> SharedState<'a> {
328 #[must_use]
329 pub fn get_symbol_table(&'a self, path: &[String]) -> Option<&'a SymbolTable> {
330 if path.is_empty() {
331 return Some(&self.lookup_table);
332 }
333 self.get_module(path)
334 .map_or(None, |module| Some(&module.namespace.symbol_table))
335 }
336
337 #[must_use]
338 pub fn get_module(&'a self, path: &[String]) -> Option<&'a ModuleRef> {
339 let resolved_path = {
340 self.lookup_table.get_package_version(&path[0]).map_or_else(
341 || path.to_vec(),
342 |found_version| {
343 let mut new_path = path.to_vec();
344 let complete_name = format!("{}-{found_version}", path[0]);
345 info!(path=?path[0], found_version, complete_name, "switched out version");
346 new_path[0] = complete_name;
347 new_path
348 },
349 )
350 };
351
352 if path.len() == 1 {
353 if let Some(module_ref) = self.lookup_table.get_module_link(&path[0]) {
354 return Some(module_ref);
355 }
356 }
357
358 if let Some(x) = self.modules.get(&resolved_path) {
359 return Some(x);
360 }
361
362 None
363 }
364}
365
366pub struct FunctionScopeState {
367 pub block_scope_stack: Vec<BlockScope>,
368 pub return_type: Type,
369}
370
371impl FunctionScopeState {
372 #[must_use]
373 pub fn new(return_type: Type) -> Self {
374 Self {
375 block_scope_stack: vec![BlockScope::new()],
376 return_type,
377 }
378 }
379}
380
381pub struct Analyzer<'a> {
382 pub shared: SharedState<'a>,
383 scope: FunctionScopeState,
384 global: FunctionScopeState,
385}
386
387impl<'a> Analyzer<'a> {
388 pub fn new(
389 state: &'a mut ProgramState,
390 modules: &'a Modules,
391 source_map: &'a SourceMap,
392 file_id: FileId,
393 ) -> Self {
394 let shared = SharedState {
395 state,
396 lookup_table: SymbolTable::default(),
397 definition_table: SymbolTable::default(),
398 modules,
399 source_map,
400 file_id,
401 };
402 Self {
403 scope: FunctionScopeState::new(Type::Unit),
404 global: FunctionScopeState::new(Type::Unit),
405 shared,
406 }
407 }
408
409 fn start_function(&mut self, return_type: Type) {
410 self.global.block_scope_stack = take(&mut self.scope.block_scope_stack);
411 self.scope = FunctionScopeState::new(return_type);
412 }
413
414 fn stop_function(&mut self) {
415 self.scope.block_scope_stack = take(&mut self.global.block_scope_stack);
416 }
417
418 fn analyze_if_expression(
419 &mut self,
420 condition: &swamp_script_ast::Expression,
421 true_expression: &swamp_script_ast::Expression,
422 maybe_false_expression: Option<&swamp_script_ast::Expression>,
423 context: &TypeContext,
424 ) -> Result<Expression, Error> {
425 let resolved_condition = self.analyze_bool_argument_expression(condition)?;
426
427 let branch_context = context.enter_compare();
428
429 let true_expr = self.analyze_expression(true_expression, &branch_context)?;
430 let resolved_true = Box::new(true_expr);
431
432 let mut detected = context.expected_type.cloned();
433 if detected.is_none() && !matches!(resolved_true.ty, Type::Never) {
434 detected = Some(resolved_true.ty.clone());
435 }
436
437 let else_statements = if let Some(false_expression) = maybe_false_expression {
439 let else_context = branch_context.with_expected_type(detected.as_ref());
440 let else_expr = self.analyze_expression(false_expression, &else_context)?;
441 if detected.is_none() && !matches!(else_expr.ty, Type::Never) {
442 detected = Some(else_expr.ty.clone());
443 }
444
445 Some(Box::new(else_expr))
446 } else {
447 None
448 };
449
450 Ok(self.create_expr(
451 ExpressionKind::If(resolved_condition, resolved_true, else_statements),
452 detected.unwrap(),
453 &condition.node,
454 ))
455 }
456
457 fn get_text(&self, ast_node: &swamp_script_ast::Node) -> &str {
458 let span = Span {
459 file_id: self.shared.file_id,
460 offset: ast_node.span.offset,
461 length: ast_node.span.length,
462 };
463 self.shared.source_map.get_span_source(
464 self.shared.file_id,
465 span.offset as usize,
466 span.length as usize,
467 )
468 }
469
470 fn get_text_resolved(&self, resolved_node: &Node) -> &str {
471 let span = Span {
472 file_id: self.shared.file_id,
473 offset: resolved_node.span.offset,
474 length: resolved_node.span.length,
475 };
476 self.shared.source_map.get_span_source(
477 self.shared.file_id,
478 span.offset as usize,
479 span.length as usize,
480 )
481 }
482
483 fn get_path(&self, ident: &swamp_script_ast::QualifiedTypeIdentifier) -> (Vec<String>, String) {
484 let path = ident
485 .module_path
486 .as_ref()
487 .map_or_else(Vec::new, |found_path| {
488 let mut v = Vec::new();
489 for p in &found_path.0 {
490 v.push(self.get_text(p).to_string());
491 }
492 v
493 });
494 (path, self.get_text(&ident.name.0).to_string())
495 }
496
497 fn analyze_return_type(
498 &mut self,
499 function: &swamp_script_ast::Function,
500 ) -> Result<Type, Error> {
501 let ast_return_type = match function {
502 swamp_script_ast::Function::Internal(x) => &x.declaration.return_type,
503 swamp_script_ast::Function::External(x) => &x.return_type,
504 };
505
506 let resolved_return_type = match ast_return_type {
507 None => Type::Unit,
508 Some(x) => self.analyze_type(x)?,
509 };
510
511 Ok(resolved_return_type)
512 }
513
514 fn analyze_function_body_expression(
515 &mut self,
516 expression: &swamp_script_ast::Expression,
517 return_type: &Type,
518 ) -> Result<Expression, Error> {
519 let context = TypeContext::new_function(return_type);
520 let resolved_statement = self.analyze_expression(expression, &context)?;
521
522 Ok(resolved_statement)
523 }
524
525 fn analyze_maybe_type(
526 &mut self,
527 maybe_type: Option<&swamp_script_ast::Type>,
528 ) -> Result<Type, Error> {
529 let found_type = match maybe_type {
530 None => Type::Unit,
531 Some(ast_type) => self.analyze_type(ast_type)?,
532 };
533 Ok(found_type)
534 }
535
536 fn analyze_for_pattern(
537 &mut self,
538 pattern: &swamp_script_ast::ForPattern,
539 key_type: Option<&Type>,
540 value_type: &Type,
541 ) -> Result<ForPattern, Error> {
542 match pattern {
543 swamp_script_ast::ForPattern::Single(var) => {
544 let variable_ref = self.create_local_variable(
545 &var.identifier,
546 Option::from(&var.is_mut),
547 value_type,
548 )?;
549 Ok(ForPattern::Single(variable_ref))
550 }
551 swamp_script_ast::ForPattern::Pair(first, second) => {
552 let found_key = key_type.unwrap();
553 let first_var_ref = self.create_local_variable(
554 &first.identifier,
555 Option::from(&first.is_mut),
556 found_key,
557 )?;
558 let second_var_ref = self.create_local_variable(
559 &second.identifier,
560 Option::from(&second.is_mut),
561 value_type,
562 )?;
563 Ok(ForPattern::Pair(first_var_ref, second_var_ref))
564 }
565 }
566 }
567
568 fn analyze_parameters(
569 &mut self,
570 parameters: &Vec<swamp_script_ast::Parameter>,
571 ) -> Result<Vec<TypeForParameter>, Error> {
572 let mut resolved_parameters = Vec::new();
573 for parameter in parameters {
574 let param_type = self.analyze_type(¶meter.param_type)?;
575 resolved_parameters.push(TypeForParameter {
576 name: self.get_text(¶meter.variable.name).to_string(),
577 resolved_type: param_type,
578 is_mutable: parameter.variable.is_mutable.is_some(),
579 node: Some(ParameterNode {
580 is_mutable: self.to_node_option(Option::from(¶meter.variable.is_mutable)),
581 name: self.to_node(¶meter.variable.name),
582 }),
583 });
584 }
585 Ok(resolved_parameters)
586 }
587
588 pub fn analyze_immutable_argument(
591 &mut self,
592 ast_expression: &swamp_script_ast::Expression,
593 expected_type: &Type,
594 ) -> Result<Expression, Error> {
595 let context = TypeContext::new_argument(expected_type);
596 self.analyze_expression(ast_expression, &context)
597 }
598
599 pub fn analyze_start_chain_expression_get_mutability(
602 &mut self,
603 ast_expression: &swamp_script_ast::Expression,
604 expected_type: Option<&Type>,
605 ) -> Result<(Expression, bool), Error> {
606 let any_parameter_context = TypeContext::new_unsure_argument(expected_type);
607 let resolved = self.analyze_expression(ast_expression, &any_parameter_context)?;
608 let mutability = match resolved.kind {
609 ExpressionKind::VariableAccess(ref resolved_variable) => resolved_variable.is_mutable(),
610 _ => false,
611 };
612
613 Ok((resolved, mutability))
614 }
615
616 #[allow(clippy::too_many_lines)]
619 pub fn analyze_expression(
620 &mut self,
621 ast_expression: &swamp_script_ast::Expression,
622 context: &TypeContext,
623 ) -> Result<Expression, Error> {
624 let expr = self.analyze_expression_internal(ast_expression, context)?;
625
626 let encountered_type = expr.ty.clone();
627
628 if let Some(found_expected_type) = context.expected_type {
629 if found_expected_type.compatible_with(&encountered_type) {
630 return Ok(expr);
631 }
632
633 let result = self.coerce_expression(
634 expr,
635 found_expected_type,
636 &encountered_type,
637 &ast_expression.node,
638 )?;
639
640 return Ok(result);
641 }
642
643 Ok(expr)
644 }
645
646 #[allow(clippy::too_many_lines)]
649 pub fn analyze_expression_internal(
650 &mut self,
651 ast_expression: &swamp_script_ast::Expression,
652 context: &TypeContext,
653 ) -> Result<Expression, Error> {
654 let expression = match &ast_expression.kind {
655 swamp_script_ast::ExpressionKind::Break => {
656 self.analyze_break(context, &ast_expression.node)?
657 }
658 swamp_script_ast::ExpressionKind::Return(optional_expression) => self.analyze_return(
659 context,
660 optional_expression.as_deref(),
661 &ast_expression.node,
662 )?,
663
664 swamp_script_ast::ExpressionKind::Continue => {
665 self.analyze_continue(context, &ast_expression.node)?
666 }
667
668 swamp_script_ast::ExpressionKind::PostfixChain(postfix_chain) => {
670 self.analyze_postfix_chain(postfix_chain)?
671 }
672
673 swamp_script_ast::ExpressionKind::VariableDefinition(
674 variable,
675 maybe_annotation,
676 source_expression,
677 ) => self.analyze_create_variable(
678 variable,
679 Option::from(maybe_annotation),
680 source_expression,
681 )?,
682
683 swamp_script_ast::ExpressionKind::VariableAssignment(variable, source_expression) => {
684 self.analyze_variable_assignment(variable, source_expression)?
685 }
686 swamp_script_ast::ExpressionKind::DestructuringAssignment(variables, expression) => {
687 self.analyze_destructuring(&ast_expression.node, variables, expression)?
688 }
689
690 swamp_script_ast::ExpressionKind::StaticFunctionReference(qualified_identifier) => {
691 self.analyze_static_function_access(qualified_identifier)?
692 }
693 swamp_script_ast::ExpressionKind::IdentifierReference(variable) => {
694 self.analyze_identifier_reference(&variable.name)?
695 }
696
697 swamp_script_ast::ExpressionKind::StaticMemberFunctionReference(
698 type_identifier,
699 member_name,
700 ) => self.analyze_static_member_access(type_identifier, member_name)?,
701
702 swamp_script_ast::ExpressionKind::ConstantReference(constant_identifier) => {
703 self.analyze_constant_access(constant_identifier)?
704 }
705
706 swamp_script_ast::ExpressionKind::Assignment(location, source) => {
707 self.analyze_assignment(location, source)?
708 }
709 swamp_script_ast::ExpressionKind::CompoundAssignment(target, op, source) => {
710 self.analyze_assignment_compound(target, op, source)?
711 }
712
713 swamp_script_ast::ExpressionKind::BinaryOp(resolved_a, operator, resolved_b) => {
715 let (resolved_op, result_type) =
716 self.analyze_binary_op(resolved_a, operator, resolved_b)?;
717
718 self.create_expr(
719 ExpressionKind::BinaryOp(resolved_op),
720 result_type,
721 &ast_expression.node,
722 )
723 }
724 swamp_script_ast::ExpressionKind::UnaryOp(operator, expression) => {
725 let (resolved_op, result_type) = self.analyze_unary_op(operator, expression)?;
726 self.create_expr(
727 ExpressionKind::UnaryOp(resolved_op),
728 result_type,
729 &ast_expression.node,
730 )
731 }
732
733 swamp_script_ast::ExpressionKind::Block(expressions) => {
734 let (block, resulting_type) =
735 self.analyze_block(&ast_expression.node, context, expressions)?;
736 self.create_expr(
737 ExpressionKind::Block(block),
738 resulting_type,
739 &ast_expression.node,
740 )
741 }
742
743 swamp_script_ast::ExpressionKind::With(variable_bindings, expression) => {
744 self.analyze_with_expr(context, variable_bindings, expression)?
745 }
746
747 swamp_script_ast::ExpressionKind::When(variable_bindings, true_expr, else_expr) => {
748 self.analyze_when_expr(context, variable_bindings, true_expr, else_expr.as_deref())?
749 }
750
751 swamp_script_ast::ExpressionKind::InterpolatedString(string_parts) => {
752 let kind = ExpressionKind::InterpolatedString(
753 self.analyze_interpolated_string(string_parts)?,
754 );
755
756 self.create_expr(kind, Type::String, &ast_expression.node)
757 }
758
759 swamp_script_ast::ExpressionKind::NamedStructLiteral(
761 struct_identifier,
762 fields,
763 has_rest,
764 ) => self.analyze_struct_instantiation(struct_identifier, fields, *has_rest)?,
765
766 swamp_script_ast::ExpressionKind::AnonymousStructLiteral(
767 fields,
768 rest_was_specified,
769 ) => self.analyze_anonymous_struct_literal(
770 &ast_expression.node,
771 fields,
772 *rest_was_specified,
773 context,
774 )?,
775
776 swamp_script_ast::ExpressionKind::Range(min_value, max_value, range_mode) => {
777 let range = self.analyze_range(min_value, max_value, range_mode)?;
778 self.create_expr(
779 ExpressionKind::Range(Box::from(range.min), Box::from(range.max), range.mode),
780 Type::Iterable(Box::from(Type::Int)),
781 &ast_expression.node,
782 )
783 }
784
785 swamp_script_ast::ExpressionKind::Literal(literal) => {
786 let (literal, resolved_type) =
787 self.analyze_literal(&ast_expression.node, literal, context)?;
788 self.create_expr(
789 ExpressionKind::Literal(literal),
790 resolved_type,
791 &ast_expression.node,
792 )
793 }
794
795 swamp_script_ast::ExpressionKind::ForLoop(pattern, iterable_expression, statements) => {
796 let resolved_iterator =
797 self.analyze_iterable(pattern.any_mut(), &iterable_expression.expression)?;
798
799 self.push_block_scope("for_loop");
800 let pattern = self.analyze_for_pattern(
801 pattern,
802 resolved_iterator.key_type.as_ref(),
803 &resolved_iterator.value_type,
804 )?;
805 let resolved_statements =
806 self.analyze_expression(statements, &context.enter_loop())?;
807 self.pop_block_scope("for_loop");
808 let resolved_type = resolved_statements.ty.clone();
809 self.create_expr(
810 ExpressionKind::ForLoop(
811 pattern,
812 resolved_iterator,
813 Box::from(resolved_statements),
814 ),
815 resolved_type,
816 &ast_expression.node,
817 )
818 }
819 swamp_script_ast::ExpressionKind::WhileLoop(expression, statements) => {
820 let condition = self.analyze_bool_argument_expression(expression)?;
821 let resolved_statements =
823 self.analyze_expression(statements, &context.enter_loop())?;
824 let resolved_type = resolved_statements.ty.clone();
825 self.create_expr(
828 ExpressionKind::WhileLoop(condition, Box::from(resolved_statements)),
829 resolved_type,
830 &ast_expression.node,
831 )
832 }
833
834 swamp_script_ast::ExpressionKind::If(
835 expression,
836 true_expression,
837 maybe_false_expression,
838 ) => self.analyze_if_expression(
839 expression,
840 true_expression,
841 maybe_false_expression.as_deref(),
842 context,
843 )?,
844
845 swamp_script_ast::ExpressionKind::Match(expression, arms) => {
846 let (match_expr, return_type) = self.analyze_match(expression, context, arms)?;
847 self.create_expr(
848 ExpressionKind::Match(match_expr),
849 return_type,
850 &ast_expression.node,
851 )
852 }
853 swamp_script_ast::ExpressionKind::Guard(guard_expressions) => {
854 self.analyze_guard(&ast_expression.node, context, guard_expressions)?
855 }
856 };
857
858 Ok(expression)
861 }
862
863 fn get_struct_type(
864 &mut self,
865 qualified_type_identifier: &swamp_script_ast::QualifiedTypeIdentifier,
866 ) -> Result<NamedStructTypeRef, Error> {
867 let maybe_struct_type = self.analyze_named_type(qualified_type_identifier)?;
868 match maybe_struct_type {
869 Type::NamedStruct(struct_type) => Ok(struct_type),
870 _ => Err(self.create_err(
871 ErrorKind::UnknownStructTypeReference,
873 &qualified_type_identifier.name.0,
874 )),
875 }
876 }
877
878 #[must_use]
880 pub fn check_built_in_type(s: &str) -> Option<Type> {
881 let found = match s {
882 "Int" => Type::Int,
883 "Float" => Type::Float,
884 "Bool" => Type::Bool,
885 "String" => Type::String,
886 _ => return None,
887 };
888 Some(found)
889 }
890
891 pub(crate) fn analyze_named_type(
892 &mut self,
893 type_name_to_find: &swamp_script_ast::QualifiedTypeIdentifier,
894 ) -> Result<Type, Error> {
895 let (path, name) = self.get_path(type_name_to_find);
896 if let Some(ty) = Self::check_built_in_type(&name) {
898 return Ok(ty);
899 }
900
901 let symbol = {
902 let maybe_symbol_table = self.shared.get_symbol_table(&path);
903 let symbol_table = maybe_symbol_table.ok_or_else(|| {
904 self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)
905 })?;
906 symbol_table
907 .get_symbol(&name)
908 .ok_or_else(|| {
909 self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)
910 })?
911 .clone()
912 };
913
914 let result_type = match symbol {
926 Symbol::Type(base_type) => base_type,
927 Symbol::Alias(alias_type) => alias_type.referenced_type.clone(),
928 _ => return Err(self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)),
929 };
930
931 Ok(result_type)
932 }
933
934 fn create_default_value_for_type(
935 &mut self,
936 node: &swamp_script_ast::Node,
937 field_type: &Type,
938 ) -> Result<Expression, Error> {
939 let kind = match field_type {
940 Type::Bool => ExpressionKind::Literal(Literal::BoolLiteral(false)),
941 Type::Int => ExpressionKind::Literal(Literal::IntLiteral(0)),
942 Type::Float => ExpressionKind::Literal(Literal::FloatLiteral(Fp::zero())),
943 Type::String => ExpressionKind::Literal(Literal::StringLiteral(String::new())),
944 Type::Vec(array_type_ref) => {
945 ExpressionKind::Literal(Literal::Vec(*array_type_ref.clone(), vec![]))
946 }
947 Type::Tuple(tuple_type_ref) => {
948 let mut expressions = Vec::new();
949 for resolved_type in tuple_type_ref {
950 let expr = self.create_default_value_for_type(node, resolved_type)?;
951 expressions.push(expr);
952 }
953 ExpressionKind::Literal(Literal::TupleLiteral(tuple_type_ref.clone(), expressions))
954 }
955 Type::Map(key, value) => {
956 ExpressionKind::Literal(Literal::Map(*key.clone(), *value.clone(), vec![]))
957 }
958 Type::Optional(_optional_type) => ExpressionKind::Literal(Literal::NoneLiteral),
959
960 Type::NamedStruct(struct_ref) => {
961 self.create_default_static_call(node, &Type::NamedStruct(struct_ref.clone()))?
962 }
963 _ => {
964 return Err(
965 self.create_err(ErrorKind::NoDefaultImplemented(field_type.clone()), node)
966 );
967 }
968 };
969
970 let expr = self.create_expr(kind, field_type.clone(), node);
971 Ok(expr)
972 }
973
974 fn create_default_static_call(
975 &mut self,
976 node: &swamp_script_ast::Node,
977 ty: &Type,
978 ) -> Result<ExpressionKind, Error> {
979 self.lookup_associated_function(ty, "default").map_or_else(
980 || Err(self.create_err(ErrorKind::NoDefaultImplementedForType(ty.clone()), node)),
981 |function| {
982 let kind = match &*function {
983 Function::Internal(internal_function) => {
984 ExpressionKind::InternalFunctionAccess(internal_function.clone())
985 }
986 Function::External(external_function) => {
987 ExpressionKind::ExternalFunctionAccess(external_function.clone())
988 }
989 };
990
991 let base_expr =
992 self.create_expr(kind, Type::Function(function.signature().clone()), node);
993
994 let empty_call_postfix = Postfix {
995 node: self.to_node(node),
996 ty: *function.signature().return_type.clone(),
997 kind: PostfixKind::FunctionCall(vec![]),
998 };
999
1000 let kind =
1001 ExpressionKind::PostfixChain(Box::new(base_expr), vec![empty_call_postfix]);
1002
1003 Ok(kind)
1004 },
1005 )
1006 }
1007
1008 fn add_postfix(
1009 &mut self,
1010 vec: &mut Vec<Postfix>,
1011 kind: PostfixKind,
1012 ty: Type,
1013 node: &swamp_script_ast::Node,
1014 ) {
1015 let resolved_node = self.to_node(node);
1016 let postfix = Postfix {
1017 node: resolved_node,
1018 ty,
1019 kind,
1020 };
1021
1022 vec.push(postfix);
1023 }
1024
1025 pub fn analyze_struct_field(
1030 &mut self,
1031 field_name: &swamp_script_ast::Node,
1032 tv: Type,
1033 ) -> Result<(AnonymousStructType, usize, Type), Error> {
1034 let field_name_str = self.get_text(field_name).to_string();
1035
1036 let anon_struct_ref = match &tv {
1037 Type::NamedStruct(struct_type) => struct_type.borrow().anon_struct_type.clone(),
1038 Type::AnonymousStruct(anon_struct) => anon_struct.clone(),
1039 _ => return Err(self.create_err(ErrorKind::UnknownStructField, field_name)),
1040 };
1041
1042 if let Some(found_field) = anon_struct_ref
1043 .field_name_sorted_fields
1044 .get(&field_name_str)
1045 {
1046 let index = anon_struct_ref
1047 .field_name_sorted_fields
1048 .get_index(&field_name_str)
1049 .expect("checked earlier");
1050
1051 return Ok((
1052 anon_struct_ref.clone(),
1053 index,
1054 found_field.field_type.clone(),
1055 ));
1056 }
1057
1058 Err(self.create_err(ErrorKind::UnknownStructField, field_name))
1059 }
1060
1061 #[allow(clippy::too_many_lines)]
1062 fn analyze_postfix_chain(
1063 &mut self,
1064 chain: &swamp_script_ast::PostfixChain,
1065 ) -> Result<Expression, Error> {
1066 if let swamp_script_ast::ExpressionKind::StaticMemberFunctionReference(
1067 qualified_type_reference,
1068 member_name,
1069 ) = &chain.base.kind
1070 {
1071 if let Some(found_expr) =
1072 self.check_for_internal_static_call(qualified_type_reference, member_name, &[])?
1073 {
1074 return Ok(found_expr);
1075 }
1076 }
1077
1078 let (start, is_mutable) =
1079 self.analyze_start_chain_expression_get_mutability(&chain.base, None)?;
1080
1081 let mut tv = TypeWithMut {
1082 resolved_type: start.ty.clone(),
1083 is_mutable,
1084 };
1085
1086 let mut uncertain = false;
1087
1088 let mut suffixes = Vec::new();
1089
1090 for item in &chain.postfixes {
1091 match item {
1092 swamp_script_ast::Postfix::FieldAccess(field_name) => {
1093 let (struct_type_ref, index, return_type) =
1094 self.analyze_struct_field(&field_name.clone(), tv.resolved_type)?;
1095 self.add_postfix(
1096 &mut suffixes,
1097 PostfixKind::StructField(struct_type_ref.clone(), index),
1098 return_type.clone(),
1099 field_name,
1100 );
1101
1102 tv.resolved_type = return_type.clone();
1103 }
1105 swamp_script_ast::Postfix::MemberCall(member_name, ast_arguments) => {
1106 let dereference = ast_arguments
1107 .iter()
1108 .map(|x| &x.expression)
1109 .collect::<Vec<_>>();
1110 if let Some(found_internal) = self.check_for_internal_member_call(
1111 &tv.resolved_type,
1112 tv.is_mutable,
1113 member_name,
1114 &dereference,
1115 )? {
1116 tv.resolved_type = found_internal.ty.clone();
1117 tv.is_mutable = false;
1118 suffixes.push(found_internal);
1119 } else {
1120 let member_name_str = self.get_text(member_name).to_string();
1121
1122 if let Some(_found_member) = self
1123 .shared
1124 .state
1125 .associated_impls
1126 .get_member_function(&tv.resolved_type, &member_name_str)
1127 {
1128 let return_type = self.analyze_postfix_member_call(
1129 &tv.resolved_type,
1130 tv.is_mutable,
1131 member_name,
1132 ast_arguments,
1133 &mut suffixes,
1134 )?;
1135
1136 tv.resolved_type = return_type.clone();
1138 tv.is_mutable = false;
1139 } else {
1140 return Err(
1141 self.create_err(ErrorKind::UnknownMemberFunction, member_name)
1142 );
1143 }
1144 }
1145 }
1146 swamp_script_ast::Postfix::FunctionCall(node, arguments) => {
1147 if let Type::Function(signature) = &tv.resolved_type {
1148 let resolved_node = self.to_node(node);
1149 let resolved_arguments = self.analyze_and_verify_parameters(
1150 &resolved_node,
1151 &signature.parameters,
1152 arguments,
1153 )?;
1154 self.add_postfix(
1155 &mut suffixes,
1156 PostfixKind::FunctionCall(resolved_arguments),
1157 *signature.return_type.clone(),
1158 node,
1159 );
1160
1161 tv.resolved_type = *signature.return_type.clone();
1162 tv.is_mutable = false;
1163 } else {
1164 panic!("{}", &format!("what is this type {:?} ", tv.resolved_type))
1165 }
1166 }
1167
1168 swamp_script_ast::Postfix::Subscript(index_expr) => {
1169 let collection_type = tv.resolved_type.clone();
1170 match &collection_type {
1171 Type::String => {
1172 if let swamp_script_ast::ExpressionKind::Range(min, max, mode) =
1173 &index_expr.kind
1174 {
1175 let range = self.analyze_range(min, max, mode)?;
1176
1177 self.add_postfix(
1178 &mut suffixes,
1179 PostfixKind::StringRangeIndex(range),
1180 collection_type.clone(),
1181 &index_expr.node,
1182 );
1183
1184 tv.resolved_type = Type::String;
1185 } else {
1186 let int_argument_context = TypeContext::new_argument(&Type::Int);
1187 let resolved_index_expr =
1188 self.analyze_expression(index_expr, &int_argument_context)?;
1189 self.add_postfix(
1190 &mut suffixes,
1191 PostfixKind::StringIndex(resolved_index_expr),
1192 Type::String,
1193 &index_expr.node,
1194 );
1195 }
1196 tv.resolved_type = Type::String;
1197 }
1199
1200 Type::Vec(array_type_ref) => {
1201 if let swamp_script_ast::ExpressionKind::Range(
1202 min_expr,
1203 max_expr,
1204 mode,
1205 ) = &index_expr.kind
1206 {
1207 let range = self.analyze_range(min_expr, max_expr, mode)?;
1208
1209 self.add_postfix(
1210 &mut suffixes,
1211 PostfixKind::ArrayRangeIndex(*array_type_ref.clone(), range),
1212 collection_type.clone(),
1213 &index_expr.node,
1214 );
1215
1216 tv.resolved_type = collection_type.clone();
1217 } else {
1218 let int_argument_context = TypeContext::new_argument(&Type::Int);
1219 let resolved_index_expr =
1220 self.analyze_expression(index_expr, &int_argument_context)?;
1221 self.add_postfix(
1222 &mut suffixes,
1223 PostfixKind::ArrayIndex(
1224 *array_type_ref.clone(),
1225 resolved_index_expr,
1226 ),
1227 *array_type_ref.clone(),
1228 &index_expr.node,
1229 );
1230
1231 tv.resolved_type = *array_type_ref.clone();
1232 }
1233
1234 }
1236
1237 Type::Map(key_type, value_type) => {
1238 let key_type_context = TypeContext::new_argument(key_type);
1239 let resolved_key_expr =
1240 self.analyze_expression(index_expr, &key_type_context)?;
1241 let return_type = Type::Optional(value_type.clone());
1242 self.add_postfix(
1243 &mut suffixes,
1244 PostfixKind::MapIndex(
1245 *key_type.clone(),
1246 *value_type.clone(),
1247 resolved_key_expr,
1248 ),
1249 return_type.clone(),
1250 &index_expr.node,
1251 );
1252
1253 tv.resolved_type = return_type;
1254 }
1256
1257 Type::Generic(base, generic_type_parameters) => match &**base {
1258 Type::External(found_rust_type) => {
1259 if found_rust_type.number == SPARSE_TYPE_ID {
1260 let sparse_id = self
1261 .shared
1262 .lookup_table
1263 .get_external_type("SparseId")
1264 .expect("SparseId is missing");
1265 let binding = Type::External(sparse_id.clone());
1266 let sparse_id_context = TypeContext::new_argument(&binding);
1267 let contained_type = &generic_type_parameters[0];
1268 let resolved_key =
1269 self.analyze_expression(index_expr, &sparse_id_context)?;
1270
1271 let return_type =
1272 Type::Optional(Box::new(contained_type.clone()));
1273
1274 self.add_postfix(
1275 &mut suffixes,
1276 PostfixKind::ExternalTypeIndexRef(
1277 found_rust_type.clone(),
1278 resolved_key,
1279 ),
1280 return_type.clone(),
1281 &index_expr.node,
1282 );
1283
1284 tv.resolved_type = return_type;
1285 } else {
1287 panic!("unknown generic type lookup")
1288 }
1289 }
1290 _ => panic!("not supported"),
1291 },
1292 _ => {
1293 return Err(self.create_err(
1294 ErrorKind::ExpectedArray(collection_type),
1295 &index_expr.node,
1296 ));
1297 }
1298 }
1299 }
1300
1301 swamp_script_ast::Postfix::NoneCoalesce(default_expr) => {
1302 let unwrapped_type = if let Type::Optional(unwrapped_type) = &tv.resolved_type {
1303 unwrapped_type
1304 } else if uncertain {
1305 &tv.resolved_type
1306 } else {
1307 return Err(
1308 self.create_err(ErrorKind::CanNotNoneCoalesce, &default_expr.node)
1309 );
1310 };
1311
1312 let unwrapped_type_context = TypeContext::new_argument(unwrapped_type);
1313 let resolved_default_expr =
1314 self.analyze_expression(default_expr, &unwrapped_type_context)?;
1315 self.add_postfix(
1316 &mut suffixes,
1317 PostfixKind::NoneCoalesce(resolved_default_expr),
1318 unwrapped_type.clone(),
1319 &default_expr.node,
1320 );
1321 tv.resolved_type = unwrapped_type.clone();
1322 uncertain = false; }
1324
1325 swamp_script_ast::Postfix::OptionUnwrap(option_node) => {
1326 if let Type::Optional(unwrapped_type) = &tv.resolved_type {
1327 uncertain = true;
1328 self.add_postfix(
1329 &mut suffixes,
1330 PostfixKind::OptionUnwrap,
1331 *unwrapped_type.clone(),
1332 option_node,
1333 );
1334 tv.resolved_type = *unwrapped_type.clone();
1335 } else {
1336 return Err(self.create_err(ErrorKind::ExpectedOptional, option_node));
1337 }
1338 }
1339 }
1340 }
1341
1342 if uncertain {
1343 if let Type::Optional(_) = tv.resolved_type {
1344 } else {
1345 tv.resolved_type = Type::Optional(Box::from(tv.resolved_type.clone()));
1346 }
1347 }
1348
1349 Ok(self.create_expr(
1350 ExpressionKind::PostfixChain(Box::new(start), suffixes),
1351 tv.resolved_type,
1352 &chain.base.node,
1353 ))
1354 }
1355
1356 fn analyze_bool_argument_expression(
1357 &mut self,
1358 expression: &swamp_script_ast::Expression,
1359 ) -> Result<BooleanExpression, Error> {
1360 let bool_context = TypeContext::new_argument(&Type::Bool);
1361 let resolved_expression = self.analyze_expression(expression, &bool_context)?;
1362 let expr_type = resolved_expression.ty.clone();
1363
1364 let bool_expression = match expr_type {
1365 Type::Bool => resolved_expression,
1366 Type::Optional(_) => self.create_expr(
1367 ExpressionKind::CoerceOptionToBool(Box::new(resolved_expression)),
1368 Type::Bool,
1369 &expression.node,
1370 ),
1371 _ => {
1372 return Err(self.create_err(ErrorKind::ExpectedBooleanExpression, &expression.node));
1373 }
1374 };
1375
1376 Ok(BooleanExpression {
1377 expression: Box::from(bool_expression),
1378 })
1379 }
1380
1381 fn analyze_iterable(
1382 &mut self,
1383 force_mut: Option<swamp_script_ast::Node>,
1384 expression: &swamp_script_ast::MutableOrImmutableExpression,
1385 ) -> Result<Iterable, Error> {
1386 let any_context = TypeContext::new_anything_argument();
1387 let resolved_expression: MutOrImmutableExpression = if force_mut.is_some() {
1388 let resolved_node = self.to_node(&force_mut.unwrap());
1389 MutOrImmutableExpression {
1390 expression_or_location: ArgumentExpressionOrLocation::Location(
1391 self.analyze_to_location(
1392 &expression.expression,
1393 &any_context,
1394 LocationSide::Rhs,
1395 )?,
1396 ),
1397 is_mutable: Some(resolved_node),
1398 }
1399 } else {
1400 self.analyze_mut_or_immutable_expression(expression, &any_context, LocationSide::Rhs)?
1401 };
1402
1403 let resolved_type = &resolved_expression.ty().clone();
1404 let (key_type, value_type): (Option<Type>, Type) = match resolved_type {
1405 Type::Vec(array_type) => (Some(Type::Int), *array_type.clone()),
1406 Type::Map(key, value) => (Some(*key.clone()), *value.clone()),
1407 Type::String => (Some(Type::Int), Type::String),
1408 Type::Iterable(item_type) => (None, *item_type.clone()),
1409 Type::Generic(_base_type, params) => {
1410 let rust_type_ref_for_id = self
1414 .shared
1415 .lookup_table
1416 .get_external_type("SparseId")
1417 .expect("SparseId was missing");
1418 let rust_id_type = Type::External(rust_type_ref_for_id.clone());
1419 (Some(rust_id_type), params[0].clone())
1420 }
1421 _ => return Err(self.create_err(ErrorKind::NotAnIterator, &expression.expression.node)),
1422 };
1423
1424 Ok(Iterable {
1425 key_type,
1426 value_type,
1427 resolved_expression: Box::new(resolved_expression),
1428 })
1429 }
1430
1431 fn analyze_argument_expressions(
1432 &mut self,
1433 expected_type: Option<&Type>,
1434 ast_expressions: &[swamp_script_ast::Expression],
1435 ) -> Result<Vec<Expression>, Error> {
1436 let mut resolved_expressions = Vec::new();
1437 let argument_expressions_context = TypeContext::new_unsure_argument(expected_type);
1438 for expression in ast_expressions {
1439 resolved_expressions
1440 .push(self.analyze_expression(expression, &argument_expressions_context)?);
1441 }
1442 Ok(resolved_expressions)
1443 }
1444
1445 fn analyze_block(
1446 &mut self,
1447 _node: &swamp_script_ast::Node,
1448 context: &TypeContext,
1449 ast_expressions: &[swamp_script_ast::Expression],
1450 ) -> Result<(Vec<Expression>, Type), Error> {
1451 if ast_expressions.is_empty() {
1452 return Ok((vec![], Type::Unit));
1453 }
1454
1455 self.push_block_scope("block");
1456
1457 let mut resolved_expressions = Vec::with_capacity(ast_expressions.len());
1458
1459 for expression in &ast_expressions[..ast_expressions.len() - 1] {
1460 let stmt_context = context.with_expected_type(Some(&Type::Unit));
1461 let expr = self.analyze_expression(expression, &stmt_context)?;
1462
1463 if matches!(expr.ty, Type::Never) {
1464 resolved_expressions.push(expr);
1465 return Ok((resolved_expressions, Type::Never));
1466 }
1467
1468 resolved_expressions.push(expr);
1469 }
1470
1471 let last_expr =
1473 self.analyze_expression(&ast_expressions[ast_expressions.len() - 1], context)?;
1474 let last_type = last_expr.ty.clone();
1475 resolved_expressions.push(last_expr);
1476
1477 self.pop_block_scope("block");
1478
1479 Ok((resolved_expressions, last_type))
1480 }
1481
1482 fn analyze_interpolated_string(
1483 &mut self,
1484 string_parts: &[swamp_script_ast::StringPart],
1485 ) -> Result<Vec<StringPart>, Error> {
1486 let mut resolved_parts = Vec::new();
1487 for part in string_parts {
1488 let resolved_string_part = match part {
1489 swamp_script_ast::StringPart::Literal(string_node, processed_string) => {
1490 StringPart::Literal(self.to_node(string_node), processed_string.to_string())
1491 }
1492 swamp_script_ast::StringPart::Interpolation(expression, format_specifier) => {
1493 let any_context = TypeContext::new_anything_argument();
1494 let expr = self.analyze_expression(expression, &any_context)?;
1495 let resolved_format_specifier =
1496 self.analyze_format_specifier(Option::from(format_specifier));
1497 StringPart::Interpolation(expr, resolved_format_specifier)
1498 }
1499 };
1500
1501 resolved_parts.push(resolved_string_part);
1502 }
1503
1504 Ok(resolved_parts)
1505 }
1506
1507 pub(crate) fn analyze_static_function_access(
1508 &self,
1509 qualified_func_name: &swamp_script_ast::QualifiedIdentifier,
1510 ) -> Result<Expression, Error> {
1511 let path = self.get_module_path(qualified_func_name.module_path.as_ref());
1512 let function_name = self.get_text(&qualified_func_name.name);
1513
1514 if let Some(found_table) = self.shared.get_symbol_table(&path) {
1515 if let Some(found_func) = found_table.get_function(function_name) {
1516 let (kind, signature) = match found_func {
1517 FuncDef::Internal(internal_fn) => (
1518 ExpressionKind::InternalFunctionAccess(internal_fn.clone()),
1519 &internal_fn.signature,
1520 ),
1521 FuncDef::External(external_fn) => (
1522 ExpressionKind::ExternalFunctionAccess(external_fn.clone()),
1523 &external_fn.signature,
1524 ),
1525 FuncDef::Intrinsic(_) => {
1527 return Err(
1528 self.create_err(ErrorKind::UnknownFunction, &qualified_func_name.name)
1529 );
1530 }
1531 };
1532
1533 return Ok(self.create_expr(
1534 kind,
1535 Type::Function(signature.clone()),
1536 &qualified_func_name.name,
1537 ));
1538 }
1539 }
1540 Err(self.create_err(ErrorKind::UnknownFunction, &qualified_func_name.name))
1541 }
1542
1543 fn analyze_identifier_reference(
1545 &self,
1546 var_node: &swamp_script_ast::Node,
1547 ) -> Result<Expression, Error> {
1548 let text = self.get_text(var_node);
1549
1550 if let Some(found_variable) = self.try_find_variable(var_node) {
1553 return Ok(self.create_expr(
1554 ExpressionKind::VariableAccess(found_variable.clone()),
1555 found_variable.resolved_type.clone(),
1556 var_node,
1557 ));
1558 }
1559
1560 if let Some(found_symbol) = self.shared.lookup_table.get_symbol(text) {
1561 let expr = match found_symbol {
1562 Symbol::FunctionDefinition(func) => match func {
1563 FuncDef::External(found_external_function) => self.create_expr(
1564 ExpressionKind::ExternalFunctionAccess(found_external_function.clone()),
1565 Type::Function(found_external_function.signature.clone()),
1566 var_node,
1567 ),
1568 FuncDef::Internal(found_internal_function) => self.create_expr(
1569 ExpressionKind::InternalFunctionAccess(found_internal_function.clone()),
1570 Type::Function(found_internal_function.signature.clone()),
1571 var_node,
1572 ),
1573 FuncDef::Intrinsic(_) => todo!(),
1574 },
1575
1576 _ => {
1577 return Err(self.create_err(ErrorKind::UnknownIdentifier, var_node));
1578 }
1579 };
1580 return Ok(expr);
1581 }
1582
1583 Err(self.create_err(ErrorKind::UnknownIdentifier, var_node))
1584 }
1585 fn analyze_usize_index(
1586 &mut self,
1587 usize_expression: &swamp_script_ast::Expression,
1588 ) -> Result<Expression, Error> {
1589 let int_context = TypeContext::new_argument(&Type::Int);
1590 let lookup_expression = self.analyze_expression(usize_expression, &int_context)?;
1591 let lookup_resolution = lookup_expression.ty.clone();
1592
1593 match &lookup_resolution {
1594 Type::Int => {}
1595 _ => Err(self.create_err(
1596 ErrorKind::ArrayIndexMustBeInt(lookup_resolution),
1597 &usize_expression.node,
1598 ))?,
1599 }
1600
1601 Ok(lookup_expression)
1602 }
1603
1604 fn analyze_slice_type_helper(
1605 &mut self,
1606 node: &swamp_script_ast::Node,
1607 items: &[swamp_script_ast::Expression],
1608 expected_type: Option<&Type>,
1609 ) -> Result<(Type, Vec<Expression>), Error> {
1610 let expressions = self.analyze_argument_expressions(None, items)?;
1611 let element_type = if expressions.is_empty() {
1612 if let Some(found_expected_type) = expected_type {
1613 info!(?found_expected_type, "found array type");
1614 if let Type::Vec(found) = found_expected_type {
1615 found.clone()
1616 } else {
1617 return Err(self.create_err(ErrorKind::NotAnArray, node));
1618 }
1619 } else {
1620 return Err(self.create_err(ErrorKind::NotAnArray, node));
1621 }
1622 } else {
1623 Box::from(expressions[0].ty.clone())
1624 };
1625
1626 Ok((*element_type, 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::Vec(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.clone(),
2252 &lookup_expr.node,
2253 );
2254 ty = *array_type.clone();
2255 }
2256
2257 Type::Map(key_type, value_type) => {
2258 let key_type_argument_context = TypeContext::new_argument(key_type);
2259 let key_expr =
2260 self.analyze_expression(lookup_expr, &key_type_argument_context)?;
2261 let is_last = i == chain.postfixes.len() - 1;
2262 let allow_auto_insert = is_last && location_side == LocationSide::Lhs;
2263 let (kind, lookup_type) = if allow_auto_insert {
2264 (
2267 LocationAccessKind::MapIndexInsertIfNonExisting(
2268 *key_type.clone(),
2269 *value_type.clone(),
2270 key_expr,
2271 ),
2272 *value_type.clone(),
2273 )
2274 } else {
2275 let optional_value_type =
2276 Type::Optional(Box::from(value_type.clone()));
2277 (
2278 LocationAccessKind::MapIndex(
2279 *key_type.clone(),
2280 *value_type.clone(),
2281 key_expr,
2282 ),
2283 optional_value_type,
2284 )
2285 };
2286
2287 self.add_location_item(
2288 &mut items,
2289 kind,
2290 lookup_type.clone(),
2291 &lookup_expr.node,
2292 );
2293 ty = lookup_type;
2294 }
2295
2296 Type::Generic(collection_type, generic_params) => {
2297 if let Type::External(rust_type) = &**collection_type {
2298 let val_type = generic_params[0].clone();
2299 if rust_type.number == SPARSE_TYPE_ID {
2300 let sparse_id_type = self
2301 .shared
2302 .lookup_table
2303 .get_external_type("SparseId")
2304 .expect("should have SparseId");
2305
2306 let key_type = Type::External(sparse_id_type.clone());
2307 let key_type_context = TypeContext::new_argument(&key_type);
2308
2309 let key_expr =
2310 self.analyze_expression(lookup_expr, &key_type_context)?;
2311
2312 self.add_location_item(
2313 &mut items,
2314 LocationAccessKind::ExternalTypeIndex(
2315 rust_type.clone(),
2316 key_expr,
2317 ),
2318 key_type.clone(),
2319 &lookup_expr.node,
2320 );
2321
2322 ty = Type::Optional(Box::from(val_type.clone()));
2323 }
2324 }
2325 }
2326
2327 _ => {
2328 return Err(
2329 self.create_err(ErrorKind::IllegalIndexInChain, &lookup_expr.node)
2330 );
2331 }
2332 }
2333 }
2334
2335 swamp_script_ast::Postfix::MemberCall(node, _) => {
2336 return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
2337 }
2338
2339 swamp_script_ast::Postfix::FunctionCall(node, _) => {
2340 return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
2341 }
2342 swamp_script_ast::Postfix::OptionUnwrap(node) => {
2343 return Err(self.create_err(ErrorKind::UnwrapCanNotBePartOfChain, node));
2344 }
2345 swamp_script_ast::Postfix::NoneCoalesce(expr) => {
2346 return Err(
2347 self.create_err(ErrorKind::NoneCoalesceCanNotBePartOfChain, &expr.node)
2348 );
2349 }
2350 }
2351 }
2352
2353 if let Some(found_expected_type) = context.expected_type {
2354 if !ty.compatible_with(found_expected_type) {
2355 return Err(self.create_err(
2356 ErrorKind::IncompatibleTypes(ty, found_expected_type.clone()),
2357 &chain.base.node,
2358 ));
2359 }
2360 }
2361
2362 let location = SingleLocationExpression {
2363 kind: SingleLocationExpressionKind::MutVariableRef,
2364 node: self.to_node(&chain.base.node),
2365 ty,
2366 starting_variable: start_variable,
2367 access_chain: items,
2368 };
2369 Ok(location)
2370 }
2371
2372 fn analyze_to_location(
2373 &mut self,
2374 expr: &swamp_script_ast::Expression,
2375 context: &TypeContext,
2376 location_type: LocationSide,
2377 ) -> Result<SingleLocationExpression, Error> {
2378 match &expr.kind {
2379 swamp_script_ast::ExpressionKind::PostfixChain(chain) => {
2380 self.analyze_chain_to_location(chain, context, location_type)
2381 }
2382 swamp_script_ast::ExpressionKind::IdentifierReference(variable) => {
2383 let var = self.find_variable(variable)?;
2384 if var.is_mutable() {
2385 Ok(SingleLocationExpression {
2386 kind: SingleLocationExpressionKind::MutVariableRef,
2387 node: self.to_node(&variable.name),
2388 ty: var.resolved_type.clone(),
2389 starting_variable: var,
2390 access_chain: vec![],
2391 })
2392 } else {
2393 Err(self.create_err(ErrorKind::VariableIsNotMutable, &expr.node))
2394 }
2395 }
2396 _ => Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, &expr.node)),
2397 }
2398 }
2399
2400 #[allow(clippy::single_match)]
2401 fn check_special_assignment_compound(
2402 &mut self,
2403 target_expression: &swamp_script_ast::Expression,
2404 target_type: &Type,
2405 op: &CompoundOperatorKind,
2406 source: &swamp_script_ast::Expression,
2407 source_type: &Type,
2408 ) -> Result<Option<ExpressionKind>, Error> {
2409 match &target_type {
2410 Type::Vec(array_type) => {
2411 let target_type_context = TypeContext::new_argument(target_type);
2412 let source_type_context = TypeContext::new_argument(source_type);
2413 if *op == CompoundOperatorKind::Add && source_type.compatible_with(array_type) {
2414 let target_location = SingleMutLocationExpression(self.analyze_to_location(
2416 target_expression,
2417 &target_type_context,
2418 LocationSide::Rhs,
2419 )?);
2420 let resolved_source = self.analyze_expression(source, &source_type_context)?;
2421 return Ok(Option::from(ExpressionKind::IntrinsicCallMut(
2422 IntrinsicFunction::VecSelfPush,
2423 target_location,
2424 vec![resolved_source],
2425 )));
2426 } else if *op == CompoundOperatorKind::Add
2427 && source_type.compatible_with(target_type)
2428 {
2429 let target_location = SingleMutLocationExpression(self.analyze_to_location(
2431 target_expression,
2432 &target_type_context,
2433 LocationSide::Rhs,
2434 )?);
2435 let resolved_source = self.analyze_expression(source, &source_type_context)?;
2436 return Ok(Option::from(ExpressionKind::IntrinsicCallMut(
2437 IntrinsicFunction::VecSelfExtend,
2438 target_location,
2439 vec![resolved_source],
2440 )));
2441 }
2442 }
2443 _ => {}
2444 }
2445
2446 Ok(None)
2447 }
2448
2449 fn analyze_assignment_compound(
2450 &mut self,
2451 target_expression: &swamp_script_ast::Expression,
2452 ast_op: &swamp_script_ast::CompoundOperator,
2453 ast_source_expression: &swamp_script_ast::Expression,
2454 ) -> Result<Expression, Error> {
2455 let resolved_op = self.analyze_compound_operator(ast_op);
2456 let any_argument_context = TypeContext::new_anything_argument();
2457 let source_expr = self.analyze_expression(ast_source_expression, &any_argument_context)?;
2458 let source_expr_type_context = TypeContext::new_argument(&source_expr.ty);
2459
2460 let resolved_location = SingleMutLocationExpression(self.analyze_to_location(
2461 target_expression,
2462 &source_expr_type_context,
2463 LocationSide::Rhs,
2464 )?);
2465
2466 let kind = if let Some(found_special) = self.check_special_assignment_compound(
2467 target_expression,
2468 &resolved_location.0.ty,
2469 &resolved_op.kind,
2470 ast_source_expression,
2471 &source_expr.ty,
2472 )? {
2473 found_special
2474 } else {
2475 ExpressionKind::CompoundAssignment(
2476 resolved_location,
2477 resolved_op.kind,
2478 Box::from(source_expr),
2479 )
2480 };
2481
2482 let expr = self.create_expr(kind, Type::Unit, &target_expression.node);
2483
2484 Ok(expr)
2485 }
2486
2487 fn analyze_assignment(
2488 &mut self,
2489 target_location: &swamp_script_ast::Expression,
2490 ast_source_expression: &swamp_script_ast::Expression,
2491 ) -> Result<Expression, Error> {
2492 let any_argument_context = TypeContext::new_anything_argument();
2493 let resolved_location =
2494 self.analyze_to_location(target_location, &any_argument_context, LocationSide::Lhs)?;
2495
2496 let ty = resolved_location.ty.clone();
2497 if ty == Type::Unit {
2498 error!(?ast_source_expression, "unit problem");
2499 }
2500
2501 let lhs_argument_context = TypeContext::new_argument(&ty);
2502 let source_expr = self.analyze_expression(ast_source_expression, &lhs_argument_context)?;
2503
2504 let mut_location = SingleMutLocationExpression(resolved_location);
2505
2506 let kind = ExpressionKind::Assignment(Box::from(mut_location), Box::from(source_expr));
2507
2508 let expr = self.create_expr(kind, Type::Unit, &target_location.node); Ok(expr)
2511 }
2512
2513 #[must_use]
2514 pub fn create_mut_single_location_expr(
2515 &self,
2516 kind: SingleLocationExpressionKind,
2517 ty: Type,
2518 ast_node: &swamp_script_ast::Node,
2519 ) -> SingleMutLocationExpression {
2520 SingleMutLocationExpression(SingleLocationExpression {
2521 kind,
2522 ty,
2523 starting_variable: Rc::new(Variable {
2524 name: Node::default(),
2525 resolved_type: Type::Int,
2526 mutable_node: None,
2527 scope_index: 0,
2528 variable_index: 0,
2529 }),
2530 node: self.to_node(ast_node),
2531 access_chain: vec![],
2532 })
2533 }
2534
2535 #[must_use]
2536 pub fn create_single_location_expr(
2537 &self,
2538 kind: SingleLocationExpressionKind,
2539 ty: Type,
2540 ast_node: &swamp_script_ast::Node,
2541 ) -> SingleLocationExpression {
2542 SingleLocationExpression {
2543 kind,
2544 ty,
2545 starting_variable: Rc::new(Variable {
2546 name: Node::default(),
2547 resolved_type: Type::Int,
2548 mutable_node: None,
2549 scope_index: 0,
2550 variable_index: 0,
2551 }),
2552 node: self.to_node(ast_node),
2553 access_chain: vec![],
2554 }
2555 }
2556
2557 #[must_use]
2558 pub fn create_single_location_expr_resolved(
2559 &self,
2560 kind: SingleLocationExpressionKind,
2561 ty: Type,
2562 node: &Node,
2563 ) -> SingleLocationExpression {
2564 SingleLocationExpression {
2565 kind,
2566 ty,
2567 starting_variable: Rc::new(Variable {
2568 name: Node::default(),
2569 resolved_type: Type::Int,
2570 mutable_node: None,
2571 scope_index: 0,
2572 variable_index: 0,
2573 }),
2574 node: node.clone(),
2575 access_chain: vec![],
2576 }
2577 }
2578 #[must_use]
2579 pub fn create_mut_single_location_expr_resolved(
2580 &self,
2581 kind: SingleLocationExpressionKind,
2582 ty: Type,
2583 node: &Node,
2584 ) -> SingleMutLocationExpression {
2585 SingleMutLocationExpression(SingleLocationExpression {
2586 kind,
2587 ty,
2588 starting_variable: Rc::new(Variable {
2589 name: Node::default(),
2590 resolved_type: Type::Int,
2591 mutable_node: None,
2592 scope_index: 0,
2593 variable_index: 0,
2594 }),
2595 node: node.clone(),
2596 access_chain: vec![],
2597 })
2598 }
2599
2600 #[must_use]
2601 pub const fn create_expr(
2602 &self,
2603 kind: ExpressionKind,
2604 ty: Type,
2605 ast_node: &swamp_script_ast::Node,
2606 ) -> Expression {
2607 Expression {
2609 kind,
2610 ty,
2611 node: self.to_node(ast_node),
2612 }
2613 }
2614
2615 #[must_use]
2616 pub fn create_expr_resolved(
2617 &self,
2618 kind: ExpressionKind,
2619 ty: Type,
2620 ast_node: &Node,
2621 ) -> Expression {
2622 Expression {
2623 kind,
2624 ty,
2625 node: ast_node.clone(),
2626 }
2627 }
2628
2629 fn analyze_destructuring(
2630 &mut self,
2631 node: &swamp_script_ast::Node,
2632 target_ast_variables: &[swamp_script_ast::Variable],
2633 tuple_expression: &swamp_script_ast::Expression,
2634 ) -> Result<Expression, Error> {
2635 let any_context = TypeContext::new_anything_argument();
2636 let tuple_resolved = self.analyze_expression(tuple_expression, &any_context)?;
2637 let tuple_expr_type = &tuple_resolved.ty;
2638
2639 let mut variable_refs = Vec::new();
2640 if let Type::Tuple(tuple) = tuple_expr_type.clone() {
2641 if target_ast_variables.len() > tuple.len() {
2642 return Err(self.create_err(ErrorKind::TooManyDestructureVariables, node));
2643 }
2644 for (variable_ref, tuple_type) in target_ast_variables.iter().zip(tuple.clone()) {
2645 let (variable_ref, _is_reassignment) =
2646 self.set_or_overwrite_variable_with_type(variable_ref, &tuple_type)?;
2647 variable_refs.push(variable_ref);
2648 }
2649 let expr_kind =
2650 ExpressionKind::TupleDestructuring(variable_refs, tuple, Box::from(tuple_resolved));
2651
2652 Ok(self.create_expr(expr_kind, Type::Unit, node))
2653 } else {
2654 Err(self.create_err(ErrorKind::CanNotDestructure, node))
2655 }
2656 }
2657
2658 fn analyze_postfix_member_func_call(
2659 &mut self,
2660 resolved_node: &Node,
2661 found_function: &FunctionRef,
2662 encountered_self_type: &Type,
2663 is_mutable: bool,
2664 arguments: &[swamp_script_ast::MutableOrImmutableExpression],
2665 ) -> Result<Postfix, Error> {
2666 let signature = found_function.signature();
2667
2668 let self_type = &signature.parameters[0];
2669 if !self_type
2670 .resolved_type
2671 .compatible_with(encountered_self_type)
2672 || self_type.is_mutable && !is_mutable
2673 {
2674 return Err(self.create_err_resolved(ErrorKind::SelfNotCorrectType, resolved_node));
2675 }
2676
2677 let resolved_arguments = self.analyze_and_verify_parameters(
2678 resolved_node,
2679 &signature.parameters[1..],
2680 arguments,
2681 )?;
2682
2683 let kind = PostfixKind::MemberCall(found_function.clone(), resolved_arguments);
2684 let postfix = Postfix {
2685 node: resolved_node.clone(),
2686 ty: *signature.return_type.clone(),
2687 kind,
2688 };
2689
2690 Ok(postfix)
2691 }
2692
2693 fn analyze_postfix_field_call(
2694 &mut self,
2695 resolved_node: &Node,
2696 struct_type: &NamedStructTypeRef,
2697 field: &StructTypeField,
2698 index: usize,
2699 signature: &Signature,
2700 arguments: &[swamp_script_ast::MutableOrImmutableExpression],
2701 ) -> Result<Vec<Postfix>, Error> {
2702 let mut suffixes = Vec::new();
2703 let struct_field_kind =
2705 PostfixKind::StructField(struct_type.borrow().anon_struct_type.clone(), index);
2706
2707 let struct_field_postfix = Postfix {
2708 node: resolved_node.clone(),
2709 ty: field.field_type.clone(),
2710 kind: struct_field_kind,
2711 };
2712
2713 suffixes.push(struct_field_postfix);
2714
2715 let resolved_arguments =
2716 self.analyze_and_verify_parameters(resolved_node, &signature.parameters, arguments)?;
2717
2718 let call_kind = PostfixKind::FunctionCall(resolved_arguments);
2719
2720 let call_postfix = Postfix {
2721 node: resolved_node.clone(),
2722 ty: *signature.return_type.clone(),
2723 kind: call_kind,
2724 };
2725 suffixes.push(call_postfix);
2726
2727 Ok(suffixes)
2728 }
2729
2730 fn analyze_postfix_member_call(
2731 &mut self,
2732 type_that_member_is_on: &Type,
2733 is_mutable: bool,
2734 member_name: &swamp_script_ast::Node,
2735 arguments: &[swamp_script_ast::MutableOrImmutableExpression],
2736 suffixes: &mut Vec<Postfix>,
2737 ) -> Result<Type, Error> {
2738 let field_name_str = self.get_text(member_name).to_string();
2739
2740 let resolved_node = self.to_node(member_name);
2741
2742 let maybe_function = self
2743 .shared
2744 .state
2745 .associated_impls
2746 .get_member_function(type_that_member_is_on, &field_name_str)
2747 .cloned();
2748
2749 let postfixes = match maybe_function {
2750 Some(found_function_member) => {
2751 let postfix = self.analyze_postfix_member_func_call(
2752 &resolved_node,
2753 &found_function_member,
2754 type_that_member_is_on,
2755 is_mutable,
2756 arguments,
2757 )?;
2758 vec![postfix]
2759 }
2760 _ => {
2761 return Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, member_name));
2762 } };
2802
2803 let last_type = postfixes.last().unwrap().ty.clone();
2804 suffixes.extend(postfixes);
2805
2806 Ok(last_type)
2807 }
2808
2809 fn analyze_break(
2825 &self,
2826 context: &TypeContext,
2827 node: &swamp_script_ast::Node,
2828 ) -> Result<Expression, Error> {
2829 if !context.allows_break() {
2830 return Err(self.create_err(ErrorKind::BreakOutsideLoop, node));
2831 }
2832
2833 Ok(Expression {
2834 kind: ExpressionKind::Break,
2835 ty: Type::Never,
2836 node: self.to_node(node),
2837 })
2838 }
2839
2840 fn analyze_return(
2841 &mut self,
2842 context: &TypeContext,
2843 optional_expression: Option<&swamp_script_ast::Expression>,
2844 node: &swamp_script_ast::Node,
2845 ) -> Result<Expression, Error> {
2846 if !context.allows_return() {
2847 return Err(self.create_err(ErrorKind::ReturnOutsideCompare, node));
2848 }
2849
2850 let return_context = context.for_return();
2851 let inner = if let Some(expr) = optional_expression {
2852 Some(Box::new(self.analyze_expression(expr, &return_context)?))
2853 } else {
2854 None
2856 };
2857
2858 Ok(self.create_expr(ExpressionKind::Return(inner), Type::Never, node))
2859 }
2860
2861 fn analyze_continue(
2862 &self,
2863 context: &TypeContext,
2864 node: &swamp_script_ast::Node,
2865 ) -> Result<Expression, Error> {
2866 if !context.allows_continue() {
2867 return Err(self.create_err(ErrorKind::ContinueOutsideLoop, node));
2868 }
2869 Ok(self.create_expr(ExpressionKind::Continue, Type::Never, node))
2870 }
2871
2872 fn coerce_expression(
2873 &self,
2874 expr: Expression,
2875 expected_type: &Type,
2876 encountered_type: &Type,
2877 node: &swamp_script_ast::Node,
2878 ) -> Result<Expression, Error> {
2879 if !matches!(encountered_type, Type::Optional(_)) {
2880 if let Type::Optional(expected_inner_type) = expected_type {
2882 if encountered_type.compatible_with(expected_inner_type) {
2883 let wrapped = self.create_expr(
2884 ExpressionKind::Option(Option::from(Box::new(expr))),
2885 expected_type.clone(),
2886 node,
2887 );
2888 return Ok(wrapped);
2889 }
2890 }
2891 } else if matches!(expected_type, &Type::Bool) {
2892 if let Type::Optional(_inner_type) = encountered_type {
2893 let wrapped = self.create_expr(
2894 ExpressionKind::CoerceOptionToBool(Box::from(expr)),
2895 Type::Bool,
2896 node,
2897 );
2898 return Ok(wrapped);
2899 }
2900 }
2901
2902 error!(?expr, "expr");
2903 error!(?expected_type, ?encountered_type, "incompatible types");
2904
2905 Err(self.create_err(
2906 ErrorKind::IncompatibleTypes(expected_type.clone(), encountered_type.clone()),
2907 node,
2908 ))
2909 }
2910}