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