1pub mod access;
6mod attributes;
7pub mod call;
8pub mod constant;
9pub mod context;
10pub mod def;
11pub mod literal;
12pub mod operator;
13pub mod pattern;
14pub mod prelude;
15pub mod shared;
16mod structure;
17mod to_string;
18pub mod types;
19pub mod variable;
20
21use crate::call::MaybeBorrowMutRefExpression;
22use crate::context::TypeContext;
23use crate::shared::SharedState;
24use crate::to_string::create_expr_resolved;
25use crate::types::TypeAnalyzeContext;
26use crate::variable::{VariableSlot, MAX_VIRTUAL_REGISTER};
27use seq_map::SeqMap;
28use source_map_cache::SourceMap;
29use source_map_node::{FileId, Node, Span};
30use std::mem::take;
31use std::num::{ParseFloatError, ParseIntError};
32use std::rc::Rc;
33use std::str::{FromStr, ParseBoolError};
34use swamp_ast::{GenericParameter, QualifiedTypeIdentifier};
35use swamp_modules::prelude::*;
36use swamp_modules::symtbl::SymbolTableRef;
37use swamp_semantic::prelude::*;
38use swamp_semantic::{
39 ArgumentExpression, BinaryOperatorKind, BlockScope, BlockScopeMode, FunctionScopeState,
40 GridType, InternalMainExpression, LocationAccess, LocationAccessKind, MapType,
41 MutableReferenceKind, NormalPattern, Postfix, PostfixKind, ScopeInfo, SingleLocationExpression,
42 SliceViewType, SparseType, TargetAssignmentLocation, TypeWithMut, VariableType, VecType,
43 WhenBinding,
44};
45use swamp_semantic::{StartOfChain, StartOfChainKind};
46use swamp_symbol::{ScopedSymbolId, TopLevelSymbolId};
47use swamp_types::prelude::*;
48use swamp_types::{Type, TypeKind};
49use tracing::error;
50pub enum VariableResolution {
82 ExistingVariable(VariableRef),
83 ReservedSlot(VariableSlot, swamp_ast::Variable, Option<TypeRef>),
84}
85
86#[derive(Debug)]
87pub enum ParseByteError {
88 InvalidFormat,
90 InvalidEscape,
92}
93
94#[derive(Copy, Clone, Eq, PartialEq)]
95pub enum AssignmentMode {
96 OwnedValue,
97 CopyBlittable,
98 CopySharedPtr,
99}
100
101#[derive(Copy, Clone, Eq, PartialEq, Debug)]
102pub enum LocationSide {
103 Lhs,
104 Mutable,
105 Rhs,
106}
107
108#[derive(Debug)]
109pub enum StartOfChainBase {
110 FunctionReference(Function),
111 Variable(VariableRef),
112}
113#[derive(Debug)]
114pub struct Program {
115 pub state: ProgramState,
116 pub modules: Modules,
117 pub default_symbol_table: DefinitionTable,
118}
119
120impl Default for Program {
121 fn default() -> Self {
122 Self::new(
123 ProgramState::new(),
124 Modules::new(),
125 DefinitionTable::new(&[]),
126 )
127 }
128}
129
130impl Program {
131 #[must_use]
132 pub const fn new(
133 state: ProgramState,
134 modules: Modules,
135 default_symbol_table: DefinitionTable,
136 ) -> Self {
137 Self {
138 state,
139 modules,
140 default_symbol_table,
141 }
142 }
143}
144
145#[must_use]
146pub const fn convert_span(without: &swamp_ast::SpanWithoutFileId, file_id: FileId) -> Span {
147 Span {
148 file_id,
149 offset: without.offset,
150 length: without.length,
151 }
152}
153
154pub struct Analyzer<'a> {
155 pub shared: SharedState<'a>,
156 scope: ScopeInfo,
157 global: FunctionScopeState,
158 module_path: Vec<String>,
159 last_function_node: Node,
160}
161
162#[derive(Copy, Clone)]
163pub struct AnalyzerOptions {
164 pub allow_unsafe: bool,
165}
166
167impl<'a> Analyzer<'a> {
168 pub fn new(
169 state: &'a mut ProgramState,
170 modules: &'a Modules,
171 core_symbol_table: SymbolTableRef,
172 source_map: &'a SourceMap,
173 module_path: &[String],
174 file_id: FileId,
175 options: AnalyzerOptions,
176 ) -> Self {
177 let shared = SharedState {
178 state,
179 lookup_table: DefinitionTable::new(&[]),
180 definition_table: DefinitionTable::new(module_path),
181 modules,
182 core_symbol_table,
183 source_map,
184 file_id,
185 allow_unsafe: options.allow_unsafe,
186 };
187
188 let mut analyzer = Self {
189 scope: ScopeInfo::default(),
190 global: FunctionScopeState::new(),
191 shared,
192 module_path: module_path.to_vec(),
193 last_function_node: Default::default(),
194 };
195
196 let unit_type = analyzer.shared.state.types.unit();
198 analyzer.add_default_functions(&unit_type, &swamp_ast::Node::default());
199
200 analyzer
201 }
202
203 fn start_function(&mut self, node: &swamp_ast::Node) {
205 self.global.block_scope_stack = take(&mut self.scope.active_scope.block_scope_stack);
206 self.last_function_node = self.to_node(node);
207 self.scope = ScopeInfo::default();
208 }
209
210 fn stop_function(&mut self) {
211 self.scope.active_scope.block_scope_stack = take(&mut self.global.block_scope_stack);
212 if self.scope.total_scopes.highest_virtual_register > MAX_VIRTUAL_REGISTER / 2 {
213 self.add_hint_resolved(
214 ErrorKind::CloseToMaxVirtualRegister,
215 &self.last_function_node.clone(),
216 );
217 }
218 }
219
220 fn analyze_if_expression(
221 &mut self,
222 condition: &swamp_ast::Expression,
223 true_expression: &swamp_ast::Expression,
224 maybe_false_expression: Option<&swamp_ast::Expression>,
225 context: &TypeContext,
226 ) -> Expression {
227 let resolved_condition = self.analyze_bool_argument_expression(condition);
228
229 let branch_context = context;
230
231 let true_expr = self.analyze_expression(true_expression, branch_context);
232
233 let resolved_true = Box::new(true_expr);
234
235 let mut detected = context.expected_type.cloned();
236 if detected.is_none() {
237 detected = Some(resolved_true.ty.clone());
238 }
239
240 let else_statements = if let Some(false_expression) = maybe_false_expression {
242 let else_context =
243 branch_context.with_expected_type(detected.as_ref(), context.has_lvalue_target);
244
245 let else_expr = self.analyze_expression(false_expression, &else_context);
246
247 if detected.is_none() {
248 detected = Some(else_expr.ty.clone());
249 }
250
251 Some(Box::new(else_expr))
252 } else {
253 None
254 };
255
256 self.create_expr(
257 ExpressionKind::If(resolved_condition, resolved_true, else_statements),
258 detected.unwrap(),
259 &condition.node,
260 )
261 }
262
263 fn get_text(&self, ast_node: &swamp_ast::Node) -> &str {
264 let span = Span {
265 file_id: self.shared.file_id,
266 offset: ast_node.span.offset,
267 length: ast_node.span.length,
268 };
269 self.shared.source_map.get_span_source(
270 self.shared.file_id,
271 span.offset as usize,
272 span.length as usize,
273 )
274 }
275
276 fn get_text_resolved(&self, resolved_node: &Node) -> &str {
277 let span = Span {
278 file_id: self.shared.file_id,
279 offset: resolved_node.span.offset,
280 length: resolved_node.span.length,
281 };
282 self.shared.source_map.get_span_source(
283 self.shared.file_id,
284 span.offset as usize,
285 span.length as usize,
286 )
287 }
288
289 fn get_path(&self, ident: &swamp_ast::QualifiedTypeIdentifier) -> (Vec<String>, String) {
290 let path = ident
291 .module_path
292 .as_ref()
293 .map_or_else(Vec::new, |found_path| {
294 let mut v = Vec::new();
295 for p in &found_path.0 {
296 v.push(self.get_text(p).to_string());
297 }
298 v
299 });
300 (path, self.get_text(&ident.name.0).to_string())
301 }
302
303 fn analyze_return_type(&mut self, function: &swamp_ast::Function) -> TypeRef {
304 let ast_return_type = match function {
305 swamp_ast::Function::Internal(x) => &x.declaration.return_type,
306 swamp_ast::Function::External(_, x) => &x.return_type,
307 };
308
309 match ast_return_type {
310 None => self.shared.state.types.unit(),
311 Some(x) => self.analyze_type(x, &TypeAnalyzeContext::default()),
312 }
313 }
314
315 fn analyze_function_body_expression(
316 &mut self,
317 expression: &swamp_ast::Expression,
318 return_type: &TypeRef,
319 ) -> Expression {
320 let context = TypeContext::new_function(return_type);
321
322 self.analyze_expression(expression, &context)
323 }
324
325 fn analyze_maybe_type(&mut self, maybe_type: Option<&swamp_ast::Type>) -> TypeRef {
326 match maybe_type {
327 None => self.shared.state.types.unit(),
328 Some(ast_type) => self.analyze_type(ast_type, &TypeAnalyzeContext::default()),
329 }
330 }
331
332 fn analyze_for_pattern(
333 &mut self,
334 pattern: &swamp_ast::ForPattern,
335 key_type: Option<&TypeRef>,
336 value_type: &TypeRef,
337 ) -> ForPattern {
338 match pattern {
339 swamp_ast::ForPattern::Single(var) => {
340 let variable_ref = self.create_local_variable(
341 &var.identifier,
342 Option::from(&var.is_mut),
343 value_type,
344 false,
345 );
346 ForPattern::Single(variable_ref)
347 }
348 swamp_ast::ForPattern::Pair(first, second) => {
349 let found_key = key_type.unwrap();
350 let first_var_ref = self.create_local_variable(
351 &first.identifier,
352 Option::from(&first.is_mut),
353 found_key,
354 false,
355 );
356 let second_var_ref = self.create_local_variable(
357 &second.identifier,
358 Option::from(&second.is_mut),
359 value_type,
360 false,
361 );
362 ForPattern::Pair(first_var_ref, second_var_ref)
363 }
364 }
365 }
366 const MAX_PARAMETER_COUNT: usize = 6; fn analyze_parameters(
368 &mut self,
369 parameters: &Vec<swamp_ast::Parameter>,
370 ) -> Vec<TypeForParameter> {
371 let mut resolved_parameters = Vec::new();
372 if parameters.len() > Self::MAX_PARAMETER_COUNT {
373 self.add_err(
374 ErrorKind::TooManyParameters {
375 encountered: parameters.len(),
376 allowed: Self::MAX_PARAMETER_COUNT,
377 },
378 ¶meters[0].variable.name,
379 );
380 return vec![];
381 }
382
383 let allow_ephemeral = TypeAnalyzeContext::new_parameter_context();
384 for parameter in parameters {
385 let param_type = self.analyze_type(¶meter.param_type, &allow_ephemeral);
386 if !param_type.allowed_as_parameter_type() {
387 self.add_err(
388 ErrorKind::ParameterTypeCanNotBeStorage(param_type),
389 ¶meter.variable.name,
390 );
391 continue;
392 }
393 resolved_parameters.push(TypeForParameter {
394 name: self.get_text(¶meter.variable.name).to_string(),
395 resolved_type: param_type,
396 is_mutable: parameter.variable.is_mutable.is_some(),
397 node: Some(ParameterNode {
398 is_mutable: self.to_node_option(Option::from(¶meter.variable.is_mutable)),
399 name: self.to_node(¶meter.variable.name),
400 }),
401 });
402 }
403 resolved_parameters
404 }
405
406 pub(crate) fn analyze_static_member_access(
407 &mut self,
408 named_type: &swamp_ast::QualifiedTypeIdentifier,
409 member_name_node: &swamp_ast::Node,
410 ) -> Option<Function> {
411 if let Some(found_function) = self.special_static_member(named_type, member_name_node) {
412 Some(found_function)
413 } else {
414 let some_type = self.analyze_named_type(named_type);
415
416 let member_name = self.get_text(member_name_node);
417 self.lookup_associated_function(&some_type, member_name)
418 }
419 }
420
421 pub fn analyze_local_function_access(
422 &mut self,
423 qualified_func_name: &swamp_ast::QualifiedIdentifier,
424 ) -> Option<Function> {
425 let path = self.get_module_path(qualified_func_name.module_path.as_ref());
426 let function_name = self.get_text(&qualified_func_name.name);
427
428 if let Some(found_table) = self.shared.get_definition_table(&path)
429 && let Some(found_func) = found_table.get_function(function_name).cloned()
430 {
431 {
432 let converted_node = self.to_node(&qualified_func_name.name);
433 let symbol_id: TopLevelSymbolId = found_func.symbol_id();
434 let refs = &mut self.shared.state.refs;
435 refs.add(symbol_id.into(), converted_node.clone());
436 self.shared
437 .definition_table
438 .refs
439 .add(symbol_id.into(), converted_node);
440 }
441 let (kind, signature) = match found_func {
442 FuncDef::Internal(internal_fn) => (
443 Function::Internal(internal_fn.clone()),
444 &internal_fn.signature.clone(),
445 ),
446 FuncDef::External(external_fn) => (
447 Function::External(external_fn.clone()),
448 &external_fn.signature.clone(),
449 ),
450 FuncDef::Intrinsic(intrinsic_fn) => (
452 Function::Intrinsic(intrinsic_fn.clone()),
453 &intrinsic_fn.signature.clone(),
454 ),
455 };
456
457 return Some(kind);
458 }
459
460 None
461 }
462
463 fn check_if_function_reference(
464 &mut self,
465 ast_expression: &swamp_ast::Expression,
466 ) -> Option<Function> {
467 match &ast_expression.kind {
468 swamp_ast::ExpressionKind::StaticMemberFunctionReference(
469 qualified_type_identifier,
470 node,
471 ) => self.analyze_static_member_access(qualified_type_identifier, node),
472 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
473 self.analyze_local_function_access(qualified_identifier)
474 }
475 _ => None,
476 }
477 }
478
479 pub fn analyze_start_chain_expression_get_mutability(
482 &mut self,
483 ast_expression: &swamp_ast::Expression,
484 ) -> Option<StartOfChainBase> {
485 self.check_if_function_reference(ast_expression)
486 .map_or_else(
487 || {
488 if let swamp_ast::ExpressionKind::IdentifierReference(
489 found_qualified_identifier,
490 ) = &ast_expression.kind
491 {
492 if let Some(found_var) =
493 self.try_find_variable(&found_qualified_identifier.name)
494 {
495 let name_node = self.to_node(&found_qualified_identifier.name);
496 self.shared
497 .state
498 .refs
499 .add(found_var.symbol_id.into(), name_node.clone());
500 self.shared
501 .definition_table
502 .refs
503 .add(found_var.symbol_id.into(), name_node);
504 Some(StartOfChainBase::Variable(found_var))
505 } else {
506 None
507 }
508 } else {
509 None
510 }
511 },
512 |found_func_def| Some(StartOfChainBase::FunctionReference(found_func_def)),
513 )
514 }
515
516 pub fn debug_expression(&self, expr: &swamp_ast::Expression, description: &str) {
517 self.debug_line(expr.node.span.offset as usize, description);
518 }
519
520 pub fn debug_line(&self, offset: usize, description: &str) {
521 let (line, col) = self
522 .shared
523 .source_map
524 .get_span_location_utf8(self.shared.file_id, offset);
525
526 let source_line = self
527 .shared
528 .source_map
529 .get_source_line(self.shared.file_id, line);
530
531 let source_path = self
532 .shared
533 .source_map
534 .fetch_relative_filename(self.shared.file_id);
535 let debug_line = format!("{source_path}:{line}:{col}> {}", source_line.unwrap());
536 }
539
540 pub fn analyze_main_expression(
543 &mut self,
544 ast_expression: &swamp_ast::Expression,
545 ) -> InternalMainExpression {
546 self.start_function(&ast_expression.node);
547
548 let context = TypeContext::new_anything_argument(true); let analyzed_expr = self.analyze_expression(ast_expression, &context);
550 let main_expr = InternalMainExpression {
551 expression: analyzed_expr,
552 scopes: self.scope.total_scopes.clone(),
553 program_unique_id: self.shared.state.allocate_internal_function_id(),
554 };
555
556 self.stop_function();
557
558 main_expr
559 }
560
561 fn analyze_maybe_ref_expression(
562 &mut self,
563 ast_expr: &swamp_ast::Expression,
564 ) -> MaybeBorrowMutRefExpression {
565 if let swamp_ast::ExpressionKind::UnaryOp(found_unary, ast_inner_expression) =
566 &ast_expr.kind
567 && let swamp_ast::UnaryOperator::BorrowMutRef(node) = found_unary
568 {
569 let resolved_node = self.to_node(node);
571 return MaybeBorrowMutRefExpression {
572 ast_expression: *ast_inner_expression.clone(),
573 has_borrow_mutable_reference: Some(resolved_node),
574 };
575 }
576
577 MaybeBorrowMutRefExpression {
578 ast_expression: ast_expr.clone(),
579 has_borrow_mutable_reference: None,
580 }
581 }
582
583 fn needs_storage_error(
585 &self,
586 expr: &Expression,
587 is_function_call: bool,
588 context: &TypeContext,
589 ast_node: &swamp_ast::Node,
590 ) -> bool {
591 let is_constant = matches!(expr.kind, ExpressionKind::ConstantAccess(_));
592 let is_variable = matches!(expr.kind, ExpressionKind::VariableAccess(_));
593
594 !context.has_lvalue_target
596 && expr.ty.collection_view_that_needs_explicit_storage()
597 && is_function_call
598 && !is_constant
599 && !is_variable
600 }
601
602 pub fn analyze_expression(
603 &mut self,
604 ast_expression: &swamp_ast::Expression,
605 context: &TypeContext,
606 ) -> Expression {
607 let expr = self.analyze_expression_internal(ast_expression, context);
610
611 if matches!(expr.kind, ExpressionKind::Error(_)) {
612 return expr;
613 }
614
615 let encountered_type = expr.ty.clone();
616
617 let expr = if let Some(found_expected_type) = context.expected_type {
619 let reduced_expected = found_expected_type;
620 let reduced_encountered_type = encountered_type;
621
622 if matches!(
623 (&*reduced_expected.kind, &*reduced_encountered_type.kind),
624 (TypeKind::StringView(_, _), TypeKind::StringStorage(..))
625 ) {
626 let string_type = self.shared.state.types.string();
631 return self.create_expr(
632 ExpressionKind::IntrinsicCallEx(
633 IntrinsicFunction::StringDuplicate,
634 vec![ArgumentExpression::Expression(expr)],
635 ),
636 string_type,
637 &ast_expression.node,
638 );
639 }
640
641 if matches!(
642 (&*reduced_expected.kind, &*reduced_encountered_type.kind),
643 (
644 TypeKind::StringView(_, _),
645 TypeKind::VecStorage(..) | TypeKind::DynamicLengthVecView(..)
646 )
647 ) {
648 let string_type = self.shared.state.types.string();
652 return self.create_expr(
653 ExpressionKind::IntrinsicCallEx(
654 IntrinsicFunction::ByteVectorToString,
655 vec![ArgumentExpression::Expression(expr)],
656 ),
657 string_type,
658 &ast_expression.node,
659 );
660 }
661
662 if matches!(
663 (&*reduced_expected.kind, &*reduced_encountered_type.kind),
664 (
665 TypeKind::StringStorage(..),
666 TypeKind::VecStorage(..) | TypeKind::DynamicLengthVecView(..)
667 )
668 ) {
669 let string_type = self.shared.state.types.string();
673 return self.create_expr(
674 ExpressionKind::IntrinsicCallEx(
675 IntrinsicFunction::ByteVectorToStringStorage,
676 vec![ArgumentExpression::Expression(expr)],
677 ),
678 string_type,
679 &ast_expression.node,
680 );
681 }
682
683 if matches!(
684 (&*reduced_expected.kind, &*reduced_encountered_type.kind),
685 (TypeKind::StringStorage(..), TypeKind::StringView(..))
686 ) {
687 let string_type = self.shared.state.types.string();
691 return self.create_expr(
692 ExpressionKind::IntrinsicCallEx(
693 IntrinsicFunction::VecCopy,
694 vec![ArgumentExpression::Expression(expr)],
695 ),
696 string_type,
697 &ast_expression.node,
698 );
699 }
700
701 if self
704 .shared
705 .state
706 .types
707 .compatible_with(reduced_expected, &reduced_encountered_type)
708 {
709 expr
710 } else {
711 self.types_did_not_match_try_late_coerce_expression(
712 expr,
713 reduced_expected,
714 &reduced_encountered_type,
715 &ast_expression.node,
716 )
717 }
718 } else {
719 expr
720 };
723
724 let is_function_call = Self::is_aggregate_function_call(ast_expression);
727
728 if self.needs_storage_error(&expr, is_function_call, context, &ast_expression.node) {
729 self.create_err(ErrorKind::NeedStorage, &ast_expression.node)
731 } else {
732 expr
733 }
734 }
735
736 #[allow(clippy::too_many_lines)]
739 pub fn analyze_expression_internal(
740 &mut self,
741 ast_expression: &swamp_ast::Expression,
742 context: &TypeContext,
743 ) -> Expression {
744 match &ast_expression.kind {
747 swamp_ast::ExpressionKind::PostfixChain(postfix_chain) => {
749 self.analyze_postfix_chain(postfix_chain, context)
750 }
751
752 swamp_ast::ExpressionKind::VariableDefinition(
753 variable,
754 maybe_annotation,
755 source_expression,
756 ) => self.analyze_variable_definition(variable, maybe_annotation, source_expression),
757
758 swamp_ast::ExpressionKind::VariableAssignment(variable, source_expression) => {
759 self.analyze_variable_assignment(variable, source_expression)
760 }
761
762 swamp_ast::ExpressionKind::Assignment(location, source) => {
763 self.analyze_assignment(location, source)
764 }
765
766 swamp_ast::ExpressionKind::DestructuringAssignment(variables, expression) => {
767 self.analyze_destructuring(&ast_expression.node, variables, expression)
768 }
769
770 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
771 self.analyze_identifier(qualified_identifier)
772 }
773
774 swamp_ast::ExpressionKind::VariableReference(variable) => {
775 self.analyze_variable_reference(&variable.name)
776 }
777
778 swamp_ast::ExpressionKind::ContextAccess => {
779 todo!("context access is not done yet")
780 }
781
782 swamp_ast::ExpressionKind::StaticMemberFunctionReference(
783 type_identifier,
784 member_name,
785 ) => {
786 let debug_name = self.get_text(member_name);
787 let type_name = self.get_text(&type_identifier.name.0);
788 self.create_err(ErrorKind::CanNotHaveSeparateMemberFuncRef, member_name)
789 }
790
791 swamp_ast::ExpressionKind::ConstantReference(constant_identifier) => {
792 self.analyze_constant_access(constant_identifier)
793 }
794
795 swamp_ast::ExpressionKind::CompoundAssignment(target, op, source) => {
796 self.analyze_assignment_compound(target, op, source)
797 }
798
799 swamp_ast::ExpressionKind::BinaryOp(resolved_a, operator, resolved_b) => {
801 let Some((resolved_op, result_type)) =
802 self.analyze_binary_op(resolved_a, operator, resolved_b)
803 else {
804 return self.create_err(ErrorKind::OperatorProblem, &operator.node);
805 };
806
807 self.create_expr(
808 ExpressionKind::BinaryOp(resolved_op),
809 result_type,
810 &ast_expression.node,
811 )
812 }
813
814 swamp_ast::ExpressionKind::UnaryOp(operator, expression) => {
815 if let swamp_ast::UnaryOperator::BorrowMutRef(_node) = operator {
816 let inner_expr =
817 self.analyze_to_location(expression, context, LocationSide::Rhs);
818 let ty = inner_expr.ty.clone();
819 if matches!(&*ty.kind, TypeKind::StringView(..)) {
820 return self.create_err(ErrorKind::CanNotBeBorrowed, &expression.node);
821 }
822 self.create_expr(
823 ExpressionKind::BorrowMutRef(Box::from(inner_expr)),
824 ty,
825 &ast_expression.node,
826 )
827 } else {
828 let Some((resolved_op, result_type)) =
829 self.analyze_unary_op(operator, expression)
830 else {
831 return self.create_err(ErrorKind::OperatorProblem, &ast_expression.node);
832 };
833 self.create_expr(
834 ExpressionKind::UnaryOp(resolved_op),
835 result_type,
836 &ast_expression.node,
837 )
838 }
839 }
840
841 swamp_ast::ExpressionKind::Block(expressions) => {
842 let (block, resulting_type) =
843 self.analyze_block(&ast_expression.node, context, expressions);
844 self.create_expr(
845 ExpressionKind::Block(block),
846 resulting_type,
847 &ast_expression.node,
848 )
849 }
850
851 swamp_ast::ExpressionKind::With(variable_bindings, expression) => {
852 self.analyze_with_expr(context, variable_bindings, expression)
853 }
854
855 swamp_ast::ExpressionKind::When(variable_bindings, true_expr, else_expr) => {
856 self.analyze_when_expr(context, variable_bindings, true_expr, else_expr.as_deref())
857 }
858
859 swamp_ast::ExpressionKind::InterpolatedString(string_parts) => {
860 self.analyze_interpolated_string_lowering(&ast_expression.node, string_parts)
861 }
862
863 swamp_ast::ExpressionKind::NamedStructLiteral(struct_identifier, fields, has_rest) => {
865 self.analyze_named_struct_literal(struct_identifier, fields, *has_rest, context)
866 }
867
868 swamp_ast::ExpressionKind::AnonymousStructLiteral(fields, rest_was_specified) => self
869 .analyze_anonymous_struct_literal(
870 &ast_expression.node,
871 fields,
872 *rest_was_specified,
873 context,
874 ),
875
876 swamp_ast::ExpressionKind::ContextAccess => {
877 todo!("lone dot not implemented yet")
878 }
879
880 swamp_ast::ExpressionKind::Range(min_value, max_value, range_mode) => {
881 self.analyze_range(min_value, max_value, range_mode, &ast_expression.node)
882 }
883
884 swamp_ast::ExpressionKind::ForLoop(pattern, iterable_expression, single_statement) => {
885 if pattern.is_key_variable_mut() {
886 return self.create_err(
887 ErrorKind::KeyVariableNotAllowedToBeMutable,
888 &ast_expression.node,
889 );
890 }
891 let resolved_iterator =
892 self.analyze_iterable(pattern.is_value_mut(), &iterable_expression.expression);
893
894 self.push_block_scope("for_loop");
895 let pattern = self.analyze_for_pattern(
896 pattern,
897 resolved_iterator.key_type.as_ref(),
898 &resolved_iterator.value_type,
899 );
900 let unit_type = self.types().unit();
901 let for_context = context.with_expected_type(Some(&unit_type), false);
902 let resolved_statement = self.analyze_expression(single_statement, &for_context);
903 assert!(matches!(&*resolved_statement.ty.kind, TypeKind::Unit));
904 self.pop_block_scope("for_loop");
905 let resolved_type = resolved_statement.ty.clone();
906 self.create_expr(
907 ExpressionKind::ForLoop(
908 pattern,
909 resolved_iterator,
910 Box::from(resolved_statement),
911 ),
912 resolved_type,
913 &ast_expression.node,
914 )
915 }
916
917 swamp_ast::ExpressionKind::WhileLoop(expression, statements) => {
918 let condition = self.analyze_bool_argument_expression(expression);
919
920 let unit = self.types().unit();
921 let unit_context = context.with_expected_type(Some(&unit), false);
922 let resolved_statements = self.analyze_expression(statements, &unit_context);
923 let resolved_type = resolved_statements.ty.clone();
924
925 self.create_expr(
926 ExpressionKind::WhileLoop(condition, Box::from(resolved_statements)),
927 resolved_type,
928 &ast_expression.node,
929 )
930 }
931
932 swamp_ast::ExpressionKind::If(expression, true_expression, maybe_false_expression) => {
933 self.analyze_if_expression(
934 expression,
935 true_expression,
936 maybe_false_expression.as_deref(),
937 context,
938 )
939 }
940
941 swamp_ast::ExpressionKind::Match(expression, arms) => {
942 let (match_expr, return_type) = self.analyze_match(expression, context, arms);
943 self.create_expr(
944 ExpressionKind::Match(match_expr),
945 return_type,
946 &ast_expression.node,
947 )
948 }
949 swamp_ast::ExpressionKind::Guard(guard_expressions) => {
950 self.analyze_guard(&ast_expression.node, context, guard_expressions)
951 }
952
953 swamp_ast::ExpressionKind::Lambda(variables, expression) => {
954 self.analyze_lambda(&ast_expression.node, variables, expression, context)
955 }
956 swamp_ast::ExpressionKind::Error => {
957 self.create_err(ErrorKind::UnexpectedType, &ast_expression.node)
958 }
959 swamp_ast::ExpressionKind::Literal(literal) => {
960 self.analyze_complex_literal_to_expression(ast_expression, literal, context)
961 } }
963 }
964
965 fn get_struct_type(
966 &mut self,
967 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
968 ) -> NamedStructType {
969 let maybe_struct_type = self.analyze_named_type(qualified_type_identifier);
970 if let TypeKind::NamedStruct(struct_type) = &*maybe_struct_type.kind {
971 struct_type.clone()
972 } else {
973 self.add_err(
974 ErrorKind::UnknownStructTypeReference,
976 &qualified_type_identifier.name.0,
977 );
978
979 NamedStructType {
980 symbol_id: TopLevelSymbolId::new_illegal(),
981 name: Default::default(),
982 module_path: vec![],
983 assigned_name: String::new(),
984 anon_struct_type: self.types().unit(),
985 }
986 }
987 }
988
989 pub(crate) fn analyze_named_type(
990 &mut self,
991 type_name_to_find: &swamp_ast::QualifiedTypeIdentifier,
992 ) -> TypeRef {
993 let (path, name) = self.get_path(type_name_to_find);
994 let mut analyzed_type_parameters = Vec::new();
995
996 if let Some(found) =
997 self.analyze_special_named_type(&path, &name, &type_name_to_find.generic_params)
998 {
999 return found;
1000 }
1001
1002 for analyzed_type in &type_name_to_find.generic_params {
1003 let ty = self.analyze_type(analyzed_type.get_type(), &TypeAnalyzeContext::default());
1004
1005 analyzed_type_parameters.push(ty);
1006 }
1007
1008 let symbol = {
1009 if let Some(symbol_table) = self.shared.get_definition_table(&path) {
1010 if let Some(x) = symbol_table.get_symbol(&name) {
1011 x.clone()
1012 } else {
1013 self.add_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0);
1014 return self.types().unit();
1015 }
1016 } else {
1017 self.add_err(ErrorKind::UnexpectedType, &type_name_to_find.name.0);
1018 return self.types().unit();
1019 }
1020 };
1021
1022 let sym_node = self.to_node(&type_name_to_find.name.0);
1023 if analyzed_type_parameters.is_empty() {
1024 match &symbol.kind {
1025 ModuleDefinitionKind::Type(symbol_id, base_type) => {
1026 self.shared
1027 .state
1028 .refs
1029 .add((*symbol_id).into(), sym_node.clone());
1030 self.shared
1031 .definition_table
1032 .refs
1033 .add((*symbol_id).into(), sym_node);
1034 base_type.clone()
1035 }
1036 ModuleDefinitionKind::Alias(alias_type) => {
1037 self.shared
1038 .state
1039 .refs
1040 .add(alias_type.symbol_id.into(), sym_node.clone());
1041 self.shared
1042 .definition_table
1043 .refs
1044 .add(alias_type.symbol_id.into(), sym_node);
1045 alias_type.ty.clone()
1046 }
1047 _ => {
1048 self.add_err(ErrorKind::UnexpectedType, &type_name_to_find.name.0);
1049 self.types().unit()
1050 }
1051 }
1052 } else {
1053 panic!("unknown type")
1054 }
1055 }
1056
1057 fn create_default_value_for_type(
1058 &mut self,
1059 node: &swamp_ast::Node,
1060 field_type: &TypeRef,
1061 ) -> Option<Expression> {
1062 let kind = match &*field_type.kind {
1063 TypeKind::Tuple(tuple_type_ref) => {
1064 let mut expressions = Vec::new();
1065 for resolved_type in tuple_type_ref {
1066 let expr = self.create_default_value_for_type(node, resolved_type)?;
1067 expressions.push(expr);
1068 }
1069 ExpressionKind::TupleLiteral(expressions)
1070 }
1071
1072 TypeKind::NamedStruct(_struct_ref) => {
1073 if self
1075 .shared
1076 .state
1077 .associated_impls
1078 .get_member_function(field_type, "default")
1079 .is_some()
1080 {
1081 self.create_default_static_call(node, field_type)
1082 } else {
1083 return None;
1085 }
1086 }
1087
1088 _ => {
1089 return None;
1091 }
1092 };
1093
1094 Some(self.create_expr(kind, field_type.clone(), node))
1095 }
1096
1097 fn create_static_member_call(
1098 &mut self,
1099 function_name: &str,
1100 arguments: &[ArgumentExpression],
1101 node: &swamp_ast::Node,
1102 ty: &TypeRef,
1103 ) -> ExpressionKind {
1104 self.lookup_associated_function(ty, function_name)
1105 .map_or_else(
1106 || {
1107 self.create_err(
1108 ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
1109 node,
1110 )
1111 .kind
1112 },
1113 |function| {
1114 let Function::Internal(internal_function) = &function else {
1115 panic!("only allowed for internal functions");
1116 };
1117
1118 ExpressionKind::InternalCall(internal_function.clone(), arguments.to_vec())
1119 },
1120 )
1121 }
1122
1123 fn create_static_member_intrinsic_call(
1124 &mut self,
1125 function_name: &str,
1126 arguments: &[ArgumentExpression],
1127 node: &swamp_ast::Node,
1128 ty: &TypeRef,
1129 ) -> ExpressionKind {
1130 if let Some(function) = self.lookup_associated_function(ty, function_name) {
1132 let Function::Internal(internal_function) = &function else {
1133 panic!("only allowed for internal functions");
1134 };
1135
1136 if let Some((intrinsic_fn, _)) =
1137 Self::extract_single_intrinsic_call(&internal_function.body)
1138 {
1139 ExpressionKind::IntrinsicCallEx(intrinsic_fn, arguments.to_vec())
1140 } else {
1141 self.create_err(
1142 ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
1143 node,
1144 )
1145 .kind
1146 }
1147 } else {
1148 self.create_err(
1149 ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
1150 node,
1151 )
1152 .kind
1153 }
1154 }
1155
1156 fn create_default_static_call(
1157 &mut self,
1158 node: &swamp_ast::Node,
1159 ty: &TypeRef,
1160 ) -> ExpressionKind {
1161 self.create_static_member_call("default", &[], node, ty)
1162 }
1163
1164 fn add_postfix(
1165 &mut self,
1166 vec: &mut Vec<Postfix>,
1167 kind: PostfixKind,
1168 ty: TypeRef,
1169 node: &swamp_ast::Node,
1170 ) {
1171 let resolved_node = self.to_node(node);
1172 let postfix = Postfix {
1173 node: resolved_node,
1174 ty,
1175 kind,
1176 };
1177
1178 vec.push(postfix);
1179 }
1180
1181 pub fn analyze_struct_field(
1186 &mut self,
1187 field_name: &swamp_ast::Node,
1188 tv: &TypeRef,
1189 ) -> (AnonymousStructType, usize, TypeRef) {
1190 let field_name_str = self.get_text(field_name).to_string();
1191
1192 let anon_struct_ref = match &*tv.kind {
1193 TypeKind::NamedStruct(struct_type) => {
1194 let TypeKind::AnonymousStruct(anon_struct) = &*struct_type.anon_struct_type.kind
1195 else {
1196 panic!("internal error")
1197 };
1198
1199 let field = anon_struct.field_name_sorted_fields.get(&field_name_str);
1200 if let Some(found) = field {
1201 let name_node = self.to_node(field_name);
1202
1203 self.shared
1204 .state
1205 .refs
1206 .add(found.symbol_id.into(), name_node.clone());
1207 self.shared
1208 .definition_table
1209 .refs
1210 .add(found.symbol_id.into(), name_node);
1211 }
1212
1213 struct_type.anon_struct_type.clone()
1214 }
1215 TypeKind::AnonymousStruct(anon_struct) => {
1216 self.shared
1218 .state
1219 .types
1220 .anonymous_struct(anon_struct.clone())
1221 }
1222 TypeKind::Range(range_struct_ref) => {
1223 if let TypeKind::NamedStruct(named_struct) = &*range_struct_ref.kind {
1225 named_struct.anon_struct_type.clone()
1226 } else {
1227 self.add_err(ErrorKind::UnknownStructField, field_name);
1228 return (
1230 AnonymousStructType::new(SeqMap::new()),
1231 0,
1232 self.shared.state.types.unit(),
1233 );
1234 }
1235 }
1236 _ => {
1237 self.add_err(ErrorKind::UnknownStructField, field_name);
1238 return (
1240 AnonymousStructType::new(SeqMap::new()),
1241 0,
1242 self.shared.state.types.unit(),
1243 );
1244 }
1245 };
1246
1247 if let TypeKind::AnonymousStruct(anon_struct) = &*anon_struct_ref.kind
1249 && let Some(found_field) = anon_struct.field_name_sorted_fields.get(&field_name_str)
1250 {
1251 let index = anon_struct
1252 .field_name_sorted_fields
1253 .get_index(&field_name_str)
1254 .expect("checked earlier");
1255
1256 return (anon_struct.clone(), index, found_field.field_type.clone());
1257 }
1258
1259 self.add_err(ErrorKind::UnknownStructField, field_name);
1260 (
1262 AnonymousStructType::new(SeqMap::new()),
1263 0,
1264 self.shared.state.types.unit(),
1265 )
1266 }
1267
1268 pub fn analyze_static_call(
1269 &mut self,
1270 ast_node: &swamp_ast::Node,
1271 func_def: Function,
1272 arguments: &[swamp_ast::Expression],
1273 context: &TypeContext,
1274 ) -> Expression {
1275 let signature = func_def.signature().clone();
1276
1277 let name_node = self.to_node(ast_node);
1278 self.shared
1279 .state
1280 .refs
1281 .add(func_def.symbol_id().into(), name_node.clone());
1282 self.shared
1283 .definition_table
1284 .refs
1285 .add(func_def.symbol_id().into(), name_node);
1286
1287 let analyzed_arguments =
1288 self.analyze_and_verify_parameters(ast_node, &signature.parameters, arguments);
1289
1290 let expr_kind = match &func_def {
1291 Function::Internal(internal) => {
1292 ExpressionKind::InternalCall(internal.clone(), analyzed_arguments)
1293 }
1294 Function::External(host) => ExpressionKind::HostCall(host.clone(), analyzed_arguments),
1295 Function::Intrinsic(intrinsic) => {
1296 ExpressionKind::IntrinsicCallEx(intrinsic.intrinsic.clone(), analyzed_arguments)
1297 }
1298 };
1299
1300 let expr = self.create_expr(expr_kind, signature.return_type.clone(), ast_node);
1301
1302 if self.needs_storage_error(&expr, true, context, ast_node) {
1304 return self.create_err(ErrorKind::NeedStorage, ast_node);
1305 }
1306
1307 expr
1308 }
1309
1310 #[allow(clippy::too_many_lines)]
1311 fn analyze_postfix_chain(
1312 &mut self,
1313 chain: &swamp_ast::PostfixChain,
1314 context: &TypeContext,
1315 ) -> Expression {
1316 let maybe_start_of_chain_base =
1317 self.analyze_start_chain_expression_get_mutability(&chain.base);
1318
1319 let mut start_index = 0;
1320
1321 let start_of_chain_kind = if let Some(start_of_chain_base) = maybe_start_of_chain_base {
1322 match start_of_chain_base {
1324 StartOfChainBase::FunctionReference(func_def) => {
1325 if let swamp_ast::Postfix::FunctionCall(
1328 ast_node,
1329 _maybe_generic_arguments,
1330 arguments,
1331 ) = &chain.postfixes[0]
1332 {
1333 start_index = 1;
1334 let call_expr =
1335 self.analyze_static_call(ast_node, func_def, arguments, context);
1336 if chain.postfixes.len() == 1 {
1337 return call_expr;
1338 }
1339 StartOfChainKind::Expression(Box::from(call_expr))
1340 } else {
1341 panic!("must be a normal function call")
1342 }
1343 }
1344 StartOfChainBase::Variable(var) => StartOfChainKind::Variable(var),
1345 }
1346 } else {
1347 let ctx = TypeContext::new_anything_argument(true); StartOfChainKind::Expression(Box::from(self.analyze_expression(&chain.base, &ctx)))
1349 };
1350
1351 let start_of_chain_node = self.to_node(&chain.base.node);
1352
1353 let start_of_chain = StartOfChain {
1354 kind: start_of_chain_kind.clone(),
1355 node: start_of_chain_node,
1356 };
1357
1358 let mut tv = TypeWithMut {
1359 resolved_type: start_of_chain_kind.ty(),
1360 is_mutable: start_of_chain_kind.is_mutable(),
1361 };
1362
1363 let mut uncertain = false;
1364 let mut previous_was_optional_chaining = false;
1365
1366 let mut suffixes = Vec::new();
1367
1368 for (index, item) in chain.postfixes[start_index..].iter().enumerate() {
1369 let is_last = index == chain.postfixes[start_index..].len() - 1;
1370
1371 if previous_was_optional_chaining {
1373 match item {
1374 swamp_ast::Postfix::FieldAccess(_)
1375 | swamp_ast::Postfix::MemberCall(_, _, _)
1376 | swamp_ast::Postfix::Subscript(_)
1377 | swamp_ast::Postfix::SubscriptTuple(_, _) => {
1378 }
1380 swamp_ast::Postfix::OptionalChainingOperator(node) => {
1381 return self
1382 .create_err(ErrorKind::InvalidOperatorAfterOptionalChaining, node);
1383 }
1384 swamp_ast::Postfix::FunctionCall(node, _, _) => {
1385 return self
1386 .create_err(ErrorKind::InvalidOperatorAfterOptionalChaining, node);
1387 }
1388 }
1389 }
1390
1391 match item {
1392 swamp_ast::Postfix::FieldAccess(field_name) => {
1399 previous_was_optional_chaining = false;
1400 let (struct_type_ref, index, return_type) =
1401 self.analyze_struct_field(&field_name.clone(), &tv.resolved_type);
1402 let struct_type_type_ref = self
1403 .shared
1404 .state
1405 .types
1406 .anonymous_struct(struct_type_ref.clone());
1407
1408 self.add_postfix(
1409 &mut suffixes,
1410 PostfixKind::StructField(struct_type_type_ref, index),
1411 return_type.clone(),
1412 field_name,
1413 );
1414
1415 tv.resolved_type = return_type.clone();
1416 }
1418
1419 swamp_ast::Postfix::SubscriptTuple(col_expr, row_expr) => {
1420 previous_was_optional_chaining = false;
1421 let collection_type = tv.resolved_type.clone();
1422 match &*collection_type.kind {
1423 TypeKind::GridStorage(element_type, x, _) => {
1424 let int_type = self.shared.state.types.int();
1425 let unsigned_int_x_context =
1426 TypeContext::new_argument(&int_type, false);
1427 let unsigned_int_x_expression =
1428 self.analyze_expression(col_expr, &unsigned_int_x_context);
1429
1430 let unsigned_int_y_context =
1431 TypeContext::new_argument(&int_type, false);
1432 let unsigned_int_y_expression =
1433 self.analyze_expression(row_expr, &unsigned_int_y_context);
1434
1435 let vec_type = GridType {
1436 element: element_type.clone(),
1437 };
1438
1439 self.add_postfix(
1440 &mut suffixes,
1441 PostfixKind::GridSubscript(
1442 vec_type,
1443 unsigned_int_x_expression,
1444 unsigned_int_y_expression,
1445 ),
1446 element_type.clone(),
1447 &col_expr.node,
1448 );
1449
1450 tv.resolved_type = element_type.clone();
1452 }
1453 _ => {
1454 return self.create_err(ErrorKind::ExpectedTupleType, &chain.base.node);
1455 }
1456 }
1457 }
1458
1459 swamp_ast::Postfix::Subscript(lookup_expr) => {
1460 previous_was_optional_chaining = false;
1461 let collection_type = tv.resolved_type.clone();
1462
1463 match &*collection_type.kind {
1464 TypeKind::MapStorage(key_type, value_type, ..)
1466 | TypeKind::DynamicLengthMapView(key_type, value_type) => {
1467 let (postfix, return_type) =
1468 self.analyze_map_subscript(key_type, value_type, lookup_expr);
1469 suffixes.push(postfix);
1470 tv.resolved_type = return_type;
1471 }
1472 _ => {
1473 let anything_context = context.with_argument_anything();
1475 let anything_expression =
1476 self.analyze_expression(lookup_expr, &anything_context);
1477
1478 match &*anything_expression.ty.kind {
1479 TypeKind::Int => {
1480 let (postfix, return_type) = self.analyze_subscript_int(
1481 collection_type,
1482 anything_expression,
1483 );
1484 suffixes.push(postfix);
1485 tv.resolved_type = return_type;
1486 }
1487 TypeKind::Range(_range_type) => {
1488 let (postfix, return_type) = self.analyze_subscript_range(
1489 collection_type,
1490 anything_expression,
1491 );
1492 suffixes.push(postfix);
1493 tv.resolved_type = return_type;
1494 }
1495 _ => {
1496 return self.create_err(
1497 ErrorKind::CanNotSubscriptWithThatType,
1498 &lookup_expr.node,
1499 );
1500 }
1501 }
1502 }
1503 }
1504 }
1505
1506 swamp_ast::Postfix::MemberCall(member_name, generic_arguments, ast_arguments) => {
1507 previous_was_optional_chaining = false;
1508 let member_name_str = self.get_text(member_name).to_string();
1509 let underlying_type = tv.resolved_type;
1510
1511 let (kind, return_type) = self.analyze_member_call(
1512 &underlying_type,
1513 &member_name_str,
1514 generic_arguments.clone(),
1515 ast_arguments,
1516 tv.is_mutable,
1517 member_name,
1518 );
1519
1520 self.add_postfix(&mut suffixes, kind, return_type.clone(), member_name);
1521 tv.resolved_type = return_type.clone();
1522 tv.is_mutable = false;
1523 }
1524 swamp_ast::Postfix::FunctionCall(node, _generic_arguments, arguments) => {
1525 return self.create_err(
1526 ErrorKind::CanOnlyHaveFunctionCallAtStartOfPostfixChain,
1527 node,
1528 );
1529 }
1530
1531 swamp_ast::Postfix::OptionalChainingOperator(option_node) => {
1532 if is_last {
1533 return self.create_err(
1534 ErrorKind::InvalidOperatorAfterOptionalChaining,
1535 option_node,
1536 );
1537 }
1538
1539 if let TypeKind::Optional(unwrapped_type) = &*tv.resolved_type.kind {
1540 uncertain = true;
1541 self.add_postfix(
1542 &mut suffixes,
1543 PostfixKind::OptionalChainingOperator,
1544 (*unwrapped_type).clone(),
1545 option_node,
1546 );
1547 tv.resolved_type = (*unwrapped_type).clone();
1548 previous_was_optional_chaining = true;
1549 } else {
1550 return self.create_err(ErrorKind::ExpectedOptional, option_node);
1551 }
1552 }
1553 }
1554 }
1555
1556 if uncertain {
1557 if let TypeKind::Optional(_) = &*tv.resolved_type.kind {} else {
1558 tv.resolved_type = self.shared.state.types.optional(&tv.resolved_type.clone());
1559 }
1560 }
1561
1562 self.create_expr(
1563 ExpressionKind::PostfixChain(start_of_chain, suffixes),
1564 tv.resolved_type,
1565 &chain.base.node,
1566 )
1567 }
1568
1569 fn analyze_bool_argument_expression(
1570 &mut self,
1571 expression: &swamp_ast::Expression,
1572 ) -> BooleanExpression {
1573 let bool_type = self.shared.state.types.bool();
1574 let bool_context = TypeContext::new_argument(&bool_type, false);
1575 let resolved_expression = self.analyze_expression(expression, &bool_context);
1576 let expr_type = resolved_expression.ty.clone();
1577
1578 let bool_expression = match &*expr_type.kind {
1579 TypeKind::Bool => resolved_expression,
1580 TypeKind::Optional(_) => {
1581 let bool = self.types().bool();
1582 self.create_expr(
1583 ExpressionKind::CoerceOptionToBool(Box::new(resolved_expression)),
1584 bool,
1585 &expression.node,
1586 )
1587 }
1588 _ => self.create_err(ErrorKind::ExpectedBooleanExpression, &expression.node),
1589 };
1590
1591 BooleanExpression {
1592 expression: Box::from(bool_expression),
1593 }
1594 }
1595
1596 fn is_aggregate_function_call(expression: &swamp_ast::Expression) -> bool {
1598 match &expression.kind {
1599 swamp_ast::ExpressionKind::PostfixChain(chain) => {
1600 if chain.postfixes.is_empty() {
1601 return false;
1602 }
1603
1604 for postfix in &chain.postfixes {
1605 if let swamp_ast::Postfix::FunctionCall(_, _, _) = postfix {
1606 return true;
1607 }
1608 }
1609 false
1610 }
1611 _ => false, }
1613 }
1614
1615 fn analyze_iterable(
1616 &mut self,
1617 mut_requested_for_value_variable: Option<swamp_ast::Node>,
1618 expression: &swamp_ast::Expression,
1619 ) -> Iterable {
1620 let has_lvalue_target = !Self::is_aggregate_function_call(expression);
1623 let any_context = TypeContext::new_anything_argument(has_lvalue_target);
1624
1625 let resolved_expression = self.analyze_expression(expression, &any_context);
1626
1627 let resolved_type = &resolved_expression.ty.clone();
1628 let int_type = Some(self.types().int());
1629 let (key_type, value_type): (Option<TypeRef>, TypeRef) = match &*resolved_type.kind {
1630 TypeKind::StringView(_, char) | TypeKind::StringStorage(_, char, _) => {
1631 (int_type, char.clone())
1632 }
1633 TypeKind::SliceView(element_type) => (int_type, element_type.clone()),
1634 TypeKind::VecStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1635 TypeKind::SparseStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1636 TypeKind::StackStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1637 TypeKind::StackView(element_type) => (int_type, element_type.clone()),
1638 TypeKind::QueueStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1639 TypeKind::QueueView(element_type) => (int_type, element_type.clone()),
1640 TypeKind::DynamicLengthVecView(element_type) => (int_type, element_type.clone()),
1641 TypeKind::SparseView(element_type) => (int_type, element_type.clone()),
1642 TypeKind::FixedCapacityAndLengthArray(element_type, _fixed_size) => {
1643 (int_type, element_type.clone())
1644 }
1645 TypeKind::DynamicLengthMapView(key_type, value_type)
1646 | TypeKind::MapStorage(key_type, value_type, _) => {
1647 (Some(key_type.clone()), value_type.clone())
1648 }
1649 TypeKind::Range(_) => (None, self.types().int()),
1650 _ => {
1651 error!(?resolved_type, "not an iterator");
1652 return Iterable {
1653 key_type: None,
1654 value_type: self.shared.state.types.unit(),
1655 resolved_expression: Box::new(
1656 self.create_err(ErrorKind::NotAnIterator, &expression.node),
1657 ),
1658 };
1659 }
1660 };
1661
1662 if mut_requested_for_value_variable.is_some() {
1663 let _resulting_location =
1665 self.analyze_to_location(expression, &any_context, LocationSide::Mutable);
1666 }
1669
1670 Iterable {
1671 key_type,
1672 value_type,
1673 resolved_expression: Box::new(resolved_expression),
1674 }
1675 }
1676
1677 fn analyze_argument_expressions(
1678 &mut self,
1679 expected_type: Option<&TypeRef>,
1680 context: &TypeContext,
1681 ast_expressions: &[swamp_ast::Expression],
1682 ) -> Vec<Expression> {
1683 let mut resolved_expressions = Vec::new();
1684 let argument_expressions_context = TypeContext::new_unsure_argument(expected_type, false);
1686
1687 for expression in ast_expressions {
1688 resolved_expressions
1689 .push(self.analyze_expression(expression, &argument_expressions_context));
1690 }
1691 resolved_expressions
1692 }
1693
1694 fn analyze_block(
1695 &mut self,
1696 _node: &swamp_ast::Node,
1697 context: &TypeContext,
1698 ast_expressions: &[swamp_ast::Expression],
1699 ) -> (Vec<Expression>, TypeRef) {
1700 if ast_expressions.is_empty() {
1701 return (vec![], self.shared.state.types.unit());
1702 }
1703
1704 self.push_block_scope("block");
1705
1706 let mut resolved_expressions = Vec::with_capacity(ast_expressions.len());
1707
1708 for expression in &ast_expressions[..ast_expressions.len() - 1] {
1709 let unit_type = self.shared.state.types.unit();
1710 let stmt_context =
1711 context.with_expected_type(Some(&unit_type), context.has_lvalue_target);
1712 let expr = self.analyze_expression(expression, &stmt_context);
1713
1714 resolved_expressions.push(expr);
1715 }
1716
1717 let last_expr =
1719 self.analyze_expression(&ast_expressions[ast_expressions.len() - 1], context);
1720 let last_type = last_expr.ty.clone();
1721 resolved_expressions.push(last_expr);
1722
1723 self.pop_block_scope("block");
1724
1725 (resolved_expressions, last_type)
1726 }
1727
1728 fn analyze_interpolated_string_lowering(
1729 &mut self,
1730 node: &swamp_ast::Node,
1731 string_parts: &[swamp_ast::StringPart],
1732 ) -> Expression {
1733 let mut last_expression: Option<Expression> = None;
1734 for part in string_parts {
1735 let created_expression = match part {
1736 swamp_ast::StringPart::Literal(string_node, processed_string) => {
1737 let string_literal =
1738 ExpressionKind::StringLiteral(processed_string.to_string());
1739 let basic_literal = string_literal;
1740 let string_type = self.shared.state.types.string();
1741 self.add_default_functions(&string_type, node);
1742 self.create_expr(basic_literal, string_type, string_node)
1743 }
1744 swamp_ast::StringPart::Interpolation(expression, format_specifier) => {
1745 let any_context = TypeContext::new_anything_argument(false); let expr = self.analyze_expression(expression, &any_context);
1748
1749 let tk = (*expr.ty.kind).clone();
1750
1751 let maybe_to_string = self
1752 .shared
1753 .state
1754 .associated_impls
1755 .get_internal_member_function(&expr.ty, "string");
1756
1757 if matches!(tk, TypeKind::StringView { .. })
1758 || matches!(tk, TypeKind::StringStorage(..))
1759 {
1760 expr
1761 } else {
1762 let underlying = expr.ty.clone();
1763
1764 if self.needs_storage_error(&expr, true, &any_context, &expression.node) {
1766 return self.create_err(ErrorKind::NeedStorage, &expression.node);
1767 }
1768
1769 let call_expr_kind = if maybe_to_string.is_none() {
1770 let string_type = self.types().string();
1771
1772 ExpressionKind::StringLiteral(format!(
1773 "missing to_string for: {string_type}"
1774 ))
1775 } else {
1784 let expr_as_param = ArgumentExpression::Expression(expr);
1785 self.create_static_member_call(
1786 "string",
1787 &[expr_as_param.clone()],
1788 &expression.node,
1789 &underlying,
1790 )
1791 };
1792
1793 let string_type = self.shared.state.types.string();
1801 self.create_expr(call_expr_kind, string_type, &expression.node)
1802 }
1803 }
1804 };
1805
1806 let x_last_expr = if let Some(last_expr) = last_expression.clone() {
1807 let op_kind = BinaryOperatorKind::Add;
1808 let node = created_expression.node.clone();
1809 let op = BinaryOperator {
1810 left: Box::new(last_expr),
1811 right: Box::new(created_expression),
1812 kind: op_kind,
1813 node: node.clone(),
1814 };
1815
1816 let string_type = self.shared.state.types.string();
1817 create_expr_resolved(ExpressionKind::BinaryOp(op), string_type, &node)
1818 } else {
1819 created_expression
1820 };
1821
1822 last_expression = Some(x_last_expr);
1823 }
1824
1825 if let Some(last) = last_expression {
1828 last
1829 } else {
1830 let string_type = self.shared.state.types.string();
1831 self.create_expr(
1832 ExpressionKind::StringLiteral(String::new()),
1833 string_type,
1834 node,
1835 )
1836 }
1837 }
1838
1839 pub(crate) fn analyze_identifier(
1840 &mut self,
1841 qualified_func_name: &swamp_ast::QualifiedIdentifier,
1842 ) -> Expression {
1843 if qualified_func_name.module_path.is_none()
1846 && qualified_func_name.generic_params.is_empty()
1847 && let Some(found_variable) = self.try_find_variable(&qualified_func_name.name)
1848 {
1849 return self.create_expr(
1850 ExpressionKind::VariableAccess(found_variable.clone()),
1851 found_variable.resolved_type.clone(),
1852 &qualified_func_name.name,
1853 );
1854 }
1855
1856 let text = self.get_text(&qualified_func_name.name);
1857 self.create_err(
1858 ErrorKind::UnknownIdentifier(text.to_string()),
1859 &qualified_func_name.name,
1860 )
1861 }
1862
1863 fn analyze_variable_reference(&mut self, var_node: &swamp_ast::Node) -> Expression {
1865 if let Some(found_variable) = self.try_find_variable(var_node) {
1866 let name_node = self.to_node(var_node);
1867
1868 self.shared
1869 .state
1870 .refs
1871 .add(found_variable.symbol_id.into(), name_node.clone());
1872 self.shared
1873 .definition_table
1874 .refs
1875 .add(found_variable.symbol_id.into(), name_node);
1876
1877 return self.create_expr(
1878 ExpressionKind::VariableAccess(found_variable.clone()),
1879 found_variable.resolved_type.clone(),
1880 var_node,
1881 );
1882 }
1883 let text = self.get_text(var_node);
1884 self.create_err(ErrorKind::UnknownIdentifier(text.to_string()), var_node)
1885 }
1886
1887 fn analyze_internal_initializer_pair_list(
1888 &mut self,
1889 node: &swamp_ast::Node,
1890 items: &[(swamp_ast::Expression, swamp_ast::Expression)],
1891 context: &TypeContext,
1892 ) -> (TypeRef, Vec<(Expression, Expression)>) {
1893 let (collection_type, key_type, value_type) = if let Some(expected_type) =
1894 context.expected_type
1895 {
1896 match &*expected_type.kind {
1897 TypeKind::MapStorage(key, value, capacity) => {
1898 if items.len() > *capacity {
1899 self.add_err(
1900 ErrorKind::TooManyInitializerListElementsForStorage {
1901 capacity: *capacity,
1902 },
1903 node,
1904 );
1905 return (self.types().unit(), vec![]);
1906 }
1907 (expected_type.clone(), key.clone(), value.clone())
1908 }
1909 TypeKind::DynamicLengthMapView(key, value) => {
1910 (expected_type.clone(), key.clone(), value.clone())
1911 }
1912 _ => {
1913 self.add_err(ErrorKind::ExpectedSlice, node);
1914 return (self.types().unit(), vec![]);
1915 }
1916 }
1917 } else if items.is_empty() {
1918 self.add_err(ErrorKind::NoInferredTypeForEmptyInitializer, node);
1919 return (self.types().unit(), vec![]);
1920 } else {
1921 let maybe_key_context = TypeContext::new_anything_argument(true);
1923
1924 let first_key_expression = self.analyze_expression(&items[0].0, &maybe_key_context);
1925
1926 let maybe_value_context = TypeContext::new_anything_argument(true);
1927 let first_value_expression = self.analyze_expression(&items[0].1, &maybe_value_context);
1928
1929 let required_key_type = first_key_expression.ty;
1930 let required_value_type = first_value_expression.ty;
1931
1932 let inferred_type =
1933 self.types()
1934 .map_storage(&required_key_type, &required_value_type, items.len());
1935
1936 (inferred_type, required_key_type, required_value_type)
1937 };
1938
1939 assert!(!matches!(*key_type.kind, TypeKind::Unit));
1940 assert!(!matches!(*value_type.kind, TypeKind::Unit));
1941
1942 let required_key_context = TypeContext::new_argument(&key_type, true);
1943 let required_value_context = TypeContext::new_argument(&value_type, true);
1944
1945 let mut resolved_items = Vec::new();
1946
1947 for (key_expr, value_expr) in items {
1948 let analyzed_key_expr = self.analyze_expression(key_expr, &required_key_context);
1949 let analyzed_value_expr = self.analyze_expression(value_expr, &required_value_context);
1950 resolved_items.push((analyzed_key_expr, analyzed_value_expr));
1951 }
1952
1953 (collection_type, resolved_items)
1954 }
1955
1956 fn analyze_internal_initializer_list(
1957 &mut self,
1958 node: &swamp_ast::Node,
1959 items: &[swamp_ast::Expression],
1960 context: &TypeContext,
1961 ) -> (TypeRef, Vec<Expression>) {
1962 let (collection_type, element_type) = if let Some(expected_type) = context.expected_type {
1963 match &*expected_type.kind {
1964 TypeKind::GridStorage(element_type, width, height) => {
1965 let capacity = width * height;
1966 if items.len() > capacity {
1967 return (
1968 self.types().unit(),
1969 self.create_err_vec(
1970 ErrorKind::TooManyInitializerListElementsForStorage { capacity },
1971 node,
1972 ),
1973 );
1974 }
1975 (expected_type.clone(), element_type.clone())
1976 }
1977 TypeKind::StackStorage(element_type, capacity)
1978 | TypeKind::QueueStorage(element_type, capacity)
1979 | TypeKind::SparseStorage(element_type, capacity)
1980 | TypeKind::VecStorage(element_type, capacity) => {
1981 if items.len() > *capacity {
1982 return (
1983 self.types().unit(),
1984 self.create_err_vec(
1985 ErrorKind::TooManyInitializerListElementsForStorage {
1986 capacity: *capacity,
1987 },
1988 node,
1989 ),
1990 );
1991 }
1992 (expected_type.clone(), element_type.clone())
1993 }
1994 TypeKind::QueueView(element_type) => {
1995 let inferred_storage_type =
1997 self.types().queue_storage(element_type, items.len());
1998 let default_node = swamp_ast::Node::default();
1999 self.add_default_functions(&inferred_storage_type, &default_node);
2000 (inferred_storage_type, element_type.clone())
2001 }
2002 TypeKind::SparseView(element_type) => {
2003 let inferred_storage_type =
2005 self.types().sparse_storage(element_type, items.len());
2006 let default_node = swamp_ast::Node::default();
2007 self.add_default_functions(&inferred_storage_type, &default_node);
2008 (inferred_storage_type, element_type.clone())
2009 }
2010 TypeKind::StackView(element_type) => {
2011 let inferred_storage_type =
2013 self.types().stack_storage(element_type, items.len());
2014 let default_node = swamp_ast::Node::default();
2015 self.add_default_functions(&inferred_storage_type, &default_node);
2016 (inferred_storage_type, element_type.clone())
2017 }
2018 TypeKind::GridView(element_type) => {
2019 (expected_type.clone(), element_type.clone())
2021 }
2022 TypeKind::DynamicLengthVecView(element_type) => {
2023 let inferred_storage_type = self.types().vec_storage(element_type, items.len());
2025 let default_node = swamp_ast::Node::default();
2026 self.add_default_functions(&inferred_storage_type, &default_node);
2027 (inferred_storage_type, element_type.clone())
2028 }
2029 TypeKind::SliceView(element_type) => {
2030 let inferred_storage_type = self.types().vec_storage(element_type, items.len());
2032 let default_node = swamp_ast::Node::default();
2033 self.add_default_functions(&inferred_storage_type, &default_node);
2034 (inferred_storage_type, element_type.clone())
2035 }
2036 TypeKind::FixedCapacityAndLengthArray(element_type, _size) => {
2037 (expected_type.clone(), element_type.clone())
2038 }
2039 _ => {
2040 return (
2041 self.types().unit(),
2042 self.create_err_vec(
2043 ErrorKind::ExpectedInitializerTarget {
2044 destination_type: expected_type.clone(),
2045 },
2046 node,
2047 ),
2048 );
2049 }
2050 }
2051 } else if items.is_empty() {
2052 return (
2053 self.types().unit(),
2054 self.create_err_vec(ErrorKind::NoInferredTypeForEmptyInitializer, node),
2055 );
2056 } else {
2057 let maybe_context = TypeContext::new_anything_argument(true);
2059 let first = self.analyze_expression(&items[0], &maybe_context);
2060 let required_type = first.ty;
2061 let inferred_vec_storage_type = self.types().vec_storage(&required_type, items.len());
2062 let default_node = swamp_ast::Node::default();
2064 self.add_default_functions(&inferred_vec_storage_type, &default_node);
2065 (inferred_vec_storage_type, required_type)
2066 };
2067
2068 let required_context = TypeContext::new_argument(&element_type, true);
2069 let mut resolved_items = Vec::new();
2070 for item in items {
2071 let resolved_expr = self.analyze_expression(item, &required_context);
2072 resolved_items.push(resolved_expr);
2073 }
2074 (collection_type, resolved_items)
2075 }
2076
2077 fn push_block_scope(&mut self, debug_str: &str) {
2078 let register_watermark = self.scope.total_scopes.current_register;
2079 self.scope.active_scope.block_scope_stack.push(BlockScope {
2082 mode: BlockScopeMode::Open,
2083 lookup: Default::default(),
2084 variables: SeqMap::default(),
2085 register_watermark,
2086 });
2087 }
2088
2089 fn push_lambda_scope(&mut self, debug_str: &str) {
2090 self.scope.active_scope.block_scope_stack.push(BlockScope {
2093 mode: BlockScopeMode::Lambda,
2094 lookup: SeqMap::default(),
2095 variables: SeqMap::default(),
2096 register_watermark: 0, });
2098 }
2099
2100 fn pop_block_scope(&mut self, debug_str: &str) {
2101 self.pop_any_block_scope();
2103 }
2104
2105 fn push_closed_block_scope(&mut self) {
2106 let register_watermark = self.scope.total_scopes.current_register;
2107 self.scope.active_scope.block_scope_stack.push(BlockScope {
2109 mode: BlockScopeMode::Closed,
2110 lookup: Default::default(),
2111 variables: SeqMap::default(),
2112 register_watermark,
2113 });
2114 }
2115
2116 fn pop_closed_block_scope(&mut self) {
2117 self.pop_any_block_scope();
2119 }
2120
2121 fn pop_any_block_scope(&mut self) {
2122 let scope = self.scope.active_scope.block_scope_stack.pop().unwrap();
2123
2124 if self.scope.total_scopes.current_register
2126 > self.scope.total_scopes.highest_virtual_register
2127 {
2128 self.scope.total_scopes.highest_virtual_register =
2129 self.scope.total_scopes.current_register;
2130 }
2131
2132 let is_inside_lambda = self
2134 .scope
2135 .active_scope
2136 .block_scope_stack
2137 .iter()
2138 .any(|s| matches!(s.mode, BlockScopeMode::Lambda));
2139
2140 if matches!(scope.mode, BlockScopeMode::Lambda) {
2141 } else if is_inside_lambda {
2143 } else {
2145 self.scope.total_scopes.current_register = scope.register_watermark;
2150 }
2151 }
2152
2153 fn analyze_match(
2154 &mut self,
2155 scrutinee: &swamp_ast::Expression,
2156 default_context: &TypeContext,
2157 arms: &Vec<swamp_ast::MatchArm>,
2158 ) -> (Match, TypeRef) {
2159 let mut known_type = default_context.expected_type.cloned();
2160 let own_context = default_context.clone();
2161
2162 self.push_block_scope("match block");
2163 let scrutinee_context = TypeContext::new_anything_argument(true); let resolved_scrutinee = self.analyze_expression(scrutinee, &scrutinee_context);
2166 let scrutinee_type = resolved_scrutinee.ty.clone();
2167
2168 let mut resolved_arms = Vec::with_capacity(arms.len());
2169
2170 if arms.is_empty() {
2172 let err_match = Match {
2173 expression: Box::new(
2174 self.create_err(ErrorKind::MatchMustHaveAtLeastOneArm, &scrutinee.node),
2175 ),
2176 arms: resolved_arms,
2177 };
2178 return (err_match, self.types().unit());
2179 }
2180
2181 for arm in arms {
2182 let (resolved_arm, _anyone_wants_mutable) = self.analyze_arm(
2183 arm,
2184 &resolved_scrutinee,
2185 &own_context.with_expected_type(known_type.as_ref(), false),
2186 &scrutinee_type,
2187 );
2188
2189 if known_type.is_none() {
2190 known_type = Some(resolved_arm.expression.ty.clone());
2191 }
2192 resolved_arms.push(resolved_arm);
2193 }
2194
2195 self.pop_block_scope("match block");
2196
2197 if let Some(encountered_type) = known_type {
2198 (
2199 Match {
2200 expression: Box::new(resolved_scrutinee),
2201 arms: resolved_arms,
2202 },
2203 encountered_type,
2204 )
2205 } else {
2206 let err_expr = self.create_err(ErrorKind::MatchArmsMustHaveTypes, &scrutinee.node);
2207
2208 (
2209 Match {
2210 expression: Box::new(err_expr),
2211 arms: resolved_arms.clone(),
2212 },
2213 self.types().unit(),
2214 )
2215 }
2216 }
2217
2218 fn analyze_arm(
2219 &mut self,
2220 arm: &swamp_ast::MatchArm,
2221 _expression: &Expression,
2222 type_context: &TypeContext,
2223 expected_condition_type: &TypeRef,
2224 ) -> (MatchArm, bool) {
2225 let (resolved_pattern, scope_was_pushed, anyone_wants_mutable) =
2226 self.analyze_pattern(&arm.pattern, expected_condition_type);
2227
2228 let resolved_expression = self.analyze_expression(&arm.expression, type_context);
2229 if scope_was_pushed {
2230 self.pop_block_scope(&format!("analyze_arm {:?}", arm.expression));
2231 }
2232
2233 let resolved_type = resolved_expression.ty.clone();
2234
2235 (
2236 MatchArm {
2237 pattern: resolved_pattern,
2238 expression: Box::from(resolved_expression),
2239 expression_type: resolved_type,
2240 },
2241 anyone_wants_mutable,
2242 )
2243 }
2244
2245 fn str_to_int(text: &str) -> Result<i32, ParseIntError> {
2246 let text = text.replace('_', "");
2247 text.strip_prefix("0x").map_or_else(
2248 || {
2249 text.strip_prefix("-0x").map_or_else(
2250 || text.parse::<i32>(),
2251 |rest| i32::from_str_radix(rest, 16).map(|x| -x),
2252 )
2253 },
2254 |rest| i32::from_str_radix(rest, 16),
2255 )
2256 }
2257
2258 pub fn str_to_byte(text: &str) -> Result<u8, ParseByteError> {
2259 let inner = text
2261 .strip_prefix("b'")
2262 .and_then(|s| s.strip_suffix("'"))
2263 .ok_or(ParseByteError::InvalidFormat)?;
2264
2265 let mut chars = inner.chars();
2266 let first = chars.next().ok_or(ParseByteError::InvalidFormat)?;
2267
2268 if first == '\\' {
2269 let esc = chars.next().ok_or(ParseByteError::InvalidEscape)?;
2270 if chars.next().is_some() {
2271 return Err(ParseByteError::InvalidFormat);
2272 }
2273 return match esc {
2274 'n' => Ok(b'\n'),
2275 'r' => Ok(b'\r'),
2276 't' => Ok(b'\t'),
2277 '0' => Ok(b'\0'),
2278 '\\' => Ok(b'\\'),
2279 '\'' => Ok(b'\''),
2280 _ => Err(ParseByteError::InvalidEscape),
2281 };
2282 }
2283
2284 if first.is_ascii() && chars.next().is_none() {
2285 return Ok(first as u8);
2286 }
2287
2288 Err(ParseByteError::InvalidFormat)
2289 }
2290 fn str_to_unsigned_int(text: &str) -> Result<u32, ParseIntError> {
2291 let text = text.replace('_', "");
2292 text.strip_prefix("0x")
2293 .map_or_else(|| text.parse::<u32>(), |rest| u32::from_str_radix(rest, 16))
2294 }
2295
2296 fn str_to_float(text: &str) -> Result<f32, ParseFloatError> {
2297 text.parse::<f32>()
2298 }
2299
2300 fn str_to_bool(text: &str) -> Result<bool, ParseBoolError> {
2301 bool::from_str(text)
2302 }
2303
2304 fn analyze_pattern_literal(
2305 &mut self,
2306 node: &swamp_ast::Node,
2307 ast_literal: &swamp_ast::LiteralKind,
2308 expected_condition_type: &TypeRef,
2309 ) -> NormalPattern {
2310 let required_condition_type_context =
2311 TypeContext::new_argument(expected_condition_type, false);
2312 let literal = self.analyze_literal(
2313 node,
2314 ast_literal,
2315 &required_condition_type_context,
2316 &required_condition_type_context,
2317 );
2318
2319 if !self
2320 .types()
2321 .compatible_with(&literal.ty, expected_condition_type)
2322 {
2323 return NormalPattern::Literal(self.create_err(
2324 ErrorKind::IncompatibleTypes {
2325 expected: expected_condition_type.clone(),
2326 found: literal.ty,
2327 },
2328 node,
2329 ));
2330 }
2331
2332 NormalPattern::Literal(literal)
2333 }
2334
2335 const fn to_node(&self, node: &swamp_ast::Node) -> Node {
2336 Node {
2337 span: Span {
2338 file_id: self.shared.file_id,
2339 offset: node.span.offset,
2340 length: node.span.length,
2341 },
2342 }
2343 }
2344
2345 fn get_module_path(&self, module_path: Option<&swamp_ast::ModulePath>) -> Vec<String> {
2346 module_path.as_ref().map_or_else(Vec::new, |found| {
2347 let mut strings = Vec::new();
2348 for path_item in &found.0 {
2349 strings.push(self.get_text(path_item).to_string());
2350 }
2351 strings
2352 })
2353 }
2354
2355 fn get_enum_variant_type(
2356 &mut self,
2357 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2358 variant_name: &str,
2359 ) -> EnumVariantType {
2360 let Some((symbol_table, enum_name)) =
2361 self.get_symbol_table_and_name(qualified_type_identifier)
2362 else {
2363 self.add_err(
2364 ErrorKind::UnknownEnumVariantType,
2365 &qualified_type_identifier.name.0,
2366 );
2367 return EnumVariantType {
2368 common: EnumVariantCommon {
2369 symbol_id: TopLevelSymbolId::new_illegal(),
2370 name: Default::default(),
2371 assigned_name: String::new(),
2372 container_index: 0,
2373 },
2374 payload_type: self.types().unit(),
2375 };
2376 };
2377
2378 if let Some(enum_name) = symbol_table.get_enum_variant_type(&enum_name, variant_name) {
2379 enum_name
2380 } else {
2381 self.add_err(
2382 ErrorKind::UnknownEnumVariantType,
2383 &qualified_type_identifier.name.0,
2384 );
2385 EnumVariantType {
2386 common: EnumVariantCommon {
2387 symbol_id: TopLevelSymbolId::new_illegal(),
2388 name: Default::default(),
2389 assigned_name: String::new(),
2390 container_index: 0,
2391 },
2392 payload_type: self.types().unit(),
2393 }
2394 }
2395 }
2396
2397 pub(crate) fn get_symbol_table_and_name(
2398 &self,
2399 type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2400 ) -> Option<(&DefinitionTable, String)> {
2401 let path = self.get_module_path(type_identifier.module_path.as_ref());
2402 let name = self.get_text(&type_identifier.name.0).to_string();
2403
2404 if let Some(found) = self.shared.get_definition_table(&path) {
2405 Some((found, name))
2406 } else {
2407 None
2408 }
2409 }
2410
2411 const fn analyze_compound_operator(
2412 &self,
2413 ast_operator: &swamp_ast::CompoundOperator,
2414 ) -> CompoundOperator {
2415 let resolved_node = self.to_node(&ast_operator.node);
2416 let resolved_kind = match ast_operator.kind {
2417 swamp_ast::CompoundOperatorKind::Add => CompoundOperatorKind::Add,
2418 swamp_ast::CompoundOperatorKind::Sub => CompoundOperatorKind::Sub,
2419 swamp_ast::CompoundOperatorKind::Mul => CompoundOperatorKind::Mul,
2420 swamp_ast::CompoundOperatorKind::Div => CompoundOperatorKind::Div,
2421 swamp_ast::CompoundOperatorKind::Modulo => CompoundOperatorKind::Modulo,
2422 };
2423
2424 CompoundOperator {
2425 node: resolved_node,
2426 kind: resolved_kind,
2427 }
2428 }
2429
2430 const fn to_node_option(&self, maybe_node: Option<&swamp_ast::Node>) -> Option<Node> {
2431 match maybe_node {
2432 None => None,
2433 Some(node) => Some(self.to_node(node)),
2434 }
2435 }
2436
2437 const fn analyze_format_specifier(
2438 &self,
2439 ast_format_specifier: Option<&swamp_ast::FormatSpecifier>,
2440 ) -> Option<FormatSpecifier> {
2441 let f = match ast_format_specifier {
2442 None => return None,
2443 Some(ast_format) => match ast_format {
2444 swamp_ast::FormatSpecifier::LowerHex(node) => FormatSpecifier {
2445 node: self.to_node(node),
2446 kind: FormatSpecifierKind::LowerHex,
2447 },
2448 swamp_ast::FormatSpecifier::UpperHex(node) => FormatSpecifier {
2449 node: self.to_node(node),
2450 kind: FormatSpecifierKind::UpperHex,
2451 },
2452 swamp_ast::FormatSpecifier::Binary(node) => FormatSpecifier {
2453 node: self.to_node(node),
2454 kind: FormatSpecifierKind::Binary,
2455 },
2456 swamp_ast::FormatSpecifier::Float(node) => FormatSpecifier {
2457 node: self.to_node(node),
2458 kind: FormatSpecifierKind::Float,
2459 },
2460 swamp_ast::FormatSpecifier::Precision(value, node, x) => {
2461 let (precision_type, precision_node) = match x {
2462 swamp_ast::PrecisionType::Float(node) => {
2463 (PrecisionType::Float, self.to_node(node))
2464 }
2465 swamp_ast::PrecisionType::String(node) => {
2466 (PrecisionType::String, self.to_node(node))
2467 }
2468 };
2469 FormatSpecifier {
2470 node: self.to_node(node),
2471 kind: FormatSpecifierKind::Precision(
2472 *value,
2473 precision_node,
2474 precision_type,
2475 ),
2476 }
2477 }
2478 },
2479 };
2480
2481 Some(f)
2482 }
2483
2484 fn analyze_with_expr(
2485 &mut self,
2486 context: &TypeContext,
2487 variables: &[swamp_ast::VariableBinding],
2488 expression: &swamp_ast::Expression,
2489 ) -> Expression {
2490 let mut variable_expressions = Vec::new();
2491
2492 for variable in variables {
2493 let any_context = TypeContext::new_anything_argument(false);
2494 let must_have_expression = if let Some(x) = &variable.expression {
2495 x
2496 } else {
2497 &swamp_ast::Expression {
2498 kind: swamp_ast::ExpressionKind::VariableReference(variable.variable.clone()),
2499 node: variable.variable.name.clone(),
2500 }
2501 };
2502
2503 let location_side = if variable.variable.is_mutable.is_some() {
2505 if let Some(expr) = &variable.expression {
2507 let maybe_ref = self.analyze_maybe_ref_expression(expr);
2509 if maybe_ref.has_borrow_mutable_reference.is_some() {
2510 LocationSide::Mutable
2511 } else {
2512 LocationSide::Rhs
2513 }
2514 } else {
2515 LocationSide::Rhs
2517 }
2518 } else {
2519 LocationSide::Rhs
2521 };
2522
2523 let var = self.analyze_mut_or_immutable_expression(
2524 must_have_expression,
2525 &any_context,
2526 location_side,
2527 );
2528
2529 variable_expressions.push(var);
2530 }
2531
2532 self.push_closed_block_scope();
2533 let mut expressions = Vec::new();
2534 for (variable_binding, resolved_expression) in variables.iter().zip(variable_expressions) {
2535 let initialize_variable_expression = self
2536 .create_variable_binding_for_with(&variable_binding.variable, resolved_expression);
2537
2538 expressions.push(initialize_variable_expression);
2542 }
2543
2544 let resolved_expression = self.analyze_expression(expression, context);
2545 let block_type = self.types().unit();
2547 expressions.push(resolved_expression);
2548
2549 let block_expression_kind = ExpressionKind::Block(expressions);
2550 self.pop_closed_block_scope();
2551
2552 self.create_expr(block_expression_kind, block_type, &expression.node)
2553 }
2554
2555 fn analyze_when_expr(
2556 &mut self,
2557 context: &TypeContext,
2558 variables: &[swamp_ast::VariableBinding],
2559 true_expr: &swamp_ast::Expression,
2560 else_expr: Option<&swamp_ast::Expression>,
2561 ) -> Expression {
2562 self.push_block_scope("when");
2564 let mut bindings = Vec::new();
2565 for variable_binding in variables {
2566 let mut_expr = if let Some(found_expr) = &variable_binding.expression {
2567 let any_context = TypeContext::new_anything_argument(true); self.analyze_mut_or_immutable_expression(
2569 found_expr,
2570 &any_context,
2571 LocationSide::Rhs,
2572 )
2573 .expect_immutable()
2574 .unwrap()
2575 } else {
2576 let same_var = self.find_variable(&variable_binding.variable);
2577
2578 let generated_expr_kind = ExpressionKind::VariableAccess(same_var.clone());
2581 self.create_expr(
2582 generated_expr_kind,
2583 same_var.resolved_type.clone(),
2584 &variable_binding.variable.name,
2585 )
2586 };
2587
2588 let tk = &mut_expr.ty.kind;
2589
2590 if let TypeKind::Optional(found_ty) = &**tk {
2591 let variable_ref = { self.create_variable(&variable_binding.variable, found_ty)
2596 };
2599
2600 let binding = WhenBinding {
2601 variable: variable_ref,
2602 expr: mut_expr,
2603 };
2604 bindings.push(binding);
2605 } else {
2606 return self.create_err(ErrorKind::ExpectedOptional, &true_expr.node);
2607 }
2608 }
2609
2610 let resolved_true = self.analyze_expression(true_expr, context);
2611 let block_type = resolved_true.ty.clone();
2612
2613 self.pop_block_scope("when");
2614
2615 let maybe_resolved_else = if let Some(found_else) = else_expr {
2616 let block_type_for_true_context = context.we_know_expected_type(&block_type, false);
2617 Some(Box::new(self.analyze_expression(
2618 found_else,
2619 &block_type_for_true_context,
2620 )))
2621 } else {
2622 None
2623 };
2624
2625 let when_kind =
2626 ExpressionKind::When(bindings, Box::from(resolved_true), maybe_resolved_else);
2627
2628 self.create_expr(when_kind, block_type, &true_expr.node)
2629 }
2630
2631 fn analyze_guard(
2632 &mut self,
2633 node: &swamp_ast::Node,
2634 context: &TypeContext,
2635 guard_expressions: &Vec<swamp_ast::GuardExpr>,
2636 ) -> Expression {
2637 let mut guards = Vec::new();
2638 let mut found_wildcard = None;
2639 let mut detected_type = context.expected_type.cloned();
2640
2641 for guard in guard_expressions {
2642 let resolved_condition = match &guard.clause {
2643 swamp_ast::GuardClause::Wildcard(x) => {
2644 if found_wildcard.is_some() {
2645 return self.create_err(ErrorKind::GuardCanNotHaveMultipleWildcards, node);
2646 }
2647 found_wildcard = Some(x);
2648 None
2649 }
2650 swamp_ast::GuardClause::Expression(clause_expr) => {
2651 if found_wildcard.is_some() {
2652 return self.create_err(ErrorKind::WildcardMustBeLastInGuard, node);
2653 }
2654 Some(self.analyze_bool_argument_expression(clause_expr))
2655 }
2656 };
2657
2658 let resolved_result = self.analyze_expression(
2659 &guard.result,
2660 &context.with_expected_type(detected_type.as_ref(), false),
2661 );
2662 let ty = resolved_result.ty.clone();
2663 if detected_type.is_none() {
2664 detected_type = Some(ty.clone());
2665 }
2666
2667 guards.push(Guard {
2668 condition: resolved_condition,
2669 result: resolved_result,
2670 });
2671 }
2672
2673 if found_wildcard.is_none() {
2674 return self.create_err(ErrorKind::GuardMustHaveWildcard, node);
2675 }
2676
2677 let kind = ExpressionKind::Guard(guards);
2678
2679 if let Some(found_expecting_type) = detected_type {
2680 self.create_expr(kind, found_expecting_type, node)
2681 } else {
2682 self.create_err(ErrorKind::GuardHasNoType, node)
2683 }
2684 }
2685
2686 fn analyze_lambda(
2687 &mut self,
2688 node: &swamp_ast::Node,
2689 variables: &[swamp_ast::Variable],
2690 ast_expr: &swamp_ast::Expression,
2691 context: &TypeContext,
2692 ) -> Expression {
2693 let TypeKind::Function(signature) = &*context.expected_type.unwrap().kind else {
2694 return self.create_err(ErrorKind::ExpectedLambda, node);
2695 };
2696
2697 let return_block_type = TypeContext::new_argument(&signature.return_type, false);
2698
2699 self.push_lambda_scope("lambda");
2702
2703 let arity_required = signature.parameters.len();
2704 let variable_types_to_create = if variables.len() == arity_required {
2705 &signature.parameters
2706 } else if variables.len() + 1 == arity_required {
2707 &signature.parameters[1..].to_vec()
2708 } else {
2709 return self.create_err(ErrorKind::WrongNumberOfArguments(0, 0), node);
2710 };
2711
2712 let mut resolved_variables = Vec::new();
2713 for (variable, variable_type) in variables.iter().zip(variable_types_to_create) {
2714 let variable_ref = self.create_local_variable(
2715 &variable.name,
2716 variable.is_mutable.as_ref(),
2717 &variable_type.resolved_type,
2718 false,
2719 );
2720 resolved_variables.push(variable_ref);
2721 }
2722
2723 let analyzed_expression = self.analyze_expression(ast_expr, &return_block_type);
2726
2727 self.pop_block_scope("lambda");
2728
2729 let function_type = self.types().function(signature.clone());
2730 self.create_expr(
2731 ExpressionKind::Lambda(resolved_variables, Box::new(analyzed_expression)),
2732 function_type,
2733 node,
2734 )
2735 }
2736
2737 #[must_use]
2738 pub fn chain_is_owned_result(
2739 start_of_chain: &StartOfChain,
2740 chains: &Vec<Postfix>,
2741 ) -> (bool, bool) {
2742 let mut is_owned_result = matches!(start_of_chain.kind, StartOfChainKind::Expression(_));
2743 let mut is_mutable = if let StartOfChainKind::Variable(var) = &start_of_chain.kind {
2744 var.is_mutable()
2745 } else {
2746 false
2747 };
2748
2749 for chain in chains {
2750 match chain.kind {
2751 PostfixKind::StructField(_, _) => {
2752 is_owned_result = false;
2753 }
2754 PostfixKind::MemberCall(_, _) => {
2755 is_owned_result = true;
2756 is_mutable = false;
2757 }
2758 PostfixKind::OptionalChainingOperator => {
2759 is_owned_result = true;
2760 is_mutable = false;
2761 }
2762 PostfixKind::VecSubscript(_, _) => {}
2763 PostfixKind::VecSubscriptRange(_, _) => {}
2764 PostfixKind::SparseSubscript(_, _) => {}
2765 PostfixKind::GridSubscript(_, _, _) => {}
2766 PostfixKind::MapSubscript(_, _) => {}
2767 }
2768 }
2769
2770 (is_owned_result, is_mutable)
2771 }
2772
2773 pub fn check_assignment_mode(
2774 &mut self,
2775 lhs_is_mutable: bool,
2776 source_expression: &Expression,
2777 ty: &TypeRef,
2778 ) -> AssignmentMode {
2779 if matches!(
2780 &source_expression.kind,
2781 _ | ExpressionKind::IntrinsicCallEx(_, _)
2782 ) {
2783 return AssignmentMode::OwnedValue;
2784 }
2785
2786 if let ExpressionKind::PostfixChain(start_chain, postfix) = &source_expression.kind {
2794 let (chain_is_owned, chain_is_mutable) =
2795 Self::chain_is_owned_result(start_chain, postfix);
2796 if lhs_is_mutable {
2797 return if chain_is_mutable {
2798 AssignmentMode::CopyBlittable
2799 } else if lhs_is_mutable {
2800 if chain_is_owned {
2801 AssignmentMode::OwnedValue
2802 } else {
2803 AssignmentMode::CopyBlittable
2804 }
2805 } else {
2806 AssignmentMode::CopySharedPtr
2807 };
2808 }
2809 }
2811
2812 AssignmentMode::CopyBlittable
2813 }
2814
2815 pub const fn check_mutable_assignment(&mut self, assignment_mode: AssignmentMode, node: &Node) {}
2816
2817 pub const fn check_mutable_variable_assignment(
2818 &mut self,
2819 source_expression: &swamp_ast::Expression,
2820 ty: &TypeRef,
2821 variable: &swamp_ast::Variable,
2822 ) {
2823 }
2829
2830 pub fn analyze_variable_definition(
2833 &mut self,
2834 variable: &swamp_ast::Variable,
2835 annotation_type: &Option<swamp_ast::Type>,
2836 source_expression: &swamp_ast::Expression,
2837 ) -> Expression {
2838 let maybe_found_variable = self.try_find_variable(&variable.name);
2839 if maybe_found_variable.is_some() {
2840 return self.create_err(ErrorKind::OverwriteVariableNotAllowedHere, &variable.name);
2841 }
2842
2843 let node = self.to_node(&variable.name);
2844
2845 let Some(variable_slot) = self.reserve_slot(&node) else {
2846 return self.create_err(ErrorKind::OutOfVirtualRegisters, &variable.name);
2847 };
2848
2849 let maybe_annotated_type = annotation_type.as_ref().map(|found_ast_type| {
2850 self.analyze_type(found_ast_type, &TypeAnalyzeContext::default())
2851 });
2852
2853 self.common_variable_util(
2854 VariableResolution::ReservedSlot(variable_slot, variable.clone(), maybe_annotated_type),
2855 &variable.name,
2856 source_expression,
2857 )
2858 }
2859
2860 pub fn analyze_variable_assignment(
2863 &mut self,
2864 variable: &swamp_ast::Variable,
2865 source_expression: &swamp_ast::Expression,
2866 ) -> Expression {
2867 let maybe_found_variable = self.try_find_variable(&variable.name);
2868
2869 let node = self.to_node(&variable.name);
2870 let resolution = if let Some(found_var) = maybe_found_variable {
2871 VariableResolution::ExistingVariable(found_var)
2872 } else {
2873 let Some(variable_slot) = self.reserve_slot(&node) else {
2874 return self.create_err(ErrorKind::OutOfVirtualRegisters, &variable.name);
2875 };
2876
2877 VariableResolution::ReservedSlot(variable_slot, variable.clone(), None)
2878 };
2879
2880 self.common_variable_util(resolution, &variable.name, source_expression)
2881 }
2882
2883 pub fn common_variable_util(
2884 &mut self,
2885 variable_resolution: VariableResolution,
2886 ast_node: &swamp_ast::Node,
2887 source_expression: &swamp_ast::Expression,
2888 ) -> Expression {
2889 let node = self.to_node(ast_node);
2890
2891 let maybe_annotated_type = match &variable_resolution {
2892 VariableResolution::ExistingVariable(existing_var) => {
2893 Some(existing_var.resolved_type.clone())
2894 }
2895 VariableResolution::ReservedSlot(_, _, maybe_annotated) => maybe_annotated.clone(),
2896 };
2897
2898 let (final_variable_type, final_source_expression) =
2899 self.resolve_variable_expression(maybe_annotated_type, source_expression);
2900
2901 let variable_type = match &variable_resolution {
2902 VariableResolution::ExistingVariable(existing) => existing.variable_type.clone(),
2903 VariableResolution::ReservedSlot(_, _, _) => VariableType::Local,
2904 };
2905
2906 let debug_text = self.get_text(ast_node);
2907 let unused_var = debug_text.starts_with('_');
2908
2909 if !unused_var {
2910 match variable_type {
2912 VariableType::Local => {
2913 if !final_variable_type.can_be_stored_in_variable() {
2914 return self.create_err_resolved(
2915 ErrorKind::VariableTypeMustBeAtLeastTransient(final_variable_type),
2916 &node,
2917 );
2918 }
2919 }
2920
2921 VariableType::Parameter => {
2922 if !final_variable_type.allowed_as_return_type() {
2923 return self.create_err_resolved(
2924 ErrorKind::VariableTypeMustBeAtLeastTransient(final_variable_type),
2925 &node,
2926 );
2927 }
2928 }
2929 }
2930 }
2931
2932 let kind = match variable_resolution {
2933 VariableResolution::ExistingVariable(found_variable) => {
2934 self.shared
2935 .state
2936 .refs
2937 .add(found_variable.symbol_id.into(), node.clone());
2938 self.shared
2939 .definition_table
2940 .refs
2941 .add(found_variable.symbol_id.into(), node.clone());
2942
2943 ExpressionKind::VariableReassignment(
2944 found_variable,
2945 Box::from(final_source_expression),
2946 )
2947 }
2948 VariableResolution::ReservedSlot(reserved_slot, ast_variable, maybe_annotated) => {
2949 let final_type = if let Some(annotated_type) = maybe_annotated {
2950 annotated_type
2951 } else {
2952 final_source_expression.ty.clone()
2953 };
2954
2955 let (found_variable, _some_string) = self.create_local_variable_with_reserved_slot(
2956 reserved_slot,
2957 ast_variable,
2958 &final_type,
2959 );
2960 ExpressionKind::VariableDefinition(
2961 found_variable,
2962 Box::from(final_source_expression),
2963 )
2964 }
2965 };
2966
2967 let unit_type = self.shared.state.types.unit();
2968 self.create_expr(kind, unit_type, ast_node)
2969 }
2970
2971 pub fn resolve_variable_expression(
2974 &mut self,
2975 maybe_annotated_type: Option<TypeRef>,
2976 source_expression: &swamp_ast::Expression,
2977 ) -> (TypeRef, Expression) {
2978 let source_expr = if let Some(target_type) = &maybe_annotated_type {
2979 self.analyze_expression_for_assignment_with_target_type(target_type, source_expression)
2980 } else {
2981 let any_type_context = TypeContext::new_anything_argument(true);
2982 self.analyze_expression(source_expression, &any_type_context)
2983 };
2984
2985 let determined_variable_type = if let Some(found_type) = &maybe_annotated_type {
2988 found_type
2989 } else {
2990 &source_expr.ty.clone()
2991 };
2992
2993 (determined_variable_type.clone(), source_expr)
2996 }
2997
2998 fn add_location_item(
3118 &mut self,
3119 vec: &mut Vec<LocationAccess>,
3120 kind: LocationAccessKind,
3121 ty: TypeRef,
3122 ast_node: &swamp_ast::Node,
3123 ) {
3124 let resolved_node = self.to_node(ast_node);
3125 let postfix = LocationAccess {
3126 node: resolved_node,
3127 ty,
3128 kind,
3129 };
3130
3131 vec.push(postfix);
3132 }
3133
3134 fn extract_single_intrinsic_call(
3135 body: &Expression,
3136 ) -> Option<(IntrinsicFunction, Vec<ArgumentExpression>)> {
3137 if let ExpressionKind::Block(expressions) = &body.kind {
3138 let first_kind = &expressions[0].kind;
3139 if let ExpressionKind::IntrinsicCallEx(intrinsic_fn, args) = &first_kind {
3140 return Some((intrinsic_fn.clone(), args.clone()));
3141 }
3142 }
3143 None
3144 }
3145
3146 #[allow(clippy::too_many_lines)]
3147 fn analyze_chain_to_location(
3148 &mut self,
3149 chain: &swamp_ast::PostfixChain,
3150 context: &TypeContext,
3151 location_side: LocationSide,
3152 ) -> SingleLocationExpression {
3153 let mut items = Vec::new();
3154
3155 let nothing_context = TypeContext::new(None, true);
3156
3157 let base_expr = self.analyze_expression(&chain.base, ¬hing_context);
3158 let ExpressionKind::VariableAccess(start_variable) = base_expr.kind else {
3159 self.add_err(ErrorKind::NotValidLocationStartingPoint, &chain.base.node);
3160 let unit_type = self.types().unit();
3161 let err_variable = Variable {
3162 symbol_id: ScopedSymbolId::new_illegal(),
3163 name: Default::default(),
3164 assigned_name: String::new(),
3165 resolved_type: unit_type,
3166 mutable_node: None,
3167 variable_type: VariableType::Local,
3168 scope_index: 0,
3169 variable_index: 0,
3170 unique_id_within_function: 0,
3171 virtual_register: 0,
3172 is_unused: false,
3173 };
3174 return SingleLocationExpression {
3175 kind: MutableReferenceKind::MutVariableRef,
3176 node: self.to_node(&chain.base.node),
3177 ty: self.shared.state.types.unit(),
3178 starting_variable: VariableRef::from(err_variable),
3179 access_chain: vec![],
3180 };
3181 };
3182
3183 if !start_variable.is_mutable() {
3184 self.add_err(ErrorKind::VariableIsNotMutable, &chain.base.node);
3185
3186 let unit_type = self.types().unit();
3187 let err_variable = Variable {
3188 symbol_id: ScopedSymbolId::new_illegal(),
3189 name: Default::default(),
3190 assigned_name: String::new(),
3191 resolved_type: unit_type,
3192 mutable_node: None,
3193 variable_type: VariableType::Local,
3194 scope_index: 0,
3195 variable_index: 0,
3196 unique_id_within_function: 0,
3197 virtual_register: 0,
3198 is_unused: false,
3199 };
3200 return SingleLocationExpression {
3201 kind: MutableReferenceKind::MutVariableRef,
3202 node: self.to_node(&chain.base.node),
3203 ty: self.shared.state.types.unit(),
3204 starting_variable: VariableRef::from(err_variable),
3205 access_chain: vec![],
3206 };
3207 }
3208
3209 let mut ty = start_variable.resolved_type.clone();
3210 for (i, item) in chain.postfixes.iter().enumerate() {
3211 let is_absolute_last_in_chain = i == chain.postfixes.len() - 1;
3212 match &item {
3213 swamp_ast::Postfix::FieldAccess(field_name_node) => {
3214 let (struct_type_ref, index, return_type) =
3216 self.analyze_struct_field(field_name_node, &ty);
3217
3218 self.add_location_item(
3219 &mut items,
3220 LocationAccessKind::FieldIndex(struct_type_ref.clone(), index),
3221 return_type.clone(),
3222 field_name_node,
3223 );
3224
3225 ty = return_type.clone();
3226 }
3227 swamp_ast::Postfix::SubscriptTuple(x_expr, y_expr) => match &*ty.kind {
3228 TypeKind::GridView(element_type)
3229 | TypeKind::GridStorage(element_type, _, _) => {
3230 let int_type = self.types().int();
3231 let unsigned_int_context = TypeContext::new_argument(&int_type, true);
3232 let unsigned_int_x_expr =
3233 self.analyze_expression(x_expr, &unsigned_int_context);
3234
3235 let unsigned_int_y_expr =
3236 self.analyze_expression(y_expr, &unsigned_int_context);
3237
3238 let grid_type = GridType {
3239 element: element_type.clone(),
3240 };
3241
3242 self.add_location_item(
3243 &mut items,
3244 LocationAccessKind::GridSubscript(
3245 grid_type,
3246 unsigned_int_x_expr,
3247 unsigned_int_y_expr,
3248 ),
3249 element_type.clone(),
3250 &x_expr.node,
3251 );
3252
3253 ty = element_type.clone();
3254 }
3255 _ => {
3256 self.add_err_resolved(
3257 ErrorKind::CanNotSubscriptWithThatType,
3258 &base_expr.node,
3259 );
3260
3261 return SingleLocationExpression {
3262 kind: MutableReferenceKind::MutVariableRef,
3263 node: Default::default(),
3264 ty,
3265 starting_variable: Rc::new(Variable {
3266 symbol_id: ScopedSymbolId::new_illegal(),
3267 name: Default::default(),
3268 assigned_name: String::new(),
3269 resolved_type: Rc::new(Type {
3270 id: TypeId::new(0),
3271 flags: Default::default(),
3272 kind: Rc::new(TypeKind::Byte),
3273 }),
3274 mutable_node: None,
3275 variable_type: VariableType::Local,
3276 scope_index: 0,
3277 variable_index: 0,
3278 unique_id_within_function: 0,
3279 virtual_register: 0,
3280 is_unused: false,
3281 }),
3282 access_chain: vec![],
3283 };
3284 }
3285 },
3286 swamp_ast::Postfix::Subscript(ast_key_expression) => {
3287 let underlying = &ty.kind;
3288 match &**underlying {
3289 TypeKind::SliceView(element_type)
3290 | TypeKind::StackStorage(element_type, _)
3291 | TypeKind::StackView(element_type)
3292 | TypeKind::VecStorage(element_type, _)
3293 | TypeKind::DynamicLengthVecView(element_type)
3294 | TypeKind::FixedCapacityAndLengthArray(element_type, _) => {
3295 let int_type = self.types().int();
3296 let unsigned_int_context = TypeContext::new_argument(&int_type, false);
3297 let unsigned_int_expr =
3298 self.analyze_expression(ast_key_expression, &unsigned_int_context);
3299
3300 let slice_type = SliceViewType {
3301 element: element_type.clone(),
3302 };
3303
3304 self.add_location_item(
3305 &mut items,
3306 LocationAccessKind::SliceViewSubscript(
3307 slice_type,
3308 unsigned_int_expr,
3309 ),
3310 element_type.clone(),
3311 &ast_key_expression.node,
3312 );
3313
3314 ty = element_type.clone();
3315 }
3316 TypeKind::SparseView(element_type)
3317 | TypeKind::SparseStorage(element_type, _) => {
3318 let int_type = self.types().int();
3319 let unsigned_int_context = TypeContext::new_argument(&int_type, false);
3320 let unsigned_int_expr =
3321 self.analyze_expression(ast_key_expression, &unsigned_int_context);
3322
3323 let slice_type = SparseType {
3324 element: element_type.clone(),
3325 };
3326
3327 self.add_location_item(
3328 &mut items,
3329 LocationAccessKind::SparseSubscript(slice_type, unsigned_int_expr),
3330 element_type.clone(),
3331 &ast_key_expression.node,
3332 );
3333
3334 ty = element_type.clone();
3335 }
3336 TypeKind::MapStorage(key_type, value_type, ..)
3337 | TypeKind::DynamicLengthMapView(key_type, value_type) => {
3338 let key_index_context = TypeContext::new_argument(key_type, false);
3339 let key_expr =
3340 self.analyze_expression(ast_key_expression, &key_index_context);
3341
3342 let map_like_type = MapType {
3343 key: key_type.clone(),
3344 value: value_type.clone(),
3345 };
3346
3347 match location_side {
3348 LocationSide::Lhs => {
3349 let access_kind = if is_absolute_last_in_chain {
3353 LocationAccessKind::MapSubscriptCreateIfNeeded(
3354 map_like_type,
3355 key_expr,
3356 )
3357 } else {
3358 LocationAccessKind::MapSubscriptMustExist(
3359 map_like_type,
3360 key_expr,
3361 )
3362 };
3363
3364 self.add_location_item(
3365 &mut items,
3366 access_kind,
3367 value_type.clone(),
3368 &ast_key_expression.node,
3369 );
3370 }
3371 LocationSide::Mutable | LocationSide::Rhs => {
3372 self.add_location_item(
3373 &mut items,
3374 LocationAccessKind::MapSubscriptMustExist(
3375 map_like_type,
3376 key_expr,
3377 ),
3378 value_type.clone(),
3379 &ast_key_expression.node,
3380 );
3381 }
3382 }
3383 ty = value_type.clone();
3384 }
3385
3386 _ => {
3387 self.add_err_resolved(
3388 ErrorKind::CanNotSubscriptWithThatType,
3389 &base_expr.node,
3390 );
3391
3392 return SingleLocationExpression {
3393 kind: MutableReferenceKind::MutVariableRef,
3394 node: Default::default(),
3395 ty,
3396 starting_variable: Rc::new(Variable {
3397 symbol_id: ScopedSymbolId::new_illegal(),
3398 name: Default::default(),
3399 assigned_name: String::new(),
3400 resolved_type: Rc::new(Type {
3401 id: TypeId::new(0),
3402 flags: Default::default(),
3403 kind: Rc::new(TypeKind::Byte),
3404 }),
3405 mutable_node: None,
3406 variable_type: VariableType::Local,
3407 scope_index: 0,
3408 variable_index: 0,
3409 unique_id_within_function: 0,
3410 virtual_register: 0,
3411 is_unused: false,
3412 }),
3413 access_chain: vec![],
3414 };
3415 }
3416 }
3417 }
3418
3419 swamp_ast::Postfix::MemberCall(node, _generic_arguments, _regular_args) => {
3420 return SingleLocationExpression {
3421 kind: MutableReferenceKind::MutVariableRef,
3422 node: self.to_node(node),
3423 ty: self.shared.state.types.unit(),
3424 starting_variable: start_variable,
3425 access_chain: vec![],
3426 };
3427 }
3428 swamp_ast::Postfix::FunctionCall(node, _generic_arguments, _regular_args) => {
3435 return SingleLocationExpression {
3436 kind: MutableReferenceKind::MutVariableRef,
3437 node: self.to_node(node),
3438 ty: self.shared.state.types.unit(),
3439 starting_variable: start_variable,
3440 access_chain: vec![],
3441 };
3442 }
3443 swamp_ast::Postfix::OptionalChainingOperator(node) => {
3444 return SingleLocationExpression {
3445 kind: MutableReferenceKind::MutVariableRef,
3446 node: self.to_node(node),
3447 ty: self.shared.state.types.unit(),
3448 starting_variable: start_variable,
3449 access_chain: vec![],
3450 };
3451 }
3452 }
3453 }
3454
3455 if let Some(found_expected_type) = context.expected_type
3456 && !self.types().compatible_with(found_expected_type, &ty)
3457 {
3458 self.add_err(
3459 ErrorKind::IncompatibleTypes {
3460 expected: found_expected_type.clone(),
3461 found: ty.clone(),
3462 },
3463 &chain.base.node,
3464 );
3465 }
3466
3467 SingleLocationExpression {
3468 kind: MutableReferenceKind::MutVariableRef,
3469 node: self.to_node(&chain.base.node),
3470 ty,
3471 starting_variable: start_variable,
3472 access_chain: items,
3473 }
3474 }
3475
3476 fn analyze_to_location(
3477 &mut self,
3478 expr: &swamp_ast::Expression,
3479 context: &TypeContext,
3480 location_type: LocationSide,
3481 ) -> SingleLocationExpression {
3482 match &expr.kind {
3483 swamp_ast::ExpressionKind::PostfixChain(chain) => {
3484 self.analyze_chain_to_location(chain, context, location_type)
3485 }
3486 swamp_ast::ExpressionKind::VariableReference(variable) => {
3487 let var = self.find_variable(variable);
3488 if !var.is_mutable() {
3489 self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
3490 }
3491
3492 let name_node = self.to_node(&variable.name);
3493 self.shared
3494 .state
3495 .refs
3496 .add(var.symbol_id.into(), name_node.clone());
3497 self.shared
3498 .definition_table
3499 .refs
3500 .add(var.symbol_id.into(), name_node.clone());
3501
3502 SingleLocationExpression {
3503 kind: MutableReferenceKind::MutVariableRef,
3504 node: name_node,
3505 ty: var.resolved_type.clone(),
3506 starting_variable: var,
3507 access_chain: vec![],
3508 }
3509 }
3510 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
3511 let generated_var = swamp_ast::Variable {
3512 name: qualified_identifier.name.clone(),
3513 is_mutable: None,
3514 };
3515 let var = self.find_variable(&generated_var);
3516 if !var.is_mutable() {
3517 self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
3518 }
3519
3520 let var_node = self.to_node(&generated_var.name);
3521 self.shared
3522 .state
3523 .refs
3524 .add(var.symbol_id.into(), var_node.clone());
3525 self.shared
3526 .definition_table
3527 .refs
3528 .add(var.symbol_id.into(), var_node.clone());
3529
3530 SingleLocationExpression {
3531 kind: MutableReferenceKind::MutVariableRef,
3532 node: var_node,
3533 ty: var.resolved_type.clone(),
3534 starting_variable: var,
3535 access_chain: vec![],
3536 }
3537 }
3538 _ => {
3539 self.add_err(ErrorKind::NotValidLocationStartingPoint, &expr.node);
3540 let unit_type = self.types().unit();
3541 SingleLocationExpression {
3542 kind: MutableReferenceKind::MutVariableRef,
3543 node: self.to_node(&expr.node),
3544 ty: unit_type.clone(),
3545 starting_variable: Rc::new(Variable {
3546 symbol_id: ScopedSymbolId::new_illegal(),
3547 name: Default::default(),
3548 assigned_name: String::new(),
3549 resolved_type: unit_type,
3550 mutable_node: None,
3551 variable_type: VariableType::Local,
3552 scope_index: 0,
3553 variable_index: 0,
3554 unique_id_within_function: 0,
3555 virtual_register: 0,
3556 is_unused: false,
3557 }),
3558 access_chain: vec![],
3559 }
3560 }
3561 }
3562 }
3563
3564 fn analyze_expression_for_assignment_compound(
3565 &mut self,
3566 target_expression: &swamp_ast::Expression,
3567 ast_source_expression: &swamp_ast::Expression,
3568 ) -> (TargetAssignmentLocation, Expression) {
3569 let any_argument_context = TypeContext::new_anything_argument(true);
3570 let source_expr = self.analyze_expression(ast_source_expression, &any_argument_context);
3571 let source_expr_type_context = TypeContext::new_argument(&source_expr.ty, true);
3572
3573 let resolved_location = TargetAssignmentLocation(self.analyze_to_location(
3574 target_expression,
3575 &source_expr_type_context,
3576 LocationSide::Rhs,
3577 ));
3578
3579 (resolved_location, source_expr)
3580 }
3581
3582 fn analyze_expression_for_assignment_with_target_type(
3609 &mut self,
3610 target_type: &TypeRef,
3611 ast_source_expression: &swamp_ast::Expression,
3612 ) -> Expression {
3613 let base_context = TypeContext::new_argument(target_type, true);
3614 let source_expr = self.analyze_expression(ast_source_expression, &base_context);
3615
3616 let final_expr = if self.types().compatible_with(target_type, &source_expr.ty) {
3617 source_expr
3618 } else {
3619 let source_type = source_expr.ty.clone();
3620 self.types_did_not_match_try_late_coerce_expression(
3621 source_expr,
3622 target_type,
3623 &source_type,
3624 &ast_source_expression.node,
3625 )
3626 };
3627
3628 let assignment_mode = self.check_assignment_mode(true, &final_expr, target_type); self.check_mutable_assignment(assignment_mode, &final_expr.node);
3631
3632 final_expr
3633 }
3634
3635 fn analyze_expression_for_assignment(
3636 &mut self,
3637 ast_target_location_expression: &swamp_ast::Expression,
3638 ast_source_expression: &swamp_ast::Expression,
3639 ) -> (TargetAssignmentLocation, Expression) {
3640 self.push_block_scope("fake outer scope to keep lvalue alive");
3641 let any_argument_context = TypeContext::new_anything_argument(true);
3642 let resolved_location = self.analyze_to_location(
3643 ast_target_location_expression,
3644 &any_argument_context,
3645 LocationSide::Lhs,
3646 );
3647
3648 self.push_block_scope("fake scope to keep lvalue alive");
3649 let target_type = resolved_location.ty.clone();
3650 let mut_type = target_type; let mut_location = TargetAssignmentLocation(resolved_location);
3652
3653 let final_expr = self
3654 .analyze_expression_for_assignment_with_target_type(&mut_type, ast_source_expression);
3655 self.pop_block_scope("fake scope for lvalue alive");
3656 self.pop_block_scope("fake outer scope for lvalue alive");
3657
3658 (mut_location, final_expr)
3659 }
3660
3661 fn analyze_assignment_compound(
3662 &mut self,
3663 target_expression: &swamp_ast::Expression,
3664 ast_op: &swamp_ast::CompoundOperator,
3665 ast_source_expression: &swamp_ast::Expression,
3666 ) -> Expression {
3667 let resolved_op = self.analyze_compound_operator(ast_op);
3668
3669 let (resolved_location, source_expr) = self
3670 .analyze_expression_for_assignment_compound(target_expression, ast_source_expression);
3671
3672 let kind = ExpressionKind::CompoundAssignment(
3673 resolved_location,
3674 resolved_op.kind,
3675 Box::from(source_expr),
3676 );
3677
3678 let unit_type = self.shared.state.types.unit();
3679
3680 self.create_expr(kind, unit_type, &target_expression.node)
3681 }
3682
3683 fn analyze_assignment_mode(lhs: SingleLocationExpression) {}
3684
3685 fn analyze_assignment(
3686 &mut self,
3687 target_location: &swamp_ast::Expression,
3688 ast_source_expression: &swamp_ast::Expression,
3689 ) -> Expression {
3690 let (mut_location, source_expr) =
3691 self.analyze_expression_for_assignment(target_location, ast_source_expression);
3692 let kind = ExpressionKind::Assignment(Box::from(mut_location), Box::from(source_expr));
3693 let unit_type = self.shared.state.types.unit();
3694
3695 self.create_expr(kind, unit_type, &target_location.node)
3698 }
3699
3700 #[must_use]
3701 pub const fn create_expr(
3702 &self,
3703 kind: ExpressionKind,
3704 ty: TypeRef,
3705 ast_node: &swamp_ast::Node,
3706 ) -> Expression {
3707 Expression {
3709 kind,
3710 ty,
3711 node: self.to_node(ast_node),
3712 }
3713 }
3714
3715 fn analyze_destructuring(
3716 &mut self,
3717 node: &swamp_ast::Node,
3718 target_ast_variables: &[swamp_ast::Variable],
3719 tuple_expression: &swamp_ast::Expression,
3720 ) -> Expression {
3721 let any_context = TypeContext::new_anything_argument(true);
3722 let tuple_resolved = self.analyze_expression(tuple_expression, &any_context);
3723 let tuple_expr_type = &tuple_resolved.ty;
3724 let unit = self.types().unit();
3725
3726 let mut variable_refs = Vec::new();
3727 if let TypeKind::Tuple(tuple) = &*tuple_expr_type.kind {
3728 if target_ast_variables.len() > tuple.len() {
3729 return self.create_err(ErrorKind::TooManyDestructureVariables, node);
3730 }
3731 for (ast_variable, tuple_type) in target_ast_variables.iter().zip(tuple.clone()) {
3732 let variable_ref = self.create_local_variable(
3733 &ast_variable.name,
3734 ast_variable.is_mutable.as_ref(),
3735 &tuple_type,
3736 true,
3737 );
3738 variable_refs.push(variable_ref);
3739 }
3740 let expr_kind = ExpressionKind::TupleDestructuring(
3741 variable_refs,
3742 tuple_expr_type.clone(),
3743 Box::from(tuple_resolved),
3744 );
3745
3746 self.create_expr(expr_kind, unit, node)
3747 } else {
3748 self.create_err(ErrorKind::CanNotDestructure, node)
3749 }
3750 }
3751
3752 fn analyze_normal_member_call(
3753 &mut self,
3754 type_that_member_is_on: &TypeRef,
3755 found_function: &FunctionRef,
3756 generic_arguments: Vec<TypeRef>,
3757 ast_arguments: &[swamp_ast::Expression],
3758 is_mutable: bool,
3759 node: &swamp_ast::Node,
3760 ) -> Signature {
3761 let resolved_node = self.to_node(node);
3762 found_function.signature().clone()
3765 }
3766
3767 fn enum_member_signature(
3768 &mut self,
3769 self_type: &TypeRef,
3770 field_name_str: &str,
3771 node: &swamp_ast::Node,
3772 ) -> Option<(IntrinsicFunction, Signature)> {
3773 let self_type_param = TypeForParameter {
3774 name: "self".to_string(),
3775 resolved_type: self_type.clone(),
3776 is_mutable: false,
3777 node: None,
3778 };
3779
3780 let self_mutable_type_param = TypeForParameter {
3781 name: "self".to_string(),
3782 resolved_type: self_type.clone(),
3783 is_mutable: true,
3784 node: None,
3785 };
3786
3787 let intrinsic_and_signature = match field_name_str {
3788 "discriminant" => (
3789 IntrinsicFunction::EnumDiscriminant,
3790 Signature {
3791 parameters: vec![self_type_param],
3792 return_type: self.types().int(),
3793 },
3794 ),
3795
3796 "from_discriminant" => (
3797 IntrinsicFunction::EnumFromDiscriminant,
3798 Signature {
3799 parameters: vec![
3800 self_mutable_type_param,
3801 TypeForParameter {
3802 name: "discriminant".to_string(),
3803 resolved_type: self.types().int(),
3804 is_mutable: false,
3805 node: None,
3806 },
3807 ],
3808 return_type: self.types().unit(),
3809 },
3810 ),
3811 _ => {
3812 self.add_err(ErrorKind::UnknownMemberFunction(self_type.clone()), node);
3813
3814 return None;
3815 }
3816 };
3817
3818 Some(intrinsic_and_signature)
3819 }
3820
3821 fn queue_member_signature(
3822 &mut self,
3823 self_type: &TypeRef,
3824 key_type: Option<&TypeRef>,
3825 element_type: &TypeRef,
3826 field_name_str: &str,
3827 lambda_variable_count: usize,
3828 node: &swamp_ast::Node,
3829 ) -> Option<(IntrinsicFunction, Signature)> {
3830 let self_type_param = TypeForParameter {
3831 name: "self".to_string(),
3832 resolved_type: self_type.clone(),
3833 is_mutable: false,
3834 node: None,
3835 };
3836 let self_mutable_type_param = TypeForParameter {
3837 name: "self".to_string(),
3838 resolved_type: self_type.clone(),
3839 is_mutable: true,
3840 node: None,
3841 };
3842 let intrinsic_and_signature = match field_name_str {
3843 "enqueue" => (
3844 IntrinsicFunction::VecPush,
3845 Signature {
3846 parameters: vec![
3847 self_mutable_type_param,
3848 TypeForParameter {
3849 name: "element".to_string(),
3850 resolved_type: element_type.clone(),
3851 is_mutable: false,
3852 node: None,
3853 },
3854 ],
3855 return_type: self.types().unit(),
3856 },
3857 ),
3858 "dequeue" => (
3859 IntrinsicFunction::VecRemoveFirstIndexGetValue,
3860 Signature {
3861 parameters: vec![self_mutable_type_param],
3862 return_type: element_type.clone(),
3863 },
3864 ),
3865 _ => {
3866 self.slice_member_signature(
3867 self_type,
3868 key_type,
3869 element_type,
3870 field_name_str,
3871 lambda_variable_count,
3872 node,
3873 )
3874 }?,
3875 };
3876
3877 Some(intrinsic_and_signature)
3878 }
3879
3880 fn sparse_member_signature(
3881 &mut self,
3882 self_type: &TypeRef,
3883 element_type: &TypeRef,
3884 field_name_str: &str,
3885 lambda_variable_count: usize,
3886 node: &swamp_ast::Node,
3887 ) -> Option<(IntrinsicFunction, Signature)> {
3888 let key_type = self.types().int(); let self_type_param = TypeForParameter {
3891 name: "self".to_string(),
3892 resolved_type: self_type.clone(),
3893 is_mutable: false,
3894 node: None,
3895 };
3896 let self_mutable_type_param = TypeForParameter {
3897 name: "self".to_string(),
3898 resolved_type: self_type.clone(),
3899 is_mutable: true,
3900 node: None,
3901 };
3902 let intrinsic_and_signature = match field_name_str {
3903 "add" => (
3904 IntrinsicFunction::SparseAdd,
3905 Signature {
3906 parameters: vec![
3907 self_mutable_type_param,
3908 TypeForParameter {
3909 name: "element".to_string(),
3910 resolved_type: element_type.clone(),
3911 is_mutable: false,
3912 node: None,
3913 },
3914 ],
3915 return_type: self.types().int(),
3916 },
3917 ),
3918 "remove" => (
3919 IntrinsicFunction::SparseRemove,
3920 Signature {
3921 parameters: vec![
3922 self_mutable_type_param,
3923 TypeForParameter {
3924 name: "key".to_string(),
3925 resolved_type: key_type,
3926 is_mutable: false,
3927 node: None,
3928 },
3929 ],
3930 return_type: self.types().unit(),
3931 },
3932 ),
3933 "is_alive" => (
3934 IntrinsicFunction::SparseIsAlive,
3935 Signature {
3936 parameters: vec![
3937 self_type_param,
3938 TypeForParameter {
3939 name: "element".to_string(),
3940 resolved_type: element_type.clone(),
3941 is_mutable: false,
3942 node: None,
3943 },
3944 ],
3945 return_type: self.types().bool(),
3946 },
3947 ),
3948
3949 _ => {
3950 self.slice_member_signature(
3951 self_type,
3952 Option::from(key_type).as_ref(),
3953 element_type,
3954 field_name_str,
3955 lambda_variable_count,
3956 node,
3957 )
3958 }?,
3959 };
3960 Some(intrinsic_and_signature)
3961 }
3962
3963 fn vec_member_signature(
3964 &mut self,
3965 self_type: &TypeRef,
3966 element_type: &TypeRef,
3967 field_name_str: &str,
3968 lambda_variable_count: usize,
3969 node: &swamp_ast::Node,
3970 ) -> Option<(IntrinsicFunction, Signature)> {
3971 let key_type = self.types().int();
3972 let self_type_param = TypeForParameter {
3973 name: "self".to_string(),
3974 resolved_type: self_type.clone(),
3975 is_mutable: false,
3976 node: None,
3977 };
3978 let self_mutable_type_param = TypeForParameter {
3979 name: "self".to_string(),
3980 resolved_type: self_type.clone(),
3981 is_mutable: true,
3982 node: None,
3983 };
3984 let intrinsic_and_signature = match field_name_str {
3985 "prepend" => (
3986 IntrinsicFunction::VecPush,
3987 Signature {
3988 parameters: vec![
3989 self_mutable_type_param,
3990 TypeForParameter {
3991 name: "element".to_string(),
3992 resolved_type: element_type.clone(),
3993 is_mutable: false,
3994 node: None,
3995 },
3996 ],
3997 return_type: self.types().unit(),
3998 },
3999 ),
4000 "push" => (
4001 IntrinsicFunction::VecPush,
4002 Signature {
4003 parameters: vec![
4004 self_mutable_type_param,
4005 TypeForParameter {
4006 name: "element".to_string(),
4007 resolved_type: element_type.clone(),
4008 is_mutable: false,
4009 node: None,
4010 },
4011 ],
4012 return_type: self.types().unit(),
4013 },
4014 ),
4015 "extend" => (
4016 IntrinsicFunction::VecExtend,
4017 Signature {
4018 parameters: vec![
4019 self_mutable_type_param,
4020 TypeForParameter {
4021 name: "other_vec".to_string(),
4022 resolved_type: self.types().dynamic_vec_view(&element_type.clone()),
4023 is_mutable: false,
4024 node: None,
4025 },
4026 ],
4027 return_type: self.types().unit(),
4028 },
4029 ),
4030 "pop" => (
4031 IntrinsicFunction::VecPop,
4032 Signature {
4033 parameters: vec![self_mutable_type_param],
4034 return_type: element_type.clone(),
4035 },
4036 ),
4037
4038 "slice" => {
4039 let range_type = self.types().range_int();
4040 (
4041 IntrinsicFunction::VecSlice,
4042 Signature {
4043 parameters: vec![
4044 self_type_param,
4045 TypeForParameter {
4046 name: "range".to_string(),
4047 resolved_type: range_type,
4048 is_mutable: false,
4049 node: None,
4050 },
4051 ],
4052 return_type: self_type.clone(),
4053 },
4054 )
4055 }
4056
4057 _ => {
4058 self.slice_member_signature(
4059 self_type,
4060 Option::from(key_type).as_ref(),
4061 element_type,
4062 field_name_str,
4063 lambda_variable_count,
4064 node,
4065 )
4066 }?,
4067 };
4068 Some(intrinsic_and_signature)
4069 }
4070
4071 #[allow(clippy::unnecessary_wraps)]
4072 fn grid_member_signature(
4073 &mut self,
4074 self_type: &TypeRef,
4075 element_type: &TypeRef,
4076 field_name_str: &str,
4077 node: &swamp_ast::Node,
4078 ) -> Option<(IntrinsicFunction, Signature)> {
4079 let self_type_param = TypeForParameter {
4080 name: "self".to_string(),
4081 resolved_type: self_type.clone(),
4082 is_mutable: false,
4083 node: None,
4084 };
4085 let self_mutable_type_param = TypeForParameter {
4086 name: "self".to_string(),
4087 resolved_type: self_type.clone(),
4088 is_mutable: true,
4089 node: None,
4090 };
4091 let element_param = TypeForParameter {
4092 name: "element".to_string(),
4093 resolved_type: element_type.clone(),
4094 is_mutable: false,
4095 node: None,
4096 };
4097 let int_type = self.types().int();
4098
4099 let int_param = TypeForParameter {
4100 name: "x_or_y".to_string(),
4101 resolved_type: int_type.clone(),
4102 is_mutable: false,
4103 node: None,
4104 };
4105 let intrinsic_and_signature = match field_name_str {
4106 "set" => (
4107 IntrinsicFunction::GridSet,
4108 Signature {
4109 parameters: vec![self_type_param, int_param.clone(), int_param, element_param],
4110 return_type: self.types().unit(),
4111 },
4112 ),
4113
4114 "get" => (
4115 IntrinsicFunction::GridGet,
4116 Signature {
4117 parameters: vec![self_type_param, int_param.clone(), int_param],
4118 return_type: element_type.clone(),
4119 },
4120 ),
4121
4122 "width" => (
4123 IntrinsicFunction::GridWidth,
4124 Signature {
4125 parameters: vec![self_type_param],
4126 return_type: int_type,
4127 },
4128 ),
4129
4130 "height" => (
4131 IntrinsicFunction::GridHeight,
4132 Signature {
4133 parameters: vec![self_type_param],
4134 return_type: int_type,
4135 },
4136 ),
4137
4138 _ => panic!("unknown grid method {field_name_str}"),
4139 };
4140
4141 Some(intrinsic_and_signature)
4142 }
4143
4144 fn ptr_member_signature(
4145 &mut self,
4146 self_type: &TypeRef,
4147 field_name_str: &str,
4148 node: &swamp_ast::Node,
4149 ) -> Option<(IntrinsicFunction, Signature)> {
4150 let self_type_param = TypeForParameter {
4151 name: "self".to_string(),
4152 resolved_type: self_type.clone(),
4153 is_mutable: false,
4154 node: None,
4155 };
4156 let self_mut_type_param = TypeForParameter {
4157 name: "self".to_string(),
4158 resolved_type: self_type.clone(),
4159 is_mutable: true,
4160 node: None,
4161 };
4162
4163 let intrinsic_and_signature = match field_name_str {
4164 "from_u32" => {
4165 let signature = Signature {
4166 parameters: vec![TypeForParameter {
4167 name: "addr".to_string(),
4168 resolved_type: self.types().int(),
4169 is_mutable: false,
4170 node: None,
4171 }],
4172 return_type: self.types().int(),
4173 };
4174 (IntrinsicFunction::VecLen, signature)
4175 }
4176 _ => return None,
4177 };
4178
4179 Some(intrinsic_and_signature)
4180 }
4181
4182 fn basic_collection_member_signature(
4183 &mut self,
4184 self_type: &TypeRef,
4185 field_name_str: &str,
4186 node: &swamp_ast::Node,
4187 ) -> Option<(IntrinsicFunction, Signature)> {
4188 let self_type_param = TypeForParameter {
4189 name: "self".to_string(),
4190 resolved_type: self_type.clone(),
4191 is_mutable: false,
4192 node: None,
4193 };
4194 let self_mut_type_param = TypeForParameter {
4195 name: "self".to_string(),
4196 resolved_type: self_type.clone(),
4197 is_mutable: true,
4198 node: None,
4199 };
4200 let intrinsic_and_signature = match field_name_str {
4201 "len" => {
4202 let signature = Signature {
4203 parameters: vec![self_type_param],
4204 return_type: self.types().int(),
4205 };
4206 (IntrinsicFunction::VecLen, signature)
4207 }
4208 "is_empty" => (
4209 IntrinsicFunction::VecIsEmpty,
4210 Signature {
4211 parameters: vec![self_type_param],
4212 return_type: self.types().bool(),
4213 },
4214 ),
4215 "clear" => {
4216 let signature = Signature {
4217 parameters: vec![self_mut_type_param],
4218 return_type: self.types().unit(),
4219 };
4220 (IntrinsicFunction::VecClear, signature)
4221 }
4222 "capacity" => {
4223 let signature = Signature {
4224 parameters: vec![self_type_param],
4225 return_type: self.types().int(),
4226 };
4227 (IntrinsicFunction::VecCapacity, signature)
4228 }
4229 _ => {
4230 self.add_err(ErrorKind::UnknownMemberFunction(self_type.clone()), node);
4231
4232 return None;
4233 }
4234 };
4235 Some(intrinsic_and_signature)
4236 }
4237 #[allow(clippy::too_many_lines)]
4238 fn codepoint_member_signature(
4239 &mut self,
4240 self_type: &TypeRef,
4241 key_type: Option<&TypeRef>,
4242 element_type: &TypeRef,
4243 field_name_str: &str,
4244 lambda_variable_count: usize,
4245 node: &swamp_ast::Node,
4246 ) -> Option<(IntrinsicFunction, Signature)> {
4247 let self_type_param = TypeForParameter {
4248 name: "self".to_string(),
4249 resolved_type: self_type.clone(),
4250 is_mutable: false,
4251 node: None,
4252 };
4253
4254 match field_name_str {
4255 "int" => Some((
4256 IntrinsicFunction::CodepointToInt,
4257 Signature {
4258 parameters: vec![self_type_param],
4259 return_type: self.types().int(),
4260 },
4261 )),
4262 "char" => Some((
4263 IntrinsicFunction::ByteToCodepoint,
4264 Signature {
4265 parameters: vec![self_type_param],
4266 return_type: self.types().codepoint(),
4267 },
4268 )),
4269 _ => None,
4270 }
4271 }
4272
4273 #[allow(clippy::too_many_lines)]
4274 fn byte_member_signature(
4275 &mut self,
4276 self_type: &TypeRef,
4277 key_type: Option<&TypeRef>,
4278 element_type: &TypeRef,
4279 field_name_str: &str,
4280 lambda_variable_count: usize,
4281 node: &swamp_ast::Node,
4282 ) -> Option<(IntrinsicFunction, Signature)> {
4283 let self_type_param = TypeForParameter {
4284 name: "self".to_string(),
4285 resolved_type: self_type.clone(),
4286 is_mutable: false,
4287 node: None,
4288 };
4289
4290 match field_name_str {
4291 "int" => Some((
4292 IntrinsicFunction::ByteToInt,
4293 Signature {
4294 parameters: vec![self_type_param],
4295 return_type: self.types().int(),
4296 },
4297 )),
4298 "float" => Some((
4299 IntrinsicFunction::ByteToFloat,
4300 Signature {
4301 parameters: vec![self_type_param],
4302 return_type: self.types().float(),
4303 },
4304 )),
4305 "char" => Some((
4306 IntrinsicFunction::ByteToCodepoint,
4307 Signature {
4308 parameters: vec![self_type_param],
4309 return_type: self.types().codepoint(),
4310 },
4311 )),
4312 _ => None,
4313 }
4314 }
4315
4316 #[allow(clippy::too_many_lines)]
4317 fn string_member_signature(
4318 &mut self,
4319 self_type: &TypeRef,
4320 key_type: Option<&TypeRef>,
4321 element_type: &TypeRef,
4322 field_name_str: &str,
4323 lambda_variable_count: usize,
4324 node: &swamp_ast::Node,
4325 ) -> Option<(IntrinsicFunction, Signature)> {
4326 let self_type_param = TypeForParameter {
4327 name: "self".to_string(),
4328 resolved_type: self_type.clone(),
4329 is_mutable: false,
4330 node: None,
4331 };
4332
4333 let x = match field_name_str {
4334 "starts_with" => (
4335 IntrinsicFunction::StringStartsWith,
4336 Signature {
4337 parameters: vec![
4338 self_type_param,
4339 TypeForParameter {
4340 name: "str".to_string(),
4341 resolved_type: self.types().string(),
4342 is_mutable: false,
4343 node: None,
4344 },
4345 ],
4346 return_type: self.types().bool(),
4347 },
4348 ),
4349 _ => {
4350 return self.vec_member_signature(
4351 self_type,
4352 element_type,
4353 field_name_str,
4354 lambda_variable_count,
4355 node,
4356 );
4357 }
4358 };
4359
4360 Some(x)
4361 }
4362
4363 #[allow(clippy::too_many_lines)]
4364 fn slice_member_signature(
4365 &mut self,
4366 self_type: &TypeRef,
4367 key_type: Option<&TypeRef>,
4368 element_type: &TypeRef,
4369 field_name_str: &str,
4370 lambda_variable_count: usize,
4371 node: &swamp_ast::Node,
4372 ) -> Option<(IntrinsicFunction, Signature)> {
4373 let slice_view_type = self.types().slice_view(&element_type.clone());
4374 let int_type = self.types().int();
4375 let self_type_param = TypeForParameter {
4376 name: "self".to_string(),
4377 resolved_type: slice_view_type.clone(),
4378 is_mutable: false,
4379 node: None,
4380 };
4381 let self_mut_type_param = TypeForParameter {
4382 name: "self".to_string(),
4383 resolved_type: slice_view_type,
4384 is_mutable: true,
4385 node: None,
4386 };
4387 let intrinsic_and_signature = match field_name_str {
4388 "for" => {
4389 let parameters = if lambda_variable_count == 2 {
4390 vec![
4391 TypeForParameter {
4392 name: "key".to_string(),
4393 resolved_type: key_type.unwrap().clone(),
4394 is_mutable: false,
4395 node: None,
4396 },
4397 TypeForParameter {
4398 name: "element".to_string(),
4399 resolved_type: element_type.clone(),
4400 is_mutable: false,
4401 node: None,
4402 },
4403 ]
4404 } else {
4405 vec![TypeForParameter {
4406 name: "element".to_string(),
4407 resolved_type: element_type.clone(),
4408 is_mutable: false,
4409 node: None,
4410 }]
4411 };
4412 let lambda_signature = Signature {
4413 parameters,
4414 return_type: self.types().unit(),
4415 };
4416 let lambda_function_type = self.types().function(lambda_signature);
4417 (
4418 IntrinsicFunction::TransformerFor,
4419 Signature {
4420 parameters: vec![
4421 self_type_param,
4422 TypeForParameter {
4423 name: "lambda".to_string(),
4424 resolved_type: lambda_function_type,
4425 is_mutable: false,
4426 node: None,
4427 },
4428 ],
4429 return_type: self.types().unit(), },
4431 )
4432 }
4433 "while" => {
4434 let parameters = if lambda_variable_count == 2 {
4435 vec![
4436 TypeForParameter {
4437 name: "key".to_string(),
4438 resolved_type: key_type.unwrap().clone(),
4439 is_mutable: false,
4440 node: None,
4441 },
4442 TypeForParameter {
4443 name: "element".to_string(),
4444 resolved_type: element_type.clone(),
4445 is_mutable: false,
4446 node: None,
4447 },
4448 ]
4449 } else {
4450 vec![TypeForParameter {
4451 name: "element".to_string(),
4452 resolved_type: element_type.clone(),
4453 is_mutable: false,
4454 node: None,
4455 }]
4456 };
4457 let lambda_signature = Signature {
4458 parameters,
4459 return_type: self.types().bool(), };
4461 let lambda_function_type = self.types().function(lambda_signature);
4462 (
4463 IntrinsicFunction::TransformerWhile,
4464 Signature {
4465 parameters: vec![
4466 self_type_param,
4467 TypeForParameter {
4468 name: "lambda".to_string(),
4469 resolved_type: lambda_function_type,
4470 is_mutable: false,
4471 node: None,
4472 },
4473 ],
4474 return_type: self.types().unit(), },
4476 )
4477 }
4478 "filter" => {
4479 let lambda_signature = Signature {
4480 parameters: vec![TypeForParameter {
4481 name: "element".to_string(),
4482 resolved_type: element_type.clone(),
4483 is_mutable: false,
4484 node: None,
4485 }],
4486 return_type: self.types().bool(),
4487 };
4488 let lambda_function_type = self.types().function(lambda_signature);
4489 (
4490 IntrinsicFunction::TransformerFilter,
4491 Signature {
4492 parameters: vec![
4493 self_type_param,
4494 TypeForParameter {
4495 name: "lambda".to_string(),
4496 resolved_type: lambda_function_type,
4497 is_mutable: false,
4498 node: None,
4499 },
4500 ],
4501 return_type: self.shared.state.types.slice_view(&element_type.clone()),
4502 },
4503 )
4504 }
4505 "filter_mut" => {
4506 let lambda_signature = Signature {
4507 parameters: vec![TypeForParameter {
4508 name: "element".to_string(),
4509 resolved_type: element_type.clone(),
4510 is_mutable: false,
4511 node: None,
4512 }],
4513 return_type: self.types().bool(),
4514 };
4515 let lambda_function_type = self.types().function(lambda_signature);
4516 (
4517 IntrinsicFunction::TransformerFilterInPlace,
4518 Signature {
4519 parameters: vec![
4520 self_mut_type_param,
4521 TypeForParameter {
4522 name: "lambda".to_string(),
4523 resolved_type: lambda_function_type,
4524 is_mutable: false,
4525 node: None,
4526 },
4527 ],
4528 return_type: self.types().unit(),
4529 },
4530 )
4531 }
4532 "find" => {
4533 let lambda_signature = Signature {
4534 parameters: vec![TypeForParameter {
4535 name: "element".to_string(),
4536 resolved_type: element_type.clone(),
4537 is_mutable: false,
4538 node: None,
4539 }],
4540 return_type: self.types().bool(),
4541 };
4542 let lambda_function_type = self.types().function(lambda_signature);
4543 (
4544 IntrinsicFunction::TransformerFind,
4545 Signature {
4546 parameters: vec![
4547 self_type_param,
4548 TypeForParameter {
4549 name: "lambda".to_string(),
4550 resolved_type: lambda_function_type,
4551 is_mutable: false,
4552 node: None,
4553 },
4554 ],
4555 return_type: self.shared.state.types.optional(&element_type.clone()),
4556 },
4557 )
4558 }
4559
4560 "remove" => {
4561 let signature = Signature {
4562 parameters: vec![
4563 self_mut_type_param,
4564 TypeForParameter {
4565 name: "index".to_string(),
4566 resolved_type: int_type,
4567 is_mutable: false,
4568 node: None,
4569 },
4570 ],
4571 return_type: self.types().unit(),
4572 };
4573 (IntrinsicFunction::VecRemoveIndex, signature)
4574 }
4575 _ => return self.basic_collection_member_signature(self_type, field_name_str, node),
4576 };
4577 Some(intrinsic_and_signature)
4578 }
4579
4580 #[allow(clippy::unnecessary_wraps, clippy::result_large_err)]
4581 fn map_member_signature(
4582 &mut self,
4583 self_type: &TypeRef,
4584 key_type: &TypeRef,
4585 value_type: &TypeRef,
4586 field_name_str: &str,
4587 node: &swamp_ast::Node,
4588 ) -> Option<(IntrinsicFunction, Signature)> {
4589 let self_type_param = TypeForParameter {
4590 name: "self".to_string(),
4591 resolved_type: self_type.clone(),
4592 is_mutable: false,
4593 node: None,
4594 };
4595
4596 let mutable_self_type_param = TypeForParameter {
4597 name: "self".to_string(),
4598 resolved_type: self_type.clone(),
4599 is_mutable: true,
4600 node: None,
4601 };
4602
4603 let intrinsic_and_signature = match field_name_str {
4604 "has" => (
4605 IntrinsicFunction::MapHas,
4606 Signature {
4607 parameters: vec![
4608 self_type_param,
4609 TypeForParameter {
4610 name: "key".to_string(),
4611 resolved_type: key_type.clone(),
4612 is_mutable: false,
4613 node: None,
4614 },
4615 ],
4616 return_type: self.types().bool(),
4617 },
4618 ),
4619 "remove" => (
4620 IntrinsicFunction::MapRemove,
4621 Signature {
4622 parameters: vec![
4623 mutable_self_type_param,
4624 TypeForParameter {
4625 name: "key".to_string(),
4626 resolved_type: key_type.clone(),
4627 is_mutable: false,
4628 node: None,
4629 },
4630 ],
4631 return_type: self.types().unit(),
4632 },
4633 ),
4634 "len" => (
4635 IntrinsicFunction::MapLen,
4636 Signature {
4637 parameters: vec![self_type_param],
4638 return_type: self.types().int(),
4639 },
4640 ),
4641 "capacity" => (
4642 IntrinsicFunction::MapCapacity,
4643 Signature {
4644 parameters: vec![self_type_param],
4645 return_type: self.types().int(),
4646 },
4647 ),
4648 "is_empty" => (
4649 IntrinsicFunction::MapIsEmpty,
4650 Signature {
4651 parameters: vec![self_type_param],
4652 return_type: self.types().bool(),
4653 },
4654 ),
4655 _ => todo!("unknown map member"),
4656 };
4657
4658 Some(intrinsic_and_signature)
4659 }
4660
4661 fn check_intrinsic_member_signature(
4662 &mut self,
4663 type_that_member_is_on: &TypeRef,
4664 field_name_str: &str,
4665 lambda_variables_count: usize,
4666 node: &swamp_ast::Node,
4667 ) -> Option<(IntrinsicFunction, Signature)> {
4668 let ty = type_that_member_is_on;
4669 let int_type = self.types().int();
4670 match &*ty.kind {
4671 TypeKind::GridStorage(element_type, ..) | TypeKind::GridView(element_type) => self
4672 .grid_member_signature(type_that_member_is_on, element_type, field_name_str, node),
4673 TypeKind::SparseStorage(element_type, ..) | TypeKind::SparseView(element_type) => self
4674 .sparse_member_signature(
4675 type_that_member_is_on,
4676 element_type,
4677 field_name_str,
4678 lambda_variables_count,
4679 node,
4680 ),
4681 TypeKind::Enum(enum_type) => self.enum_member_signature(ty, field_name_str, node),
4682 TypeKind::QueueStorage(element_type, ..) => self.queue_member_signature(
4683 type_that_member_is_on,
4684 None,
4685 element_type,
4686 field_name_str,
4687 lambda_variables_count,
4688 node,
4689 ),
4690 TypeKind::StackStorage(element_type, ..)
4691 | TypeKind::QueueStorage(element_type, ..)
4692 | TypeKind::VecStorage(element_type, ..)
4693 | TypeKind::DynamicLengthVecView(element_type) => self.vec_member_signature(
4694 type_that_member_is_on,
4695 element_type,
4696 field_name_str,
4697 lambda_variables_count,
4698 node,
4699 ),
4700 TypeKind::SliceView(element_type) => self.slice_member_signature(
4701 type_that_member_is_on,
4702 Some(&int_type),
4703 element_type,
4704 field_name_str,
4705 lambda_variables_count,
4706 node,
4707 ),
4708 TypeKind::Pointer(inner) => {
4709 self.ptr_member_signature(type_that_member_is_on, field_name_str, node)
4710 }
4711 TypeKind::Byte => {
4712 let element_type = self.shared.state.types.byte();
4713 self.byte_member_signature(
4714 type_that_member_is_on,
4715 Some(&int_type),
4716 &element_type,
4717 field_name_str,
4718 lambda_variables_count,
4719 node,
4720 )
4721 }
4722 TypeKind::Codepoint => {
4723 let element_type = self.shared.state.types.codepoint();
4724 self.codepoint_member_signature(
4725 type_that_member_is_on,
4726 Some(&int_type),
4727 &element_type,
4728 field_name_str,
4729 lambda_variables_count,
4730 node,
4731 )
4732 }
4733 TypeKind::StringView { .. } | TypeKind::StringStorage(..) => {
4734 let element_type = self.shared.state.types.byte();
4735 self.string_member_signature(
4736 type_that_member_is_on,
4737 Some(&int_type),
4738 &element_type,
4739 field_name_str,
4740 lambda_variables_count,
4741 node,
4742 )
4743 }
4744 TypeKind::DynamicLengthMapView(key, value) | TypeKind::MapStorage(key, value, _) => {
4745 self.map_member_signature(type_that_member_is_on, key, value, field_name_str, node)
4746 }
4747
4748 TypeKind::FixedCapacityAndLengthArray(element_type, _) => self.slice_member_signature(
4749 type_that_member_is_on,
4750 Some(&int_type),
4751 element_type,
4752 field_name_str,
4753 lambda_variables_count,
4754 node,
4755 ),
4756 _ => {
4757 self.add_err(
4758 ErrorKind::UnknownMemberFunction(type_that_member_is_on.clone()),
4759 node,
4760 );
4761
4762 None
4763 }
4764 }
4765 }
4766
4767 fn analyze_member_call(
4768 &mut self,
4769 type_that_member_is_on: &TypeRef,
4770 field_name_str: &str,
4771 ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4772 ast_arguments: &[swamp_ast::Expression],
4773 chain_self_is_mutable: bool,
4774 node: &swamp_ast::Node,
4775 ) -> (PostfixKind, TypeRef) {
4776 let generic_arguments = if let Some(ast_generic_arguments) = ast_maybe_generic_arguments {
4777 let mut resolved_types = Vec::new();
4778 for ast_type in ast_generic_arguments {
4779 resolved_types
4780 .push(self.analyze_type(ast_type.get_type(), &TypeAnalyzeContext::default()));
4781 }
4782 resolved_types
4783 } else {
4784 vec![]
4785 };
4786
4787 let maybe_function = self
4788 .shared
4789 .state
4790 .associated_impls
4791 .get_member_function(type_that_member_is_on, field_name_str)
4792 .cloned();
4793
4794 let (function_ref, instantiated_signature) = if let Some(found_function) = maybe_function {
4795 let signature = self.analyze_normal_member_call(
4796 type_that_member_is_on,
4797 &found_function,
4798 generic_arguments,
4799 ast_arguments,
4800 chain_self_is_mutable,
4801 node,
4802 );
4803 (found_function, signature)
4804 } else {
4805 let lambda_variables_count = if ast_arguments.is_empty() {
4806 0
4807 } else if let swamp_ast::ExpressionKind::Lambda(variables, ..) = &ast_arguments[0].kind
4808 {
4809 variables.len()
4810 } else {
4811 0
4812 };
4813 let Some((intrinsic_fn, signature)) = self.check_intrinsic_member_signature(
4814 type_that_member_is_on,
4815 field_name_str,
4816 lambda_variables_count,
4817 node,
4818 ) else {
4819 return (PostfixKind::OptionalChainingOperator, self.types().unit());
4820 };
4821 let def = IntrinsicFunctionDefinition {
4822 name: field_name_str.to_string(),
4823 signature,
4824 intrinsic: intrinsic_fn,
4825 };
4826 let function_ref = FunctionRef::from(Function::Intrinsic(
4827 IntrinsicFunctionDefinitionRef::from(def.clone()),
4828 ));
4829 (function_ref, def.signature)
4830 };
4831
4832 let self_type_in_signature = &instantiated_signature.parameters[0];
4833
4834 if self_type_in_signature.is_mutable && !chain_self_is_mutable {
4835 self.add_err(ErrorKind::SelfNotCorrectMutableState, node);
4836 }
4837
4838 let resolved_arguments = self.analyze_and_verify_parameters(
4839 node,
4840 &instantiated_signature.parameters[1..],
4841 ast_arguments,
4842 );
4843
4844 let name_node = self.to_node(node);
4845 self.shared
4846 .state
4847 .refs
4848 .add(function_ref.symbol_id().into(), name_node.clone());
4849 self.shared
4850 .definition_table
4851 .refs
4852 .add(function_ref.symbol_id().into(), name_node);
4853
4854 (
4855 PostfixKind::MemberCall(function_ref, resolved_arguments),
4856 TypeRef::from(instantiated_signature.return_type.clone()),
4857 )
4858 }
4859
4860 fn analyze_postfix_member_call(
4861 &mut self,
4862 type_that_member_is_on: &TypeRef,
4863 is_mutable: bool,
4864 member_name: &swamp_ast::Node,
4865 ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4866 ast_arguments: &[swamp_ast::Expression],
4867 suffixes: &mut Vec<Postfix>,
4868 ) -> TypeRef {
4869 let field_name_str = self.get_text(member_name).to_string();
4870
4871 let resolved_node = self.to_node(member_name);
4872
4873 let (kind, return_type) = self.analyze_member_call(
4874 type_that_member_is_on,
4875 &field_name_str,
4876 ast_maybe_generic_arguments,
4877 ast_arguments,
4878 is_mutable,
4879 member_name,
4880 );
4881 let postfix = Postfix {
4882 node: resolved_node,
4883 ty: return_type,
4884 kind,
4885 };
4886
4887 let last_type = postfix.ty.clone();
4888 suffixes.push(postfix);
4889
4890 last_type
4891 }
4892
4893 fn is_compatible_initializer_list_target(
4894 &mut self,
4895 target_type: &TypeRef,
4896 initializer_element_type: &TypeRef,
4897 ) -> bool {
4898 match &*target_type.kind {
4899 TypeKind::VecStorage(vec_element_type, _vec_capacity) => self
4900 .types()
4901 .compatible_with(vec_element_type, initializer_element_type),
4902 TypeKind::FixedCapacityAndLengthArray(array_element_type, _array_capacity) => self
4903 .types()
4904 .compatible_with(array_element_type, initializer_element_type),
4905 _ => false,
4906 }
4907 }
4908
4909 fn is_compatible_initializer_pair_list_target(
4910 &mut self,
4911 target_type: &TypeRef,
4912 initializer_key_type: &TypeRef,
4913 initializer_value_type: &TypeRef,
4914 ) -> bool {
4915 match &*target_type.kind {
4916 TypeKind::MapStorage(storage_key, storage_value, _) => {
4917 self.types()
4918 .compatible_with(initializer_key_type, storage_key)
4919 && self
4920 .types()
4921 .compatible_with(initializer_value_type, storage_value)
4922 }
4923 _ => false,
4924 }
4925 }
4926
4927 fn types_did_not_match_try_late_coerce_expression(
4928 &mut self,
4929 expr: Expression,
4930 special_expected_type: &TypeRef,
4931 special_encountered_type: &TypeRef,
4932 node: &swamp_ast::Node,
4933 ) -> Expression {
4934 let expected_type = special_expected_type;
4935 let encountered_type = special_encountered_type;
4936
4937 if matches!(&*expected_type.kind, TypeKind::Any) && encountered_type.is_storage() {
4938 let wrapped = self.create_expr(
4939 ExpressionKind::CoerceToAny(Box::new(expr)),
4940 expected_type.clone(),
4941 node,
4942 );
4943 return wrapped;
4944 }
4945
4946 let encountered_is_optional = matches!(&*encountered_type.kind, TypeKind::Optional(_));
4947 if let TypeKind::Optional(expected_inner_type) = &*expected_type.kind {
4948 let inner_is_also_optional =
4949 matches!(&*expected_inner_type.kind, TypeKind::Optional(_));
4950 assert!(!inner_is_also_optional);
4953
4954 if !encountered_is_optional {
4957 if self
4959 .types()
4960 .compatible_with(expected_inner_type, encountered_type)
4961 {
4962 let wrapped = self.create_expr(
4964 ExpressionKind::Option(Option::from(Box::new(expr))),
4965 expected_type.clone(),
4966 node,
4967 );
4968 return wrapped;
4969 }
4970 }
4971 }
4972
4973 if matches!(&*expected_type.kind, &TypeKind::Bool) {
4974 if encountered_is_optional {
4976 let bool_type = self.types().bool();
4977 let wrapped = self.create_expr(
4978 ExpressionKind::CoerceOptionToBool(Box::from(expr)),
4979 bool_type,
4980 node,
4981 );
4982 return wrapped;
4983 }
4984 }
4985
4986 if matches!(
4987 (&*expected_type.kind, &*encountered_type.kind),
4988 (TypeKind::Codepoint, TypeKind::Int)
4989 ) {
4990 let coerced = self.create_expr(
4991 ExpressionKind::CoerceIntToChar(Box::new(expr)),
4992 expected_type.clone(),
4993 node,
4994 );
4995 return coerced;
4996 }
4997
4998 if matches!(
4999 (&*expected_type.kind, &*encountered_type.kind),
5000 (TypeKind::Byte, TypeKind::Int)
5001 ) {
5002 let coerced = self.create_expr(
5003 ExpressionKind::CoerceIntToByte(Box::new(expr)),
5004 expected_type.clone(),
5005 node,
5006 );
5007 return coerced;
5008 }
5009
5010 error!(?expected_type, ?encountered_type, "incompatible");
5011 self.create_err(
5012 ErrorKind::IncompatibleTypes {
5013 expected: expected_type.clone(),
5014 found: encountered_type.clone(),
5015 },
5016 node,
5017 )
5018 }
5019
5020 #[must_use]
5021 pub fn analyze_generic_parameter_usize(&self, generic_parameter: &GenericParameter) -> usize {
5022 let usize_node = generic_parameter.get_unsigned_int_node();
5023 let usize_str = self.get_text(usize_node);
5024 Self::str_to_unsigned_int(usize_str).unwrap() as usize
5025 }
5026
5027 #[must_use]
5028 pub fn analyze_generic_parameter_usize_tuple(
5029 &self,
5030 generic_parameter: &GenericParameter,
5031 ) -> (usize, usize) {
5032 let (first, second) = generic_parameter.get_unsigned_int_tuple_nodes();
5033 let first_str = self.get_text(first);
5034 let second_str = self.get_text(second);
5035 let first_value = Self::str_to_unsigned_int(first_str).unwrap() as usize;
5036 let second_value = Self::str_to_unsigned_int(second_str).unwrap() as usize;
5037
5038 (first_value, second_value)
5039 }
5040
5041 pub fn analyze_special_named_type(
5042 &mut self,
5043 path: &[String],
5044 name: &str,
5045 ast_generic_parameters: &[GenericParameter],
5046 ) -> Option<TypeRef> {
5047 let converted_type = match name {
5048 "Any" => self.shared.state.types.any(),
5049 "Ptr" => {
5050 if self.shared.allow_unsafe {
5051 let inner_type = if ast_generic_parameters.len() == 1 {
5052 self.analyze_type(
5053 ast_generic_parameters[0].get_type(),
5054 &TypeAnalyzeContext::default(),
5055 )
5056 } else if ast_generic_parameters.is_empty() {
5057 self.shared.state.types.byte() } else {
5059 self.add_err_resolved(ErrorKind::UnexpectedType, &Node::default());
5060 return None;
5061 };
5062 let new_type = self.shared.state.types.ptr(inner_type);
5063 self.shared.state.associated_impls.prepare(&new_type);
5064 new_type
5065 } else {
5066 panic!("unsafe Ptr is not allowed");
5067 }
5068 }
5069 "String" => {
5070 if ast_generic_parameters.len() == 1 {
5071 let fixed_size =
5072 self.analyze_generic_parameter_usize(&ast_generic_parameters[0]);
5073 let new_type = self.shared.state.types.string_storage(fixed_size);
5074 let default_node = swamp_ast::Node::default();
5075 self.add_default_functions(&new_type, &default_node);
5076 new_type
5077 } else {
5078 return None;
5079 }
5080 }
5081 "Vec" => {
5082 if ast_generic_parameters.len() == 1 {
5083 let element_type = self.analyze_type(
5084 ast_generic_parameters[0].get_type(),
5085 &TypeAnalyzeContext::default(),
5086 );
5087 let vec_type = self.shared.state.types.dynamic_vec_view(&element_type);
5088 let default_node = swamp_ast::Node::default();
5090 self.add_default_functions(&vec_type, &default_node);
5091 vec_type
5092 } else if ast_generic_parameters.len() == 2 {
5093 let element_type = self.analyze_type(
5094 ast_generic_parameters[0].get_type(),
5095 &TypeAnalyzeContext::default(),
5096 );
5097 let fixed_size =
5098 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
5099 let vec_storage_type = self
5100 .shared
5101 .state
5102 .types
5103 .vec_storage(&element_type, fixed_size);
5104 let default_node = swamp_ast::Node::default();
5106 self.add_default_functions(&vec_storage_type, &default_node);
5107 vec_storage_type
5108 } else {
5109 panic!("todo: make this into an error")
5110 }
5111 }
5112 "Stack" => {
5113 if ast_generic_parameters.len() == 1 {
5114 let element_type = self.analyze_type(
5115 ast_generic_parameters[0].get_type(),
5116 &TypeAnalyzeContext::default(),
5117 );
5118 let stack_view_type = self.shared.state.types.stack_view(&element_type);
5119 let default_node = swamp_ast::Node::default();
5121 self.add_default_functions(&stack_view_type, &default_node);
5122 stack_view_type
5123 } else if ast_generic_parameters.len() == 2 {
5124 let element_type = self.analyze_type(
5125 ast_generic_parameters[0].get_type(),
5126 &TypeAnalyzeContext::default(),
5127 );
5128 let fixed_size =
5129 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
5130 let stack_storage_type = self
5131 .shared
5132 .state
5133 .types
5134 .stack_storage(&element_type, fixed_size);
5135 let default_node = swamp_ast::Node::default();
5137 self.add_default_functions(&stack_storage_type, &default_node);
5138 stack_storage_type
5139 } else {
5140 panic!("todo: make this into an error")
5141 }
5142 }
5143 "Queue" => {
5144 if ast_generic_parameters.len() == 1 {
5145 let element_type = self.analyze_type(
5146 ast_generic_parameters[0].get_type(),
5147 &TypeAnalyzeContext::default(),
5148 );
5149 let queue_view_type = self.shared.state.types.queue_view(&element_type);
5150 let default_node = swamp_ast::Node::default();
5152 self.add_default_functions(&queue_view_type, &default_node);
5153 queue_view_type
5154 } else if ast_generic_parameters.len() == 2 {
5155 let element_type = self.analyze_type(
5156 ast_generic_parameters[0].get_type(),
5157 &TypeAnalyzeContext::default(),
5158 );
5159 let fixed_size =
5160 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
5161 let queue_storage_type = self
5162 .shared
5163 .state
5164 .types
5165 .queue_storage(&element_type, fixed_size);
5166 let default_node = swamp_ast::Node::default();
5168 self.add_default_functions(&queue_storage_type, &default_node);
5169 queue_storage_type
5170 } else {
5171 panic!("todo: make this into an error")
5172 }
5173 }
5174 "Sparse" => {
5175 if ast_generic_parameters.len() == 1 {
5176 let element_type = self.analyze_type(
5177 ast_generic_parameters[0].get_type(),
5178 &TypeAnalyzeContext::default(),
5179 );
5180 let sparse_view_type = self.shared.state.types.sparse_view(&element_type);
5181 let default_node = swamp_ast::Node::default();
5183 self.add_default_functions(&sparse_view_type, &default_node);
5184 sparse_view_type
5185 } else if ast_generic_parameters.len() == 2 {
5186 let element_type = self.analyze_type(
5187 ast_generic_parameters[0].get_type(),
5188 &TypeAnalyzeContext::default(),
5189 );
5190 let fixed_size =
5191 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
5192 let sparse_storage_type = self
5193 .shared
5194 .state
5195 .types
5196 .sparse_storage(&element_type, fixed_size);
5197 let default_node = swamp_ast::Node::default();
5199 self.add_default_functions(&sparse_storage_type, &default_node);
5200 sparse_storage_type
5201 } else {
5202 panic!("todo: make this into an error")
5203 }
5204 }
5205
5206 "Grid" => {
5207 if ast_generic_parameters.len() == 1 {
5208 let element_type = self.analyze_type(
5209 ast_generic_parameters[0].get_type(),
5210 &TypeAnalyzeContext::default(),
5211 );
5212 let grid_view_type = self.shared.state.types.grid_view(&element_type);
5213 let default_node = swamp_ast::Node::default();
5215 self.add_default_functions(&grid_view_type, &default_node);
5216 grid_view_type
5217 } else if ast_generic_parameters.len() == 2 {
5218 let element_type = self.analyze_type(
5219 ast_generic_parameters[0].get_type(),
5220 &TypeAnalyzeContext::default(),
5221 );
5222 let (width, height) =
5223 self.analyze_generic_parameter_usize_tuple(&ast_generic_parameters[1]);
5224 let grid_storage_type =
5225 self.shared
5226 .state
5227 .types
5228 .grid_storage(&element_type, width, height);
5229 let default_node = swamp_ast::Node::default();
5231 self.add_default_functions(&grid_storage_type, &default_node);
5232 grid_storage_type
5233 } else {
5234 panic!("todo: make this into an error")
5235 }
5236 }
5237
5238 _ => return None,
5239 };
5240
5241 Some(converted_type)
5242 }
5243
5244 fn special_static_member(
5245 &self,
5246 type_identifier: &QualifiedTypeIdentifier,
5247 member_name_node: &swamp_ast::Node,
5248 ) -> Option<Function> {
5249 if type_identifier.generic_params.is_empty() {
5250 return None;
5251 }
5252
5253 if type_identifier.module_path.is_some() {
5254 return None;
5255 }
5256
5257 let member_name = self.get_text(member_name_node);
5258 let name = self.get_text(&type_identifier.name.0);
5259
5260 match name {
5261 "Stack" => None,
5262 _ => None,
5263 }
5264 }
5265
5266 fn analyze_subscript_int(
5267 &mut self,
5268 collection_type: TypeRef,
5269 unsigned_int_expression: Expression,
5270 ) -> (Postfix, TypeRef) {
5271 let node = &unsigned_int_expression.node;
5272 match &*collection_type.kind {
5273 TypeKind::QueueStorage(element_type, _)
5274 | TypeKind::StackStorage(element_type, _)
5275 | TypeKind::StackView(element_type)
5276 | TypeKind::VecStorage(element_type, _)
5277 | TypeKind::StringStorage(element_type, _, _)
5278 | TypeKind::StringView(element_type, _)
5279 | TypeKind::FixedCapacityAndLengthArray(element_type, _)
5280 | TypeKind::DynamicLengthVecView(element_type)
5281 | TypeKind::SliceView(element_type) => {
5282 let vec_type = VecType {
5283 element: element_type.clone(),
5284 };
5285
5286 let postfix = Postfix {
5287 node: node.clone(),
5288 ty: collection_type.clone(),
5289 kind: PostfixKind::VecSubscript(vec_type, unsigned_int_expression),
5290 };
5291
5292 (postfix, element_type.clone())
5293 }
5294 TypeKind::SparseStorage(element_type, _) | TypeKind::SparseView(element_type) => {
5296 let sparse_type = SparseType {
5297 element: element_type.clone(),
5298 };
5299
5300 let postfix = Postfix {
5301 node: node.clone(),
5302 ty: collection_type.clone(),
5303 kind: PostfixKind::SparseSubscript(sparse_type, unsigned_int_expression),
5304 };
5305
5306 (postfix, element_type.clone())
5307 }
5308
5309 _ => {
5310 self.add_err_resolved(ErrorKind::CanNotSubscriptWithThatType, node);
5311
5312 let error_vec_type = VecType {
5313 element: self.types().unit(),
5314 };
5315
5316 let error_postfix = Postfix {
5317 node: node.clone(),
5318 ty: collection_type.clone(),
5319 kind: PostfixKind::VecSubscript(error_vec_type, unsigned_int_expression),
5320 };
5321
5322 (error_postfix, self.types().unit())
5323 }
5324 }
5325 }
5326
5327 fn analyze_subscript_range(
5328 &mut self,
5329 collection_type: TypeRef,
5330 range_expression: Expression,
5331 ) -> (Postfix, TypeRef) {
5332 let node = &range_expression.node;
5333 match &*collection_type.kind {
5334 TypeKind::QueueStorage(element_type, _)
5335 | TypeKind::StackStorage(element_type, _)
5336 | TypeKind::StackView(element_type)
5337 | TypeKind::VecStorage(element_type, _)
5338 | TypeKind::StringStorage(element_type, _, _)
5339 | TypeKind::StringView(element_type, _)
5340 | TypeKind::FixedCapacityAndLengthArray(element_type, _)
5341 | TypeKind::DynamicLengthVecView(element_type)
5342 | TypeKind::SliceView(element_type) => {
5343 let vec_type = VecType {
5344 element: element_type.clone(),
5345 };
5346
5347 let postfix = Postfix {
5348 node: node.clone(),
5349 ty: collection_type.clone(),
5350 kind: PostfixKind::VecSubscriptRange(vec_type, range_expression),
5351 };
5352
5353 (postfix, collection_type.clone())
5355 }
5356
5357 _ => {
5358 self.add_err_resolved(ErrorKind::CanNotSubscriptWithThatType, node);
5359
5360 let error_vec_type = VecType {
5361 element: self.types().unit(),
5362 };
5363
5364 let error_postfix = Postfix {
5365 node: node.clone(),
5366 ty: collection_type.clone(),
5367 kind: PostfixKind::VecSubscriptRange(error_vec_type, range_expression),
5368 };
5369
5370 (error_postfix, self.types().unit())
5371 }
5372 }
5373 }
5374 fn analyze_map_subscript(
5375 &mut self,
5376 key_type: &TypeRef,
5377 value_type: &TypeRef,
5378 lookup_expr: &swamp_ast::Expression,
5379 ) -> (Postfix, TypeRef) {
5380 let key_context = TypeContext::new_argument(key_type, false);
5381 let key_expression = self.analyze_expression(lookup_expr, &key_context);
5382
5383 let map_type = MapType {
5384 key: key_type.clone(),
5385 value: value_type.clone(),
5386 };
5387
5388 let postfix = Postfix {
5389 node: self.to_node(&lookup_expr.node),
5390 ty: key_type.clone(),
5391 kind: PostfixKind::MapSubscript(map_type, key_expression),
5392 };
5393
5394 (postfix, value_type.clone())
5395 }
5396}