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