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::prelude::*;
41use swamp_types::TypeKind;
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::StringStorage(element_type, _, _)
1368 | TypeKind::String(element_type, _)
1369 | TypeKind::DynamicLengthVecView(element_type)
1370 | TypeKind::SliceView(element_type) => {
1371 let int_type = self.shared.state.types.int();
1372 let unsigned_int_context = TypeContext::new_argument(&int_type, false);
1373 let unsigned_int_expression =
1374 self.analyze_expression(lookup_expr, &unsigned_int_context);
1375
1376 let vec_type = VecType {
1377 element: element_type.clone(),
1378 };
1379
1380 self.add_postfix(
1381 &mut suffixes,
1382 PostfixKind::VecSubscript(vec_type, unsigned_int_expression),
1383 element_type.clone(),
1384 &lookup_expr.node,
1385 );
1386
1387 tv.resolved_type = element_type.clone();
1389 }
1390 TypeKind::SparseStorage(element_type, _)
1391 | TypeKind::SparseView(element_type) => {
1392 let int_type = self.shared.state.types.int();
1393 let unsigned_int_context = TypeContext::new_argument(&int_type, false);
1394 let unsigned_int_expression =
1395 self.analyze_expression(lookup_expr, &unsigned_int_context);
1396
1397 let vec_type = SparseType {
1398 element: element_type.clone(),
1399 };
1400
1401 self.add_postfix(
1402 &mut suffixes,
1403 PostfixKind::SparseSubscript(vec_type, unsigned_int_expression),
1404 element_type.clone(),
1405 &lookup_expr.node,
1406 );
1407
1408 tv.resolved_type = element_type.clone();
1410 }
1411 TypeKind::MapStorage(key_type, value_type, _)
1412 | TypeKind::DynamicLengthMapView(key_type, value_type) => {
1413 let key_context = TypeContext::new_argument(key_type, false);
1414 let key_expression = self.analyze_expression(lookup_expr, &key_context);
1415
1416 let map_type = MapType {
1417 key: key_type.clone(),
1418 value: value_type.clone(),
1419 };
1420
1421 self.add_postfix(
1422 &mut suffixes,
1423 PostfixKind::MapSubscript(map_type, key_expression),
1424 value_type.clone(),
1425 &lookup_expr.node,
1426 );
1427
1428 tv.resolved_type = value_type.clone();
1430 }
1431 _ => {
1432 eprintln!("xwhat is this: {collection_type:?}");
1433 return self
1434 .create_err(ErrorKind::MissingSubscriptMember, &lookup_expr.node);
1435 }
1436 }
1437 }
1438
1439 swamp_ast::Postfix::MemberCall(member_name, generic_arguments, ast_arguments) => {
1440 let member_name_str = self.get_text(member_name).to_string();
1441 let underlying_type = tv.resolved_type;
1442
1443 let (kind, return_type) = self.analyze_member_call(
1444 &underlying_type,
1445 &member_name_str,
1446 generic_arguments.clone(),
1447 ast_arguments,
1448 tv.is_mutable,
1449 member_name,
1450 );
1451
1452 self.add_postfix(&mut suffixes, kind, return_type.clone(), member_name);
1453 tv.resolved_type = return_type.clone();
1454 tv.is_mutable = false;
1455 }
1456 swamp_ast::Postfix::FunctionCall(node, _generic_arguments, arguments) => {
1457 panic!("can only have function call at the start of a postfix chain")
1458 }
1459
1460 swamp_ast::Postfix::NoneCoalescingOperator(default_expr) => {
1461 let unwrapped_type = if let TypeKind::Optional(unwrapped_type) =
1462 &*tv.resolved_type.kind
1463 {
1464 unwrapped_type
1465 } else if uncertain {
1466 &tv.resolved_type
1467 } else {
1468 return self.create_err(ErrorKind::CanNotNoneCoalesce, &default_expr.node);
1469 };
1470
1471 let unwrapped_type_context = TypeContext::new_argument(unwrapped_type, false);
1472 let resolved_default_expr =
1473 self.analyze_expression(default_expr, &unwrapped_type_context);
1474 self.add_postfix(
1475 &mut suffixes,
1476 PostfixKind::NoneCoalescingOperator(resolved_default_expr),
1477 (*unwrapped_type).clone(),
1478 &default_expr.node,
1479 );
1480 tv.resolved_type = (*unwrapped_type).clone();
1481 uncertain = false; }
1483
1484 swamp_ast::Postfix::OptionalChainingOperator(option_node) => {
1485 if is_last {
1486 return self.create_err(
1487 ErrorKind::OptionalChainingOperatorCanNotBePartOfChain,
1488 option_node,
1489 );
1490 }
1491
1492 if let TypeKind::Optional(unwrapped_type) = &*tv.resolved_type.kind {
1493 uncertain = true;
1494 self.add_postfix(
1495 &mut suffixes,
1496 PostfixKind::OptionalChainingOperator,
1497 (*unwrapped_type).clone(),
1498 option_node,
1499 );
1500 tv.resolved_type = (*unwrapped_type).clone();
1501 } else {
1502 return self.create_err(ErrorKind::ExpectedOptional, option_node);
1503 }
1504 }
1505 }
1506 }
1507
1508 if uncertain {
1509 if let TypeKind::Optional(_) = &*tv.resolved_type.kind {} else {
1510 tv.resolved_type = self.shared.state.types.optional(&tv.resolved_type.clone());
1511 }
1512 }
1513
1514 self.create_expr(
1515 ExpressionKind::PostfixChain(start_of_chain, suffixes),
1516 tv.resolved_type,
1517 &chain.base.node,
1518 )
1519 }
1520
1521 fn analyze_bool_argument_expression(
1522 &mut self,
1523 expression: &swamp_ast::Expression,
1524 ) -> BooleanExpression {
1525 let bool_type = self.shared.state.types.bool();
1526 let bool_context = TypeContext::new_argument(&bool_type, false);
1527 let resolved_expression = self.analyze_expression(expression, &bool_context);
1528 let expr_type = resolved_expression.ty.clone();
1529
1530 let bool_expression = match &*expr_type.kind {
1531 TypeKind::Bool => resolved_expression,
1532 TypeKind::Optional(_) => {
1533 let bool = self.types().bool();
1534 self.create_expr(
1535 ExpressionKind::CoerceOptionToBool(Box::new(resolved_expression)),
1536 bool,
1537 &expression.node,
1538 )
1539 }
1540 _ => self.create_err(ErrorKind::ExpectedBooleanExpression, &expression.node),
1541 };
1542
1543 BooleanExpression {
1544 expression: Box::from(bool_expression),
1545 }
1546 }
1547
1548 fn is_aggregate_function_call(expression: &swamp_ast::Expression) -> bool {
1550 match &expression.kind {
1551 swamp_ast::ExpressionKind::PostfixChain(chain) => {
1552 if chain.postfixes.is_empty() {
1553 return false;
1554 }
1555
1556 for postfix in &chain.postfixes {
1557 if let swamp_ast::Postfix::FunctionCall(_, _, _) = postfix {
1558 return true;
1559 }
1560 }
1561 false
1562 }
1563 _ => false, }
1565 }
1566
1567 fn analyze_iterable(
1568 &mut self,
1569 mut_requested_for_value_variable: Option<swamp_ast::Node>,
1570 expression: &swamp_ast::Expression,
1571 ) -> Iterable {
1572 let has_lvalue_target = !Self::is_aggregate_function_call(expression);
1575 let any_context = TypeContext::new_anything_argument(has_lvalue_target);
1576
1577 let resolved_expression = self.analyze_expression(expression, &any_context);
1578
1579 let resolved_type = &resolved_expression.ty.clone();
1580 let int_type = Some(self.types().int());
1581 let (key_type, value_type): (Option<TypeRef>, TypeRef) = match &*resolved_type.kind {
1582 TypeKind::String(_, char) => (int_type, char.clone()),
1583 TypeKind::SliceView(element_type) => (int_type, element_type.clone()),
1584 TypeKind::VecStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1585 TypeKind::SparseStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1586 TypeKind::StackStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1587 TypeKind::StackView(element_type) => (int_type, element_type.clone()),
1588 TypeKind::QueueStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1589 TypeKind::QueueView(element_type) => (int_type, element_type.clone()),
1590 TypeKind::DynamicLengthVecView(element_type) => (int_type, element_type.clone()),
1591 TypeKind::SparseView(element_type) => (int_type, element_type.clone()),
1592 TypeKind::DynamicLengthMapView(key_type, value_type)
1593 | TypeKind::MapStorage(key_type, value_type, _) => {
1594 (Some(key_type.clone()), value_type.clone())
1595 }
1596 TypeKind::Range(_) => (None, self.types().int()),
1597 _ => {
1598 error!(?resolved_type, "not an iterator");
1599 return Iterable {
1600 key_type: None,
1601 value_type: self.shared.state.types.unit(),
1602 resolved_expression: Box::new(
1603 self.create_err(ErrorKind::NotAnIterator, &expression.node),
1604 ),
1605 };
1606 }
1607 };
1608
1609 if mut_requested_for_value_variable.is_some() {
1610 let _resulting_location =
1612 self.analyze_to_location(expression, &any_context, LocationSide::Mutable);
1613 }
1616
1617 Iterable {
1618 key_type,
1619 value_type,
1620 resolved_expression: Box::new(resolved_expression),
1621 }
1622 }
1623
1624 fn analyze_argument_expressions(
1625 &mut self,
1626 expected_type: Option<&TypeRef>,
1627 context: &TypeContext,
1628 ast_expressions: &[swamp_ast::Expression],
1629 ) -> Vec<Expression> {
1630 let mut resolved_expressions = Vec::new();
1631 let argument_expressions_context = TypeContext::new_unsure_argument(expected_type, false);
1633
1634 for expression in ast_expressions {
1635 resolved_expressions
1636 .push(self.analyze_expression(expression, &argument_expressions_context));
1637 }
1638 resolved_expressions
1639 }
1640
1641 fn analyze_block(
1642 &mut self,
1643 _node: &swamp_ast::Node,
1644 context: &TypeContext,
1645 ast_expressions: &[swamp_ast::Expression],
1646 ) -> (Vec<Expression>, TypeRef) {
1647 if ast_expressions.is_empty() {
1648 return (vec![], self.shared.state.types.unit());
1649 }
1650
1651 self.push_block_scope("block");
1652
1653 let mut resolved_expressions = Vec::with_capacity(ast_expressions.len());
1654
1655 for expression in &ast_expressions[..ast_expressions.len() - 1] {
1656 let unit_type = self.shared.state.types.unit();
1657 let stmt_context =
1658 context.with_expected_type(Some(&unit_type), context.has_lvalue_target);
1659 let expr = self.analyze_expression(expression, &stmt_context);
1660
1661 resolved_expressions.push(expr);
1662 }
1663
1664 let last_expr =
1666 self.analyze_expression(&ast_expressions[ast_expressions.len() - 1], context);
1667 let last_type = last_expr.ty.clone();
1668 resolved_expressions.push(last_expr);
1669
1670 self.pop_block_scope("block");
1671
1672 (resolved_expressions, last_type)
1673 }
1674
1675 fn analyze_interpolated_string_lowering(
1676 &mut self,
1677 node: &swamp_ast::Node,
1678 string_parts: &[swamp_ast::StringPart],
1679 ) -> Expression {
1680 let mut last_expression: Option<Expression> = None;
1681 for part in string_parts {
1682 let created_expression = match part {
1683 swamp_ast::StringPart::Literal(string_node, processed_string) => {
1684 let string_literal =
1685 ExpressionKind::StringLiteral(processed_string.to_string());
1686 let basic_literal = string_literal;
1687 let string_type = self.shared.state.types.string();
1688 self.create_expr(basic_literal, string_type, string_node)
1689 }
1690 swamp_ast::StringPart::Interpolation(expression, format_specifier) => {
1691 let any_context = TypeContext::new_anything_argument(false); let expr = self.analyze_expression(expression, &any_context);
1694
1695 let tk = (*expr.ty.kind).clone();
1696
1697 let maybe_to_string = self
1698 .shared
1699 .state
1700 .associated_impls
1701 .get_internal_member_function(&expr.ty, "to_string");
1702
1703 if matches!(tk, TypeKind::String { .. }) {
1704 expr
1705 } else {
1706 let underlying = expr.ty.clone();
1707
1708 if self.needs_storage_error(&expr, true, &any_context, &expression.node) {
1710 return self.create_err(ErrorKind::NeedStorage, &expression.node);
1711 }
1712
1713 let call_expr_kind = if maybe_to_string.is_none() {
1714 let string_type = self.types().string();
1715
1716 ExpressionKind::StringLiteral(format!("missing {string_type}"))
1717 } else {
1726 let expr_as_param = ArgumentExpression::Expression(expr);
1727 self.create_static_member_call(
1728 "to_string",
1729 &[expr_as_param.clone()],
1730 &expression.node,
1731 &underlying,
1732 )
1733 };
1734
1735 let string_type = self.shared.state.types.string();
1743 self.create_expr(call_expr_kind, string_type, &expression.node)
1744 }
1745 }
1746 };
1747
1748 let x_last_expr = if let Some(last_expr) = last_expression.clone() {
1749 let op_kind = BinaryOperatorKind::Add;
1750 let node = created_expression.node.clone();
1751 let op = BinaryOperator {
1752 left: Box::new(last_expr),
1753 right: Box::new(created_expression),
1754 kind: op_kind,
1755 node: node.clone(),
1756 };
1757
1758 let string_type = self.shared.state.types.string();
1759 create_expr_resolved(ExpressionKind::BinaryOp(op), string_type, &node)
1760 } else {
1761 created_expression
1762 };
1763
1764 last_expression = Some(x_last_expr);
1765 }
1766
1767 if let Some(last) = last_expression {
1770 last
1771 } else {
1772 let string_type = self.shared.state.types.string();
1773 self.create_expr(
1774 ExpressionKind::StringLiteral(String::new()),
1775 string_type,
1776 node,
1777 )
1778 }
1779 }
1780
1781 pub(crate) fn analyze_identifier(
1782 &mut self,
1783 qualified_func_name: &swamp_ast::QualifiedIdentifier,
1784 ) -> Expression {
1785 if qualified_func_name.module_path.is_none()
1788 && qualified_func_name.generic_params.is_empty()
1789 {
1790 if let Some(found_variable) = self.try_find_variable(&qualified_func_name.name) {
1791 return self.create_expr(
1792 ExpressionKind::VariableAccess(found_variable.clone()),
1793 found_variable.resolved_type.clone(),
1794 &qualified_func_name.name,
1795 );
1796 }
1797 }
1798
1799 let text = self.get_text(&qualified_func_name.name);
1800 self.create_err(
1801 ErrorKind::UnknownIdentifier(text.to_string()),
1802 &qualified_func_name.name,
1803 )
1804 }
1805
1806 fn analyze_variable_reference(&mut self, var_node: &swamp_ast::Node) -> Expression {
1808 if let Some(found_variable) = self.try_find_variable(var_node) {
1809 return self.create_expr(
1810 ExpressionKind::VariableAccess(found_variable.clone()),
1811 found_variable.resolved_type.clone(),
1812 var_node,
1813 );
1814 }
1815 let text = self.get_text(var_node);
1816 self.create_err(ErrorKind::UnknownIdentifier(text.to_string()), var_node)
1817 }
1818 fn analyze_slice_pair_literal(
1819 &mut self,
1820 node: &swamp_ast::Node,
1821 entries: &[(swamp_ast::Expression, swamp_ast::Expression)],
1822 ) -> (Vec<(Expression, Expression)>, TypeRef, TypeRef) {
1823 if entries.is_empty() {
1824 return (
1825 vec![],
1826 self.shared.state.types.unit(),
1827 self.shared.state.types.unit(),
1828 );
1829 }
1830
1831 let (first_key, first_value) = &entries[0];
1833 let anything_context = TypeContext::new_anything_argument(true);
1834 let resolved_first_key = self.analyze_expression(first_key, &anything_context);
1835 let resolved_first_value = self.analyze_expression(first_value, &anything_context);
1836 let key_type = resolved_first_key.ty.clone();
1837 let value_type = resolved_first_value.ty.clone();
1838
1839 let key_context = TypeContext::new_argument(&key_type, true);
1840 let value_context = TypeContext::new_argument(&value_type, true);
1841
1842 let mut resolved_entries = Vec::new();
1844 resolved_entries.push((resolved_first_key, resolved_first_value));
1845
1846 for (key, value) in entries.iter().skip(1) {
1847 let resolved_key = self.analyze_expression(key, &key_context);
1848 let resolved_value = self.analyze_expression(value, &value_context);
1849
1850 if !self
1851 .shared
1852 .state
1853 .types
1854 .compatible_with(&resolved_key.ty, &key_type)
1855 {
1856 return (
1857 vec![],
1858 self.shared.state.types.unit(),
1859 self.shared.state.types.unit(),
1860 );
1861 }
1862
1863 if !self
1864 .shared
1865 .state
1866 .types
1867 .compatible_with(&resolved_value.ty, &value_type)
1868 {
1869 return (
1870 vec![],
1871 self.shared.state.types.unit(),
1872 self.shared.state.types.unit(),
1873 );
1874 }
1875
1876 resolved_entries.push((resolved_key, resolved_value));
1877 }
1878
1879 (resolved_entries, key_type, value_type)
1880 }
1881
1882 fn analyze_internal_initializer_pair_list(
1883 &mut self,
1884 node: &swamp_ast::Node,
1885 items: &[(swamp_ast::Expression, swamp_ast::Expression)],
1886 context: &TypeContext,
1887 ) -> (TypeRef, Vec<(Expression, Expression)>) {
1888 let (collection_type, key_type, value_type) = if let Some(expected_type) =
1889 context.expected_type
1890 {
1891 match &*expected_type.kind {
1892 TypeKind::MapStorage(key, value, capacity) => {
1893 if items.len() > *capacity {
1894 self.add_err(
1895 ErrorKind::TooManyInitializerListElementsForStorage {
1896 capacity: *capacity,
1897 },
1898 node,
1899 );
1900 return (self.types().unit(), vec![]);
1901 }
1902 (expected_type.clone(), key.clone(), value.clone())
1903 }
1904 TypeKind::DynamicLengthMapView(key, value) => {
1905 (expected_type.clone(), key.clone(), value.clone())
1906 }
1907 _ => {
1908 self.add_err(ErrorKind::ExpectedSlice, node);
1909 return (self.types().unit(), vec![]);
1910 }
1911 }
1912 } else if items.is_empty() {
1913 self.add_err(ErrorKind::NoInferredTypeForEmptyInitializer, node);
1914 return (self.types().unit(), vec![]);
1915 } else {
1916 let maybe_key_context = TypeContext::new_anything_argument(true);
1918
1919 let first_key_expression = self.analyze_expression(&items[0].0, &maybe_key_context);
1920
1921 let maybe_value_context = TypeContext::new_anything_argument(true);
1922 let first_value_expression = self.analyze_expression(&items[0].1, &maybe_value_context);
1923
1924 let required_key_type = first_key_expression.ty;
1925 let required_value_type = first_value_expression.ty;
1926
1927 let inferred_type =
1928 self.types()
1929 .map_storage(&required_key_type, &required_value_type, items.len());
1930
1931 (inferred_type, required_key_type, required_value_type)
1932 };
1933
1934 assert!(!matches!(*key_type.kind, TypeKind::Unit));
1935 assert!(!matches!(*value_type.kind, TypeKind::Unit));
1936
1937 let required_key_context = TypeContext::new_argument(&key_type, true);
1938 let required_value_context = TypeContext::new_argument(&value_type, true);
1939
1940 let mut resolved_items = Vec::new();
1941
1942 for (key_expr, value_expr) in items {
1943 let analyzed_key_expr = self.analyze_expression(key_expr, &required_key_context);
1944 let analyzed_value_expr = self.analyze_expression(value_expr, &required_value_context);
1945 resolved_items.push((analyzed_key_expr, analyzed_value_expr));
1946 }
1947
1948 (collection_type, resolved_items)
1949 }
1950
1951 fn analyze_internal_initializer_list(
1952 &mut self,
1953 node: &swamp_ast::Node,
1954 items: &[swamp_ast::Expression],
1955 context: &TypeContext,
1956 ) -> (TypeRef, Vec<Expression>) {
1957 let (collection_type, element_type) = if let Some(expected_type) = context.expected_type {
1958 match &*expected_type.kind {
1959 TypeKind::GridStorage(element_type, width, height) => {
1960 let capacity = width * height;
1961 if items.len() > capacity {
1962 return (
1963 self.types().unit(),
1964 self.create_err_vec(
1965 ErrorKind::TooManyInitializerListElementsForStorage { capacity },
1966 node,
1967 ),
1968 );
1969 }
1970 (expected_type.clone(), element_type.clone())
1971 }
1972 TypeKind::StackStorage(element_type, capacity)
1973 | TypeKind::QueueStorage(element_type, capacity)
1974 | TypeKind::SparseStorage(element_type, capacity)
1975 | TypeKind::VecStorage(element_type, capacity) => {
1976 if items.len() > *capacity {
1977 return (
1978 self.types().unit(),
1979 self.create_err_vec(
1980 ErrorKind::TooManyInitializerListElementsForStorage {
1981 capacity: *capacity,
1982 },
1983 node,
1984 ),
1985 );
1986 }
1987 (expected_type.clone(), element_type.clone())
1988 }
1989 TypeKind::QueueView(element_type)
1990 | TypeKind::SparseView(element_type)
1991 | TypeKind::StackView(element_type)
1992 | TypeKind::GridView(element_type)
1993 | TypeKind::DynamicLengthVecView(element_type) => {
1994 (expected_type.clone(), element_type.clone())
1995 }
1996 TypeKind::FixedCapacityAndLengthArray(element_type, _size) => {
1997 (expected_type.clone(), element_type.clone())
1998 }
1999 TypeKind::SliceView(element_type) => (expected_type.clone(), element_type.clone()),
2000 _ => {
2001 return (
2002 self.types().unit(),
2003 self.create_err_vec(
2004 ErrorKind::ExpectedInitializerTarget {
2005 destination_type: expected_type.clone(),
2006 },
2007 node,
2008 ),
2009 );
2010 }
2011 }
2012 } else if items.is_empty() {
2013 return (
2014 self.types().unit(),
2015 self.create_err_vec(ErrorKind::NoInferredTypeForEmptyInitializer, node),
2016 );
2017 } else {
2018 let maybe_context = TypeContext::new_anything_argument(true);
2020 let first = self.analyze_expression(&items[0], &maybe_context);
2021 let required_type = first.ty;
2022 let inferred_vec_storage_type = self.types().vec_storage(&required_type, items.len());
2023 let default_node = swamp_ast::Node::default();
2025 self.add_default_functions(&inferred_vec_storage_type, &default_node);
2026 (inferred_vec_storage_type, required_type)
2027 };
2028
2029 let required_context = TypeContext::new_argument(&element_type, true);
2030 let mut resolved_items = Vec::new();
2031 for item in items {
2032 let resolved_expr = self.analyze_expression(item, &required_context);
2033 resolved_items.push(resolved_expr);
2034 }
2035 (collection_type, resolved_items)
2036 }
2037
2038 fn push_block_scope(&mut self, debug_str: &str) {
2039 let register_watermark = self.scope.total_scopes.current_register;
2040
2041 self.scope.active_scope.block_scope_stack.push(BlockScope {
2042 mode: BlockScopeMode::Open,
2043 lookup: Default::default(),
2044 variables: SeqMap::default(),
2045 register_watermark,
2046 });
2047 }
2048
2049 fn push_lambda_scope(&mut self, debug_str: &str) {
2050 self.scope.active_scope.block_scope_stack.push(BlockScope {
2053 mode: BlockScopeMode::Lambda,
2054 lookup: SeqMap::default(),
2055 variables: SeqMap::default(),
2056 register_watermark: 0, });
2058 }
2059
2060 fn pop_block_scope(&mut self, debug_str: &str) {
2061 self.pop_any_block_scope();
2062 }
2063
2064 fn push_closed_block_scope(&mut self) {
2065 let register_watermark = self.scope.total_scopes.current_register;
2066 self.scope.active_scope.block_scope_stack.push(BlockScope {
2067 mode: BlockScopeMode::Closed,
2068 lookup: Default::default(),
2069 variables: SeqMap::default(),
2070 register_watermark,
2071 });
2072 }
2073
2074 fn pop_closed_block_scope(&mut self) {
2075 self.pop_any_block_scope();
2077 }
2078
2079 fn pop_any_block_scope(&mut self) {
2080 let scope = self.scope.active_scope.block_scope_stack.pop().unwrap();
2081
2082 self.scope.total_scopes.highest_virtual_register = self.scope.total_scopes.current_register;
2084
2085 let is_inside_lambda = self
2087 .scope
2088 .active_scope
2089 .block_scope_stack
2090 .iter()
2091 .any(|s| matches!(s.mode, BlockScopeMode::Lambda));
2092
2093 if matches!(scope.mode, BlockScopeMode::Lambda) {
2094 } else if is_inside_lambda {
2096 } else {
2098 self.scope.total_scopes.current_register = scope.register_watermark;
2100 }
2101 }
2102
2103 fn analyze_match(
2104 &mut self,
2105 scrutinee: &swamp_ast::Expression,
2106 default_context: &TypeContext,
2107 arms: &Vec<swamp_ast::MatchArm>,
2108 ) -> (Match, TypeRef) {
2109 let mut known_type = default_context.expected_type.cloned();
2110 let own_context = default_context.clone();
2111 let scrutinee_context = TypeContext::new_anything_argument(true); let resolved_scrutinee = self.analyze_expression(scrutinee, &scrutinee_context);
2114 let scrutinee_type = resolved_scrutinee.ty.clone();
2115
2116 let mut resolved_arms = Vec::with_capacity(arms.len());
2117
2118 if arms.is_empty() {
2120 let err_match = Match {
2121 expression: Box::new(
2122 self.create_err(ErrorKind::MatchMustHaveAtLeastOneArm, &scrutinee.node),
2123 ),
2124 arms: resolved_arms,
2125 };
2126 return (err_match, self.types().unit());
2127 }
2128
2129 for arm in arms {
2130 let (resolved_arm, _anyone_wants_mutable) = self.analyze_arm(
2131 arm,
2132 &resolved_scrutinee,
2133 &own_context.with_expected_type(known_type.as_ref(), false),
2134 &scrutinee_type,
2135 );
2136
2137 if known_type.is_none() {
2138 known_type = Some(resolved_arm.expression.ty.clone());
2139 }
2140 resolved_arms.push(resolved_arm);
2141 }
2142
2143 if let Some(encountered_type) = known_type {
2144 (
2145 Match {
2146 expression: Box::new(resolved_scrutinee),
2147 arms: resolved_arms,
2148 },
2149 encountered_type,
2150 )
2151 } else {
2152 let err_expr = self.create_err(ErrorKind::MatchArmsMustHaveTypes, &scrutinee.node);
2153
2154 (
2155 Match {
2156 expression: Box::new(err_expr),
2157 arms: resolved_arms.clone(),
2158 },
2159 self.types().unit(),
2160 )
2161 }
2162 }
2163
2164 fn analyze_arm(
2165 &mut self,
2166 arm: &swamp_ast::MatchArm,
2167 _expression: &Expression,
2168 type_context: &TypeContext,
2169 expected_condition_type: &TypeRef,
2170 ) -> (MatchArm, bool) {
2171 let (resolved_pattern, scope_was_pushed, anyone_wants_mutable) =
2172 self.analyze_pattern(&arm.pattern, expected_condition_type);
2173
2174 let resolved_expression = self.analyze_expression(&arm.expression, type_context);
2175 if scope_was_pushed {
2176 self.pop_block_scope("analyze_arm");
2177 }
2178
2179 let resolved_type = resolved_expression.ty.clone();
2180
2181 (
2182 MatchArm {
2183 pattern: resolved_pattern,
2184 expression: Box::from(resolved_expression),
2185 expression_type: resolved_type,
2186 },
2187 anyone_wants_mutable,
2188 )
2189 }
2190
2191 fn str_to_int(text: &str) -> Result<i32, ParseIntError> {
2192 let text = text.replace('_', "");
2193 text.strip_prefix("0x").map_or_else(
2194 || {
2195 text.strip_prefix("-0x").map_or_else(
2196 || text.parse::<i32>(),
2197 |rest| i32::from_str_radix(rest, 16).map(|x| -x),
2198 )
2199 },
2200 |rest| i32::from_str_radix(rest, 16),
2201 )
2202 }
2203
2204 fn str_to_unsigned_int(text: &str) -> Result<u32, ParseIntError> {
2205 let text = text.replace('_', "");
2206 text.strip_prefix("0x")
2207 .map_or_else(|| text.parse::<u32>(), |rest| u32::from_str_radix(rest, 16))
2208 }
2209
2210 fn str_to_float(text: &str) -> Result<f32, ParseFloatError> {
2211 text.parse::<f32>()
2212 }
2213
2214 fn str_to_bool(text: &str) -> Result<bool, ParseBoolError> {
2215 bool::from_str(text)
2216 }
2217
2218 fn analyze_pattern_literal(
2219 &mut self,
2220 node: &swamp_ast::Node,
2221 ast_literal: &swamp_ast::LiteralKind,
2222 expected_condition_type: &TypeRef,
2223 ) -> NormalPattern {
2224 let required_condition_type_context =
2225 TypeContext::new_argument(expected_condition_type, false);
2226 let literal = self.analyze_literal(node, ast_literal, &required_condition_type_context);
2227
2228 if !self
2229 .types()
2230 .compatible_with(&literal.ty, expected_condition_type)
2231 {
2232 return NormalPattern::Literal(self.create_err(
2233 ErrorKind::IncompatibleTypes {
2234 expected: expected_condition_type.clone(),
2235 found: literal.ty,
2236 },
2237 node,
2238 ));
2239 }
2240
2241 NormalPattern::Literal(literal)
2242 }
2243
2244 const fn to_node(&self, node: &swamp_ast::Node) -> Node {
2245 Node {
2246 span: Span {
2247 file_id: self.shared.file_id,
2248 offset: node.span.offset,
2249 length: node.span.length,
2250 },
2251 }
2252 }
2253
2254 fn get_module_path(&self, module_path: Option<&swamp_ast::ModulePath>) -> Vec<String> {
2255 module_path.as_ref().map_or_else(Vec::new, |found| {
2256 let mut strings = Vec::new();
2257 for path_item in &found.0 {
2258 strings.push(self.get_text(path_item).to_string());
2259 }
2260 strings
2261 })
2262 }
2263
2264 fn get_enum_variant_type(
2265 &mut self,
2266 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2267 variant_name: &str,
2268 ) -> EnumVariantType {
2269 let Some((symbol_table, enum_name)) =
2270 self.get_symbol_table_and_name(qualified_type_identifier)
2271 else {
2272 self.add_err(
2273 ErrorKind::UnknownEnumVariantType,
2274 &qualified_type_identifier.name.0,
2275 );
2276 return EnumVariantType {
2277 common: EnumVariantCommon {
2278 name: Default::default(),
2279 assigned_name: String::new(),
2280 container_index: 0,
2281 },
2282 payload_type: self.types().unit(),
2283 };
2284 };
2285
2286 if let Some(enum_name) = symbol_table.get_enum_variant_type(&enum_name, variant_name) {
2287 enum_name
2288 } else {
2289 self.add_err(
2290 ErrorKind::UnknownEnumVariantType,
2291 &qualified_type_identifier.name.0,
2292 );
2293 EnumVariantType {
2294 common: EnumVariantCommon {
2295 name: Default::default(),
2296 assigned_name: String::new(),
2297 container_index: 0,
2298 },
2299 payload_type: self.types().unit(),
2300 }
2301 }
2302 }
2303
2304 pub(crate) fn get_symbol_table_and_name(
2305 &self,
2306 type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2307 ) -> Option<(&SymbolTable, String)> {
2308 let path = self.get_module_path(type_identifier.module_path.as_ref());
2309 let name = self.get_text(&type_identifier.name.0).to_string();
2310
2311 if let Some(found) = self.shared.get_symbol_table(&path) {
2312 Some((found, name))
2313 } else {
2314 None
2315 }
2316 }
2317
2318 const fn analyze_compound_operator(
2319 &self,
2320 ast_operator: &swamp_ast::CompoundOperator,
2321 ) -> CompoundOperator {
2322 let resolved_node = self.to_node(&ast_operator.node);
2323 let resolved_kind = match ast_operator.kind {
2324 swamp_ast::CompoundOperatorKind::Add => CompoundOperatorKind::Add,
2325 swamp_ast::CompoundOperatorKind::Sub => CompoundOperatorKind::Sub,
2326 swamp_ast::CompoundOperatorKind::Mul => CompoundOperatorKind::Mul,
2327 swamp_ast::CompoundOperatorKind::Div => CompoundOperatorKind::Div,
2328 swamp_ast::CompoundOperatorKind::Modulo => CompoundOperatorKind::Modulo,
2329 };
2330
2331 CompoundOperator {
2332 node: resolved_node,
2333 kind: resolved_kind,
2334 }
2335 }
2336
2337 const fn to_node_option(&self, maybe_node: Option<&swamp_ast::Node>) -> Option<Node> {
2338 match maybe_node {
2339 None => None,
2340 Some(node) => Some(self.to_node(node)),
2341 }
2342 }
2343
2344 const fn analyze_format_specifier(
2345 &self,
2346 ast_format_specifier: Option<&swamp_ast::FormatSpecifier>,
2347 ) -> Option<FormatSpecifier> {
2348 let f = match ast_format_specifier {
2349 None => return None,
2350 Some(ast_format) => match ast_format {
2351 swamp_ast::FormatSpecifier::LowerHex(node) => FormatSpecifier {
2352 node: self.to_node(node),
2353 kind: FormatSpecifierKind::LowerHex,
2354 },
2355 swamp_ast::FormatSpecifier::UpperHex(node) => FormatSpecifier {
2356 node: self.to_node(node),
2357 kind: FormatSpecifierKind::UpperHex,
2358 },
2359 swamp_ast::FormatSpecifier::Binary(node) => FormatSpecifier {
2360 node: self.to_node(node),
2361 kind: FormatSpecifierKind::Binary,
2362 },
2363 swamp_ast::FormatSpecifier::Float(node) => FormatSpecifier {
2364 node: self.to_node(node),
2365 kind: FormatSpecifierKind::Float,
2366 },
2367 swamp_ast::FormatSpecifier::Precision(value, node, x) => {
2368 let (precision_type, precision_node) = match x {
2369 swamp_ast::PrecisionType::Float(node) => {
2370 (PrecisionType::Float, self.to_node(node))
2371 }
2372 swamp_ast::PrecisionType::String(node) => {
2373 (PrecisionType::String, self.to_node(node))
2374 }
2375 };
2376 FormatSpecifier {
2377 node: self.to_node(node),
2378 kind: FormatSpecifierKind::Precision(
2379 *value,
2380 precision_node,
2381 precision_type,
2382 ),
2383 }
2384 }
2385 },
2386 };
2387
2388 Some(f)
2389 }
2390
2391 fn analyze_with_expr(
2392 &mut self,
2393 context: &TypeContext,
2394 variables: &[swamp_ast::VariableBinding],
2395 expression: &swamp_ast::Expression,
2396 ) -> Expression {
2397 let mut variable_expressions = Vec::new();
2398
2399 for variable in variables {
2400 let any_context = TypeContext::new_anything_argument(false);
2401 let must_have_expression = if let Some(x) = &variable.expression {
2402 x
2403 } else {
2404 &swamp_ast::Expression {
2405 kind: swamp_ast::ExpressionKind::VariableReference(variable.variable.clone()),
2406 node: variable.variable.name.clone(),
2407 }
2408 };
2409
2410 let location_side = if variable.variable.is_mutable.is_some() {
2412 if let Some(expr) = &variable.expression {
2414 let maybe_ref = self.analyze_maybe_ref_expression(expr);
2416 if maybe_ref.has_borrow_mutable_reference.is_some() {
2417 LocationSide::Mutable
2418 } else {
2419 LocationSide::Rhs
2420 }
2421 } else {
2422 LocationSide::Rhs
2424 }
2425 } else {
2426 LocationSide::Rhs
2428 };
2429
2430 let var = self.analyze_mut_or_immutable_expression(
2431 must_have_expression,
2432 &any_context,
2433 location_side,
2434 );
2435
2436 variable_expressions.push(var);
2437 }
2438
2439 self.push_closed_block_scope();
2440 let mut expressions = Vec::new();
2441 for (variable_binding, resolved_expression) in variables.iter().zip(variable_expressions) {
2442 let initialize_variable_expression = self
2443 .create_variable_binding_for_with(&variable_binding.variable, resolved_expression);
2444
2445 expressions.push(initialize_variable_expression);
2449 }
2450
2451 let resolved_expression = self.analyze_expression(expression, context);
2452 let block_type = self.types().unit();
2454 expressions.push(resolved_expression);
2455
2456 let block_expression_kind = ExpressionKind::Block(expressions);
2457 self.pop_closed_block_scope();
2458
2459 self.create_expr(block_expression_kind, block_type, &expression.node)
2460 }
2461
2462 fn analyze_when_expr(
2463 &mut self,
2464 context: &TypeContext,
2465 variables: &[swamp_ast::VariableBinding],
2466 true_expr: &swamp_ast::Expression,
2467 else_expr: Option<&swamp_ast::Expression>,
2468 ) -> Expression {
2469 self.push_block_scope("when");
2471 let mut bindings = Vec::new();
2472 for variable_binding in variables {
2473 let mut_expr = if let Some(found_expr) = &variable_binding.expression {
2474 let any_context = TypeContext::new_anything_argument(true); self.analyze_mut_or_immutable_expression(
2476 found_expr,
2477 &any_context,
2478 LocationSide::Rhs,
2479 )
2480 .expect_immutable()
2481 .unwrap()
2482 } else {
2483 let same_var = self.find_variable(&variable_binding.variable);
2484
2485 let generated_expr_kind = ExpressionKind::VariableAccess(same_var.clone());
2488 self.create_expr(
2489 generated_expr_kind,
2490 same_var.resolved_type.clone(),
2491 &variable_binding.variable.name,
2492 )
2493 };
2494
2495 let tk = &mut_expr.ty.kind;
2496
2497 if let TypeKind::Optional(found_ty) = &**tk {
2498 let variable_ref = self.create_variable(&variable_binding.variable, found_ty);
2499
2500 let binding = WhenBinding {
2501 variable: variable_ref,
2502 expr: mut_expr,
2503 };
2504 bindings.push(binding);
2505 } else {
2506 return self.create_err(ErrorKind::ExpectedOptional, &true_expr.node);
2507 }
2508 }
2509
2510 let resolved_true = self.analyze_expression(true_expr, context);
2511 let block_type = resolved_true.ty.clone();
2512
2513 self.pop_block_scope("when");
2514
2515 let maybe_resolved_else = if let Some(found_else) = else_expr {
2516 let block_type_for_true_context = context.we_know_expected_type(&block_type, false);
2517 Some(Box::new(self.analyze_expression(
2518 found_else,
2519 &block_type_for_true_context,
2520 )))
2521 } else {
2522 None
2523 };
2524
2525 let when_kind =
2526 ExpressionKind::When(bindings, Box::from(resolved_true), maybe_resolved_else);
2527
2528 self.create_expr(when_kind, block_type, &true_expr.node)
2529 }
2530
2531 fn analyze_guard(
2532 &mut self,
2533 node: &swamp_ast::Node,
2534 context: &TypeContext,
2535 guard_expressions: &Vec<swamp_ast::GuardExpr>,
2536 ) -> Expression {
2537 let mut guards = Vec::new();
2538 let mut found_wildcard = None;
2539 let mut detected_type = context.expected_type.cloned();
2540
2541 for guard in guard_expressions {
2542 let resolved_condition = match &guard.clause {
2543 swamp_ast::GuardClause::Wildcard(x) => {
2544 if found_wildcard.is_some() {
2545 return self.create_err(ErrorKind::GuardCanNotHaveMultipleWildcards, node);
2546 }
2547 found_wildcard = Some(x);
2548 None
2549 }
2550 swamp_ast::GuardClause::Expression(clause_expr) => {
2551 if found_wildcard.is_some() {
2552 return self.create_err(ErrorKind::WildcardMustBeLastInGuard, node);
2553 }
2554 Some(self.analyze_bool_argument_expression(clause_expr))
2555 }
2556 };
2557
2558 let resolved_result = self.analyze_expression(
2559 &guard.result,
2560 &context.with_expected_type(detected_type.as_ref(), false),
2561 );
2562 let ty = resolved_result.ty.clone();
2563 if detected_type.is_none() {
2564 detected_type = Some(ty.clone());
2565 }
2566
2567 guards.push(Guard {
2568 condition: resolved_condition,
2569 result: resolved_result,
2570 });
2571 }
2572
2573 if found_wildcard.is_none() {
2574 return self.create_err(ErrorKind::GuardMustHaveWildcard, node);
2575 }
2576
2577 let kind = ExpressionKind::Guard(guards);
2578
2579 if let Some(found_expecting_type) = detected_type {
2580 self.create_expr(kind, found_expecting_type, node)
2581 } else {
2582 self.create_err(ErrorKind::GuardHasNoType, node)
2583 }
2584 }
2585
2586 fn analyze_lambda(
2587 &mut self,
2588 node: &swamp_ast::Node,
2589 variables: &[swamp_ast::Variable],
2590 ast_expr: &swamp_ast::Expression,
2591 context: &TypeContext,
2592 ) -> Expression {
2593 let TypeKind::Function(signature) = &*context.expected_type.unwrap().kind else {
2594 return self.create_err(ErrorKind::ExpectedLambda, node);
2595 };
2596
2597 let return_block_type = TypeContext::new_argument(&signature.return_type, false);
2598
2599 self.push_lambda_scope("lambda");
2602
2603 let arity_required = signature.parameters.len();
2604 let variable_types_to_create = if variables.len() == arity_required {
2605 &signature.parameters
2606 } else if variables.len() + 1 == arity_required {
2607 &signature.parameters[1..].to_vec()
2608 } else {
2609 return self.create_err(ErrorKind::WrongNumberOfArguments(0, 0), node);
2610 };
2611
2612 let mut resolved_variables = Vec::new();
2613 for (variable, variable_type) in variables.iter().zip(variable_types_to_create) {
2614 let variable_ref = self.create_local_variable(
2615 &variable.name,
2616 variable.is_mutable.as_ref(),
2617 &variable_type.resolved_type,
2618 false,
2619 );
2620 resolved_variables.push(variable_ref);
2621 }
2622
2623 let analyzed_expression = self.analyze_expression(ast_expr, &return_block_type);
2626
2627 self.pop_block_scope("lambda");
2628
2629 let function_type = self.types().function(signature.clone());
2630 self.create_expr(
2631 ExpressionKind::Lambda(resolved_variables, Box::new(analyzed_expression)),
2632 function_type,
2633 node,
2634 )
2635 }
2636
2637 #[must_use]
2638 pub fn chain_is_owned_result(
2639 start_of_chain: &StartOfChain,
2640 chains: &Vec<Postfix>,
2641 ) -> (bool, bool) {
2642 let mut is_owned_result = matches!(start_of_chain.kind, StartOfChainKind::Expression(_));
2643 let mut is_mutable = if let StartOfChainKind::Variable(var) = &start_of_chain.kind {
2644 var.is_mutable()
2645 } else {
2646 false
2647 };
2648
2649 for chain in chains {
2650 match chain.kind {
2651 PostfixKind::StructField(_, _) => {
2652 is_owned_result = false;
2653 }
2654 PostfixKind::SliceViewSubscript(_, _) => {
2655 is_owned_result = false;
2656 }
2657 PostfixKind::MemberCall(_, _) => {
2658 is_owned_result = true;
2659 is_mutable = false;
2660 }
2661 PostfixKind::OptionalChainingOperator => {
2662 is_owned_result = true;
2663 is_mutable = false;
2664 }
2665 PostfixKind::NoneCoalescingOperator(_) => {
2666 is_owned_result = true;
2667 is_mutable = false;
2668 }
2669 PostfixKind::VecSubscript(_, _) => {}
2670 PostfixKind::SparseSubscript(_, _) => {}
2671 PostfixKind::GridSubscript(_, _, _) => {}
2672 PostfixKind::MapSubscript(_, _) => {}
2673 }
2674 }
2675
2676 (is_owned_result, is_mutable)
2677 }
2678
2679 pub fn check_assignment_mode(
2680 &mut self,
2681 lhs_is_mutable: bool,
2682 source_expression: &Expression,
2683 ty: &TypeRef,
2684 ) -> AssignmentMode {
2685 if matches!(
2686 &source_expression.kind,
2687 _ | ExpressionKind::IntrinsicCallEx(_, _)
2688 ) {
2689 return AssignmentMode::OwnedValue;
2690 }
2691
2692 if let ExpressionKind::PostfixChain(start_chain, postfix) = &source_expression.kind {
2700 let (chain_is_owned, chain_is_mutable) =
2701 Self::chain_is_owned_result(start_chain, postfix);
2702 if lhs_is_mutable {
2703 return if chain_is_mutable {
2704 AssignmentMode::CopyBlittable
2705 } else if lhs_is_mutable {
2706 if chain_is_owned {
2707 AssignmentMode::OwnedValue
2708 } else {
2709 AssignmentMode::CopyBlittable
2710 }
2711 } else {
2712 AssignmentMode::CopySharedPtr
2713 };
2714 }
2715 }
2717
2718 AssignmentMode::CopyBlittable
2719 }
2720
2721 pub const fn check_mutable_assignment(&mut self, assignment_mode: AssignmentMode, node: &Node) {}
2722
2723 pub const fn check_mutable_variable_assignment(
2724 &mut self,
2725 source_expression: &swamp_ast::Expression,
2726 ty: &TypeRef,
2727 variable: &swamp_ast::Variable,
2728 ) {
2729 }
2735
2736 pub fn analyze_variable_assignment(
2739 &mut self,
2740 variable: &swamp_ast::Variable,
2741 source_expression: &swamp_ast::Expression,
2742 ) -> Expression {
2743 let maybe_found_variable = self.try_find_variable(&variable.name);
2744
2745 let required_type = maybe_found_variable
2746 .as_ref()
2747 .map(|found_variable| found_variable.resolved_type.clone());
2748
2749 let source_expr = if let Some(target_type) = &required_type {
2750 self.analyze_expression_for_assignment_with_target_type(target_type, source_expression)
2751 } else {
2752 let any_type_context = TypeContext::new_anything_argument(true);
2753 self.analyze_expression(source_expression, &any_type_context)
2754 };
2755
2756 let target_type = if let Some(found_var) = &maybe_found_variable {
2759 &found_var.resolved_type
2760 } else {
2761 &source_expr.ty
2762 };
2763
2764 let should_check_blittable = if let Some(found_var) = &maybe_found_variable {
2766 !matches!(found_var.variable_type, VariableType::Parameter)
2767 } else {
2768 true };
2770
2771 if should_check_blittable && !target_type.is_blittable() {
2772 let debug_text = self.get_text(&variable.name);
2773 if !debug_text.starts_with('_') {
2774 return self.create_err(
2775 ErrorKind::VariableTypeMustBeBlittable(target_type.clone()),
2776 &variable.name,
2777 );
2778 }
2779 }
2780
2781 let kind: ExpressionKind = if let Some(found_var) = maybe_found_variable {
2782 if !found_var.is_mutable() {
2783 return self.create_err(ErrorKind::VariableIsNotMutable, &variable.name);
2784 }
2785 if !self
2786 .types()
2787 .compatible_with(&found_var.resolved_type, &source_expr.ty)
2788 {
2789 return self.create_err(
2790 ErrorKind::IncompatibleTypes {
2791 expected: source_expr.ty,
2792 found: found_var.resolved_type.clone(),
2793 },
2794 &variable.name,
2795 );
2796 }
2797 self.check_mutable_variable_assignment(source_expression, &source_expr.ty, variable);
2798 ExpressionKind::VariableReassignment(found_var, Box::from(source_expr))
2799 } else {
2800 if !source_expr.ty.is_blittable() {
2801 let text = self.get_text(&variable.name);
2802 error!(?text, ?required_type, ?source_expr, "variable is wrong");
2803 }
2804
2805 if variable.is_mutable.is_some() {
2808 self.check_mutable_variable_assignment(
2809 source_expression,
2810 &source_expr.ty,
2811 variable,
2812 );
2813 }
2814 let new_var = self.create_variable(variable, &source_expr.ty);
2815 ExpressionKind::VariableDefinition(new_var, Box::from(source_expr))
2816 };
2817
2818 let unit_type = self.shared.state.types.unit();
2819 self.create_expr(kind, unit_type, &variable.name)
2820 }
2821
2822 fn analyze_create_variable(
2823 &mut self,
2824 var: &swamp_ast::Variable,
2825 annotation_type: Option<&swamp_ast::Type>,
2826 source_expression: &swamp_ast::Expression,
2827 ) -> Expression {
2828 let maybe_annotated_type =
2829 annotation_type.map(|found_ast_type| self.analyze_type(found_ast_type));
2830
2831 let unsure_arg_context =
2832 TypeContext::new_unsure_argument(maybe_annotated_type.as_ref(), true);
2833
2834 let resolved_source = self.analyze_expression(source_expression, &unsure_arg_context);
2835
2836 let resulting_type = if let Some(annotated_type) = maybe_annotated_type {
2837 annotated_type
2838 } else {
2839 resolved_source.ty.clone()
2840 };
2841 let var_ref = self.create_local_variable(
2842 &var.name,
2843 Option::from(&var.is_mutable),
2844 &resulting_type,
2845 true,
2846 );
2847
2848 assert_ne!(&*resulting_type.kind, &TypeKind::Unit);
2849 let kind = ExpressionKind::VariableDefinition(var_ref, Box::from(resolved_source));
2850
2851 let unit_type = self.shared.state.types.unit();
2852
2853 self.create_expr(kind, unit_type, &var.name)
2854 }
2855
2856 fn add_location_item(
2857 &mut self,
2858 vec: &mut Vec<LocationAccess>,
2859 kind: LocationAccessKind,
2860 ty: TypeRef,
2861 ast_node: &swamp_ast::Node,
2862 ) {
2863 let resolved_node = self.to_node(ast_node);
2864 let postfix = LocationAccess {
2865 node: resolved_node,
2866 ty,
2867 kind,
2868 };
2869
2870 vec.push(postfix);
2871 }
2872
2873 fn extract_single_intrinsic_call(
2874 body: &Expression,
2875 ) -> Option<(IntrinsicFunction, Vec<ArgumentExpression>)> {
2876 if let ExpressionKind::Block(expressions) = &body.kind {
2877 let first_kind = &expressions[0].kind;
2878 if let ExpressionKind::IntrinsicCallEx(intrinsic_fn, args) = &first_kind {
2879 return Some((intrinsic_fn.clone(), args.clone()));
2880 }
2881 }
2882 None
2883 }
2884
2885 #[allow(clippy::too_many_lines)]
2886 fn analyze_chain_to_location(
2887 &mut self,
2888 chain: &swamp_ast::PostfixChain,
2889 context: &TypeContext,
2890 location_side: LocationSide,
2891 ) -> SingleLocationExpression {
2892 let mut items = Vec::new();
2893
2894 let nothing_context = TypeContext::new(None, true);
2895
2896 let base_expr = self.analyze_expression(&chain.base, ¬hing_context);
2897 let ExpressionKind::VariableAccess(start_variable) = base_expr.kind else {
2898 self.add_err(ErrorKind::NotValidLocationStartingPoint, &chain.base.node);
2899 let unit_type = self.types().unit();
2900 let err_variable = Variable {
2901 name: Default::default(),
2902 assigned_name: String::new(),
2903 resolved_type: unit_type,
2904 mutable_node: None,
2905 variable_type: VariableType::Local,
2906 scope_index: 0,
2907 variable_index: 0,
2908 unique_id_within_function: 0,
2909 virtual_register: 0,
2910 is_unused: false,
2911 };
2912 return SingleLocationExpression {
2913 kind: MutableReferenceKind::MutVariableRef,
2914 node: self.to_node(&chain.base.node),
2915 ty: self.shared.state.types.unit(),
2916 starting_variable: VariableRef::from(err_variable),
2917 access_chain: vec![],
2918 };
2919 };
2920
2921 if !start_variable.is_mutable() {
2922 self.add_err(ErrorKind::VariableIsNotMutable, &chain.base.node);
2923
2924 let unit_type = self.types().unit();
2925 let err_variable = Variable {
2926 name: Default::default(),
2927 assigned_name: String::new(),
2928 resolved_type: unit_type,
2929 mutable_node: None,
2930 variable_type: VariableType::Local,
2931 scope_index: 0,
2932 variable_index: 0,
2933 unique_id_within_function: 0,
2934 virtual_register: 0,
2935 is_unused: false,
2936 };
2937 return SingleLocationExpression {
2938 kind: MutableReferenceKind::MutVariableRef,
2939 node: self.to_node(&chain.base.node),
2940 ty: self.shared.state.types.unit(),
2941 starting_variable: VariableRef::from(err_variable),
2942 access_chain: vec![],
2943 };
2944 }
2945
2946 let mut ty = start_variable.resolved_type.clone();
2947 for (i, item) in chain.postfixes.iter().enumerate() {
2948 let is_absolute_last_in_chain = i == chain.postfixes.len() - 1;
2949 match &item {
2950 swamp_ast::Postfix::FieldAccess(field_name_node) => {
2951 let (struct_type_ref, index, return_type) =
2953 self.analyze_struct_field(field_name_node, &ty);
2954
2955 self.add_location_item(
2956 &mut items,
2957 LocationAccessKind::FieldIndex(struct_type_ref.clone(), index),
2958 return_type.clone(),
2959 field_name_node,
2960 );
2961
2962 ty = return_type.clone();
2963 }
2964 swamp_ast::Postfix::SubscriptTuple(x_expr, y_expr) => match &*ty.kind {
2965 TypeKind::GridView(element_type)
2966 | TypeKind::GridStorage(element_type, _, _) => {
2967 let int_type = self.types().int();
2968 let unsigned_int_context = TypeContext::new_argument(&int_type, true);
2969 let unsigned_int_x_expr =
2970 self.analyze_expression(x_expr, &unsigned_int_context);
2971
2972 let unsigned_int_y_expr =
2973 self.analyze_expression(y_expr, &unsigned_int_context);
2974
2975 let grid_type = GridType {
2976 element: element_type.clone(),
2977 };
2978
2979 self.add_location_item(
2980 &mut items,
2981 LocationAccessKind::GridSubscript(
2982 grid_type,
2983 unsigned_int_x_expr,
2984 unsigned_int_y_expr,
2985 ),
2986 element_type.clone(),
2987 &x_expr.node,
2988 );
2989
2990 ty = element_type.clone();
2991 }
2992 _ => panic!("not allowed"),
2993 },
2994 swamp_ast::Postfix::Subscript(ast_key_expression) => {
2995 let underlying = &ty.kind;
2996 match &**underlying {
2997 TypeKind::SliceView(element_type)
2998 | TypeKind::StackStorage(element_type, _)
2999 | TypeKind::StackView(element_type)
3000 | TypeKind::VecStorage(element_type, _)
3001 | TypeKind::DynamicLengthVecView(element_type)
3002 | TypeKind::FixedCapacityAndLengthArray(element_type, _) => {
3003 let int_type = self.types().int();
3004 let unsigned_int_context = TypeContext::new_argument(&int_type, false);
3005 let unsigned_int_expr =
3006 self.analyze_expression(ast_key_expression, &unsigned_int_context);
3007
3008 let slice_type = SliceViewType {
3009 element: element_type.clone(),
3010 };
3011
3012 self.add_location_item(
3013 &mut items,
3014 LocationAccessKind::SliceViewSubscript(
3015 slice_type,
3016 unsigned_int_expr,
3017 ),
3018 element_type.clone(),
3019 &ast_key_expression.node,
3020 );
3021
3022 ty = element_type.clone();
3023 }
3024 TypeKind::SparseView(element_type)
3025 | TypeKind::SparseStorage(element_type, _) => {
3026 let int_type = self.types().int();
3027 let unsigned_int_context = TypeContext::new_argument(&int_type, false);
3028 let unsigned_int_expr =
3029 self.analyze_expression(ast_key_expression, &unsigned_int_context);
3030
3031 let slice_type = SparseType {
3032 element: element_type.clone(),
3033 };
3034
3035 self.add_location_item(
3036 &mut items,
3037 LocationAccessKind::SparseSubscript(slice_type, unsigned_int_expr),
3038 element_type.clone(),
3039 &ast_key_expression.node,
3040 );
3041
3042 ty = element_type.clone();
3043 }
3044 TypeKind::MapStorage(key_type, value_type, ..)
3045 | TypeKind::DynamicLengthMapView(key_type, value_type) => {
3046 let key_index_context = TypeContext::new_argument(key_type, false);
3047 let key_expr =
3048 self.analyze_expression(ast_key_expression, &key_index_context);
3049
3050 let map_like_type = MapType {
3051 key: key_type.clone(),
3052 value: value_type.clone(),
3053 };
3054
3055 match location_side {
3056 LocationSide::Lhs => {
3057 let access_kind = if is_absolute_last_in_chain {
3061 LocationAccessKind::MapSubscriptCreateIfNeeded(
3062 map_like_type,
3063 key_expr,
3064 )
3065 } else {
3066 LocationAccessKind::MapSubscriptMustExist(
3067 map_like_type,
3068 key_expr,
3069 )
3070 };
3071
3072 self.add_location_item(
3073 &mut items,
3074 access_kind,
3075 value_type.clone(),
3076 &ast_key_expression.node,
3077 );
3078 }
3079 LocationSide::Mutable | LocationSide::Rhs => {
3080 self.add_location_item(
3081 &mut items,
3082 LocationAccessKind::MapSubscriptMustExist(
3083 map_like_type,
3084 key_expr,
3085 ),
3086 value_type.clone(),
3087 &ast_key_expression.node,
3088 );
3089 }
3090 }
3091 ty = value_type.clone();
3092 }
3093
3094 _ => {
3095 eprintln!("can not subscript with this type: {underlying}");
3096 todo!()
3097 }
3098 }
3099 }
3100
3101 swamp_ast::Postfix::MemberCall(node, _generic_arguments, _regular_args) => {
3102 return SingleLocationExpression {
3103 kind: MutableReferenceKind::MutVariableRef,
3104 node: self.to_node(node),
3105 ty: self.shared.state.types.unit(),
3106 starting_variable: start_variable,
3107 access_chain: vec![],
3108 };
3109 }
3110 swamp_ast::Postfix::FunctionCall(node, _generic_arguments, _regular_args) => {
3117 return SingleLocationExpression {
3118 kind: MutableReferenceKind::MutVariableRef,
3119 node: self.to_node(node),
3120 ty: self.shared.state.types.unit(),
3121 starting_variable: start_variable,
3122 access_chain: vec![],
3123 };
3124 }
3125 swamp_ast::Postfix::OptionalChainingOperator(node) => {
3126 return SingleLocationExpression {
3127 kind: MutableReferenceKind::MutVariableRef,
3128 node: self.to_node(node),
3129 ty: self.shared.state.types.unit(),
3130 starting_variable: start_variable,
3131 access_chain: vec![],
3132 };
3133 }
3134 swamp_ast::Postfix::NoneCoalescingOperator(expr) => {
3135 return SingleLocationExpression {
3136 kind: MutableReferenceKind::MutVariableRef,
3137 node: self.to_node(&expr.node),
3138 ty: self.shared.state.types.unit(),
3139 starting_variable: start_variable,
3140 access_chain: vec![],
3141 };
3142 }
3143 }
3144 }
3145
3146 if let Some(found_expected_type) = context.expected_type {
3147 if !self.types().compatible_with(found_expected_type, &ty) {
3148 self.add_err(
3149 ErrorKind::IncompatibleTypes {
3150 expected: found_expected_type.clone(),
3151 found: ty.clone(),
3152 },
3153 &chain.base.node,
3154 );
3155 }
3156 }
3157
3158 SingleLocationExpression {
3159 kind: MutableReferenceKind::MutVariableRef,
3160 node: self.to_node(&chain.base.node),
3161 ty,
3162 starting_variable: start_variable,
3163 access_chain: items,
3164 }
3165 }
3166
3167 fn analyze_to_location(
3168 &mut self,
3169 expr: &swamp_ast::Expression,
3170 context: &TypeContext,
3171 location_type: LocationSide,
3172 ) -> SingleLocationExpression {
3173 match &expr.kind {
3174 swamp_ast::ExpressionKind::PostfixChain(chain) => {
3175 self.analyze_chain_to_location(chain, context, location_type)
3176 }
3177 swamp_ast::ExpressionKind::VariableReference(variable) => {
3178 let var = self.find_variable(variable);
3179 if !var.is_mutable() {
3180 self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
3181 }
3182
3183 SingleLocationExpression {
3184 kind: MutableReferenceKind::MutVariableRef,
3185 node: self.to_node(&variable.name),
3186 ty: var.resolved_type.clone(),
3187 starting_variable: var,
3188 access_chain: vec![],
3189 }
3190 }
3191 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
3192 let generated_var = swamp_ast::Variable {
3193 name: qualified_identifier.name.clone(),
3194 is_mutable: None,
3195 };
3196 let var = self.find_variable(&generated_var);
3197 if !var.is_mutable() {
3198 self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
3199 }
3200 SingleLocationExpression {
3201 kind: MutableReferenceKind::MutVariableRef,
3202 node: self.to_node(&generated_var.name),
3203 ty: var.resolved_type.clone(),
3204 starting_variable: var,
3205 access_chain: vec![],
3206 }
3207 }
3208 _ => {
3209 self.add_err(ErrorKind::NotValidLocationStartingPoint, &expr.node);
3210 let unit_type = self.types().unit();
3211 SingleLocationExpression {
3212 kind: MutableReferenceKind::MutVariableRef,
3213 node: self.to_node(&expr.node),
3214 ty: unit_type.clone(),
3215 starting_variable: Rc::new(Variable {
3216 name: Default::default(),
3217 assigned_name: String::new(),
3218 resolved_type: unit_type,
3219 mutable_node: None,
3220 variable_type: VariableType::Local,
3221 scope_index: 0,
3222 variable_index: 0,
3223 unique_id_within_function: 0,
3224 virtual_register: 0,
3225 is_unused: false,
3226 }),
3227 access_chain: vec![],
3228 }
3229 }
3230 }
3231 }
3232
3233 fn analyze_expression_for_assignment_compound(
3234 &mut self,
3235 target_expression: &swamp_ast::Expression,
3236 ast_source_expression: &swamp_ast::Expression,
3237 ) -> (TargetAssignmentLocation, Expression) {
3238 let any_argument_context = TypeContext::new_anything_argument(true);
3239 let source_expr = self.analyze_expression(ast_source_expression, &any_argument_context);
3240 let source_expr_type_context = TypeContext::new_argument(&source_expr.ty, true);
3241
3242 let resolved_location = TargetAssignmentLocation(self.analyze_to_location(
3243 target_expression,
3244 &source_expr_type_context,
3245 LocationSide::Rhs,
3246 ));
3247
3248 (resolved_location, source_expr)
3249 }
3250
3251 fn analyze_expression_for_assignment_with_target_type(
3278 &mut self,
3279 target_type: &TypeRef,
3280 ast_source_expression: &swamp_ast::Expression,
3281 ) -> Expression {
3282 let base_context = TypeContext::new_argument(target_type, true);
3283 let source_expr = self.analyze_expression(ast_source_expression, &base_context);
3284
3285 let final_expr = if self.types().compatible_with(target_type, &source_expr.ty) {
3286 source_expr
3287 } else {
3288 let source_type = source_expr.ty.clone();
3289 self.types_did_not_match_try_late_coerce_expression(
3290 source_expr,
3291 target_type,
3292 &source_type,
3293 &ast_source_expression.node,
3294 )
3295 };
3296
3297 let assignment_mode = self.check_assignment_mode(true, &final_expr, target_type); self.check_mutable_assignment(assignment_mode, &final_expr.node);
3300
3301 final_expr
3302 }
3303
3304 fn analyze_expression_for_assignment(
3305 &mut self,
3306 ast_target_location_expression: &swamp_ast::Expression,
3307 ast_source_expression: &swamp_ast::Expression,
3308 ) -> (TargetAssignmentLocation, Expression) {
3309 let any_argument_context = TypeContext::new_anything_argument(true);
3310 let resolved_location = self.analyze_to_location(
3311 ast_target_location_expression,
3312 &any_argument_context,
3313 LocationSide::Lhs,
3314 );
3315
3316 let target_type = resolved_location.ty.clone();
3317 let mut_type = target_type; let mut_location = TargetAssignmentLocation(resolved_location);
3319
3320 let final_expr = self
3321 .analyze_expression_for_assignment_with_target_type(&mut_type, ast_source_expression);
3322
3323 (mut_location, final_expr)
3324 }
3325
3326 fn analyze_assignment_compound(
3327 &mut self,
3328 target_expression: &swamp_ast::Expression,
3329 ast_op: &swamp_ast::CompoundOperator,
3330 ast_source_expression: &swamp_ast::Expression,
3331 ) -> Expression {
3332 let resolved_op = self.analyze_compound_operator(ast_op);
3333
3334 let (resolved_location, source_expr) = self
3335 .analyze_expression_for_assignment_compound(target_expression, ast_source_expression);
3336
3337 let kind = ExpressionKind::CompoundAssignment(
3338 resolved_location,
3339 resolved_op.kind,
3340 Box::from(source_expr),
3341 );
3342
3343 let unit_type = self.shared.state.types.unit();
3344
3345 self.create_expr(kind, unit_type, &target_expression.node)
3346 }
3347
3348 fn analyze_assignment_mode(lhs: SingleLocationExpression) {}
3349
3350 fn analyze_assignment(
3351 &mut self,
3352 target_location: &swamp_ast::Expression,
3353 ast_source_expression: &swamp_ast::Expression,
3354 ) -> Expression {
3355 let (mut_location, source_expr) =
3356 self.analyze_expression_for_assignment(target_location, ast_source_expression);
3357 let kind = ExpressionKind::Assignment(Box::from(mut_location), Box::from(source_expr));
3358 let unit_type = self.shared.state.types.unit();
3359
3360 self.create_expr(kind, unit_type, &target_location.node)
3363 }
3364
3365 #[must_use]
3366 pub const fn create_expr(
3367 &self,
3368 kind: ExpressionKind,
3369 ty: TypeRef,
3370 ast_node: &swamp_ast::Node,
3371 ) -> Expression {
3372 Expression {
3374 kind,
3375 ty,
3376 node: self.to_node(ast_node),
3377 }
3378 }
3379
3380 fn analyze_destructuring(
3381 &mut self,
3382 node: &swamp_ast::Node,
3383 target_ast_variables: &[swamp_ast::Variable],
3384 tuple_expression: &swamp_ast::Expression,
3385 ) -> Expression {
3386 let any_context = TypeContext::new_anything_argument(true);
3387 let tuple_resolved = self.analyze_expression(tuple_expression, &any_context);
3388 let tuple_expr_type = &tuple_resolved.ty;
3389 let unit = self.types().unit();
3390
3391 let mut variable_refs = Vec::new();
3392 if let TypeKind::Tuple(tuple) = &*tuple_expr_type.kind {
3393 if target_ast_variables.len() > tuple.len() {
3394 return self.create_err(ErrorKind::TooManyDestructureVariables, node);
3395 }
3396 for (ast_variable, tuple_type) in target_ast_variables.iter().zip(tuple.clone()) {
3397 let variable_ref = self.create_local_variable(
3398 &ast_variable.name,
3399 ast_variable.is_mutable.as_ref(),
3400 &tuple_type,
3401 true,
3402 );
3403 variable_refs.push(variable_ref);
3404 }
3405 let expr_kind = ExpressionKind::TupleDestructuring(
3406 variable_refs,
3407 tuple_expr_type.clone(),
3408 Box::from(tuple_resolved),
3409 );
3410
3411 self.create_expr(expr_kind, unit, node)
3412 } else {
3413 self.create_err(ErrorKind::CanNotDestructure, node)
3414 }
3415 }
3416
3417 fn analyze_normal_member_call(
3418 &mut self,
3419 type_that_member_is_on: &TypeRef,
3420 found_function: &FunctionRef,
3421 generic_arguments: Vec<TypeRef>,
3422 ast_arguments: &[swamp_ast::Expression],
3423 is_mutable: bool,
3424 node: &swamp_ast::Node,
3425 ) -> Signature {
3426 let resolved_node = self.to_node(node);
3427 found_function.signature().clone()
3430 }
3431
3432 fn queue_member_signature(
3433 &mut self,
3434 self_type: &TypeRef,
3435 key_type: Option<&TypeRef>,
3436 element_type: &TypeRef,
3437 field_name_str: &str,
3438 lambda_variable_count: usize,
3439 node: &swamp_ast::Node,
3440 ) -> Option<(IntrinsicFunction, Signature)> {
3441 let self_type_param = TypeForParameter {
3442 name: "self".to_string(),
3443 resolved_type: self_type.clone(),
3444 is_mutable: false,
3445 node: None,
3446 };
3447 let self_mutable_type_param = TypeForParameter {
3448 name: "self".to_string(),
3449 resolved_type: self_type.clone(),
3450 is_mutable: true,
3451 node: None,
3452 };
3453 let intrinsic_and_signature = match field_name_str {
3454 "enqueue" => (
3455 IntrinsicFunction::VecPush,
3456 Signature {
3457 parameters: vec![
3458 self_mutable_type_param,
3459 TypeForParameter {
3460 name: "element".to_string(),
3461 resolved_type: element_type.clone(),
3462 is_mutable: false,
3463 node: None,
3464 },
3465 ],
3466 return_type: self.types().unit(),
3467 },
3468 ),
3469 "dequeue" => (
3470 IntrinsicFunction::VecRemoveFirstIndexGetValue,
3471 Signature {
3472 parameters: vec![self_mutable_type_param],
3473 return_type: element_type.clone(),
3474 },
3475 ),
3476 _ => {
3477 self.slice_member_signature(
3478 self_type,
3479 key_type,
3480 element_type,
3481 field_name_str,
3482 lambda_variable_count,
3483 node,
3484 )
3485 }?,
3486 };
3487
3488 Some(intrinsic_and_signature)
3489 }
3490
3491 fn sparse_member_signature(
3492 &mut self,
3493 self_type: &TypeRef,
3494 element_type: &TypeRef,
3495 field_name_str: &str,
3496 lambda_variable_count: usize,
3497 node: &swamp_ast::Node,
3498 ) -> Option<(IntrinsicFunction, Signature)> {
3499 let key_type = self.types().int(); let self_type_param = TypeForParameter {
3502 name: "self".to_string(),
3503 resolved_type: self_type.clone(),
3504 is_mutable: false,
3505 node: None,
3506 };
3507 let self_mutable_type_param = TypeForParameter {
3508 name: "self".to_string(),
3509 resolved_type: self_type.clone(),
3510 is_mutable: true,
3511 node: None,
3512 };
3513 let intrinsic_and_signature = match field_name_str {
3514 "add" => (
3515 IntrinsicFunction::SparseAdd,
3516 Signature {
3517 parameters: vec![
3518 self_mutable_type_param,
3519 TypeForParameter {
3520 name: "element".to_string(),
3521 resolved_type: element_type.clone(),
3522 is_mutable: false,
3523 node: None,
3524 },
3525 ],
3526 return_type: self.types().int(),
3527 },
3528 ),
3529 "remove" => (
3530 IntrinsicFunction::SparseRemove,
3531 Signature {
3532 parameters: vec![
3533 self_mutable_type_param,
3534 TypeForParameter {
3535 name: "key".to_string(),
3536 resolved_type: key_type,
3537 is_mutable: false,
3538 node: None,
3539 },
3540 ],
3541 return_type: self.types().unit(),
3542 },
3543 ),
3544 "is_alive" => (
3545 IntrinsicFunction::SparseIsAlive,
3546 Signature {
3547 parameters: vec![
3548 self_type_param,
3549 TypeForParameter {
3550 name: "element".to_string(),
3551 resolved_type: element_type.clone(),
3552 is_mutable: false,
3553 node: None,
3554 },
3555 ],
3556 return_type: self.types().bool(),
3557 },
3558 ),
3559
3560 _ => {
3561 self.slice_member_signature(
3562 self_type,
3563 Option::from(key_type).as_ref(),
3564 element_type,
3565 field_name_str,
3566 lambda_variable_count,
3567 node,
3568 )
3569 }?,
3570 };
3571 Some(intrinsic_and_signature)
3572 }
3573
3574 fn vec_member_signature(
3575 &mut self,
3576 self_type: &TypeRef,
3577 element_type: &TypeRef,
3578 field_name_str: &str,
3579 lambda_variable_count: usize,
3580 node: &swamp_ast::Node,
3581 ) -> Option<(IntrinsicFunction, Signature)> {
3582 let key_type = self.types().int();
3583 let self_type_param = TypeForParameter {
3584 name: "self".to_string(),
3585 resolved_type: self_type.clone(),
3586 is_mutable: false,
3587 node: None,
3588 };
3589 let self_mutable_type_param = TypeForParameter {
3590 name: "self".to_string(),
3591 resolved_type: self_type.clone(),
3592 is_mutable: true,
3593 node: None,
3594 };
3595 let intrinsic_and_signature = match field_name_str {
3596 "prepend" => (
3597 IntrinsicFunction::VecPush,
3598 Signature {
3599 parameters: vec![
3600 self_mutable_type_param,
3601 TypeForParameter {
3602 name: "element".to_string(),
3603 resolved_type: element_type.clone(),
3604 is_mutable: false,
3605 node: None,
3606 },
3607 ],
3608 return_type: self.types().unit(),
3609 },
3610 ),
3611 "push" => (
3612 IntrinsicFunction::VecPush,
3613 Signature {
3614 parameters: vec![
3615 self_mutable_type_param,
3616 TypeForParameter {
3617 name: "element".to_string(),
3618 resolved_type: element_type.clone(),
3619 is_mutable: false,
3620 node: None,
3621 },
3622 ],
3623 return_type: self.types().unit(),
3624 },
3625 ),
3626 "pop" => (
3627 IntrinsicFunction::VecPop,
3628 Signature {
3629 parameters: vec![self_mutable_type_param],
3630 return_type: element_type.clone(),
3631 },
3632 ),
3633
3634 _ => {
3635 self.slice_member_signature(
3636 self_type,
3637 Option::from(key_type).as_ref(),
3638 element_type,
3639 field_name_str,
3640 lambda_variable_count,
3641 node,
3642 )
3643 }?,
3644 };
3645 Some(intrinsic_and_signature)
3646 }
3647
3648 #[allow(clippy::unnecessary_wraps)]
3649 fn grid_member_signature(
3650 &mut self,
3651 self_type: &TypeRef,
3652 element_type: &TypeRef,
3653 field_name_str: &str,
3654 node: &swamp_ast::Node,
3655 ) -> Option<(IntrinsicFunction, Signature)> {
3656 let self_type_param = TypeForParameter {
3657 name: "self".to_string(),
3658 resolved_type: self_type.clone(),
3659 is_mutable: false,
3660 node: None,
3661 };
3662 let self_mutable_type_param = TypeForParameter {
3663 name: "self".to_string(),
3664 resolved_type: self_type.clone(),
3665 is_mutable: true,
3666 node: None,
3667 };
3668 let element_param = TypeForParameter {
3669 name: "element".to_string(),
3670 resolved_type: element_type.clone(),
3671 is_mutable: false,
3672 node: None,
3673 };
3674 let int_type = self.types().int();
3675
3676 let int_param = TypeForParameter {
3677 name: "x_or_y".to_string(),
3678 resolved_type: int_type.clone(),
3679 is_mutable: false,
3680 node: None,
3681 };
3682 let intrinsic_and_signature = match field_name_str {
3683 "set" => (
3684 IntrinsicFunction::GridSet,
3685 Signature {
3686 parameters: vec![self_type_param, int_param.clone(), int_param, element_param],
3687 return_type: self.types().unit(),
3688 },
3689 ),
3690
3691 "get" => (
3692 IntrinsicFunction::GridGet,
3693 Signature {
3694 parameters: vec![self_type_param, int_param.clone(), int_param],
3695 return_type: element_type.clone(),
3696 },
3697 ),
3698
3699 "width" => (
3700 IntrinsicFunction::GridWidth,
3701 Signature {
3702 parameters: vec![self_type_param],
3703 return_type: int_type,
3704 },
3705 ),
3706
3707 "height" => (
3708 IntrinsicFunction::GridHeight,
3709 Signature {
3710 parameters: vec![self_type_param],
3711 return_type: int_type,
3712 },
3713 ),
3714
3715 _ => panic!("unknown grid method {field_name_str}"),
3716 };
3717
3718 Some(intrinsic_and_signature)
3719 }
3720
3721 fn basic_collection_member_signature(
3722 &mut self,
3723 self_type: &TypeRef,
3724 field_name_str: &str,
3725 node: &swamp_ast::Node,
3726 ) -> Option<(IntrinsicFunction, Signature)> {
3727 let self_type_param = TypeForParameter {
3728 name: "self".to_string(),
3729 resolved_type: self_type.clone(),
3730 is_mutable: false,
3731 node: None,
3732 };
3733 let self_mut_type_param = TypeForParameter {
3734 name: "self".to_string(),
3735 resolved_type: self_type.clone(),
3736 is_mutable: true,
3737 node: None,
3738 };
3739 let intrinsic_and_signature = match field_name_str {
3740 "len" => {
3741 let signature = Signature {
3742 parameters: vec![self_type_param],
3743 return_type: self.types().int(),
3744 };
3745 (IntrinsicFunction::VecLen, signature)
3746 }
3747 "is_empty" => (
3748 IntrinsicFunction::VecIsEmpty,
3749 Signature {
3750 parameters: vec![self_type_param],
3751 return_type: self.types().bool(),
3752 },
3753 ),
3754 "capacity" => {
3755 let signature = Signature {
3756 parameters: vec![self_type_param],
3757 return_type: self.types().int(),
3758 };
3759 (IntrinsicFunction::VecCapacity, signature)
3760 }
3761 _ => {
3762 self.add_err(ErrorKind::UnknownMemberFunction(self_type.clone()), node);
3763
3764 return None;
3765 }
3766 };
3767 Some(intrinsic_and_signature)
3768 }
3769 #[allow(clippy::too_many_lines)]
3770 fn codepoint_member_signature(
3771 &mut self,
3772 self_type: &TypeRef,
3773 key_type: Option<&TypeRef>,
3774 element_type: &TypeRef,
3775 field_name_str: &str,
3776 lambda_variable_count: usize,
3777 node: &swamp_ast::Node,
3778 ) -> Option<(IntrinsicFunction, Signature)> {
3779 let self_type_param = TypeForParameter {
3780 name: "self".to_string(),
3781 resolved_type: self_type.clone(),
3782 is_mutable: false,
3783 node: None,
3784 };
3785
3786 match field_name_str {
3787 "to_int" => Some((
3788 IntrinsicFunction::CodepointToInt,
3789 Signature {
3790 parameters: vec![self_type_param],
3791 return_type: self.types().int(),
3792 },
3793 )),
3794 _ => None,
3795 }
3796 }
3797
3798 #[allow(clippy::too_many_lines)]
3799 fn byte_member_signature(
3800 &mut self,
3801 self_type: &TypeRef,
3802 key_type: Option<&TypeRef>,
3803 element_type: &TypeRef,
3804 field_name_str: &str,
3805 lambda_variable_count: usize,
3806 node: &swamp_ast::Node,
3807 ) -> Option<(IntrinsicFunction, Signature)> {
3808 let self_type_param = TypeForParameter {
3809 name: "self".to_string(),
3810 resolved_type: self_type.clone(),
3811 is_mutable: false,
3812 node: None,
3813 };
3814
3815 match field_name_str {
3816 "to_int" => Some((
3817 IntrinsicFunction::ByteToInt,
3818 Signature {
3819 parameters: vec![self_type_param],
3820 return_type: self.types().int(),
3821 },
3822 )),
3823 _ => None,
3824 }
3825 }
3826
3827 #[allow(clippy::too_many_lines)]
3828 fn string_member_signature(
3829 &mut self,
3830 self_type: &TypeRef,
3831 key_type: Option<&TypeRef>,
3832 element_type: &TypeRef,
3833 field_name_str: &str,
3834 lambda_variable_count: usize,
3835 node: &swamp_ast::Node,
3836 ) -> Option<(IntrinsicFunction, Signature)> {
3837 self.vec_member_signature(
3838 self_type,
3839 element_type,
3840 field_name_str,
3841 lambda_variable_count,
3842 node,
3843 )
3844 }
3845
3846 #[allow(clippy::too_many_lines)]
3847 fn slice_member_signature(
3848 &mut self,
3849 self_type: &TypeRef,
3850 key_type: Option<&TypeRef>,
3851 element_type: &TypeRef,
3852 field_name_str: &str,
3853 lambda_variable_count: usize,
3854 node: &swamp_ast::Node,
3855 ) -> Option<(IntrinsicFunction, Signature)> {
3856 let slice_view_type = self.types().slice_view(&element_type.clone());
3857 let int_type = self.types().int();
3858 let self_type_param = TypeForParameter {
3859 name: "self".to_string(),
3860 resolved_type: slice_view_type.clone(),
3861 is_mutable: false,
3862 node: None,
3863 };
3864 let self_mut_type_param = TypeForParameter {
3865 name: "self".to_string(),
3866 resolved_type: slice_view_type,
3867 is_mutable: true,
3868 node: None,
3869 };
3870 let intrinsic_and_signature = match field_name_str {
3871 "for" => {
3872 let parameters = if lambda_variable_count == 2 {
3873 vec![
3874 TypeForParameter {
3875 name: "key".to_string(),
3876 resolved_type: key_type.unwrap().clone(),
3877 is_mutable: false,
3878 node: None,
3879 },
3880 TypeForParameter {
3881 name: "element".to_string(),
3882 resolved_type: element_type.clone(),
3883 is_mutable: false,
3884 node: None,
3885 },
3886 ]
3887 } else {
3888 vec![TypeForParameter {
3889 name: "element".to_string(),
3890 resolved_type: element_type.clone(),
3891 is_mutable: false,
3892 node: None,
3893 }]
3894 };
3895 let lambda_signature = Signature {
3896 parameters,
3897 return_type: self.types().unit(),
3898 };
3899 let lambda_function_type = self.types().function(lambda_signature);
3900 (
3901 IntrinsicFunction::TransformerFor,
3902 Signature {
3903 parameters: vec![
3904 self_type_param,
3905 TypeForParameter {
3906 name: "lambda".to_string(),
3907 resolved_type: lambda_function_type,
3908 is_mutable: false,
3909 node: None,
3910 },
3911 ],
3912 return_type: self.types().unit(), },
3914 )
3915 }
3916 "while" => {
3917 let parameters = if lambda_variable_count == 2 {
3918 vec![
3919 TypeForParameter {
3920 name: "key".to_string(),
3921 resolved_type: key_type.unwrap().clone(),
3922 is_mutable: false,
3923 node: None,
3924 },
3925 TypeForParameter {
3926 name: "element".to_string(),
3927 resolved_type: element_type.clone(),
3928 is_mutable: false,
3929 node: None,
3930 },
3931 ]
3932 } else {
3933 vec![TypeForParameter {
3934 name: "element".to_string(),
3935 resolved_type: element_type.clone(),
3936 is_mutable: false,
3937 node: None,
3938 }]
3939 };
3940 let lambda_signature = Signature {
3941 parameters,
3942 return_type: self.types().bool(), };
3944 let lambda_function_type = self.types().function(lambda_signature);
3945 (
3946 IntrinsicFunction::TransformerWhile,
3947 Signature {
3948 parameters: vec![
3949 self_type_param,
3950 TypeForParameter {
3951 name: "lambda".to_string(),
3952 resolved_type: lambda_function_type,
3953 is_mutable: false,
3954 node: None,
3955 },
3956 ],
3957 return_type: self.types().unit(), },
3959 )
3960 }
3961 "filter" => {
3962 let lambda_signature = Signature {
3963 parameters: vec![TypeForParameter {
3964 name: "element".to_string(),
3965 resolved_type: element_type.clone(),
3966 is_mutable: false,
3967 node: None,
3968 }],
3969 return_type: self.types().bool(),
3970 };
3971 let lambda_function_type = self.types().function(lambda_signature);
3972 (
3973 IntrinsicFunction::TransformerFilter,
3974 Signature {
3975 parameters: vec![
3976 self_type_param,
3977 TypeForParameter {
3978 name: "lambda".to_string(),
3979 resolved_type: lambda_function_type,
3980 is_mutable: false,
3981 node: None,
3982 },
3983 ],
3984 return_type: self.shared.state.types.slice_view(&element_type.clone()),
3985 },
3986 )
3987 }
3988 "find" => {
3989 let lambda_signature = Signature {
3990 parameters: vec![TypeForParameter {
3991 name: "element".to_string(),
3992 resolved_type: element_type.clone(),
3993 is_mutable: false,
3994 node: None,
3995 }],
3996 return_type: self.types().bool(),
3997 };
3998 let lambda_function_type = self.types().function(lambda_signature);
3999 (
4000 IntrinsicFunction::TransformerFind,
4001 Signature {
4002 parameters: vec![
4003 self_type_param,
4004 TypeForParameter {
4005 name: "lambda".to_string(),
4006 resolved_type: lambda_function_type,
4007 is_mutable: false,
4008 node: None,
4009 },
4010 ],
4011 return_type: self.shared.state.types.optional(&element_type.clone()),
4012 },
4013 )
4014 }
4015
4016 "remove" => {
4017 let signature = Signature {
4018 parameters: vec![
4019 self_mut_type_param,
4020 TypeForParameter {
4021 name: "index".to_string(),
4022 resolved_type: int_type,
4023 is_mutable: false,
4024 node: None,
4025 },
4026 ],
4027 return_type: self.types().unit(),
4028 };
4029 (IntrinsicFunction::VecRemoveIndex, signature)
4030 }
4031 _ => return self.basic_collection_member_signature(self_type, field_name_str, node),
4032 };
4033 Some(intrinsic_and_signature)
4034 }
4035
4036 #[allow(clippy::unnecessary_wraps, clippy::result_large_err)]
4037 fn map_member_signature(
4038 &mut self,
4039 self_type: &TypeRef,
4040 key_type: &TypeRef,
4041 value_type: &TypeRef,
4042 field_name_str: &str,
4043 node: &swamp_ast::Node,
4044 ) -> Option<(IntrinsicFunction, Signature)> {
4045 let self_type_param = TypeForParameter {
4046 name: "self".to_string(),
4047 resolved_type: self_type.clone(),
4048 is_mutable: false,
4049 node: None,
4050 };
4051
4052 let mutable_self_type_param = TypeForParameter {
4053 name: "self".to_string(),
4054 resolved_type: self_type.clone(),
4055 is_mutable: true,
4056 node: None,
4057 };
4058
4059 let intrinsic_and_signature = match field_name_str {
4060 "has" => (
4061 IntrinsicFunction::MapHas,
4062 Signature {
4063 parameters: vec![
4064 self_type_param,
4065 TypeForParameter {
4066 name: "key".to_string(),
4067 resolved_type: key_type.clone(),
4068 is_mutable: false,
4069 node: None,
4070 },
4071 ],
4072 return_type: self.types().bool(),
4073 },
4074 ),
4075 "remove" => (
4076 IntrinsicFunction::MapRemove,
4077 Signature {
4078 parameters: vec![
4079 mutable_self_type_param,
4080 TypeForParameter {
4081 name: "key".to_string(),
4082 resolved_type: key_type.clone(),
4083 is_mutable: false,
4084 node: None,
4085 },
4086 ],
4087 return_type: self.types().unit(),
4088 },
4089 ),
4090 "len" => (
4091 IntrinsicFunction::MapLen,
4092 Signature {
4093 parameters: vec![self_type_param],
4094 return_type: self.types().int(),
4095 },
4096 ),
4097 "capacity" => (
4098 IntrinsicFunction::MapCapacity,
4099 Signature {
4100 parameters: vec![self_type_param],
4101 return_type: self.types().int(),
4102 },
4103 ),
4104 "is_empty" => (
4105 IntrinsicFunction::MapIsEmpty,
4106 Signature {
4107 parameters: vec![self_type_param],
4108 return_type: self.types().bool(),
4109 },
4110 ),
4111 _ => todo!("unknown map member"),
4112 };
4113
4114 Some(intrinsic_and_signature)
4115 }
4116
4117 fn check_intrinsic_member_signature(
4118 &mut self,
4119 type_that_member_is_on: &TypeRef,
4120 field_name_str: &str,
4121 lambda_variables_count: usize,
4122 node: &swamp_ast::Node,
4123 ) -> Option<(IntrinsicFunction, Signature)> {
4124 let ty = type_that_member_is_on;
4125 let int_type = self.types().int();
4126 match &*ty.kind {
4127 TypeKind::GridStorage(element_type, ..) | TypeKind::GridView(element_type) => self
4128 .grid_member_signature(type_that_member_is_on, element_type, field_name_str, node),
4129 TypeKind::SparseStorage(element_type, ..) | TypeKind::SparseView(element_type) => self
4130 .sparse_member_signature(
4131 type_that_member_is_on,
4132 element_type,
4133 field_name_str,
4134 lambda_variables_count,
4135 node,
4136 ),
4137 TypeKind::QueueStorage(element_type, ..) => self.queue_member_signature(
4138 type_that_member_is_on,
4139 None,
4140 element_type,
4141 field_name_str,
4142 lambda_variables_count,
4143 node,
4144 ),
4145 TypeKind::StackStorage(element_type, ..)
4146 | TypeKind::QueueStorage(element_type, ..)
4147 | TypeKind::VecStorage(element_type, ..)
4148 | TypeKind::DynamicLengthVecView(element_type) => self.vec_member_signature(
4149 type_that_member_is_on,
4150 element_type,
4151 field_name_str,
4152 lambda_variables_count,
4153 node,
4154 ),
4155 TypeKind::SliceView(element_type) => self.slice_member_signature(
4156 type_that_member_is_on,
4157 Some(&int_type),
4158 element_type,
4159 field_name_str,
4160 lambda_variables_count,
4161 node,
4162 ),
4163 TypeKind::Byte => {
4164 let element_type = self.shared.state.types.byte();
4165 self.byte_member_signature(
4166 type_that_member_is_on,
4167 Some(&int_type),
4168 &element_type,
4169 field_name_str,
4170 lambda_variables_count,
4171 node,
4172 )
4173 }
4174 TypeKind::Codepoint => {
4175 let element_type = self.shared.state.types.codepoint();
4176 self.codepoint_member_signature(
4177 type_that_member_is_on,
4178 Some(&int_type),
4179 &element_type,
4180 field_name_str,
4181 lambda_variables_count,
4182 node,
4183 )
4184 }
4185 TypeKind::String { .. } | TypeKind::StringStorage(..) => {
4186 let element_type = self.shared.state.types.byte();
4187 self.string_member_signature(
4188 type_that_member_is_on,
4189 Some(&int_type),
4190 &element_type,
4191 field_name_str,
4192 lambda_variables_count,
4193 node,
4194 )
4195 }
4196 TypeKind::DynamicLengthMapView(key, value) | TypeKind::MapStorage(key, value, _) => {
4197 self.map_member_signature(type_that_member_is_on, key, value, field_name_str, node)
4198 }
4199
4200 TypeKind::FixedCapacityAndLengthArray(element_type, _) => self.slice_member_signature(
4201 type_that_member_is_on,
4202 Some(&int_type),
4203 element_type,
4204 field_name_str,
4205 lambda_variables_count,
4206 node,
4207 ),
4208 _ => {
4209 self.add_err(
4210 ErrorKind::UnknownMemberFunction(type_that_member_is_on.clone()),
4211 node,
4212 );
4213
4214 None
4215 }
4216 }
4217 }
4218
4219 fn analyze_member_call(
4220 &mut self,
4221 type_that_member_is_on: &TypeRef,
4222 field_name_str: &str,
4223 ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4224 ast_arguments: &[swamp_ast::Expression],
4225 chain_self_is_mutable: bool,
4226 node: &swamp_ast::Node,
4227 ) -> (PostfixKind, TypeRef) {
4228 let generic_arguments = if let Some(ast_generic_arguments) = ast_maybe_generic_arguments {
4229 let mut resolved_types = Vec::new();
4230 for ast_type in ast_generic_arguments {
4231 resolved_types.push(self.analyze_type(ast_type.get_type()));
4232 }
4233 resolved_types
4234 } else {
4235 vec![]
4236 };
4237
4238 let maybe_function = self
4239 .shared
4240 .state
4241 .associated_impls
4242 .get_member_function(type_that_member_is_on, field_name_str)
4243 .cloned();
4244
4245 let (function_ref, instantiated_signature) = if let Some(found_function) = maybe_function {
4246 let signature = self.analyze_normal_member_call(
4247 type_that_member_is_on,
4248 &found_function,
4249 generic_arguments,
4250 ast_arguments,
4251 chain_self_is_mutable,
4252 node,
4253 );
4254 (found_function, signature)
4255 } else {
4256 let lambda_variables_count = if ast_arguments.is_empty() {
4257 0
4258 } else if let swamp_ast::ExpressionKind::Lambda(variables, ..) = &ast_arguments[0].kind
4259 {
4260 variables.len()
4261 } else {
4262 0
4263 };
4264 let Some((intrinsic_fn, signature)) = self.check_intrinsic_member_signature(
4265 type_that_member_is_on,
4266 field_name_str,
4267 lambda_variables_count,
4268 node,
4269 ) else {
4270 return (PostfixKind::OptionalChainingOperator, self.types().unit());
4271 };
4272 let def = IntrinsicFunctionDefinition {
4273 name: field_name_str.to_string(),
4274 signature,
4275 intrinsic: intrinsic_fn,
4276 };
4277 let function_ref = FunctionRef::from(Function::Intrinsic(
4278 IntrinsicFunctionDefinitionRef::from(def.clone()),
4279 ));
4280 (function_ref, def.signature)
4281 };
4282
4283 let self_type_in_signature = &instantiated_signature.parameters[0];
4284
4285 if self_type_in_signature.is_mutable && !chain_self_is_mutable {
4286 self.add_err(ErrorKind::SelfNotCorrectMutableState, node);
4287 }
4288
4289 let resolved_arguments = self.analyze_and_verify_parameters(
4290 node,
4291 &instantiated_signature.parameters[1..],
4292 ast_arguments,
4293 );
4294
4295 (
4296 PostfixKind::MemberCall(function_ref, resolved_arguments),
4297 TypeRef::from(instantiated_signature.return_type.clone()),
4298 )
4299 }
4300
4301 fn analyze_postfix_member_call(
4302 &mut self,
4303 type_that_member_is_on: &TypeRef,
4304 is_mutable: bool,
4305 member_name: &swamp_ast::Node,
4306 ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4307 ast_arguments: &[swamp_ast::Expression],
4308 suffixes: &mut Vec<Postfix>,
4309 ) -> TypeRef {
4310 let field_name_str = self.get_text(member_name).to_string();
4311
4312 let resolved_node = self.to_node(member_name);
4313
4314 let (kind, return_type) = self.analyze_member_call(
4315 type_that_member_is_on,
4316 &field_name_str,
4317 ast_maybe_generic_arguments,
4318 ast_arguments,
4319 is_mutable,
4320 member_name,
4321 );
4322 let postfix = Postfix {
4323 node: resolved_node,
4324 ty: return_type,
4325 kind,
4326 };
4327
4328 let last_type = postfix.ty.clone();
4329 suffixes.push(postfix);
4330
4331 last_type
4332 }
4333
4334 fn is_compatible_initializer_list_target(
4335 &mut self,
4336 target_type: &TypeRef,
4337 initializer_element_type: &TypeRef,
4338 ) -> bool {
4339 match &*target_type.kind {
4340 TypeKind::VecStorage(vec_element_type, _vec_capacity) => self
4341 .types()
4342 .compatible_with(vec_element_type, initializer_element_type),
4343 TypeKind::FixedCapacityAndLengthArray(array_element_type, _array_capacity) => self
4344 .types()
4345 .compatible_with(array_element_type, initializer_element_type),
4346 _ => false,
4347 }
4348 }
4349
4350 fn is_compatible_initializer_pair_list_target(
4351 &mut self,
4352 target_type: &TypeRef,
4353 initializer_key_type: &TypeRef,
4354 initializer_value_type: &TypeRef,
4355 ) -> bool {
4356 match &*target_type.kind {
4357 TypeKind::MapStorage(storage_key, storage_value, _) => {
4358 self.types()
4359 .compatible_with(initializer_key_type, storage_key)
4360 && self
4361 .types()
4362 .compatible_with(initializer_value_type, storage_value)
4363 }
4364 _ => false,
4365 }
4366 }
4367
4368 fn types_did_not_match_try_late_coerce_expression(
4369 &mut self,
4370 expr: Expression,
4371 special_expected_type: &TypeRef,
4372 special_encountered_type: &TypeRef,
4373 node: &swamp_ast::Node,
4374 ) -> Expression {
4375 let expected_type = special_expected_type;
4376 let encountered_type = special_encountered_type;
4377 let encountered_is_optional = matches!(&*encountered_type.kind, TypeKind::Optional(_));
4378 if let TypeKind::Optional(expected_inner_type) = &*expected_type.kind {
4379 let inner_is_also_optional =
4380 matches!(&*expected_inner_type.kind, TypeKind::Optional(_));
4381 assert!(!inner_is_also_optional);
4384
4385 if !encountered_is_optional {
4388 if self
4390 .types()
4391 .compatible_with(expected_inner_type, encountered_type)
4392 {
4393 let wrapped = self.create_expr(
4395 ExpressionKind::Option(Option::from(Box::new(expr))),
4396 expected_type.clone(),
4397 node,
4398 );
4399 return wrapped;
4400 }
4401 }
4402 }
4403
4404 if matches!(&*expected_type.kind, &TypeKind::Bool) {
4405 if encountered_is_optional {
4407 let bool_type = self.types().bool();
4408 let wrapped = self.create_expr(
4409 ExpressionKind::CoerceOptionToBool(Box::from(expr)),
4410 bool_type,
4411 node,
4412 );
4413 return wrapped;
4414 }
4415 }
4416
4417 if matches!(
4418 (&*expected_type.kind, &*encountered_type.kind),
4419 (TypeKind::Codepoint, TypeKind::Int)
4420 ) {
4421 let coerced = self.create_expr(
4422 ExpressionKind::CoerceIntToChar(Box::new(expr)),
4423 expected_type.clone(),
4424 node,
4425 );
4426 return coerced;
4427 }
4428
4429 error!(?expected_type, ?encountered_type, "incompatible");
4430 self.create_err(
4431 ErrorKind::IncompatibleTypes {
4432 expected: expected_type.clone(),
4433 found: encountered_type.clone(),
4434 },
4435 node,
4436 )
4437 }
4438
4439 #[must_use]
4440 pub fn analyze_generic_parameter_usize(&self, generic_parameter: &GenericParameter) -> usize {
4441 let usize_node = generic_parameter.get_unsigned_int_node();
4442 let usize_str = self.get_text(usize_node);
4443 Self::str_to_unsigned_int(usize_str).unwrap() as usize
4444 }
4445
4446 #[must_use]
4447 pub fn analyze_generic_parameter_usize_tuple(
4448 &self,
4449 generic_parameter: &GenericParameter,
4450 ) -> (usize, usize) {
4451 let (first, second) = generic_parameter.get_unsigned_int_tuple_nodes();
4452 let first_str = self.get_text(first);
4453 let second_str = self.get_text(second);
4454 let first_value = Self::str_to_unsigned_int(first_str).unwrap() as usize;
4455 let second_value = Self::str_to_unsigned_int(second_str).unwrap() as usize;
4456
4457 (first_value, second_value)
4458 }
4459
4460 pub fn analyze_special_named_type(
4461 &mut self,
4462 path: &[String],
4463 name: &str,
4464 ast_generic_parameters: &[GenericParameter],
4465 ) -> Option<TypeRef> {
4466 let converted_type = match name {
4467 "String" => {
4468 if ast_generic_parameters.len() == 1 {
4469 let fixed_size =
4470 self.analyze_generic_parameter_usize(&ast_generic_parameters[0]);
4471 let new_type = self.shared.state.types.string_storage(fixed_size);
4472 let default_node = swamp_ast::Node::default();
4473 self.add_default_functions(&new_type, &default_node);
4474 new_type
4475 } else {
4476 return None;
4477 }
4478 }
4479 "Vec" => {
4480 if ast_generic_parameters.len() == 1 {
4481 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4482 let vec_type = self.shared.state.types.dynamic_vec_view(&element_type);
4483 let default_node = swamp_ast::Node::default();
4485 self.add_default_functions(&vec_type, &default_node);
4486 vec_type
4487 } else if ast_generic_parameters.len() == 2 {
4488 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4489 let fixed_size =
4490 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4491 let vec_storage_type = self
4492 .shared
4493 .state
4494 .types
4495 .vec_storage(&element_type, fixed_size);
4496 let default_node = swamp_ast::Node::default();
4498 self.add_default_functions(&vec_storage_type, &default_node);
4499 vec_storage_type
4500 } else {
4501 panic!("todo: make this into an error")
4502 }
4503 }
4504 "Stack" => {
4505 if ast_generic_parameters.len() == 1 {
4506 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4507 let stack_view_type = self.shared.state.types.stack_view(&element_type);
4508 let default_node = swamp_ast::Node::default();
4510 self.add_default_functions(&stack_view_type, &default_node);
4511 stack_view_type
4512 } else if ast_generic_parameters.len() == 2 {
4513 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4514 let fixed_size =
4515 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4516 let stack_storage_type = self
4517 .shared
4518 .state
4519 .types
4520 .stack_storage(&element_type, fixed_size);
4521 let default_node = swamp_ast::Node::default();
4523 self.add_default_functions(&stack_storage_type, &default_node);
4524 stack_storage_type
4525 } else {
4526 panic!("todo: make this into an error")
4527 }
4528 }
4529 "Queue" => {
4530 if ast_generic_parameters.len() == 1 {
4531 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4532 let queue_view_type = self.shared.state.types.queue_view(&element_type);
4533 let default_node = swamp_ast::Node::default();
4535 self.add_default_functions(&queue_view_type, &default_node);
4536 queue_view_type
4537 } else if ast_generic_parameters.len() == 2 {
4538 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4539 let fixed_size =
4540 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4541 let queue_storage_type = self
4542 .shared
4543 .state
4544 .types
4545 .queue_storage(&element_type, fixed_size);
4546 let default_node = swamp_ast::Node::default();
4548 self.add_default_functions(&queue_storage_type, &default_node);
4549 queue_storage_type
4550 } else {
4551 panic!("todo: make this into an error")
4552 }
4553 }
4554 "Sparse" => {
4555 if ast_generic_parameters.len() == 1 {
4556 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4557 let sparse_view_type = self.shared.state.types.sparse_view(&element_type);
4558 let default_node = swamp_ast::Node::default();
4560 self.add_default_functions(&sparse_view_type, &default_node);
4561 sparse_view_type
4562 } else if ast_generic_parameters.len() == 2 {
4563 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4564 let fixed_size =
4565 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4566 let sparse_storage_type = self
4567 .shared
4568 .state
4569 .types
4570 .sparse_storage(&element_type, fixed_size);
4571 let default_node = swamp_ast::Node::default();
4573 self.add_default_functions(&sparse_storage_type, &default_node);
4574 sparse_storage_type
4575 } else {
4576 panic!("todo: make this into an error")
4577 }
4578 }
4579
4580 "Grid" => {
4581 if ast_generic_parameters.len() == 1 {
4582 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4583 let grid_view_type = self.shared.state.types.grid_view(&element_type);
4584 let default_node = swamp_ast::Node::default();
4586 self.add_default_functions(&grid_view_type, &default_node);
4587 grid_view_type
4588 } else if ast_generic_parameters.len() == 2 {
4589 let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4590 let (width, height) =
4591 self.analyze_generic_parameter_usize_tuple(&ast_generic_parameters[1]);
4592 let grid_storage_type =
4593 self.shared
4594 .state
4595 .types
4596 .grid_storage(&element_type, width, height);
4597 let default_node = swamp_ast::Node::default();
4599 self.add_default_functions(&grid_storage_type, &default_node);
4600 grid_storage_type
4601 } else {
4602 panic!("todo: make this into an error")
4603 }
4604 }
4605
4606 _ => return None,
4607 };
4608
4609 Some(converted_type)
4610 }
4611
4612 fn special_static_member(
4613 &self,
4614 type_identifier: &QualifiedTypeIdentifier,
4615 member_name_node: &swamp_ast::Node,
4616 ) -> Option<Function> {
4617 if type_identifier.generic_params.is_empty() {
4618 return None;
4619 }
4620
4621 if type_identifier.module_path.is_some() {
4622 return None;
4623 }
4624
4625 let member_name = self.get_text(member_name_node);
4626 let name = self.get_text(&type_identifier.name.0);
4627
4628 match name {
4629 "Stack" => None,
4630 _ => None,
4631 }
4632 }
4633}