1pub mod access;
6mod attributes;
7pub mod call;
8pub mod constant;
9pub mod context;
10pub mod def;
11pub mod literal;
12pub mod operator;
13pub mod pattern;
14pub mod prelude;
15pub mod shared;
16mod structure;
17mod to_string;
18pub mod types;
19pub mod variable;
20
21use crate::call::MaybeBorrowMutRefExpression;
22use crate::context::TypeContext;
23use crate::shared::SharedState;
24use crate::to_string::create_expr_resolved;
25use crate::types::TypeAnalyzeContext;
26use seq_map::SeqMap;
27use source_map_cache::SourceMap;
28use source_map_node::{FileId, Node, Span};
29use std::mem::take;
30use std::num::{ParseFloatError, ParseIntError};
31use std::rc::Rc;
32use std::str::{FromStr, ParseBoolError};
33use swamp_ast::{GenericParameter, QualifiedTypeIdentifier};
34use swamp_modules::prelude::*;
35use swamp_modules::symtbl::SymbolTableRef;
36use swamp_semantic::prelude::*;
37use swamp_semantic::{
38 ArgumentExpression, BinaryOperatorKind, BlockScope, BlockScopeMode, FunctionScopeState,
39 GridType, InternalMainExpression, LocationAccess, LocationAccessKind, MapType,
40 MutableReferenceKind, NormalPattern, Postfix, PostfixKind, ScopeInfo, SingleLocationExpression,
41 SliceViewType, SparseType, TargetAssignmentLocation, TypeWithMut, VariableType, VecType,
42 WhenBinding,
43};
44use swamp_semantic::{StartOfChain, StartOfChainKind};
45use swamp_types::prelude::*;
46use swamp_types::{Type, TypeKind};
47use tracing::error;
48#[derive(Copy, Clone, Eq, PartialEq)]
80pub enum AssignmentMode {
81 OwnedValue,
82 CopyBlittable,
83 CopySharedPtr,
84}
85
86#[derive(Copy, Clone, Eq, PartialEq, Debug)]
87pub enum LocationSide {
88 Lhs,
89 Mutable,
90 Rhs,
91}
92
93#[derive(Debug)]
94pub enum StartOfChainBase {
95 FunctionReference(Function),
96 Variable(VariableRef),
97}
98#[derive(Debug)]
99pub struct Program {
100 pub state: ProgramState,
101 pub modules: Modules,
102 pub default_symbol_table: SymbolTable,
103}
104
105impl Default for Program {
106 fn default() -> Self {
107 Self::new(ProgramState::new(), Modules::new(), SymbolTable::new(&[]))
108 }
109}
110
111impl Program {
112 #[must_use]
113 pub const fn new(
114 state: ProgramState,
115 modules: Modules,
116 default_symbol_table: SymbolTable,
117 ) -> Self {
118 Self {
119 state,
120 modules,
121 default_symbol_table,
122 }
123 }
124}
125
126#[must_use]
127pub const fn convert_span(without: &swamp_ast::SpanWithoutFileId, file_id: FileId) -> Span {
128 Span {
129 file_id,
130 offset: without.offset,
131 length: without.length,
132 }
133}
134
135pub struct Analyzer<'a> {
136 pub shared: SharedState<'a>,
137 scope: ScopeInfo,
138 global: FunctionScopeState,
139 module_path: Vec<String>,
140}
141
142impl<'a> Analyzer<'a> {
143 pub fn new(
144 state: &'a mut ProgramState,
145 modules: &'a Modules,
146 core_symbol_table: SymbolTableRef,
147 source_map: &'a SourceMap,
148 module_path: &[String],
149 file_id: FileId,
150 ) -> Self {
151 let shared = SharedState {
152 state,
153 lookup_table: SymbolTable::new(&[]),
154 definition_table: SymbolTable::new(module_path),
155 modules,
156 core_symbol_table,
157 source_map,
158 file_id,
159 };
160 Self {
161 scope: ScopeInfo::default(),
162 global: FunctionScopeState::new(),
163 shared,
164 module_path: module_path.to_vec(),
165 }
166 }
167
168 fn start_function(&mut self) {
170 self.global.block_scope_stack = take(&mut self.scope.active_scope.block_scope_stack);
171 self.scope = ScopeInfo::default();
172 }
173
174 fn stop_function(&mut self) {
175 self.scope.active_scope.block_scope_stack = take(&mut self.global.block_scope_stack);
176 }
177
178 fn analyze_if_expression(
179 &mut self,
180 condition: &swamp_ast::Expression,
181 true_expression: &swamp_ast::Expression,
182 maybe_false_expression: Option<&swamp_ast::Expression>,
183 context: &TypeContext,
184 ) -> Expression {
185 let resolved_condition = self.analyze_bool_argument_expression(condition);
186
187 let branch_context = context;
188
189 let true_expr = self.analyze_expression(true_expression, branch_context);
190 let resolved_true = Box::new(true_expr);
191
192 let mut detected = context.expected_type.cloned();
193 if detected.is_none() {
194 detected = Some(resolved_true.ty.clone());
195 }
196
197 let else_statements = if let Some(false_expression) = maybe_false_expression {
199 let else_context =
200 branch_context.with_expected_type(detected.as_ref(), context.has_lvalue_target);
201 let else_expr = self.analyze_expression(false_expression, &else_context);
202 if detected.is_none() {
203 detected = Some(else_expr.ty.clone());
204 }
205
206 Some(Box::new(else_expr))
207 } else {
208 None
209 };
210
211 self.create_expr(
212 ExpressionKind::If(resolved_condition, resolved_true, else_statements),
213 detected.unwrap(),
214 &condition.node,
215 )
216 }
217
218 fn get_text(&self, ast_node: &swamp_ast::Node) -> &str {
219 let span = Span {
220 file_id: self.shared.file_id,
221 offset: ast_node.span.offset,
222 length: ast_node.span.length,
223 };
224 self.shared.source_map.get_span_source(
225 self.shared.file_id,
226 span.offset as usize,
227 span.length as usize,
228 )
229 }
230
231 fn get_text_resolved(&self, resolved_node: &Node) -> &str {
232 let span = Span {
233 file_id: self.shared.file_id,
234 offset: resolved_node.span.offset,
235 length: resolved_node.span.length,
236 };
237 self.shared.source_map.get_span_source(
238 self.shared.file_id,
239 span.offset as usize,
240 span.length as usize,
241 )
242 }
243
244 fn get_path(&self, ident: &swamp_ast::QualifiedTypeIdentifier) -> (Vec<String>, String) {
245 let path = ident
246 .module_path
247 .as_ref()
248 .map_or_else(Vec::new, |found_path| {
249 let mut v = Vec::new();
250 for p in &found_path.0 {
251 v.push(self.get_text(p).to_string());
252 }
253 v
254 });
255 (path, self.get_text(&ident.name.0).to_string())
256 }
257
258 fn analyze_return_type(&mut self, function: &swamp_ast::Function) -> TypeRef {
259 let ast_return_type = match function {
260 swamp_ast::Function::Internal(x) => &x.declaration.return_type,
261 swamp_ast::Function::External(_, x) => &x.return_type,
262 };
263
264 match ast_return_type {
265 None => self.shared.state.types.unit(),
266 Some(x) => self.analyze_type(x, &TypeAnalyzeContext::default()),
267 }
268 }
269
270 fn analyze_function_body_expression(
271 &mut self,
272 expression: &swamp_ast::Expression,
273 return_type: &TypeRef,
274 ) -> Expression {
275 let context = TypeContext::new_function(return_type);
276
277 self.analyze_expression(expression, &context)
278 }
279
280 fn analyze_maybe_type(&mut self, maybe_type: Option<&swamp_ast::Type>) -> TypeRef {
281 match maybe_type {
282 None => self.shared.state.types.unit(),
283 Some(ast_type) => self.analyze_type(ast_type, &TypeAnalyzeContext::default()),
284 }
285 }
286
287 fn analyze_for_pattern(
288 &mut self,
289 pattern: &swamp_ast::ForPattern,
290 key_type: Option<&TypeRef>,
291 value_type: &TypeRef,
292 ) -> ForPattern {
293 match pattern {
294 swamp_ast::ForPattern::Single(var) => {
295 let variable_ref = self.create_local_variable(
296 &var.identifier,
297 Option::from(&var.is_mut),
298 value_type,
299 false,
300 );
301 ForPattern::Single(variable_ref)
302 }
303 swamp_ast::ForPattern::Pair(first, second) => {
304 let found_key = key_type.unwrap();
305 let first_var_ref = self.create_local_variable(
306 &first.identifier,
307 Option::from(&first.is_mut),
308 found_key,
309 false,
310 );
311 let second_var_ref = self.create_local_variable(
312 &second.identifier,
313 Option::from(&second.is_mut),
314 value_type,
315 false,
316 );
317 ForPattern::Pair(first_var_ref, second_var_ref)
318 }
319 }
320 }
321 const MAX_PARAMETER_COUNT: usize = 6; fn analyze_parameters(
323 &mut self,
324 parameters: &Vec<swamp_ast::Parameter>,
325 ) -> Vec<TypeForParameter> {
326 let mut resolved_parameters = Vec::new();
327 if parameters.len() > Self::MAX_PARAMETER_COUNT {
328 self.add_err(
329 ErrorKind::TooManyParameters {
330 encountered: parameters.len(),
331 allowed: Self::MAX_PARAMETER_COUNT,
332 },
333 ¶meters[0].variable.name,
334 );
335 return vec![];
336 }
337
338 let allow_ephemeral = TypeAnalyzeContext::new_ephemeral();
339 for parameter in parameters {
340 let param_type = self.analyze_type(¶meter.param_type, &allow_ephemeral);
341 if !param_type.allowed_as_parameter_type() {
342 self.add_err(
343 ErrorKind::ParameterTypeCanNotBeStorage(param_type),
344 ¶meter.variable.name,
345 );
346 continue;
347 }
348 resolved_parameters.push(TypeForParameter {
349 name: self.get_text(¶meter.variable.name).to_string(),
350 resolved_type: param_type,
351 is_mutable: parameter.variable.is_mutable.is_some(),
352 node: Some(ParameterNode {
353 is_mutable: self.to_node_option(Option::from(¶meter.variable.is_mutable)),
354 name: self.to_node(¶meter.variable.name),
355 }),
356 });
357 }
358 resolved_parameters
359 }
360
361 pub(crate) fn analyze_static_member_access(
362 &mut self,
363 named_type: &swamp_ast::QualifiedTypeIdentifier,
364 member_name_node: &swamp_ast::Node,
365 ) -> Option<Function> {
366 if let Some(found_function) = self.special_static_member(named_type, member_name_node) {
367 Some(found_function)
368 } else {
369 let some_type = self.analyze_named_type(named_type);
370
371 let member_name = self.get_text(member_name_node);
372 self.lookup_associated_function(&some_type, member_name)
373 }
374 }
375
376 pub fn analyze_local_function_access(
377 &mut self,
378 qualified_func_name: &swamp_ast::QualifiedIdentifier,
379 ) -> Option<Function> {
380 let path = self.get_module_path(qualified_func_name.module_path.as_ref());
381 let function_name = self.get_text(&qualified_func_name.name);
382
383 if let Some(found_table) = self.shared.get_symbol_table(&path)
384 && let Some(found_func) = found_table.get_function(function_name) {
385 let (kind, signature) = match found_func {
386 FuncDef::Internal(internal_fn) => (
387 Function::Internal(internal_fn.clone()),
388 &internal_fn.signature,
389 ),
390 FuncDef::External(external_fn) => (
391 Function::External(external_fn.clone()),
392 &external_fn.signature,
393 ),
394 FuncDef::Intrinsic(intrinsic_fn) => (
396 Function::Intrinsic(intrinsic_fn.clone()),
397 &intrinsic_fn.signature,
398 ),
399 };
400
401 return Some(kind);
402 }
403
404 None
405 }
406
407 fn check_if_function_reference(
408 &mut self,
409 ast_expression: &swamp_ast::Expression,
410 ) -> Option<Function> {
411 match &ast_expression.kind {
412 swamp_ast::ExpressionKind::StaticMemberFunctionReference(
413 qualified_type_identifier,
414 node,
415 ) => self.analyze_static_member_access(qualified_type_identifier, node),
416 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
417 self.analyze_local_function_access(qualified_identifier)
418 }
419 _ => None,
420 }
421 }
422
423 pub fn analyze_start_chain_expression_get_mutability(
426 &mut self,
427 ast_expression: &swamp_ast::Expression,
428 ) -> Option<StartOfChainBase> {
429 self.check_if_function_reference(ast_expression)
430 .map_or_else(
431 || {
432 if let swamp_ast::ExpressionKind::IdentifierReference(
433 found_qualified_identifier,
434 ) = &ast_expression.kind
435 {
436 self.try_find_variable(&found_qualified_identifier.name)
437 .map(StartOfChainBase::Variable)
438 } else {
439 None
440 }
441 },
442 |found_func_def| Some(StartOfChainBase::FunctionReference(found_func_def)),
443 )
444 }
445
446 pub fn debug_expression(&self, expr: &swamp_ast::Expression, description: &str) {
447 self.debug_line(expr.node.span.offset as usize, description);
448 }
449
450 pub fn debug_line(&self, offset: usize, description: &str) {
451 let (line, col) = self
452 .shared
453 .source_map
454 .get_span_location_utf8(self.shared.file_id, offset);
455
456 let source_line = self
457 .shared
458 .source_map
459 .get_source_line(self.shared.file_id, line);
460
461 let source_path = self
462 .shared
463 .source_map
464 .fetch_relative_filename(self.shared.file_id);
465 let debug_line = format!("{source_path}:{line}:{col}> {}", source_line.unwrap());
466 }
469
470 pub fn analyze_main_expression(
473 &mut self,
474 ast_expression: &swamp_ast::Expression,
475 ) -> InternalMainExpression {
476 self.start_function();
477
478 let context = TypeContext::new_anything_argument(true); let analyzed_expr = self.analyze_expression(ast_expression, &context);
480 let main_expr = InternalMainExpression {
481 expression: analyzed_expr,
482 scopes: self.scope.total_scopes.clone(),
483 program_unique_id: self.shared.state.allocate_internal_function_id(),
484 };
485
486 self.stop_function();
487
488 main_expr
489 }
490
491 fn analyze_maybe_ref_expression(
492 &mut self,
493 ast_expr: &swamp_ast::Expression,
494 ) -> MaybeBorrowMutRefExpression {
495 if let swamp_ast::ExpressionKind::UnaryOp(found_unary, ast_inner_expression) =
496 &ast_expr.kind
497 && let swamp_ast::UnaryOperator::BorrowMutRef(node) = found_unary {
498 let resolved_node = self.to_node(node);
500 return MaybeBorrowMutRefExpression {
501 ast_expression: *ast_inner_expression.clone(),
502 has_borrow_mutable_reference: Some(resolved_node),
503 };
504 }
505
506 MaybeBorrowMutRefExpression {
507 ast_expression: ast_expr.clone(),
508 has_borrow_mutable_reference: None,
509 }
510 }
511
512 fn needs_storage_error(
514 &self,
515 expr: &Expression,
516 is_function_call: bool,
517 context: &TypeContext,
518 ast_node: &swamp_ast::Node,
519 ) -> bool {
520 let is_constant = matches!(expr.kind, ExpressionKind::ConstantAccess(_));
521 let is_variable = matches!(expr.kind, ExpressionKind::VariableAccess(_));
522
523 !context.has_lvalue_target
525 && expr.ty.collection_view_that_needs_explicit_storage()
526 && is_function_call
527 && !is_constant
528 && !is_variable
529 }
530
531 pub fn analyze_expression(
532 &mut self,
533 ast_expression: &swamp_ast::Expression,
534 context: &TypeContext,
535 ) -> Expression {
536 let expr = self.analyze_expression_internal(ast_expression, context);
539
540 if matches!(expr.kind, ExpressionKind::Error(_)) {
541 return expr;
542 }
543
544 let encountered_type = expr.ty.clone();
545
546 let expr = if let Some(found_expected_type) = context.expected_type {
548 let reduced_expected = found_expected_type;
549
550 let reduced_encountered_type = encountered_type;
551
552 if self
553 .shared
554 .state
555 .types
556 .compatible_with(reduced_expected, &reduced_encountered_type)
557 {
558 expr
559 } else {
560 self.types_did_not_match_try_late_coerce_expression(
561 expr,
562 reduced_expected,
563 &reduced_encountered_type,
564 &ast_expression.node,
565 )
566 }
567 } else {
568 expr
569 };
572
573 let is_function_call = Self::is_aggregate_function_call(ast_expression);
576
577 if self.needs_storage_error(&expr, is_function_call, context, &ast_expression.node) {
578 self.create_err(ErrorKind::NeedStorage, &ast_expression.node)
580 } else {
581 expr
582 }
583 }
584
585 #[allow(clippy::too_many_lines)]
588 pub fn analyze_expression_internal(
589 &mut self,
590 ast_expression: &swamp_ast::Expression,
591 context: &TypeContext,
592 ) -> Expression {
593 match &ast_expression.kind {
596 swamp_ast::ExpressionKind::PostfixChain(postfix_chain) => {
598 self.analyze_postfix_chain(postfix_chain, context)
599 }
600
601 swamp_ast::ExpressionKind::VariableDefinition(
602 variable,
603 maybe_annotation,
604 source_expression,
605 ) => self.analyze_create_variable(
606 variable,
607 Option::from(maybe_annotation),
608 source_expression,
609 ),
610
611 swamp_ast::ExpressionKind::VariableAssignment(variable, source_expression) => {
612 self.analyze_variable_assignment(variable, source_expression)
613 }
614
615 swamp_ast::ExpressionKind::DestructuringAssignment(variables, expression) => {
616 self.analyze_destructuring(&ast_expression.node, variables, expression)
617 }
618
619 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
620 self.analyze_identifier(qualified_identifier)
621 }
622
623 swamp_ast::ExpressionKind::VariableReference(variable) => {
624 self.analyze_variable_reference(&variable.name)
625 }
626
627 swamp_ast::ExpressionKind::ContextAccess => {
628 todo!("context access is not done yet")
629 }
630
631 swamp_ast::ExpressionKind::StaticMemberFunctionReference(
632 type_identifier,
633 member_name,
634 ) => {
635 let debug_name = self.get_text(member_name);
636 let type_name = self.get_text(&type_identifier.name.0);
637 panic!("can not have separate member func ref {type_name:?} {debug_name}")
638 }
639
640 swamp_ast::ExpressionKind::ConstantReference(constant_identifier) => {
641 self.analyze_constant_access(constant_identifier)
642 }
643
644 swamp_ast::ExpressionKind::Assignment(location, source) => {
645 self.analyze_assignment(location, source)
646 }
647
648 swamp_ast::ExpressionKind::CompoundAssignment(target, op, source) => {
649 self.analyze_assignment_compound(target, op, source)
650 }
651
652 swamp_ast::ExpressionKind::BinaryOp(resolved_a, operator, resolved_b) => {
654 let Some((resolved_op, result_type)) =
655 self.analyze_binary_op(resolved_a, operator, resolved_b)
656 else {
657 return self.create_err(ErrorKind::OperatorProblem, &operator.node);
658 };
659
660 self.create_expr(
661 ExpressionKind::BinaryOp(resolved_op),
662 result_type,
663 &ast_expression.node,
664 )
665 }
666
667 swamp_ast::ExpressionKind::UnaryOp(operator, expression) => {
668 if let swamp_ast::UnaryOperator::BorrowMutRef(_node) = operator {
669 let inner_expr =
670 self.analyze_to_location(expression, context, LocationSide::Rhs);
671 let ty = inner_expr.ty.clone();
672 self.create_expr(
673 ExpressionKind::BorrowMutRef(Box::from(inner_expr)),
674 ty,
675 &ast_expression.node,
676 )
677 } else {
678 let Some((resolved_op, result_type)) =
679 self.analyze_unary_op(operator, expression)
680 else {
681 return self.create_err(ErrorKind::OperatorProblem, &ast_expression.node);
682 };
683 self.create_expr(
684 ExpressionKind::UnaryOp(resolved_op),
685 result_type,
686 &ast_expression.node,
687 )
688 }
689 }
690
691 swamp_ast::ExpressionKind::Block(expressions) => {
692 let (block, resulting_type) =
693 self.analyze_block(&ast_expression.node, context, expressions);
694 self.create_expr(
695 ExpressionKind::Block(block),
696 resulting_type,
697 &ast_expression.node,
698 )
699 }
700
701 swamp_ast::ExpressionKind::With(variable_bindings, expression) => {
702 self.analyze_with_expr(context, variable_bindings, expression)
703 }
704
705 swamp_ast::ExpressionKind::When(variable_bindings, true_expr, else_expr) => {
706 self.analyze_when_expr(context, variable_bindings, true_expr, else_expr.as_deref())
707 }
708
709 swamp_ast::ExpressionKind::InterpolatedString(string_parts) => {
710 self.analyze_interpolated_string_lowering(&ast_expression.node, string_parts)
711 }
712
713 swamp_ast::ExpressionKind::NamedStructLiteral(struct_identifier, fields, has_rest) => {
715 self.analyze_named_struct_literal(struct_identifier, fields, *has_rest, context)
716 }
717
718 swamp_ast::ExpressionKind::AnonymousStructLiteral(fields, rest_was_specified) => self
719 .analyze_anonymous_struct_literal(
720 &ast_expression.node,
721 fields,
722 *rest_was_specified,
723 context,
724 ),
725
726 swamp_ast::ExpressionKind::ContextAccess => {
727 todo!("lone dot not implemented yet")
728 }
729
730 swamp_ast::ExpressionKind::Range(min_value, max_value, range_mode) => {
731 self.analyze_range(min_value, max_value, range_mode, &ast_expression.node)
732 }
733
734 swamp_ast::ExpressionKind::ForLoop(pattern, iterable_expression, statements) => {
735 if pattern.is_key_variable_mut() {
736 return self.create_err(
737 ErrorKind::KeyVariableNotAllowedToBeMutable,
738 &ast_expression.node,
739 );
740 }
741 let resolved_iterator =
742 self.analyze_iterable(pattern.is_value_mut(), &iterable_expression.expression);
743
744 self.push_block_scope("for_loop");
745 let pattern = self.analyze_for_pattern(
746 pattern,
747 resolved_iterator.key_type.as_ref(),
748 &resolved_iterator.value_type,
749 );
750 let resolved_statements = self.analyze_expression(statements, context);
751 self.pop_block_scope("for_loop");
752 let resolved_type = resolved_statements.ty.clone();
753 self.create_expr(
754 ExpressionKind::ForLoop(
755 pattern,
756 resolved_iterator,
757 Box::from(resolved_statements),
758 ),
759 resolved_type,
760 &ast_expression.node,
761 )
762 }
763
764 swamp_ast::ExpressionKind::WhileLoop(expression, statements) => {
765 let condition = self.analyze_bool_argument_expression(expression);
766 let resolved_statements = self.analyze_expression(statements, context);
768 let resolved_type = resolved_statements.ty.clone();
769 self.create_expr(
772 ExpressionKind::WhileLoop(condition, Box::from(resolved_statements)),
773 resolved_type,
774 &ast_expression.node,
775 )
776 }
777
778 swamp_ast::ExpressionKind::If(expression, true_expression, maybe_false_expression) => {
779 self.analyze_if_expression(
780 expression,
781 true_expression,
782 maybe_false_expression.as_deref(),
783 context,
784 )
785 }
786
787 swamp_ast::ExpressionKind::Match(expression, arms) => {
788 let (match_expr, return_type) = self.analyze_match(expression, context, arms);
789 self.create_expr(
790 ExpressionKind::Match(match_expr),
791 return_type,
792 &ast_expression.node,
793 )
794 }
795 swamp_ast::ExpressionKind::Guard(guard_expressions) => {
796 self.analyze_guard(&ast_expression.node, context, guard_expressions)
797 }
798
799 swamp_ast::ExpressionKind::Lambda(variables, expression) => {
800 self.analyze_lambda(&ast_expression.node, variables, expression, context)
801 }
802 swamp_ast::ExpressionKind::Error => {
803 self.create_err(ErrorKind::UnexpectedType, &ast_expression.node)
804 }
805 swamp_ast::ExpressionKind::Literal(literal) => {
806 self.analyze_complex_literal_to_expression(ast_expression, literal, context)
807 } }
809 }
810
811 fn get_struct_type(
812 &mut self,
813 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
814 ) -> NamedStructType {
815 let maybe_struct_type = self.analyze_named_type(qualified_type_identifier);
816 if let TypeKind::NamedStruct(struct_type) = &*maybe_struct_type.kind {
817 struct_type.clone()
818 } else {
819 self.add_err(
820 ErrorKind::UnknownStructTypeReference,
822 &qualified_type_identifier.name.0,
823 );
824
825 NamedStructType {
826 name: Default::default(),
827 module_path: vec![],
828 assigned_name: String::new(),
829 anon_struct_type: self.types().unit(),
830 instantiated_type_parameters: vec![],
831 }
832 }
833 }
834
835 pub(crate) fn analyze_named_type(
836 &mut self,
837 type_name_to_find: &swamp_ast::QualifiedTypeIdentifier,
838 ) -> TypeRef {
839 let (path, name) = self.get_path(type_name_to_find);
840 let mut analyzed_type_parameters = Vec::new();
841
842 if let Some(found) =
843 self.analyze_special_named_type(&path, &name, &type_name_to_find.generic_params)
844 {
845 return found;
846 }
847
848 for analyzed_type in &type_name_to_find.generic_params {
849 let ty = self.analyze_type(analyzed_type.get_type(), &TypeAnalyzeContext::default());
850
851 analyzed_type_parameters.push(ty);
852 }
853
854 let symbol = {
855 if let Some(symbol_table) = self.shared.get_symbol_table(&path) {
856 if let Some(x) = symbol_table.get_symbol(&name) {
857 x
858 } else {
859 self.add_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0);
860 return self.types().unit();
861 }
862 } else {
863 self.add_err(ErrorKind::UnexpectedType, &type_name_to_find.name.0);
864 return self.types().unit();
865 }
866 };
867
868 if analyzed_type_parameters.is_empty() {
869 match &symbol {
870 Symbol::Type(base_type) => base_type.clone(),
871 Symbol::Alias(alias_type) => alias_type.ty.clone(),
872 _ => {
873 self.add_err(ErrorKind::UnexpectedType, &type_name_to_find.name.0);
874 self.types().unit()
875 }
876 }
877 } else {
878 panic!("unknown type")
879 }
880 }
881
882 fn create_default_value_for_type(
883 &mut self,
884 node: &swamp_ast::Node,
885 field_type: &TypeRef,
886 ) -> Option<Expression> {
887 let kind = match &*field_type.kind {
888 TypeKind::Tuple(tuple_type_ref) => {
889 let mut expressions = Vec::new();
890 for resolved_type in tuple_type_ref {
891 let expr = self.create_default_value_for_type(node, resolved_type)?;
892 expressions.push(expr);
893 }
894 ExpressionKind::TupleLiteral(expressions)
895 }
896
897 TypeKind::NamedStruct(_struct_ref) => {
898 if self
900 .shared
901 .state
902 .associated_impls
903 .get_member_function(field_type, "default")
904 .is_some()
905 {
906 self.create_default_static_call(node, field_type)
907 } else {
908 return None;
910 }
911 }
912
913 _ => {
914 return None;
916 }
917 };
918
919 Some(self.create_expr(kind, field_type.clone(), node))
920 }
921
922 fn create_static_member_call(
923 &mut self,
924 function_name: &str,
925 arguments: &[ArgumentExpression],
926 node: &swamp_ast::Node,
927 ty: &TypeRef,
928 ) -> ExpressionKind {
929 self.lookup_associated_function(ty, function_name)
930 .map_or_else(
931 || {
932 self.create_err(
933 ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
934 node,
935 )
936 .kind
937 },
938 |function| {
939 let Function::Internal(internal_function) = &function else {
940 panic!("only allowed for internal functions");
941 };
942
943 ExpressionKind::InternalCall(internal_function.clone(), arguments.to_vec())
944 },
945 )
946 }
947
948 fn create_static_member_intrinsic_call(
949 &mut self,
950 function_name: &str,
951 arguments: &[ArgumentExpression],
952 node: &swamp_ast::Node,
953 ty: &TypeRef,
954 ) -> ExpressionKind {
955 if let Some(function) = self.lookup_associated_function(ty, function_name) {
957 let Function::Internal(internal_function) = &function else {
958 panic!("only allowed for internal functions");
959 };
960
961 if let Some((intrinsic_fn, _)) =
962 Self::extract_single_intrinsic_call(&internal_function.body)
963 {
964 ExpressionKind::IntrinsicCallEx(intrinsic_fn, arguments.to_vec())
965 } else {
966 self.create_err(
967 ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
968 node,
969 )
970 .kind
971 }
972 } else {
973 self.create_err(
974 ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
975 node,
976 )
977 .kind
978 }
979 }
980
981 fn create_default_static_call(
982 &mut self,
983 node: &swamp_ast::Node,
984 ty: &TypeRef,
985 ) -> ExpressionKind {
986 self.create_static_member_call("default", &[], node, ty)
987 }
988
989 fn add_postfix(
990 &mut self,
991 vec: &mut Vec<Postfix>,
992 kind: PostfixKind,
993 ty: TypeRef,
994 node: &swamp_ast::Node,
995 ) {
996 let resolved_node = self.to_node(node);
997 let postfix = Postfix {
998 node: resolved_node,
999 ty,
1000 kind,
1001 };
1002
1003 vec.push(postfix);
1004 }
1005
1006
1007 pub fn analyze_struct_field(
1012 &mut self,
1013 field_name: &swamp_ast::Node,
1014 tv: &TypeRef,
1015 ) -> (AnonymousStructType, usize, TypeRef) {
1016 let field_name_str = self.get_text(field_name).to_string();
1017
1018 let anon_struct_ref = match &*tv.kind {
1019 TypeKind::NamedStruct(struct_type) => struct_type.anon_struct_type.clone(),
1020 TypeKind::AnonymousStruct(anon_struct) => {
1021 self.shared
1023 .state
1024 .types
1025 .anonymous_struct(anon_struct.clone())
1026 }
1027 TypeKind::Range(range_struct_ref) => {
1028 if let TypeKind::NamedStruct(named_struct) = &*range_struct_ref.kind {
1030 named_struct.anon_struct_type.clone()
1031 } else {
1032 self.add_err(ErrorKind::UnknownStructField, field_name);
1033 return (
1035 AnonymousStructType::new(SeqMap::new()),
1036 0,
1037 self.shared.state.types.unit(),
1038 );
1039 }
1040 }
1041 _ => {
1042 self.add_err(ErrorKind::UnknownStructField, field_name);
1043 return (
1045 AnonymousStructType::new(SeqMap::new()),
1046 0,
1047 self.shared.state.types.unit(),
1048 );
1049 }
1050 };
1051
1052 if let TypeKind::AnonymousStruct(anon_struct) = &*anon_struct_ref.kind
1054 && let Some(found_field) = anon_struct.field_name_sorted_fields.get(&field_name_str) {
1055 let index = anon_struct
1056 .field_name_sorted_fields
1057 .get_index(&field_name_str)
1058 .expect("checked earlier");
1059
1060 return (anon_struct.clone(), index, found_field.field_type.clone());
1061 }
1062
1063 self.add_err(ErrorKind::UnknownStructField, field_name);
1064 (
1066 AnonymousStructType::new(SeqMap::new()),
1067 0,
1068 self.shared.state.types.unit(),
1069 )
1070 }
1071
1072 pub fn analyze_static_call(
1073 &mut self,
1074 ast_node: &swamp_ast::Node,
1075 maybe_associated_to_type: Option<TypeRef>,
1076 func_def: Function,
1077 maybe_generic_arguments: &Option<Vec<swamp_ast::GenericParameter>>,
1078 arguments: &[swamp_ast::Expression],
1079 context: &TypeContext,
1080 ) -> Expression {
1081 let signature = func_def.signature().clone();
1082
1083 let analyzed_arguments =
1084 self.analyze_and_verify_parameters(ast_node, &signature.parameters, arguments);
1085
1086 let expr_kind = match &func_def {
1087 Function::Internal(internal) => {
1088 ExpressionKind::InternalCall(internal.clone(), analyzed_arguments)
1089 }
1090 Function::External(host) => ExpressionKind::HostCall(host.clone(), analyzed_arguments),
1091 Function::Intrinsic(intrinsic) => {
1092 ExpressionKind::IntrinsicCallEx(intrinsic.intrinsic.clone(), analyzed_arguments)
1093 }
1094 };
1095
1096 let expr = self.create_expr(expr_kind, signature.return_type.clone(), ast_node);
1097
1098 if self.needs_storage_error(&expr, true, context, ast_node) {
1100 return self.create_err(ErrorKind::NeedStorage, ast_node);
1101 }
1102
1103 expr
1104 }
1105
1106 #[allow(clippy::too_many_lines)]
1107 fn analyze_postfix_chain(
1108 &mut self,
1109 chain: &swamp_ast::PostfixChain,
1110 context: &TypeContext,
1111 ) -> Expression {
1112 let maybe_start_of_chain_base =
1113 self.analyze_start_chain_expression_get_mutability(&chain.base);
1114
1115 let mut start_index = 0;
1116
1117 let start_of_chain_kind = if let Some(start_of_chain_base) = maybe_start_of_chain_base {
1118 match start_of_chain_base {
1120 StartOfChainBase::FunctionReference(func_def) => {
1121 if let swamp_ast::Postfix::FunctionCall(
1124 ast_node,
1125 maybe_generic_arguments,
1126 arguments,
1127 ) = &chain.postfixes[0]
1128 {
1129 start_index = 1;
1130 let call_expr = self.analyze_static_call(
1131 ast_node,
1132 None,
1133 func_def,
1134 maybe_generic_arguments,
1135 arguments,
1136 context,
1137 );
1138 if chain.postfixes.len() == 1 {
1139 return call_expr;
1140 }
1141 StartOfChainKind::Expression(Box::from(call_expr))
1142 } else {
1143 panic!("must be a normal function call")
1144 }
1145 }
1146 StartOfChainBase::Variable(var) => StartOfChainKind::Variable(var),
1147 }
1148 } else {
1149 let ctx = TypeContext::new_anything_argument(true); StartOfChainKind::Expression(Box::from(self.analyze_expression(&chain.base, &ctx)))
1151 };
1152
1153 let start_of_chain_node = self.to_node(&chain.base.node);
1154
1155 let start_of_chain = StartOfChain {
1156 kind: start_of_chain_kind.clone(),
1157 node: start_of_chain_node,
1158 };
1159
1160 let mut tv = TypeWithMut {
1161 resolved_type: start_of_chain_kind.ty(),
1162 is_mutable: start_of_chain_kind.is_mutable(),
1163 };
1164
1165 let mut uncertain = false;
1166 let mut previous_was_optional_chaining = false;
1167
1168 let mut suffixes = Vec::new();
1169
1170 for (index, item) in chain.postfixes[start_index..].iter().enumerate() {
1171 let is_last = index == chain.postfixes[start_index..].len() - 1;
1172
1173 if previous_was_optional_chaining {
1175 match item {
1176 swamp_ast::Postfix::FieldAccess(_)
1177 | swamp_ast::Postfix::MemberCall(_, _, _)
1178 | swamp_ast::Postfix::Subscript(_)
1179 | swamp_ast::Postfix::SubscriptTuple(_, _) => {
1180 }
1182 swamp_ast::Postfix::OptionalChainingOperator(node) => {
1183 return self
1184 .create_err(ErrorKind::InvalidOperatorAfterOptionalChaining, node);
1185 }
1186 swamp_ast::Postfix::FunctionCall(node, _, _) => {
1187 return self
1188 .create_err(ErrorKind::InvalidOperatorAfterOptionalChaining, node);
1189 }
1190 }
1191 }
1192
1193 match item {
1194 swamp_ast::Postfix::FieldAccess(field_name) => {
1201 previous_was_optional_chaining = false;
1202 let (struct_type_ref, index, return_type) =
1203 self.analyze_struct_field(&field_name.clone(), &tv.resolved_type);
1204 let struct_type_type_ref = self
1205 .shared
1206 .state
1207 .types
1208 .anonymous_struct(struct_type_ref.clone());
1209 self.add_postfix(
1210 &mut suffixes,
1211 PostfixKind::StructField(struct_type_type_ref, index),
1212 return_type.clone(),
1213 field_name,
1214 );
1215
1216 tv.resolved_type = return_type.clone();
1217 }
1219
1220 swamp_ast::Postfix::SubscriptTuple(col_expr, row_expr) => {
1221 previous_was_optional_chaining = false;
1222 let collection_type = tv.resolved_type.clone();
1223 match &*collection_type.kind {
1224 TypeKind::GridStorage(element_type, x, _) => {
1225 let int_type = self.shared.state.types.int();
1226 let unsigned_int_x_context =
1227 TypeContext::new_argument(&int_type, false);
1228 let unsigned_int_x_expression =
1229 self.analyze_expression(col_expr, &unsigned_int_x_context);
1230
1231 let unsigned_int_y_context =
1232 TypeContext::new_argument(&int_type, false);
1233 let unsigned_int_y_expression =
1234 self.analyze_expression(row_expr, &unsigned_int_y_context);
1235
1236 let vec_type = GridType {
1237 element: element_type.clone(),
1238 };
1239
1240 self.add_postfix(
1241 &mut suffixes,
1242 PostfixKind::GridSubscript(
1243 vec_type,
1244 unsigned_int_x_expression,
1245 unsigned_int_y_expression,
1246 ),
1247 element_type.clone(),
1248 &col_expr.node,
1249 );
1250
1251 tv.resolved_type = element_type.clone();
1253 }
1254 _ => return self.create_err(ErrorKind::ExpectedTupleType, &chain.base.node),
1255 }
1256 }
1257
1258 swamp_ast::Postfix::Subscript(lookup_expr) => {
1259 previous_was_optional_chaining = false;
1260 let collection_type = tv.resolved_type.clone();
1261
1262 match &*collection_type.kind {
1263 TypeKind::MapStorage(key_type, value_type, ..) | TypeKind::DynamicLengthMapView(key_type, value_type) => {
1265 let (postfix, return_type) = self.analyze_map_subscript(key_type, value_type, lookup_expr);
1266 suffixes.push(postfix);
1267 tv.resolved_type = return_type;
1268 }
1269 _ => {
1270 let anything_context = context.with_argument_anything();
1272 let anything_expression =
1273 self.analyze_expression(lookup_expr, &anything_context);
1274
1275 match &*anything_expression.ty.kind {
1276 TypeKind::Int => {
1277 let (postfix, return_type) = self.analyze_subscript_int(collection_type, anything_expression);
1278 suffixes.push(postfix);
1279 tv.resolved_type = return_type;
1280 }
1281 TypeKind::Range(_range_type) => {
1282 let (postfix, return_type) = self.analyze_subscript_range(collection_type, anything_expression);
1283 suffixes.push(postfix);
1284 tv.resolved_type = return_type;
1285 }
1286 _ => {
1287 return self.create_err(ErrorKind::CanNotSubscriptWithThatType, &lookup_expr.node)
1288 }
1289 }
1290 }
1291 }
1292 }
1293
1294 swamp_ast::Postfix::MemberCall(member_name, generic_arguments, ast_arguments) => {
1295 previous_was_optional_chaining = false;
1296 let member_name_str = self.get_text(member_name).to_string();
1297 let underlying_type = tv.resolved_type;
1298
1299 let (kind, return_type) = self.analyze_member_call(
1300 &underlying_type,
1301 &member_name_str,
1302 generic_arguments.clone(),
1303 ast_arguments,
1304 tv.is_mutable,
1305 member_name,
1306 );
1307
1308 self.add_postfix(&mut suffixes, kind, return_type.clone(), member_name);
1309 tv.resolved_type = return_type.clone();
1310 tv.is_mutable = false;
1311 }
1312 swamp_ast::Postfix::FunctionCall(node, _generic_arguments, arguments) => {
1313 panic!("can only have function call at the start of a postfix chain")
1314 }
1315
1316 swamp_ast::Postfix::OptionalChainingOperator(option_node) => {
1317 if is_last {
1318 return self.create_err(
1319 ErrorKind::InvalidOperatorAfterOptionalChaining,
1320 option_node,
1321 );
1322 }
1323
1324 if let TypeKind::Optional(unwrapped_type) = &*tv.resolved_type.kind {
1325 uncertain = true;
1326 self.add_postfix(
1327 &mut suffixes,
1328 PostfixKind::OptionalChainingOperator,
1329 (*unwrapped_type).clone(),
1330 option_node,
1331 );
1332 tv.resolved_type = (*unwrapped_type).clone();
1333 previous_was_optional_chaining = true;
1334 } else {
1335 return self.create_err(ErrorKind::ExpectedOptional, option_node);
1336 }
1337 }
1338 }
1339 }
1340
1341 if uncertain {
1342 if let TypeKind::Optional(_) = &*tv.resolved_type.kind {} else {
1343 tv.resolved_type = self.shared.state.types.optional(&tv.resolved_type.clone());
1344 }
1345 }
1346
1347 self.create_expr(
1348 ExpressionKind::PostfixChain(start_of_chain, suffixes),
1349 tv.resolved_type,
1350 &chain.base.node,
1351 )
1352 }
1353
1354 fn analyze_bool_argument_expression(
1355 &mut self,
1356 expression: &swamp_ast::Expression,
1357 ) -> BooleanExpression {
1358 let bool_type = self.shared.state.types.bool();
1359 let bool_context = TypeContext::new_argument(&bool_type, false);
1360 let resolved_expression = self.analyze_expression(expression, &bool_context);
1361 let expr_type = resolved_expression.ty.clone();
1362
1363 let bool_expression = match &*expr_type.kind {
1364 TypeKind::Bool => resolved_expression,
1365 TypeKind::Optional(_) => {
1366 let bool = self.types().bool();
1367 self.create_expr(
1368 ExpressionKind::CoerceOptionToBool(Box::new(resolved_expression)),
1369 bool,
1370 &expression.node,
1371 )
1372 }
1373 _ => self.create_err(ErrorKind::ExpectedBooleanExpression, &expression.node),
1374 };
1375
1376 BooleanExpression {
1377 expression: Box::from(bool_expression),
1378 }
1379 }
1380
1381 fn is_aggregate_function_call(expression: &swamp_ast::Expression) -> bool {
1383 match &expression.kind {
1384 swamp_ast::ExpressionKind::PostfixChain(chain) => {
1385 if chain.postfixes.is_empty() {
1386 return false;
1387 }
1388
1389 for postfix in &chain.postfixes {
1390 if let swamp_ast::Postfix::FunctionCall(_, _, _) = postfix {
1391 return true;
1392 }
1393 }
1394 false
1395 }
1396 _ => false, }
1398 }
1399
1400 fn analyze_iterable(
1401 &mut self,
1402 mut_requested_for_value_variable: Option<swamp_ast::Node>,
1403 expression: &swamp_ast::Expression,
1404 ) -> Iterable {
1405 let has_lvalue_target = !Self::is_aggregate_function_call(expression);
1408 let any_context = TypeContext::new_anything_argument(has_lvalue_target);
1409
1410 let resolved_expression = self.analyze_expression(expression, &any_context);
1411
1412 let resolved_type = &resolved_expression.ty.clone();
1413 let int_type = Some(self.types().int());
1414 let (key_type, value_type): (Option<TypeRef>, TypeRef) = match &*resolved_type.kind {
1415 TypeKind::String(_, char) => (int_type, char.clone()),
1416 TypeKind::SliceView(element_type) => (int_type, element_type.clone()),
1417 TypeKind::VecStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1418 TypeKind::SparseStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1419 TypeKind::StackStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1420 TypeKind::StackView(element_type) => (int_type, element_type.clone()),
1421 TypeKind::QueueStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1422 TypeKind::QueueView(element_type) => (int_type, element_type.clone()),
1423 TypeKind::DynamicLengthVecView(element_type) => (int_type, element_type.clone()),
1424 TypeKind::SparseView(element_type) => (int_type, element_type.clone()),
1425 TypeKind::FixedCapacityAndLengthArray(element_type, _fixed_size) => {
1426 (int_type, element_type.clone())
1427 }
1428 TypeKind::DynamicLengthMapView(key_type, value_type)
1429 | TypeKind::MapStorage(key_type, value_type, _) => {
1430 (Some(key_type.clone()), value_type.clone())
1431 }
1432 TypeKind::Range(_) => (None, self.types().int()),
1433 _ => {
1434 error!(?resolved_type, "not an iterator");
1435 return Iterable {
1436 key_type: None,
1437 value_type: self.shared.state.types.unit(),
1438 resolved_expression: Box::new(
1439 self.create_err(ErrorKind::NotAnIterator, &expression.node),
1440 ),
1441 };
1442 }
1443 };
1444
1445 if mut_requested_for_value_variable.is_some() {
1446 let _resulting_location =
1448 self.analyze_to_location(expression, &any_context, LocationSide::Mutable);
1449 }
1452
1453 Iterable {
1454 key_type,
1455 value_type,
1456 resolved_expression: Box::new(resolved_expression),
1457 }
1458 }
1459
1460 fn analyze_argument_expressions(
1461 &mut self,
1462 expected_type: Option<&TypeRef>,
1463 context: &TypeContext,
1464 ast_expressions: &[swamp_ast::Expression],
1465 ) -> Vec<Expression> {
1466 let mut resolved_expressions = Vec::new();
1467 let argument_expressions_context = TypeContext::new_unsure_argument(expected_type, false);
1469
1470 for expression in ast_expressions {
1471 resolved_expressions
1472 .push(self.analyze_expression(expression, &argument_expressions_context));
1473 }
1474 resolved_expressions
1475 }
1476
1477 fn analyze_block(
1478 &mut self,
1479 _node: &swamp_ast::Node,
1480 context: &TypeContext,
1481 ast_expressions: &[swamp_ast::Expression],
1482 ) -> (Vec<Expression>, TypeRef) {
1483 if ast_expressions.is_empty() {
1484 return (vec![], self.shared.state.types.unit());
1485 }
1486
1487 self.push_block_scope("block");
1488
1489 let mut resolved_expressions = Vec::with_capacity(ast_expressions.len());
1490
1491 for expression in &ast_expressions[..ast_expressions.len() - 1] {
1492 let unit_type = self.shared.state.types.unit();
1493 let stmt_context =
1494 context.with_expected_type(Some(&unit_type), context.has_lvalue_target);
1495 let expr = self.analyze_expression(expression, &stmt_context);
1496
1497 resolved_expressions.push(expr);
1498 }
1499
1500 let last_expr =
1502 self.analyze_expression(&ast_expressions[ast_expressions.len() - 1], context);
1503 let last_type = last_expr.ty.clone();
1504 resolved_expressions.push(last_expr);
1505
1506 self.pop_block_scope("block");
1507
1508 (resolved_expressions, last_type)
1509 }
1510
1511 fn analyze_interpolated_string_lowering(
1512 &mut self,
1513 node: &swamp_ast::Node,
1514 string_parts: &[swamp_ast::StringPart],
1515 ) -> Expression {
1516 let mut last_expression: Option<Expression> = None;
1517 for part in string_parts {
1518 let created_expression = match part {
1519 swamp_ast::StringPart::Literal(string_node, processed_string) => {
1520 let string_literal =
1521 ExpressionKind::StringLiteral(processed_string.to_string());
1522 let basic_literal = string_literal;
1523 let string_type = self.shared.state.types.string();
1524 self.create_expr(basic_literal, string_type, string_node)
1525 }
1526 swamp_ast::StringPart::Interpolation(expression, format_specifier) => {
1527 let any_context = TypeContext::new_anything_argument(false); let expr = self.analyze_expression(expression, &any_context);
1530
1531 let tk = (*expr.ty.kind).clone();
1532
1533 let maybe_to_string = self
1534 .shared
1535 .state
1536 .associated_impls
1537 .get_internal_member_function(&expr.ty, "string");
1538
1539 if matches!(tk, TypeKind::String { .. }) {
1540 expr
1541 } else {
1542 let underlying = expr.ty.clone();
1543
1544 if self.needs_storage_error(&expr, true, &any_context, &expression.node) {
1546 return self.create_err(ErrorKind::NeedStorage, &expression.node);
1547 }
1548
1549 let call_expr_kind = if maybe_to_string.is_none() {
1550 let string_type = self.types().string();
1551
1552 ExpressionKind::StringLiteral(format!("missing {string_type}"))
1553 } else {
1562 let expr_as_param = ArgumentExpression::Expression(expr);
1563 self.create_static_member_call(
1564 "string",
1565 &[expr_as_param.clone()],
1566 &expression.node,
1567 &underlying,
1568 )
1569 };
1570
1571 let string_type = self.shared.state.types.string();
1579 self.create_expr(call_expr_kind, string_type, &expression.node)
1580 }
1581 }
1582 };
1583
1584 let x_last_expr = if let Some(last_expr) = last_expression.clone() {
1585 let op_kind = BinaryOperatorKind::Add;
1586 let node = created_expression.node.clone();
1587 let op = BinaryOperator {
1588 left: Box::new(last_expr),
1589 right: Box::new(created_expression),
1590 kind: op_kind,
1591 node: node.clone(),
1592 };
1593
1594 let string_type = self.shared.state.types.string();
1595 create_expr_resolved(ExpressionKind::BinaryOp(op), string_type, &node)
1596 } else {
1597 created_expression
1598 };
1599
1600 last_expression = Some(x_last_expr);
1601 }
1602
1603 if let Some(last) = last_expression {
1606 last
1607 } else {
1608 let string_type = self.shared.state.types.string();
1609 self.create_expr(
1610 ExpressionKind::StringLiteral(String::new()),
1611 string_type,
1612 node,
1613 )
1614 }
1615 }
1616
1617 pub(crate) fn analyze_identifier(
1618 &mut self,
1619 qualified_func_name: &swamp_ast::QualifiedIdentifier,
1620 ) -> Expression {
1621 if qualified_func_name.module_path.is_none()
1624 && qualified_func_name.generic_params.is_empty()
1625 && let Some(found_variable) = self.try_find_variable(&qualified_func_name.name) {
1626 return self.create_expr(
1627 ExpressionKind::VariableAccess(found_variable.clone()),
1628 found_variable.resolved_type.clone(),
1629 &qualified_func_name.name,
1630 );
1631 }
1632
1633 let text = self.get_text(&qualified_func_name.name);
1634 self.create_err(
1635 ErrorKind::UnknownIdentifier(text.to_string()),
1636 &qualified_func_name.name,
1637 )
1638 }
1639
1640 fn analyze_variable_reference(&mut self, var_node: &swamp_ast::Node) -> Expression {
1642 if let Some(found_variable) = self.try_find_variable(var_node) {
1643 return self.create_expr(
1644 ExpressionKind::VariableAccess(found_variable.clone()),
1645 found_variable.resolved_type.clone(),
1646 var_node,
1647 );
1648 }
1649 let text = self.get_text(var_node);
1650 self.create_err(ErrorKind::UnknownIdentifier(text.to_string()), var_node)
1651 }
1652
1653 fn analyze_internal_initializer_pair_list(
1654 &mut self,
1655 node: &swamp_ast::Node,
1656 items: &[(swamp_ast::Expression, swamp_ast::Expression)],
1657 context: &TypeContext,
1658 ) -> (TypeRef, Vec<(Expression, Expression)>) {
1659 let (collection_type, key_type, value_type) = if let Some(expected_type) =
1660 context.expected_type
1661 {
1662 match &*expected_type.kind {
1663 TypeKind::MapStorage(key, value, capacity) => {
1664 if items.len() > *capacity {
1665 self.add_err(
1666 ErrorKind::TooManyInitializerListElementsForStorage {
1667 capacity: *capacity,
1668 },
1669 node,
1670 );
1671 return (self.types().unit(), vec![]);
1672 }
1673 (expected_type.clone(), key.clone(), value.clone())
1674 }
1675 TypeKind::DynamicLengthMapView(key, value) => {
1676 (expected_type.clone(), key.clone(), value.clone())
1677 }
1678 _ => {
1679 self.add_err(ErrorKind::ExpectedSlice, node);
1680 return (self.types().unit(), vec![]);
1681 }
1682 }
1683 } else if items.is_empty() {
1684 self.add_err(ErrorKind::NoInferredTypeForEmptyInitializer, node);
1685 return (self.types().unit(), vec![]);
1686 } else {
1687 let maybe_key_context = TypeContext::new_anything_argument(true);
1689
1690 let first_key_expression = self.analyze_expression(&items[0].0, &maybe_key_context);
1691
1692 let maybe_value_context = TypeContext::new_anything_argument(true);
1693 let first_value_expression = self.analyze_expression(&items[0].1, &maybe_value_context);
1694
1695 let required_key_type = first_key_expression.ty;
1696 let required_value_type = first_value_expression.ty;
1697
1698 let inferred_type =
1699 self.types()
1700 .map_storage(&required_key_type, &required_value_type, items.len());
1701
1702 (inferred_type, required_key_type, required_value_type)
1703 };
1704
1705 assert!(!matches!(*key_type.kind, TypeKind::Unit));
1706 assert!(!matches!(*value_type.kind, TypeKind::Unit));
1707
1708 let required_key_context = TypeContext::new_argument(&key_type, true);
1709 let required_value_context = TypeContext::new_argument(&value_type, true);
1710
1711 let mut resolved_items = Vec::new();
1712
1713 for (key_expr, value_expr) in items {
1714 let analyzed_key_expr = self.analyze_expression(key_expr, &required_key_context);
1715 let analyzed_value_expr = self.analyze_expression(value_expr, &required_value_context);
1716 resolved_items.push((analyzed_key_expr, analyzed_value_expr));
1717 }
1718
1719 (collection_type, resolved_items)
1720 }
1721
1722 fn analyze_internal_initializer_list(
1723 &mut self,
1724 node: &swamp_ast::Node,
1725 items: &[swamp_ast::Expression],
1726 context: &TypeContext,
1727 ) -> (TypeRef, Vec<Expression>) {
1728 let (collection_type, element_type) = if let Some(expected_type) = context.expected_type {
1729 match &*expected_type.kind {
1730 TypeKind::GridStorage(element_type, width, height) => {
1731 let capacity = width * height;
1732 if items.len() > capacity {
1733 return (
1734 self.types().unit(),
1735 self.create_err_vec(
1736 ErrorKind::TooManyInitializerListElementsForStorage { capacity },
1737 node,
1738 ),
1739 );
1740 }
1741 (expected_type.clone(), element_type.clone())
1742 }
1743 TypeKind::StackStorage(element_type, capacity)
1744 | TypeKind::QueueStorage(element_type, capacity)
1745 | TypeKind::SparseStorage(element_type, capacity)
1746 | TypeKind::VecStorage(element_type, capacity) => {
1747 if items.len() > *capacity {
1748 return (
1749 self.types().unit(),
1750 self.create_err_vec(
1751 ErrorKind::TooManyInitializerListElementsForStorage {
1752 capacity: *capacity,
1753 },
1754 node,
1755 ),
1756 );
1757 }
1758 (expected_type.clone(), element_type.clone())
1759 }
1760 TypeKind::QueueView(element_type) => {
1761 let inferred_storage_type =
1763 self.types().queue_storage(element_type, items.len());
1764 let default_node = swamp_ast::Node::default();
1765 self.add_default_functions(&inferred_storage_type, &default_node);
1766 (inferred_storage_type, element_type.clone())
1767 }
1768 TypeKind::SparseView(element_type) => {
1769 let inferred_storage_type =
1771 self.types().sparse_storage(element_type, items.len());
1772 let default_node = swamp_ast::Node::default();
1773 self.add_default_functions(&inferred_storage_type, &default_node);
1774 (inferred_storage_type, element_type.clone())
1775 }
1776 TypeKind::StackView(element_type) => {
1777 let inferred_storage_type =
1779 self.types().stack_storage(element_type, items.len());
1780 let default_node = swamp_ast::Node::default();
1781 self.add_default_functions(&inferred_storage_type, &default_node);
1782 (inferred_storage_type, element_type.clone())
1783 }
1784 TypeKind::GridView(element_type) => {
1785 (expected_type.clone(), element_type.clone())
1787 }
1788 TypeKind::DynamicLengthVecView(element_type) => {
1789 let inferred_storage_type = self.types().vec_storage(element_type, items.len());
1791 let default_node = swamp_ast::Node::default();
1792 self.add_default_functions(&inferred_storage_type, &default_node);
1793 (inferred_storage_type, element_type.clone())
1794 }
1795 TypeKind::SliceView(element_type) => {
1796 let inferred_storage_type = self.types().vec_storage(element_type, items.len());
1798 let default_node = swamp_ast::Node::default();
1799 self.add_default_functions(&inferred_storage_type, &default_node);
1800 (inferred_storage_type, element_type.clone())
1801 }
1802 TypeKind::FixedCapacityAndLengthArray(element_type, _size) => {
1803 (expected_type.clone(), element_type.clone())
1804 }
1805 _ => {
1806 return (
1807 self.types().unit(),
1808 self.create_err_vec(
1809 ErrorKind::ExpectedInitializerTarget {
1810 destination_type: expected_type.clone(),
1811 },
1812 node,
1813 ),
1814 );
1815 }
1816 }
1817 } else if items.is_empty() {
1818 return (
1819 self.types().unit(),
1820 self.create_err_vec(ErrorKind::NoInferredTypeForEmptyInitializer, node),
1821 );
1822 } else {
1823 let maybe_context = TypeContext::new_anything_argument(true);
1825 let first = self.analyze_expression(&items[0], &maybe_context);
1826 let required_type = first.ty;
1827 let inferred_vec_storage_type = self.types().vec_storage(&required_type, items.len());
1828 let default_node = swamp_ast::Node::default();
1830 self.add_default_functions(&inferred_vec_storage_type, &default_node);
1831 (inferred_vec_storage_type, required_type)
1832 };
1833
1834 let required_context = TypeContext::new_argument(&element_type, true);
1835 let mut resolved_items = Vec::new();
1836 for item in items {
1837 let resolved_expr = self.analyze_expression(item, &required_context);
1838 resolved_items.push(resolved_expr);
1839 }
1840 (collection_type, resolved_items)
1841 }
1842
1843 fn push_block_scope(&mut self, debug_str: &str) {
1844 let register_watermark = self.scope.total_scopes.current_register;
1845
1846 self.scope.active_scope.block_scope_stack.push(BlockScope {
1847 mode: BlockScopeMode::Open,
1848 lookup: Default::default(),
1849 variables: SeqMap::default(),
1850 register_watermark,
1851 });
1852 }
1853
1854 fn push_lambda_scope(&mut self, debug_str: &str) {
1855 self.scope.active_scope.block_scope_stack.push(BlockScope {
1858 mode: BlockScopeMode::Lambda,
1859 lookup: SeqMap::default(),
1860 variables: SeqMap::default(),
1861 register_watermark: 0, });
1863 }
1864
1865 fn pop_block_scope(&mut self, debug_str: &str) {
1866 self.pop_any_block_scope();
1867 }
1868
1869 fn push_closed_block_scope(&mut self) {
1870 let register_watermark = self.scope.total_scopes.current_register;
1871 self.scope.active_scope.block_scope_stack.push(BlockScope {
1872 mode: BlockScopeMode::Closed,
1873 lookup: Default::default(),
1874 variables: SeqMap::default(),
1875 register_watermark,
1876 });
1877 }
1878
1879 fn pop_closed_block_scope(&mut self) {
1880 self.pop_any_block_scope();
1882 }
1883
1884 fn pop_any_block_scope(&mut self) {
1885 let scope = self.scope.active_scope.block_scope_stack.pop().unwrap();
1886
1887 self.scope.total_scopes.highest_virtual_register = self.scope.total_scopes.current_register;
1889
1890 let is_inside_lambda = self
1892 .scope
1893 .active_scope
1894 .block_scope_stack
1895 .iter()
1896 .any(|s| matches!(s.mode, BlockScopeMode::Lambda));
1897
1898 if matches!(scope.mode, BlockScopeMode::Lambda) {
1899 } else if is_inside_lambda {
1901 } else {
1903 self.scope.total_scopes.current_register = scope.register_watermark;
1905 }
1906 }
1907
1908 fn analyze_match(
1909 &mut self,
1910 scrutinee: &swamp_ast::Expression,
1911 default_context: &TypeContext,
1912 arms: &Vec<swamp_ast::MatchArm>,
1913 ) -> (Match, TypeRef) {
1914 let mut known_type = default_context.expected_type.cloned();
1915 let own_context = default_context.clone();
1916 let scrutinee_context = TypeContext::new_anything_argument(true); let resolved_scrutinee = self.analyze_expression(scrutinee, &scrutinee_context);
1919 let scrutinee_type = resolved_scrutinee.ty.clone();
1920
1921 let mut resolved_arms = Vec::with_capacity(arms.len());
1922
1923 if arms.is_empty() {
1925 let err_match = Match {
1926 expression: Box::new(
1927 self.create_err(ErrorKind::MatchMustHaveAtLeastOneArm, &scrutinee.node),
1928 ),
1929 arms: resolved_arms,
1930 };
1931 return (err_match, self.types().unit());
1932 }
1933
1934 for arm in arms {
1935 let (resolved_arm, _anyone_wants_mutable) = self.analyze_arm(
1936 arm,
1937 &resolved_scrutinee,
1938 &own_context.with_expected_type(known_type.as_ref(), false),
1939 &scrutinee_type,
1940 );
1941
1942 if known_type.is_none() {
1943 known_type = Some(resolved_arm.expression.ty.clone());
1944 }
1945 resolved_arms.push(resolved_arm);
1946 }
1947
1948 if let Some(encountered_type) = known_type {
1949 (
1950 Match {
1951 expression: Box::new(resolved_scrutinee),
1952 arms: resolved_arms,
1953 },
1954 encountered_type,
1955 )
1956 } else {
1957 let err_expr = self.create_err(ErrorKind::MatchArmsMustHaveTypes, &scrutinee.node);
1958
1959 (
1960 Match {
1961 expression: Box::new(err_expr),
1962 arms: resolved_arms.clone(),
1963 },
1964 self.types().unit(),
1965 )
1966 }
1967 }
1968
1969 fn analyze_arm(
1970 &mut self,
1971 arm: &swamp_ast::MatchArm,
1972 _expression: &Expression,
1973 type_context: &TypeContext,
1974 expected_condition_type: &TypeRef,
1975 ) -> (MatchArm, bool) {
1976 let (resolved_pattern, scope_was_pushed, anyone_wants_mutable) =
1977 self.analyze_pattern(&arm.pattern, expected_condition_type);
1978
1979 let resolved_expression = self.analyze_expression(&arm.expression, type_context);
1980 if scope_was_pushed {
1981 self.pop_block_scope("analyze_arm");
1982 }
1983
1984 let resolved_type = resolved_expression.ty.clone();
1985
1986 (
1987 MatchArm {
1988 pattern: resolved_pattern,
1989 expression: Box::from(resolved_expression),
1990 expression_type: resolved_type,
1991 },
1992 anyone_wants_mutable,
1993 )
1994 }
1995
1996 fn str_to_int(text: &str) -> Result<i32, ParseIntError> {
1997 let text = text.replace('_', "");
1998 text.strip_prefix("0x").map_or_else(
1999 || {
2000 text.strip_prefix("-0x").map_or_else(
2001 || text.parse::<i32>(),
2002 |rest| i32::from_str_radix(rest, 16).map(|x| -x),
2003 )
2004 },
2005 |rest| i32::from_str_radix(rest, 16),
2006 )
2007 }
2008
2009 fn str_to_unsigned_int(text: &str) -> Result<u32, ParseIntError> {
2010 let text = text.replace('_', "");
2011 text.strip_prefix("0x")
2012 .map_or_else(|| text.parse::<u32>(), |rest| u32::from_str_radix(rest, 16))
2013 }
2014
2015 fn str_to_float(text: &str) -> Result<f32, ParseFloatError> {
2016 text.parse::<f32>()
2017 }
2018
2019 fn str_to_bool(text: &str) -> Result<bool, ParseBoolError> {
2020 bool::from_str(text)
2021 }
2022
2023 fn analyze_pattern_literal(
2024 &mut self,
2025 node: &swamp_ast::Node,
2026 ast_literal: &swamp_ast::LiteralKind,
2027 expected_condition_type: &TypeRef,
2028 ) -> NormalPattern {
2029 let required_condition_type_context =
2030 TypeContext::new_argument(expected_condition_type, false);
2031 let literal = self.analyze_literal(
2032 node,
2033 ast_literal,
2034 &required_condition_type_context,
2035 &required_condition_type_context,
2036 );
2037
2038 if !self
2039 .types()
2040 .compatible_with(&literal.ty, expected_condition_type)
2041 {
2042 return NormalPattern::Literal(self.create_err(
2043 ErrorKind::IncompatibleTypes {
2044 expected: expected_condition_type.clone(),
2045 found: literal.ty,
2046 },
2047 node,
2048 ));
2049 }
2050
2051 NormalPattern::Literal(literal)
2052 }
2053
2054 const fn to_node(&self, node: &swamp_ast::Node) -> Node {
2055 Node {
2056 span: Span {
2057 file_id: self.shared.file_id,
2058 offset: node.span.offset,
2059 length: node.span.length,
2060 },
2061 }
2062 }
2063
2064 fn get_module_path(&self, module_path: Option<&swamp_ast::ModulePath>) -> Vec<String> {
2065 module_path.as_ref().map_or_else(Vec::new, |found| {
2066 let mut strings = Vec::new();
2067 for path_item in &found.0 {
2068 strings.push(self.get_text(path_item).to_string());
2069 }
2070 strings
2071 })
2072 }
2073
2074 fn get_enum_variant_type(
2075 &mut self,
2076 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2077 variant_name: &str,
2078 ) -> EnumVariantType {
2079 let Some((symbol_table, enum_name)) =
2080 self.get_symbol_table_and_name(qualified_type_identifier)
2081 else {
2082 self.add_err(
2083 ErrorKind::UnknownEnumVariantType,
2084 &qualified_type_identifier.name.0,
2085 );
2086 return EnumVariantType {
2087 common: EnumVariantCommon {
2088 name: Default::default(),
2089 assigned_name: String::new(),
2090 container_index: 0,
2091 },
2092 payload_type: self.types().unit(),
2093 };
2094 };
2095
2096 if let Some(enum_name) = symbol_table.get_enum_variant_type(&enum_name, variant_name) {
2097 enum_name
2098 } else {
2099 self.add_err(
2100 ErrorKind::UnknownEnumVariantType,
2101 &qualified_type_identifier.name.0,
2102 );
2103 EnumVariantType {
2104 common: EnumVariantCommon {
2105 name: Default::default(),
2106 assigned_name: String::new(),
2107 container_index: 0,
2108 },
2109 payload_type: self.types().unit(),
2110 }
2111 }
2112 }
2113
2114 pub(crate) fn get_symbol_table_and_name(
2115 &self,
2116 type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2117 ) -> Option<(&SymbolTable, String)> {
2118 let path = self.get_module_path(type_identifier.module_path.as_ref());
2119 let name = self.get_text(&type_identifier.name.0).to_string();
2120
2121 if let Some(found) = self.shared.get_symbol_table(&path) {
2122 Some((found, name))
2123 } else {
2124 None
2125 }
2126 }
2127
2128 const fn analyze_compound_operator(
2129 &self,
2130 ast_operator: &swamp_ast::CompoundOperator,
2131 ) -> CompoundOperator {
2132 let resolved_node = self.to_node(&ast_operator.node);
2133 let resolved_kind = match ast_operator.kind {
2134 swamp_ast::CompoundOperatorKind::Add => CompoundOperatorKind::Add,
2135 swamp_ast::CompoundOperatorKind::Sub => CompoundOperatorKind::Sub,
2136 swamp_ast::CompoundOperatorKind::Mul => CompoundOperatorKind::Mul,
2137 swamp_ast::CompoundOperatorKind::Div => CompoundOperatorKind::Div,
2138 swamp_ast::CompoundOperatorKind::Modulo => CompoundOperatorKind::Modulo,
2139 };
2140
2141 CompoundOperator {
2142 node: resolved_node,
2143 kind: resolved_kind,
2144 }
2145 }
2146
2147 const fn to_node_option(&self, maybe_node: Option<&swamp_ast::Node>) -> Option<Node> {
2148 match maybe_node {
2149 None => None,
2150 Some(node) => Some(self.to_node(node)),
2151 }
2152 }
2153
2154 const fn analyze_format_specifier(
2155 &self,
2156 ast_format_specifier: Option<&swamp_ast::FormatSpecifier>,
2157 ) -> Option<FormatSpecifier> {
2158 let f = match ast_format_specifier {
2159 None => return None,
2160 Some(ast_format) => match ast_format {
2161 swamp_ast::FormatSpecifier::LowerHex(node) => FormatSpecifier {
2162 node: self.to_node(node),
2163 kind: FormatSpecifierKind::LowerHex,
2164 },
2165 swamp_ast::FormatSpecifier::UpperHex(node) => FormatSpecifier {
2166 node: self.to_node(node),
2167 kind: FormatSpecifierKind::UpperHex,
2168 },
2169 swamp_ast::FormatSpecifier::Binary(node) => FormatSpecifier {
2170 node: self.to_node(node),
2171 kind: FormatSpecifierKind::Binary,
2172 },
2173 swamp_ast::FormatSpecifier::Float(node) => FormatSpecifier {
2174 node: self.to_node(node),
2175 kind: FormatSpecifierKind::Float,
2176 },
2177 swamp_ast::FormatSpecifier::Precision(value, node, x) => {
2178 let (precision_type, precision_node) = match x {
2179 swamp_ast::PrecisionType::Float(node) => {
2180 (PrecisionType::Float, self.to_node(node))
2181 }
2182 swamp_ast::PrecisionType::String(node) => {
2183 (PrecisionType::String, self.to_node(node))
2184 }
2185 };
2186 FormatSpecifier {
2187 node: self.to_node(node),
2188 kind: FormatSpecifierKind::Precision(
2189 *value,
2190 precision_node,
2191 precision_type,
2192 ),
2193 }
2194 }
2195 },
2196 };
2197
2198 Some(f)
2199 }
2200
2201 fn analyze_with_expr(
2202 &mut self,
2203 context: &TypeContext,
2204 variables: &[swamp_ast::VariableBinding],
2205 expression: &swamp_ast::Expression,
2206 ) -> Expression {
2207 let mut variable_expressions = Vec::new();
2208
2209 for variable in variables {
2210 let any_context = TypeContext::new_anything_argument(false);
2211 let must_have_expression = if let Some(x) = &variable.expression {
2212 x
2213 } else {
2214 &swamp_ast::Expression {
2215 kind: swamp_ast::ExpressionKind::VariableReference(variable.variable.clone()),
2216 node: variable.variable.name.clone(),
2217 }
2218 };
2219
2220 let location_side = if variable.variable.is_mutable.is_some() {
2222 if let Some(expr) = &variable.expression {
2224 let maybe_ref = self.analyze_maybe_ref_expression(expr);
2226 if maybe_ref.has_borrow_mutable_reference.is_some() {
2227 LocationSide::Mutable
2228 } else {
2229 LocationSide::Rhs
2230 }
2231 } else {
2232 LocationSide::Rhs
2234 }
2235 } else {
2236 LocationSide::Rhs
2238 };
2239
2240 let var = self.analyze_mut_or_immutable_expression(
2241 must_have_expression,
2242 &any_context,
2243 location_side,
2244 );
2245
2246 variable_expressions.push(var);
2247 }
2248
2249 self.push_closed_block_scope();
2250 let mut expressions = Vec::new();
2251 for (variable_binding, resolved_expression) in variables.iter().zip(variable_expressions) {
2252 let initialize_variable_expression = self
2253 .create_variable_binding_for_with(&variable_binding.variable, resolved_expression);
2254
2255 expressions.push(initialize_variable_expression);
2259 }
2260
2261 let resolved_expression = self.analyze_expression(expression, context);
2262 let block_type = self.types().unit();
2264 expressions.push(resolved_expression);
2265
2266 let block_expression_kind = ExpressionKind::Block(expressions);
2267 self.pop_closed_block_scope();
2268
2269 self.create_expr(block_expression_kind, block_type, &expression.node)
2270 }
2271
2272 fn analyze_when_expr(
2273 &mut self,
2274 context: &TypeContext,
2275 variables: &[swamp_ast::VariableBinding],
2276 true_expr: &swamp_ast::Expression,
2277 else_expr: Option<&swamp_ast::Expression>,
2278 ) -> Expression {
2279 self.push_block_scope("when");
2281 let mut bindings = Vec::new();
2282 for variable_binding in variables {
2283 let mut_expr = if let Some(found_expr) = &variable_binding.expression {
2284 let any_context = TypeContext::new_anything_argument(true); self.analyze_mut_or_immutable_expression(
2286 found_expr,
2287 &any_context,
2288 LocationSide::Rhs,
2289 )
2290 .expect_immutable()
2291 .unwrap()
2292 } else {
2293 let same_var = self.find_variable(&variable_binding.variable);
2294
2295 let generated_expr_kind = ExpressionKind::VariableAccess(same_var.clone());
2298 self.create_expr(
2299 generated_expr_kind,
2300 same_var.resolved_type.clone(),
2301 &variable_binding.variable.name,
2302 )
2303 };
2304
2305 let tk = &mut_expr.ty.kind;
2306
2307 if let TypeKind::Optional(found_ty) = &**tk {
2308 let variable_ref = { self.create_variable(&variable_binding.variable, found_ty)
2313 };
2316
2317 let binding = WhenBinding {
2318 variable: variable_ref,
2319 expr: mut_expr,
2320 };
2321 bindings.push(binding);
2322 } else {
2323 return self.create_err(ErrorKind::ExpectedOptional, &true_expr.node);
2324 }
2325 }
2326
2327 let resolved_true = self.analyze_expression(true_expr, context);
2328 let block_type = resolved_true.ty.clone();
2329
2330 self.pop_block_scope("when");
2331
2332 let maybe_resolved_else = if let Some(found_else) = else_expr {
2333 let block_type_for_true_context = context.we_know_expected_type(&block_type, false);
2334 Some(Box::new(self.analyze_expression(
2335 found_else,
2336 &block_type_for_true_context,
2337 )))
2338 } else {
2339 None
2340 };
2341
2342 let when_kind =
2343 ExpressionKind::When(bindings, Box::from(resolved_true), maybe_resolved_else);
2344
2345 self.create_expr(when_kind, block_type, &true_expr.node)
2346 }
2347
2348 fn analyze_guard(
2349 &mut self,
2350 node: &swamp_ast::Node,
2351 context: &TypeContext,
2352 guard_expressions: &Vec<swamp_ast::GuardExpr>,
2353 ) -> Expression {
2354 let mut guards = Vec::new();
2355 let mut found_wildcard = None;
2356 let mut detected_type = context.expected_type.cloned();
2357
2358 for guard in guard_expressions {
2359 let resolved_condition = match &guard.clause {
2360 swamp_ast::GuardClause::Wildcard(x) => {
2361 if found_wildcard.is_some() {
2362 return self.create_err(ErrorKind::GuardCanNotHaveMultipleWildcards, node);
2363 }
2364 found_wildcard = Some(x);
2365 None
2366 }
2367 swamp_ast::GuardClause::Expression(clause_expr) => {
2368 if found_wildcard.is_some() {
2369 return self.create_err(ErrorKind::WildcardMustBeLastInGuard, node);
2370 }
2371 Some(self.analyze_bool_argument_expression(clause_expr))
2372 }
2373 };
2374
2375 let resolved_result = self.analyze_expression(
2376 &guard.result,
2377 &context.with_expected_type(detected_type.as_ref(), false),
2378 );
2379 let ty = resolved_result.ty.clone();
2380 if detected_type.is_none() {
2381 detected_type = Some(ty.clone());
2382 }
2383
2384 guards.push(Guard {
2385 condition: resolved_condition,
2386 result: resolved_result,
2387 });
2388 }
2389
2390 if found_wildcard.is_none() {
2391 return self.create_err(ErrorKind::GuardMustHaveWildcard, node);
2392 }
2393
2394 let kind = ExpressionKind::Guard(guards);
2395
2396 if let Some(found_expecting_type) = detected_type {
2397 self.create_expr(kind, found_expecting_type, node)
2398 } else {
2399 self.create_err(ErrorKind::GuardHasNoType, node)
2400 }
2401 }
2402
2403 fn analyze_lambda(
2404 &mut self,
2405 node: &swamp_ast::Node,
2406 variables: &[swamp_ast::Variable],
2407 ast_expr: &swamp_ast::Expression,
2408 context: &TypeContext,
2409 ) -> Expression {
2410 let TypeKind::Function(signature) = &*context.expected_type.unwrap().kind else {
2411 return self.create_err(ErrorKind::ExpectedLambda, node);
2412 };
2413
2414 let return_block_type = TypeContext::new_argument(&signature.return_type, false);
2415
2416 self.push_lambda_scope("lambda");
2419
2420 let arity_required = signature.parameters.len();
2421 let variable_types_to_create = if variables.len() == arity_required {
2422 &signature.parameters
2423 } else if variables.len() + 1 == arity_required {
2424 &signature.parameters[1..].to_vec()
2425 } else {
2426 return self.create_err(ErrorKind::WrongNumberOfArguments(0, 0), node);
2427 };
2428
2429 let mut resolved_variables = Vec::new();
2430 for (variable, variable_type) in variables.iter().zip(variable_types_to_create) {
2431 let variable_ref = self.create_local_variable(
2432 &variable.name,
2433 variable.is_mutable.as_ref(),
2434 &variable_type.resolved_type,
2435 false,
2436 );
2437 resolved_variables.push(variable_ref);
2438 }
2439
2440 let analyzed_expression = self.analyze_expression(ast_expr, &return_block_type);
2443
2444 self.pop_block_scope("lambda");
2445
2446 let function_type = self.types().function(signature.clone());
2447 self.create_expr(
2448 ExpressionKind::Lambda(resolved_variables, Box::new(analyzed_expression)),
2449 function_type,
2450 node,
2451 )
2452 }
2453
2454 #[must_use]
2455 pub fn chain_is_owned_result(
2456 start_of_chain: &StartOfChain,
2457 chains: &Vec<Postfix>,
2458 ) -> (bool, bool) {
2459 let mut is_owned_result = matches!(start_of_chain.kind, StartOfChainKind::Expression(_));
2460 let mut is_mutable = if let StartOfChainKind::Variable(var) = &start_of_chain.kind {
2461 var.is_mutable()
2462 } else {
2463 false
2464 };
2465
2466 for chain in chains {
2467 match chain.kind {
2468 PostfixKind::StructField(_, _) => {
2469 is_owned_result = false;
2470 }
2471 PostfixKind::MemberCall(_, _) => {
2472 is_owned_result = true;
2473 is_mutable = false;
2474 }
2475 PostfixKind::OptionalChainingOperator => {
2476 is_owned_result = true;
2477 is_mutable = false;
2478 }
2479 PostfixKind::VecSubscript(_, _) => {}
2480 PostfixKind::VecSubscriptRange(_, _) => {}
2481 PostfixKind::SparseSubscript(_, _) => {}
2482 PostfixKind::GridSubscript(_, _, _) => {}
2483 PostfixKind::MapSubscript(_, _) => {}
2484 }
2485 }
2486
2487 (is_owned_result, is_mutable)
2488 }
2489
2490 pub fn check_assignment_mode(
2491 &mut self,
2492 lhs_is_mutable: bool,
2493 source_expression: &Expression,
2494 ty: &TypeRef,
2495 ) -> AssignmentMode {
2496 if matches!(
2497 &source_expression.kind,
2498 _ | ExpressionKind::IntrinsicCallEx(_, _)
2499 ) {
2500 return AssignmentMode::OwnedValue;
2501 }
2502
2503 if let ExpressionKind::PostfixChain(start_chain, postfix) = &source_expression.kind {
2511 let (chain_is_owned, chain_is_mutable) =
2512 Self::chain_is_owned_result(start_chain, postfix);
2513 if lhs_is_mutable {
2514 return if chain_is_mutable {
2515 AssignmentMode::CopyBlittable
2516 } else if lhs_is_mutable {
2517 if chain_is_owned {
2518 AssignmentMode::OwnedValue
2519 } else {
2520 AssignmentMode::CopyBlittable
2521 }
2522 } else {
2523 AssignmentMode::CopySharedPtr
2524 };
2525 }
2526 }
2528
2529 AssignmentMode::CopyBlittable
2530 }
2531
2532 pub const fn check_mutable_assignment(&mut self, assignment_mode: AssignmentMode, node: &Node) {}
2533
2534 pub const fn check_mutable_variable_assignment(
2535 &mut self,
2536 source_expression: &swamp_ast::Expression,
2537 ty: &TypeRef,
2538 variable: &swamp_ast::Variable,
2539 ) {
2540 }
2546
2547 pub fn analyze_variable_assignment(
2550 &mut self,
2551 variable: &swamp_ast::Variable,
2552 source_expression: &swamp_ast::Expression,
2553 ) -> Expression {
2554 let maybe_found_variable = self.try_find_variable(&variable.name);
2555
2556 let required_type = maybe_found_variable
2557 .as_ref()
2558 .map(|found_variable| found_variable.resolved_type.clone());
2559
2560 let source_expr = if let Some(target_type) = &required_type {
2561 self.analyze_expression_for_assignment_with_target_type(target_type, source_expression)
2562 } else {
2563 let any_type_context = TypeContext::new_anything_argument(true);
2564 self.analyze_expression(source_expression, &any_type_context)
2565 };
2566
2567 let target_type = if let Some(found_var) = &maybe_found_variable {
2570 &found_var.resolved_type
2571 } else {
2572 &source_expr.ty
2573 };
2574
2575 let should_check_blittable = if let Some(found_var) = &maybe_found_variable {
2577 !matches!(found_var.variable_type, VariableType::Parameter)
2578 } else {
2579 true };
2581
2582 if should_check_blittable && !target_type.is_blittable() {
2583 let debug_text = self.get_text(&variable.name);
2584 if !debug_text.starts_with('_') {
2585 return self.create_err(
2586 ErrorKind::VariableTypeMustBeBlittable(target_type.clone()),
2587 &variable.name,
2588 );
2589 }
2590 }
2591
2592 let kind: ExpressionKind = if let Some(found_var) = maybe_found_variable {
2593 if !found_var.is_mutable() {
2594 return self.create_err(ErrorKind::VariableIsNotMutable, &variable.name);
2595 }
2596 if !self
2597 .types()
2598 .compatible_with(&found_var.resolved_type, &source_expr.ty)
2599 {
2600 return self.create_err(
2601 ErrorKind::IncompatibleTypes {
2602 expected: source_expr.ty,
2603 found: found_var.resolved_type.clone(),
2604 },
2605 &variable.name,
2606 );
2607 }
2608 self.check_mutable_variable_assignment(source_expression, &source_expr.ty, variable);
2609 ExpressionKind::VariableReassignment(found_var, Box::from(source_expr))
2610 } else {
2611 if !source_expr.ty.is_blittable() {
2612 let text = self.get_text(&variable.name);
2613 error!(?text, ?required_type, ?source_expr, "variable is wrong");
2614 }
2615
2616 if variable.is_mutable.is_some() {
2619 self.check_mutable_variable_assignment(
2620 source_expression,
2621 &source_expr.ty,
2622 variable,
2623 );
2624 }
2625 let new_var = self.create_variable(variable, &source_expr.ty);
2626 ExpressionKind::VariableDefinition(new_var, Box::from(source_expr))
2627 };
2628
2629 let unit_type = self.shared.state.types.unit();
2630 self.create_expr(kind, unit_type, &variable.name)
2631 }
2632
2633 fn analyze_create_variable(
2634 &mut self,
2635 var: &swamp_ast::Variable,
2636 annotation_type: Option<&swamp_ast::Type>,
2637 source_expression: &swamp_ast::Expression,
2638 ) -> Expression {
2639 let maybe_annotated_type =
2640 annotation_type.map(|found_ast_type| self.analyze_type(found_ast_type, &TypeAnalyzeContext::default()));
2641
2642 let unsure_arg_context =
2643 TypeContext::new_unsure_argument(maybe_annotated_type.as_ref(), true);
2644
2645 let resolved_source = self.analyze_expression(source_expression, &unsure_arg_context);
2646
2647 let resulting_type = if let Some(annotated_type) = maybe_annotated_type {
2648 annotated_type
2649 } else {
2650 resolved_source.ty.clone()
2651 };
2652 let var_ref = self.create_local_variable(
2653 &var.name,
2654 Option::from(&var.is_mutable),
2655 &resulting_type,
2656 true,
2657 );
2658
2659 if *resulting_type.kind == TypeKind::Unit {
2660 return self.create_err(ErrorKind::VariableTypeMustBeBlittable(resulting_type), &var.name);
2661 }
2662 assert_ne!(&*resulting_type.kind, &TypeKind::Unit);
2663 let kind = ExpressionKind::VariableDefinition(var_ref, Box::from(resolved_source));
2664
2665 let unit_type = self.shared.state.types.unit();
2666
2667 self.create_expr(kind, unit_type, &var.name)
2668 }
2669
2670 fn add_location_item(
2671 &mut self,
2672 vec: &mut Vec<LocationAccess>,
2673 kind: LocationAccessKind,
2674 ty: TypeRef,
2675 ast_node: &swamp_ast::Node,
2676 ) {
2677 let resolved_node = self.to_node(ast_node);
2678 let postfix = LocationAccess {
2679 node: resolved_node,
2680 ty,
2681 kind,
2682 };
2683
2684 vec.push(postfix);
2685 }
2686
2687 fn extract_single_intrinsic_call(
2688 body: &Expression,
2689 ) -> Option<(IntrinsicFunction, Vec<ArgumentExpression>)> {
2690 if let ExpressionKind::Block(expressions) = &body.kind {
2691 let first_kind = &expressions[0].kind;
2692 if let ExpressionKind::IntrinsicCallEx(intrinsic_fn, args) = &first_kind {
2693 return Some((intrinsic_fn.clone(), args.clone()));
2694 }
2695 }
2696 None
2697 }
2698
2699 #[allow(clippy::too_many_lines)]
2700 fn analyze_chain_to_location(
2701 &mut self,
2702 chain: &swamp_ast::PostfixChain,
2703 context: &TypeContext,
2704 location_side: LocationSide,
2705 ) -> SingleLocationExpression {
2706 let mut items = Vec::new();
2707
2708 let nothing_context = TypeContext::new(None, true);
2709
2710 let base_expr = self.analyze_expression(&chain.base, ¬hing_context);
2711 let ExpressionKind::VariableAccess(start_variable) = base_expr.kind else {
2712 self.add_err(ErrorKind::NotValidLocationStartingPoint, &chain.base.node);
2713 let unit_type = self.types().unit();
2714 let err_variable = Variable {
2715 name: Default::default(),
2716 assigned_name: String::new(),
2717 resolved_type: unit_type,
2718 mutable_node: None,
2719 variable_type: VariableType::Local,
2720 scope_index: 0,
2721 variable_index: 0,
2722 unique_id_within_function: 0,
2723 virtual_register: 0,
2724 is_unused: false,
2725 };
2726 return SingleLocationExpression {
2727 kind: MutableReferenceKind::MutVariableRef,
2728 node: self.to_node(&chain.base.node),
2729 ty: self.shared.state.types.unit(),
2730 starting_variable: VariableRef::from(err_variable),
2731 access_chain: vec![],
2732 };
2733 };
2734
2735 if !start_variable.is_mutable() {
2736 self.add_err(ErrorKind::VariableIsNotMutable, &chain.base.node);
2737
2738 let unit_type = self.types().unit();
2739 let err_variable = Variable {
2740 name: Default::default(),
2741 assigned_name: String::new(),
2742 resolved_type: unit_type,
2743 mutable_node: None,
2744 variable_type: VariableType::Local,
2745 scope_index: 0,
2746 variable_index: 0,
2747 unique_id_within_function: 0,
2748 virtual_register: 0,
2749 is_unused: false,
2750 };
2751 return SingleLocationExpression {
2752 kind: MutableReferenceKind::MutVariableRef,
2753 node: self.to_node(&chain.base.node),
2754 ty: self.shared.state.types.unit(),
2755 starting_variable: VariableRef::from(err_variable),
2756 access_chain: vec![],
2757 };
2758 }
2759
2760 let mut ty = start_variable.resolved_type.clone();
2761 for (i, item) in chain.postfixes.iter().enumerate() {
2762 let is_absolute_last_in_chain = i == chain.postfixes.len() - 1;
2763 match &item {
2764 swamp_ast::Postfix::FieldAccess(field_name_node) => {
2765 let (struct_type_ref, index, return_type) =
2767 self.analyze_struct_field(field_name_node, &ty);
2768
2769 self.add_location_item(
2770 &mut items,
2771 LocationAccessKind::FieldIndex(struct_type_ref.clone(), index),
2772 return_type.clone(),
2773 field_name_node,
2774 );
2775
2776 ty = return_type.clone();
2777 }
2778 swamp_ast::Postfix::SubscriptTuple(x_expr, y_expr) => match &*ty.kind {
2779 TypeKind::GridView(element_type)
2780 | TypeKind::GridStorage(element_type, _, _) => {
2781 let int_type = self.types().int();
2782 let unsigned_int_context = TypeContext::new_argument(&int_type, true);
2783 let unsigned_int_x_expr =
2784 self.analyze_expression(x_expr, &unsigned_int_context);
2785
2786 let unsigned_int_y_expr =
2787 self.analyze_expression(y_expr, &unsigned_int_context);
2788
2789 let grid_type = GridType {
2790 element: element_type.clone(),
2791 };
2792
2793 self.add_location_item(
2794 &mut items,
2795 LocationAccessKind::GridSubscript(
2796 grid_type,
2797 unsigned_int_x_expr,
2798 unsigned_int_y_expr,
2799 ),
2800 element_type.clone(),
2801 &x_expr.node,
2802 );
2803
2804 ty = element_type.clone();
2805 }
2806 _ => {
2807 self.add_err_resolved(ErrorKind::CanNotSubscriptWithThatType, &base_expr.node);
2808
2809 return SingleLocationExpression {
2810 kind: MutableReferenceKind::MutVariableRef,
2811 node: Default::default(),
2812 ty,
2813 starting_variable: Rc::new(Variable {
2814 name: Default::default(),
2815 assigned_name: String::new(),
2816 resolved_type: Rc::new(Type {
2817 id: TypeId::new(0),
2818 flags: Default::default(),
2819 kind: Rc::new(TypeKind::Byte),
2820 }),
2821 mutable_node: None,
2822 variable_type: VariableType::Local,
2823 scope_index: 0,
2824 variable_index: 0,
2825 unique_id_within_function: 0,
2826 virtual_register: 0,
2827 is_unused: false,
2828 }),
2829 access_chain: vec![],
2830 };
2831 }
2832 },
2833 swamp_ast::Postfix::Subscript(ast_key_expression) => {
2834 let underlying = &ty.kind;
2835 match &**underlying {
2836 TypeKind::SliceView(element_type)
2837 | TypeKind::StackStorage(element_type, _)
2838 | TypeKind::StackView(element_type)
2839 | TypeKind::VecStorage(element_type, _)
2840 | TypeKind::DynamicLengthVecView(element_type)
2841 | TypeKind::FixedCapacityAndLengthArray(element_type, _) => {
2842 let int_type = self.types().int();
2843 let unsigned_int_context = TypeContext::new_argument(&int_type, false);
2844 let unsigned_int_expr =
2845 self.analyze_expression(ast_key_expression, &unsigned_int_context);
2846
2847 let slice_type = SliceViewType {
2848 element: element_type.clone(),
2849 };
2850
2851 self.add_location_item(
2852 &mut items,
2853 LocationAccessKind::SliceViewSubscript(
2854 slice_type,
2855 unsigned_int_expr,
2856 ),
2857 element_type.clone(),
2858 &ast_key_expression.node,
2859 );
2860
2861 ty = element_type.clone();
2862 }
2863 TypeKind::SparseView(element_type)
2864 | TypeKind::SparseStorage(element_type, _) => {
2865 let int_type = self.types().int();
2866 let unsigned_int_context = TypeContext::new_argument(&int_type, false);
2867 let unsigned_int_expr =
2868 self.analyze_expression(ast_key_expression, &unsigned_int_context);
2869
2870 let slice_type = SparseType {
2871 element: element_type.clone(),
2872 };
2873
2874 self.add_location_item(
2875 &mut items,
2876 LocationAccessKind::SparseSubscript(slice_type, unsigned_int_expr),
2877 element_type.clone(),
2878 &ast_key_expression.node,
2879 );
2880
2881 ty = element_type.clone();
2882 }
2883 TypeKind::MapStorage(key_type, value_type, ..)
2884 | TypeKind::DynamicLengthMapView(key_type, value_type) => {
2885 let key_index_context = TypeContext::new_argument(key_type, false);
2886 let key_expr =
2887 self.analyze_expression(ast_key_expression, &key_index_context);
2888
2889 let map_like_type = MapType {
2890 key: key_type.clone(),
2891 value: value_type.clone(),
2892 };
2893
2894 match location_side {
2895 LocationSide::Lhs => {
2896 let access_kind = if is_absolute_last_in_chain {
2900 LocationAccessKind::MapSubscriptCreateIfNeeded(
2901 map_like_type,
2902 key_expr,
2903 )
2904 } else {
2905 LocationAccessKind::MapSubscriptMustExist(
2906 map_like_type,
2907 key_expr,
2908 )
2909 };
2910
2911 self.add_location_item(
2912 &mut items,
2913 access_kind,
2914 value_type.clone(),
2915 &ast_key_expression.node,
2916 );
2917 }
2918 LocationSide::Mutable | LocationSide::Rhs => {
2919 self.add_location_item(
2920 &mut items,
2921 LocationAccessKind::MapSubscriptMustExist(
2922 map_like_type,
2923 key_expr,
2924 ),
2925 value_type.clone(),
2926 &ast_key_expression.node,
2927 );
2928 }
2929 }
2930 ty = value_type.clone();
2931 }
2932
2933 _ => {
2934 self.add_err_resolved(ErrorKind::CanNotSubscriptWithThatType, &base_expr.node);
2935
2936 return SingleLocationExpression {
2937 kind: MutableReferenceKind::MutVariableRef,
2938 node: Default::default(),
2939 ty,
2940 starting_variable: Rc::new(Variable {
2941 name: Default::default(),
2942 assigned_name: String::new(),
2943 resolved_type: Rc::new(Type {
2944 id: TypeId::new(0),
2945 flags: Default::default(),
2946 kind: Rc::new(TypeKind::Byte),
2947 }),
2948 mutable_node: None,
2949 variable_type: VariableType::Local,
2950 scope_index: 0,
2951 variable_index: 0,
2952 unique_id_within_function: 0,
2953 virtual_register: 0,
2954 is_unused: false,
2955 }),
2956 access_chain: vec![],
2957 };
2958 }
2959 }
2960 }
2961
2962 swamp_ast::Postfix::MemberCall(node, _generic_arguments, _regular_args) => {
2963 return SingleLocationExpression {
2964 kind: MutableReferenceKind::MutVariableRef,
2965 node: self.to_node(node),
2966 ty: self.shared.state.types.unit(),
2967 starting_variable: start_variable,
2968 access_chain: vec![],
2969 };
2970 }
2971 swamp_ast::Postfix::FunctionCall(node, _generic_arguments, _regular_args) => {
2978 return SingleLocationExpression {
2979 kind: MutableReferenceKind::MutVariableRef,
2980 node: self.to_node(node),
2981 ty: self.shared.state.types.unit(),
2982 starting_variable: start_variable,
2983 access_chain: vec![],
2984 };
2985 }
2986 swamp_ast::Postfix::OptionalChainingOperator(node) => {
2987 return SingleLocationExpression {
2988 kind: MutableReferenceKind::MutVariableRef,
2989 node: self.to_node(node),
2990 ty: self.shared.state.types.unit(),
2991 starting_variable: start_variable,
2992 access_chain: vec![],
2993 };
2994 }
2995 }
2996 }
2997
2998 if let Some(found_expected_type) = context.expected_type
2999 && !self.types().compatible_with(found_expected_type, &ty) {
3000 self.add_err(
3001 ErrorKind::IncompatibleTypes {
3002 expected: found_expected_type.clone(),
3003 found: ty.clone(),
3004 },
3005 &chain.base.node,
3006 );
3007 }
3008
3009 SingleLocationExpression {
3010 kind: MutableReferenceKind::MutVariableRef,
3011 node: self.to_node(&chain.base.node),
3012 ty,
3013 starting_variable: start_variable,
3014 access_chain: items,
3015 }
3016 }
3017
3018 fn analyze_to_location(
3019 &mut self,
3020 expr: &swamp_ast::Expression,
3021 context: &TypeContext,
3022 location_type: LocationSide,
3023 ) -> SingleLocationExpression {
3024 match &expr.kind {
3025 swamp_ast::ExpressionKind::PostfixChain(chain) => {
3026 self.analyze_chain_to_location(chain, context, location_type)
3027 }
3028 swamp_ast::ExpressionKind::VariableReference(variable) => {
3029 let var = self.find_variable(variable);
3030 if !var.is_mutable() {
3031 self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
3032 }
3033
3034 SingleLocationExpression {
3035 kind: MutableReferenceKind::MutVariableRef,
3036 node: self.to_node(&variable.name),
3037 ty: var.resolved_type.clone(),
3038 starting_variable: var,
3039 access_chain: vec![],
3040 }
3041 }
3042 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
3043 let generated_var = swamp_ast::Variable {
3044 name: qualified_identifier.name.clone(),
3045 is_mutable: None,
3046 };
3047 let var = self.find_variable(&generated_var);
3048 if !var.is_mutable() {
3049 self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
3050 }
3051 SingleLocationExpression {
3052 kind: MutableReferenceKind::MutVariableRef,
3053 node: self.to_node(&generated_var.name),
3054 ty: var.resolved_type.clone(),
3055 starting_variable: var,
3056 access_chain: vec![],
3057 }
3058 }
3059 _ => {
3060 self.add_err(ErrorKind::NotValidLocationStartingPoint, &expr.node);
3061 let unit_type = self.types().unit();
3062 SingleLocationExpression {
3063 kind: MutableReferenceKind::MutVariableRef,
3064 node: self.to_node(&expr.node),
3065 ty: unit_type.clone(),
3066 starting_variable: Rc::new(Variable {
3067 name: Default::default(),
3068 assigned_name: String::new(),
3069 resolved_type: unit_type,
3070 mutable_node: None,
3071 variable_type: VariableType::Local,
3072 scope_index: 0,
3073 variable_index: 0,
3074 unique_id_within_function: 0,
3075 virtual_register: 0,
3076 is_unused: false,
3077 }),
3078 access_chain: vec![],
3079 }
3080 }
3081 }
3082 }
3083
3084 fn analyze_expression_for_assignment_compound(
3085 &mut self,
3086 target_expression: &swamp_ast::Expression,
3087 ast_source_expression: &swamp_ast::Expression,
3088 ) -> (TargetAssignmentLocation, Expression) {
3089 let any_argument_context = TypeContext::new_anything_argument(true);
3090 let source_expr = self.analyze_expression(ast_source_expression, &any_argument_context);
3091 let source_expr_type_context = TypeContext::new_argument(&source_expr.ty, true);
3092
3093 let resolved_location = TargetAssignmentLocation(self.analyze_to_location(
3094 target_expression,
3095 &source_expr_type_context,
3096 LocationSide::Rhs,
3097 ));
3098
3099 (resolved_location, source_expr)
3100 }
3101
3102 fn analyze_expression_for_assignment_with_target_type(
3129 &mut self,
3130 target_type: &TypeRef,
3131 ast_source_expression: &swamp_ast::Expression,
3132 ) -> Expression {
3133 let base_context = TypeContext::new_argument(target_type, true);
3134 let source_expr = self.analyze_expression(ast_source_expression, &base_context);
3135
3136 let final_expr = if self.types().compatible_with(target_type, &source_expr.ty) {
3137 source_expr
3138 } else {
3139 let source_type = source_expr.ty.clone();
3140 self.types_did_not_match_try_late_coerce_expression(
3141 source_expr,
3142 target_type,
3143 &source_type,
3144 &ast_source_expression.node,
3145 )
3146 };
3147
3148 let assignment_mode = self.check_assignment_mode(true, &final_expr, target_type); self.check_mutable_assignment(assignment_mode, &final_expr.node);
3151
3152 final_expr
3153 }
3154
3155 fn analyze_expression_for_assignment(
3156 &mut self,
3157 ast_target_location_expression: &swamp_ast::Expression,
3158 ast_source_expression: &swamp_ast::Expression,
3159 ) -> (TargetAssignmentLocation, Expression) {
3160 let any_argument_context = TypeContext::new_anything_argument(true);
3161 let resolved_location = self.analyze_to_location(
3162 ast_target_location_expression,
3163 &any_argument_context,
3164 LocationSide::Lhs,
3165 );
3166
3167 let target_type = resolved_location.ty.clone();
3168 let mut_type = target_type; let mut_location = TargetAssignmentLocation(resolved_location);
3170
3171 let final_expr = self
3172 .analyze_expression_for_assignment_with_target_type(&mut_type, ast_source_expression);
3173
3174 (mut_location, final_expr)
3175 }
3176
3177 fn analyze_assignment_compound(
3178 &mut self,
3179 target_expression: &swamp_ast::Expression,
3180 ast_op: &swamp_ast::CompoundOperator,
3181 ast_source_expression: &swamp_ast::Expression,
3182 ) -> Expression {
3183 let resolved_op = self.analyze_compound_operator(ast_op);
3184
3185 let (resolved_location, source_expr) = self
3186 .analyze_expression_for_assignment_compound(target_expression, ast_source_expression);
3187
3188 let kind = ExpressionKind::CompoundAssignment(
3189 resolved_location,
3190 resolved_op.kind,
3191 Box::from(source_expr),
3192 );
3193
3194 let unit_type = self.shared.state.types.unit();
3195
3196 self.create_expr(kind, unit_type, &target_expression.node)
3197 }
3198
3199 fn analyze_assignment_mode(lhs: SingleLocationExpression) {}
3200
3201 fn analyze_assignment(
3202 &mut self,
3203 target_location: &swamp_ast::Expression,
3204 ast_source_expression: &swamp_ast::Expression,
3205 ) -> Expression {
3206 let (mut_location, source_expr) =
3207 self.analyze_expression_for_assignment(target_location, ast_source_expression);
3208 let kind = ExpressionKind::Assignment(Box::from(mut_location), Box::from(source_expr));
3209 let unit_type = self.shared.state.types.unit();
3210
3211 self.create_expr(kind, unit_type, &target_location.node)
3214 }
3215
3216 #[must_use]
3217 pub const fn create_expr(
3218 &self,
3219 kind: ExpressionKind,
3220 ty: TypeRef,
3221 ast_node: &swamp_ast::Node,
3222 ) -> Expression {
3223 Expression {
3225 kind,
3226 ty,
3227 node: self.to_node(ast_node),
3228 }
3229 }
3230
3231 fn analyze_destructuring(
3232 &mut self,
3233 node: &swamp_ast::Node,
3234 target_ast_variables: &[swamp_ast::Variable],
3235 tuple_expression: &swamp_ast::Expression,
3236 ) -> Expression {
3237 let any_context = TypeContext::new_anything_argument(true);
3238 let tuple_resolved = self.analyze_expression(tuple_expression, &any_context);
3239 let tuple_expr_type = &tuple_resolved.ty;
3240 let unit = self.types().unit();
3241
3242 let mut variable_refs = Vec::new();
3243 if let TypeKind::Tuple(tuple) = &*tuple_expr_type.kind {
3244 if target_ast_variables.len() > tuple.len() {
3245 return self.create_err(ErrorKind::TooManyDestructureVariables, node);
3246 }
3247 for (ast_variable, tuple_type) in target_ast_variables.iter().zip(tuple.clone()) {
3248 let variable_ref = self.create_local_variable(
3249 &ast_variable.name,
3250 ast_variable.is_mutable.as_ref(),
3251 &tuple_type,
3252 true,
3253 );
3254 variable_refs.push(variable_ref);
3255 }
3256 let expr_kind = ExpressionKind::TupleDestructuring(
3257 variable_refs,
3258 tuple_expr_type.clone(),
3259 Box::from(tuple_resolved),
3260 );
3261
3262 self.create_expr(expr_kind, unit, node)
3263 } else {
3264 self.create_err(ErrorKind::CanNotDestructure, node)
3265 }
3266 }
3267
3268 fn analyze_normal_member_call(
3269 &mut self,
3270 type_that_member_is_on: &TypeRef,
3271 found_function: &FunctionRef,
3272 generic_arguments: Vec<TypeRef>,
3273 ast_arguments: &[swamp_ast::Expression],
3274 is_mutable: bool,
3275 node: &swamp_ast::Node,
3276 ) -> Signature {
3277 let resolved_node = self.to_node(node);
3278 found_function.signature().clone()
3281 }
3282
3283 fn queue_member_signature(
3284 &mut self,
3285 self_type: &TypeRef,
3286 key_type: Option<&TypeRef>,
3287 element_type: &TypeRef,
3288 field_name_str: &str,
3289 lambda_variable_count: usize,
3290 node: &swamp_ast::Node,
3291 ) -> Option<(IntrinsicFunction, Signature)> {
3292 let self_type_param = TypeForParameter {
3293 name: "self".to_string(),
3294 resolved_type: self_type.clone(),
3295 is_mutable: false,
3296 node: None,
3297 };
3298 let self_mutable_type_param = TypeForParameter {
3299 name: "self".to_string(),
3300 resolved_type: self_type.clone(),
3301 is_mutable: true,
3302 node: None,
3303 };
3304 let intrinsic_and_signature = match field_name_str {
3305 "enqueue" => (
3306 IntrinsicFunction::VecPush,
3307 Signature {
3308 parameters: vec![
3309 self_mutable_type_param,
3310 TypeForParameter {
3311 name: "element".to_string(),
3312 resolved_type: element_type.clone(),
3313 is_mutable: false,
3314 node: None,
3315 },
3316 ],
3317 return_type: self.types().unit(),
3318 },
3319 ),
3320 "dequeue" => (
3321 IntrinsicFunction::VecRemoveFirstIndexGetValue,
3322 Signature {
3323 parameters: vec![self_mutable_type_param],
3324 return_type: element_type.clone(),
3325 },
3326 ),
3327 _ => {
3328 self.slice_member_signature(
3329 self_type,
3330 key_type,
3331 element_type,
3332 field_name_str,
3333 lambda_variable_count,
3334 node,
3335 )
3336 }?,
3337 };
3338
3339 Some(intrinsic_and_signature)
3340 }
3341
3342 fn sparse_member_signature(
3343 &mut self,
3344 self_type: &TypeRef,
3345 element_type: &TypeRef,
3346 field_name_str: &str,
3347 lambda_variable_count: usize,
3348 node: &swamp_ast::Node,
3349 ) -> Option<(IntrinsicFunction, Signature)> {
3350 let key_type = self.types().int(); let self_type_param = TypeForParameter {
3353 name: "self".to_string(),
3354 resolved_type: self_type.clone(),
3355 is_mutable: false,
3356 node: None,
3357 };
3358 let self_mutable_type_param = TypeForParameter {
3359 name: "self".to_string(),
3360 resolved_type: self_type.clone(),
3361 is_mutable: true,
3362 node: None,
3363 };
3364 let intrinsic_and_signature = match field_name_str {
3365 "add" => (
3366 IntrinsicFunction::SparseAdd,
3367 Signature {
3368 parameters: vec![
3369 self_mutable_type_param,
3370 TypeForParameter {
3371 name: "element".to_string(),
3372 resolved_type: element_type.clone(),
3373 is_mutable: false,
3374 node: None,
3375 },
3376 ],
3377 return_type: self.types().int(),
3378 },
3379 ),
3380 "remove" => (
3381 IntrinsicFunction::SparseRemove,
3382 Signature {
3383 parameters: vec![
3384 self_mutable_type_param,
3385 TypeForParameter {
3386 name: "key".to_string(),
3387 resolved_type: key_type,
3388 is_mutable: false,
3389 node: None,
3390 },
3391 ],
3392 return_type: self.types().unit(),
3393 },
3394 ),
3395 "is_alive" => (
3396 IntrinsicFunction::SparseIsAlive,
3397 Signature {
3398 parameters: vec![
3399 self_type_param,
3400 TypeForParameter {
3401 name: "element".to_string(),
3402 resolved_type: element_type.clone(),
3403 is_mutable: false,
3404 node: None,
3405 },
3406 ],
3407 return_type: self.types().bool(),
3408 },
3409 ),
3410
3411 _ => {
3412 self.slice_member_signature(
3413 self_type,
3414 Option::from(key_type).as_ref(),
3415 element_type,
3416 field_name_str,
3417 lambda_variable_count,
3418 node,
3419 )
3420 }?,
3421 };
3422 Some(intrinsic_and_signature)
3423 }
3424
3425 fn vec_member_signature(
3426 &mut self,
3427 self_type: &TypeRef,
3428 element_type: &TypeRef,
3429 field_name_str: &str,
3430 lambda_variable_count: usize,
3431 node: &swamp_ast::Node,
3432 ) -> Option<(IntrinsicFunction, Signature)> {
3433 let key_type = self.types().int();
3434 let self_type_param = TypeForParameter {
3435 name: "self".to_string(),
3436 resolved_type: self_type.clone(),
3437 is_mutable: false,
3438 node: None,
3439 };
3440 let self_mutable_type_param = TypeForParameter {
3441 name: "self".to_string(),
3442 resolved_type: self_type.clone(),
3443 is_mutable: true,
3444 node: None,
3445 };
3446 let intrinsic_and_signature = match field_name_str {
3447 "prepend" => (
3448 IntrinsicFunction::VecPush,
3449 Signature {
3450 parameters: vec![
3451 self_mutable_type_param,
3452 TypeForParameter {
3453 name: "element".to_string(),
3454 resolved_type: element_type.clone(),
3455 is_mutable: false,
3456 node: None,
3457 },
3458 ],
3459 return_type: self.types().unit(),
3460 },
3461 ),
3462 "push" => (
3463 IntrinsicFunction::VecPush,
3464 Signature {
3465 parameters: vec![
3466 self_mutable_type_param,
3467 TypeForParameter {
3468 name: "element".to_string(),
3469 resolved_type: element_type.clone(),
3470 is_mutable: false,
3471 node: None,
3472 },
3473 ],
3474 return_type: self.types().unit(),
3475 },
3476 ),
3477 "pop" => (
3478 IntrinsicFunction::VecPop,
3479 Signature {
3480 parameters: vec![self_mutable_type_param],
3481 return_type: element_type.clone(),
3482 },
3483 ),
3484
3485 "slice" => {
3486 let range_type = self.types().range_int();
3487 (
3488 IntrinsicFunction::VecSlice,
3489 Signature {
3490 parameters: vec![self_type_param,
3491 TypeForParameter {
3492 name: "range".to_string(),
3493 resolved_type: range_type,
3494 is_mutable: false,
3495 node: None,
3496 }, ],
3497 return_type: self_type.clone(),
3498 },
3499 )
3500 }
3501
3502 _ => {
3503 self.slice_member_signature(
3504 self_type,
3505 Option::from(key_type).as_ref(),
3506 element_type,
3507 field_name_str,
3508 lambda_variable_count,
3509 node,
3510 )
3511 }?,
3512 };
3513 Some(intrinsic_and_signature)
3514 }
3515
3516 #[allow(clippy::unnecessary_wraps)]
3517 fn grid_member_signature(
3518 &mut self,
3519 self_type: &TypeRef,
3520 element_type: &TypeRef,
3521 field_name_str: &str,
3522 node: &swamp_ast::Node,
3523 ) -> Option<(IntrinsicFunction, Signature)> {
3524 let self_type_param = TypeForParameter {
3525 name: "self".to_string(),
3526 resolved_type: self_type.clone(),
3527 is_mutable: false,
3528 node: None,
3529 };
3530 let self_mutable_type_param = TypeForParameter {
3531 name: "self".to_string(),
3532 resolved_type: self_type.clone(),
3533 is_mutable: true,
3534 node: None,
3535 };
3536 let element_param = TypeForParameter {
3537 name: "element".to_string(),
3538 resolved_type: element_type.clone(),
3539 is_mutable: false,
3540 node: None,
3541 };
3542 let int_type = self.types().int();
3543
3544 let int_param = TypeForParameter {
3545 name: "x_or_y".to_string(),
3546 resolved_type: int_type.clone(),
3547 is_mutable: false,
3548 node: None,
3549 };
3550 let intrinsic_and_signature = match field_name_str {
3551 "set" => (
3552 IntrinsicFunction::GridSet,
3553 Signature {
3554 parameters: vec![self_type_param, int_param.clone(), int_param, element_param],
3555 return_type: self.types().unit(),
3556 },
3557 ),
3558
3559 "get" => (
3560 IntrinsicFunction::GridGet,
3561 Signature {
3562 parameters: vec![self_type_param, int_param.clone(), int_param],
3563 return_type: element_type.clone(),
3564 },
3565 ),
3566
3567 "width" => (
3568 IntrinsicFunction::GridWidth,
3569 Signature {
3570 parameters: vec![self_type_param],
3571 return_type: int_type,
3572 },
3573 ),
3574
3575 "height" => (
3576 IntrinsicFunction::GridHeight,
3577 Signature {
3578 parameters: vec![self_type_param],
3579 return_type: int_type,
3580 },
3581 ),
3582
3583 _ => panic!("unknown grid method {field_name_str}"),
3584 };
3585
3586 Some(intrinsic_and_signature)
3587 }
3588
3589 fn basic_collection_member_signature(
3590 &mut self,
3591 self_type: &TypeRef,
3592 field_name_str: &str,
3593 node: &swamp_ast::Node,
3594 ) -> Option<(IntrinsicFunction, Signature)> {
3595 let self_type_param = TypeForParameter {
3596 name: "self".to_string(),
3597 resolved_type: self_type.clone(),
3598 is_mutable: false,
3599 node: None,
3600 };
3601 let self_mut_type_param = TypeForParameter {
3602 name: "self".to_string(),
3603 resolved_type: self_type.clone(),
3604 is_mutable: true,
3605 node: None,
3606 };
3607 let intrinsic_and_signature = match field_name_str {
3608 "len" => {
3609 let signature = Signature {
3610 parameters: vec![self_type_param],
3611 return_type: self.types().int(),
3612 };
3613 (IntrinsicFunction::VecLen, signature)
3614 }
3615 "is_empty" => (
3616 IntrinsicFunction::VecIsEmpty,
3617 Signature {
3618 parameters: vec![self_type_param],
3619 return_type: self.types().bool(),
3620 },
3621 ),
3622 "clear" => {
3623 let signature = Signature {
3624 parameters: vec![self_mut_type_param],
3625 return_type: self.types().unit(),
3626 };
3627 (IntrinsicFunction::VecClear, signature)
3628 }
3629 "capacity" => {
3630 let signature = Signature {
3631 parameters: vec![self_type_param],
3632 return_type: self.types().int(),
3633 };
3634 (IntrinsicFunction::VecCapacity, signature)
3635 }
3636 _ => {
3637 self.add_err(ErrorKind::UnknownMemberFunction(self_type.clone()), node);
3638
3639 return None;
3640 }
3641 };
3642 Some(intrinsic_and_signature)
3643 }
3644 #[allow(clippy::too_many_lines)]
3645 fn codepoint_member_signature(
3646 &mut self,
3647 self_type: &TypeRef,
3648 key_type: Option<&TypeRef>,
3649 element_type: &TypeRef,
3650 field_name_str: &str,
3651 lambda_variable_count: usize,
3652 node: &swamp_ast::Node,
3653 ) -> Option<(IntrinsicFunction, Signature)> {
3654 let self_type_param = TypeForParameter {
3655 name: "self".to_string(),
3656 resolved_type: self_type.clone(),
3657 is_mutable: false,
3658 node: None,
3659 };
3660
3661 match field_name_str {
3662 "to_int" => Some((
3663 IntrinsicFunction::CodepointToInt,
3664 Signature {
3665 parameters: vec![self_type_param],
3666 return_type: self.types().int(),
3667 },
3668 )),
3669 _ => None,
3670 }
3671 }
3672
3673 #[allow(clippy::too_many_lines)]
3674 fn byte_member_signature(
3675 &mut self,
3676 self_type: &TypeRef,
3677 key_type: Option<&TypeRef>,
3678 element_type: &TypeRef,
3679 field_name_str: &str,
3680 lambda_variable_count: usize,
3681 node: &swamp_ast::Node,
3682 ) -> Option<(IntrinsicFunction, Signature)> {
3683 let self_type_param = TypeForParameter {
3684 name: "self".to_string(),
3685 resolved_type: self_type.clone(),
3686 is_mutable: false,
3687 node: None,
3688 };
3689
3690 match field_name_str {
3691 "to_int" => Some((
3692 IntrinsicFunction::ByteToInt,
3693 Signature {
3694 parameters: vec![self_type_param],
3695 return_type: self.types().int(),
3696 },
3697 )),
3698 _ => None,
3699 }
3700 }
3701
3702 #[allow(clippy::too_many_lines)]
3703 fn string_member_signature(
3704 &mut self,
3705 self_type: &TypeRef,
3706 key_type: Option<&TypeRef>,
3707 element_type: &TypeRef,
3708 field_name_str: &str,
3709 lambda_variable_count: usize,
3710 node: &swamp_ast::Node,
3711 ) -> Option<(IntrinsicFunction, Signature)> {
3712 self.vec_member_signature(
3713 self_type,
3714 element_type,
3715 field_name_str,
3716 lambda_variable_count,
3717 node,
3718 )
3719 }
3720
3721 #[allow(clippy::too_many_lines)]
3722 fn slice_member_signature(
3723 &mut self,
3724 self_type: &TypeRef,
3725 key_type: Option<&TypeRef>,
3726 element_type: &TypeRef,
3727 field_name_str: &str,
3728 lambda_variable_count: usize,
3729 node: &swamp_ast::Node,
3730 ) -> Option<(IntrinsicFunction, Signature)> {
3731 let slice_view_type = self.types().slice_view(&element_type.clone());
3732 let int_type = self.types().int();
3733 let self_type_param = TypeForParameter {
3734 name: "self".to_string(),
3735 resolved_type: slice_view_type.clone(),
3736 is_mutable: false,
3737 node: None,
3738 };
3739 let self_mut_type_param = TypeForParameter {
3740 name: "self".to_string(),
3741 resolved_type: slice_view_type,
3742 is_mutable: true,
3743 node: None,
3744 };
3745 let intrinsic_and_signature = match field_name_str {
3746 "for" => {
3747 let parameters = if lambda_variable_count == 2 {
3748 vec![
3749 TypeForParameter {
3750 name: "key".to_string(),
3751 resolved_type: key_type.unwrap().clone(),
3752 is_mutable: false,
3753 node: None,
3754 },
3755 TypeForParameter {
3756 name: "element".to_string(),
3757 resolved_type: element_type.clone(),
3758 is_mutable: false,
3759 node: None,
3760 },
3761 ]
3762 } else {
3763 vec![TypeForParameter {
3764 name: "element".to_string(),
3765 resolved_type: element_type.clone(),
3766 is_mutable: false,
3767 node: None,
3768 }]
3769 };
3770 let lambda_signature = Signature {
3771 parameters,
3772 return_type: self.types().unit(),
3773 };
3774 let lambda_function_type = self.types().function(lambda_signature);
3775 (
3776 IntrinsicFunction::TransformerFor,
3777 Signature {
3778 parameters: vec![
3779 self_type_param,
3780 TypeForParameter {
3781 name: "lambda".to_string(),
3782 resolved_type: lambda_function_type,
3783 is_mutable: false,
3784 node: None,
3785 },
3786 ],
3787 return_type: self.types().unit(), },
3789 )
3790 }
3791 "while" => {
3792 let parameters = if lambda_variable_count == 2 {
3793 vec![
3794 TypeForParameter {
3795 name: "key".to_string(),
3796 resolved_type: key_type.unwrap().clone(),
3797 is_mutable: false,
3798 node: None,
3799 },
3800 TypeForParameter {
3801 name: "element".to_string(),
3802 resolved_type: element_type.clone(),
3803 is_mutable: false,
3804 node: None,
3805 },
3806 ]
3807 } else {
3808 vec![TypeForParameter {
3809 name: "element".to_string(),
3810 resolved_type: element_type.clone(),
3811 is_mutable: false,
3812 node: None,
3813 }]
3814 };
3815 let lambda_signature = Signature {
3816 parameters,
3817 return_type: self.types().bool(), };
3819 let lambda_function_type = self.types().function(lambda_signature);
3820 (
3821 IntrinsicFunction::TransformerWhile,
3822 Signature {
3823 parameters: vec![
3824 self_type_param,
3825 TypeForParameter {
3826 name: "lambda".to_string(),
3827 resolved_type: lambda_function_type,
3828 is_mutable: false,
3829 node: None,
3830 },
3831 ],
3832 return_type: self.types().unit(), },
3834 )
3835 }
3836 "filter" => {
3837 let lambda_signature = Signature {
3838 parameters: vec![TypeForParameter {
3839 name: "element".to_string(),
3840 resolved_type: element_type.clone(),
3841 is_mutable: false,
3842 node: None,
3843 }],
3844 return_type: self.types().bool(),
3845 };
3846 let lambda_function_type = self.types().function(lambda_signature);
3847 (
3848 IntrinsicFunction::TransformerFilter,
3849 Signature {
3850 parameters: vec![
3851 self_type_param,
3852 TypeForParameter {
3853 name: "lambda".to_string(),
3854 resolved_type: lambda_function_type,
3855 is_mutable: false,
3856 node: None,
3857 },
3858 ],
3859 return_type: self.shared.state.types.slice_view(&element_type.clone()),
3860 },
3861 )
3862 }
3863 "find" => {
3864 let lambda_signature = Signature {
3865 parameters: vec![TypeForParameter {
3866 name: "element".to_string(),
3867 resolved_type: element_type.clone(),
3868 is_mutable: false,
3869 node: None,
3870 }],
3871 return_type: self.types().bool(),
3872 };
3873 let lambda_function_type = self.types().function(lambda_signature);
3874 (
3875 IntrinsicFunction::TransformerFind,
3876 Signature {
3877 parameters: vec![
3878 self_type_param,
3879 TypeForParameter {
3880 name: "lambda".to_string(),
3881 resolved_type: lambda_function_type,
3882 is_mutable: false,
3883 node: None,
3884 },
3885 ],
3886 return_type: self.shared.state.types.optional(&element_type.clone()),
3887 },
3888 )
3889 }
3890
3891 "remove" => {
3892 let signature = Signature {
3893 parameters: vec![
3894 self_mut_type_param,
3895 TypeForParameter {
3896 name: "index".to_string(),
3897 resolved_type: int_type,
3898 is_mutable: false,
3899 node: None,
3900 },
3901 ],
3902 return_type: self.types().unit(),
3903 };
3904 (IntrinsicFunction::VecRemoveIndex, signature)
3905 }
3906 _ => return self.basic_collection_member_signature(self_type, field_name_str, node),
3907 };
3908 Some(intrinsic_and_signature)
3909 }
3910
3911 #[allow(clippy::unnecessary_wraps, clippy::result_large_err)]
3912 fn map_member_signature(
3913 &mut self,
3914 self_type: &TypeRef,
3915 key_type: &TypeRef,
3916 value_type: &TypeRef,
3917 field_name_str: &str,
3918 node: &swamp_ast::Node,
3919 ) -> Option<(IntrinsicFunction, Signature)> {
3920 let self_type_param = TypeForParameter {
3921 name: "self".to_string(),
3922 resolved_type: self_type.clone(),
3923 is_mutable: false,
3924 node: None,
3925 };
3926
3927 let mutable_self_type_param = TypeForParameter {
3928 name: "self".to_string(),
3929 resolved_type: self_type.clone(),
3930 is_mutable: true,
3931 node: None,
3932 };
3933
3934 let intrinsic_and_signature = match field_name_str {
3935 "has" => (
3936 IntrinsicFunction::MapHas,
3937 Signature {
3938 parameters: vec![
3939 self_type_param,
3940 TypeForParameter {
3941 name: "key".to_string(),
3942 resolved_type: key_type.clone(),
3943 is_mutable: false,
3944 node: None,
3945 },
3946 ],
3947 return_type: self.types().bool(),
3948 },
3949 ),
3950 "remove" => (
3951 IntrinsicFunction::MapRemove,
3952 Signature {
3953 parameters: vec![
3954 mutable_self_type_param,
3955 TypeForParameter {
3956 name: "key".to_string(),
3957 resolved_type: key_type.clone(),
3958 is_mutable: false,
3959 node: None,
3960 },
3961 ],
3962 return_type: self.types().unit(),
3963 },
3964 ),
3965 "len" => (
3966 IntrinsicFunction::MapLen,
3967 Signature {
3968 parameters: vec![self_type_param],
3969 return_type: self.types().int(),
3970 },
3971 ),
3972 "capacity" => (
3973 IntrinsicFunction::MapCapacity,
3974 Signature {
3975 parameters: vec![self_type_param],
3976 return_type: self.types().int(),
3977 },
3978 ),
3979 "is_empty" => (
3980 IntrinsicFunction::MapIsEmpty,
3981 Signature {
3982 parameters: vec![self_type_param],
3983 return_type: self.types().bool(),
3984 },
3985 ),
3986 _ => todo!("unknown map member"),
3987 };
3988
3989 Some(intrinsic_and_signature)
3990 }
3991
3992 fn check_intrinsic_member_signature(
3993 &mut self,
3994 type_that_member_is_on: &TypeRef,
3995 field_name_str: &str,
3996 lambda_variables_count: usize,
3997 node: &swamp_ast::Node,
3998 ) -> Option<(IntrinsicFunction, Signature)> {
3999 let ty = type_that_member_is_on;
4000 let int_type = self.types().int();
4001 match &*ty.kind {
4002 TypeKind::GridStorage(element_type, ..) | TypeKind::GridView(element_type) => self
4003 .grid_member_signature(type_that_member_is_on, element_type, field_name_str, node),
4004 TypeKind::SparseStorage(element_type, ..) | TypeKind::SparseView(element_type) => self
4005 .sparse_member_signature(
4006 type_that_member_is_on,
4007 element_type,
4008 field_name_str,
4009 lambda_variables_count,
4010 node,
4011 ),
4012 TypeKind::QueueStorage(element_type, ..) => self.queue_member_signature(
4013 type_that_member_is_on,
4014 None,
4015 element_type,
4016 field_name_str,
4017 lambda_variables_count,
4018 node,
4019 ),
4020 TypeKind::StackStorage(element_type, ..)
4021 | TypeKind::QueueStorage(element_type, ..)
4022 | TypeKind::VecStorage(element_type, ..)
4023 | TypeKind::DynamicLengthVecView(element_type) => self.vec_member_signature(
4024 type_that_member_is_on,
4025 element_type,
4026 field_name_str,
4027 lambda_variables_count,
4028 node,
4029 ),
4030 TypeKind::SliceView(element_type) => self.slice_member_signature(
4031 type_that_member_is_on,
4032 Some(&int_type),
4033 element_type,
4034 field_name_str,
4035 lambda_variables_count,
4036 node,
4037 ),
4038 TypeKind::Byte => {
4039 let element_type = self.shared.state.types.byte();
4040 self.byte_member_signature(
4041 type_that_member_is_on,
4042 Some(&int_type),
4043 &element_type,
4044 field_name_str,
4045 lambda_variables_count,
4046 node,
4047 )
4048 }
4049 TypeKind::Codepoint => {
4050 let element_type = self.shared.state.types.codepoint();
4051 self.codepoint_member_signature(
4052 type_that_member_is_on,
4053 Some(&int_type),
4054 &element_type,
4055 field_name_str,
4056 lambda_variables_count,
4057 node,
4058 )
4059 }
4060 TypeKind::String { .. } | TypeKind::StringStorage(..) => {
4061 let element_type = self.shared.state.types.byte();
4062 self.string_member_signature(
4063 type_that_member_is_on,
4064 Some(&int_type),
4065 &element_type,
4066 field_name_str,
4067 lambda_variables_count,
4068 node,
4069 )
4070 }
4071 TypeKind::DynamicLengthMapView(key, value) | TypeKind::MapStorage(key, value, _) => {
4072 self.map_member_signature(type_that_member_is_on, key, value, field_name_str, node)
4073 }
4074
4075 TypeKind::FixedCapacityAndLengthArray(element_type, _) => self.slice_member_signature(
4076 type_that_member_is_on,
4077 Some(&int_type),
4078 element_type,
4079 field_name_str,
4080 lambda_variables_count,
4081 node,
4082 ),
4083 _ => {
4084 self.add_err(
4085 ErrorKind::UnknownMemberFunction(type_that_member_is_on.clone()),
4086 node,
4087 );
4088
4089 None
4090 }
4091 }
4092 }
4093
4094 fn analyze_member_call(
4095 &mut self,
4096 type_that_member_is_on: &TypeRef,
4097 field_name_str: &str,
4098 ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4099 ast_arguments: &[swamp_ast::Expression],
4100 chain_self_is_mutable: bool,
4101 node: &swamp_ast::Node,
4102 ) -> (PostfixKind, TypeRef) {
4103 let generic_arguments = if let Some(ast_generic_arguments) = ast_maybe_generic_arguments {
4104 let mut resolved_types = Vec::new();
4105 for ast_type in ast_generic_arguments {
4106 resolved_types.push(self.analyze_type(ast_type.get_type(), &TypeAnalyzeContext::default()));
4107 }
4108 resolved_types
4109 } else {
4110 vec![]
4111 };
4112
4113 let maybe_function = self
4114 .shared
4115 .state
4116 .associated_impls
4117 .get_member_function(type_that_member_is_on, field_name_str)
4118 .cloned();
4119
4120 let (function_ref, instantiated_signature) = if let Some(found_function) = maybe_function {
4121 let signature = self.analyze_normal_member_call(
4122 type_that_member_is_on,
4123 &found_function,
4124 generic_arguments,
4125 ast_arguments,
4126 chain_self_is_mutable,
4127 node,
4128 );
4129 (found_function, signature)
4130 } else {
4131 let lambda_variables_count = if ast_arguments.is_empty() {
4132 0
4133 } else if let swamp_ast::ExpressionKind::Lambda(variables, ..) = &ast_arguments[0].kind
4134 {
4135 variables.len()
4136 } else {
4137 0
4138 };
4139 let Some((intrinsic_fn, signature)) = self.check_intrinsic_member_signature(
4140 type_that_member_is_on,
4141 field_name_str,
4142 lambda_variables_count,
4143 node,
4144 ) else {
4145 return (PostfixKind::OptionalChainingOperator, self.types().unit());
4146 };
4147 let def = IntrinsicFunctionDefinition {
4148 name: field_name_str.to_string(),
4149 signature,
4150 intrinsic: intrinsic_fn,
4151 };
4152 let function_ref = FunctionRef::from(Function::Intrinsic(
4153 IntrinsicFunctionDefinitionRef::from(def.clone()),
4154 ));
4155 (function_ref, def.signature)
4156 };
4157
4158 let self_type_in_signature = &instantiated_signature.parameters[0];
4159
4160 if self_type_in_signature.is_mutable && !chain_self_is_mutable {
4161 self.add_err(ErrorKind::SelfNotCorrectMutableState, node);
4162 }
4163
4164 let resolved_arguments = self.analyze_and_verify_parameters(
4165 node,
4166 &instantiated_signature.parameters[1..],
4167 ast_arguments,
4168 );
4169
4170 (
4171 PostfixKind::MemberCall(function_ref, resolved_arguments),
4172 TypeRef::from(instantiated_signature.return_type.clone()),
4173 )
4174 }
4175
4176 fn analyze_postfix_member_call(
4177 &mut self,
4178 type_that_member_is_on: &TypeRef,
4179 is_mutable: bool,
4180 member_name: &swamp_ast::Node,
4181 ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4182 ast_arguments: &[swamp_ast::Expression],
4183 suffixes: &mut Vec<Postfix>,
4184 ) -> TypeRef {
4185 let field_name_str = self.get_text(member_name).to_string();
4186
4187 let resolved_node = self.to_node(member_name);
4188
4189 let (kind, return_type) = self.analyze_member_call(
4190 type_that_member_is_on,
4191 &field_name_str,
4192 ast_maybe_generic_arguments,
4193 ast_arguments,
4194 is_mutable,
4195 member_name,
4196 );
4197 let postfix = Postfix {
4198 node: resolved_node,
4199 ty: return_type,
4200 kind,
4201 };
4202
4203 let last_type = postfix.ty.clone();
4204 suffixes.push(postfix);
4205
4206 last_type
4207 }
4208
4209 fn is_compatible_initializer_list_target(
4210 &mut self,
4211 target_type: &TypeRef,
4212 initializer_element_type: &TypeRef,
4213 ) -> bool {
4214 match &*target_type.kind {
4215 TypeKind::VecStorage(vec_element_type, _vec_capacity) => self
4216 .types()
4217 .compatible_with(vec_element_type, initializer_element_type),
4218 TypeKind::FixedCapacityAndLengthArray(array_element_type, _array_capacity) => self
4219 .types()
4220 .compatible_with(array_element_type, initializer_element_type),
4221 _ => false,
4222 }
4223 }
4224
4225 fn is_compatible_initializer_pair_list_target(
4226 &mut self,
4227 target_type: &TypeRef,
4228 initializer_key_type: &TypeRef,
4229 initializer_value_type: &TypeRef,
4230 ) -> bool {
4231 match &*target_type.kind {
4232 TypeKind::MapStorage(storage_key, storage_value, _) => {
4233 self.types()
4234 .compatible_with(initializer_key_type, storage_key)
4235 && self
4236 .types()
4237 .compatible_with(initializer_value_type, storage_value)
4238 }
4239 _ => false,
4240 }
4241 }
4242
4243 fn types_did_not_match_try_late_coerce_expression(
4244 &mut self,
4245 expr: Expression,
4246 special_expected_type: &TypeRef,
4247 special_encountered_type: &TypeRef,
4248 node: &swamp_ast::Node,
4249 ) -> Expression {
4250 let expected_type = special_expected_type;
4251 let encountered_type = special_encountered_type;
4252 let encountered_is_optional = matches!(&*encountered_type.kind, TypeKind::Optional(_));
4253 if let TypeKind::Optional(expected_inner_type) = &*expected_type.kind {
4254 let inner_is_also_optional =
4255 matches!(&*expected_inner_type.kind, TypeKind::Optional(_));
4256 assert!(!inner_is_also_optional);
4259
4260 if !encountered_is_optional {
4263 if self
4265 .types()
4266 .compatible_with(expected_inner_type, encountered_type)
4267 {
4268 let wrapped = self.create_expr(
4270 ExpressionKind::Option(Option::from(Box::new(expr))),
4271 expected_type.clone(),
4272 node,
4273 );
4274 return wrapped;
4275 }
4276 }
4277 }
4278
4279 if matches!(&*expected_type.kind, &TypeKind::Bool) {
4280 if encountered_is_optional {
4282 let bool_type = self.types().bool();
4283 let wrapped = self.create_expr(
4284 ExpressionKind::CoerceOptionToBool(Box::from(expr)),
4285 bool_type,
4286 node,
4287 );
4288 return wrapped;
4289 }
4290 }
4291
4292 if matches!(
4293 (&*expected_type.kind, &*encountered_type.kind),
4294 (TypeKind::Codepoint, TypeKind::Int)
4295 ) {
4296 let coerced = self.create_expr(
4297 ExpressionKind::CoerceIntToChar(Box::new(expr)),
4298 expected_type.clone(),
4299 node,
4300 );
4301 return coerced;
4302 }
4303
4304 error!(?expected_type, ?encountered_type, "incompatible");
4305 self.create_err(
4306 ErrorKind::IncompatibleTypes {
4307 expected: expected_type.clone(),
4308 found: encountered_type.clone(),
4309 },
4310 node,
4311 )
4312 }
4313
4314 #[must_use]
4315 pub fn analyze_generic_parameter_usize(&self, generic_parameter: &GenericParameter) -> usize {
4316 let usize_node = generic_parameter.get_unsigned_int_node();
4317 let usize_str = self.get_text(usize_node);
4318 Self::str_to_unsigned_int(usize_str).unwrap() as usize
4319 }
4320
4321 #[must_use]
4322 pub fn analyze_generic_parameter_usize_tuple(
4323 &self,
4324 generic_parameter: &GenericParameter,
4325 ) -> (usize, usize) {
4326 let (first, second) = generic_parameter.get_unsigned_int_tuple_nodes();
4327 let first_str = self.get_text(first);
4328 let second_str = self.get_text(second);
4329 let first_value = Self::str_to_unsigned_int(first_str).unwrap() as usize;
4330 let second_value = Self::str_to_unsigned_int(second_str).unwrap() as usize;
4331
4332 (first_value, second_value)
4333 }
4334
4335 pub fn analyze_special_named_type(
4336 &mut self,
4337 path: &[String],
4338 name: &str,
4339 ast_generic_parameters: &[GenericParameter],
4340 ) -> Option<TypeRef> {
4341 let converted_type = match name {
4342 "Any" => {
4343 let new_type = self.shared.state.types.any();
4344 let default_node = swamp_ast::Node::default();
4345 new_type
4346 }
4347 "String" => {
4348 if ast_generic_parameters.len() == 1 {
4349 let fixed_size =
4350 self.analyze_generic_parameter_usize(&ast_generic_parameters[0]);
4351 let new_type = self.shared.state.types.string_storage(fixed_size);
4352 let default_node = swamp_ast::Node::default();
4353 self.add_default_functions(&new_type, &default_node);
4354 new_type
4355 } else {
4356 return None;
4357 }
4358 }
4359 "Vec" => {
4360 if ast_generic_parameters.len() == 1 {
4361 let element_type = self.analyze_type(ast_generic_parameters[0].get_type(), &TypeAnalyzeContext::default());
4362 let vec_type = self.shared.state.types.dynamic_vec_view(&element_type);
4363 let default_node = swamp_ast::Node::default();
4365 self.add_default_functions(&vec_type, &default_node);
4366 vec_type
4367 } else if ast_generic_parameters.len() == 2 {
4368 let element_type = self.analyze_type(ast_generic_parameters[0].get_type(), &TypeAnalyzeContext::default());
4369 let fixed_size =
4370 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4371 let vec_storage_type = self
4372 .shared
4373 .state
4374 .types
4375 .vec_storage(&element_type, fixed_size);
4376 let default_node = swamp_ast::Node::default();
4378 self.add_default_functions(&vec_storage_type, &default_node);
4379 vec_storage_type
4380 } else {
4381 panic!("todo: make this into an error")
4382 }
4383 }
4384 "Stack" => {
4385 if ast_generic_parameters.len() == 1 {
4386 let element_type = self.analyze_type(ast_generic_parameters[0].get_type(), &TypeAnalyzeContext::default());
4387 let stack_view_type = self.shared.state.types.stack_view(&element_type);
4388 let default_node = swamp_ast::Node::default();
4390 self.add_default_functions(&stack_view_type, &default_node);
4391 stack_view_type
4392 } else if ast_generic_parameters.len() == 2 {
4393 let element_type = self.analyze_type(ast_generic_parameters[0].get_type(), &TypeAnalyzeContext::default());
4394 let fixed_size =
4395 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4396 let stack_storage_type = self
4397 .shared
4398 .state
4399 .types
4400 .stack_storage(&element_type, fixed_size);
4401 let default_node = swamp_ast::Node::default();
4403 self.add_default_functions(&stack_storage_type, &default_node);
4404 stack_storage_type
4405 } else {
4406 panic!("todo: make this into an error")
4407 }
4408 }
4409 "Queue" => {
4410 if ast_generic_parameters.len() == 1 {
4411 let element_type = self.analyze_type(ast_generic_parameters[0].get_type(), &TypeAnalyzeContext::default());
4412 let queue_view_type = self.shared.state.types.queue_view(&element_type);
4413 let default_node = swamp_ast::Node::default();
4415 self.add_default_functions(&queue_view_type, &default_node);
4416 queue_view_type
4417 } else if ast_generic_parameters.len() == 2 {
4418 let element_type = self.analyze_type(ast_generic_parameters[0].get_type(), &TypeAnalyzeContext::default());
4419 let fixed_size =
4420 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4421 let queue_storage_type = self
4422 .shared
4423 .state
4424 .types
4425 .queue_storage(&element_type, fixed_size);
4426 let default_node = swamp_ast::Node::default();
4428 self.add_default_functions(&queue_storage_type, &default_node);
4429 queue_storage_type
4430 } else {
4431 panic!("todo: make this into an error")
4432 }
4433 }
4434 "Sparse" => {
4435 if ast_generic_parameters.len() == 1 {
4436 let element_type = self.analyze_type(ast_generic_parameters[0].get_type(), &TypeAnalyzeContext::default());
4437 let sparse_view_type = self.shared.state.types.sparse_view(&element_type);
4438 let default_node = swamp_ast::Node::default();
4440 self.add_default_functions(&sparse_view_type, &default_node);
4441 sparse_view_type
4442 } else if ast_generic_parameters.len() == 2 {
4443 let element_type = self.analyze_type(ast_generic_parameters[0].get_type(), &TypeAnalyzeContext::default());
4444 let fixed_size =
4445 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4446 let sparse_storage_type = self
4447 .shared
4448 .state
4449 .types
4450 .sparse_storage(&element_type, fixed_size);
4451 let default_node = swamp_ast::Node::default();
4453 self.add_default_functions(&sparse_storage_type, &default_node);
4454 sparse_storage_type
4455 } else {
4456 panic!("todo: make this into an error")
4457 }
4458 }
4459
4460 "Grid" => {
4461 if ast_generic_parameters.len() == 1 {
4462 let element_type = self.analyze_type(ast_generic_parameters[0].get_type(), &TypeAnalyzeContext::default());
4463 let grid_view_type = self.shared.state.types.grid_view(&element_type);
4464 let default_node = swamp_ast::Node::default();
4466 self.add_default_functions(&grid_view_type, &default_node);
4467 grid_view_type
4468 } else if ast_generic_parameters.len() == 2 {
4469 let element_type = self.analyze_type(ast_generic_parameters[0].get_type(), &TypeAnalyzeContext::default());
4470 let (width, height) =
4471 self.analyze_generic_parameter_usize_tuple(&ast_generic_parameters[1]);
4472 let grid_storage_type =
4473 self.shared
4474 .state
4475 .types
4476 .grid_storage(&element_type, width, height);
4477 let default_node = swamp_ast::Node::default();
4479 self.add_default_functions(&grid_storage_type, &default_node);
4480 grid_storage_type
4481 } else {
4482 panic!("todo: make this into an error")
4483 }
4484 }
4485
4486 _ => return None,
4487 };
4488
4489 Some(converted_type)
4490 }
4491
4492 fn special_static_member(
4493 &self,
4494 type_identifier: &QualifiedTypeIdentifier,
4495 member_name_node: &swamp_ast::Node,
4496 ) -> Option<Function> {
4497 if type_identifier.generic_params.is_empty() {
4498 return None;
4499 }
4500
4501 if type_identifier.module_path.is_some() {
4502 return None;
4503 }
4504
4505 let member_name = self.get_text(member_name_node);
4506 let name = self.get_text(&type_identifier.name.0);
4507
4508 match name {
4509 "Stack" => None,
4510 _ => None,
4511 }
4512 }
4513
4514 fn analyze_subscript_int(&mut self, collection_type: TypeRef, unsigned_int_expression: Expression) -> (Postfix, TypeRef) {
4515 let node = &unsigned_int_expression.node;
4516 match &*collection_type.kind {
4517 TypeKind::QueueStorage(element_type, _)
4518 | TypeKind::StackStorage(element_type, _)
4519 | TypeKind::StackView(element_type)
4520 | TypeKind::VecStorage(element_type, _)
4521 | TypeKind::StringStorage(element_type, _, _)
4522 | TypeKind::String(element_type, _)
4523 | TypeKind::FixedCapacityAndLengthArray(element_type, _)
4524 | TypeKind::DynamicLengthVecView(element_type)
4525 | TypeKind::SliceView(element_type) => {
4526 let vec_type = VecType {
4527 element: element_type.clone(),
4528 };
4529
4530 let postfix = Postfix {
4531 node: node.clone(),
4532 ty: collection_type.clone(),
4533 kind: PostfixKind::VecSubscript(
4534 vec_type,
4535 unsigned_int_expression,
4536 ),
4537 };
4538
4539 (postfix, element_type.clone())
4540 }
4541 TypeKind::SparseStorage(element_type, _)
4543 | TypeKind::SparseView(element_type) => {
4544 let sparse_type = SparseType {
4545 element: element_type.clone(),
4546 };
4547
4548
4549 let postfix = Postfix {
4550 node: node.clone(),
4551 ty: collection_type.clone(),
4552 kind: PostfixKind::SparseSubscript(
4553 sparse_type,
4554 unsigned_int_expression,
4555 ),
4556 };
4557
4558 (postfix, element_type.clone())
4559 }
4560
4561 _ => {
4562 self
4563 .add_err_resolved(ErrorKind::CanNotSubscriptWithThatType, node);
4564
4565 let error_vec_type = VecType {
4566 element: self.types().unit(),
4567 };
4568
4569 let error_postfix = Postfix {
4570 node: node.clone(),
4571 ty: collection_type.clone(),
4572 kind: PostfixKind::VecSubscript(
4573 error_vec_type,
4574 unsigned_int_expression,
4575 ),
4576 };
4577
4578 (error_postfix, self.types().unit())
4579 }
4580 }
4581 }
4582
4583
4584 fn analyze_subscript_range(&mut self, collection_type: TypeRef, range_expression: Expression) -> (Postfix, TypeRef) {
4585 let node = &range_expression.node;
4586 match &*collection_type.kind {
4587 TypeKind::QueueStorage(element_type, _)
4588 | TypeKind::StackStorage(element_type, _)
4589 | TypeKind::StackView(element_type)
4590 | TypeKind::VecStorage(element_type, _)
4591 | TypeKind::StringStorage(element_type, _, _)
4592 | TypeKind::String(element_type, _)
4593 | TypeKind::FixedCapacityAndLengthArray(element_type, _)
4594 | TypeKind::DynamicLengthVecView(element_type)
4595 | TypeKind::SliceView(element_type) => {
4596 let vec_type = VecType {
4597 element: element_type.clone(),
4598 };
4599
4600 let postfix = Postfix {
4601 node: node.clone(),
4602 ty: collection_type.clone(),
4603 kind: PostfixKind::VecSubscriptRange(
4604 vec_type,
4605 range_expression,
4606 ),
4607 };
4608
4609 (postfix, collection_type.clone())
4611 }
4612
4613 _ => {
4614 self
4615 .add_err_resolved(ErrorKind::CanNotSubscriptWithThatType, node);
4616
4617 let error_vec_type = VecType {
4618 element: self.types().unit(),
4619 };
4620
4621 let error_postfix = Postfix {
4622 node: node.clone(),
4623 ty: collection_type.clone(),
4624 kind: PostfixKind::VecSubscriptRange(
4625 error_vec_type,
4626 range_expression,
4627 ),
4628 };
4629
4630 (error_postfix, self.types().unit())
4631 }
4632 }
4633 }
4634 fn analyze_map_subscript(&mut self, key_type: &TypeRef, value_type: &TypeRef, lookup_expr: &swamp_ast::Expression) -> (Postfix, TypeRef) {
4635 let key_context = TypeContext::new_argument(key_type, false);
4636 let key_expression = self.analyze_expression(lookup_expr, &key_context);
4637
4638 let map_type = MapType {
4639 key: key_type.clone(),
4640 value: value_type.clone(),
4641 };
4642
4643 let postfix = Postfix {
4644 node: self.to_node(&lookup_expr.node),
4645 ty: key_type.clone(),
4646 kind: PostfixKind::MapSubscript(map_type, key_expression),
4647 };
4648
4649 (postfix, value_type.clone())
4650 }
4651}