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 seq_map::SeqMap;
26use source_map_cache::SourceMap;
27use source_map_node::{FileId, Node, Span};
28use std::mem::take;
29use std::num::{ParseFloatError, ParseIntError};
30use std::rc::Rc;
31use std::str::{FromStr, ParseBoolError};
32use swamp_ast::{GenericParameter, QualifiedTypeIdentifier};
33use swamp_modules::prelude::*;
34use swamp_modules::symtbl::SymbolTableRef;
35use swamp_semantic::prelude::*;
36use swamp_semantic::{
37 ArgumentExpression, BinaryOperatorKind, BlockScope, BlockScopeMode, FunctionScopeState,
38 GridType, InternalMainExpression, LocationAccess, LocationAccessKind, MapType,
39 MutableReferenceKind, NormalPattern, Postfix, PostfixKind, ScopeInfo, SingleLocationExpression,
40 SliceViewType, SparseType, TargetAssignmentLocation, TypeWithMut, VariableType, VecType,
41 WhenBinding,
42};
43use swamp_semantic::{StartOfChain, StartOfChainKind};
44use swamp_types::prelude::*;
45use swamp_types::TypeKind;
46use tracing::error;
47
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),
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),
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 for parameter in parameters {
338 let param_type = self.analyze_type(¶meter.param_type);
339 if !param_type.allowed_as_parameter_type() {
340 self.add_err(
341 ErrorKind::ParameterTypeCanNotBeStorage(param_type),
342 ¶meter.variable.name,
343 );
344 continue;
345 }
346 resolved_parameters.push(TypeForParameter {
347 name: self.get_text(¶meter.variable.name).to_string(),
348 resolved_type: param_type,
349 is_mutable: parameter.variable.is_mutable.is_some(),
350 node: Some(ParameterNode {
351 is_mutable: self.to_node_option(Option::from(¶meter.variable.is_mutable)),
352 name: self.to_node(¶meter.variable.name),
353 }),
354 });
355 }
356 resolved_parameters
357 }
358
359 pub(crate) fn analyze_static_member_access(
360 &mut self,
361 named_type: &swamp_ast::QualifiedTypeIdentifier,
362 member_name_node: &swamp_ast::Node,
363 ) -> Option<Function> {
364 if let Some(found_function) = self.special_static_member(named_type, member_name_node) {
365 Some(found_function)
366 } else {
367 let some_type = self.analyze_named_type(named_type);
368
369 let member_name = self.get_text(member_name_node);
370 self.lookup_associated_function(&some_type, member_name)
371 }
372 }
373
374 pub fn analyze_local_function_access(
375 &mut self,
376 qualified_func_name: &swamp_ast::QualifiedIdentifier,
377 ) -> Option<Function> {
378 let path = self.get_module_path(qualified_func_name.module_path.as_ref());
379 let function_name = self.get_text(&qualified_func_name.name);
380
381 if let Some(found_table) = self.shared.get_symbol_table(&path) {
382 if let Some(found_func) = found_table.get_function(function_name) {
383 let (kind, signature) = match found_func {
384 FuncDef::Internal(internal_fn) => (
385 Function::Internal(internal_fn.clone()),
386 &internal_fn.signature,
387 ),
388 FuncDef::External(external_fn) => (
389 Function::External(external_fn.clone()),
390 &external_fn.signature,
391 ),
392 FuncDef::Intrinsic(intrinsic_fn) => (
394 Function::Intrinsic(intrinsic_fn.clone()),
395 &intrinsic_fn.signature,
396 ),
397 };
398
399 return Some(kind);
400 }
401 }
402
403 None
404 }
405
406 fn check_if_function_reference(
407 &mut self,
408 ast_expression: &swamp_ast::Expression,
409 ) -> Option<Function> {
410 match &ast_expression.kind {
411 swamp_ast::ExpressionKind::StaticMemberFunctionReference(
412 qualified_type_identifier,
413 node,
414 ) => self.analyze_static_member_access(qualified_type_identifier, node),
415 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
416 self.analyze_local_function_access(qualified_identifier)
417 }
418 _ => None,
419 }
420 }
421
422 pub fn analyze_start_chain_expression_get_mutability(
425 &mut self,
426 ast_expression: &swamp_ast::Expression,
427 ) -> Option<StartOfChainBase> {
428 self.check_if_function_reference(ast_expression)
429 .map_or_else(
430 || {
431 if let swamp_ast::ExpressionKind::IdentifierReference(
432 found_qualified_identifier,
433 ) = &ast_expression.kind
434 {
435 self.try_find_variable(&found_qualified_identifier.name)
436 .map(StartOfChainBase::Variable)
437 } else {
438 None
439 }
440 },
441 |found_func_def| Some(StartOfChainBase::FunctionReference(found_func_def)),
442 )
443 }
444
445 pub fn debug_expression(&self, expr: &swamp_ast::Expression, description: &str) {
446 self.debug_line(expr.node.span.offset as usize, description);
447 }
448
449 pub fn debug_line(&self, offset: usize, description: &str) {
450 let (line, col) = self
451 .shared
452 .source_map
453 .get_span_location_utf8(self.shared.file_id, offset);
454
455 let source_line = self
456 .shared
457 .source_map
458 .get_source_line(self.shared.file_id, line);
459
460 let source_path = self
461 .shared
462 .source_map
463 .fetch_relative_filename(self.shared.file_id);
464 let debug_line = format!("{source_path}:{line}:{col}> {}", source_line.unwrap());
465 }
468
469 pub fn analyze_main_expression(
472 &mut self,
473 ast_expression: &swamp_ast::Expression,
474 ) -> InternalMainExpression {
475 self.start_function();
476
477 let context = TypeContext::new_anything_argument(true); let analyzed_expr = self.analyze_expression(ast_expression, &context);
479 let main_expr = InternalMainExpression {
480 expression: analyzed_expr,
481 scopes: self.scope.total_scopes.clone(),
482 program_unique_id: self.shared.state.allocate_internal_function_id(),
483 };
484
485 self.stop_function();
486
487 main_expr
488 }
489
490 fn analyze_maybe_ref_expression(
491 &mut self,
492 ast_expr: &swamp_ast::Expression,
493 ) -> MaybeBorrowMutRefExpression {
494 if let swamp_ast::ExpressionKind::UnaryOp(found_unary, ast_inner_expression) =
495 &ast_expr.kind
496 {
497 if 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
507 MaybeBorrowMutRefExpression {
508 ast_expression: ast_expr.clone(),
509 has_borrow_mutable_reference: None,
510 }
511 }
512
513 fn needs_storage_error(
515 &self,
516 expr: &Expression,
517 is_function_call: bool,
518 context: &TypeContext,
519 ast_node: &swamp_ast::Node,
520 ) -> bool {
521 let is_constant = matches!(expr.kind, ExpressionKind::ConstantAccess(_));
522 let is_variable = matches!(expr.kind, ExpressionKind::VariableAccess(_));
523
524 !context.has_lvalue_target
526 && expr.ty.collection_view_that_needs_explicit_storage()
527 && is_function_call
528 && !is_constant
529 && !is_variable
530 }
531
532 pub fn analyze_expression(
533 &mut self,
534 ast_expression: &swamp_ast::Expression,
535 context: &TypeContext,
536 ) -> Expression {
537 let expr = self.analyze_expression_internal(ast_expression, context);
540
541 if matches!(expr.kind, ExpressionKind::Error(_)) {
542 return expr;
543 }
544
545 let encountered_type = expr.ty.clone();
546
547 let expr = if let Some(found_expected_type) = context.expected_type {
549 let reduced_expected = found_expected_type;
550
551 let reduced_encountered_type = encountered_type;
552
553 if self
554 .shared
555 .state
556 .types
557 .compatible_with(reduced_expected, &reduced_encountered_type)
558 {
559 expr
560 } else {
561 self.types_did_not_match_try_late_coerce_expression(
562 expr,
563 reduced_expected,
564 &reduced_encountered_type,
565 &ast_expression.node,
566 )
567 }
568 } else {
569 expr
570 };
573
574 let is_function_call = Self::is_aggregate_function_call(ast_expression);
577
578 if self.needs_storage_error(&expr, is_function_call, context, &ast_expression.node) {
579 self.create_err(ErrorKind::NeedStorage, &ast_expression.node)
581 } else {
582 expr
583 }
584 }
585
586 #[allow(clippy::too_many_lines)]
589 pub fn analyze_expression_internal(
590 &mut self,
591 ast_expression: &swamp_ast::Expression,
592 context: &TypeContext,
593 ) -> Expression {
594 match &ast_expression.kind {
597 swamp_ast::ExpressionKind::PostfixChain(postfix_chain) => {
599 self.analyze_postfix_chain(postfix_chain, context)
600 }
601
602 swamp_ast::ExpressionKind::VariableDefinition(
603 variable,
604 maybe_annotation,
605 source_expression,
606 ) => self.analyze_create_variable(
607 variable,
608 Option::from(maybe_annotation),
609 source_expression,
610 ),
611
612 swamp_ast::ExpressionKind::VariableAssignment(variable, source_expression) => {
613 self.analyze_variable_assignment(variable, source_expression)
614 }
615
616 swamp_ast::ExpressionKind::DestructuringAssignment(variables, expression) => {
617 self.analyze_destructuring(&ast_expression.node, variables, expression)
618 }
619
620 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
621 self.analyze_identifier(qualified_identifier)
622 }
623
624 swamp_ast::ExpressionKind::VariableReference(variable) => {
625 self.analyze_variable_reference(&variable.name)
626 }
627
628 swamp_ast::ExpressionKind::ContextAccess => {
629 todo!("context access is not done yet")
630 }
631
632 swamp_ast::ExpressionKind::StaticMemberFunctionReference(
633 type_identifier,
634 member_name,
635 ) => {
636 let debug_name = self.get_text(member_name);
637 let type_name = self.get_text(&type_identifier.name.0);
638 panic!("can not have separate member func ref {type_name:?} {debug_name}")
639 }
640
641 swamp_ast::ExpressionKind::ConstantReference(constant_identifier) => {
642 self.analyze_constant_access(constant_identifier)
643 }
644
645 swamp_ast::ExpressionKind::Assignment(location, source) => {
646 self.analyze_assignment(location, source)
647 }
648
649 swamp_ast::ExpressionKind::CompoundAssignment(target, op, source) => {
650 self.analyze_assignment_compound(target, op, source)
651 }
652
653 swamp_ast::ExpressionKind::BinaryOp(resolved_a, operator, resolved_b) => {
655 let Some((resolved_op, result_type)) =
656 self.analyze_binary_op(resolved_a, operator, resolved_b)
657 else {
658 return self.create_err(ErrorKind::OperatorProblem, &operator.node);
659 };
660
661 self.create_expr(
662 ExpressionKind::BinaryOp(resolved_op),
663 result_type,
664 &ast_expression.node,
665 )
666 }
667
668 swamp_ast::ExpressionKind::UnaryOp(operator, expression) => {
669 if let swamp_ast::UnaryOperator::BorrowMutRef(_node) = operator {
670 let inner_expr =
671 self.analyze_to_location(expression, context, LocationSide::Rhs);
672 let ty = inner_expr.ty.clone();
673 self.create_expr(
674 ExpressionKind::BorrowMutRef(Box::from(inner_expr)),
675 ty,
676 &ast_expression.node,
677 )
678 } else {
679 let Some((resolved_op, result_type)) =
680 self.analyze_unary_op(operator, expression)
681 else {
682 return self.create_err(ErrorKind::OperatorProblem, &ast_expression.node);
683 };
684 self.create_expr(
685 ExpressionKind::UnaryOp(resolved_op),
686 result_type,
687 &ast_expression.node,
688 )
689 }
690 }
691
692 swamp_ast::ExpressionKind::Block(expressions) => {
693 let (block, resulting_type) =
694 self.analyze_block(&ast_expression.node, context, expressions);
695 self.create_expr(
696 ExpressionKind::Block(block),
697 resulting_type,
698 &ast_expression.node,
699 )
700 }
701
702 swamp_ast::ExpressionKind::With(variable_bindings, expression) => {
703 self.analyze_with_expr(context, variable_bindings, expression)
704 }
705
706 swamp_ast::ExpressionKind::When(variable_bindings, true_expr, else_expr) => {
707 self.analyze_when_expr(context, variable_bindings, true_expr, else_expr.as_deref())
708 }
709
710 swamp_ast::ExpressionKind::InterpolatedString(string_parts) => {
711 self.analyze_interpolated_string_lowering(&ast_expression.node, string_parts)
712 }
713
714 swamp_ast::ExpressionKind::NamedStructLiteral(struct_identifier, fields, has_rest) => {
716 self.analyze_named_struct_literal(struct_identifier, fields, *has_rest)
717 }
718
719 swamp_ast::ExpressionKind::AnonymousStructLiteral(fields, rest_was_specified) => self
720 .analyze_anonymous_struct_literal(
721 &ast_expression.node,
722 fields,
723 *rest_was_specified,
724 context,
725 ),
726
727 swamp_ast::ExpressionKind::ContextAccess => {
728 todo!("lone dot not implemented yet")
729 }
730
731 swamp_ast::ExpressionKind::Range(min_value, max_value, range_mode) => {
732 self.analyze_range(min_value, max_value, range_mode, &ast_expression.node)
733 }
734
735 swamp_ast::ExpressionKind::ForLoop(pattern, iterable_expression, statements) => {
736 if pattern.is_key_variable_mut() {
737 return self.create_err(
738 ErrorKind::KeyVariableNotAllowedToBeMutable,
739 &ast_expression.node,
740 );
741 }
742 let resolved_iterator =
743 self.analyze_iterable(pattern.is_value_mut(), &iterable_expression.expression);
744
745 self.push_block_scope("for_loop");
746 let pattern = self.analyze_for_pattern(
747 pattern,
748 resolved_iterator.key_type.as_ref(),
749 &resolved_iterator.value_type,
750 );
751 let resolved_statements = self.analyze_expression(statements, context);
752 self.pop_block_scope("for_loop");
753 let resolved_type = resolved_statements.ty.clone();
754 self.create_expr(
755 ExpressionKind::ForLoop(
756 pattern,
757 resolved_iterator,
758 Box::from(resolved_statements),
759 ),
760 resolved_type,
761 &ast_expression.node,
762 )
763 }
764
765 swamp_ast::ExpressionKind::WhileLoop(expression, statements) => {
766 let condition = self.analyze_bool_argument_expression(expression);
767 let resolved_statements = self.analyze_expression(statements, context);
769 let resolved_type = resolved_statements.ty.clone();
770 self.create_expr(
773 ExpressionKind::WhileLoop(condition, Box::from(resolved_statements)),
774 resolved_type,
775 &ast_expression.node,
776 )
777 }
778
779 swamp_ast::ExpressionKind::If(expression, true_expression, maybe_false_expression) => {
780 self.analyze_if_expression(
781 expression,
782 true_expression,
783 maybe_false_expression.as_deref(),
784 context,
785 )
786 }
787
788 swamp_ast::ExpressionKind::Match(expression, arms) => {
789 let (match_expr, return_type) = self.analyze_match(expression, context, arms);
790 self.create_expr(
791 ExpressionKind::Match(match_expr),
792 return_type,
793 &ast_expression.node,
794 )
795 }
796 swamp_ast::ExpressionKind::Guard(guard_expressions) => {
797 self.analyze_guard(&ast_expression.node, context, guard_expressions)
798 }
799
800 swamp_ast::ExpressionKind::Lambda(variables, expression) => {
801 self.analyze_lambda(&ast_expression.node, variables, expression, context)
802 }
803 swamp_ast::ExpressionKind::Error => {
804 self.create_err(ErrorKind::UnexpectedType, &ast_expression.node)
805 }
806 swamp_ast::ExpressionKind::Literal(literal) => {
807 self.analyze_complex_literal_to_expression(ast_expression, literal, context)
808 } }
810 }
811
812 fn get_struct_type(
813 &mut self,
814 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
815 ) -> NamedStructType {
816 let maybe_struct_type = self.analyze_named_type(qualified_type_identifier);
817 if let TypeKind::NamedStruct(struct_type) = &*maybe_struct_type.kind {
818 struct_type.clone()
819 } else {
820 self.add_err(
821 ErrorKind::UnknownStructTypeReference,
823 &qualified_type_identifier.name.0,
824 );
825
826 NamedStructType {
827 name: Default::default(),
828 module_path: vec![],
829 assigned_name: String::new(),
830 anon_struct_type: self.types().unit(),
831 instantiated_type_parameters: vec![],
832 }
833 }
834 }
835
836 pub(crate) fn analyze_named_type(
837 &mut self,
838 type_name_to_find: &swamp_ast::QualifiedTypeIdentifier,
839 ) -> TypeRef {
840 let (path, name) = self.get_path(type_name_to_find);
841 let mut analyzed_type_parameters = Vec::new();
842
843 if let Some(found) =
844 self.analyze_special_named_type(&path, &name, &type_name_to_find.generic_params)
845 {
846 return found;
847 }
848
849 for analyzed_type in &type_name_to_find.generic_params {
850 let ty = self.analyze_type(analyzed_type.get_type());
851
852 analyzed_type_parameters.push(ty);
853 }
854
855 let symbol = {
856 if let Some(symbol_table) = self.shared.get_symbol_table(&path) {
857 if let Some(x) = symbol_table.get_symbol(&name) {
858 x
859 } else {
860 self.add_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0);
861 return self.types().unit();
862 }
863 } else {
864 self.add_err(ErrorKind::UnexpectedType, &type_name_to_find.name.0);
865 return self.types().unit();
866 }
867 };
868
869 if analyzed_type_parameters.is_empty() {
870 match &symbol {
871 Symbol::Type(base_type) => base_type.clone(),
872 Symbol::Alias(alias_type) => alias_type.ty.clone(),
873 _ => {
874 self.add_err(ErrorKind::UnexpectedType, &type_name_to_find.name.0);
875 self.types().unit()
876 }
877 }
878 } else {
879 panic!("unknown type")
880 }
881 }
882
883 fn create_default_value_for_type(
884 &mut self,
885 node: &swamp_ast::Node,
886 field_type: &TypeRef,
887 ) -> Option<Expression> {
888 let kind = match &*field_type.kind {
889 TypeKind::Tuple(tuple_type_ref) => {
890 let mut expressions = Vec::new();
891 for resolved_type in tuple_type_ref {
892 let expr = self.create_default_value_for_type(node, resolved_type)?;
893 expressions.push(expr);
894 }
895 ExpressionKind::TupleLiteral(expressions)
896 }
897
898 TypeKind::NamedStruct(_struct_ref) => {
899 if self
901 .shared
902 .state
903 .associated_impls
904 .get_member_function(field_type, "default")
905 .is_some()
906 {
907 self.create_default_static_call(node, field_type)
908 } else {
909 return None;
911 }
912 }
913
914 _ => {
915 return None;
917 }
918 };
919
920 Some(self.create_expr(kind, field_type.clone(), node))
921 }
922
923 fn create_static_member_call(
924 &mut self,
925 function_name: &str,
926 arguments: &[ArgumentExpression],
927 node: &swamp_ast::Node,
928 ty: &TypeRef,
929 ) -> ExpressionKind {
930 self.lookup_associated_function(ty, function_name)
931 .map_or_else(
932 || {
933 self.create_err(
934 ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
935 node,
936 )
937 .kind
938 },
939 |function| {
940 let Function::Internal(internal_function) = &function else {
941 panic!("only allowed for internal functions");
942 };
943
944 ExpressionKind::InternalCall(internal_function.clone(), arguments.to_vec())
945 },
946 )
947 }
948
949 fn create_static_member_intrinsic_call(
950 &mut self,
951 function_name: &str,
952 arguments: &[ArgumentExpression],
953 node: &swamp_ast::Node,
954 ty: &TypeRef,
955 ) -> ExpressionKind {
956 if let Some(function) = self.lookup_associated_function(ty, function_name) {
958 let Function::Internal(internal_function) = &function else {
959 panic!("only allowed for internal functions");
960 };
961
962 if let Some((intrinsic_fn, _)) =
963 Self::extract_single_intrinsic_call(&internal_function.body)
964 {
965 ExpressionKind::IntrinsicCallEx(intrinsic_fn, arguments.to_vec())
966 } else {
967 self.create_err(
968 ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
969 node,
970 )
971 .kind
972 }
973 } else {
974 self.create_err(
975 ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
976 node,
977 )
978 .kind
979 }
980 }
981
982 fn create_default_static_call(
983 &mut self,
984 node: &swamp_ast::Node,
985 ty: &TypeRef,
986 ) -> ExpressionKind {
987 self.create_static_member_call("default", &[], node, ty)
988 }
989
990 fn add_postfix(
991 &mut self,
992 vec: &mut Vec<Postfix>,
993 kind: PostfixKind,
994 ty: TypeRef,
995 node: &swamp_ast::Node,
996 ) {
997 let resolved_node = self.to_node(node);
998 let postfix = Postfix {
999 node: resolved_node,
1000 ty,
1001 kind,
1002 };
1003
1004 vec.push(postfix);
1005 }
1006
1007
1008 pub fn analyze_struct_field(
1013 &mut self,
1014 field_name: &swamp_ast::Node,
1015 tv: &TypeRef,
1016 ) -> (AnonymousStructType, usize, TypeRef) {
1017 let field_name_str = self.get_text(field_name).to_string();
1018
1019 let anon_struct_ref = match &*tv.kind {
1020 TypeKind::NamedStruct(struct_type) => struct_type.anon_struct_type.clone(),
1021 TypeKind::AnonymousStruct(anon_struct) => {
1022 self.shared
1024 .state
1025 .types
1026 .anonymous_struct(anon_struct.clone())
1027 }
1028 TypeKind::Range(range_struct_ref) => {
1029 if let TypeKind::NamedStruct(named_struct) = &*range_struct_ref.kind {
1031 named_struct.anon_struct_type.clone()
1032 } else {
1033 self.add_err(ErrorKind::UnknownStructField, field_name);
1034 return (
1036 AnonymousStructType::new(SeqMap::new()),
1037 0,
1038 self.shared.state.types.unit(),
1039 );
1040 }
1041 }
1042 _ => {
1043 self.add_err(ErrorKind::UnknownStructField, field_name);
1044 return (
1046 AnonymousStructType::new(SeqMap::new()),
1047 0,
1048 self.shared.state.types.unit(),
1049 );
1050 }
1051 };
1052
1053 if let TypeKind::AnonymousStruct(anon_struct) = &*anon_struct_ref.kind {
1055 if let Some(found_field) = anon_struct.field_name_sorted_fields.get(&field_name_str) {
1056 let index = anon_struct
1057 .field_name_sorted_fields
1058 .get_index(&field_name_str)
1059 .expect("checked earlier");
1060
1061 return (anon_struct.clone(), index, found_field.field_type.clone());
1062 }
1063 }
1064
1065 self.add_err(ErrorKind::UnknownStructField, field_name);
1066 (
1068 AnonymousStructType::new(SeqMap::new()),
1069 0,
1070 self.shared.state.types.unit(),
1071 )
1072 }
1073
1074 pub fn analyze_static_call(
1075 &mut self,
1076 ast_node: &swamp_ast::Node,
1077 maybe_associated_to_type: Option<TypeRef>,
1078 func_def: Function,
1079 maybe_generic_arguments: &Option<Vec<swamp_ast::GenericParameter>>,
1080 arguments: &[swamp_ast::Expression],
1081 context: &TypeContext,
1082 ) -> Expression {
1083 let signature = func_def.signature().clone();
1084
1085 let analyzed_arguments =
1086 self.analyze_and_verify_parameters(ast_node, &signature.parameters, arguments);
1087
1088 let expr_kind = match &func_def {
1089 Function::Internal(internal) => {
1090 ExpressionKind::InternalCall(internal.clone(), analyzed_arguments)
1091 }
1092 Function::External(host) => ExpressionKind::HostCall(host.clone(), analyzed_arguments),
1093 Function::Intrinsic(intrinsic) => {
1094 ExpressionKind::IntrinsicCallEx(intrinsic.intrinsic.clone(), analyzed_arguments)
1095 }
1096 };
1097
1098 let expr = self.create_expr(expr_kind, signature.return_type.clone(), ast_node);
1099
1100 if self.needs_storage_error(&expr, true, context, ast_node) {
1102 return self.create_err(ErrorKind::NeedStorage, ast_node);
1103 }
1104
1105 expr
1106 }
1107
1108 #[allow(clippy::too_many_lines)]
1109 fn analyze_postfix_chain(
1110 &mut self,
1111 chain: &swamp_ast::PostfixChain,
1112 context: &TypeContext,
1113 ) -> Expression {
1114 let maybe_start_of_chain_base =
1115 self.analyze_start_chain_expression_get_mutability(&chain.base);
1116
1117 let mut start_index = 0;
1118
1119 let start_of_chain_kind = if let Some(start_of_chain_base) = maybe_start_of_chain_base {
1120 match start_of_chain_base {
1122 StartOfChainBase::FunctionReference(func_def) => {
1123 if let swamp_ast::Postfix::FunctionCall(
1126 ast_node,
1127 maybe_generic_arguments,
1128 arguments,
1129 ) = &chain.postfixes[0]
1130 {
1131 start_index = 1;
1132 let call_expr = self.analyze_static_call(
1133 ast_node,
1134 None,
1135 func_def,
1136 maybe_generic_arguments,
1137 arguments,
1138 context,
1139 );
1140 if chain.postfixes.len() == 1 {
1141 return call_expr;
1142 }
1143 StartOfChainKind::Expression(Box::from(call_expr))
1144 } else {
1145 panic!("must be a normal function call")
1146 }
1147 }
1148 StartOfChainBase::Variable(var) => StartOfChainKind::Variable(var),
1149 }
1150 } else {
1151 let ctx = TypeContext::new_anything_argument(true); StartOfChainKind::Expression(Box::from(self.analyze_expression(&chain.base, &ctx)))
1153 };
1154
1155 let start_of_chain_node = self.to_node(&chain.base.node);
1156
1157 let start_of_chain = StartOfChain {
1158 kind: start_of_chain_kind.clone(),
1159 node: start_of_chain_node,
1160 };
1161
1162 let mut tv = TypeWithMut {
1163 resolved_type: start_of_chain_kind.ty(),
1164 is_mutable: start_of_chain_kind.is_mutable(),
1165 };
1166
1167 let mut uncertain = false;
1168 let mut previous_was_optional_chaining = false;
1169
1170 let mut suffixes = Vec::new();
1171
1172 for (index, item) in chain.postfixes[start_index..].iter().enumerate() {
1173 let is_last = index == chain.postfixes[start_index..].len() - 1;
1174
1175 if previous_was_optional_chaining {
1177 match item {
1178 swamp_ast::Postfix::FieldAccess(_)
1179 | swamp_ast::Postfix::MemberCall(_, _, _)
1180 | swamp_ast::Postfix::Subscript(_)
1181 | swamp_ast::Postfix::SubscriptTuple(_, _) => {
1182 }
1184 swamp_ast::Postfix::OptionalChainingOperator(node) => {
1185 return self
1186 .create_err(ErrorKind::InvalidOperatorAfterOptionalChaining, node);
1187 }
1188 swamp_ast::Postfix::FunctionCall(node, _, _) => {
1189 return self
1190 .create_err(ErrorKind::InvalidOperatorAfterOptionalChaining, node);
1191 }
1192 }
1193 }
1194
1195 match item {
1196 swamp_ast::Postfix::FieldAccess(field_name) => {
1203 previous_was_optional_chaining = false;
1204 let (struct_type_ref, index, return_type) =
1205 self.analyze_struct_field(&field_name.clone(), &tv.resolved_type);
1206 let struct_type_type_ref = self
1207 .shared
1208 .state
1209 .types
1210 .anonymous_struct(struct_type_ref.clone());
1211 self.add_postfix(
1212 &mut suffixes,
1213 PostfixKind::StructField(struct_type_type_ref, index),
1214 return_type.clone(),
1215 field_name,
1216 );
1217
1218 tv.resolved_type = return_type.clone();
1219 }
1221
1222 swamp_ast::Postfix::SubscriptTuple(col_expr, row_expr) => {
1223 previous_was_optional_chaining = false;
1224 let collection_type = tv.resolved_type.clone();
1225 match &*collection_type.kind {
1226 TypeKind::GridStorage(element_type, x, _) => {
1227 let int_type = self.shared.state.types.int();
1228 let unsigned_int_x_context =
1229 TypeContext::new_argument(&int_type, false);
1230 let unsigned_int_x_expression =
1231 self.analyze_expression(col_expr, &unsigned_int_x_context);
1232
1233 let unsigned_int_y_context =
1234 TypeContext::new_argument(&int_type, false);
1235 let unsigned_int_y_expression =
1236 self.analyze_expression(row_expr, &unsigned_int_y_context);
1237
1238 let vec_type = GridType {
1239 element: element_type.clone(),
1240 };
1241
1242 self.add_postfix(
1243 &mut suffixes,
1244 PostfixKind::GridSubscript(
1245 vec_type,
1246 unsigned_int_x_expression,
1247 unsigned_int_y_expression,
1248 ),
1249 element_type.clone(),
1250 &col_expr.node,
1251 );
1252
1253 tv.resolved_type = element_type.clone();
1255 }
1256 _ => panic!("not a subscript tuple"),
1257 }
1258 }
1259
1260 swamp_ast::Postfix::Subscript(lookup_expr) => {
1261 previous_was_optional_chaining = false;
1262 let collection_type = tv.resolved_type.clone();
1263
1264 match &*collection_type.kind {
1265 TypeKind::MapStorage(key_type, value_type, ..) | TypeKind::DynamicLengthMapView(key_type, value_type) => {
1267 let (postfix, return_type) = self.analyze_map_subscript(key_type, value_type, lookup_expr);
1268 suffixes.push(postfix);
1269 tv.resolved_type = return_type;
1270 }
1271 _ => {
1272 let anything_context = context.with_argument_anything();
1274 let anything_expression =
1275 self.analyze_expression(lookup_expr, &anything_context);
1276
1277 match &*anything_expression.ty.kind {
1278 TypeKind::Int => {
1279 let (postfix, return_type) = self.analyze_subscript_int(collection_type, anything_expression);
1280 suffixes.push(postfix);
1281 tv.resolved_type = return_type;
1282 }
1283 TypeKind::Range(_range_type) => {
1284 let (postfix, return_type) = self.analyze_subscript_range(collection_type, anything_expression);
1285 suffixes.push(postfix);
1286 tv.resolved_type = return_type;
1287 }
1288 _ => {
1289 return self.create_err(ErrorKind::CanNotSubscriptWithThatType, &lookup_expr.node)
1290 }
1291 }
1292 }
1293 }
1294 }
1295
1296 swamp_ast::Postfix::MemberCall(member_name, generic_arguments, ast_arguments) => {
1297 previous_was_optional_chaining = false;
1298 let member_name_str = self.get_text(member_name).to_string();
1299 let underlying_type = tv.resolved_type;
1300
1301 let (kind, return_type) = self.analyze_member_call(
1302 &underlying_type,
1303 &member_name_str,
1304 generic_arguments.clone(),
1305 ast_arguments,
1306 tv.is_mutable,
1307 member_name,
1308 );
1309
1310 self.add_postfix(&mut suffixes, kind, return_type.clone(), member_name);
1311 tv.resolved_type = return_type.clone();
1312 tv.is_mutable = false;
1313 }
1314 swamp_ast::Postfix::FunctionCall(node, _generic_arguments, arguments) => {
1315 panic!("can only have function call at the start of a postfix chain")
1316 }
1317
1318 swamp_ast::Postfix::OptionalChainingOperator(option_node) => {
1319 if is_last {
1320 return self.create_err(
1321 ErrorKind::InvalidOperatorAfterOptionalChaining,
1322 option_node,
1323 );
1324 }
1325
1326 if let TypeKind::Optional(unwrapped_type) = &*tv.resolved_type.kind {
1327 uncertain = true;
1328 self.add_postfix(
1329 &mut suffixes,
1330 PostfixKind::OptionalChainingOperator,
1331 (*unwrapped_type).clone(),
1332 option_node,
1333 );
1334 tv.resolved_type = (*unwrapped_type).clone();
1335 previous_was_optional_chaining = true;
1336 } else {
1337 return self.create_err(ErrorKind::ExpectedOptional, option_node);
1338 }
1339 }
1340 }
1341 }
1342
1343 if uncertain {
1344 if let TypeKind::Optional(_) = &*tv.resolved_type.kind {} else {
1345 tv.resolved_type = self.shared.state.types.optional(&tv.resolved_type.clone());
1346 }
1347 }
1348
1349 self.create_expr(
1350 ExpressionKind::PostfixChain(start_of_chain, suffixes),
1351 tv.resolved_type,
1352 &chain.base.node,
1353 )
1354 }
1355
1356 fn analyze_bool_argument_expression(
1357 &mut self,
1358 expression: &swamp_ast::Expression,
1359 ) -> BooleanExpression {
1360 let bool_type = self.shared.state.types.bool();
1361 let bool_context = TypeContext::new_argument(&bool_type, false);
1362 let resolved_expression = self.analyze_expression(expression, &bool_context);
1363 let expr_type = resolved_expression.ty.clone();
1364
1365 let bool_expression = match &*expr_type.kind {
1366 TypeKind::Bool => resolved_expression,
1367 TypeKind::Optional(_) => {
1368 let bool = self.types().bool();
1369 self.create_expr(
1370 ExpressionKind::CoerceOptionToBool(Box::new(resolved_expression)),
1371 bool,
1372 &expression.node,
1373 )
1374 }
1375 _ => self.create_err(ErrorKind::ExpectedBooleanExpression, &expression.node),
1376 };
1377
1378 BooleanExpression {
1379 expression: Box::from(bool_expression),
1380 }
1381 }
1382
1383 fn is_aggregate_function_call(expression: &swamp_ast::Expression) -> bool {
1385 match &expression.kind {
1386 swamp_ast::ExpressionKind::PostfixChain(chain) => {
1387 if chain.postfixes.is_empty() {
1388 return false;
1389 }
1390
1391 for postfix in &chain.postfixes {
1392 if let swamp_ast::Postfix::FunctionCall(_, _, _) = postfix {
1393 return true;
1394 }
1395 }
1396 false
1397 }
1398 _ => false, }
1400 }
1401
1402 fn analyze_iterable(
1403 &mut self,
1404 mut_requested_for_value_variable: Option<swamp_ast::Node>,
1405 expression: &swamp_ast::Expression,
1406 ) -> Iterable {
1407 let has_lvalue_target = !Self::is_aggregate_function_call(expression);
1410 let any_context = TypeContext::new_anything_argument(has_lvalue_target);
1411
1412 let resolved_expression = self.analyze_expression(expression, &any_context);
1413
1414 let resolved_type = &resolved_expression.ty.clone();
1415 let int_type = Some(self.types().int());
1416 let (key_type, value_type): (Option<TypeRef>, TypeRef) = match &*resolved_type.kind {
1417 TypeKind::String(_, char) => (int_type, char.clone()),
1418 TypeKind::SliceView(element_type) => (int_type, element_type.clone()),
1419 TypeKind::VecStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1420 TypeKind::SparseStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1421 TypeKind::StackStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1422 TypeKind::StackView(element_type) => (int_type, element_type.clone()),
1423 TypeKind::QueueStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1424 TypeKind::QueueView(element_type) => (int_type, element_type.clone()),
1425 TypeKind::DynamicLengthVecView(element_type) => (int_type, element_type.clone()),
1426 TypeKind::SparseView(element_type) => (int_type, element_type.clone()),
1427 TypeKind::FixedCapacityAndLengthArray(element_type, _fixed_size) => {
1428 (int_type, element_type.clone())
1429 }
1430 TypeKind::DynamicLengthMapView(key_type, value_type)
1431 | TypeKind::MapStorage(key_type, value_type, _) => {
1432 (Some(key_type.clone()), value_type.clone())
1433 }
1434 TypeKind::Range(_) => (None, self.types().int()),
1435 _ => {
1436 error!(?resolved_type, "not an iterator");
1437 return Iterable {
1438 key_type: None,
1439 value_type: self.shared.state.types.unit(),
1440 resolved_expression: Box::new(
1441 self.create_err(ErrorKind::NotAnIterator, &expression.node),
1442 ),
1443 };
1444 }
1445 };
1446
1447 if mut_requested_for_value_variable.is_some() {
1448 let _resulting_location =
1450 self.analyze_to_location(expression, &any_context, LocationSide::Mutable);
1451 }
1454
1455 Iterable {
1456 key_type,
1457 value_type,
1458 resolved_expression: Box::new(resolved_expression),
1459 }
1460 }
1461
1462 fn analyze_argument_expressions(
1463 &mut self,
1464 expected_type: Option<&TypeRef>,
1465 context: &TypeContext,
1466 ast_expressions: &[swamp_ast::Expression],
1467 ) -> Vec<Expression> {
1468 let mut resolved_expressions = Vec::new();
1469 let argument_expressions_context = TypeContext::new_unsure_argument(expected_type, false);
1471
1472 for expression in ast_expressions {
1473 resolved_expressions
1474 .push(self.analyze_expression(expression, &argument_expressions_context));
1475 }
1476 resolved_expressions
1477 }
1478
1479 fn analyze_block(
1480 &mut self,
1481 _node: &swamp_ast::Node,
1482 context: &TypeContext,
1483 ast_expressions: &[swamp_ast::Expression],
1484 ) -> (Vec<Expression>, TypeRef) {
1485 if ast_expressions.is_empty() {
1486 return (vec![], self.shared.state.types.unit());
1487 }
1488
1489 self.push_block_scope("block");
1490
1491 let mut resolved_expressions = Vec::with_capacity(ast_expressions.len());
1492
1493 for expression in &ast_expressions[..ast_expressions.len() - 1] {
1494 let unit_type = self.shared.state.types.unit();
1495 let stmt_context =
1496 context.with_expected_type(Some(&unit_type), context.has_lvalue_target);
1497 let expr = self.analyze_expression(expression, &stmt_context);
1498
1499 resolved_expressions.push(expr);
1500 }
1501
1502 let last_expr =
1504 self.analyze_expression(&ast_expressions[ast_expressions.len() - 1], context);
1505 let last_type = last_expr.ty.clone();
1506 resolved_expressions.push(last_expr);
1507
1508 self.pop_block_scope("block");
1509
1510 (resolved_expressions, last_type)
1511 }
1512
1513 fn analyze_interpolated_string_lowering(
1514 &mut self,
1515 node: &swamp_ast::Node,
1516 string_parts: &[swamp_ast::StringPart],
1517 ) -> Expression {
1518 let mut last_expression: Option<Expression> = None;
1519 for part in string_parts {
1520 let created_expression = match part {
1521 swamp_ast::StringPart::Literal(string_node, processed_string) => {
1522 let string_literal =
1523 ExpressionKind::StringLiteral(processed_string.to_string());
1524 let basic_literal = string_literal;
1525 let string_type = self.shared.state.types.string();
1526 self.create_expr(basic_literal, string_type, string_node)
1527 }
1528 swamp_ast::StringPart::Interpolation(expression, format_specifier) => {
1529 let any_context = TypeContext::new_anything_argument(false); let expr = self.analyze_expression(expression, &any_context);
1532
1533 let tk = (*expr.ty.kind).clone();
1534
1535 let maybe_to_string = self
1536 .shared
1537 .state
1538 .associated_impls
1539 .get_internal_member_function(&expr.ty, "to_string");
1540
1541 if matches!(tk, TypeKind::String { .. }) {
1542 expr
1543 } else {
1544 let underlying = expr.ty.clone();
1545
1546 if self.needs_storage_error(&expr, true, &any_context, &expression.node) {
1548 return self.create_err(ErrorKind::NeedStorage, &expression.node);
1549 }
1550
1551 let call_expr_kind = if maybe_to_string.is_none() {
1552 let string_type = self.types().string();
1553
1554 ExpressionKind::StringLiteral(format!("missing {string_type}"))
1555 } else {
1564 let expr_as_param = ArgumentExpression::Expression(expr);
1565 self.create_static_member_call(
1566 "to_string",
1567 &[expr_as_param.clone()],
1568 &expression.node,
1569 &underlying,
1570 )
1571 };
1572
1573 let string_type = self.shared.state.types.string();
1581 self.create_expr(call_expr_kind, string_type, &expression.node)
1582 }
1583 }
1584 };
1585
1586 let x_last_expr = if let Some(last_expr) = last_expression.clone() {
1587 let op_kind = BinaryOperatorKind::Add;
1588 let node = created_expression.node.clone();
1589 let op = BinaryOperator {
1590 left: Box::new(last_expr),
1591 right: Box::new(created_expression),
1592 kind: op_kind,
1593 node: node.clone(),
1594 };
1595
1596 let string_type = self.shared.state.types.string();
1597 create_expr_resolved(ExpressionKind::BinaryOp(op), string_type, &node)
1598 } else {
1599 created_expression
1600 };
1601
1602 last_expression = Some(x_last_expr);
1603 }
1604
1605 if let Some(last) = last_expression {
1608 last
1609 } else {
1610 let string_type = self.shared.state.types.string();
1611 self.create_expr(
1612 ExpressionKind::StringLiteral(String::new()),
1613 string_type,
1614 node,
1615 )
1616 }
1617 }
1618
1619 pub(crate) fn analyze_identifier(
1620 &mut self,
1621 qualified_func_name: &swamp_ast::QualifiedIdentifier,
1622 ) -> Expression {
1623 if qualified_func_name.module_path.is_none()
1626 && qualified_func_name.generic_params.is_empty()
1627 {
1628 if let Some(found_variable) = self.try_find_variable(&qualified_func_name.name) {
1629 return self.create_expr(
1630 ExpressionKind::VariableAccess(found_variable.clone()),
1631 found_variable.resolved_type.clone(),
1632 &qualified_func_name.name,
1633 );
1634 }
1635 }
1636
1637 let text = self.get_text(&qualified_func_name.name);
1638 self.create_err(
1639 ErrorKind::UnknownIdentifier(text.to_string()),
1640 &qualified_func_name.name,
1641 )
1642 }
1643
1644 fn analyze_variable_reference(&mut self, var_node: &swamp_ast::Node) -> Expression {
1646 if let Some(found_variable) = self.try_find_variable(var_node) {
1647 return self.create_expr(
1648 ExpressionKind::VariableAccess(found_variable.clone()),
1649 found_variable.resolved_type.clone(),
1650 var_node,
1651 );
1652 }
1653 let text = self.get_text(var_node);
1654 self.create_err(ErrorKind::UnknownIdentifier(text.to_string()), var_node)
1655 }
1656
1657 fn analyze_internal_initializer_pair_list(
1658 &mut self,
1659 node: &swamp_ast::Node,
1660 items: &[(swamp_ast::Expression, swamp_ast::Expression)],
1661 context: &TypeContext,
1662 ) -> (TypeRef, Vec<(Expression, Expression)>) {
1663 let (collection_type, key_type, value_type) = if let Some(expected_type) =
1664 context.expected_type
1665 {
1666 match &*expected_type.kind {
1667 TypeKind::MapStorage(key, value, capacity) => {
1668 if items.len() > *capacity {
1669 self.add_err(
1670 ErrorKind::TooManyInitializerListElementsForStorage {
1671 capacity: *capacity,
1672 },
1673 node,
1674 );
1675 return (self.types().unit(), vec![]);
1676 }
1677 (expected_type.clone(), key.clone(), value.clone())
1678 }
1679 TypeKind::DynamicLengthMapView(key, value) => {
1680 (expected_type.clone(), key.clone(), value.clone())
1681 }
1682 _ => {
1683 self.add_err(ErrorKind::ExpectedSlice, node);
1684 return (self.types().unit(), vec![]);
1685 }
1686 }
1687 } else if items.is_empty() {
1688 self.add_err(ErrorKind::NoInferredTypeForEmptyInitializer, node);
1689 return (self.types().unit(), vec![]);
1690 } else {
1691 let maybe_key_context = TypeContext::new_anything_argument(true);
1693
1694 let first_key_expression = self.analyze_expression(&items[0].0, &maybe_key_context);
1695
1696 let maybe_value_context = TypeContext::new_anything_argument(true);
1697 let first_value_expression = self.analyze_expression(&items[0].1, &maybe_value_context);
1698
1699 let required_key_type = first_key_expression.ty;
1700 let required_value_type = first_value_expression.ty;
1701
1702 let inferred_type =
1703 self.types()
1704 .map_storage(&required_key_type, &required_value_type, items.len());
1705
1706 (inferred_type, required_key_type, required_value_type)
1707 };
1708
1709 assert!(!matches!(*key_type.kind, TypeKind::Unit));
1710 assert!(!matches!(*value_type.kind, TypeKind::Unit));
1711
1712 let required_key_context = TypeContext::new_argument(&key_type, true);
1713 let required_value_context = TypeContext::new_argument(&value_type, true);
1714
1715 let mut resolved_items = Vec::new();
1716
1717 for (key_expr, value_expr) in items {
1718 let analyzed_key_expr = self.analyze_expression(key_expr, &required_key_context);
1719 let analyzed_value_expr = self.analyze_expression(value_expr, &required_value_context);
1720 resolved_items.push((analyzed_key_expr, analyzed_value_expr));
1721 }
1722
1723 (collection_type, resolved_items)
1724 }
1725
1726 fn analyze_internal_initializer_list(
1727 &mut self,
1728 node: &swamp_ast::Node,
1729 items: &[swamp_ast::Expression],
1730 context: &TypeContext,
1731 ) -> (TypeRef, Vec<Expression>) {
1732 let (collection_type, element_type) = if let Some(expected_type) = context.expected_type {
1733 match &*expected_type.kind {
1734 TypeKind::GridStorage(element_type, width, height) => {
1735 let capacity = width * height;
1736 if items.len() > capacity {
1737 return (
1738 self.types().unit(),
1739 self.create_err_vec(
1740 ErrorKind::TooManyInitializerListElementsForStorage { capacity },
1741 node,
1742 ),
1743 );
1744 }
1745 (expected_type.clone(), element_type.clone())
1746 }
1747 TypeKind::StackStorage(element_type, capacity)
1748 | TypeKind::QueueStorage(element_type, capacity)
1749 | TypeKind::SparseStorage(element_type, capacity)
1750 | TypeKind::VecStorage(element_type, capacity) => {
1751 if items.len() > *capacity {
1752 return (
1753 self.types().unit(),
1754 self.create_err_vec(
1755 ErrorKind::TooManyInitializerListElementsForStorage {
1756 capacity: *capacity,
1757 },
1758 node,
1759 ),
1760 );
1761 }
1762 (expected_type.clone(), element_type.clone())
1763 }
1764 TypeKind::QueueView(element_type) => {
1765 let inferred_storage_type =
1767 self.types().queue_storage(element_type, items.len());
1768 let default_node = swamp_ast::Node::default();
1769 self.add_default_functions(&inferred_storage_type, &default_node);
1770 (inferred_storage_type, element_type.clone())
1771 }
1772 TypeKind::SparseView(element_type) => {
1773 let inferred_storage_type =
1775 self.types().sparse_storage(element_type, items.len());
1776 let default_node = swamp_ast::Node::default();
1777 self.add_default_functions(&inferred_storage_type, &default_node);
1778 (inferred_storage_type, element_type.clone())
1779 }
1780 TypeKind::StackView(element_type) => {
1781 let inferred_storage_type =
1783 self.types().stack_storage(element_type, items.len());
1784 let default_node = swamp_ast::Node::default();
1785 self.add_default_functions(&inferred_storage_type, &default_node);
1786 (inferred_storage_type, element_type.clone())
1787 }
1788 TypeKind::GridView(element_type) => {
1789 (expected_type.clone(), element_type.clone())
1791 }
1792 TypeKind::DynamicLengthVecView(element_type) => {
1793 let inferred_storage_type = self.types().vec_storage(element_type, items.len());
1795 let default_node = swamp_ast::Node::default();
1796 self.add_default_functions(&inferred_storage_type, &default_node);
1797 (inferred_storage_type, element_type.clone())
1798 }
1799 TypeKind::SliceView(element_type) => {
1800 let inferred_storage_type = self.types().vec_storage(element_type, items.len());
1802 let default_node = swamp_ast::Node::default();
1803 self.add_default_functions(&inferred_storage_type, &default_node);
1804 (inferred_storage_type, element_type.clone())
1805 }
1806 TypeKind::FixedCapacityAndLengthArray(element_type, _size) => {
1807 (expected_type.clone(), element_type.clone())
1808 }
1809 _ => {
1810 return (
1811 self.types().unit(),
1812 self.create_err_vec(
1813 ErrorKind::ExpectedInitializerTarget {
1814 destination_type: expected_type.clone(),
1815 },
1816 node,
1817 ),
1818 );
1819 }
1820 }
1821 } else if items.is_empty() {
1822 return (
1823 self.types().unit(),
1824 self.create_err_vec(ErrorKind::NoInferredTypeForEmptyInitializer, node),
1825 );
1826 } else {
1827 let maybe_context = TypeContext::new_anything_argument(true);
1829 let first = self.analyze_expression(&items[0], &maybe_context);
1830 let required_type = first.ty;
1831 let inferred_vec_storage_type = self.types().vec_storage(&required_type, items.len());
1832 let default_node = swamp_ast::Node::default();
1834 self.add_default_functions(&inferred_vec_storage_type, &default_node);
1835 (inferred_vec_storage_type, required_type)
1836 };
1837
1838 let required_context = TypeContext::new_argument(&element_type, true);
1839 let mut resolved_items = Vec::new();
1840 for item in items {
1841 let resolved_expr = self.analyze_expression(item, &required_context);
1842 resolved_items.push(resolved_expr);
1843 }
1844 (collection_type, resolved_items)
1845 }
1846
1847 fn push_block_scope(&mut self, debug_str: &str) {
1848 let register_watermark = self.scope.total_scopes.current_register;
1849
1850 self.scope.active_scope.block_scope_stack.push(BlockScope {
1851 mode: BlockScopeMode::Open,
1852 lookup: Default::default(),
1853 variables: SeqMap::default(),
1854 register_watermark,
1855 });
1856 }
1857
1858 fn push_lambda_scope(&mut self, debug_str: &str) {
1859 self.scope.active_scope.block_scope_stack.push(BlockScope {
1862 mode: BlockScopeMode::Lambda,
1863 lookup: SeqMap::default(),
1864 variables: SeqMap::default(),
1865 register_watermark: 0, });
1867 }
1868
1869 fn pop_block_scope(&mut self, debug_str: &str) {
1870 self.pop_any_block_scope();
1871 }
1872
1873 fn push_closed_block_scope(&mut self) {
1874 let register_watermark = self.scope.total_scopes.current_register;
1875 self.scope.active_scope.block_scope_stack.push(BlockScope {
1876 mode: BlockScopeMode::Closed,
1877 lookup: Default::default(),
1878 variables: SeqMap::default(),
1879 register_watermark,
1880 });
1881 }
1882
1883 fn pop_closed_block_scope(&mut self) {
1884 self.pop_any_block_scope();
1886 }
1887
1888 fn pop_any_block_scope(&mut self) {
1889 let scope = self.scope.active_scope.block_scope_stack.pop().unwrap();
1890
1891 self.scope.total_scopes.highest_virtual_register = self.scope.total_scopes.current_register;
1893
1894 let is_inside_lambda = self
1896 .scope
1897 .active_scope
1898 .block_scope_stack
1899 .iter()
1900 .any(|s| matches!(s.mode, BlockScopeMode::Lambda));
1901
1902 if matches!(scope.mode, BlockScopeMode::Lambda) {
1903 } else if is_inside_lambda {
1905 } else {
1907 self.scope.total_scopes.current_register = scope.register_watermark;
1909 }
1910 }
1911
1912 fn analyze_match(
1913 &mut self,
1914 scrutinee: &swamp_ast::Expression,
1915 default_context: &TypeContext,
1916 arms: &Vec<swamp_ast::MatchArm>,
1917 ) -> (Match, TypeRef) {
1918 let mut known_type = default_context.expected_type.cloned();
1919 let own_context = default_context.clone();
1920 let scrutinee_context = TypeContext::new_anything_argument(true); let resolved_scrutinee = self.analyze_expression(scrutinee, &scrutinee_context);
1923 let scrutinee_type = resolved_scrutinee.ty.clone();
1924
1925 let mut resolved_arms = Vec::with_capacity(arms.len());
1926
1927 if arms.is_empty() {
1929 let err_match = Match {
1930 expression: Box::new(
1931 self.create_err(ErrorKind::MatchMustHaveAtLeastOneArm, &scrutinee.node),
1932 ),
1933 arms: resolved_arms,
1934 };
1935 return (err_match, self.types().unit());
1936 }
1937
1938 for arm in arms {
1939 let (resolved_arm, _anyone_wants_mutable) = self.analyze_arm(
1940 arm,
1941 &resolved_scrutinee,
1942 &own_context.with_expected_type(known_type.as_ref(), false),
1943 &scrutinee_type,
1944 );
1945
1946 if known_type.is_none() {
1947 known_type = Some(resolved_arm.expression.ty.clone());
1948 }
1949 resolved_arms.push(resolved_arm);
1950 }
1951
1952 if let Some(encountered_type) = known_type {
1953 (
1954 Match {
1955 expression: Box::new(resolved_scrutinee),
1956 arms: resolved_arms,
1957 },
1958 encountered_type,
1959 )
1960 } else {
1961 let err_expr = self.create_err(ErrorKind::MatchArmsMustHaveTypes, &scrutinee.node);
1962
1963 (
1964 Match {
1965 expression: Box::new(err_expr),
1966 arms: resolved_arms.clone(),
1967 },
1968 self.types().unit(),
1969 )
1970 }
1971 }
1972
1973 fn analyze_arm(
1974 &mut self,
1975 arm: &swamp_ast::MatchArm,
1976 _expression: &Expression,
1977 type_context: &TypeContext,
1978 expected_condition_type: &TypeRef,
1979 ) -> (MatchArm, bool) {
1980 let (resolved_pattern, scope_was_pushed, anyone_wants_mutable) =
1981 self.analyze_pattern(&arm.pattern, expected_condition_type);
1982
1983 let resolved_expression = self.analyze_expression(&arm.expression, type_context);
1984 if scope_was_pushed {
1985 self.pop_block_scope("analyze_arm");
1986 }
1987
1988 let resolved_type = resolved_expression.ty.clone();
1989
1990 (
1991 MatchArm {
1992 pattern: resolved_pattern,
1993 expression: Box::from(resolved_expression),
1994 expression_type: resolved_type,
1995 },
1996 anyone_wants_mutable,
1997 )
1998 }
1999
2000 fn str_to_int(text: &str) -> Result<i32, ParseIntError> {
2001 let text = text.replace('_', "");
2002 text.strip_prefix("0x").map_or_else(
2003 || {
2004 text.strip_prefix("-0x").map_or_else(
2005 || text.parse::<i32>(),
2006 |rest| i32::from_str_radix(rest, 16).map(|x| -x),
2007 )
2008 },
2009 |rest| i32::from_str_radix(rest, 16),
2010 )
2011 }
2012
2013 fn str_to_unsigned_int(text: &str) -> Result<u32, ParseIntError> {
2014 let text = text.replace('_', "");
2015 text.strip_prefix("0x")
2016 .map_or_else(|| text.parse::<u32>(), |rest| u32::from_str_radix(rest, 16))
2017 }
2018
2019 fn str_to_float(text: &str) -> Result<f32, ParseFloatError> {
2020 text.parse::<f32>()
2021 }
2022
2023 fn str_to_bool(text: &str) -> Result<bool, ParseBoolError> {
2024 bool::from_str(text)
2025 }
2026
2027 fn analyze_pattern_literal(
2028 &mut self,
2029 node: &swamp_ast::Node,
2030 ast_literal: &swamp_ast::LiteralKind,
2031 expected_condition_type: &TypeRef,
2032 ) -> NormalPattern {
2033 let required_condition_type_context =
2034 TypeContext::new_argument(expected_condition_type, false);
2035 let literal = self.analyze_literal(
2036 node,
2037 ast_literal,
2038 &required_condition_type_context,
2039 &required_condition_type_context,
2040 );
2041
2042 if !self
2043 .types()
2044 .compatible_with(&literal.ty, expected_condition_type)
2045 {
2046 return NormalPattern::Literal(self.create_err(
2047 ErrorKind::IncompatibleTypes {
2048 expected: expected_condition_type.clone(),
2049 found: literal.ty,
2050 },
2051 node,
2052 ));
2053 }
2054
2055 NormalPattern::Literal(literal)
2056 }
2057
2058 const fn to_node(&self, node: &swamp_ast::Node) -> Node {
2059 Node {
2060 span: Span {
2061 file_id: self.shared.file_id,
2062 offset: node.span.offset,
2063 length: node.span.length,
2064 },
2065 }
2066 }
2067
2068 fn get_module_path(&self, module_path: Option<&swamp_ast::ModulePath>) -> Vec<String> {
2069 module_path.as_ref().map_or_else(Vec::new, |found| {
2070 let mut strings = Vec::new();
2071 for path_item in &found.0 {
2072 strings.push(self.get_text(path_item).to_string());
2073 }
2074 strings
2075 })
2076 }
2077
2078 fn get_enum_variant_type(
2079 &mut self,
2080 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2081 variant_name: &str,
2082 ) -> EnumVariantType {
2083 let Some((symbol_table, enum_name)) =
2084 self.get_symbol_table_and_name(qualified_type_identifier)
2085 else {
2086 self.add_err(
2087 ErrorKind::UnknownEnumVariantType,
2088 &qualified_type_identifier.name.0,
2089 );
2090 return EnumVariantType {
2091 common: EnumVariantCommon {
2092 name: Default::default(),
2093 assigned_name: String::new(),
2094 container_index: 0,
2095 },
2096 payload_type: self.types().unit(),
2097 };
2098 };
2099
2100 if let Some(enum_name) = symbol_table.get_enum_variant_type(&enum_name, variant_name) {
2101 enum_name
2102 } else {
2103 self.add_err(
2104 ErrorKind::UnknownEnumVariantType,
2105 &qualified_type_identifier.name.0,
2106 );
2107 EnumVariantType {
2108 common: EnumVariantCommon {
2109 name: Default::default(),
2110 assigned_name: String::new(),
2111 container_index: 0,
2112 },
2113 payload_type: self.types().unit(),
2114 }
2115 }
2116 }
2117
2118 pub(crate) fn get_symbol_table_and_name(
2119 &self,
2120 type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2121 ) -> Option<(&SymbolTable, String)> {
2122 let path = self.get_module_path(type_identifier.module_path.as_ref());
2123 let name = self.get_text(&type_identifier.name.0).to_string();
2124
2125 if let Some(found) = self.shared.get_symbol_table(&path) {
2126 Some((found, name))
2127 } else {
2128 None
2129 }
2130 }
2131
2132 const fn analyze_compound_operator(
2133 &self,
2134 ast_operator: &swamp_ast::CompoundOperator,
2135 ) -> CompoundOperator {
2136 let resolved_node = self.to_node(&ast_operator.node);
2137 let resolved_kind = match ast_operator.kind {
2138 swamp_ast::CompoundOperatorKind::Add => CompoundOperatorKind::Add,
2139 swamp_ast::CompoundOperatorKind::Sub => CompoundOperatorKind::Sub,
2140 swamp_ast::CompoundOperatorKind::Mul => CompoundOperatorKind::Mul,
2141 swamp_ast::CompoundOperatorKind::Div => CompoundOperatorKind::Div,
2142 swamp_ast::CompoundOperatorKind::Modulo => CompoundOperatorKind::Modulo,
2143 };
2144
2145 CompoundOperator {
2146 node: resolved_node,
2147 kind: resolved_kind,
2148 }
2149 }
2150
2151 const fn to_node_option(&self, maybe_node: Option<&swamp_ast::Node>) -> Option<Node> {
2152 match maybe_node {
2153 None => None,
2154 Some(node) => Some(self.to_node(node)),
2155 }
2156 }
2157
2158 const fn analyze_format_specifier(
2159 &self,
2160 ast_format_specifier: Option<&swamp_ast::FormatSpecifier>,
2161 ) -> Option<FormatSpecifier> {
2162 let f = match ast_format_specifier {
2163 None => return None,
2164 Some(ast_format) => match ast_format {
2165 swamp_ast::FormatSpecifier::LowerHex(node) => FormatSpecifier {
2166 node: self.to_node(node),
2167 kind: FormatSpecifierKind::LowerHex,
2168 },
2169 swamp_ast::FormatSpecifier::UpperHex(node) => FormatSpecifier {
2170 node: self.to_node(node),
2171 kind: FormatSpecifierKind::UpperHex,
2172 },
2173 swamp_ast::FormatSpecifier::Binary(node) => FormatSpecifier {
2174 node: self.to_node(node),
2175 kind: FormatSpecifierKind::Binary,
2176 },
2177 swamp_ast::FormatSpecifier::Float(node) => FormatSpecifier {
2178 node: self.to_node(node),
2179 kind: FormatSpecifierKind::Float,
2180 },
2181 swamp_ast::FormatSpecifier::Precision(value, node, x) => {
2182 let (precision_type, precision_node) = match x {
2183 swamp_ast::PrecisionType::Float(node) => {
2184 (PrecisionType::Float, self.to_node(node))
2185 }
2186 swamp_ast::PrecisionType::String(node) => {
2187 (PrecisionType::String, self.to_node(node))
2188 }
2189 };
2190 FormatSpecifier {
2191 node: self.to_node(node),
2192 kind: FormatSpecifierKind::Precision(
2193 *value,
2194 precision_node,
2195 precision_type,
2196 ),
2197 }
2198 }
2199 },
2200 };
2201
2202 Some(f)
2203 }
2204
2205 fn analyze_with_expr(
2206 &mut self,
2207 context: &TypeContext,
2208 variables: &[swamp_ast::VariableBinding],
2209 expression: &swamp_ast::Expression,
2210 ) -> Expression {
2211 let mut variable_expressions = Vec::new();
2212
2213 for variable in variables {
2214 let any_context = TypeContext::new_anything_argument(false);
2215 let must_have_expression = if let Some(x) = &variable.expression {
2216 x
2217 } else {
2218 &swamp_ast::Expression {
2219 kind: swamp_ast::ExpressionKind::VariableReference(variable.variable.clone()),
2220 node: variable.variable.name.clone(),
2221 }
2222 };
2223
2224 let location_side = if variable.variable.is_mutable.is_some() {
2226 if let Some(expr) = &variable.expression {
2228 let maybe_ref = self.analyze_maybe_ref_expression(expr);
2230 if maybe_ref.has_borrow_mutable_reference.is_some() {
2231 LocationSide::Mutable
2232 } else {
2233 LocationSide::Rhs
2234 }
2235 } else {
2236 LocationSide::Rhs
2238 }
2239 } else {
2240 LocationSide::Rhs
2242 };
2243
2244 let var = self.analyze_mut_or_immutable_expression(
2245 must_have_expression,
2246 &any_context,
2247 location_side,
2248 );
2249
2250 variable_expressions.push(var);
2251 }
2252
2253 self.push_closed_block_scope();
2254 let mut expressions = Vec::new();
2255 for (variable_binding, resolved_expression) in variables.iter().zip(variable_expressions) {
2256 let initialize_variable_expression = self
2257 .create_variable_binding_for_with(&variable_binding.variable, resolved_expression);
2258
2259 expressions.push(initialize_variable_expression);
2263 }
2264
2265 let resolved_expression = self.analyze_expression(expression, context);
2266 let block_type = self.types().unit();
2268 expressions.push(resolved_expression);
2269
2270 let block_expression_kind = ExpressionKind::Block(expressions);
2271 self.pop_closed_block_scope();
2272
2273 self.create_expr(block_expression_kind, block_type, &expression.node)
2274 }
2275
2276 fn analyze_when_expr(
2277 &mut self,
2278 context: &TypeContext,
2279 variables: &[swamp_ast::VariableBinding],
2280 true_expr: &swamp_ast::Expression,
2281 else_expr: Option<&swamp_ast::Expression>,
2282 ) -> Expression {
2283 self.push_block_scope("when");
2285 let mut bindings = Vec::new();
2286 for variable_binding in variables {
2287 let mut_expr = if let Some(found_expr) = &variable_binding.expression {
2288 let any_context = TypeContext::new_anything_argument(true); self.analyze_mut_or_immutable_expression(
2290 found_expr,
2291 &any_context,
2292 LocationSide::Rhs,
2293 )
2294 .expect_immutable()
2295 .unwrap()
2296 } else {
2297 let same_var = self.find_variable(&variable_binding.variable);
2298
2299 let generated_expr_kind = ExpressionKind::VariableAccess(same_var.clone());
2302 self.create_expr(
2303 generated_expr_kind,
2304 same_var.resolved_type.clone(),
2305 &variable_binding.variable.name,
2306 )
2307 };
2308
2309 let tk = &mut_expr.ty.kind;
2310
2311 if let TypeKind::Optional(found_ty) = &**tk {
2312 let variable_ref = self.create_variable(&variable_binding.variable, found_ty);
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));
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 if !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
2960 SingleLocationExpression {
2961 kind: MutableReferenceKind::MutVariableRef,
2962 node: self.to_node(&chain.base.node),
2963 ty,
2964 starting_variable: start_variable,
2965 access_chain: items,
2966 }
2967 }
2968
2969 fn analyze_to_location(
2970 &mut self,
2971 expr: &swamp_ast::Expression,
2972 context: &TypeContext,
2973 location_type: LocationSide,
2974 ) -> SingleLocationExpression {
2975 match &expr.kind {
2976 swamp_ast::ExpressionKind::PostfixChain(chain) => {
2977 self.analyze_chain_to_location(chain, context, location_type)
2978 }
2979 swamp_ast::ExpressionKind::VariableReference(variable) => {
2980 let var = self.find_variable(variable);
2981 if !var.is_mutable() {
2982 self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
2983 }
2984
2985 SingleLocationExpression {
2986 kind: MutableReferenceKind::MutVariableRef,
2987 node: self.to_node(&variable.name),
2988 ty: var.resolved_type.clone(),
2989 starting_variable: var,
2990 access_chain: vec![],
2991 }
2992 }
2993 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
2994 let generated_var = swamp_ast::Variable {
2995 name: qualified_identifier.name.clone(),
2996 is_mutable: None,
2997 };
2998 let var = self.find_variable(&generated_var);
2999 if !var.is_mutable() {
3000 self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
3001 }
3002 SingleLocationExpression {
3003 kind: MutableReferenceKind::MutVariableRef,
3004 node: self.to_node(&generated_var.name),
3005 ty: var.resolved_type.clone(),
3006 starting_variable: var,
3007 access_chain: vec![],
3008 }
3009 }
3010 _ => {
3011 self.add_err(ErrorKind::NotValidLocationStartingPoint, &expr.node);
3012 let unit_type = self.types().unit();
3013 SingleLocationExpression {
3014 kind: MutableReferenceKind::MutVariableRef,
3015 node: self.to_node(&expr.node),
3016 ty: unit_type.clone(),
3017 starting_variable: Rc::new(Variable {
3018 name: Default::default(),
3019 assigned_name: String::new(),
3020 resolved_type: unit_type,
3021 mutable_node: None,
3022 variable_type: VariableType::Local,
3023 scope_index: 0,
3024 variable_index: 0,
3025 unique_id_within_function: 0,
3026 virtual_register: 0,
3027 is_unused: false,
3028 }),
3029 access_chain: vec![],
3030 }
3031 }
3032 }
3033 }
3034
3035 fn analyze_expression_for_assignment_compound(
3036 &mut self,
3037 target_expression: &swamp_ast::Expression,
3038 ast_source_expression: &swamp_ast::Expression,
3039 ) -> (TargetAssignmentLocation, Expression) {
3040 let any_argument_context = TypeContext::new_anything_argument(true);
3041 let source_expr = self.analyze_expression(ast_source_expression, &any_argument_context);
3042 let source_expr_type_context = TypeContext::new_argument(&source_expr.ty, true);
3043
3044 let resolved_location = TargetAssignmentLocation(self.analyze_to_location(
3045 target_expression,
3046 &source_expr_type_context,
3047 LocationSide::Rhs,
3048 ));
3049
3050 (resolved_location, source_expr)
3051 }
3052
3053 fn analyze_expression_for_assignment_with_target_type(
3080 &mut self,
3081 target_type: &TypeRef,
3082 ast_source_expression: &swamp_ast::Expression,
3083 ) -> Expression {
3084 let base_context = TypeContext::new_argument(target_type, true);
3085 let source_expr = self.analyze_expression(ast_source_expression, &base_context);
3086
3087 let final_expr = if self.types().compatible_with(target_type, &source_expr.ty) {
3088 source_expr
3089 } else {
3090 let source_type = source_expr.ty.clone();
3091 self.types_did_not_match_try_late_coerce_expression(
3092 source_expr,
3093 target_type,
3094 &source_type,
3095 &ast_source_expression.node,
3096 )
3097 };
3098
3099 let assignment_mode = self.check_assignment_mode(true, &final_expr, target_type); self.check_mutable_assignment(assignment_mode, &final_expr.node);
3102
3103 final_expr
3104 }
3105
3106 fn analyze_expression_for_assignment(
3107 &mut self,
3108 ast_target_location_expression: &swamp_ast::Expression,
3109 ast_source_expression: &swamp_ast::Expression,
3110 ) -> (TargetAssignmentLocation, Expression) {
3111 let any_argument_context = TypeContext::new_anything_argument(true);
3112 let resolved_location = self.analyze_to_location(
3113 ast_target_location_expression,
3114 &any_argument_context,
3115 LocationSide::Lhs,
3116 );
3117
3118 let target_type = resolved_location.ty.clone();
3119 let mut_type = target_type; let mut_location = TargetAssignmentLocation(resolved_location);
3121
3122 let final_expr = self
3123 .analyze_expression_for_assignment_with_target_type(&mut_type, ast_source_expression);
3124
3125 (mut_location, final_expr)
3126 }
3127
3128 fn analyze_assignment_compound(
3129 &mut self,
3130 target_expression: &swamp_ast::Expression,
3131 ast_op: &swamp_ast::CompoundOperator,
3132 ast_source_expression: &swamp_ast::Expression,
3133 ) -> Expression {
3134 let resolved_op = self.analyze_compound_operator(ast_op);
3135
3136 let (resolved_location, source_expr) = self
3137 .analyze_expression_for_assignment_compound(target_expression, ast_source_expression);
3138
3139 let kind = ExpressionKind::CompoundAssignment(
3140 resolved_location,
3141 resolved_op.kind,
3142 Box::from(source_expr),
3143 );
3144
3145 let unit_type = self.shared.state.types.unit();
3146
3147 self.create_expr(kind, unit_type, &target_expression.node)
3148 }
3149
3150 fn analyze_assignment_mode(lhs: SingleLocationExpression) {}
3151
3152 fn analyze_assignment(
3153 &mut self,
3154 target_location: &swamp_ast::Expression,
3155 ast_source_expression: &swamp_ast::Expression,
3156 ) -> Expression {
3157 let (mut_location, source_expr) =
3158 self.analyze_expression_for_assignment(target_location, ast_source_expression);
3159 let kind = ExpressionKind::Assignment(Box::from(mut_location), Box::from(source_expr));
3160 let unit_type = self.shared.state.types.unit();
3161
3162 self.create_expr(kind, unit_type, &target_location.node)
3165 }
3166
3167 #[must_use]
3168 pub const fn create_expr(
3169 &self,
3170 kind: ExpressionKind,
3171 ty: TypeRef,
3172 ast_node: &swamp_ast::Node,
3173 ) -> Expression {
3174 Expression {
3176 kind,
3177 ty,
3178 node: self.to_node(ast_node),
3179 }
3180 }
3181
3182 fn analyze_destructuring(
3183 &mut self,
3184 node: &swamp_ast::Node,
3185 target_ast_variables: &[swamp_ast::Variable],
3186 tuple_expression: &swamp_ast::Expression,
3187 ) -> Expression {
3188 let any_context = TypeContext::new_anything_argument(true);
3189 let tuple_resolved = self.analyze_expression(tuple_expression, &any_context);
3190 let tuple_expr_type = &tuple_resolved.ty;
3191 let unit = self.types().unit();
3192
3193 let mut variable_refs = Vec::new();
3194 if let TypeKind::Tuple(tuple) = &*tuple_expr_type.kind {
3195 if target_ast_variables.len() > tuple.len() {
3196 return self.create_err(ErrorKind::TooManyDestructureVariables, node);
3197 }
3198 for (ast_variable, tuple_type) in target_ast_variables.iter().zip(tuple.clone()) {
3199 let variable_ref = self.create_local_variable(
3200 &ast_variable.name,
3201 ast_variable.is_mutable.as_ref(),
3202 &tuple_type,
3203 true,
3204 );
3205 variable_refs.push(variable_ref);
3206 }
3207 let expr_kind = ExpressionKind::TupleDestructuring(
3208 variable_refs,
3209 tuple_expr_type.clone(),
3210 Box::from(tuple_resolved),
3211 );
3212
3213 self.create_expr(expr_kind, unit, node)
3214 } else {
3215 self.create_err(ErrorKind::CanNotDestructure, node)
3216 }
3217 }
3218
3219 fn analyze_normal_member_call(
3220 &mut self,
3221 type_that_member_is_on: &TypeRef,
3222 found_function: &FunctionRef,
3223 generic_arguments: Vec<TypeRef>,
3224 ast_arguments: &[swamp_ast::Expression],
3225 is_mutable: bool,
3226 node: &swamp_ast::Node,
3227 ) -> Signature {
3228 let resolved_node = self.to_node(node);
3229 found_function.signature().clone()
3232 }
3233
3234 fn queue_member_signature(
3235 &mut self,
3236 self_type: &TypeRef,
3237 key_type: Option<&TypeRef>,
3238 element_type: &TypeRef,
3239 field_name_str: &str,
3240 lambda_variable_count: usize,
3241 node: &swamp_ast::Node,
3242 ) -> Option<(IntrinsicFunction, Signature)> {
3243 let self_type_param = TypeForParameter {
3244 name: "self".to_string(),
3245 resolved_type: self_type.clone(),
3246 is_mutable: false,
3247 node: None,
3248 };
3249 let self_mutable_type_param = TypeForParameter {
3250 name: "self".to_string(),
3251 resolved_type: self_type.clone(),
3252 is_mutable: true,
3253 node: None,
3254 };
3255 let intrinsic_and_signature = match field_name_str {
3256 "enqueue" => (
3257 IntrinsicFunction::VecPush,
3258 Signature {
3259 parameters: vec![
3260 self_mutable_type_param,
3261 TypeForParameter {
3262 name: "element".to_string(),
3263 resolved_type: element_type.clone(),
3264 is_mutable: false,
3265 node: None,
3266 },
3267 ],
3268 return_type: self.types().unit(),
3269 },
3270 ),
3271 "dequeue" => (
3272 IntrinsicFunction::VecRemoveFirstIndexGetValue,
3273 Signature {
3274 parameters: vec![self_mutable_type_param],
3275 return_type: element_type.clone(),
3276 },
3277 ),
3278 _ => {
3279 self.slice_member_signature(
3280 self_type,
3281 key_type,
3282 element_type,
3283 field_name_str,
3284 lambda_variable_count,
3285 node,
3286 )
3287 }?,
3288 };
3289
3290 Some(intrinsic_and_signature)
3291 }
3292
3293 fn sparse_member_signature(
3294 &mut self,
3295 self_type: &TypeRef,
3296 element_type: &TypeRef,
3297 field_name_str: &str,
3298 lambda_variable_count: usize,
3299 node: &swamp_ast::Node,
3300 ) -> Option<(IntrinsicFunction, Signature)> {
3301 let key_type = self.types().int(); let self_type_param = TypeForParameter {
3304 name: "self".to_string(),
3305 resolved_type: self_type.clone(),
3306 is_mutable: false,
3307 node: None,
3308 };
3309 let self_mutable_type_param = TypeForParameter {
3310 name: "self".to_string(),
3311 resolved_type: self_type.clone(),
3312 is_mutable: true,
3313 node: None,
3314 };
3315 let intrinsic_and_signature = match field_name_str {
3316 "add" => (
3317 IntrinsicFunction::SparseAdd,
3318 Signature {
3319 parameters: vec![
3320 self_mutable_type_param,
3321 TypeForParameter {
3322 name: "element".to_string(),
3323 resolved_type: element_type.clone(),
3324 is_mutable: false,
3325 node: None,
3326 },
3327 ],
3328 return_type: self.types().int(),
3329 },
3330 ),
3331 "remove" => (
3332 IntrinsicFunction::SparseRemove,
3333 Signature {
3334 parameters: vec![
3335 self_mutable_type_param,
3336 TypeForParameter {
3337 name: "key".to_string(),
3338 resolved_type: key_type,
3339 is_mutable: false,
3340 node: None,
3341 },
3342 ],
3343 return_type: self.types().unit(),
3344 },
3345 ),
3346 "is_alive" => (
3347 IntrinsicFunction::SparseIsAlive,
3348 Signature {
3349 parameters: vec![
3350 self_type_param,
3351 TypeForParameter {
3352 name: "element".to_string(),
3353 resolved_type: element_type.clone(),
3354 is_mutable: false,
3355 node: None,
3356 },
3357 ],
3358 return_type: self.types().bool(),
3359 },
3360 ),
3361
3362 _ => {
3363 self.slice_member_signature(
3364 self_type,
3365 Option::from(key_type).as_ref(),
3366 element_type,
3367 field_name_str,
3368 lambda_variable_count,
3369 node,
3370 )
3371 }?,
3372 };
3373 Some(intrinsic_and_signature)
3374 }
3375
3376 fn vec_member_signature(
3377 &mut self,
3378 self_type: &TypeRef,
3379 element_type: &TypeRef,
3380 field_name_str: &str,
3381 lambda_variable_count: usize,
3382 node: &swamp_ast::Node,
3383 ) -> Option<(IntrinsicFunction, Signature)> {
3384 let key_type = self.types().int();
3385 let self_type_param = TypeForParameter {
3386 name: "self".to_string(),
3387 resolved_type: self_type.clone(),
3388 is_mutable: false,
3389 node: None,
3390 };
3391 let self_mutable_type_param = TypeForParameter {
3392 name: "self".to_string(),
3393 resolved_type: self_type.clone(),
3394 is_mutable: true,
3395 node: None,
3396 };
3397 let intrinsic_and_signature = match field_name_str {
3398 "prepend" => (
3399 IntrinsicFunction::VecPush,
3400 Signature {
3401 parameters: vec![
3402 self_mutable_type_param,
3403 TypeForParameter {
3404 name: "element".to_string(),
3405 resolved_type: element_type.clone(),
3406 is_mutable: false,
3407 node: None,
3408 },
3409 ],
3410 return_type: self.types().unit(),
3411 },
3412 ),
3413 "push" => (
3414 IntrinsicFunction::VecPush,
3415 Signature {
3416 parameters: vec![
3417 self_mutable_type_param,
3418 TypeForParameter {
3419 name: "element".to_string(),
3420 resolved_type: element_type.clone(),
3421 is_mutable: false,
3422 node: None,
3423 },
3424 ],
3425 return_type: self.types().unit(),
3426 },
3427 ),
3428 "pop" => (
3429 IntrinsicFunction::VecPop,
3430 Signature {
3431 parameters: vec![self_mutable_type_param],
3432 return_type: element_type.clone(),
3433 },
3434 ),
3435
3436 "slice" => {
3437 let range_type = self.types().range_int();
3438 (
3439 IntrinsicFunction::VecSlice,
3440 Signature {
3441 parameters: vec![self_type_param,
3442 TypeForParameter {
3443 name: "range".to_string(),
3444 resolved_type: range_type,
3445 is_mutable: false,
3446 node: None,
3447 }, ],
3448 return_type: self_type.clone(),
3449 },
3450 )
3451 }
3452
3453 _ => {
3454 self.slice_member_signature(
3455 self_type,
3456 Option::from(key_type).as_ref(),
3457 element_type,
3458 field_name_str,
3459 lambda_variable_count,
3460 node,
3461 )
3462 }?,
3463 };
3464 Some(intrinsic_and_signature)
3465 }
3466
3467 #[allow(clippy::unnecessary_wraps)]
3468 fn grid_member_signature(
3469 &mut self,
3470 self_type: &TypeRef,
3471 element_type: &TypeRef,
3472 field_name_str: &str,
3473 node: &swamp_ast::Node,
3474 ) -> Option<(IntrinsicFunction, Signature)> {
3475 let self_type_param = TypeForParameter {
3476 name: "self".to_string(),
3477 resolved_type: self_type.clone(),
3478 is_mutable: false,
3479 node: None,
3480 };
3481 let self_mutable_type_param = TypeForParameter {
3482 name: "self".to_string(),
3483 resolved_type: self_type.clone(),
3484 is_mutable: true,
3485 node: None,
3486 };
3487 let element_param = TypeForParameter {
3488 name: "element".to_string(),
3489 resolved_type: element_type.clone(),
3490 is_mutable: false,
3491 node: None,
3492 };
3493 let int_type = self.types().int();
3494
3495 let int_param = TypeForParameter {
3496 name: "x_or_y".to_string(),
3497 resolved_type: int_type.clone(),
3498 is_mutable: false,
3499 node: None,
3500 };
3501 let intrinsic_and_signature = match field_name_str {
3502 "set" => (
3503 IntrinsicFunction::GridSet,
3504 Signature {
3505 parameters: vec![self_type_param, int_param.clone(), int_param, element_param],
3506 return_type: self.types().unit(),
3507 },
3508 ),
3509
3510 "get" => (
3511 IntrinsicFunction::GridGet,
3512 Signature {
3513 parameters: vec![self_type_param, int_param.clone(), int_param],
3514 return_type: element_type.clone(),
3515 },
3516 ),
3517
3518 "width" => (
3519 IntrinsicFunction::GridWidth,
3520 Signature {
3521 parameters: vec![self_type_param],
3522 return_type: int_type,
3523 },
3524 ),
3525
3526 "height" => (
3527 IntrinsicFunction::GridHeight,
3528 Signature {
3529 parameters: vec![self_type_param],
3530 return_type: int_type,
3531 },
3532 ),
3533
3534 _ => panic!("unknown grid method {field_name_str}"),
3535 };
3536
3537 Some(intrinsic_and_signature)
3538 }
3539
3540 fn basic_collection_member_signature(
3541 &mut self,
3542 self_type: &TypeRef,
3543 field_name_str: &str,
3544 node: &swamp_ast::Node,
3545 ) -> Option<(IntrinsicFunction, Signature)> {
3546 let self_type_param = TypeForParameter {
3547 name: "self".to_string(),
3548 resolved_type: self_type.clone(),
3549 is_mutable: false,
3550 node: None,
3551 };
3552 let self_mut_type_param = TypeForParameter {
3553 name: "self".to_string(),
3554 resolved_type: self_type.clone(),
3555 is_mutable: true,
3556 node: None,
3557 };
3558 let intrinsic_and_signature = match field_name_str {
3559 "len" => {
3560 let signature = Signature {
3561 parameters: vec![self_type_param],
3562 return_type: self.types().int(),
3563 };
3564 (IntrinsicFunction::VecLen, signature)
3565 }
3566 "is_empty" => (
3567 IntrinsicFunction::VecIsEmpty,
3568 Signature {
3569 parameters: vec![self_type_param],
3570 return_type: self.types().bool(),
3571 },
3572 ),
3573 "capacity" => {
3574 let signature = Signature {
3575 parameters: vec![self_type_param],
3576 return_type: self.types().int(),
3577 };
3578 (IntrinsicFunction::VecCapacity, signature)
3579 }
3580 _ => {
3581 self.add_err(ErrorKind::UnknownMemberFunction(self_type.clone()), node);
3582
3583 return None;
3584 }
3585 };
3586 Some(intrinsic_and_signature)
3587 }
3588 #[allow(clippy::too_many_lines)]
3589 fn codepoint_member_signature(
3590 &mut self,
3591 self_type: &TypeRef,
3592 key_type: Option<&TypeRef>,
3593 element_type: &TypeRef,
3594 field_name_str: &str,
3595 lambda_variable_count: usize,
3596 node: &swamp_ast::Node,
3597 ) -> Option<(IntrinsicFunction, Signature)> {
3598 let self_type_param = TypeForParameter {
3599 name: "self".to_string(),
3600 resolved_type: self_type.clone(),
3601 is_mutable: false,
3602 node: None,
3603 };
3604
3605 match field_name_str {
3606 "to_int" => Some((
3607 IntrinsicFunction::CodepointToInt,
3608 Signature {
3609 parameters: vec![self_type_param],
3610 return_type: self.types().int(),
3611 },
3612 )),
3613 _ => None,
3614 }
3615 }
3616
3617 #[allow(clippy::too_many_lines)]
3618 fn byte_member_signature(
3619 &mut self,
3620 self_type: &TypeRef,
3621 key_type: Option<&TypeRef>,
3622 element_type: &TypeRef,
3623 field_name_str: &str,
3624 lambda_variable_count: usize,
3625 node: &swamp_ast::Node,
3626 ) -> Option<(IntrinsicFunction, Signature)> {
3627 let self_type_param = TypeForParameter {
3628 name: "self".to_string(),
3629 resolved_type: self_type.clone(),
3630 is_mutable: false,
3631 node: None,
3632 };
3633
3634 match field_name_str {
3635 "to_int" => Some((
3636 IntrinsicFunction::ByteToInt,
3637 Signature {
3638 parameters: vec![self_type_param],
3639 return_type: self.types().int(),
3640 },
3641 )),
3642 _ => None,
3643 }
3644 }
3645
3646 #[allow(clippy::too_many_lines)]
3647 fn string_member_signature(
3648 &mut self,
3649 self_type: &TypeRef,
3650 key_type: Option<&TypeRef>,
3651 element_type: &TypeRef,
3652 field_name_str: &str,
3653 lambda_variable_count: usize,
3654 node: &swamp_ast::Node,
3655 ) -> Option<(IntrinsicFunction, Signature)> {
3656 self.vec_member_signature(
3657 self_type,
3658 element_type,
3659 field_name_str,
3660 lambda_variable_count,
3661 node,
3662 )
3663 }
3664
3665 #[allow(clippy::too_many_lines)]
3666 fn slice_member_signature(
3667 &mut self,
3668 self_type: &TypeRef,
3669 key_type: Option<&TypeRef>,
3670 element_type: &TypeRef,
3671 field_name_str: &str,
3672 lambda_variable_count: usize,
3673 node: &swamp_ast::Node,
3674 ) -> Option<(IntrinsicFunction, Signature)> {
3675 let slice_view_type = self.types().slice_view(&element_type.clone());
3676 let int_type = self.types().int();
3677 let self_type_param = TypeForParameter {
3678 name: "self".to_string(),
3679 resolved_type: slice_view_type.clone(),
3680 is_mutable: false,
3681 node: None,
3682 };
3683 let self_mut_type_param = TypeForParameter {
3684 name: "self".to_string(),
3685 resolved_type: slice_view_type,
3686 is_mutable: true,
3687 node: None,
3688 };
3689 let intrinsic_and_signature = match field_name_str {
3690 "for" => {
3691 let parameters = if lambda_variable_count == 2 {
3692 vec![
3693 TypeForParameter {
3694 name: "key".to_string(),
3695 resolved_type: key_type.unwrap().clone(),
3696 is_mutable: false,
3697 node: None,
3698 },
3699 TypeForParameter {
3700 name: "element".to_string(),
3701 resolved_type: element_type.clone(),
3702 is_mutable: false,
3703 node: None,
3704 },
3705 ]
3706 } else {
3707 vec![TypeForParameter {
3708 name: "element".to_string(),
3709 resolved_type: element_type.clone(),
3710 is_mutable: false,
3711 node: None,
3712 }]
3713 };
3714 let lambda_signature = Signature {
3715 parameters,
3716 return_type: self.types().unit(),
3717 };
3718 let lambda_function_type = self.types().function(lambda_signature);
3719 (
3720 IntrinsicFunction::TransformerFor,
3721 Signature {
3722 parameters: vec![
3723 self_type_param,
3724 TypeForParameter {
3725 name: "lambda".to_string(),
3726 resolved_type: lambda_function_type,
3727 is_mutable: false,
3728 node: None,
3729 },
3730 ],
3731 return_type: self.types().unit(), },
3733 )
3734 }
3735 "while" => {
3736 let parameters = if lambda_variable_count == 2 {
3737 vec![
3738 TypeForParameter {
3739 name: "key".to_string(),
3740 resolved_type: key_type.unwrap().clone(),
3741 is_mutable: false,
3742 node: None,
3743 },
3744 TypeForParameter {
3745 name: "element".to_string(),
3746 resolved_type: element_type.clone(),
3747 is_mutable: false,
3748 node: None,
3749 },
3750 ]
3751 } else {
3752 vec![TypeForParameter {
3753 name: "element".to_string(),
3754 resolved_type: element_type.clone(),
3755 is_mutable: false,
3756 node: None,
3757 }]
3758 };
3759 let lambda_signature = Signature {
3760 parameters,
3761 return_type: self.types().bool(), };
3763 let lambda_function_type = self.types().function(lambda_signature);
3764 (
3765 IntrinsicFunction::TransformerWhile,
3766 Signature {
3767 parameters: vec![
3768 self_type_param,
3769 TypeForParameter {
3770 name: "lambda".to_string(),
3771 resolved_type: lambda_function_type,
3772 is_mutable: false,
3773 node: None,
3774 },
3775 ],
3776 return_type: self.types().unit(), },
3778 )
3779 }
3780 "filter" => {
3781 let lambda_signature = Signature {
3782 parameters: vec![TypeForParameter {
3783 name: "element".to_string(),
3784 resolved_type: element_type.clone(),
3785 is_mutable: false,
3786 node: None,
3787 }],
3788 return_type: self.types().bool(),
3789 };
3790 let lambda_function_type = self.types().function(lambda_signature);
3791 (
3792 IntrinsicFunction::TransformerFilter,
3793 Signature {
3794 parameters: vec![
3795 self_type_param,
3796 TypeForParameter {
3797 name: "lambda".to_string(),
3798 resolved_type: lambda_function_type,
3799 is_mutable: false,
3800 node: None,
3801 },
3802 ],
3803 return_type: self.shared.state.types.slice_view(&element_type.clone()),
3804 },
3805 )
3806 }
3807 "find" => {
3808 let lambda_signature = Signature {
3809 parameters: vec![TypeForParameter {
3810 name: "element".to_string(),
3811 resolved_type: element_type.clone(),
3812 is_mutable: false,
3813 node: None,
3814 }],
3815 return_type: self.types().bool(),
3816 };
3817 let lambda_function_type = self.types().function(lambda_signature);
3818 (
3819 IntrinsicFunction::TransformerFind,
3820 Signature {
3821 parameters: vec![
3822 self_type_param,
3823 TypeForParameter {
3824 name: "lambda".to_string(),
3825 resolved_type: lambda_function_type,
3826 is_mutable: false,
3827 node: None,
3828 },
3829 ],
3830 return_type: self.shared.state.types.optional(&element_type.clone()),
3831 },
3832 )
3833 }
3834
3835 "remove" => {
3836 let signature = Signature {
3837 parameters: vec![
3838 self_mut_type_param,
3839 TypeForParameter {
3840 name: "index".to_string(),
3841 resolved_type: int_type,
3842 is_mutable: false,
3843 node: None,
3844 },
3845 ],
3846 return_type: self.types().unit(),
3847 };
3848 (IntrinsicFunction::VecRemoveIndex, signature)
3849 }
3850 _ => return self.basic_collection_member_signature(self_type, field_name_str, node),
3851 };
3852 Some(intrinsic_and_signature)
3853 }
3854
3855 #[allow(clippy::unnecessary_wraps, clippy::result_large_err)]
3856 fn map_member_signature(
3857 &mut self,
3858 self_type: &TypeRef,
3859 key_type: &TypeRef,
3860 value_type: &TypeRef,
3861 field_name_str: &str,
3862 node: &swamp_ast::Node,
3863 ) -> Option<(IntrinsicFunction, Signature)> {
3864 let self_type_param = TypeForParameter {
3865 name: "self".to_string(),
3866 resolved_type: self_type.clone(),
3867 is_mutable: false,
3868 node: None,
3869 };
3870
3871 let mutable_self_type_param = TypeForParameter {
3872 name: "self".to_string(),
3873 resolved_type: self_type.clone(),
3874 is_mutable: true,
3875 node: None,
3876 };
3877
3878 let intrinsic_and_signature = match field_name_str {
3879 "has" => (
3880 IntrinsicFunction::MapHas,
3881 Signature {
3882 parameters: vec![
3883 self_type_param,
3884 TypeForParameter {
3885 name: "key".to_string(),
3886 resolved_type: key_type.clone(),
3887 is_mutable: false,
3888 node: None,
3889 },
3890 ],
3891 return_type: self.types().bool(),
3892 },
3893 ),
3894 "remove" => (
3895 IntrinsicFunction::MapRemove,
3896 Signature {
3897 parameters: vec![
3898 mutable_self_type_param,
3899 TypeForParameter {
3900 name: "key".to_string(),
3901 resolved_type: key_type.clone(),
3902 is_mutable: false,
3903 node: None,
3904 },
3905 ],
3906 return_type: self.types().unit(),
3907 },
3908 ),
3909 "len" => (
3910 IntrinsicFunction::MapLen,
3911 Signature {
3912 parameters: vec![self_type_param],
3913 return_type: self.types().int(),
3914 },
3915 ),
3916 "capacity" => (
3917 IntrinsicFunction::MapCapacity,
3918 Signature {
3919 parameters: vec![self_type_param],
3920 return_type: self.types().int(),
3921 },
3922 ),
3923 "is_empty" => (
3924 IntrinsicFunction::MapIsEmpty,
3925 Signature {
3926 parameters: vec![self_type_param],
3927 return_type: self.types().bool(),
3928 },
3929 ),
3930 _ => todo!("unknown map member"),
3931 };
3932
3933 Some(intrinsic_and_signature)
3934 }
3935
3936 fn check_intrinsic_member_signature(
3937 &mut self,
3938 type_that_member_is_on: &TypeRef,
3939 field_name_str: &str,
3940 lambda_variables_count: usize,
3941 node: &swamp_ast::Node,
3942 ) -> Option<(IntrinsicFunction, Signature)> {
3943 let ty = type_that_member_is_on;
3944 let int_type = self.types().int();
3945 match &*ty.kind {
3946 TypeKind::GridStorage(element_type, ..) | TypeKind::GridView(element_type) => self
3947 .grid_member_signature(type_that_member_is_on, element_type, field_name_str, node),
3948 TypeKind::SparseStorage(element_type, ..) | TypeKind::SparseView(element_type) => self
3949 .sparse_member_signature(
3950 type_that_member_is_on,
3951 element_type,
3952 field_name_str,
3953 lambda_variables_count,
3954 node,
3955 ),
3956 TypeKind::QueueStorage(element_type, ..) => self.queue_member_signature(
3957 type_that_member_is_on,
3958 None,
3959 element_type,
3960 field_name_str,
3961 lambda_variables_count,
3962 node,
3963 ),
3964 TypeKind::StackStorage(element_type, ..)
3965 | TypeKind::QueueStorage(element_type, ..)
3966 | TypeKind::VecStorage(element_type, ..)
3967 | TypeKind::DynamicLengthVecView(element_type) => self.vec_member_signature(
3968 type_that_member_is_on,
3969 element_type,
3970 field_name_str,
3971 lambda_variables_count,
3972 node,
3973 ),
3974 TypeKind::SliceView(element_type) => self.slice_member_signature(
3975 type_that_member_is_on,
3976 Some(&int_type),
3977 element_type,
3978 field_name_str,
3979 lambda_variables_count,
3980 node,
3981 ),
3982 TypeKind::Byte => {
3983 let element_type = self.shared.state.types.byte();
3984 self.byte_member_signature(
3985 type_that_member_is_on,
3986 Some(&int_type),
3987 &element_type,
3988 field_name_str,
3989 lambda_variables_count,
3990 node,
3991 )
3992 }
3993 TypeKind::Codepoint => {
3994 let element_type = self.shared.state.types.codepoint();
3995 self.codepoint_member_signature(
3996 type_that_member_is_on,
3997 Some(&int_type),
3998 &element_type,
3999 field_name_str,
4000 lambda_variables_count,
4001 node,
4002 )
4003 }
4004 TypeKind::String { .. } | TypeKind::StringStorage(..) => {
4005 let element_type = self.shared.state.types.byte();
4006 self.string_member_signature(
4007 type_that_member_is_on,
4008 Some(&int_type),
4009 &element_type,
4010 field_name_str,
4011 lambda_variables_count,
4012 node,
4013 )
4014 }
4015 TypeKind::DynamicLengthMapView(key, value) | TypeKind::MapStorage(key, value, _) => {
4016 self.map_member_signature(type_that_member_is_on, key, value, field_name_str, node)
4017 }
4018
4019 TypeKind::FixedCapacityAndLengthArray(element_type, _) => self.slice_member_signature(
4020 type_that_member_is_on,
4021 Some(&int_type),
4022 element_type,
4023 field_name_str,
4024 lambda_variables_count,
4025 node,
4026 ),
4027 _ => {
4028 self.add_err(
4029 ErrorKind::UnknownMemberFunction(type_that_member_is_on.clone()),
4030 node,
4031 );
4032
4033 None
4034 }
4035 }
4036 }
4037
4038 fn analyze_member_call(
4039 &mut self,
4040 type_that_member_is_on: &TypeRef,
4041 field_name_str: &str,
4042 ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4043 ast_arguments: &[swamp_ast::Expression],
4044 chain_self_is_mutable: bool,
4045 node: &swamp_ast::Node,
4046 ) -> (PostfixKind, TypeRef) {
4047 let generic_arguments = if let Some(ast_generic_arguments) = ast_maybe_generic_arguments {
4048 let mut resolved_types = Vec::new();
4049 for ast_type in ast_generic_arguments {
4050 resolved_types.push(self.analyze_type(ast_type.get_type()));
4051 }
4052 resolved_types
4053 } else {
4054 vec![]
4055 };
4056
4057 let maybe_function = self
4058 .shared
4059 .state
4060 .associated_impls
4061 .get_member_function(type_that_member_is_on, field_name_str)
4062 .cloned();
4063
4064 let (function_ref, instantiated_signature) = if let Some(found_function) = maybe_function {
4065 let signature = self.analyze_normal_member_call(
4066 type_that_member_is_on,
4067 &found_function,
4068 generic_arguments,
4069 ast_arguments,
4070 chain_self_is_mutable,
4071 node,
4072 );
4073 (found_function, signature)
4074 } else {
4075 let lambda_variables_count = if ast_arguments.is_empty() {
4076 0
4077 } else if let swamp_ast::ExpressionKind::Lambda(variables, ..) = &ast_arguments[0].kind
4078 {
4079 variables.len()
4080 } else {
4081 0
4082 };
4083 let Some((intrinsic_fn, signature)) = self.check_intrinsic_member_signature(
4084 type_that_member_is_on,
4085 field_name_str,
4086 lambda_variables_count,
4087 node,
4088 ) else {
4089 return (PostfixKind::OptionalChainingOperator, self.types().unit());
4090 };
4091 let def = IntrinsicFunctionDefinition {
4092 name: field_name_str.to_string(),
4093 signature,
4094 intrinsic: intrinsic_fn,
4095 };
4096 let function_ref = FunctionRef::from(Function::Intrinsic(
4097 IntrinsicFunctionDefinitionRef::from(def.clone()),
4098 ));
4099 (function_ref, def.signature)
4100 };
4101
4102 let self_type_in_signature = &instantiated_signature.parameters[0];
4103
4104 if self_type_in_signature.is_mutable && !chain_self_is_mutable {
4105 self.add_err(ErrorKind::SelfNotCorrectMutableState, node);
4106 }
4107
4108 let resolved_arguments = self.analyze_and_verify_parameters(
4109 node,
4110 &instantiated_signature.parameters[1..],
4111 ast_arguments,
4112 );
4113
4114 (
4115 PostfixKind::MemberCall(function_ref, resolved_arguments),
4116 TypeRef::from(instantiated_signature.return_type.clone()),
4117 )
4118 }
4119
4120 fn analyze_postfix_member_call(
4121 &mut self,
4122 type_that_member_is_on: &TypeRef,
4123 is_mutable: bool,
4124 member_name: &swamp_ast::Node,
4125 ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4126 ast_arguments: &[swamp_ast::Expression],
4127 suffixes: &mut Vec<Postfix>,
4128 ) -> TypeRef {
4129 let field_name_str = self.get_text(member_name).to_string();
4130
4131 let resolved_node = self.to_node(member_name);
4132
4133 let (kind, return_type) = self.analyze_member_call(
4134 type_that_member_is_on,
4135 &field_name_str,
4136 ast_maybe_generic_arguments,
4137 ast_arguments,
4138 is_mutable,
4139 member_name,
4140 );
4141 let postfix = Postfix {
4142 node: resolved_node,
4143 ty: return_type,
4144 kind,
4145 };
4146
4147 let last_type = postfix.ty.clone();
4148 suffixes.push(postfix);
4149
4150 last_type
4151 }
4152
4153 fn is_compatible_initializer_list_target(
4154 &mut self,
4155 target_type: &TypeRef,
4156 initializer_element_type: &TypeRef,
4157 ) -> bool {
4158 match &*target_type.kind {
4159 TypeKind::VecStorage(vec_element_type, _vec_capacity) => self
4160 .types()
4161 .compatible_with(vec_element_type, initializer_element_type),
4162 TypeKind::FixedCapacityAndLengthArray(array_element_type, _array_capacity) => self
4163 .types()
4164 .compatible_with(array_element_type, initializer_element_type),
4165 _ => false,
4166 }
4167 }
4168
4169 fn is_compatible_initializer_pair_list_target(
4170 &mut self,
4171 target_type: &TypeRef,
4172 initializer_key_type: &TypeRef,
4173 initializer_value_type: &TypeRef,
4174 ) -> bool {
4175 match &*target_type.kind {
4176 TypeKind::MapStorage(storage_key, storage_value, _) => {
4177 self.types()
4178 .compatible_with(initializer_key_type, storage_key)
4179 && self
4180 .types()
4181 .compatible_with(initializer_value_type, storage_value)
4182 }
4183 _ => false,
4184 }
4185 }
4186
4187 fn types_did_not_match_try_late_coerce_expression(
4188 &mut self,
4189 expr: Expression,
4190 special_expected_type: &TypeRef,
4191 special_encountered_type: &TypeRef,
4192 node: &swamp_ast::Node,
4193 ) -> Expression {
4194 let expected_type = special_expected_type;
4195 let encountered_type = special_encountered_type;
4196 let encountered_is_optional = matches!(&*encountered_type.kind, TypeKind::Optional(_));
4197 if let TypeKind::Optional(expected_inner_type) = &*expected_type.kind {
4198 let inner_is_also_optional =
4199 matches!(&*expected_inner_type.kind, TypeKind::Optional(_));
4200 assert!(!inner_is_also_optional);
4203
4204 if !encountered_is_optional {
4207 if self
4209 .types()
4210 .compatible_with(expected_inner_type, encountered_type)
4211 {
4212 let wrapped = self.create_expr(
4214 ExpressionKind::Option(Option::from(Box::new(expr))),
4215 expected_type.clone(),
4216 node,
4217 );
4218 return wrapped;
4219 }
4220 }
4221 }
4222
4223 if matches!(&*expected_type.kind, &TypeKind::Bool) {
4224 if encountered_is_optional {
4226 let bool_type = self.types().bool();
4227 let wrapped = self.create_expr(
4228 ExpressionKind::CoerceOptionToBool(Box::from(expr)),
4229 bool_type,
4230 node,
4231 );
4232 return wrapped;
4233 }
4234 }
4235
4236 if matches!(
4237 (&*expected_type.kind, &*encountered_type.kind),
4238 (TypeKind::Codepoint, TypeKind::Int)
4239 ) {
4240 let coerced = self.create_expr(
4241 ExpressionKind::CoerceIntToChar(Box::new(expr)),
4242 expected_type.clone(),
4243 node,
4244 );
4245 return coerced;
4246 }
4247
4248 error!(?expected_type, ?encountered_type, "incompatible");
4249 self.create_err(
4250 ErrorKind::IncompatibleTypes {
4251 expected: expected_type.clone(),
4252 found: encountered_type.clone(),
4253 },
4254 node,
4255 )
4256 }
4257
4258 #[must_use]
4259 pub fn analyze_generic_parameter_usize(&self, generic_parameter: &GenericParameter) -> usize {
4260 let usize_node = generic_parameter.get_unsigned_int_node();
4261 let usize_str = self.get_text(usize_node);
4262 Self::str_to_unsigned_int(usize_str).unwrap() as usize
4263 }
4264
4265 #[must_use]
4266 pub fn analyze_generic_parameter_usize_tuple(
4267 &self,
4268 generic_parameter: &GenericParameter,
4269 ) -> (usize, usize) {
4270 let (first, second) = generic_parameter.get_unsigned_int_tuple_nodes();
4271 let first_str = self.get_text(first);
4272 let second_str = self.get_text(second);
4273 let first_value = Self::str_to_unsigned_int(first_str).unwrap() as usize;
4274 let second_value = Self::str_to_unsigned_int(second_str).unwrap() as usize;
4275
4276 (first_value, second_value)
4277 }
4278
4279 pub fn analyze_special_named_type(
4280 &mut self,
4281 path: &[String],
4282 name: &str,
4283 ast_generic_parameters: &[GenericParameter],
4284 ) -> Option<TypeRef> {
4285 let converted_type = match name {
4286 "String" => {
4287 if ast_generic_parameters.len() == 1 {
4288 let fixed_size =
4289 self.analyze_generic_parameter_usize(&ast_generic_parameters[0]);
4290 let new_type = self.shared.state.types.string_storage(fixed_size);
4291 let default_node = swamp_ast::Node::default();
4292 self.add_default_functions(&new_type, &default_node);
4293 new_type
4294 } else {
4295 return None;
4296 }
4297 }
4298 "Vec" => {
4299 if ast_generic_parameters.len() == 1 {
4300 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4301 let vec_type = self.shared.state.types.dynamic_vec_view(&element_type);
4302 let default_node = swamp_ast::Node::default();
4304 self.add_default_functions(&vec_type, &default_node);
4305 vec_type
4306 } else if ast_generic_parameters.len() == 2 {
4307 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4308 let fixed_size =
4309 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4310 let vec_storage_type = self
4311 .shared
4312 .state
4313 .types
4314 .vec_storage(&element_type, fixed_size);
4315 let default_node = swamp_ast::Node::default();
4317 self.add_default_functions(&vec_storage_type, &default_node);
4318 vec_storage_type
4319 } else {
4320 panic!("todo: make this into an error")
4321 }
4322 }
4323 "Stack" => {
4324 if ast_generic_parameters.len() == 1 {
4325 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4326 let stack_view_type = self.shared.state.types.stack_view(&element_type);
4327 let default_node = swamp_ast::Node::default();
4329 self.add_default_functions(&stack_view_type, &default_node);
4330 stack_view_type
4331 } else if ast_generic_parameters.len() == 2 {
4332 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4333 let fixed_size =
4334 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4335 let stack_storage_type = self
4336 .shared
4337 .state
4338 .types
4339 .stack_storage(&element_type, fixed_size);
4340 let default_node = swamp_ast::Node::default();
4342 self.add_default_functions(&stack_storage_type, &default_node);
4343 stack_storage_type
4344 } else {
4345 panic!("todo: make this into an error")
4346 }
4347 }
4348 "Queue" => {
4349 if ast_generic_parameters.len() == 1 {
4350 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4351 let queue_view_type = self.shared.state.types.queue_view(&element_type);
4352 let default_node = swamp_ast::Node::default();
4354 self.add_default_functions(&queue_view_type, &default_node);
4355 queue_view_type
4356 } else if ast_generic_parameters.len() == 2 {
4357 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4358 let fixed_size =
4359 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4360 let queue_storage_type = self
4361 .shared
4362 .state
4363 .types
4364 .queue_storage(&element_type, fixed_size);
4365 let default_node = swamp_ast::Node::default();
4367 self.add_default_functions(&queue_storage_type, &default_node);
4368 queue_storage_type
4369 } else {
4370 panic!("todo: make this into an error")
4371 }
4372 }
4373 "Sparse" => {
4374 if ast_generic_parameters.len() == 1 {
4375 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4376 let sparse_view_type = self.shared.state.types.sparse_view(&element_type);
4377 let default_node = swamp_ast::Node::default();
4379 self.add_default_functions(&sparse_view_type, &default_node);
4380 sparse_view_type
4381 } else if ast_generic_parameters.len() == 2 {
4382 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4383 let fixed_size =
4384 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4385 let sparse_storage_type = self
4386 .shared
4387 .state
4388 .types
4389 .sparse_storage(&element_type, fixed_size);
4390 let default_node = swamp_ast::Node::default();
4392 self.add_default_functions(&sparse_storage_type, &default_node);
4393 sparse_storage_type
4394 } else {
4395 panic!("todo: make this into an error")
4396 }
4397 }
4398
4399 "Grid" => {
4400 if ast_generic_parameters.len() == 1 {
4401 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4402 let grid_view_type = self.shared.state.types.grid_view(&element_type);
4403 let default_node = swamp_ast::Node::default();
4405 self.add_default_functions(&grid_view_type, &default_node);
4406 grid_view_type
4407 } else if ast_generic_parameters.len() == 2 {
4408 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4409 let (width, height) =
4410 self.analyze_generic_parameter_usize_tuple(&ast_generic_parameters[1]);
4411 let grid_storage_type =
4412 self.shared
4413 .state
4414 .types
4415 .grid_storage(&element_type, width, height);
4416 let default_node = swamp_ast::Node::default();
4418 self.add_default_functions(&grid_storage_type, &default_node);
4419 grid_storage_type
4420 } else {
4421 panic!("todo: make this into an error")
4422 }
4423 }
4424
4425 _ => return None,
4426 };
4427
4428 Some(converted_type)
4429 }
4430
4431 fn special_static_member(
4432 &self,
4433 type_identifier: &QualifiedTypeIdentifier,
4434 member_name_node: &swamp_ast::Node,
4435 ) -> Option<Function> {
4436 if type_identifier.generic_params.is_empty() {
4437 return None;
4438 }
4439
4440 if type_identifier.module_path.is_some() {
4441 return None;
4442 }
4443
4444 let member_name = self.get_text(member_name_node);
4445 let name = self.get_text(&type_identifier.name.0);
4446
4447 match name {
4448 "Stack" => None,
4449 _ => None,
4450 }
4451 }
4452
4453 fn analyze_subscript_int(&mut self, collection_type: TypeRef, unsigned_int_expression: Expression) -> (Postfix, TypeRef) {
4454 let node = &unsigned_int_expression.node;
4455 match &*collection_type.kind {
4456 TypeKind::QueueStorage(element_type, _)
4457 | TypeKind::StackStorage(element_type, _)
4458 | TypeKind::StackView(element_type)
4459 | TypeKind::VecStorage(element_type, _)
4460 | TypeKind::StringStorage(element_type, _, _)
4461 | TypeKind::String(element_type, _)
4462 | TypeKind::FixedCapacityAndLengthArray(element_type, _)
4463 | TypeKind::DynamicLengthVecView(element_type)
4464 | TypeKind::SliceView(element_type) => {
4465 let vec_type = VecType {
4466 element: element_type.clone(),
4467 };
4468
4469 let postfix = Postfix {
4470 node: node.clone(),
4471 ty: collection_type.clone(),
4472 kind: PostfixKind::VecSubscript(
4473 vec_type,
4474 unsigned_int_expression,
4475 ),
4476 };
4477
4478 (postfix, element_type.clone())
4479 }
4480 TypeKind::SparseStorage(element_type, _)
4482 | TypeKind::SparseView(element_type) => {
4483 let sparse_type = SparseType {
4484 element: element_type.clone(),
4485 };
4486
4487
4488 let postfix = Postfix {
4489 node: node.clone(),
4490 ty: collection_type.clone(),
4491 kind: PostfixKind::SparseSubscript(
4492 sparse_type,
4493 unsigned_int_expression,
4494 ),
4495 };
4496
4497 (postfix, element_type.clone())
4498 }
4499
4500 _ => {
4501 self
4502 .add_err_resolved(ErrorKind::CanNotSubscriptWithThatType, node);
4503
4504 let error_vec_type = VecType {
4505 element: self.types().unit(),
4506 };
4507
4508 let error_postfix = Postfix {
4509 node: node.clone(),
4510 ty: collection_type.clone(),
4511 kind: PostfixKind::VecSubscript(
4512 error_vec_type,
4513 unsigned_int_expression,
4514 ),
4515 };
4516
4517 (error_postfix, self.types().unit())
4518 }
4519 }
4520 }
4521
4522
4523 fn analyze_subscript_range(&mut self, collection_type: TypeRef, range_expression: Expression) -> (Postfix, TypeRef) {
4524 let node = &range_expression.node;
4525 match &*collection_type.kind {
4526 TypeKind::QueueStorage(element_type, _)
4527 | TypeKind::StackStorage(element_type, _)
4528 | TypeKind::StackView(element_type)
4529 | TypeKind::VecStorage(element_type, _)
4530 | TypeKind::StringStorage(element_type, _, _)
4531 | TypeKind::String(element_type, _)
4532 | TypeKind::FixedCapacityAndLengthArray(element_type, _)
4533 | TypeKind::DynamicLengthVecView(element_type)
4534 | TypeKind::SliceView(element_type) => {
4535 let vec_type = VecType {
4536 element: element_type.clone(),
4537 };
4538
4539 let postfix = Postfix {
4540 node: node.clone(),
4541 ty: collection_type.clone(),
4542 kind: PostfixKind::VecSubscriptRange(
4543 vec_type,
4544 range_expression,
4545 ),
4546 };
4547
4548 (postfix, collection_type.clone())
4550 }
4551
4552 _ => {
4553 self
4554 .add_err_resolved(ErrorKind::CanNotSubscriptWithThatType, node);
4555
4556 let error_vec_type = VecType {
4557 element: self.types().unit(),
4558 };
4559
4560 let error_postfix = Postfix {
4561 node: node.clone(),
4562 ty: collection_type.clone(),
4563 kind: PostfixKind::VecSubscriptRange(
4564 error_vec_type,
4565 range_expression,
4566 ),
4567 };
4568
4569 (error_postfix, self.types().unit())
4570 }
4571 }
4572 }
4573 fn analyze_map_subscript(&mut self, key_type: &TypeRef, value_type: &TypeRef, lookup_expr: &swamp_ast::Expression) -> (Postfix, TypeRef) {
4574 let key_context = TypeContext::new_argument(key_type, false);
4575 let key_expression = self.analyze_expression(lookup_expr, &key_context);
4576
4577 let map_type = MapType {
4578 key: key_type.clone(),
4579 value: value_type.clone(),
4580 };
4581
4582 let postfix = Postfix {
4583 node: self.to_node(&lookup_expr.node),
4584 ty: key_type.clone(),
4585 kind: PostfixKind::MapSubscript(map_type, key_expression),
4586 };
4587
4588 (postfix, value_type.clone())
4589 }
4590}