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