use core::fmt;
pub use self::{
expr::{Expr, ExprType, SpannedExpr},
lvalue::{
Destructure, DestructureRest, Lvalue, LvalueLen, LvalueType, ObjectDestructure,
ObjectDestructureField, SpannedLvalue,
},
};
use crate::{
alloc::{vec, Box, Vec},
grammars::Grammar,
spans::Spanned,
};
mod expr;
mod lvalue;
#[derive(Debug)]
#[non_exhaustive]
pub struct ObjectExpr<'a, T: Grammar> {
pub fields: Vec<(Spanned<'a>, Option<SpannedExpr<'a, T>>)>,
}
impl<'a, T: Grammar> Clone for ObjectExpr<'a, T> {
fn clone(&self) -> Self {
Self {
fields: self.fields.clone(),
}
}
}
impl<'a, T: Grammar> PartialEq for ObjectExpr<'a, T> {
fn eq(&self, other: &Self) -> bool {
self.fields == other.fields
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum Statement<'a, T: Grammar> {
Expr(SpannedExpr<'a, T>),
Assignment {
lhs: SpannedLvalue<'a, T::Type<'a>>,
rhs: Box<SpannedExpr<'a, T>>,
},
}
impl<'a, T: Grammar> Statement<'a, T> {
pub fn ty(&self) -> StatementType {
match self {
Self::Expr(_) => StatementType::Expr,
Self::Assignment { .. } => StatementType::Assignment,
}
}
}
impl<'a, T: Grammar> Clone for Statement<'a, T> {
fn clone(&self) -> Self {
match self {
Self::Expr(expr) => Self::Expr(expr.clone()),
Self::Assignment { lhs, rhs } => Self::Assignment {
lhs: lhs.clone(),
rhs: rhs.clone(),
},
}
}
}
impl<'a, T> PartialEq for Statement<'a, T>
where
T: Grammar,
T::Lit: PartialEq,
T::Type<'a>: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Expr(this), Self::Expr(that)) => this == that,
(
Self::Assignment { lhs, rhs },
Self::Assignment {
lhs: that_lhs,
rhs: that_rhs,
},
) => lhs == that_lhs && rhs == that_rhs,
_ => false,
}
}
}
pub type SpannedStatement<'a, T> = Spanned<'a, Statement<'a, T>>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum StatementType {
Expr,
Assignment,
}
impl fmt::Display for StatementType {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(match self {
Self::Expr => "expression",
Self::Assignment => "variable assignment",
})
}
}
#[derive(Debug)]
#[non_exhaustive]
pub struct Block<'a, T: Grammar> {
pub statements: Vec<SpannedStatement<'a, T>>,
pub return_value: Option<Box<SpannedExpr<'a, T>>>,
}
impl<'a, T: Grammar> Clone for Block<'a, T> {
fn clone(&self) -> Self {
Self {
statements: self.statements.clone(),
return_value: self.return_value.clone(),
}
}
}
impl<'a, T> PartialEq for Block<'a, T>
where
T: Grammar,
T::Lit: PartialEq,
T::Type<'a>: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.return_value == other.return_value && self.statements == other.statements
}
}
impl<'a, T: Grammar> Block<'a, T> {
pub fn empty() -> Self {
Self {
statements: vec![],
return_value: None,
}
}
}
#[derive(Debug)]
#[non_exhaustive]
pub struct FnDefinition<'a, T: Grammar> {
pub args: Spanned<'a, Destructure<'a, T::Type<'a>>>,
pub body: Block<'a, T>,
}
impl<'a, T: Grammar> Clone for FnDefinition<'a, T> {
fn clone(&self) -> Self {
Self {
args: self.args.clone(),
body: self.body.clone(),
}
}
}
impl<'a, T> PartialEq for FnDefinition<'a, T>
where
T: Grammar,
T::Lit: PartialEq,
T::Type<'a>: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.args == other.args && self.body == other.body
}
}