cairo_lang_semantic/expr/
pattern.rs1use cairo_lang_debug::DebugWithDb;
2use cairo_lang_defs::ids::FunctionWithBodyId;
3use cairo_lang_diagnostics::DiagnosticAdded;
4use cairo_lang_filesystem::ids::SmolStrId;
5use cairo_lang_proc_macros::{DebugWithDb, SemanticObject};
6use cairo_lang_syntax::node::ast;
7use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
8use salsa::Database;
9
10use super::fmt::ExprFormatter;
11use crate::items::function_with_body::FunctionWithBodySemantic;
12use crate::{
13 ConcreteStructId, ExprLiteral, ExprStringLiteral, LocalVariable, PatternArena, PatternId,
14 semantic,
15};
16
17#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, SemanticObject)]
26#[debug_db(ExprFormatter<'db>)]
27pub enum Pattern<'db> {
28 Literal(PatternLiteral<'db>),
29 StringLiteral(PatternStringLiteral<'db>),
30 Variable(PatternVariable<'db>),
31 Struct(PatternStruct<'db>),
32 Tuple(PatternTuple<'db>),
33 FixedSizeArray(PatternFixedSizeArray<'db>),
34 EnumVariant(PatternEnumVariant<'db>),
35 Otherwise(PatternOtherwise<'db>),
36 Missing(PatternMissing<'db>),
37}
38
39impl<'db> Pattern<'db> {
40 pub fn ty(&self) -> semantic::TypeId<'db> {
41 match self {
42 Pattern::Literal(literal) => literal.literal.ty,
43 Pattern::StringLiteral(string_literal) => string_literal.string_literal.ty,
44 Pattern::Variable(variable) => variable.var.ty,
45 Pattern::Struct(pattern_struct) => pattern_struct.ty,
46 Pattern::Tuple(pattern_tuple) => pattern_tuple.ty,
47 Pattern::FixedSizeArray(pattern_fixed_size_array) => pattern_fixed_size_array.ty,
48 Pattern::EnumVariant(pattern_enum_variant) => pattern_enum_variant.ty,
49 Pattern::Otherwise(pattern_otherwise) => pattern_otherwise.ty,
50 Pattern::Missing(pattern_missing) => pattern_missing.ty,
51 }
52 }
53
54 pub fn variables(
55 &self,
56 queryable: &dyn PatternVariablesQueryable<'db>,
57 ) -> Vec<PatternVariable<'db>> {
58 match self {
59 Pattern::Variable(variable) => vec![variable.clone()],
60 Pattern::Struct(pattern_struct) => pattern_struct
61 .field_patterns
62 .iter()
63 .flat_map(|(pattern, _member)| queryable.query(*pattern))
64 .collect(),
65 Pattern::Tuple(pattern_tuple) => pattern_tuple
66 .field_patterns
67 .iter()
68 .flat_map(|pattern| queryable.query(*pattern))
69 .collect(),
70 Pattern::FixedSizeArray(pattern_fixed_size_array) => pattern_fixed_size_array
71 .elements_patterns
72 .iter()
73 .flat_map(|pattern| queryable.query(*pattern))
74 .collect(),
75 Pattern::EnumVariant(pattern_enum_variant) => {
76 match &pattern_enum_variant.inner_pattern {
77 Some(pattern) => queryable.query(*pattern),
78 None => vec![],
79 }
80 }
81 Pattern::Literal(_)
82 | Pattern::StringLiteral(_)
83 | Pattern::Otherwise(_)
84 | Pattern::Missing(_) => vec![],
85 }
86 }
87
88 pub fn stable_ptr(&self) -> ast::PatternPtr<'db> {
89 match self {
90 Pattern::Literal(pattern) => pattern.stable_ptr,
91 Pattern::StringLiteral(pattern) => pattern.stable_ptr,
92 Pattern::Variable(pattern) => pattern.stable_ptr,
93 Pattern::Struct(pattern) => pattern.stable_ptr.into(),
94 Pattern::Tuple(pattern) => pattern.stable_ptr.into(),
95 Pattern::FixedSizeArray(pattern) => pattern.stable_ptr.into(),
96 Pattern::EnumVariant(pattern) => pattern.stable_ptr,
97 Pattern::Otherwise(pattern) => pattern.stable_ptr.into(),
98 Pattern::Missing(pattern) => pattern.stable_ptr,
99 }
100 }
101}
102
103impl<'db> From<&Pattern<'db>> for SyntaxStablePtrId<'db> {
104 fn from(pattern: &Pattern<'db>) -> Self {
105 pattern.stable_ptr().into()
106 }
107}
108
109pub trait PatternVariablesQueryable<'a> {
111 fn query(&self, id: PatternId) -> Vec<PatternVariable<'a>>;
113}
114
115impl<'a> PatternVariablesQueryable<'a> for PatternArena<'a> {
116 fn query(&self, id: PatternId) -> Vec<PatternVariable<'a>> {
117 self[id].variables(self)
118 }
119}
120
121pub struct QueryPatternVariablesFromDb<'a>(
126 pub &'a (dyn Database + 'static),
127 pub FunctionWithBodyId<'a>,
128);
129
130impl<'a> PatternVariablesQueryable<'a> for QueryPatternVariablesFromDb<'a> {
131 fn query(&self, id: PatternId) -> Vec<PatternVariable<'a>> {
132 let pattern: Pattern<'a> = self.0.pattern_semantic(self.1, id);
133 pattern.variables(self)
134 }
135}
136
137#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
138#[debug_db(ExprFormatter<'db>)]
139pub struct PatternLiteral<'db> {
140 pub literal: ExprLiteral<'db>,
141 #[hide_field_debug_with_db]
142 #[dont_rewrite]
143 pub stable_ptr: ast::PatternPtr<'db>,
144}
145
146#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
147#[debug_db(ExprFormatter<'db>)]
148pub struct PatternStringLiteral<'db> {
149 pub string_literal: ExprStringLiteral<'db>,
150 #[hide_field_debug_with_db]
151 #[dont_rewrite]
152 pub stable_ptr: ast::PatternPtr<'db>,
153}
154
155#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
157pub struct PatternVariable<'db> {
158 #[dont_rewrite]
159 pub name: SmolStrId<'db>,
160 pub var: LocalVariable<'db>,
161 #[dont_rewrite]
162 pub stable_ptr: ast::PatternPtr<'db>,
163}
164impl<'db> DebugWithDb<'db> for PatternVariable<'db> {
165 type Db = ExprFormatter<'db>;
166
167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db ExprFormatter<'_>) -> std::fmt::Result {
168 write!(f, "{}", self.name.long(db.db))
169 }
170}
171
172#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb, SemanticObject)]
174#[debug_db(ExprFormatter<'db>)]
175pub struct PatternStruct<'db> {
176 pub concrete_struct_id: ConcreteStructId<'db>,
177 pub field_patterns: Vec<(PatternId, semantic::Member<'db>)>,
179 pub ty: semantic::TypeId<'db>,
180 #[dont_rewrite]
181 pub n_snapshots: usize,
182 #[hide_field_debug_with_db]
183 #[dont_rewrite]
184 pub stable_ptr: ast::PatternStructPtr<'db>,
185}
186
187#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
189#[debug_db(ExprFormatter<'db>)]
190pub struct PatternTuple<'db> {
191 pub field_patterns: Vec<PatternId>,
192 pub ty: semantic::TypeId<'db>,
193 #[hide_field_debug_with_db]
194 #[dont_rewrite]
195 pub stable_ptr: ast::PatternTuplePtr<'db>,
196}
197
198#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
200#[debug_db(ExprFormatter<'db>)]
201pub struct PatternFixedSizeArray<'db> {
202 pub elements_patterns: Vec<PatternId>,
203 pub ty: semantic::TypeId<'db>,
204 #[hide_field_debug_with_db]
205 #[dont_rewrite]
206 pub stable_ptr: ast::PatternFixedSizeArrayPtr<'db>,
207}
208
209#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
211#[debug_db(ExprFormatter<'db>)]
212pub struct PatternEnumVariant<'db> {
213 pub variant: semantic::ConcreteVariant<'db>,
214 pub inner_pattern: Option<PatternId>,
215 pub ty: semantic::TypeId<'db>,
216 #[hide_field_debug_with_db]
217 #[dont_rewrite]
218 pub stable_ptr: ast::PatternPtr<'db>,
219}
220
221#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
222#[debug_db(ExprFormatter<'db>)]
223pub struct PatternOtherwise<'db> {
224 pub ty: semantic::TypeId<'db>,
225 #[hide_field_debug_with_db]
226 #[dont_rewrite]
227 pub stable_ptr: ast::TerminalUnderscorePtr<'db>,
228}
229
230#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
231#[debug_db(ExprFormatter<'db>)]
232pub struct PatternMissing<'db> {
233 pub ty: semantic::TypeId<'db>,
234 #[hide_field_debug_with_db]
235 #[dont_rewrite]
236 pub stable_ptr: ast::PatternPtr<'db>,
237 #[hide_field_debug_with_db]
238 #[dont_rewrite]
239 pub diag_added: DiagnosticAdded,
240}