use std::sync::Arc;
use num_rational::Ratio;
use crate::diag::Span;
use crate::quantity::UnitExpr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct NodeId(pub u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BinaryOp {
Add,
Sub,
Mul,
Div,
Pow,
Cmp(CmpOp),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CmpOp {
Gte,
Lte,
Gt,
Lt,
EqEq,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum UnaryOp {
Neg,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Callee {
Ident(String),
Path(Vec<String>),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum CallArg {
Positional(NodeId),
Named {
name: String,
value: NodeId,
},
}
#[derive(Debug, Clone, PartialEq)]
pub enum ExprKind {
Number {
value: Ratio<i128>,
text: String,
},
Quantity {
magnitude: Ratio<i128>,
mag_text: String,
unit: UnitExpr,
},
Length {
inches: Ratio<i128>,
},
Ident {
name: String,
},
Unary {
op: UnaryOp,
operand: NodeId,
},
Binary {
op: BinaryOp,
left: NodeId,
right: NodeId,
},
Call {
callee: Callee,
args: Vec<CallArg>,
},
}
#[derive(Debug, Clone)]
pub struct Expr {
pub nodes: Vec<ExprNode>,
pub root: NodeId,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ExprNode {
pub id: NodeId,
pub span: Span,
pub kind: ExprKind,
}
impl Expr {
pub fn node(&self, id: NodeId) -> &ExprNode {
&self.nodes[id.0 as usize]
}
pub fn root_node(&self) -> &ExprNode {
self.node(self.root)
}
pub fn hole() -> Arc<Self> {
use num_traits::Zero;
Arc::new(Self {
nodes: vec![ExprNode {
id: NodeId(0),
span: Span::empty(0),
kind: ExprKind::Number {
value: Ratio::zero(),
text: "0".into(),
},
}],
root: NodeId(0),
})
}
}
impl ExprKind {
pub fn is_quantity_like(&self) -> bool {
matches!(self, Self::Quantity { .. } | Self::Length { .. })
}
}