conlang: Split assignment into plain Assign and assign-with-Modify

This commit is contained in:
2024-05-19 14:31:30 -05:00
parent 8d8928b8a8
commit f330a7eaa5
8 changed files with 140 additions and 78 deletions

View File

@@ -346,8 +346,10 @@ pub enum ExprKind {
/// An empty expression: `(` `)`
#[default]
Empty,
/// An [Assign]ment expression: [`Expr`] ([`AssignKind`] [`Expr`])\+
/// An [Assign]ment expression: [`Expr`] (`=` [`Expr`])\+
Assign(Assign),
/// A [Modify]-assignment expression: [`Expr`] ([`ModifyKind`] [`Expr`])\+
Modify(Modify),
/// A [Binary] expression: [`Expr`] ([`BinaryKind`] [`Expr`])\+
Binary(Binary),
/// A [Unary] expression: [`UnaryKind`]\* [`Expr`]
@@ -394,14 +396,18 @@ pub enum ExprKind {
/// An [Assign]ment expression: [`Expr`] ([`AssignKind`] [`Expr`])\+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Assign {
pub kind: AssignKind,
pub parts: Box<(ExprKind, ExprKind)>,
}
/// A [Modify]-assignment expression: [`Expr`] ([`ModifyKind`] [`Expr`])\+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Modify {
pub kind: ModifyKind,
pub parts: Box<(ExprKind, ExprKind)>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum AssignKind {
/// Standard Assignment with no read-back
Plain,
pub enum ModifyKind {
And,
Or,
Xor,

View File

@@ -420,6 +420,7 @@ mod display {
match self {
ExprKind::Empty => "()".fmt(f),
ExprKind::Assign(v) => v.fmt(f),
ExprKind::Modify(v) => v.fmt(f),
ExprKind::Binary(v) => v.fmt(f),
ExprKind::Unary(v) => v.fmt(f),
ExprKind::Member(v) => v.fmt(f),
@@ -445,26 +446,32 @@ mod display {
}
impl Display for Assign {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { parts } = self;
write!(f, "{} = {}", parts.0, parts.1)
}
}
impl Display for Modify {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { kind, parts } = self;
write!(f, "{} {kind} {}", parts.0, parts.1)
}
}
impl Display for AssignKind {
impl Display for ModifyKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AssignKind::Plain => "=",
AssignKind::Mul => "*=",
AssignKind::Div => "/=",
AssignKind::Rem => "%=",
AssignKind::Add => "+=",
AssignKind::Sub => "-=",
AssignKind::And => "&=",
AssignKind::Or => "|=",
AssignKind::Xor => "^=",
AssignKind::Shl => "<<=",
AssignKind::Shr => ">>=",
ModifyKind::Mul => "*=",
ModifyKind::Div => "/=",
ModifyKind::Rem => "%=",
ModifyKind::Add => "+=",
ModifyKind::Sub => "-=",
ModifyKind::And => "&=",
ModifyKind::Or => "|=",
ModifyKind::Xor => "^=",
ModifyKind::Shl => "<<=",
ModifyKind::Shr => ">>=",
}
.fmt(f)
}
@@ -749,6 +756,7 @@ mod convert {
}
impl From for ExprKind {
Assign => ExprKind::Assign,
Modify => ExprKind::Modify,
Binary => ExprKind::Binary,
Unary => ExprKind::Unary,
Member => ExprKind::Member,

View File

@@ -234,14 +234,19 @@ pub trait Fold {
or_fold_expr_kind(self, kind)
}
fn fold_assign(&mut self, a: Assign) -> Assign {
let Assign { kind, parts } = a;
let Assign { parts } = a;
let (head, tail) = *parts;
Assign {
kind: self.fold_assign_kind(kind),
Assign { parts: Box::new((self.fold_expr_kind(head), self.fold_expr_kind(tail))) }
}
fn fold_modify(&mut self, m: Modify) -> Modify {
let Modify { kind, parts } = m;
let (head, tail) = *parts;
Modify {
kind: self.fold_modify_kind(kind),
parts: Box::new((self.fold_expr_kind(head), self.fold_expr_kind(tail))),
}
}
fn fold_assign_kind(&mut self, kind: AssignKind) -> AssignKind {
fn fold_modify_kind(&mut self, kind: ModifyKind) -> ModifyKind {
kind
}
fn fold_binary(&mut self, b: Binary) -> Binary {
@@ -522,6 +527,7 @@ pub fn or_fold_expr_kind<F: Fold + ?Sized>(folder: &mut F, kind: ExprKind) -> Ex
match kind {
ExprKind::Empty => ExprKind::Empty,
ExprKind::Assign(a) => ExprKind::Assign(folder.fold_assign(a)),
ExprKind::Modify(m) => ExprKind::Modify(folder.fold_modify(m)),
ExprKind::Binary(b) => ExprKind::Binary(folder.fold_binary(b)),
ExprKind::Unary(u) => ExprKind::Unary(folder.fold_unary(u)),
ExprKind::Member(m) => ExprKind::Member(folder.fold_member(m)),

View File

@@ -202,13 +202,19 @@ pub trait Visit<'a>: Sized {
or_visit_expr_kind(self, e)
}
fn visit_assign(&mut self, a: &'a Assign) {
let Assign { kind, parts } = a;
let Assign { parts } = a;
let (head, tail) = parts.as_ref();
self.visit_assign_kind(kind);
self.visit_expr_kind(head);
self.visit_expr_kind(tail);
}
fn visit_assign_kind(&mut self, _kind: &'a AssignKind) {}
fn visit_modify(&mut self, m: &'a Modify) {
let Modify { kind, parts } = m;
let (head, tail) = parts.as_ref();
self.visit_modify_kind(kind);
self.visit_expr_kind(head);
self.visit_expr_kind(tail);
}
fn visit_modify_kind(&mut self, _kind: &'a ModifyKind) {}
fn visit_binary(&mut self, b: &'a Binary) {
let Binary { kind, parts } = b;
let (head, tail) = parts.as_ref();
@@ -437,6 +443,7 @@ pub fn or_visit_expr_kind<'a, V: Visit<'a>>(visitor: &mut V, e: &'a ExprKind) {
match e {
ExprKind::Empty => {}
ExprKind::Assign(a) => visitor.visit_assign(a),
ExprKind::Modify(m) => visitor.visit_modify(m),
ExprKind::Binary(b) => visitor.visit_binary(b),
ExprKind::Unary(u) => visitor.visit_unary(u),
ExprKind::Member(m) => visitor.visit_member(m),