1use cairo_lang_debug::DebugWithDb;
2use cairo_lang_defs::ids::{MemberId, NamedLanguageElementId, StatementUseId, VarId};
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, Id};
8use num_bigint::BigInt;
9
10use super::fmt::ExprFormatter;
11use super::pattern::Pattern;
12use crate::db::SemanticGroup;
13use crate::items::constant::ConstValueId;
14use crate::{ConcreteStructId, FunctionId, TypeId, semantic};
15
16pub type PatternId = Id<Pattern>;
17pub type ExprId = Id<Expr>;
18pub type StatementId = Id<Statement>;
19
20impl DebugWithDb<ExprFormatter<'_>> for PatternId {
21 fn fmt(
22 &self,
23 f: &mut std::fmt::Formatter<'_>,
24 expr_formatter: &ExprFormatter<'_>,
25 ) -> std::fmt::Result {
26 expr_formatter.db.pattern_semantic(expr_formatter.function_id, *self).fmt(f, expr_formatter)
27 }
28}
29impl DebugWithDb<ExprFormatter<'_>> for ExprId {
30 fn fmt(
31 &self,
32 f: &mut std::fmt::Formatter<'_>,
33 expr_formatter: &ExprFormatter<'_>,
34 ) -> std::fmt::Result {
35 expr_formatter.db.expr_semantic(expr_formatter.function_id, *self).fmt(f, expr_formatter)
36 }
37}
38impl DebugWithDb<ExprFormatter<'_>> for StatementId {
39 fn fmt(
40 &self,
41 f: &mut std::fmt::Formatter<'_>,
42 expr_formatter: &ExprFormatter<'_>,
43 ) -> std::fmt::Result {
44 expr_formatter
45 .db
46 .statement_semantic(expr_formatter.function_id, *self)
47 .fmt(f, expr_formatter)
48 }
49}
50
51#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
52#[debug_db(ExprFormatter<'a>)]
53pub enum Statement {
54 Expr(StatementExpr),
55 Let(StatementLet),
56 Continue(StatementContinue),
57 Return(StatementReturn),
58 Break(StatementBreak),
59 Item(StatementItem),
60}
61impl Statement {
62 pub fn stable_ptr(&self) -> ast::StatementPtr {
63 match self {
64 Statement::Expr(stmt) => stmt.stable_ptr,
65 Statement::Let(stmt) => stmt.stable_ptr,
66 Statement::Continue(stmt) => stmt.stable_ptr,
67 Statement::Return(stmt) => stmt.stable_ptr,
68 Statement::Break(stmt) => stmt.stable_ptr,
69 Statement::Item(stmt) => stmt.stable_ptr,
70 }
71 }
72}
73
74impl From<&Statement> for SyntaxStablePtrId {
75 fn from(statement: &Statement) -> Self {
76 statement.stable_ptr().into()
77 }
78}
79
80#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
81#[debug_db(ExprFormatter<'a>)]
82pub struct StatementExpr {
83 pub expr: ExprId,
84 #[hide_field_debug_with_db]
85 #[dont_rewrite]
86 pub stable_ptr: ast::StatementPtr,
87}
88
89#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
90#[debug_db(ExprFormatter<'a>)]
91pub struct StatementLet {
92 pub pattern: PatternId,
93 pub expr: ExprId,
94 pub else_clause: Option<ExprId>,
95 #[hide_field_debug_with_db]
96 #[dont_rewrite]
97 pub stable_ptr: ast::StatementPtr,
98}
99
100#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
101#[debug_db(ExprFormatter<'a>)]
102pub struct StatementContinue {
103 #[hide_field_debug_with_db]
104 #[dont_rewrite]
105 pub stable_ptr: ast::StatementPtr,
106}
107
108#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
109#[debug_db(ExprFormatter<'a>)]
110pub struct StatementReturn {
111 pub expr_option: Option<ExprId>,
112 #[hide_field_debug_with_db]
113 #[dont_rewrite]
114 pub stable_ptr: ast::StatementPtr,
115}
116
117#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
118#[debug_db(ExprFormatter<'a>)]
119pub struct StatementBreak {
120 pub expr_option: Option<ExprId>,
121 #[hide_field_debug_with_db]
122 #[dont_rewrite]
123 pub stable_ptr: ast::StatementPtr,
124}
125
126#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
127#[debug_db(ExprFormatter<'a>)]
128pub struct StatementItem {
129 #[hide_field_debug_with_db]
130 #[dont_rewrite]
131 pub stable_ptr: ast::StatementPtr,
132}
133
134#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
136#[debug_db(ExprFormatter<'a>)]
137pub enum Expr {
138 Tuple(ExprTuple),
139 Snapshot(ExprSnapshot),
140 Desnap(ExprDesnap),
141 Assignment(ExprAssignment),
142 LogicalOperator(ExprLogicalOperator),
143 Block(ExprBlock),
144 Loop(ExprLoop),
145 While(ExprWhile),
146 For(ExprFor),
147 FunctionCall(ExprFunctionCall),
148 Match(ExprMatch),
149 If(ExprIf),
150 Var(ExprVar),
151 Literal(ExprLiteral),
152 StringLiteral(ExprStringLiteral),
153 MemberAccess(ExprMemberAccess),
154 StructCtor(ExprStructCtor),
155 EnumVariantCtor(ExprEnumVariantCtor),
156 PropagateError(ExprPropagateError),
157 Constant(ExprConstant),
158 FixedSizeArray(ExprFixedSizeArray),
159 ExprClosure(ExprClosure),
160 Missing(ExprMissing),
161}
162impl Expr {
163 pub fn ty(&self) -> semantic::TypeId {
164 match self {
165 Expr::Assignment(expr) => expr.ty,
166 Expr::Tuple(expr) => expr.ty,
167 Expr::Snapshot(expr) => expr.ty,
168 Expr::Desnap(expr) => expr.ty,
169 Expr::LogicalOperator(expr) => expr.ty,
170 Expr::Block(expr) => expr.ty,
171 Expr::Loop(expr) => expr.ty,
172 Expr::While(expr) => expr.ty,
173 Expr::For(expr) => expr.ty,
174 Expr::FunctionCall(expr) => expr.ty,
175 Expr::Match(expr) => expr.ty,
176 Expr::If(expr) => expr.ty,
177 Expr::Var(expr) => expr.ty,
178 Expr::Literal(expr) => expr.ty,
179 Expr::StringLiteral(expr) => expr.ty,
180 Expr::MemberAccess(expr) => expr.ty,
181 Expr::StructCtor(expr) => expr.ty,
182 Expr::EnumVariantCtor(expr) => expr.ty,
183 Expr::PropagateError(expr) => expr.ok_variant.ty,
184 Expr::Constant(expr) => expr.ty,
185 Expr::Missing(expr) => expr.ty,
186 Expr::FixedSizeArray(expr) => expr.ty,
187 Expr::ExprClosure(expr) => expr.ty,
188 }
189 }
190 pub fn stable_ptr(&self) -> ast::ExprPtr {
191 match self {
192 Expr::Assignment(expr) => expr.stable_ptr,
193 Expr::Tuple(expr) => expr.stable_ptr,
194 Expr::Snapshot(expr) => expr.stable_ptr,
195 Expr::Desnap(expr) => expr.stable_ptr,
196 Expr::LogicalOperator(expr) => expr.stable_ptr,
197 Expr::Block(expr) => expr.stable_ptr,
198 Expr::Loop(expr) => expr.stable_ptr,
199 Expr::While(expr) => expr.stable_ptr,
200 Expr::For(expr) => expr.stable_ptr,
201 Expr::FunctionCall(expr) => expr.stable_ptr,
202 Expr::Match(expr) => expr.stable_ptr,
203 Expr::If(expr) => expr.stable_ptr,
204 Expr::Var(expr) => expr.stable_ptr,
205 Expr::Literal(expr) => expr.stable_ptr,
206 Expr::StringLiteral(expr) => expr.stable_ptr,
207 Expr::MemberAccess(expr) => expr.stable_ptr,
208 Expr::StructCtor(expr) => expr.stable_ptr,
209 Expr::EnumVariantCtor(expr) => expr.stable_ptr,
210 Expr::PropagateError(expr) => expr.stable_ptr,
211 Expr::Constant(expr) => expr.stable_ptr,
212 Expr::Missing(expr) => expr.stable_ptr,
213 Expr::FixedSizeArray(expr) => expr.stable_ptr,
214 Expr::ExprClosure(expr) => expr.stable_ptr,
215 }
216 }
217
218 pub fn as_member_path(&self) -> Option<ExprVarMemberPath> {
219 match self {
220 Expr::Var(expr) => Some(ExprVarMemberPath::Var(expr.clone())),
221 Expr::MemberAccess(expr) => expr.member_path.clone(),
222 _ => None,
223 }
224 }
225}
226
227impl From<&Expr> for SyntaxStablePtrId {
228 fn from(expr: &Expr) -> Self {
229 expr.stable_ptr().into()
230 }
231}
232
233#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
234#[debug_db(ExprFormatter<'a>)]
235pub struct ExprTuple {
236 pub items: Vec<ExprId>,
237 pub ty: semantic::TypeId,
238 #[hide_field_debug_with_db]
239 #[dont_rewrite]
240 pub stable_ptr: ast::ExprPtr,
241}
242
243#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
244#[debug_db(ExprFormatter<'a>)]
245pub struct ExprFixedSizeArray {
246 pub items: FixedSizeArrayItems,
247 pub ty: semantic::TypeId,
248 #[hide_field_debug_with_db]
249 #[dont_rewrite]
250 pub stable_ptr: ast::ExprPtr,
251}
252
253#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
256#[debug_db(ExprFormatter<'a>)]
257pub enum FixedSizeArrayItems {
258 Items(Vec<ExprId>),
259 ValueAndSize(ExprId, ConstValueId),
260}
261
262#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
263#[debug_db(ExprFormatter<'a>)]
264pub struct ExprSnapshot {
265 pub inner: ExprId,
266 pub ty: semantic::TypeId,
267 #[hide_field_debug_with_db]
268 #[dont_rewrite]
269 pub stable_ptr: ast::ExprPtr,
270}
271
272#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
273#[debug_db(ExprFormatter<'a>)]
274pub struct ExprDesnap {
275 pub inner: ExprId,
276 pub ty: semantic::TypeId,
277 #[hide_field_debug_with_db]
278 #[dont_rewrite]
279 pub stable_ptr: ast::ExprPtr,
280}
281
282#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
283#[debug_db(ExprFormatter<'a>)]
284pub struct ExprBlock {
285 pub statements: Vec<StatementId>,
286 pub tail: Option<ExprId>,
291 pub ty: semantic::TypeId,
292 #[hide_field_debug_with_db]
293 #[dont_rewrite]
294 pub stable_ptr: ast::ExprPtr,
295}
296
297#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
298#[debug_db(ExprFormatter<'a>)]
299pub struct ExprLoop {
300 pub body: ExprId,
301 pub ty: semantic::TypeId,
302 #[hide_field_debug_with_db]
303 #[dont_rewrite]
304 pub stable_ptr: ast::ExprPtr,
305}
306
307#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
308#[debug_db(ExprFormatter<'a>)]
309pub struct ExprWhile {
310 pub condition: Condition,
311 pub body: ExprId,
312 pub ty: semantic::TypeId,
313 #[hide_field_debug_with_db]
314 #[dont_rewrite]
315 pub stable_ptr: ast::ExprPtr,
316}
317
318#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
319#[debug_db(ExprFormatter<'a>)]
320pub struct ExprFor {
321 pub into_iter: FunctionId,
322 pub into_iter_member_path: ExprVarMemberPath,
323 pub next_function_id: FunctionId,
324 pub expr_id: ExprId,
325 pub pattern: PatternId,
326 pub body: ExprId,
327 pub ty: semantic::TypeId,
328 #[hide_field_debug_with_db]
329 #[dont_rewrite]
330 pub stable_ptr: ast::ExprPtr,
331}
332
333#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
335pub enum ExprVarMemberPath {
336 Var(ExprVar),
337 Member {
338 parent: Box<ExprVarMemberPath>,
339 member_id: MemberId,
340 #[dont_rewrite]
341 stable_ptr: ast::ExprPtr,
342 concrete_struct_id: ConcreteStructId,
343 ty: TypeId,
345 },
346}
347impl ExprVarMemberPath {
348 pub fn base_var(&self) -> VarId {
349 match self {
350 ExprVarMemberPath::Var(expr) => expr.var,
351 ExprVarMemberPath::Member { parent, .. } => parent.base_var(),
352 }
353 }
354 pub fn ty(&self) -> TypeId {
355 match self {
356 ExprVarMemberPath::Var(expr) => expr.ty,
357 ExprVarMemberPath::Member { ty, .. } => *ty,
358 }
359 }
360 pub fn stable_ptr(&self) -> ast::ExprPtr {
361 match self {
362 ExprVarMemberPath::Var(var) => var.stable_ptr,
363 ExprVarMemberPath::Member { stable_ptr, .. } => *stable_ptr,
364 }
365 }
366}
367impl<'a> DebugWithDb<ExprFormatter<'a>> for ExprVarMemberPath {
368 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &ExprFormatter<'a>) -> std::fmt::Result {
369 match self {
370 ExprVarMemberPath::Var(var) => var.fmt(f, db),
371 ExprVarMemberPath::Member { parent, member_id, .. } => {
372 write!(f, "{:?}::{}", parent.debug(db), member_id.name(db.db))
373 }
374 }
375 }
376}
377#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
378#[debug_db(ExprFormatter<'a>)]
379pub struct ExprClosure {
380 pub body: ExprId,
381 pub params: Vec<semantic::Parameter>,
382 #[hide_field_debug_with_db]
383 #[dont_rewrite]
384 pub stable_ptr: ast::ExprPtr,
385 pub ty: TypeId,
386}
387
388#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
389#[debug_db(ExprFormatter<'a>)]
390pub enum ExprFunctionCallArg {
391 Reference(ExprVarMemberPath),
392 Value(ExprId),
393}
394
395#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
396#[debug_db(ExprFormatter<'a>)]
397pub struct ExprFunctionCall {
398 pub function: FunctionId,
399 pub args: Vec<ExprFunctionCallArg>,
400 pub coupon_arg: Option<ExprId>,
404 pub ty: semantic::TypeId,
405 #[hide_field_debug_with_db]
406 #[dont_rewrite]
407 pub stable_ptr: ast::ExprPtr,
408}
409
410#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
411#[debug_db(ExprFormatter<'a>)]
412pub struct ExprMatch {
413 pub matched_expr: ExprId,
414 pub arms: Vec<MatchArm>,
415 pub ty: semantic::TypeId,
416 #[hide_field_debug_with_db]
417 #[dont_rewrite]
418 pub stable_ptr: ast::ExprPtr,
419}
420
421#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
422#[debug_db(ExprFormatter<'a>)]
423pub struct ExprIf {
424 pub conditions: Vec<Condition>,
425 pub if_block: ExprId,
426 pub else_block: Option<ExprId>,
427 pub ty: semantic::TypeId,
428 #[hide_field_debug_with_db]
429 #[dont_rewrite]
430 pub stable_ptr: ast::ExprPtr,
431}
432
433#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
434#[debug_db(ExprFormatter<'a>)]
435pub enum Condition {
436 BoolExpr(ExprId),
437 Let(ExprId, Vec<PatternId>),
438}
439
440#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
441#[debug_db(ExprFormatter<'a>)]
442pub struct MatchArm {
443 pub patterns: Vec<PatternId>,
444 pub expression: ExprId,
445}
446
447#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
448#[debug_db(ExprFormatter<'a>)]
449pub struct ExprAssignment {
450 pub ref_arg: ExprVarMemberPath,
451 pub rhs: semantic::ExprId,
452 pub ty: semantic::TypeId,
454 #[hide_field_debug_with_db]
455 #[dont_rewrite]
456 pub stable_ptr: ast::ExprPtr,
457}
458
459#[derive(Clone, Debug, Eq, Hash, PartialEq)]
460pub enum LogicalOperator {
461 AndAnd,
462 OrOr,
463}
464
465#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
466#[debug_db(ExprFormatter<'a>)]
467pub struct ExprLogicalOperator {
468 pub lhs: semantic::ExprId,
469 #[dont_rewrite]
470 pub op: LogicalOperator,
471 pub rhs: semantic::ExprId,
472 pub ty: semantic::TypeId,
474 #[hide_field_debug_with_db]
475 #[dont_rewrite]
476 pub stable_ptr: ast::ExprPtr,
477}
478
479#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
480pub struct ExprVar {
481 pub var: VarId,
482 pub ty: semantic::TypeId,
483 #[dont_rewrite]
484 pub stable_ptr: ast::ExprPtr,
485}
486impl<'a> DebugWithDb<ExprFormatter<'a>> for ExprVar {
487 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &ExprFormatter<'a>) -> std::fmt::Result {
488 self.var.fmt(f, db)
489 }
490}
491
492#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
494#[debug_db(ExprFormatter<'a>)]
495pub struct ExprLiteral {
496 #[dont_rewrite]
497 pub value: BigInt,
498 pub ty: semantic::TypeId,
499 #[hide_field_debug_with_db]
500 #[dont_rewrite]
501 pub stable_ptr: ast::ExprPtr,
502}
503
504#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
505#[debug_db(ExprFormatter<'a>)]
506pub struct ExprStringLiteral {
507 #[dont_rewrite]
508 pub value: String,
509 pub ty: semantic::TypeId,
510 #[hide_field_debug_with_db]
511 #[dont_rewrite]
512 pub stable_ptr: ast::ExprPtr,
513}
514
515#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
516#[debug_db(ExprFormatter<'a>)]
517pub struct ExprMemberAccess {
518 pub expr: semantic::ExprId,
519 pub concrete_struct_id: ConcreteStructId,
520 pub member: MemberId,
521 pub ty: semantic::TypeId,
522 #[hide_field_debug_with_db]
523 pub member_path: Option<ExprVarMemberPath>,
524 #[hide_field_debug_with_db]
525 #[dont_rewrite]
526 pub n_snapshots: usize,
527 #[hide_field_debug_with_db]
528 #[dont_rewrite]
529 pub stable_ptr: ast::ExprPtr,
530}
531
532#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
533#[debug_db(ExprFormatter<'a>)]
534pub struct ExprStructCtor {
535 pub concrete_struct_id: ConcreteStructId,
536 pub members: Vec<(MemberId, ExprId)>,
537 pub base_struct: Option<ExprId>,
540 pub ty: semantic::TypeId,
541 #[hide_field_debug_with_db]
542 #[dont_rewrite]
543 pub stable_ptr: ast::ExprPtr,
544}
545
546#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
547#[debug_db(ExprFormatter<'a>)]
548pub struct ExprEnumVariantCtor {
549 pub variant: semantic::ConcreteVariant,
550 pub value_expr: ExprId,
551 pub ty: semantic::TypeId,
552 #[hide_field_debug_with_db]
553 #[dont_rewrite]
554 pub stable_ptr: ast::ExprPtr,
555}
556
557#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
558#[debug_db(ExprFormatter<'a>)]
559pub struct ExprPropagateError {
560 pub inner: ExprId,
561 pub ok_variant: semantic::ConcreteVariant,
562 pub err_variant: semantic::ConcreteVariant,
563 pub func_err_variant: semantic::ConcreteVariant,
564 #[hide_field_debug_with_db]
565 #[dont_rewrite]
566 pub stable_ptr: ast::ExprPtr,
567}
568
569#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
570#[debug_db(ExprFormatter<'a>)]
571pub struct ExprConstant {
572 pub const_value_id: ConstValueId,
573 pub ty: semantic::TypeId,
574 #[dont_rewrite]
575 #[hide_field_debug_with_db]
576 pub stable_ptr: ast::ExprPtr,
577}
578
579#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
580#[debug_db(ExprFormatter<'a>)]
581pub struct ExprUse {
582 pub const_value_id: StatementUseId,
583 pub ty: semantic::TypeId,
584 #[dont_rewrite]
585 #[hide_field_debug_with_db]
586 pub stable_ptr: ast::ExprPtr,
587}
588
589#[derive(Clone, Debug, Hash, PartialEq, Eq, DebugWithDb, SemanticObject)]
590#[debug_db(ExprFormatter<'a>)]
591pub struct ExprMissing {
592 pub ty: semantic::TypeId,
593 #[hide_field_debug_with_db]
594 #[dont_rewrite]
595 pub stable_ptr: ast::ExprPtr,
596 #[hide_field_debug_with_db]
597 #[dont_rewrite]
598 pub diag_added: DiagnosticAdded,
599}
600
601#[derive(Clone, Debug, Default, PartialEq, Eq, DebugWithDb)]
603#[debug_db(dyn SemanticGroup + 'static)]
604pub struct Arenas {
605 pub exprs: Arena<semantic::Expr>,
606 pub patterns: Arena<semantic::Pattern>,
607 pub statements: Arena<semantic::Statement>,
608}