1use crate::ir::span::Span;
2
3#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
5pub struct BindingExpr {
6 pub expr: Expr,
7 pub span: Span,
8}
9
10#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
12pub enum Expr {
13 FieldAccess(FieldAccessExpr),
15 SharedFieldAccess(SharedFieldAccessExpr),
17 MethodCall(MethodCallExpr),
18 BinaryOp(BinaryOpExpr),
19 UnaryOp(UnaryOpExpr),
20 Conditional(ConditionalExpr),
21 Literal(LiteralExpr),
22}
23
24#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
26pub struct FieldAccessExpr {
27 pub path: Vec<String>,
28}
29
30#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
35pub struct SharedFieldAccessExpr {
36 pub path: Vec<String>,
38}
39
40#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
42pub struct MethodCallExpr {
43 pub receiver: Box<Expr>,
44 pub method: String,
45 pub args: Vec<Expr>,
46}
47
48#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
50pub struct BinaryOpExpr {
51 pub left: Box<Expr>,
52 pub op: BinaryOp,
53 pub right: Box<Expr>,
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
57pub enum BinaryOp {
58 Eq,
59 Ne,
60 Lt,
61 Le,
62 Gt,
63 Ge,
64 And,
65 Or,
66 Add,
67 Sub,
68 Mul,
69 Div,
70}
71
72#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
74pub struct UnaryOpExpr {
75 pub op: UnaryOp,
76 pub operand: Box<Expr>,
77}
78
79#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
80pub enum UnaryOp {
81 Not,
82 Neg,
83}
84
85#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
87pub struct ConditionalExpr {
88 pub condition: Box<Expr>,
89 pub then_branch: Box<Expr>,
90 pub else_branch: Box<Expr>,
91}
92
93#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
95pub enum LiteralExpr {
96 String(String),
97 Integer(i64),
98 Float(f64),
99 Bool(bool),
100}
101
102impl Expr {
107 pub fn uses_shared(&self) -> bool {
130 match self {
131 Expr::SharedFieldAccess(_) => true,
132 Expr::FieldAccess(_) => false,
133 Expr::Literal(_) => false,
134 Expr::MethodCall(m) => {
135 m.receiver.uses_shared() || m.args.iter().any(|a| a.uses_shared())
136 }
137 Expr::BinaryOp(b) => b.left.uses_shared() || b.right.uses_shared(),
138 Expr::UnaryOp(u) => u.operand.uses_shared(),
139 Expr::Conditional(c) => {
140 c.condition.uses_shared()
141 || c.then_branch.uses_shared()
142 || c.else_branch.uses_shared()
143 }
144 }
145 }
146
147 pub fn uses_model(&self) -> bool {
152 match self {
153 Expr::FieldAccess(_) => true,
154 Expr::SharedFieldAccess(_) => false,
155 Expr::Literal(_) => false,
156 Expr::MethodCall(m) => m.receiver.uses_model() || m.args.iter().any(|a| a.uses_model()),
157 Expr::BinaryOp(b) => b.left.uses_model() || b.right.uses_model(),
158 Expr::UnaryOp(u) => u.operand.uses_model(),
159 Expr::Conditional(c) => {
160 c.condition.uses_model() || c.then_branch.uses_model() || c.else_branch.uses_model()
161 }
162 }
163 }
164}
165
166impl BindingExpr {
167 pub fn uses_shared(&self) -> bool {
171 self.expr.uses_shared()
172 }
173
174 pub fn uses_model(&self) -> bool {
178 self.expr.uses_model()
179 }
180}