swamp_analyzer/
constant.rs1use crate::{Analyzer, TypeContext};
6use swamp_semantic::err::ErrorKind;
7use swamp_semantic::{Constant, ConstantId, ConstantRef, Expression, ExpressionKind};
8
9impl Analyzer<'_> {
10 fn analyze_constant(&mut self, constant: &swamp_ast::ConstantInfo) {
11 let maybe_annotation_type = constant
12 .annotation
13 .as_ref()
14 .map(|found_ast_type| self.analyze_type(found_ast_type));
15
16 let context = TypeContext::new_unsure_argument(maybe_annotation_type.as_ref(), true);
17
18 let resolved_expr = self.analyze_expression(&constant.expression, &context);
19
20 let actual_constant_type = if let Some(annotation_type) = maybe_annotation_type {
21 let extra_verification = false;
22 if extra_verification {
23 let debug_context = TypeContext::new_anything_argument(
24 annotation_type.collection_view_that_needs_explicit_storage(),
25 );
26 let worked_without_annotation =
27 self.analyze_expression(&constant.expression, &debug_context);
28 if self
29 .shared
30 .state
31 .types
32 .compatible_with(&annotation_type, &worked_without_annotation.ty)
33 {
34 let identifier_name = { self.get_text(&constant.constant_identifier.0) };
35 eprintln!(
36 "annotation was not needed for constant: {identifier_name} in {:?}",
37 self.module_path
38 );
39 }
40 }
41 annotation_type
42 } else {
43 resolved_expr.ty.clone()
44 };
45
46 if !actual_constant_type.can_be_stored_in_transient_field() {
48 self.add_err(ErrorKind::NeedStorage, &constant.constant_identifier.0);
49 return;
50 }
51 if !actual_constant_type.can_be_stored_in_field() {
52 self.add_hint(ErrorKind::NeedStorage, &constant.constant_identifier.0);
53 }
54
55 let name_node = self.to_node(&constant.constant_identifier.0);
58 let name_text = self.get_text_resolved(&name_node).to_string();
59 let constant = Constant {
60 name: name_node.clone(),
61 assigned_name: name_text,
62 id: ConstantId::from(self.shared.state.internal_function_id_allocator.alloc()),
63 expr: resolved_expr,
64 resolved_type: actual_constant_type,
65 function_scope_state: self.scope.total_scopes.clone(),
66 };
67
68 let const_ref = match self.shared.definition_table.add_constant(constant) {
69 Ok(c) => c,
70 Err(sem_err) => {
71 self.add_err_resolved(ErrorKind::SemanticError(sem_err), &name_node);
72 return;
73 }
74 };
75
76 match self
77 .shared
78 .lookup_table
79 .add_constant_link(const_ref.clone())
80 {
81 Ok(c) => c,
82 Err(sem_err) => {
83 self.add_err_resolved(ErrorKind::SemanticError(sem_err), &name_node);
84 return;
85 }
86 }
87
88 self.shared
90 .state
91 .constants_in_dependency_order
92 .push(const_ref);
93 }
94
95 pub(crate) fn analyze_constant_definition(&mut self, constant: &swamp_ast::ConstantInfo) {
96 self.analyze_constant(constant);
97 }
98
99 pub(crate) fn analyze_constant_access(
100 &mut self,
101 qualified_constant_identifier: &swamp_ast::QualifiedConstantIdentifier,
102 ) -> Expression {
103 match self.try_find_constant(qualified_constant_identifier) {
104 None => self.create_err(
105 ErrorKind::UnknownConstant,
106 &qualified_constant_identifier.name,
107 ),
108 Some(constant_ref) => {
109 let ty = constant_ref.resolved_type.clone();
110 self.create_expr(
111 ExpressionKind::ConstantAccess(constant_ref.clone()),
112 ty,
113 &qualified_constant_identifier.name,
114 )
115 }
116 }
117 }
118
119 #[must_use]
120 pub fn try_find_constant(
121 &self,
122 qualified_constant_identifier: &swamp_ast::QualifiedConstantIdentifier,
123 ) -> Option<&ConstantRef> {
124 let path = self.get_module_path(qualified_constant_identifier.module_path.as_ref());
125 let constant_name = self.get_text(&qualified_constant_identifier.name);
126
127 let maybe_symbol_table = self.shared.get_symbol_table(&path);
128 maybe_symbol_table.map_or_else(
129 || None,
130 |symbol_table| Some(symbol_table.get_constant(constant_name)),
131 )?
132 }
133}