use crate::expr::Expression;
use crate::{Decor, Spanned};
use std::ops::Range;
#[doc(inline)]
pub use hcl_primitives::expr::{BinaryOperator, UnaryOperator};
#[derive(Debug, Clone, Eq)]
pub struct UnaryOp {
    pub operator: Spanned<UnaryOperator>,
    pub expr: Expression,
    decor: Decor,
    span: Option<Range<usize>>,
}
impl UnaryOp {
    pub fn new(
        operator: impl Into<Spanned<UnaryOperator>>,
        expr: impl Into<Expression>,
    ) -> UnaryOp {
        UnaryOp {
            operator: operator.into(),
            expr: expr.into(),
            decor: Decor::default(),
            span: None,
        }
    }
    pub(crate) fn despan(&mut self, input: &str) {
        self.decor.despan(input);
        self.expr.despan(input);
    }
}
impl PartialEq for UnaryOp {
    fn eq(&self, other: &Self) -> bool {
        self.operator == other.operator && self.expr == other.expr
    }
}
#[derive(Debug, Clone, Eq)]
pub struct BinaryOp {
    pub lhs_expr: Expression,
    pub operator: Spanned<BinaryOperator>,
    pub rhs_expr: Expression,
    decor: Decor,
    span: Option<Range<usize>>,
}
impl BinaryOp {
    pub fn new(
        lhs_expr: impl Into<Expression>,
        operator: impl Into<Spanned<BinaryOperator>>,
        rhs_expr: impl Into<Expression>,
    ) -> BinaryOp {
        BinaryOp {
            lhs_expr: lhs_expr.into(),
            operator: operator.into(),
            rhs_expr: rhs_expr.into(),
            decor: Decor::default(),
            span: None,
        }
    }
    pub(crate) fn despan(&mut self, input: &str) {
        self.decor.despan(input);
        self.lhs_expr.despan(input);
        self.rhs_expr.despan(input);
    }
}
impl PartialEq for BinaryOp {
    fn eq(&self, other: &Self) -> bool {
        self.lhs_expr == other.lhs_expr
            && self.operator == other.operator
            && self.rhs_expr == other.rhs_expr
    }
}
decorate_impl!(UnaryOp, BinaryOp);
span_impl!(UnaryOp, BinaryOp);