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