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