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