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