use super::*;
use crate::Span;
#[derive(Clone, Debug)]
pub struct StmtList {
list: Vec<Stmt>,
}
impl Grammar for StmtList {}
impl StmtList {
pub(crate) fn new(list: Vec<Stmt>) -> Self {
Self { list }
}
pub(crate) fn iter(&self) -> std::slice::Iter<'_, Stmt> {
self.list.iter()
}
}
pub struct StmtListIterator {
stmts: <Vec<Stmt> as IntoIterator>::IntoIter,
}
impl Iterator for StmtListIterator {
type Item = Stmt;
fn next(&mut self) -> Option<Self::Item> {
self.stmts.next()
}
}
impl IntoIterator for StmtList {
type Item = Stmt;
type IntoIter = StmtListIterator;
fn into_iter(self) -> Self::IntoIter {
Self::IntoIter {
stmts: self.list.into_iter(),
}
}
}
#[derive(Clone, Debug)]
pub enum StmtKind {
Expr(RcExpr),
Assignment(Assignment),
}
impl From<RcExpr> for StmtKind {
fn from(expr: RcExpr) -> Self {
StmtKind::Expr(expr)
}
}
impl From<Assignment> for StmtKind {
fn from(asgn: Assignment) -> Self {
StmtKind::Assignment(asgn)
}
}
#[derive(Clone, Debug)]
pub struct Stmt {
pub kind: StmtKind,
vw: usize,
}
impl Grammar for Stmt {}
impl Stmt {
pub fn new(kind: StmtKind, vw: usize) -> Self {
Self { kind, vw }
}
pub fn update_with(
self,
expr_update: impl FnOnce(RcExpr) -> RcExpr,
asgn_update: impl FnOnce(Assignment) -> Assignment,
) -> Self {
let kind = match self.kind {
StmtKind::Expr(expr) => expr_update(expr).into(),
StmtKind::Assignment(asgn) => asgn_update(asgn).into(),
};
Self { kind, ..self }
}
pub fn vw(&self) -> usize {
self.vw
}
pub fn span(&self) -> &Span {
match &self.kind {
StmtKind::Expr(e) => &e.span,
StmtKind::Assignment(a) => &a.span,
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum AssignmentOp {
Equal(Span),
AssignDefine(Span),
}
impl AssignmentOp {
pub fn span(&self) -> &Span {
match self {
AssignmentOp::Equal(span) => span,
AssignmentOp::AssignDefine(span) => span,
}
}
}
#[derive(Clone, Debug)]
pub struct Assignment {
pub lhs: RcExpr,
pub asgn_op: AssignmentOp,
pub rhs: RcExpr,
pub span: Span,
}
impl Assignment {
pub fn redefine_with(mut self, eval: impl FnOnce(RcExpr) -> RcExpr) -> Self {
self.rhs = eval(self.rhs);
self
}
}
#[derive(Clone, PartialEq, Debug)]
pub enum Expr {
Const(f64),
Var(InternedStr),
BinaryExpr(BinaryExpr<RcExpr>),
UnaryExpr(UnaryExpr<RcExpr>),
Parend(RcExpr),
Bracketed(RcExpr),
}
impl Grammar for Expr {}
impl Expr {
pub(crate) fn complexity(&self) -> u8 {
1 + match self {
Self::Const(_) => 0,
Self::Var(_) => 0,
Self::BinaryExpr(BinaryExpr { lhs, rhs, .. }) => lhs.complexity() + rhs.complexity(),
Self::UnaryExpr(UnaryExpr { rhs, .. }) => rhs.complexity(),
Self::Parend(expr) | Self::Bracketed(expr) => expr.complexity(),
}
}
pub fn get_const(&self) -> Option<f64> {
match self {
Self::Const(c) => Some(*c),
_ => None,
}
}
pub fn get_var(&self) -> Option<InternedStr> {
match self {
Self::Var(v) => Some(*v),
_ => None,
}
}
}
impl Eq for Expr {}
impl PartialOrd for Expr {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Expr {
fn cmp(&self, other: &Self) -> Ordering {
match (self, other) {
(Self::Var(a), Self::Var(b)) => a.get().cmp(&b.get()),
(Self::Const(a), Self::Const(b)) => a.partial_cmp(b).unwrap(),
(Self::UnaryExpr(a), Self::UnaryExpr(b)) => a.cmp(b),
(Self::BinaryExpr(a), Self::BinaryExpr(b)) => a.cmp(b),
(Self::Parend(a), Self::Parend(b)) => a.cmp(b),
(Self::Bracketed(a), Self::Bracketed(b)) => a.cmp(b),
(Self::Const(_), Self::Var(_))
| (Self::UnaryExpr(_), Self::Const(_))
| (Self::UnaryExpr(_), Self::Var(_))
| (Self::BinaryExpr(_), Self::UnaryExpr(_))
| (Self::BinaryExpr(_), Self::Const(_))
| (Self::BinaryExpr(_), Self::Var(_))
| (Self::Parend(_), Self::BinaryExpr(_))
| (Self::Parend(_), Self::UnaryExpr(_))
| (Self::Parend(_), Self::Const(_))
| (Self::Parend(_), Self::Var(_))
| (Self::Bracketed(_), Self::Parend(_))
| (Self::Bracketed(_), Self::BinaryExpr(_))
| (Self::Bracketed(_), Self::UnaryExpr(_))
| (Self::Bracketed(_), Self::Const(_))
| (Self::Bracketed(_), Self::Var(_)) => Ordering::Greater,
(Self::Var(_), _)
| (Self::Const(_), _)
| (Self::UnaryExpr(_), _)
| (Self::BinaryExpr(_), _)
| (Self::Parend(_), _) => Ordering::Less,
}
}
}
#[allow(clippy::derive_hash_xor_eq)]
impl core::hash::Hash for Expr {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
use Expr::*;
match self {
Const(f) => state.write(f.to_string().as_bytes()),
Var(v) => v.hash(state),
BinaryExpr(e) => e.hash(state),
UnaryExpr(e) => e.hash(state),
e @ Parend(_) => e.to_string().hash(state),
e @ Bracketed(_) => e.to_string().hash(state),
}
}
}
impl From<f64> for Expr {
fn from(f: f64) -> Self {
Self::Const(f)
}
}