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