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