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::{MAX_VIRTUAL_REGISTER, VariableSlot};
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 {
1558 } else {
1559 tv.resolved_type = self.shared.state.types.optional(&tv.resolved_type.clone());
1560 }
1561 }
1562
1563 self.create_expr(
1564 ExpressionKind::PostfixChain(start_of_chain, suffixes),
1565 tv.resolved_type,
1566 &chain.base.node,
1567 )
1568 }
1569
1570 fn analyze_bool_argument_expression(
1571 &mut self,
1572 expression: &swamp_ast::Expression,
1573 ) -> BooleanExpression {
1574 let bool_type = self.shared.state.types.bool();
1575 let bool_context = TypeContext::new_argument(&bool_type, false);
1576 let resolved_expression = self.analyze_expression(expression, &bool_context);
1577 let expr_type = resolved_expression.ty.clone();
1578
1579 let bool_expression = match &*expr_type.kind {
1580 TypeKind::Bool => resolved_expression,
1581 TypeKind::Optional(_) => {
1582 let bool = self.types().bool();
1583 self.create_expr(
1584 ExpressionKind::CoerceOptionToBool(Box::new(resolved_expression)),
1585 bool,
1586 &expression.node,
1587 )
1588 }
1589 _ => self.create_err(ErrorKind::ExpectedBooleanExpression, &expression.node),
1590 };
1591
1592 BooleanExpression {
1593 expression: Box::from(bool_expression),
1594 }
1595 }
1596
1597 fn is_aggregate_function_call(expression: &swamp_ast::Expression) -> bool {
1599 match &expression.kind {
1600 swamp_ast::ExpressionKind::PostfixChain(chain) => {
1601 if chain.postfixes.is_empty() {
1602 return false;
1603 }
1604
1605 for postfix in &chain.postfixes {
1606 if let swamp_ast::Postfix::FunctionCall(_, _, _) = postfix {
1607 return true;
1608 }
1609 }
1610 false
1611 }
1612 _ => false, }
1614 }
1615
1616 fn analyze_iterable(
1617 &mut self,
1618 mut_requested_for_value_variable: Option<swamp_ast::Node>,
1619 expression: &swamp_ast::Expression,
1620 ) -> Iterable {
1621 let has_lvalue_target = !Self::is_aggregate_function_call(expression);
1624 let any_context = TypeContext::new_anything_argument(has_lvalue_target);
1625
1626 let resolved_expression = self.analyze_expression(expression, &any_context);
1627
1628 let resolved_type = &resolved_expression.ty.clone();
1629 let int_type = Some(self.types().int());
1630 let (key_type, value_type): (Option<TypeRef>, TypeRef) = match &*resolved_type.kind {
1631 TypeKind::StringView(_, char) | TypeKind::StringStorage(_, char, _) => {
1632 (int_type, char.clone())
1633 }
1634 TypeKind::SliceView(element_type) => (int_type, element_type.clone()),
1635 TypeKind::VecStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1636 TypeKind::SparseStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1637 TypeKind::StackStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1638 TypeKind::StackView(element_type) => (int_type, element_type.clone()),
1639 TypeKind::QueueStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1640 TypeKind::QueueView(element_type) => (int_type, element_type.clone()),
1641 TypeKind::DynamicLengthVecView(element_type) => (int_type, element_type.clone()),
1642 TypeKind::SparseView(element_type) => (int_type, element_type.clone()),
1643 TypeKind::FixedCapacityAndLengthArray(element_type, _fixed_size) => {
1644 (int_type, element_type.clone())
1645 }
1646 TypeKind::DynamicLengthMapView(key_type, value_type)
1647 | TypeKind::MapStorage(key_type, value_type, _) => {
1648 (Some(key_type.clone()), value_type.clone())
1649 }
1650 TypeKind::Range(_) => (None, self.types().int()),
1651 _ => {
1652 error!(?resolved_type, "not an iterator");
1653 return Iterable {
1654 key_type: None,
1655 value_type: self.shared.state.types.unit(),
1656 resolved_expression: Box::new(
1657 self.create_err(ErrorKind::NotAnIterator, &expression.node),
1658 ),
1659 };
1660 }
1661 };
1662
1663 if mut_requested_for_value_variable.is_some() {
1664 let _resulting_location =
1666 self.analyze_to_location(expression, &any_context, LocationSide::Mutable);
1667 }
1670
1671 Iterable {
1672 key_type,
1673 value_type,
1674 resolved_expression: Box::new(resolved_expression),
1675 }
1676 }
1677
1678 fn analyze_argument_expressions(
1679 &mut self,
1680 expected_type: Option<&TypeRef>,
1681 context: &TypeContext,
1682 ast_expressions: &[swamp_ast::Expression],
1683 ) -> Vec<Expression> {
1684 let mut resolved_expressions = Vec::new();
1685 let argument_expressions_context = TypeContext::new_unsure_argument(expected_type, false);
1687
1688 for expression in ast_expressions {
1689 resolved_expressions
1690 .push(self.analyze_expression(expression, &argument_expressions_context));
1691 }
1692 resolved_expressions
1693 }
1694
1695 fn analyze_block(
1696 &mut self,
1697 _node: &swamp_ast::Node,
1698 context: &TypeContext,
1699 ast_expressions: &[swamp_ast::Expression],
1700 ) -> (Vec<Expression>, TypeRef) {
1701 if ast_expressions.is_empty() {
1702 return (vec![], self.shared.state.types.unit());
1703 }
1704
1705 self.push_block_scope("block");
1706
1707 let mut resolved_expressions = Vec::with_capacity(ast_expressions.len());
1708
1709 for expression in &ast_expressions[..ast_expressions.len() - 1] {
1710 let unit_type = self.shared.state.types.unit();
1711 let stmt_context =
1712 context.with_expected_type(Some(&unit_type), context.has_lvalue_target);
1713 let expr = self.analyze_expression(expression, &stmt_context);
1714
1715 resolved_expressions.push(expr);
1716 }
1717
1718 let last_expr =
1720 self.analyze_expression(&ast_expressions[ast_expressions.len() - 1], context);
1721 let last_type = last_expr.ty.clone();
1722 resolved_expressions.push(last_expr);
1723
1724 self.pop_block_scope("block");
1725
1726 (resolved_expressions, last_type)
1727 }
1728
1729 fn analyze_interpolated_string_lowering(
1730 &mut self,
1731 node: &swamp_ast::Node,
1732 string_parts: &[swamp_ast::StringPart],
1733 ) -> Expression {
1734 let mut last_expression: Option<Expression> = None;
1735 for part in string_parts {
1736 let created_expression = match part {
1737 swamp_ast::StringPart::Literal(string_node, processed_string) => {
1738 let string_literal =
1739 ExpressionKind::StringLiteral(processed_string.to_string());
1740 let basic_literal = string_literal;
1741 let string_type = self.shared.state.types.string();
1742 self.add_default_functions(&string_type, node);
1743 self.create_expr(basic_literal, string_type, string_node)
1744 }
1745 swamp_ast::StringPart::Interpolation(expression, format_specifier) => {
1746 let any_context = TypeContext::new_anything_argument(false); let expr = self.analyze_expression(expression, &any_context);
1749
1750 let tk = (*expr.ty.kind).clone();
1751
1752 let maybe_to_string = self
1753 .shared
1754 .state
1755 .associated_impls
1756 .get_internal_member_function(&expr.ty, "string");
1757
1758 if matches!(tk, TypeKind::StringView { .. })
1759 || matches!(tk, TypeKind::StringStorage(..))
1760 {
1761 expr
1762 } else {
1763 let underlying = expr.ty.clone();
1764
1765 if self.needs_storage_error(&expr, true, &any_context, &expression.node) {
1767 return self.create_err(ErrorKind::NeedStorage, &expression.node);
1768 }
1769
1770 let call_expr_kind = if maybe_to_string.is_none() {
1771 let string_type = self.types().string();
1772
1773 ExpressionKind::StringLiteral(format!(
1774 "missing to_string for: {string_type}"
1775 ))
1776 } else {
1785 let expr_as_param = ArgumentExpression::Expression(expr);
1786 self.create_static_member_call(
1787 "string",
1788 &[expr_as_param.clone()],
1789 &expression.node,
1790 &underlying,
1791 )
1792 };
1793
1794 let string_type = self.shared.state.types.string();
1802 self.create_expr(call_expr_kind, string_type, &expression.node)
1803 }
1804 }
1805 };
1806
1807 let x_last_expr = if let Some(last_expr) = last_expression.clone() {
1808 let op_kind = BinaryOperatorKind::Add;
1809 let node = created_expression.node.clone();
1810 let op = BinaryOperator {
1811 left: Box::new(last_expr),
1812 right: Box::new(created_expression),
1813 kind: op_kind,
1814 node: node.clone(),
1815 };
1816
1817 let string_type = self.shared.state.types.string();
1818 create_expr_resolved(ExpressionKind::BinaryOp(op), string_type, &node)
1819 } else {
1820 created_expression
1821 };
1822
1823 last_expression = Some(x_last_expr);
1824 }
1825
1826 if let Some(last) = last_expression {
1829 last
1830 } else {
1831 let string_type = self.shared.state.types.string();
1832 self.create_expr(
1833 ExpressionKind::StringLiteral(String::new()),
1834 string_type,
1835 node,
1836 )
1837 }
1838 }
1839
1840 pub(crate) fn analyze_identifier(
1841 &mut self,
1842 qualified_func_name: &swamp_ast::QualifiedIdentifier,
1843 ) -> Expression {
1844 if qualified_func_name.module_path.is_none()
1847 && qualified_func_name.generic_params.is_empty()
1848 && let Some(found_variable) = self.try_find_variable(&qualified_func_name.name)
1849 {
1850 return self.create_expr(
1851 ExpressionKind::VariableAccess(found_variable.clone()),
1852 found_variable.resolved_type.clone(),
1853 &qualified_func_name.name,
1854 );
1855 }
1856
1857 let text = self.get_text(&qualified_func_name.name);
1858 self.create_err(
1859 ErrorKind::UnknownIdentifier(text.to_string()),
1860 &qualified_func_name.name,
1861 )
1862 }
1863
1864 fn analyze_variable_reference(&mut self, var_node: &swamp_ast::Node) -> Expression {
1866 if let Some(found_variable) = self.try_find_variable(var_node) {
1867 let name_node = self.to_node(var_node);
1868
1869 self.shared
1870 .state
1871 .refs
1872 .add(found_variable.symbol_id.into(), name_node.clone());
1873 self.shared
1874 .definition_table
1875 .refs
1876 .add(found_variable.symbol_id.into(), name_node);
1877
1878 return self.create_expr(
1879 ExpressionKind::VariableAccess(found_variable.clone()),
1880 found_variable.resolved_type.clone(),
1881 var_node,
1882 );
1883 }
1884 let text = self.get_text(var_node);
1885 self.create_err(ErrorKind::UnknownIdentifier(text.to_string()), var_node)
1886 }
1887
1888 fn analyze_internal_initializer_pair_list(
1889 &mut self,
1890 node: &swamp_ast::Node,
1891 items: &[(swamp_ast::Expression, swamp_ast::Expression)],
1892 context: &TypeContext,
1893 ) -> (TypeRef, Vec<(Expression, Expression)>) {
1894 let (collection_type, key_type, value_type) = if let Some(expected_type) =
1895 context.expected_type
1896 {
1897 match &*expected_type.kind {
1898 TypeKind::MapStorage(key, value, capacity) => {
1899 if items.len() > *capacity {
1900 self.add_err(
1901 ErrorKind::TooManyInitializerListElementsForStorage {
1902 capacity: *capacity,
1903 },
1904 node,
1905 );
1906 return (self.types().unit(), vec![]);
1907 }
1908 (expected_type.clone(), key.clone(), value.clone())
1909 }
1910 TypeKind::DynamicLengthMapView(key, value) => {
1911 (expected_type.clone(), key.clone(), value.clone())
1912 }
1913 _ => {
1914 self.add_err(ErrorKind::ExpectedSlice, node);
1915 return (self.types().unit(), vec![]);
1916 }
1917 }
1918 } else if items.is_empty() {
1919 self.add_err(ErrorKind::NoInferredTypeForEmptyInitializer, node);
1920 return (self.types().unit(), vec![]);
1921 } else {
1922 let maybe_key_context = TypeContext::new_anything_argument(true);
1924
1925 let first_key_expression = self.analyze_expression(&items[0].0, &maybe_key_context);
1926
1927 let maybe_value_context = TypeContext::new_anything_argument(true);
1928 let first_value_expression = self.analyze_expression(&items[0].1, &maybe_value_context);
1929
1930 let required_key_type = first_key_expression.ty;
1931 let required_value_type = first_value_expression.ty;
1932
1933 let inferred_type =
1934 self.types()
1935 .map_storage(&required_key_type, &required_value_type, items.len());
1936
1937 (inferred_type, required_key_type, required_value_type)
1938 };
1939
1940 assert!(!matches!(*key_type.kind, TypeKind::Unit));
1941 assert!(!matches!(*value_type.kind, TypeKind::Unit));
1942
1943 let required_key_context = TypeContext::new_argument(&key_type, true);
1944 let required_value_context = TypeContext::new_argument(&value_type, true);
1945
1946 let mut resolved_items = Vec::new();
1947
1948 for (key_expr, value_expr) in items {
1949 let analyzed_key_expr = self.analyze_expression(key_expr, &required_key_context);
1950 let analyzed_value_expr = self.analyze_expression(value_expr, &required_value_context);
1951 resolved_items.push((analyzed_key_expr, analyzed_value_expr));
1952 }
1953
1954 (collection_type, resolved_items)
1955 }
1956
1957 fn analyze_internal_initializer_list(
1958 &mut self,
1959 node: &swamp_ast::Node,
1960 items: &[swamp_ast::Expression],
1961 context: &TypeContext,
1962 ) -> (TypeRef, Vec<Expression>) {
1963 let (collection_type, element_type) = if let Some(expected_type) = context.expected_type {
1964 match &*expected_type.kind {
1965 TypeKind::GridStorage(element_type, width, height) => {
1966 let capacity = width * height;
1967 if items.len() > capacity {
1968 return (
1969 self.types().unit(),
1970 self.create_err_vec(
1971 ErrorKind::TooManyInitializerListElementsForStorage { capacity },
1972 node,
1973 ),
1974 );
1975 }
1976 (expected_type.clone(), element_type.clone())
1977 }
1978 TypeKind::StackStorage(element_type, capacity)
1979 | TypeKind::QueueStorage(element_type, capacity)
1980 | TypeKind::SparseStorage(element_type, capacity)
1981 | TypeKind::VecStorage(element_type, capacity) => {
1982 if items.len() > *capacity {
1983 return (
1984 self.types().unit(),
1985 self.create_err_vec(
1986 ErrorKind::TooManyInitializerListElementsForStorage {
1987 capacity: *capacity,
1988 },
1989 node,
1990 ),
1991 );
1992 }
1993 (expected_type.clone(), element_type.clone())
1994 }
1995 TypeKind::QueueView(element_type) => {
1996 let inferred_storage_type =
1998 self.types().queue_storage(element_type, items.len());
1999 let default_node = swamp_ast::Node::default();
2000 self.add_default_functions(&inferred_storage_type, &default_node);
2001 (inferred_storage_type, element_type.clone())
2002 }
2003 TypeKind::SparseView(element_type) => {
2004 let inferred_storage_type =
2006 self.types().sparse_storage(element_type, items.len());
2007 let default_node = swamp_ast::Node::default();
2008 self.add_default_functions(&inferred_storage_type, &default_node);
2009 (inferred_storage_type, element_type.clone())
2010 }
2011 TypeKind::StackView(element_type) => {
2012 let inferred_storage_type =
2014 self.types().stack_storage(element_type, items.len());
2015 let default_node = swamp_ast::Node::default();
2016 self.add_default_functions(&inferred_storage_type, &default_node);
2017 (inferred_storage_type, element_type.clone())
2018 }
2019 TypeKind::GridView(element_type) => {
2020 (expected_type.clone(), element_type.clone())
2022 }
2023 TypeKind::DynamicLengthVecView(element_type) => {
2024 let inferred_storage_type = self.types().vec_storage(element_type, items.len());
2026 let default_node = swamp_ast::Node::default();
2027 self.add_default_functions(&inferred_storage_type, &default_node);
2028 (inferred_storage_type, element_type.clone())
2029 }
2030 TypeKind::SliceView(element_type) => {
2031 let inferred_storage_type = self.types().vec_storage(element_type, items.len());
2033 let default_node = swamp_ast::Node::default();
2034 self.add_default_functions(&inferred_storage_type, &default_node);
2035 (inferred_storage_type, element_type.clone())
2036 }
2037 TypeKind::FixedCapacityAndLengthArray(element_type, _size) => {
2038 (expected_type.clone(), element_type.clone())
2039 }
2040 _ => {
2041 return (
2042 self.types().unit(),
2043 self.create_err_vec(
2044 ErrorKind::ExpectedInitializerTarget {
2045 destination_type: expected_type.clone(),
2046 },
2047 node,
2048 ),
2049 );
2050 }
2051 }
2052 } else if items.is_empty() {
2053 return (
2054 self.types().unit(),
2055 self.create_err_vec(ErrorKind::NoInferredTypeForEmptyInitializer, node),
2056 );
2057 } else {
2058 let maybe_context = TypeContext::new_anything_argument(true);
2060 let first = self.analyze_expression(&items[0], &maybe_context);
2061 let required_type = first.ty;
2062 let inferred_vec_storage_type = self.types().vec_storage(&required_type, items.len());
2063 let default_node = swamp_ast::Node::default();
2065 self.add_default_functions(&inferred_vec_storage_type, &default_node);
2066 (inferred_vec_storage_type, required_type)
2067 };
2068
2069 let required_context = TypeContext::new_argument(&element_type, true);
2070 let mut resolved_items = Vec::new();
2071 for item in items {
2072 let resolved_expr = self.analyze_expression(item, &required_context);
2073 resolved_items.push(resolved_expr);
2074 }
2075 (collection_type, resolved_items)
2076 }
2077
2078 fn push_block_scope(&mut self, debug_str: &str) {
2079 let register_watermark = self.scope.total_scopes.current_register;
2080 self.scope.active_scope.block_scope_stack.push(BlockScope {
2083 mode: BlockScopeMode::Open,
2084 lookup: Default::default(),
2085 variables: SeqMap::default(),
2086 register_watermark,
2087 });
2088 }
2089
2090 fn push_lambda_scope(&mut self, debug_str: &str) {
2091 self.scope.active_scope.block_scope_stack.push(BlockScope {
2094 mode: BlockScopeMode::Lambda,
2095 lookup: SeqMap::default(),
2096 variables: SeqMap::default(),
2097 register_watermark: 0, });
2099 }
2100
2101 fn pop_block_scope(&mut self, debug_str: &str) {
2102 self.pop_any_block_scope();
2104 }
2105
2106 fn push_closed_block_scope(&mut self) {
2107 let register_watermark = self.scope.total_scopes.current_register;
2108 self.scope.active_scope.block_scope_stack.push(BlockScope {
2110 mode: BlockScopeMode::Closed,
2111 lookup: Default::default(),
2112 variables: SeqMap::default(),
2113 register_watermark,
2114 });
2115 }
2116
2117 fn pop_closed_block_scope(&mut self) {
2118 self.pop_any_block_scope();
2120 }
2121
2122 fn pop_any_block_scope(&mut self) {
2123 let scope = self.scope.active_scope.block_scope_stack.pop().unwrap();
2124
2125 if self.scope.total_scopes.current_register
2127 > self.scope.total_scopes.highest_virtual_register
2128 {
2129 self.scope.total_scopes.highest_virtual_register =
2130 self.scope.total_scopes.current_register;
2131 }
2132
2133 let is_inside_lambda = self
2135 .scope
2136 .active_scope
2137 .block_scope_stack
2138 .iter()
2139 .any(|s| matches!(s.mode, BlockScopeMode::Lambda));
2140
2141 if matches!(scope.mode, BlockScopeMode::Lambda) {
2142 } else if is_inside_lambda {
2144 } else {
2146 self.scope.total_scopes.current_register = scope.register_watermark;
2151 }
2152 }
2153
2154 fn analyze_match(
2155 &mut self,
2156 scrutinee: &swamp_ast::Expression,
2157 default_context: &TypeContext,
2158 arms: &Vec<swamp_ast::MatchArm>,
2159 ) -> (Match, TypeRef) {
2160 let mut known_type = default_context.expected_type.cloned();
2161 let own_context = default_context.clone();
2162
2163 self.push_block_scope("match block");
2164 let scrutinee_context = TypeContext::new_anything_argument(true); let resolved_scrutinee = self.analyze_expression(scrutinee, &scrutinee_context);
2167 let scrutinee_type = resolved_scrutinee.ty.clone();
2168
2169 let mut resolved_arms = Vec::with_capacity(arms.len());
2170
2171 if arms.is_empty() {
2173 let err_match = Match {
2174 expression: Box::new(
2175 self.create_err(ErrorKind::MatchMustHaveAtLeastOneArm, &scrutinee.node),
2176 ),
2177 arms: resolved_arms,
2178 };
2179 return (err_match, self.types().unit());
2180 }
2181
2182 for arm in arms {
2183 let (resolved_arm, _anyone_wants_mutable) = self.analyze_arm(
2184 arm,
2185 &resolved_scrutinee,
2186 &own_context.with_expected_type(known_type.as_ref(), false),
2187 &scrutinee_type,
2188 );
2189
2190 if known_type.is_none() {
2191 known_type = Some(resolved_arm.expression.ty.clone());
2192 }
2193 resolved_arms.push(resolved_arm);
2194 }
2195
2196 self.pop_block_scope("match block");
2197
2198 if let Some(encountered_type) = known_type {
2199 (
2200 Match {
2201 expression: Box::new(resolved_scrutinee),
2202 arms: resolved_arms,
2203 },
2204 encountered_type,
2205 )
2206 } else {
2207 let err_expr = self.create_err(ErrorKind::MatchArmsMustHaveTypes, &scrutinee.node);
2208
2209 (
2210 Match {
2211 expression: Box::new(err_expr),
2212 arms: resolved_arms.clone(),
2213 },
2214 self.types().unit(),
2215 )
2216 }
2217 }
2218
2219 fn analyze_arm(
2220 &mut self,
2221 arm: &swamp_ast::MatchArm,
2222 _expression: &Expression,
2223 type_context: &TypeContext,
2224 expected_condition_type: &TypeRef,
2225 ) -> (MatchArm, bool) {
2226 let (resolved_pattern, scope_was_pushed, anyone_wants_mutable) =
2227 self.analyze_pattern(&arm.pattern, expected_condition_type);
2228
2229 let resolved_expression = self.analyze_expression(&arm.expression, type_context);
2230 if scope_was_pushed {
2231 self.pop_block_scope(&format!("analyze_arm {:?}", arm.expression));
2232 }
2233
2234 let resolved_type = resolved_expression.ty.clone();
2235
2236 (
2237 MatchArm {
2238 pattern: resolved_pattern,
2239 expression: Box::from(resolved_expression),
2240 expression_type: resolved_type,
2241 },
2242 anyone_wants_mutable,
2243 )
2244 }
2245
2246 fn str_to_int(text: &str) -> Result<i32, ParseIntError> {
2247 let text = text.replace('_', "");
2248 text.strip_prefix("0x").map_or_else(
2249 || {
2250 text.strip_prefix("-0x").map_or_else(
2251 || text.parse::<i32>(),
2252 |rest| i32::from_str_radix(rest, 16).map(|x| -x),
2253 )
2254 },
2255 |rest| i32::from_str_radix(rest, 16),
2256 )
2257 }
2258
2259 pub fn str_to_byte(text: &str) -> Result<u8, ParseByteError> {
2260 let inner = text
2262 .strip_prefix("b'")
2263 .and_then(|s| s.strip_suffix("'"))
2264 .ok_or(ParseByteError::InvalidFormat)?;
2265
2266 let mut chars = inner.chars();
2267 let first = chars.next().ok_or(ParseByteError::InvalidFormat)?;
2268
2269 if first == '\\' {
2270 let esc = chars.next().ok_or(ParseByteError::InvalidEscape)?;
2271 if chars.next().is_some() {
2272 return Err(ParseByteError::InvalidFormat);
2273 }
2274 return match esc {
2275 'n' => Ok(b'\n'),
2276 'r' => Ok(b'\r'),
2277 't' => Ok(b'\t'),
2278 '0' => Ok(b'\0'),
2279 '\\' => Ok(b'\\'),
2280 '\'' => Ok(b'\''),
2281 _ => Err(ParseByteError::InvalidEscape),
2282 };
2283 }
2284
2285 if first.is_ascii() && chars.next().is_none() {
2286 return Ok(first as u8);
2287 }
2288
2289 Err(ParseByteError::InvalidFormat)
2290 }
2291 fn str_to_unsigned_int(text: &str) -> Result<u32, ParseIntError> {
2292 let text = text.replace('_', "");
2293 text.strip_prefix("0x")
2294 .map_or_else(|| text.parse::<u32>(), |rest| u32::from_str_radix(rest, 16))
2295 }
2296
2297 fn str_to_float(text: &str) -> Result<f32, ParseFloatError> {
2298 text.parse::<f32>()
2299 }
2300
2301 fn str_to_bool(text: &str) -> Result<bool, ParseBoolError> {
2302 bool::from_str(text)
2303 }
2304
2305 fn analyze_pattern_literal(
2306 &mut self,
2307 node: &swamp_ast::Node,
2308 ast_literal: &swamp_ast::LiteralKind,
2309 expected_condition_type: &TypeRef,
2310 ) -> NormalPattern {
2311 let required_condition_type_context =
2312 TypeContext::new_argument(expected_condition_type, false);
2313 let literal = self.analyze_literal(
2314 node,
2315 ast_literal,
2316 &required_condition_type_context,
2317 &required_condition_type_context,
2318 );
2319
2320 if !self
2321 .types()
2322 .compatible_with(&literal.ty, expected_condition_type)
2323 {
2324 return NormalPattern::Literal(self.create_err(
2325 ErrorKind::IncompatibleTypes {
2326 expected: expected_condition_type.clone(),
2327 found: literal.ty,
2328 },
2329 node,
2330 ));
2331 }
2332
2333 NormalPattern::Literal(literal)
2334 }
2335
2336 const fn to_node(&self, node: &swamp_ast::Node) -> Node {
2337 Node {
2338 span: Span {
2339 file_id: self.shared.file_id,
2340 offset: node.span.offset,
2341 length: node.span.length,
2342 },
2343 }
2344 }
2345
2346 fn get_module_path(&self, module_path: Option<&swamp_ast::ModulePath>) -> Vec<String> {
2347 module_path.as_ref().map_or_else(Vec::new, |found| {
2348 let mut strings = Vec::new();
2349 for path_item in &found.0 {
2350 strings.push(self.get_text(path_item).to_string());
2351 }
2352 strings
2353 })
2354 }
2355
2356 fn get_enum_variant_type(
2357 &mut self,
2358 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2359 variant_name: &str,
2360 ) -> EnumVariantType {
2361 let Some((symbol_table, enum_name)) =
2362 self.get_symbol_table_and_name(qualified_type_identifier)
2363 else {
2364 self.add_err(
2365 ErrorKind::UnknownEnumVariantType,
2366 &qualified_type_identifier.name.0,
2367 );
2368 return EnumVariantType {
2369 common: EnumVariantCommon {
2370 symbol_id: TopLevelSymbolId::new_illegal(),
2371 name: Default::default(),
2372 assigned_name: String::new(),
2373 container_index: 0,
2374 },
2375 payload_type: self.types().unit(),
2376 };
2377 };
2378
2379 if let Some(enum_name) = symbol_table.get_enum_variant_type(&enum_name, variant_name) {
2380 enum_name
2381 } else {
2382 self.add_err(
2383 ErrorKind::UnknownEnumVariantType,
2384 &qualified_type_identifier.name.0,
2385 );
2386 EnumVariantType {
2387 common: EnumVariantCommon {
2388 symbol_id: TopLevelSymbolId::new_illegal(),
2389 name: Default::default(),
2390 assigned_name: String::new(),
2391 container_index: 0,
2392 },
2393 payload_type: self.types().unit(),
2394 }
2395 }
2396 }
2397
2398 pub(crate) fn get_symbol_table_and_name(
2399 &self,
2400 type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2401 ) -> Option<(&DefinitionTable, String)> {
2402 let path = self.get_module_path(type_identifier.module_path.as_ref());
2403 let name = self.get_text(&type_identifier.name.0).to_string();
2404
2405 if let Some(found) = self.shared.get_definition_table(&path) {
2406 Some((found, name))
2407 } else {
2408 None
2409 }
2410 }
2411
2412 const fn analyze_compound_operator(
2413 &self,
2414 ast_operator: &swamp_ast::CompoundOperator,
2415 ) -> CompoundOperator {
2416 let resolved_node = self.to_node(&ast_operator.node);
2417 let resolved_kind = match ast_operator.kind {
2418 swamp_ast::CompoundOperatorKind::Add => CompoundOperatorKind::Add,
2419 swamp_ast::CompoundOperatorKind::Sub => CompoundOperatorKind::Sub,
2420 swamp_ast::CompoundOperatorKind::Mul => CompoundOperatorKind::Mul,
2421 swamp_ast::CompoundOperatorKind::Div => CompoundOperatorKind::Div,
2422 swamp_ast::CompoundOperatorKind::Modulo => CompoundOperatorKind::Modulo,
2423 };
2424
2425 CompoundOperator {
2426 node: resolved_node,
2427 kind: resolved_kind,
2428 }
2429 }
2430
2431 const fn to_node_option(&self, maybe_node: Option<&swamp_ast::Node>) -> Option<Node> {
2432 match maybe_node {
2433 None => None,
2434 Some(node) => Some(self.to_node(node)),
2435 }
2436 }
2437
2438 const fn analyze_format_specifier(
2439 &self,
2440 ast_format_specifier: Option<&swamp_ast::FormatSpecifier>,
2441 ) -> Option<FormatSpecifier> {
2442 let f = match ast_format_specifier {
2443 None => return None,
2444 Some(ast_format) => match ast_format {
2445 swamp_ast::FormatSpecifier::LowerHex(node) => FormatSpecifier {
2446 node: self.to_node(node),
2447 kind: FormatSpecifierKind::LowerHex,
2448 },
2449 swamp_ast::FormatSpecifier::UpperHex(node) => FormatSpecifier {
2450 node: self.to_node(node),
2451 kind: FormatSpecifierKind::UpperHex,
2452 },
2453 swamp_ast::FormatSpecifier::Binary(node) => FormatSpecifier {
2454 node: self.to_node(node),
2455 kind: FormatSpecifierKind::Binary,
2456 },
2457 swamp_ast::FormatSpecifier::Float(node) => FormatSpecifier {
2458 node: self.to_node(node),
2459 kind: FormatSpecifierKind::Float,
2460 },
2461 swamp_ast::FormatSpecifier::Precision(value, node, x) => {
2462 let (precision_type, precision_node) = match x {
2463 swamp_ast::PrecisionType::Float(node) => {
2464 (PrecisionType::Float, self.to_node(node))
2465 }
2466 swamp_ast::PrecisionType::String(node) => {
2467 (PrecisionType::String, self.to_node(node))
2468 }
2469 };
2470 FormatSpecifier {
2471 node: self.to_node(node),
2472 kind: FormatSpecifierKind::Precision(
2473 *value,
2474 precision_node,
2475 precision_type,
2476 ),
2477 }
2478 }
2479 },
2480 };
2481
2482 Some(f)
2483 }
2484
2485 fn analyze_with_expr(
2486 &mut self,
2487 context: &TypeContext,
2488 variables: &[swamp_ast::VariableBinding],
2489 expression: &swamp_ast::Expression,
2490 ) -> Expression {
2491 let mut variable_expressions = Vec::new();
2492
2493 for variable in variables {
2494 let any_context = TypeContext::new_anything_argument(false);
2495 let must_have_expression = if let Some(x) = &variable.expression {
2496 x
2497 } else {
2498 &swamp_ast::Expression {
2499 kind: swamp_ast::ExpressionKind::VariableReference(variable.variable.clone()),
2500 node: variable.variable.name.clone(),
2501 }
2502 };
2503
2504 let location_side = if variable.variable.is_mutable.is_some() {
2506 if let Some(expr) = &variable.expression {
2508 let maybe_ref = self.analyze_maybe_ref_expression(expr);
2510 if maybe_ref.has_borrow_mutable_reference.is_some() {
2511 LocationSide::Mutable
2512 } else {
2513 LocationSide::Rhs
2514 }
2515 } else {
2516 LocationSide::Rhs
2518 }
2519 } else {
2520 LocationSide::Rhs
2522 };
2523
2524 let var = self.analyze_mut_or_immutable_expression(
2525 must_have_expression,
2526 &any_context,
2527 location_side,
2528 );
2529
2530 variable_expressions.push(var);
2531 }
2532
2533 self.push_closed_block_scope();
2534 let mut expressions = Vec::new();
2535 for (variable_binding, resolved_expression) in variables.iter().zip(variable_expressions) {
2536 let initialize_variable_expression = self
2537 .create_variable_binding_for_with(&variable_binding.variable, resolved_expression);
2538
2539 expressions.push(initialize_variable_expression);
2543 }
2544
2545 let resolved_expression = self.analyze_expression(expression, context);
2546 let block_type = self.types().unit();
2548 expressions.push(resolved_expression);
2549
2550 let block_expression_kind = ExpressionKind::Block(expressions);
2551 self.pop_closed_block_scope();
2552
2553 self.create_expr(block_expression_kind, block_type, &expression.node)
2554 }
2555
2556 fn analyze_when_expr(
2557 &mut self,
2558 context: &TypeContext,
2559 variables: &[swamp_ast::VariableBinding],
2560 true_expr: &swamp_ast::Expression,
2561 else_expr: Option<&swamp_ast::Expression>,
2562 ) -> Expression {
2563 self.push_block_scope("when");
2565 let mut bindings = Vec::new();
2566 for variable_binding in variables {
2567 let mut_expr = if let Some(found_expr) = &variable_binding.expression {
2568 let any_context = TypeContext::new_anything_argument(true); self.analyze_mut_or_immutable_expression(
2570 found_expr,
2571 &any_context,
2572 LocationSide::Rhs,
2573 )
2574 .expect_immutable()
2575 .unwrap()
2576 } else {
2577 let same_var = self.find_variable(&variable_binding.variable);
2578
2579 let generated_expr_kind = ExpressionKind::VariableAccess(same_var.clone());
2582 self.create_expr(
2583 generated_expr_kind,
2584 same_var.resolved_type.clone(),
2585 &variable_binding.variable.name,
2586 )
2587 };
2588
2589 let tk = &mut_expr.ty.kind;
2590
2591 if let TypeKind::Optional(found_ty) = &**tk {
2592 let variable_ref = { self.create_variable(&variable_binding.variable, found_ty)
2597 };
2600
2601 let binding = WhenBinding {
2602 variable: variable_ref,
2603 expr: mut_expr,
2604 };
2605 bindings.push(binding);
2606 } else {
2607 return self.create_err(ErrorKind::ExpectedOptional, &true_expr.node);
2608 }
2609 }
2610
2611 let resolved_true = self.analyze_expression(true_expr, context);
2612 let block_type = resolved_true.ty.clone();
2613
2614 self.pop_block_scope("when");
2615
2616 let maybe_resolved_else = if let Some(found_else) = else_expr {
2617 let block_type_for_true_context = context.we_know_expected_type(&block_type, false);
2618 Some(Box::new(self.analyze_expression(
2619 found_else,
2620 &block_type_for_true_context,
2621 )))
2622 } else {
2623 None
2624 };
2625
2626 let when_kind =
2627 ExpressionKind::When(bindings, Box::from(resolved_true), maybe_resolved_else);
2628
2629 self.create_expr(when_kind, block_type, &true_expr.node)
2630 }
2631
2632 fn analyze_guard(
2633 &mut self,
2634 node: &swamp_ast::Node,
2635 context: &TypeContext,
2636 guard_expressions: &Vec<swamp_ast::GuardExpr>,
2637 ) -> Expression {
2638 let mut guards = Vec::new();
2639 let mut found_wildcard = None;
2640 let mut detected_type = context.expected_type.cloned();
2641
2642 for guard in guard_expressions {
2643 let resolved_condition = match &guard.clause {
2644 swamp_ast::GuardClause::Wildcard(x) => {
2645 if found_wildcard.is_some() {
2646 return self.create_err(ErrorKind::GuardCanNotHaveMultipleWildcards, node);
2647 }
2648 found_wildcard = Some(x);
2649 None
2650 }
2651 swamp_ast::GuardClause::Expression(clause_expr) => {
2652 if found_wildcard.is_some() {
2653 return self.create_err(ErrorKind::WildcardMustBeLastInGuard, node);
2654 }
2655 Some(self.analyze_bool_argument_expression(clause_expr))
2656 }
2657 };
2658
2659 let resolved_result = self.analyze_expression(
2660 &guard.result,
2661 &context.with_expected_type(detected_type.as_ref(), false),
2662 );
2663 let ty = resolved_result.ty.clone();
2664 if detected_type.is_none() {
2665 detected_type = Some(ty.clone());
2666 }
2667
2668 guards.push(Guard {
2669 condition: resolved_condition,
2670 result: resolved_result,
2671 });
2672 }
2673
2674 if found_wildcard.is_none() {
2675 return self.create_err(ErrorKind::GuardMustHaveWildcard, node);
2676 }
2677
2678 let kind = ExpressionKind::Guard(guards);
2679
2680 if let Some(found_expecting_type) = detected_type {
2681 self.create_expr(kind, found_expecting_type, node)
2682 } else {
2683 self.create_err(ErrorKind::GuardHasNoType, node)
2684 }
2685 }
2686
2687 fn analyze_lambda(
2688 &mut self,
2689 node: &swamp_ast::Node,
2690 variables: &[swamp_ast::Variable],
2691 ast_expr: &swamp_ast::Expression,
2692 context: &TypeContext,
2693 ) -> Expression {
2694 let TypeKind::Function(signature) = &*context.expected_type.unwrap().kind else {
2695 return self.create_err(ErrorKind::ExpectedLambda, node);
2696 };
2697
2698 let return_block_type = TypeContext::new_argument(&signature.return_type, false);
2699
2700 self.push_lambda_scope("lambda");
2703
2704 let arity_required = signature.parameters.len();
2705 let variable_types_to_create = if variables.len() == arity_required {
2706 &signature.parameters
2707 } else if variables.len() + 1 == arity_required {
2708 &signature.parameters[1..].to_vec()
2709 } else {
2710 return self.create_err(ErrorKind::WrongNumberOfArguments(0, 0), node);
2711 };
2712
2713 let mut resolved_variables = Vec::new();
2714 for (variable, variable_type) in variables.iter().zip(variable_types_to_create) {
2715 let variable_ref = self.create_local_variable(
2716 &variable.name,
2717 variable.is_mutable.as_ref(),
2718 &variable_type.resolved_type,
2719 false,
2720 );
2721 resolved_variables.push(variable_ref);
2722 }
2723
2724 let analyzed_expression = self.analyze_expression(ast_expr, &return_block_type);
2727
2728 self.pop_block_scope("lambda");
2729
2730 let function_type = self.types().function(signature.clone());
2731 self.create_expr(
2732 ExpressionKind::Lambda(resolved_variables, Box::new(analyzed_expression)),
2733 function_type,
2734 node,
2735 )
2736 }
2737
2738 #[must_use]
2739 pub fn chain_is_owned_result(
2740 start_of_chain: &StartOfChain,
2741 chains: &Vec<Postfix>,
2742 ) -> (bool, bool) {
2743 let mut is_owned_result = matches!(start_of_chain.kind, StartOfChainKind::Expression(_));
2744 let mut is_mutable = if let StartOfChainKind::Variable(var) = &start_of_chain.kind {
2745 var.is_mutable()
2746 } else {
2747 false
2748 };
2749
2750 for chain in chains {
2751 match chain.kind {
2752 PostfixKind::StructField(_, _) => {
2753 is_owned_result = false;
2754 }
2755 PostfixKind::MemberCall(_, _) => {
2756 is_owned_result = true;
2757 is_mutable = false;
2758 }
2759 PostfixKind::OptionalChainingOperator => {
2760 is_owned_result = true;
2761 is_mutable = false;
2762 }
2763 PostfixKind::VecSubscript(_, _) => {}
2764 PostfixKind::VecSubscriptRange(_, _) => {}
2765 PostfixKind::SparseSubscript(_, _) => {}
2766 PostfixKind::GridSubscript(_, _, _) => {}
2767 PostfixKind::MapSubscript(_, _) => {}
2768 }
2769 }
2770
2771 (is_owned_result, is_mutable)
2772 }
2773
2774 pub fn check_assignment_mode(
2775 &mut self,
2776 lhs_is_mutable: bool,
2777 source_expression: &Expression,
2778 ty: &TypeRef,
2779 ) -> AssignmentMode {
2780 if matches!(
2781 &source_expression.kind,
2782 _ | ExpressionKind::IntrinsicCallEx(_, _)
2783 ) {
2784 return AssignmentMode::OwnedValue;
2785 }
2786
2787 if let ExpressionKind::PostfixChain(start_chain, postfix) = &source_expression.kind {
2795 let (chain_is_owned, chain_is_mutable) =
2796 Self::chain_is_owned_result(start_chain, postfix);
2797 if lhs_is_mutable {
2798 return if chain_is_mutable {
2799 AssignmentMode::CopyBlittable
2800 } else if lhs_is_mutable {
2801 if chain_is_owned {
2802 AssignmentMode::OwnedValue
2803 } else {
2804 AssignmentMode::CopyBlittable
2805 }
2806 } else {
2807 AssignmentMode::CopySharedPtr
2808 };
2809 }
2810 }
2812
2813 AssignmentMode::CopyBlittable
2814 }
2815
2816 pub const fn check_mutable_assignment(&mut self, assignment_mode: AssignmentMode, node: &Node) {
2817 }
2818
2819 pub const fn check_mutable_variable_assignment(
2820 &mut self,
2821 source_expression: &swamp_ast::Expression,
2822 ty: &TypeRef,
2823 variable: &swamp_ast::Variable,
2824 ) {
2825 }
2831
2832 pub fn analyze_variable_definition(
2835 &mut self,
2836 variable: &swamp_ast::Variable,
2837 annotation_type: &Option<swamp_ast::Type>,
2838 source_expression: &swamp_ast::Expression,
2839 ) -> Expression {
2840 let maybe_found_variable = self.try_find_variable(&variable.name);
2841 if maybe_found_variable.is_some() {
2842 return self.create_err(ErrorKind::OverwriteVariableNotAllowedHere, &variable.name);
2843 }
2844
2845 let node = self.to_node(&variable.name);
2846
2847 let Some(variable_slot) = self.reserve_slot(&node) else {
2848 return self.create_err(ErrorKind::OutOfVirtualRegisters, &variable.name);
2849 };
2850
2851 let maybe_annotated_type = annotation_type.as_ref().map(|found_ast_type| {
2852 self.analyze_type(found_ast_type, &TypeAnalyzeContext::default())
2853 });
2854
2855 self.common_variable_util(
2856 VariableResolution::ReservedSlot(variable_slot, variable.clone(), maybe_annotated_type),
2857 &variable.name,
2858 source_expression,
2859 )
2860 }
2861
2862 pub fn analyze_variable_assignment(
2865 &mut self,
2866 variable: &swamp_ast::Variable,
2867 source_expression: &swamp_ast::Expression,
2868 ) -> Expression {
2869 let maybe_found_variable = self.try_find_variable(&variable.name);
2870
2871 let node = self.to_node(&variable.name);
2872 let resolution = if let Some(found_var) = maybe_found_variable {
2873 VariableResolution::ExistingVariable(found_var)
2874 } else {
2875 let Some(variable_slot) = self.reserve_slot(&node) else {
2876 return self.create_err(ErrorKind::OutOfVirtualRegisters, &variable.name);
2877 };
2878
2879 VariableResolution::ReservedSlot(variable_slot, variable.clone(), None)
2880 };
2881
2882 self.common_variable_util(resolution, &variable.name, source_expression)
2883 }
2884
2885 pub fn common_variable_util(
2886 &mut self,
2887 variable_resolution: VariableResolution,
2888 ast_node: &swamp_ast::Node,
2889 source_expression: &swamp_ast::Expression,
2890 ) -> Expression {
2891 let node = self.to_node(ast_node);
2892
2893 let maybe_annotated_type = match &variable_resolution {
2894 VariableResolution::ExistingVariable(existing_var) => {
2895 Some(existing_var.resolved_type.clone())
2896 }
2897 VariableResolution::ReservedSlot(_, _, maybe_annotated) => maybe_annotated.clone(),
2898 };
2899
2900 let (final_variable_type, final_source_expression) =
2901 self.resolve_variable_expression(maybe_annotated_type, source_expression);
2902
2903 let variable_type = match &variable_resolution {
2904 VariableResolution::ExistingVariable(existing) => existing.variable_type.clone(),
2905 VariableResolution::ReservedSlot(_, _, _) => VariableType::Local,
2906 };
2907
2908 let debug_text = self.get_text(ast_node);
2909 let unused_var = debug_text.starts_with('_');
2910
2911 if !unused_var {
2912 match variable_type {
2914 VariableType::Local => {
2915 if !final_variable_type.can_be_stored_in_variable() {
2916 return self.create_err_resolved(
2917 ErrorKind::VariableTypeMustBeAtLeastTransient(final_variable_type),
2918 &node,
2919 );
2920 }
2921 }
2922
2923 VariableType::Parameter => {
2924 if !final_variable_type.allowed_as_return_type() {
2925 return self.create_err_resolved(
2926 ErrorKind::VariableTypeMustBeAtLeastTransient(final_variable_type),
2927 &node,
2928 );
2929 }
2930 }
2931 }
2932 }
2933
2934 let kind = match variable_resolution {
2935 VariableResolution::ExistingVariable(found_variable) => {
2936 self.shared
2937 .state
2938 .refs
2939 .add(found_variable.symbol_id.into(), node.clone());
2940 self.shared
2941 .definition_table
2942 .refs
2943 .add(found_variable.symbol_id.into(), node.clone());
2944
2945 ExpressionKind::VariableReassignment(
2946 found_variable,
2947 Box::from(final_source_expression),
2948 )
2949 }
2950 VariableResolution::ReservedSlot(reserved_slot, ast_variable, maybe_annotated) => {
2951 let final_type = if let Some(annotated_type) = maybe_annotated {
2952 annotated_type
2953 } else {
2954 final_source_expression.ty.clone()
2955 };
2956
2957 let (found_variable, _some_string) = self.create_local_variable_with_reserved_slot(
2958 reserved_slot,
2959 ast_variable,
2960 &final_type,
2961 );
2962 ExpressionKind::VariableDefinition(
2963 found_variable,
2964 Box::from(final_source_expression),
2965 )
2966 }
2967 };
2968
2969 let unit_type = self.shared.state.types.unit();
2970 self.create_expr(kind, unit_type, ast_node)
2971 }
2972
2973 pub fn resolve_variable_expression(
2976 &mut self,
2977 maybe_annotated_type: Option<TypeRef>,
2978 source_expression: &swamp_ast::Expression,
2979 ) -> (TypeRef, Expression) {
2980 let source_expr = if let Some(target_type) = &maybe_annotated_type {
2981 self.analyze_expression_for_assignment_with_target_type(target_type, source_expression)
2982 } else {
2983 let any_type_context = TypeContext::new_anything_argument(true);
2984 self.analyze_expression(source_expression, &any_type_context)
2985 };
2986
2987 let determined_variable_type = if let Some(found_type) = &maybe_annotated_type {
2990 found_type
2991 } else {
2992 &source_expr.ty.clone()
2993 };
2994
2995 (determined_variable_type.clone(), source_expr)
2998 }
2999
3000 fn add_location_item(
3120 &mut self,
3121 vec: &mut Vec<LocationAccess>,
3122 kind: LocationAccessKind,
3123 ty: TypeRef,
3124 ast_node: &swamp_ast::Node,
3125 ) {
3126 let resolved_node = self.to_node(ast_node);
3127 let postfix = LocationAccess {
3128 node: resolved_node,
3129 ty,
3130 kind,
3131 };
3132
3133 vec.push(postfix);
3134 }
3135
3136 fn extract_single_intrinsic_call(
3137 body: &Expression,
3138 ) -> Option<(IntrinsicFunction, Vec<ArgumentExpression>)> {
3139 if let ExpressionKind::Block(expressions) = &body.kind {
3140 let first_kind = &expressions[0].kind;
3141 if let ExpressionKind::IntrinsicCallEx(intrinsic_fn, args) = &first_kind {
3142 return Some((intrinsic_fn.clone(), args.clone()));
3143 }
3144 }
3145 None
3146 }
3147
3148 #[allow(clippy::too_many_lines)]
3149 fn analyze_chain_to_location(
3150 &mut self,
3151 chain: &swamp_ast::PostfixChain,
3152 context: &TypeContext,
3153 location_side: LocationSide,
3154 ) -> SingleLocationExpression {
3155 let mut items = Vec::new();
3156
3157 let nothing_context = TypeContext::new(None, true);
3158
3159 let base_expr = self.analyze_expression(&chain.base, ¬hing_context);
3160 let ExpressionKind::VariableAccess(start_variable) = base_expr.kind else {
3161 self.add_err(ErrorKind::NotValidLocationStartingPoint, &chain.base.node);
3162 let unit_type = self.types().unit();
3163 let err_variable = Variable {
3164 symbol_id: ScopedSymbolId::new_illegal(),
3165 name: Default::default(),
3166 assigned_name: String::new(),
3167 resolved_type: unit_type,
3168 mutable_node: None,
3169 variable_type: VariableType::Local,
3170 scope_index: 0,
3171 variable_index: 0,
3172 unique_id_within_function: 0,
3173 virtual_register: 0,
3174 is_unused: false,
3175 };
3176 return SingleLocationExpression {
3177 kind: MutableReferenceKind::MutVariableRef,
3178 node: self.to_node(&chain.base.node),
3179 ty: self.shared.state.types.unit(),
3180 starting_variable: VariableRef::from(err_variable),
3181 access_chain: vec![],
3182 };
3183 };
3184
3185 if !start_variable.is_mutable() {
3186 self.add_err(ErrorKind::VariableIsNotMutable, &chain.base.node);
3187
3188 let unit_type = self.types().unit();
3189 let err_variable = Variable {
3190 symbol_id: ScopedSymbolId::new_illegal(),
3191 name: Default::default(),
3192 assigned_name: String::new(),
3193 resolved_type: unit_type,
3194 mutable_node: None,
3195 variable_type: VariableType::Local,
3196 scope_index: 0,
3197 variable_index: 0,
3198 unique_id_within_function: 0,
3199 virtual_register: 0,
3200 is_unused: false,
3201 };
3202 return SingleLocationExpression {
3203 kind: MutableReferenceKind::MutVariableRef,
3204 node: self.to_node(&chain.base.node),
3205 ty: self.shared.state.types.unit(),
3206 starting_variable: VariableRef::from(err_variable),
3207 access_chain: vec![],
3208 };
3209 }
3210
3211 let mut ty = start_variable.resolved_type.clone();
3212 for (i, item) in chain.postfixes.iter().enumerate() {
3213 let is_absolute_last_in_chain = i == chain.postfixes.len() - 1;
3214 match &item {
3215 swamp_ast::Postfix::FieldAccess(field_name_node) => {
3216 let (struct_type_ref, index, return_type) =
3218 self.analyze_struct_field(field_name_node, &ty);
3219
3220 self.add_location_item(
3221 &mut items,
3222 LocationAccessKind::FieldIndex(struct_type_ref.clone(), index),
3223 return_type.clone(),
3224 field_name_node,
3225 );
3226
3227 ty = return_type.clone();
3228 }
3229 swamp_ast::Postfix::SubscriptTuple(x_expr, y_expr) => match &*ty.kind {
3230 TypeKind::GridView(element_type)
3231 | TypeKind::GridStorage(element_type, _, _) => {
3232 let int_type = self.types().int();
3233 let unsigned_int_context = TypeContext::new_argument(&int_type, true);
3234 let unsigned_int_x_expr =
3235 self.analyze_expression(x_expr, &unsigned_int_context);
3236
3237 let unsigned_int_y_expr =
3238 self.analyze_expression(y_expr, &unsigned_int_context);
3239
3240 let grid_type = GridType {
3241 element: element_type.clone(),
3242 };
3243
3244 self.add_location_item(
3245 &mut items,
3246 LocationAccessKind::GridSubscript(
3247 grid_type,
3248 unsigned_int_x_expr,
3249 unsigned_int_y_expr,
3250 ),
3251 element_type.clone(),
3252 &x_expr.node,
3253 );
3254
3255 ty = element_type.clone();
3256 }
3257 _ => {
3258 self.add_err_resolved(
3259 ErrorKind::CanNotSubscriptWithThatType,
3260 &base_expr.node,
3261 );
3262
3263 return SingleLocationExpression {
3264 kind: MutableReferenceKind::MutVariableRef,
3265 node: Default::default(),
3266 ty,
3267 starting_variable: Rc::new(Variable {
3268 symbol_id: ScopedSymbolId::new_illegal(),
3269 name: Default::default(),
3270 assigned_name: String::new(),
3271 resolved_type: Rc::new(Type {
3272 id: TypeId::new(0),
3273 flags: Default::default(),
3274 kind: Rc::new(TypeKind::Byte),
3275 }),
3276 mutable_node: None,
3277 variable_type: VariableType::Local,
3278 scope_index: 0,
3279 variable_index: 0,
3280 unique_id_within_function: 0,
3281 virtual_register: 0,
3282 is_unused: false,
3283 }),
3284 access_chain: vec![],
3285 };
3286 }
3287 },
3288 swamp_ast::Postfix::Subscript(ast_key_expression) => {
3289 let underlying = &ty.kind;
3290 match &**underlying {
3291 TypeKind::SliceView(element_type)
3292 | TypeKind::StackStorage(element_type, _)
3293 | TypeKind::StackView(element_type)
3294 | TypeKind::VecStorage(element_type, _)
3295 | TypeKind::DynamicLengthVecView(element_type)
3296 | TypeKind::FixedCapacityAndLengthArray(element_type, _) => {
3297 let int_type = self.types().int();
3298 let unsigned_int_context = TypeContext::new_argument(&int_type, false);
3299 let unsigned_int_expr =
3300 self.analyze_expression(ast_key_expression, &unsigned_int_context);
3301
3302 let slice_type = SliceViewType {
3303 element: element_type.clone(),
3304 };
3305
3306 self.add_location_item(
3307 &mut items,
3308 LocationAccessKind::SliceViewSubscript(
3309 slice_type,
3310 unsigned_int_expr,
3311 ),
3312 element_type.clone(),
3313 &ast_key_expression.node,
3314 );
3315
3316 ty = element_type.clone();
3317 }
3318 TypeKind::SparseView(element_type)
3319 | TypeKind::SparseStorage(element_type, _) => {
3320 let int_type = self.types().int();
3321 let unsigned_int_context = TypeContext::new_argument(&int_type, false);
3322 let unsigned_int_expr =
3323 self.analyze_expression(ast_key_expression, &unsigned_int_context);
3324
3325 let slice_type = SparseType {
3326 element: element_type.clone(),
3327 };
3328
3329 self.add_location_item(
3330 &mut items,
3331 LocationAccessKind::SparseSubscript(slice_type, unsigned_int_expr),
3332 element_type.clone(),
3333 &ast_key_expression.node,
3334 );
3335
3336 ty = element_type.clone();
3337 }
3338 TypeKind::MapStorage(key_type, value_type, ..)
3339 | TypeKind::DynamicLengthMapView(key_type, value_type) => {
3340 let key_index_context = TypeContext::new_argument(key_type, false);
3341 let key_expr =
3342 self.analyze_expression(ast_key_expression, &key_index_context);
3343
3344 let map_like_type = MapType {
3345 key: key_type.clone(),
3346 value: value_type.clone(),
3347 };
3348
3349 match location_side {
3350 LocationSide::Lhs => {
3351 let access_kind = if is_absolute_last_in_chain {
3355 LocationAccessKind::MapSubscriptCreateIfNeeded(
3356 map_like_type,
3357 key_expr,
3358 )
3359 } else {
3360 LocationAccessKind::MapSubscriptMustExist(
3361 map_like_type,
3362 key_expr,
3363 )
3364 };
3365
3366 self.add_location_item(
3367 &mut items,
3368 access_kind,
3369 value_type.clone(),
3370 &ast_key_expression.node,
3371 );
3372 }
3373 LocationSide::Mutable | LocationSide::Rhs => {
3374 self.add_location_item(
3375 &mut items,
3376 LocationAccessKind::MapSubscriptMustExist(
3377 map_like_type,
3378 key_expr,
3379 ),
3380 value_type.clone(),
3381 &ast_key_expression.node,
3382 );
3383 }
3384 }
3385 ty = value_type.clone();
3386 }
3387
3388 _ => {
3389 self.add_err_resolved(
3390 ErrorKind::CanNotSubscriptWithThatType,
3391 &base_expr.node,
3392 );
3393
3394 return SingleLocationExpression {
3395 kind: MutableReferenceKind::MutVariableRef,
3396 node: Default::default(),
3397 ty,
3398 starting_variable: Rc::new(Variable {
3399 symbol_id: ScopedSymbolId::new_illegal(),
3400 name: Default::default(),
3401 assigned_name: String::new(),
3402 resolved_type: Rc::new(Type {
3403 id: TypeId::new(0),
3404 flags: Default::default(),
3405 kind: Rc::new(TypeKind::Byte),
3406 }),
3407 mutable_node: None,
3408 variable_type: VariableType::Local,
3409 scope_index: 0,
3410 variable_index: 0,
3411 unique_id_within_function: 0,
3412 virtual_register: 0,
3413 is_unused: false,
3414 }),
3415 access_chain: vec![],
3416 };
3417 }
3418 }
3419 }
3420
3421 swamp_ast::Postfix::MemberCall(node, _generic_arguments, _regular_args) => {
3422 return SingleLocationExpression {
3423 kind: MutableReferenceKind::MutVariableRef,
3424 node: self.to_node(node),
3425 ty: self.shared.state.types.unit(),
3426 starting_variable: start_variable,
3427 access_chain: vec![],
3428 };
3429 }
3430 swamp_ast::Postfix::FunctionCall(node, _generic_arguments, _regular_args) => {
3437 return SingleLocationExpression {
3438 kind: MutableReferenceKind::MutVariableRef,
3439 node: self.to_node(node),
3440 ty: self.shared.state.types.unit(),
3441 starting_variable: start_variable,
3442 access_chain: vec![],
3443 };
3444 }
3445 swamp_ast::Postfix::OptionalChainingOperator(node) => {
3446 return SingleLocationExpression {
3447 kind: MutableReferenceKind::MutVariableRef,
3448 node: self.to_node(node),
3449 ty: self.shared.state.types.unit(),
3450 starting_variable: start_variable,
3451 access_chain: vec![],
3452 };
3453 }
3454 }
3455 }
3456
3457 if let Some(found_expected_type) = context.expected_type
3458 && !self.types().compatible_with(found_expected_type, &ty)
3459 {
3460 self.add_err(
3461 ErrorKind::IncompatibleTypes {
3462 expected: found_expected_type.clone(),
3463 found: ty.clone(),
3464 },
3465 &chain.base.node,
3466 );
3467 }
3468
3469 SingleLocationExpression {
3470 kind: MutableReferenceKind::MutVariableRef,
3471 node: self.to_node(&chain.base.node),
3472 ty,
3473 starting_variable: start_variable,
3474 access_chain: items,
3475 }
3476 }
3477
3478 fn analyze_to_location(
3479 &mut self,
3480 expr: &swamp_ast::Expression,
3481 context: &TypeContext,
3482 location_type: LocationSide,
3483 ) -> SingleLocationExpression {
3484 match &expr.kind {
3485 swamp_ast::ExpressionKind::PostfixChain(chain) => {
3486 self.analyze_chain_to_location(chain, context, location_type)
3487 }
3488 swamp_ast::ExpressionKind::VariableReference(variable) => {
3489 let var = self.find_variable(variable);
3490 if !var.is_mutable() {
3491 self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
3492 }
3493
3494 let name_node = self.to_node(&variable.name);
3495 self.shared
3496 .state
3497 .refs
3498 .add(var.symbol_id.into(), name_node.clone());
3499 self.shared
3500 .definition_table
3501 .refs
3502 .add(var.symbol_id.into(), name_node.clone());
3503
3504 SingleLocationExpression {
3505 kind: MutableReferenceKind::MutVariableRef,
3506 node: name_node,
3507 ty: var.resolved_type.clone(),
3508 starting_variable: var,
3509 access_chain: vec![],
3510 }
3511 }
3512 swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
3513 let generated_var = swamp_ast::Variable {
3514 name: qualified_identifier.name.clone(),
3515 is_mutable: None,
3516 };
3517 let var = self.find_variable(&generated_var);
3518 if !var.is_mutable() {
3519 self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
3520 }
3521
3522 let var_node = self.to_node(&generated_var.name);
3523 self.shared
3524 .state
3525 .refs
3526 .add(var.symbol_id.into(), var_node.clone());
3527 self.shared
3528 .definition_table
3529 .refs
3530 .add(var.symbol_id.into(), var_node.clone());
3531
3532 SingleLocationExpression {
3533 kind: MutableReferenceKind::MutVariableRef,
3534 node: var_node,
3535 ty: var.resolved_type.clone(),
3536 starting_variable: var,
3537 access_chain: vec![],
3538 }
3539 }
3540 _ => {
3541 self.add_err(ErrorKind::NotValidLocationStartingPoint, &expr.node);
3542 let unit_type = self.types().unit();
3543 SingleLocationExpression {
3544 kind: MutableReferenceKind::MutVariableRef,
3545 node: self.to_node(&expr.node),
3546 ty: unit_type.clone(),
3547 starting_variable: Rc::new(Variable {
3548 symbol_id: ScopedSymbolId::new_illegal(),
3549 name: Default::default(),
3550 assigned_name: String::new(),
3551 resolved_type: unit_type,
3552 mutable_node: None,
3553 variable_type: VariableType::Local,
3554 scope_index: 0,
3555 variable_index: 0,
3556 unique_id_within_function: 0,
3557 virtual_register: 0,
3558 is_unused: false,
3559 }),
3560 access_chain: vec![],
3561 }
3562 }
3563 }
3564 }
3565
3566 fn analyze_expression_for_assignment_compound(
3567 &mut self,
3568 target_expression: &swamp_ast::Expression,
3569 ast_source_expression: &swamp_ast::Expression,
3570 ) -> (TargetAssignmentLocation, Expression) {
3571 let any_argument_context = TypeContext::new_anything_argument(true);
3572 let source_expr = self.analyze_expression(ast_source_expression, &any_argument_context);
3573 let source_expr_type_context = TypeContext::new_argument(&source_expr.ty, true);
3574
3575 let resolved_location = TargetAssignmentLocation(self.analyze_to_location(
3576 target_expression,
3577 &source_expr_type_context,
3578 LocationSide::Rhs,
3579 ));
3580
3581 (resolved_location, source_expr)
3582 }
3583
3584 fn analyze_expression_for_assignment_with_target_type(
3611 &mut self,
3612 target_type: &TypeRef,
3613 ast_source_expression: &swamp_ast::Expression,
3614 ) -> Expression {
3615 let base_context = TypeContext::new_argument(target_type, true);
3616 let source_expr = self.analyze_expression(ast_source_expression, &base_context);
3617
3618 let final_expr = if self.types().compatible_with(target_type, &source_expr.ty) {
3619 source_expr
3620 } else {
3621 let source_type = source_expr.ty.clone();
3622 self.types_did_not_match_try_late_coerce_expression(
3623 source_expr,
3624 target_type,
3625 &source_type,
3626 &ast_source_expression.node,
3627 )
3628 };
3629
3630 let assignment_mode = self.check_assignment_mode(true, &final_expr, target_type); self.check_mutable_assignment(assignment_mode, &final_expr.node);
3633
3634 final_expr
3635 }
3636
3637 fn analyze_expression_for_assignment(
3638 &mut self,
3639 ast_target_location_expression: &swamp_ast::Expression,
3640 ast_source_expression: &swamp_ast::Expression,
3641 ) -> (TargetAssignmentLocation, Expression) {
3642 self.push_block_scope("fake outer scope to keep lvalue alive");
3643 let any_argument_context = TypeContext::new_anything_argument(true);
3644 let resolved_location = self.analyze_to_location(
3645 ast_target_location_expression,
3646 &any_argument_context,
3647 LocationSide::Lhs,
3648 );
3649
3650 self.push_block_scope("fake scope to keep lvalue alive");
3651 let target_type = resolved_location.ty.clone();
3652 let mut_type = target_type; let mut_location = TargetAssignmentLocation(resolved_location);
3654
3655 let final_expr = self
3656 .analyze_expression_for_assignment_with_target_type(&mut_type, ast_source_expression);
3657 self.pop_block_scope("fake scope for lvalue alive");
3658 self.pop_block_scope("fake outer scope for lvalue alive");
3659
3660 (mut_location, final_expr)
3661 }
3662
3663 fn analyze_assignment_compound(
3664 &mut self,
3665 target_expression: &swamp_ast::Expression,
3666 ast_op: &swamp_ast::CompoundOperator,
3667 ast_source_expression: &swamp_ast::Expression,
3668 ) -> Expression {
3669 let resolved_op = self.analyze_compound_operator(ast_op);
3670
3671 let (resolved_location, source_expr) = self
3672 .analyze_expression_for_assignment_compound(target_expression, ast_source_expression);
3673
3674 let kind = ExpressionKind::CompoundAssignment(
3675 resolved_location,
3676 resolved_op.kind,
3677 Box::from(source_expr),
3678 );
3679
3680 let unit_type = self.shared.state.types.unit();
3681
3682 self.create_expr(kind, unit_type, &target_expression.node)
3683 }
3684
3685 fn analyze_assignment_mode(lhs: SingleLocationExpression) {}
3686
3687 fn analyze_assignment(
3688 &mut self,
3689 target_location: &swamp_ast::Expression,
3690 ast_source_expression: &swamp_ast::Expression,
3691 ) -> Expression {
3692 let (mut_location, source_expr) =
3693 self.analyze_expression_for_assignment(target_location, ast_source_expression);
3694 let kind = ExpressionKind::Assignment(Box::from(mut_location), Box::from(source_expr));
3695 let unit_type = self.shared.state.types.unit();
3696
3697 self.create_expr(kind, unit_type, &target_location.node)
3700 }
3701
3702 #[must_use]
3703 pub const fn create_expr(
3704 &self,
3705 kind: ExpressionKind,
3706 ty: TypeRef,
3707 ast_node: &swamp_ast::Node,
3708 ) -> Expression {
3709 Expression {
3711 kind,
3712 ty,
3713 node: self.to_node(ast_node),
3714 }
3715 }
3716
3717 fn analyze_destructuring(
3718 &mut self,
3719 node: &swamp_ast::Node,
3720 target_ast_variables: &[swamp_ast::Variable],
3721 tuple_expression: &swamp_ast::Expression,
3722 ) -> Expression {
3723 let any_context = TypeContext::new_anything_argument(true);
3724 let tuple_resolved = self.analyze_expression(tuple_expression, &any_context);
3725 let tuple_expr_type = &tuple_resolved.ty;
3726 let unit = self.types().unit();
3727
3728 let mut variable_refs = Vec::new();
3729 if let TypeKind::Tuple(tuple) = &*tuple_expr_type.kind {
3730 if target_ast_variables.len() > tuple.len() {
3731 return self.create_err(ErrorKind::TooManyDestructureVariables, node);
3732 }
3733 for (ast_variable, tuple_type) in target_ast_variables.iter().zip(tuple.clone()) {
3734 let variable_ref = self.create_local_variable(
3735 &ast_variable.name,
3736 ast_variable.is_mutable.as_ref(),
3737 &tuple_type,
3738 true,
3739 );
3740 variable_refs.push(variable_ref);
3741 }
3742 let expr_kind = ExpressionKind::TupleDestructuring(
3743 variable_refs,
3744 tuple_expr_type.clone(),
3745 Box::from(tuple_resolved),
3746 );
3747
3748 self.create_expr(expr_kind, unit, node)
3749 } else {
3750 self.create_err(ErrorKind::CanNotDestructure, node)
3751 }
3752 }
3753
3754 fn analyze_normal_member_call(
3755 &mut self,
3756 type_that_member_is_on: &TypeRef,
3757 found_function: &FunctionRef,
3758 generic_arguments: Vec<TypeRef>,
3759 ast_arguments: &[swamp_ast::Expression],
3760 is_mutable: bool,
3761 node: &swamp_ast::Node,
3762 ) -> Signature {
3763 let resolved_node = self.to_node(node);
3764 found_function.signature().clone()
3767 }
3768
3769 fn enum_member_signature(
3770 &mut self,
3771 self_type: &TypeRef,
3772 field_name_str: &str,
3773 node: &swamp_ast::Node,
3774 ) -> Option<(IntrinsicFunction, Signature)> {
3775 let self_type_param = TypeForParameter {
3776 name: "self".to_string(),
3777 resolved_type: self_type.clone(),
3778 is_mutable: false,
3779 node: None,
3780 };
3781
3782 let self_mutable_type_param = TypeForParameter {
3783 name: "self".to_string(),
3784 resolved_type: self_type.clone(),
3785 is_mutable: true,
3786 node: None,
3787 };
3788
3789 let intrinsic_and_signature = match field_name_str {
3790 "discriminant" => (
3791 IntrinsicFunction::EnumDiscriminant,
3792 Signature {
3793 parameters: vec![self_type_param],
3794 return_type: self.types().int(),
3795 },
3796 ),
3797
3798 "from_discriminant" => (
3799 IntrinsicFunction::EnumFromDiscriminant,
3800 Signature {
3801 parameters: vec![
3802 self_mutable_type_param,
3803 TypeForParameter {
3804 name: "discriminant".to_string(),
3805 resolved_type: self.types().int(),
3806 is_mutable: false,
3807 node: None,
3808 },
3809 ],
3810 return_type: self.types().unit(),
3811 },
3812 ),
3813 _ => {
3814 self.add_err(ErrorKind::UnknownMemberFunction(self_type.clone()), node);
3815
3816 return None;
3817 }
3818 };
3819
3820 Some(intrinsic_and_signature)
3821 }
3822
3823 fn queue_member_signature(
3824 &mut self,
3825 self_type: &TypeRef,
3826 key_type: Option<&TypeRef>,
3827 element_type: &TypeRef,
3828 field_name_str: &str,
3829 lambda_variable_count: usize,
3830 node: &swamp_ast::Node,
3831 ) -> Option<(IntrinsicFunction, Signature)> {
3832 let self_type_param = TypeForParameter {
3833 name: "self".to_string(),
3834 resolved_type: self_type.clone(),
3835 is_mutable: false,
3836 node: None,
3837 };
3838 let self_mutable_type_param = TypeForParameter {
3839 name: "self".to_string(),
3840 resolved_type: self_type.clone(),
3841 is_mutable: true,
3842 node: None,
3843 };
3844 let intrinsic_and_signature = match field_name_str {
3845 "enqueue" => (
3846 IntrinsicFunction::VecPush,
3847 Signature {
3848 parameters: vec![
3849 self_mutable_type_param,
3850 TypeForParameter {
3851 name: "element".to_string(),
3852 resolved_type: element_type.clone(),
3853 is_mutable: false,
3854 node: None,
3855 },
3856 ],
3857 return_type: self.types().unit(),
3858 },
3859 ),
3860 "dequeue" => (
3861 IntrinsicFunction::VecRemoveFirstIndexGetValue,
3862 Signature {
3863 parameters: vec![self_mutable_type_param],
3864 return_type: element_type.clone(),
3865 },
3866 ),
3867 _ => {
3868 self.slice_member_signature(
3869 self_type,
3870 key_type,
3871 element_type,
3872 field_name_str,
3873 lambda_variable_count,
3874 node,
3875 )
3876 }?,
3877 };
3878
3879 Some(intrinsic_and_signature)
3880 }
3881
3882 fn sparse_member_signature(
3883 &mut self,
3884 self_type: &TypeRef,
3885 element_type: &TypeRef,
3886 field_name_str: &str,
3887 lambda_variable_count: usize,
3888 node: &swamp_ast::Node,
3889 ) -> Option<(IntrinsicFunction, Signature)> {
3890 let key_type = self.types().int(); let self_type_param = TypeForParameter {
3893 name: "self".to_string(),
3894 resolved_type: self_type.clone(),
3895 is_mutable: false,
3896 node: None,
3897 };
3898 let self_mutable_type_param = TypeForParameter {
3899 name: "self".to_string(),
3900 resolved_type: self_type.clone(),
3901 is_mutable: true,
3902 node: None,
3903 };
3904 let intrinsic_and_signature = match field_name_str {
3905 "add" => (
3906 IntrinsicFunction::SparseAdd,
3907 Signature {
3908 parameters: vec![
3909 self_mutable_type_param,
3910 TypeForParameter {
3911 name: "element".to_string(),
3912 resolved_type: element_type.clone(),
3913 is_mutable: false,
3914 node: None,
3915 },
3916 ],
3917 return_type: self.types().int(),
3918 },
3919 ),
3920 "remove" => (
3921 IntrinsicFunction::SparseRemove,
3922 Signature {
3923 parameters: vec![
3924 self_mutable_type_param,
3925 TypeForParameter {
3926 name: "key".to_string(),
3927 resolved_type: key_type,
3928 is_mutable: false,
3929 node: None,
3930 },
3931 ],
3932 return_type: self.types().unit(),
3933 },
3934 ),
3935 "is_alive" => (
3936 IntrinsicFunction::SparseIsAlive,
3937 Signature {
3938 parameters: vec![
3939 self_type_param,
3940 TypeForParameter {
3941 name: "element".to_string(),
3942 resolved_type: element_type.clone(),
3943 is_mutable: false,
3944 node: None,
3945 },
3946 ],
3947 return_type: self.types().bool(),
3948 },
3949 ),
3950
3951 _ => {
3952 self.slice_member_signature(
3953 self_type,
3954 Option::from(key_type).as_ref(),
3955 element_type,
3956 field_name_str,
3957 lambda_variable_count,
3958 node,
3959 )
3960 }?,
3961 };
3962 Some(intrinsic_and_signature)
3963 }
3964
3965 fn vec_member_signature(
3966 &mut self,
3967 self_type: &TypeRef,
3968 element_type: &TypeRef,
3969 field_name_str: &str,
3970 lambda_variable_count: usize,
3971 node: &swamp_ast::Node,
3972 ) -> Option<(IntrinsicFunction, Signature)> {
3973 let key_type = self.types().int();
3974 let self_type_param = TypeForParameter {
3975 name: "self".to_string(),
3976 resolved_type: self_type.clone(),
3977 is_mutable: false,
3978 node: None,
3979 };
3980 let self_mutable_type_param = TypeForParameter {
3981 name: "self".to_string(),
3982 resolved_type: self_type.clone(),
3983 is_mutable: true,
3984 node: None,
3985 };
3986 let intrinsic_and_signature = match field_name_str {
3987 "prepend" => (
3988 IntrinsicFunction::VecPush,
3989 Signature {
3990 parameters: vec![
3991 self_mutable_type_param,
3992 TypeForParameter {
3993 name: "element".to_string(),
3994 resolved_type: element_type.clone(),
3995 is_mutable: false,
3996 node: None,
3997 },
3998 ],
3999 return_type: self.types().unit(),
4000 },
4001 ),
4002 "push" => (
4003 IntrinsicFunction::VecPush,
4004 Signature {
4005 parameters: vec![
4006 self_mutable_type_param,
4007 TypeForParameter {
4008 name: "element".to_string(),
4009 resolved_type: element_type.clone(),
4010 is_mutable: false,
4011 node: None,
4012 },
4013 ],
4014 return_type: self.types().unit(),
4015 },
4016 ),
4017 "extend" => (
4018 IntrinsicFunction::VecExtend,
4019 Signature {
4020 parameters: vec![
4021 self_mutable_type_param,
4022 TypeForParameter {
4023 name: "other_vec".to_string(),
4024 resolved_type: self.types().dynamic_vec_view(&element_type.clone()),
4025 is_mutable: false,
4026 node: None,
4027 },
4028 ],
4029 return_type: self.types().unit(),
4030 },
4031 ),
4032 "pop" => (
4033 IntrinsicFunction::VecPop,
4034 Signature {
4035 parameters: vec![self_mutable_type_param],
4036 return_type: element_type.clone(),
4037 },
4038 ),
4039
4040 "slice" => {
4041 let range_type = self.types().range_int();
4042 (
4043 IntrinsicFunction::VecSlice,
4044 Signature {
4045 parameters: vec![
4046 self_type_param,
4047 TypeForParameter {
4048 name: "range".to_string(),
4049 resolved_type: range_type,
4050 is_mutable: false,
4051 node: None,
4052 },
4053 ],
4054 return_type: self_type.clone(),
4055 },
4056 )
4057 }
4058
4059 _ => {
4060 self.slice_member_signature(
4061 self_type,
4062 Option::from(key_type).as_ref(),
4063 element_type,
4064 field_name_str,
4065 lambda_variable_count,
4066 node,
4067 )
4068 }?,
4069 };
4070 Some(intrinsic_and_signature)
4071 }
4072
4073 #[allow(clippy::unnecessary_wraps)]
4074 fn grid_member_signature(
4075 &mut self,
4076 self_type: &TypeRef,
4077 element_type: &TypeRef,
4078 field_name_str: &str,
4079 node: &swamp_ast::Node,
4080 ) -> Option<(IntrinsicFunction, Signature)> {
4081 let self_type_param = TypeForParameter {
4082 name: "self".to_string(),
4083 resolved_type: self_type.clone(),
4084 is_mutable: false,
4085 node: None,
4086 };
4087 let self_mutable_type_param = TypeForParameter {
4088 name: "self".to_string(),
4089 resolved_type: self_type.clone(),
4090 is_mutable: true,
4091 node: None,
4092 };
4093 let element_param = TypeForParameter {
4094 name: "element".to_string(),
4095 resolved_type: element_type.clone(),
4096 is_mutable: false,
4097 node: None,
4098 };
4099 let int_type = self.types().int();
4100
4101 let int_param = TypeForParameter {
4102 name: "x_or_y".to_string(),
4103 resolved_type: int_type.clone(),
4104 is_mutable: false,
4105 node: None,
4106 };
4107 let intrinsic_and_signature = match field_name_str {
4108 "set" => (
4109 IntrinsicFunction::GridSet,
4110 Signature {
4111 parameters: vec![self_type_param, int_param.clone(), int_param, element_param],
4112 return_type: self.types().unit(),
4113 },
4114 ),
4115
4116 "get" => (
4117 IntrinsicFunction::GridGet,
4118 Signature {
4119 parameters: vec![self_type_param, int_param.clone(), int_param],
4120 return_type: element_type.clone(),
4121 },
4122 ),
4123
4124 "width" => (
4125 IntrinsicFunction::GridWidth,
4126 Signature {
4127 parameters: vec![self_type_param],
4128 return_type: int_type,
4129 },
4130 ),
4131
4132 "height" => (
4133 IntrinsicFunction::GridHeight,
4134 Signature {
4135 parameters: vec![self_type_param],
4136 return_type: int_type,
4137 },
4138 ),
4139
4140 _ => panic!("unknown grid method {field_name_str}"),
4141 };
4142
4143 Some(intrinsic_and_signature)
4144 }
4145
4146 fn ptr_member_signature(
4147 &mut self,
4148 self_type: &TypeRef,
4149 field_name_str: &str,
4150 node: &swamp_ast::Node,
4151 ) -> Option<(IntrinsicFunction, Signature)> {
4152 let self_type_param = TypeForParameter {
4153 name: "self".to_string(),
4154 resolved_type: self_type.clone(),
4155 is_mutable: false,
4156 node: None,
4157 };
4158 let self_mut_type_param = TypeForParameter {
4159 name: "self".to_string(),
4160 resolved_type: self_type.clone(),
4161 is_mutable: true,
4162 node: None,
4163 };
4164
4165 let intrinsic_and_signature = match field_name_str {
4166 "from_u32" => {
4167 let signature = Signature {
4168 parameters: vec![TypeForParameter {
4169 name: "addr".to_string(),
4170 resolved_type: self.types().int(),
4171 is_mutable: false,
4172 node: None,
4173 }],
4174 return_type: self.types().int(),
4175 };
4176 (IntrinsicFunction::VecLen, signature)
4177 }
4178 _ => return None,
4179 };
4180
4181 Some(intrinsic_and_signature)
4182 }
4183
4184 fn basic_collection_member_signature(
4185 &mut self,
4186 self_type: &TypeRef,
4187 field_name_str: &str,
4188 node: &swamp_ast::Node,
4189 ) -> Option<(IntrinsicFunction, Signature)> {
4190 let self_type_param = TypeForParameter {
4191 name: "self".to_string(),
4192 resolved_type: self_type.clone(),
4193 is_mutable: false,
4194 node: None,
4195 };
4196 let self_mut_type_param = TypeForParameter {
4197 name: "self".to_string(),
4198 resolved_type: self_type.clone(),
4199 is_mutable: true,
4200 node: None,
4201 };
4202 let intrinsic_and_signature = match field_name_str {
4203 "len" => {
4204 let signature = Signature {
4205 parameters: vec![self_type_param],
4206 return_type: self.types().int(),
4207 };
4208 (IntrinsicFunction::VecLen, signature)
4209 }
4210 "is_empty" => (
4211 IntrinsicFunction::VecIsEmpty,
4212 Signature {
4213 parameters: vec![self_type_param],
4214 return_type: self.types().bool(),
4215 },
4216 ),
4217 "clear" => {
4218 let signature = Signature {
4219 parameters: vec![self_mut_type_param],
4220 return_type: self.types().unit(),
4221 };
4222 (IntrinsicFunction::VecClear, signature)
4223 }
4224 "capacity" => {
4225 let signature = Signature {
4226 parameters: vec![self_type_param],
4227 return_type: self.types().int(),
4228 };
4229 (IntrinsicFunction::VecCapacity, signature)
4230 }
4231 _ => {
4232 self.add_err(ErrorKind::UnknownMemberFunction(self_type.clone()), node);
4233
4234 return None;
4235 }
4236 };
4237 Some(intrinsic_and_signature)
4238 }
4239 #[allow(clippy::too_many_lines)]
4240 fn codepoint_member_signature(
4241 &mut self,
4242 self_type: &TypeRef,
4243 key_type: Option<&TypeRef>,
4244 element_type: &TypeRef,
4245 field_name_str: &str,
4246 lambda_variable_count: usize,
4247 node: &swamp_ast::Node,
4248 ) -> Option<(IntrinsicFunction, Signature)> {
4249 let self_type_param = TypeForParameter {
4250 name: "self".to_string(),
4251 resolved_type: self_type.clone(),
4252 is_mutable: false,
4253 node: None,
4254 };
4255
4256 match field_name_str {
4257 "int" => Some((
4258 IntrinsicFunction::CodepointToInt,
4259 Signature {
4260 parameters: vec![self_type_param],
4261 return_type: self.types().int(),
4262 },
4263 )),
4264 "char" => Some((
4265 IntrinsicFunction::ByteToCodepoint,
4266 Signature {
4267 parameters: vec![self_type_param],
4268 return_type: self.types().codepoint(),
4269 },
4270 )),
4271 _ => None,
4272 }
4273 }
4274
4275 #[allow(clippy::too_many_lines)]
4276 fn byte_member_signature(
4277 &mut self,
4278 self_type: &TypeRef,
4279 key_type: Option<&TypeRef>,
4280 element_type: &TypeRef,
4281 field_name_str: &str,
4282 lambda_variable_count: usize,
4283 node: &swamp_ast::Node,
4284 ) -> Option<(IntrinsicFunction, Signature)> {
4285 let self_type_param = TypeForParameter {
4286 name: "self".to_string(),
4287 resolved_type: self_type.clone(),
4288 is_mutable: false,
4289 node: None,
4290 };
4291
4292 match field_name_str {
4293 "int" => Some((
4294 IntrinsicFunction::ByteToInt,
4295 Signature {
4296 parameters: vec![self_type_param],
4297 return_type: self.types().int(),
4298 },
4299 )),
4300 "float" => Some((
4301 IntrinsicFunction::ByteToFloat,
4302 Signature {
4303 parameters: vec![self_type_param],
4304 return_type: self.types().float(),
4305 },
4306 )),
4307 "char" => Some((
4308 IntrinsicFunction::ByteToCodepoint,
4309 Signature {
4310 parameters: vec![self_type_param],
4311 return_type: self.types().codepoint(),
4312 },
4313 )),
4314 _ => None,
4315 }
4316 }
4317
4318 #[allow(clippy::too_many_lines)]
4319 fn string_member_signature(
4320 &mut self,
4321 self_type: &TypeRef,
4322 key_type: Option<&TypeRef>,
4323 element_type: &TypeRef,
4324 field_name_str: &str,
4325 lambda_variable_count: usize,
4326 node: &swamp_ast::Node,
4327 ) -> Option<(IntrinsicFunction, Signature)> {
4328 let self_type_param = TypeForParameter {
4329 name: "self".to_string(),
4330 resolved_type: self_type.clone(),
4331 is_mutable: false,
4332 node: None,
4333 };
4334
4335 let x = match field_name_str {
4336 "starts_with" => (
4337 IntrinsicFunction::StringStartsWith,
4338 Signature {
4339 parameters: vec![
4340 self_type_param,
4341 TypeForParameter {
4342 name: "str".to_string(),
4343 resolved_type: self.types().string(),
4344 is_mutable: false,
4345 node: None,
4346 },
4347 ],
4348 return_type: self.types().bool(),
4349 },
4350 ),
4351 _ => {
4352 return self.vec_member_signature(
4353 self_type,
4354 element_type,
4355 field_name_str,
4356 lambda_variable_count,
4357 node,
4358 );
4359 }
4360 };
4361
4362 Some(x)
4363 }
4364
4365 #[allow(clippy::too_many_lines)]
4366 fn slice_member_signature(
4367 &mut self,
4368 self_type: &TypeRef,
4369 key_type: Option<&TypeRef>,
4370 element_type: &TypeRef,
4371 field_name_str: &str,
4372 lambda_variable_count: usize,
4373 node: &swamp_ast::Node,
4374 ) -> Option<(IntrinsicFunction, Signature)> {
4375 let slice_view_type = self.types().slice_view(&element_type.clone());
4376 let int_type = self.types().int();
4377 let self_type_param = TypeForParameter {
4378 name: "self".to_string(),
4379 resolved_type: slice_view_type.clone(),
4380 is_mutable: false,
4381 node: None,
4382 };
4383 let self_mut_type_param = TypeForParameter {
4384 name: "self".to_string(),
4385 resolved_type: slice_view_type,
4386 is_mutable: true,
4387 node: None,
4388 };
4389 let intrinsic_and_signature = match field_name_str {
4390 "for" => {
4391 let parameters = if lambda_variable_count == 2 {
4392 vec![
4393 TypeForParameter {
4394 name: "key".to_string(),
4395 resolved_type: key_type.unwrap().clone(),
4396 is_mutable: false,
4397 node: None,
4398 },
4399 TypeForParameter {
4400 name: "element".to_string(),
4401 resolved_type: element_type.clone(),
4402 is_mutable: false,
4403 node: None,
4404 },
4405 ]
4406 } else {
4407 vec![TypeForParameter {
4408 name: "element".to_string(),
4409 resolved_type: element_type.clone(),
4410 is_mutable: false,
4411 node: None,
4412 }]
4413 };
4414 let lambda_signature = Signature {
4415 parameters,
4416 return_type: self.types().unit(),
4417 };
4418 let lambda_function_type = self.types().function(lambda_signature);
4419 (
4420 IntrinsicFunction::TransformerFor,
4421 Signature {
4422 parameters: vec![
4423 self_type_param,
4424 TypeForParameter {
4425 name: "lambda".to_string(),
4426 resolved_type: lambda_function_type,
4427 is_mutable: false,
4428 node: None,
4429 },
4430 ],
4431 return_type: self.types().unit(), },
4433 )
4434 }
4435 "while" => {
4436 let parameters = if lambda_variable_count == 2 {
4437 vec![
4438 TypeForParameter {
4439 name: "key".to_string(),
4440 resolved_type: key_type.unwrap().clone(),
4441 is_mutable: false,
4442 node: None,
4443 },
4444 TypeForParameter {
4445 name: "element".to_string(),
4446 resolved_type: element_type.clone(),
4447 is_mutable: false,
4448 node: None,
4449 },
4450 ]
4451 } else {
4452 vec![TypeForParameter {
4453 name: "element".to_string(),
4454 resolved_type: element_type.clone(),
4455 is_mutable: false,
4456 node: None,
4457 }]
4458 };
4459 let lambda_signature = Signature {
4460 parameters,
4461 return_type: self.types().bool(), };
4463 let lambda_function_type = self.types().function(lambda_signature);
4464 (
4465 IntrinsicFunction::TransformerWhile,
4466 Signature {
4467 parameters: vec![
4468 self_type_param,
4469 TypeForParameter {
4470 name: "lambda".to_string(),
4471 resolved_type: lambda_function_type,
4472 is_mutable: false,
4473 node: None,
4474 },
4475 ],
4476 return_type: self.types().unit(), },
4478 )
4479 }
4480 "filter" => {
4481 let lambda_signature = Signature {
4482 parameters: vec![TypeForParameter {
4483 name: "element".to_string(),
4484 resolved_type: element_type.clone(),
4485 is_mutable: false,
4486 node: None,
4487 }],
4488 return_type: self.types().bool(),
4489 };
4490 let lambda_function_type = self.types().function(lambda_signature);
4491 (
4492 IntrinsicFunction::TransformerFilter,
4493 Signature {
4494 parameters: vec![
4495 self_type_param,
4496 TypeForParameter {
4497 name: "lambda".to_string(),
4498 resolved_type: lambda_function_type,
4499 is_mutable: false,
4500 node: None,
4501 },
4502 ],
4503 return_type: self.shared.state.types.slice_view(&element_type.clone()),
4504 },
4505 )
4506 }
4507 "find" => {
4508 let lambda_signature = Signature {
4509 parameters: vec![TypeForParameter {
4510 name: "element".to_string(),
4511 resolved_type: element_type.clone(),
4512 is_mutable: false,
4513 node: None,
4514 }],
4515 return_type: self.types().bool(),
4516 };
4517 let lambda_function_type = self.types().function(lambda_signature);
4518 (
4519 IntrinsicFunction::TransformerFind,
4520 Signature {
4521 parameters: vec![
4522 self_type_param,
4523 TypeForParameter {
4524 name: "lambda".to_string(),
4525 resolved_type: lambda_function_type,
4526 is_mutable: false,
4527 node: None,
4528 },
4529 ],
4530 return_type: self.shared.state.types.optional(&element_type.clone()),
4531 },
4532 )
4533 }
4534
4535 "remove" => {
4536 let signature = Signature {
4537 parameters: vec![
4538 self_mut_type_param,
4539 TypeForParameter {
4540 name: "index".to_string(),
4541 resolved_type: int_type,
4542 is_mutable: false,
4543 node: None,
4544 },
4545 ],
4546 return_type: self.types().unit(),
4547 };
4548 (IntrinsicFunction::VecRemoveIndex, signature)
4549 }
4550 _ => return self.basic_collection_member_signature(self_type, field_name_str, node),
4551 };
4552 Some(intrinsic_and_signature)
4553 }
4554
4555 #[allow(clippy::unnecessary_wraps, clippy::result_large_err)]
4556 fn map_member_signature(
4557 &mut self,
4558 self_type: &TypeRef,
4559 key_type: &TypeRef,
4560 value_type: &TypeRef,
4561 field_name_str: &str,
4562 node: &swamp_ast::Node,
4563 ) -> Option<(IntrinsicFunction, Signature)> {
4564 let self_type_param = TypeForParameter {
4565 name: "self".to_string(),
4566 resolved_type: self_type.clone(),
4567 is_mutable: false,
4568 node: None,
4569 };
4570
4571 let mutable_self_type_param = TypeForParameter {
4572 name: "self".to_string(),
4573 resolved_type: self_type.clone(),
4574 is_mutable: true,
4575 node: None,
4576 };
4577
4578 let intrinsic_and_signature = match field_name_str {
4579 "has" => (
4580 IntrinsicFunction::MapHas,
4581 Signature {
4582 parameters: vec![
4583 self_type_param,
4584 TypeForParameter {
4585 name: "key".to_string(),
4586 resolved_type: key_type.clone(),
4587 is_mutable: false,
4588 node: None,
4589 },
4590 ],
4591 return_type: self.types().bool(),
4592 },
4593 ),
4594 "remove" => (
4595 IntrinsicFunction::MapRemove,
4596 Signature {
4597 parameters: vec![
4598 mutable_self_type_param,
4599 TypeForParameter {
4600 name: "key".to_string(),
4601 resolved_type: key_type.clone(),
4602 is_mutable: false,
4603 node: None,
4604 },
4605 ],
4606 return_type: self.types().unit(),
4607 },
4608 ),
4609 "len" => (
4610 IntrinsicFunction::MapLen,
4611 Signature {
4612 parameters: vec![self_type_param],
4613 return_type: self.types().int(),
4614 },
4615 ),
4616 "capacity" => (
4617 IntrinsicFunction::MapCapacity,
4618 Signature {
4619 parameters: vec![self_type_param],
4620 return_type: self.types().int(),
4621 },
4622 ),
4623 "is_empty" => (
4624 IntrinsicFunction::MapIsEmpty,
4625 Signature {
4626 parameters: vec![self_type_param],
4627 return_type: self.types().bool(),
4628 },
4629 ),
4630 _ => todo!("unknown map member"),
4631 };
4632
4633 Some(intrinsic_and_signature)
4634 }
4635
4636 fn check_intrinsic_member_signature(
4637 &mut self,
4638 type_that_member_is_on: &TypeRef,
4639 field_name_str: &str,
4640 lambda_variables_count: usize,
4641 node: &swamp_ast::Node,
4642 ) -> Option<(IntrinsicFunction, Signature)> {
4643 let ty = type_that_member_is_on;
4644 let int_type = self.types().int();
4645 match &*ty.kind {
4646 TypeKind::GridStorage(element_type, ..) | TypeKind::GridView(element_type) => self
4647 .grid_member_signature(type_that_member_is_on, element_type, field_name_str, node),
4648 TypeKind::SparseStorage(element_type, ..) | TypeKind::SparseView(element_type) => self
4649 .sparse_member_signature(
4650 type_that_member_is_on,
4651 element_type,
4652 field_name_str,
4653 lambda_variables_count,
4654 node,
4655 ),
4656 TypeKind::Enum(enum_type) => self.enum_member_signature(ty, field_name_str, node),
4657 TypeKind::QueueStorage(element_type, ..) => self.queue_member_signature(
4658 type_that_member_is_on,
4659 None,
4660 element_type,
4661 field_name_str,
4662 lambda_variables_count,
4663 node,
4664 ),
4665 TypeKind::StackStorage(element_type, ..)
4666 | TypeKind::QueueStorage(element_type, ..)
4667 | TypeKind::VecStorage(element_type, ..)
4668 | TypeKind::DynamicLengthVecView(element_type) => self.vec_member_signature(
4669 type_that_member_is_on,
4670 element_type,
4671 field_name_str,
4672 lambda_variables_count,
4673 node,
4674 ),
4675 TypeKind::SliceView(element_type) => self.slice_member_signature(
4676 type_that_member_is_on,
4677 Some(&int_type),
4678 element_type,
4679 field_name_str,
4680 lambda_variables_count,
4681 node,
4682 ),
4683 TypeKind::Pointer(inner) => {
4684 self.ptr_member_signature(type_that_member_is_on, field_name_str, node)
4685 }
4686 TypeKind::Byte => {
4687 let element_type = self.shared.state.types.byte();
4688 self.byte_member_signature(
4689 type_that_member_is_on,
4690 Some(&int_type),
4691 &element_type,
4692 field_name_str,
4693 lambda_variables_count,
4694 node,
4695 )
4696 }
4697 TypeKind::Codepoint => {
4698 let element_type = self.shared.state.types.codepoint();
4699 self.codepoint_member_signature(
4700 type_that_member_is_on,
4701 Some(&int_type),
4702 &element_type,
4703 field_name_str,
4704 lambda_variables_count,
4705 node,
4706 )
4707 }
4708 TypeKind::StringView { .. } | TypeKind::StringStorage(..) => {
4709 let element_type = self.shared.state.types.byte();
4710 self.string_member_signature(
4711 type_that_member_is_on,
4712 Some(&int_type),
4713 &element_type,
4714 field_name_str,
4715 lambda_variables_count,
4716 node,
4717 )
4718 }
4719 TypeKind::DynamicLengthMapView(key, value) | TypeKind::MapStorage(key, value, _) => {
4720 self.map_member_signature(type_that_member_is_on, key, value, field_name_str, node)
4721 }
4722
4723 TypeKind::FixedCapacityAndLengthArray(element_type, _) => self.slice_member_signature(
4724 type_that_member_is_on,
4725 Some(&int_type),
4726 element_type,
4727 field_name_str,
4728 lambda_variables_count,
4729 node,
4730 ),
4731 _ => {
4732 self.add_err(
4733 ErrorKind::UnknownMemberFunction(type_that_member_is_on.clone()),
4734 node,
4735 );
4736
4737 None
4738 }
4739 }
4740 }
4741
4742 fn analyze_member_call(
4743 &mut self,
4744 type_that_member_is_on: &TypeRef,
4745 field_name_str: &str,
4746 ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4747 ast_arguments: &[swamp_ast::Expression],
4748 chain_self_is_mutable: bool,
4749 node: &swamp_ast::Node,
4750 ) -> (PostfixKind, TypeRef) {
4751 let generic_arguments = if let Some(ast_generic_arguments) = ast_maybe_generic_arguments {
4752 let mut resolved_types = Vec::new();
4753 for ast_type in ast_generic_arguments {
4754 resolved_types
4755 .push(self.analyze_type(ast_type.get_type(), &TypeAnalyzeContext::default()));
4756 }
4757 resolved_types
4758 } else {
4759 vec![]
4760 };
4761
4762 let maybe_function = self
4763 .shared
4764 .state
4765 .associated_impls
4766 .get_member_function(type_that_member_is_on, field_name_str)
4767 .cloned();
4768
4769 let (function_ref, instantiated_signature) = if let Some(found_function) = maybe_function {
4770 let signature = self.analyze_normal_member_call(
4771 type_that_member_is_on,
4772 &found_function,
4773 generic_arguments,
4774 ast_arguments,
4775 chain_self_is_mutable,
4776 node,
4777 );
4778 (found_function, signature)
4779 } else {
4780 let lambda_variables_count = if ast_arguments.is_empty() {
4781 0
4782 } else if let swamp_ast::ExpressionKind::Lambda(variables, ..) = &ast_arguments[0].kind
4783 {
4784 variables.len()
4785 } else {
4786 0
4787 };
4788 let Some((intrinsic_fn, signature)) = self.check_intrinsic_member_signature(
4789 type_that_member_is_on,
4790 field_name_str,
4791 lambda_variables_count,
4792 node,
4793 ) else {
4794 return (PostfixKind::OptionalChainingOperator, self.types().unit());
4795 };
4796 let def = IntrinsicFunctionDefinition {
4797 name: field_name_str.to_string(),
4798 signature,
4799 intrinsic: intrinsic_fn,
4800 };
4801 let function_ref = FunctionRef::from(Function::Intrinsic(
4802 IntrinsicFunctionDefinitionRef::from(def.clone()),
4803 ));
4804 (function_ref, def.signature)
4805 };
4806
4807 let self_type_in_signature = &instantiated_signature.parameters[0];
4808
4809 if self_type_in_signature.is_mutable && !chain_self_is_mutable {
4810 self.add_err(ErrorKind::SelfNotCorrectMutableState, node);
4811 }
4812
4813 let resolved_arguments = self.analyze_and_verify_parameters(
4814 node,
4815 &instantiated_signature.parameters[1..],
4816 ast_arguments,
4817 );
4818
4819 let name_node = self.to_node(node);
4820 self.shared
4821 .state
4822 .refs
4823 .add(function_ref.symbol_id().into(), name_node.clone());
4824 self.shared
4825 .definition_table
4826 .refs
4827 .add(function_ref.symbol_id().into(), name_node);
4828
4829 (
4830 PostfixKind::MemberCall(function_ref, resolved_arguments),
4831 TypeRef::from(instantiated_signature.return_type.clone()),
4832 )
4833 }
4834
4835 fn analyze_postfix_member_call(
4836 &mut self,
4837 type_that_member_is_on: &TypeRef,
4838 is_mutable: bool,
4839 member_name: &swamp_ast::Node,
4840 ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4841 ast_arguments: &[swamp_ast::Expression],
4842 suffixes: &mut Vec<Postfix>,
4843 ) -> TypeRef {
4844 let field_name_str = self.get_text(member_name).to_string();
4845
4846 let resolved_node = self.to_node(member_name);
4847
4848 let (kind, return_type) = self.analyze_member_call(
4849 type_that_member_is_on,
4850 &field_name_str,
4851 ast_maybe_generic_arguments,
4852 ast_arguments,
4853 is_mutable,
4854 member_name,
4855 );
4856 let postfix = Postfix {
4857 node: resolved_node,
4858 ty: return_type,
4859 kind,
4860 };
4861
4862 let last_type = postfix.ty.clone();
4863 suffixes.push(postfix);
4864
4865 last_type
4866 }
4867
4868 fn is_compatible_initializer_list_target(
4869 &mut self,
4870 target_type: &TypeRef,
4871 initializer_element_type: &TypeRef,
4872 ) -> bool {
4873 match &*target_type.kind {
4874 TypeKind::VecStorage(vec_element_type, _vec_capacity) => self
4875 .types()
4876 .compatible_with(vec_element_type, initializer_element_type),
4877 TypeKind::FixedCapacityAndLengthArray(array_element_type, _array_capacity) => self
4878 .types()
4879 .compatible_with(array_element_type, initializer_element_type),
4880 _ => false,
4881 }
4882 }
4883
4884 fn is_compatible_initializer_pair_list_target(
4885 &mut self,
4886 target_type: &TypeRef,
4887 initializer_key_type: &TypeRef,
4888 initializer_value_type: &TypeRef,
4889 ) -> bool {
4890 match &*target_type.kind {
4891 TypeKind::MapStorage(storage_key, storage_value, _) => {
4892 self.types()
4893 .compatible_with(initializer_key_type, storage_key)
4894 && self
4895 .types()
4896 .compatible_with(initializer_value_type, storage_value)
4897 }
4898 _ => false,
4899 }
4900 }
4901
4902 fn types_did_not_match_try_late_coerce_expression(
4903 &mut self,
4904 expr: Expression,
4905 special_expected_type: &TypeRef,
4906 special_encountered_type: &TypeRef,
4907 node: &swamp_ast::Node,
4908 ) -> Expression {
4909 let expected_type = special_expected_type;
4910 let encountered_type = special_encountered_type;
4911
4912 if matches!(&*expected_type.kind, TypeKind::Any) && encountered_type.is_storage() {
4913 let wrapped = self.create_expr(
4914 ExpressionKind::CoerceToAny(Box::new(expr)),
4915 expected_type.clone(),
4916 node,
4917 );
4918 return wrapped;
4919 }
4920
4921 let encountered_is_optional = matches!(&*encountered_type.kind, TypeKind::Optional(_));
4922 if let TypeKind::Optional(expected_inner_type) = &*expected_type.kind {
4923 let inner_is_also_optional =
4924 matches!(&*expected_inner_type.kind, TypeKind::Optional(_));
4925 assert!(!inner_is_also_optional);
4928
4929 if !encountered_is_optional {
4932 if self
4934 .types()
4935 .compatible_with(expected_inner_type, encountered_type)
4936 {
4937 let wrapped = self.create_expr(
4939 ExpressionKind::Option(Option::from(Box::new(expr))),
4940 expected_type.clone(),
4941 node,
4942 );
4943 return wrapped;
4944 }
4945 }
4946 }
4947
4948 if matches!(&*expected_type.kind, &TypeKind::Bool) {
4949 if encountered_is_optional {
4951 let bool_type = self.types().bool();
4952 let wrapped = self.create_expr(
4953 ExpressionKind::CoerceOptionToBool(Box::from(expr)),
4954 bool_type,
4955 node,
4956 );
4957 return wrapped;
4958 }
4959 }
4960
4961 if matches!(
4962 (&*expected_type.kind, &*encountered_type.kind),
4963 (TypeKind::Codepoint, TypeKind::Int)
4964 ) {
4965 let coerced = self.create_expr(
4966 ExpressionKind::CoerceIntToChar(Box::new(expr)),
4967 expected_type.clone(),
4968 node,
4969 );
4970 return coerced;
4971 }
4972
4973 if matches!(
4974 (&*expected_type.kind, &*encountered_type.kind),
4975 (TypeKind::Byte, TypeKind::Int)
4976 ) {
4977 let coerced = self.create_expr(
4978 ExpressionKind::CoerceIntToByte(Box::new(expr)),
4979 expected_type.clone(),
4980 node,
4981 );
4982 return coerced;
4983 }
4984
4985 error!(?expected_type, ?encountered_type, "incompatible");
4986 self.create_err(
4987 ErrorKind::IncompatibleTypes {
4988 expected: expected_type.clone(),
4989 found: encountered_type.clone(),
4990 },
4991 node,
4992 )
4993 }
4994
4995 #[must_use]
4996 pub fn analyze_generic_parameter_usize(&self, generic_parameter: &GenericParameter) -> usize {
4997 let usize_node = generic_parameter.get_unsigned_int_node();
4998 let usize_str = self.get_text(usize_node);
4999 Self::str_to_unsigned_int(usize_str).unwrap() as usize
5000 }
5001
5002 #[must_use]
5003 pub fn analyze_generic_parameter_usize_tuple(
5004 &self,
5005 generic_parameter: &GenericParameter,
5006 ) -> (usize, usize) {
5007 let (first, second) = generic_parameter.get_unsigned_int_tuple_nodes();
5008 let first_str = self.get_text(first);
5009 let second_str = self.get_text(second);
5010 let first_value = Self::str_to_unsigned_int(first_str).unwrap() as usize;
5011 let second_value = Self::str_to_unsigned_int(second_str).unwrap() as usize;
5012
5013 (first_value, second_value)
5014 }
5015
5016 pub fn analyze_special_named_type(
5017 &mut self,
5018 path: &[String],
5019 name: &str,
5020 ast_generic_parameters: &[GenericParameter],
5021 ) -> Option<TypeRef> {
5022 let converted_type = match name {
5023 "Any" => self.shared.state.types.any(),
5024 "Ptr" => {
5025 if self.shared.allow_unsafe {
5026 let inner_type = if ast_generic_parameters.len() == 1 {
5027 self.analyze_type(
5028 ast_generic_parameters[0].get_type(),
5029 &TypeAnalyzeContext::default(),
5030 )
5031 } else if ast_generic_parameters.is_empty() {
5032 self.shared.state.types.byte() } else {
5034 self.add_err_resolved(ErrorKind::UnexpectedType, &Node::default());
5035 return None;
5036 };
5037 let new_type = self.shared.state.types.ptr(inner_type);
5038 self.shared.state.associated_impls.prepare(&new_type);
5039 new_type
5040 } else {
5041 panic!("unsafe Ptr is not allowed");
5042 }
5043 }
5044 "String" => {
5045 if ast_generic_parameters.len() == 1 {
5046 let fixed_size =
5047 self.analyze_generic_parameter_usize(&ast_generic_parameters[0]);
5048 let new_type = self.shared.state.types.string_storage(fixed_size);
5049 let default_node = swamp_ast::Node::default();
5050 self.add_default_functions(&new_type, &default_node);
5051 new_type
5052 } else {
5053 return None;
5054 }
5055 }
5056 "Vec" => {
5057 if ast_generic_parameters.len() == 1 {
5058 let element_type = self.analyze_type(
5059 ast_generic_parameters[0].get_type(),
5060 &TypeAnalyzeContext::default(),
5061 );
5062 let vec_type = self.shared.state.types.dynamic_vec_view(&element_type);
5063 let default_node = swamp_ast::Node::default();
5065 self.add_default_functions(&vec_type, &default_node);
5066 vec_type
5067 } else if ast_generic_parameters.len() == 2 {
5068 let element_type = self.analyze_type(
5069 ast_generic_parameters[0].get_type(),
5070 &TypeAnalyzeContext::default(),
5071 );
5072 let fixed_size =
5073 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
5074 let vec_storage_type = self
5075 .shared
5076 .state
5077 .types
5078 .vec_storage(&element_type, fixed_size);
5079 let default_node = swamp_ast::Node::default();
5081 self.add_default_functions(&vec_storage_type, &default_node);
5082 vec_storage_type
5083 } else {
5084 panic!("todo: make this into an error")
5085 }
5086 }
5087 "Stack" => {
5088 if ast_generic_parameters.len() == 1 {
5089 let element_type = self.analyze_type(
5090 ast_generic_parameters[0].get_type(),
5091 &TypeAnalyzeContext::default(),
5092 );
5093 let stack_view_type = self.shared.state.types.stack_view(&element_type);
5094 let default_node = swamp_ast::Node::default();
5096 self.add_default_functions(&stack_view_type, &default_node);
5097 stack_view_type
5098 } else if ast_generic_parameters.len() == 2 {
5099 let element_type = self.analyze_type(
5100 ast_generic_parameters[0].get_type(),
5101 &TypeAnalyzeContext::default(),
5102 );
5103 let fixed_size =
5104 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
5105 let stack_storage_type = self
5106 .shared
5107 .state
5108 .types
5109 .stack_storage(&element_type, fixed_size);
5110 let default_node = swamp_ast::Node::default();
5112 self.add_default_functions(&stack_storage_type, &default_node);
5113 stack_storage_type
5114 } else {
5115 panic!("todo: make this into an error")
5116 }
5117 }
5118 "Queue" => {
5119 if ast_generic_parameters.len() == 1 {
5120 let element_type = self.analyze_type(
5121 ast_generic_parameters[0].get_type(),
5122 &TypeAnalyzeContext::default(),
5123 );
5124 let queue_view_type = self.shared.state.types.queue_view(&element_type);
5125 let default_node = swamp_ast::Node::default();
5127 self.add_default_functions(&queue_view_type, &default_node);
5128 queue_view_type
5129 } else if ast_generic_parameters.len() == 2 {
5130 let element_type = self.analyze_type(
5131 ast_generic_parameters[0].get_type(),
5132 &TypeAnalyzeContext::default(),
5133 );
5134 let fixed_size =
5135 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
5136 let queue_storage_type = self
5137 .shared
5138 .state
5139 .types
5140 .queue_storage(&element_type, fixed_size);
5141 let default_node = swamp_ast::Node::default();
5143 self.add_default_functions(&queue_storage_type, &default_node);
5144 queue_storage_type
5145 } else {
5146 panic!("todo: make this into an error")
5147 }
5148 }
5149 "Sparse" => {
5150 if ast_generic_parameters.len() == 1 {
5151 let element_type = self.analyze_type(
5152 ast_generic_parameters[0].get_type(),
5153 &TypeAnalyzeContext::default(),
5154 );
5155 let sparse_view_type = self.shared.state.types.sparse_view(&element_type);
5156 let default_node = swamp_ast::Node::default();
5158 self.add_default_functions(&sparse_view_type, &default_node);
5159 sparse_view_type
5160 } else if ast_generic_parameters.len() == 2 {
5161 let element_type = self.analyze_type(
5162 ast_generic_parameters[0].get_type(),
5163 &TypeAnalyzeContext::default(),
5164 );
5165 let fixed_size =
5166 self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
5167 let sparse_storage_type = self
5168 .shared
5169 .state
5170 .types
5171 .sparse_storage(&element_type, fixed_size);
5172 let default_node = swamp_ast::Node::default();
5174 self.add_default_functions(&sparse_storage_type, &default_node);
5175 sparse_storage_type
5176 } else {
5177 panic!("todo: make this into an error")
5178 }
5179 }
5180
5181 "Grid" => {
5182 if ast_generic_parameters.len() == 1 {
5183 let element_type = self.analyze_type(
5184 ast_generic_parameters[0].get_type(),
5185 &TypeAnalyzeContext::default(),
5186 );
5187 let grid_view_type = self.shared.state.types.grid_view(&element_type);
5188 let default_node = swamp_ast::Node::default();
5190 self.add_default_functions(&grid_view_type, &default_node);
5191 grid_view_type
5192 } else if ast_generic_parameters.len() == 2 {
5193 let element_type = self.analyze_type(
5194 ast_generic_parameters[0].get_type(),
5195 &TypeAnalyzeContext::default(),
5196 );
5197 let (width, height) =
5198 self.analyze_generic_parameter_usize_tuple(&ast_generic_parameters[1]);
5199 let grid_storage_type =
5200 self.shared
5201 .state
5202 .types
5203 .grid_storage(&element_type, width, height);
5204 let default_node = swamp_ast::Node::default();
5206 self.add_default_functions(&grid_storage_type, &default_node);
5207 grid_storage_type
5208 } else {
5209 panic!("todo: make this into an error")
5210 }
5211 }
5212
5213 _ => return None,
5214 };
5215
5216 Some(converted_type)
5217 }
5218
5219 fn special_static_member(
5220 &self,
5221 type_identifier: &QualifiedTypeIdentifier,
5222 member_name_node: &swamp_ast::Node,
5223 ) -> Option<Function> {
5224 if type_identifier.generic_params.is_empty() {
5225 return None;
5226 }
5227
5228 if type_identifier.module_path.is_some() {
5229 return None;
5230 }
5231
5232 let member_name = self.get_text(member_name_node);
5233 let name = self.get_text(&type_identifier.name.0);
5234
5235 match name {
5236 "Stack" => None,
5237 _ => None,
5238 }
5239 }
5240
5241 fn analyze_subscript_int(
5242 &mut self,
5243 collection_type: TypeRef,
5244 unsigned_int_expression: Expression,
5245 ) -> (Postfix, TypeRef) {
5246 let node = &unsigned_int_expression.node;
5247 match &*collection_type.kind {
5248 TypeKind::QueueStorage(element_type, _)
5249 | TypeKind::StackStorage(element_type, _)
5250 | TypeKind::StackView(element_type)
5251 | TypeKind::VecStorage(element_type, _)
5252 | TypeKind::StringStorage(element_type, _, _)
5253 | TypeKind::StringView(element_type, _)
5254 | TypeKind::FixedCapacityAndLengthArray(element_type, _)
5255 | TypeKind::DynamicLengthVecView(element_type)
5256 | TypeKind::SliceView(element_type) => {
5257 let vec_type = VecType {
5258 element: element_type.clone(),
5259 };
5260
5261 let postfix = Postfix {
5262 node: node.clone(),
5263 ty: collection_type.clone(),
5264 kind: PostfixKind::VecSubscript(vec_type, unsigned_int_expression),
5265 };
5266
5267 (postfix, element_type.clone())
5268 }
5269 TypeKind::SparseStorage(element_type, _) | TypeKind::SparseView(element_type) => {
5271 let sparse_type = SparseType {
5272 element: element_type.clone(),
5273 };
5274
5275 let postfix = Postfix {
5276 node: node.clone(),
5277 ty: collection_type.clone(),
5278 kind: PostfixKind::SparseSubscript(sparse_type, unsigned_int_expression),
5279 };
5280
5281 (postfix, element_type.clone())
5282 }
5283
5284 _ => {
5285 self.add_err_resolved(ErrorKind::CanNotSubscriptWithThatType, node);
5286
5287 let error_vec_type = VecType {
5288 element: self.types().unit(),
5289 };
5290
5291 let error_postfix = Postfix {
5292 node: node.clone(),
5293 ty: collection_type.clone(),
5294 kind: PostfixKind::VecSubscript(error_vec_type, unsigned_int_expression),
5295 };
5296
5297 (error_postfix, self.types().unit())
5298 }
5299 }
5300 }
5301
5302 fn analyze_subscript_range(
5303 &mut self,
5304 collection_type: TypeRef,
5305 range_expression: Expression,
5306 ) -> (Postfix, TypeRef) {
5307 let node = &range_expression.node;
5308 match &*collection_type.kind {
5309 TypeKind::QueueStorage(element_type, _)
5310 | TypeKind::StackStorage(element_type, _)
5311 | TypeKind::StackView(element_type)
5312 | TypeKind::VecStorage(element_type, _)
5313 | TypeKind::StringStorage(element_type, _, _)
5314 | TypeKind::StringView(element_type, _)
5315 | TypeKind::FixedCapacityAndLengthArray(element_type, _)
5316 | TypeKind::DynamicLengthVecView(element_type)
5317 | TypeKind::SliceView(element_type) => {
5318 let vec_type = VecType {
5319 element: element_type.clone(),
5320 };
5321
5322 let postfix = Postfix {
5323 node: node.clone(),
5324 ty: collection_type.clone(),
5325 kind: PostfixKind::VecSubscriptRange(vec_type, range_expression),
5326 };
5327
5328 (postfix, collection_type.clone())
5330 }
5331
5332 _ => {
5333 self.add_err_resolved(ErrorKind::CanNotSubscriptWithThatType, node);
5334
5335 let error_vec_type = VecType {
5336 element: self.types().unit(),
5337 };
5338
5339 let error_postfix = Postfix {
5340 node: node.clone(),
5341 ty: collection_type.clone(),
5342 kind: PostfixKind::VecSubscriptRange(error_vec_type, range_expression),
5343 };
5344
5345 (error_postfix, self.types().unit())
5346 }
5347 }
5348 }
5349 fn analyze_map_subscript(
5350 &mut self,
5351 key_type: &TypeRef,
5352 value_type: &TypeRef,
5353 lookup_expr: &swamp_ast::Expression,
5354 ) -> (Postfix, TypeRef) {
5355 let key_context = TypeContext::new_argument(key_type, false);
5356 let key_expression = self.analyze_expression(lookup_expr, &key_context);
5357
5358 let map_type = MapType {
5359 key: key_type.clone(),
5360 value: value_type.clone(),
5361 };
5362
5363 let postfix = Postfix {
5364 node: self.to_node(&lookup_expr.node),
5365 ty: key_type.clone(),
5366 kind: PostfixKind::MapSubscript(map_type, key_expression),
5367 };
5368
5369 (postfix, value_type.clone())
5370 }
5371}