use crate::ir::span::Span;
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct BindingExpr {
pub expr: Expr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum Expr {
FieldAccess(FieldAccessExpr),
SharedFieldAccess(SharedFieldAccessExpr),
MethodCall(MethodCallExpr),
BinaryOp(BinaryOpExpr),
UnaryOp(UnaryOpExpr),
Conditional(ConditionalExpr),
Literal(LiteralExpr),
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct FieldAccessExpr {
pub path: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct SharedFieldAccessExpr {
pub path: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct MethodCallExpr {
pub receiver: Box<Expr>,
pub method: String,
pub args: Vec<Expr>,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct BinaryOpExpr {
pub left: Box<Expr>,
pub op: BinaryOp,
pub right: Box<Expr>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum BinaryOp {
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
And,
Or,
Add,
Sub,
Mul,
Div,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct UnaryOpExpr {
pub op: UnaryOp,
pub operand: Box<Expr>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum UnaryOp {
Not,
Neg,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct ConditionalExpr {
pub condition: Box<Expr>,
pub then_branch: Box<Expr>,
pub else_branch: Box<Expr>,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum LiteralExpr {
String(String),
Integer(i64),
Float(f64),
Bool(bool),
}
impl Expr {
pub fn uses_shared(&self) -> bool {
match self {
Expr::SharedFieldAccess(_) => true,
Expr::FieldAccess(_) => false,
Expr::Literal(_) => false,
Expr::MethodCall(m) => {
m.receiver.uses_shared() || m.args.iter().any(|a| a.uses_shared())
}
Expr::BinaryOp(b) => b.left.uses_shared() || b.right.uses_shared(),
Expr::UnaryOp(u) => u.operand.uses_shared(),
Expr::Conditional(c) => {
c.condition.uses_shared()
|| c.then_branch.uses_shared()
|| c.else_branch.uses_shared()
}
}
}
pub fn uses_model(&self) -> bool {
match self {
Expr::FieldAccess(_) => true,
Expr::SharedFieldAccess(_) => false,
Expr::Literal(_) => false,
Expr::MethodCall(m) => m.receiver.uses_model() || m.args.iter().any(|a| a.uses_model()),
Expr::BinaryOp(b) => b.left.uses_model() || b.right.uses_model(),
Expr::UnaryOp(u) => u.operand.uses_model(),
Expr::Conditional(c) => {
c.condition.uses_model() || c.then_branch.uses_model() || c.else_branch.uses_model()
}
}
}
}
impl BindingExpr {
pub fn uses_shared(&self) -> bool {
self.expr.uses_shared()
}
pub fn uses_model(&self) -> bool {
self.expr.uses_model()
}
}