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 let identifier_name = { self.get_text(&constant.constant_identifier.0) };
48 debug_assert!(
49 actual_constant_type.can_be_stored_in_field(),
50 "this field is not blittable {identifier_name:?}"
51 ); let name_node = self.to_node(&constant.constant_identifier.0);
54 let name_text = self.get_text_resolved(&name_node).to_string();
55 let constant = Constant {
56 name: name_node.clone(),
57 assigned_name: name_text,
58 id: ConstantId::from(self.shared.state.internal_function_id_allocator.alloc()),
59 expr: resolved_expr,
60 resolved_type: actual_constant_type,
61 function_scope_state: self.scope.total_scopes.clone(),
62 };
63
64 let const_ref = match self.shared.definition_table.add_constant(constant) {
65 Ok(c) => c,
66 Err(sem_err) => {
67 self.add_err_resolved(ErrorKind::SemanticError(sem_err), &name_node);
68 return;
69 }
70 };
71
72 match self
73 .shared
74 .lookup_table
75 .add_constant_link(const_ref.clone())
76 {
77 Ok(c) => c,
78 Err(sem_err) => {
79 self.add_err_resolved(ErrorKind::SemanticError(sem_err), &name_node);
80 return;
81 }
82 }
83
84 self.shared
86 .state
87 .constants_in_dependency_order
88 .push(const_ref);
89 }
90
91 pub(crate) fn analyze_constant_definition(&mut self, constant: &swamp_ast::ConstantInfo) {
92 self.analyze_constant(constant);
93 }
94
95 pub(crate) fn analyze_constant_access(
96 &mut self,
97 qualified_constant_identifier: &swamp_ast::QualifiedConstantIdentifier,
98 ) -> Expression {
99 match self.try_find_constant(qualified_constant_identifier) {
100 None => self.create_err(
101 ErrorKind::UnknownConstant,
102 &qualified_constant_identifier.name,
103 ),
104 Some(constant_ref) => {
105 let ty = constant_ref.resolved_type.clone();
106 self.create_expr(
107 ExpressionKind::ConstantAccess(constant_ref.clone()),
108 ty,
109 &qualified_constant_identifier.name,
110 )
111 }
112 }
113 }
114
115 #[must_use]
116 pub fn try_find_constant(
117 &self,
118 qualified_constant_identifier: &swamp_ast::QualifiedConstantIdentifier,
119 ) -> Option<&ConstantRef> {
120 let path = self.get_module_path(qualified_constant_identifier.module_path.as_ref());
121 let constant_name = self.get_text(&qualified_constant_identifier.name);
122
123 let maybe_symbol_table = self.shared.get_symbol_table(&path);
124 maybe_symbol_table.map_or_else(
125 || None,
126 |symbol_table| Some(symbol_table.get_constant(constant_name)),
127 )?
128 }
129}