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