1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use std::sync::Arc;
use cairo_lang_defs::ids::{ConstantId, LanguageElementId};
use cairo_lang_diagnostics::{Diagnostics, Maybe, ToMaybe};
use cairo_lang_proc_macros::DebugWithDb;
use crate::db::SemanticGroup;
use crate::diagnostic::SemanticDiagnostics;
use crate::expr::compute::{compute_expr_semantic, ComputationContext, Environment};
use crate::resolve_path::{ResolvedLookback, Resolver};
use crate::types::resolve_type;
use crate::{Expr, SemanticDiagnostic};
#[cfg(test)]
#[path = "constant_test.rs"]
mod test;
#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
#[debug_db(dyn SemanticGroup + 'static)]
pub struct Constant {
pub value: Expr,
}
#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
#[debug_db(dyn SemanticGroup + 'static)]
pub struct ConstantData {
diagnostics: Diagnostics<SemanticDiagnostic>,
constant: Constant,
resolved_lookback: Arc<ResolvedLookback>,
}
pub fn priv_constant_semantic_data(
db: &dyn SemanticGroup,
const_id: ConstantId,
) -> Maybe<ConstantData> {
let module_file_id = const_id.module_file_id(db.upcast());
let mut diagnostics = SemanticDiagnostics::new(module_file_id);
let module_constants = db.module_constants(module_file_id.0)?;
let const_ast = module_constants.get(&const_id).to_maybe()?;
let syntax_db = db.upcast();
let mut resolver = Resolver::new(db, module_file_id, &[]);
let const_type = resolve_type(
db,
&mut diagnostics,
&mut resolver,
&const_ast.type_clause(syntax_db).ty(syntax_db),
);
let mut ctx =
ComputationContext::new(db, &mut diagnostics, resolver, None, Environment::default());
let value = compute_expr_semantic(&mut ctx, &const_ast.value(syntax_db));
let value_type = value.ty();
if !const_type.is_missing(db) && !value_type.is_missing(db) && value_type != const_type {
ctx.diagnostics.report(
&const_ast.value(syntax_db),
crate::diagnostic::SemanticDiagnosticKind::WrongType {
expected_ty: const_type,
actual_ty: value_type,
},
);
}
if !matches!(value, Expr::Literal(_)) {
ctx.diagnostics.report(
&const_ast.value(syntax_db),
crate::diagnostic::SemanticDiagnosticKind::OnlyLiteralConstants,
);
};
let constant = Constant { value };
let resolved_lookback = Arc::new(ctx.resolver.lookback);
Ok(ConstantData { diagnostics: diagnostics.build(), constant, resolved_lookback })
}
pub fn constant_semantic_diagnostics(
db: &dyn SemanticGroup,
const_id: ConstantId,
) -> Diagnostics<SemanticDiagnostic> {
db.priv_constant_semantic_data(const_id).map(|data| data.diagnostics).unwrap_or_default()
}
pub fn constant_semantic_data(db: &dyn SemanticGroup, const_id: ConstantId) -> Maybe<Constant> {
Ok(db.priv_constant_semantic_data(const_id)?.constant)
}
pub fn constant_resolved_lookback(
db: &dyn SemanticGroup,
const_id: ConstantId,
) -> Maybe<Arc<ResolvedLookback>> {
Ok(db.priv_constant_semantic_data(const_id)?.resolved_lookback)
}