Streamline op-assignments.

This commit is contained in:
Stephen Chung
2022-04-18 23:12:47 +08:00
parent 3f74e5e674
commit 60a933862e
7 changed files with 116 additions and 96 deletions

View File

@@ -17,6 +17,8 @@ use std::{
/// _(internals)_ An op-assignment operator.
/// Exported under the `internals` feature only.
///
/// This type may hold a straight assignment (i.e. not an op-assignment).
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct OpAssignment<'a> {
/// Hash of the op-assignment call.
@@ -27,9 +29,29 @@ pub struct OpAssignment<'a> {
pub op_assign: &'a str,
/// Underlying operator.
pub op: &'a str,
/// [Position] of the op-assignment operator.
pub pos: Position,
}
impl OpAssignment<'_> {
/// Create a new [`OpAssignment`] that is only a straight assignment.
#[must_use]
#[inline(always)]
pub const fn new_assignment(pos: Position) -> Self {
Self {
hash_op_assign: 0,
hash_op: 0,
op_assign: "=",
op: "=",
pos,
}
}
/// Is this an op-assignment?
#[must_use]
#[inline(always)]
pub const fn is_op_assignment(&self) -> bool {
self.hash_op_assign != 0 || self.hash_op != 0
}
/// Create a new [`OpAssignment`].
///
/// # Panics
@@ -37,8 +59,8 @@ impl OpAssignment<'_> {
/// Panics if the name is not an op-assignment operator.
#[must_use]
#[inline(always)]
pub fn new(name: &str) -> Self {
Self::new_from_token(Token::lookup_from_syntax(name).expect("operator"))
pub fn new_op_assignment(name: &str, pos: Position) -> Self {
Self::new_op_assignment_from_token(Token::lookup_from_syntax(name).expect("operator"), pos)
}
/// Create a new [`OpAssignment`] from a [`Token`].
///
@@ -46,7 +68,7 @@ impl OpAssignment<'_> {
///
/// Panics if the token is not an op-assignment operator.
#[must_use]
pub fn new_from_token(op: Token) -> Self {
pub fn new_op_assignment_from_token(op: Token, pos: Position) -> Self {
let op_raw = op
.get_base_op_from_assignment()
.expect("op-assignment operator")
@@ -56,6 +78,7 @@ impl OpAssignment<'_> {
hash_op: calc_fn_hash(op_raw, 2),
op_assign: op.literal_syntax(),
op: op_raw,
pos,
}
}
/// Create a new [`OpAssignment`] from a base operator.
@@ -65,8 +88,11 @@ impl OpAssignment<'_> {
/// Panics if the name is not an operator that can be converted into an op-operator.
#[must_use]
#[inline(always)]
pub fn new_from_base(name: &str) -> Self {
Self::new_from_base_token(Token::lookup_from_syntax(name).expect("operator"))
pub fn new_op_assignment_from_base(name: &str, pos: Position) -> Self {
Self::new_op_assignment_from_base_token(
Token::lookup_from_syntax(name).expect("operator"),
pos,
)
}
/// Convert a [`Token`] into a new [`OpAssignment`].
///
@@ -75,8 +101,8 @@ impl OpAssignment<'_> {
/// Panics if the token is cannot be converted into an op-assignment operator.
#[inline(always)]
#[must_use]
pub fn new_from_base_token(op: Token) -> Self {
Self::new_from_token(op.convert_to_op_assignment().expect("operator"))
pub fn new_op_assignment_from_base_token(op: Token, pos: Position) -> Self {
Self::new_op_assignment_from_token(op.convert_to_op_assignment().expect("operator"), pos)
}
}
@@ -375,7 +401,7 @@ pub enum Stmt {
/// * [`CONSTANT`][ASTFlags::CONSTANT] = `const`
Var(Box<(Ident, Expr, Option<NonZeroUsize>)>, ASTFlags, Position),
/// expr op`=` expr
Assignment(Box<(Option<OpAssignment<'static>>, BinaryExpr)>, Position),
Assignment(Box<(OpAssignment<'static>, BinaryExpr)>),
/// func `(` expr `,` ... `)`
///
/// Note - this is a duplicate of [`Expr::FnCall`] to cover the very common pattern of a single
@@ -464,7 +490,6 @@ impl Stmt {
match self {
Self::Noop(pos)
| Self::BreakLoop(.., pos)
| Self::Assignment(.., pos)
| Self::FnCall(.., pos)
| Self::If(.., pos)
| Self::Switch(.., pos)
@@ -475,6 +500,8 @@ impl Stmt {
| Self::Var(.., pos)
| Self::TryCatch(.., pos) => *pos,
Self::Assignment(x) => x.0.pos,
Self::Block(x) => x.position(),
Self::Expr(x) => x.start_position(),
@@ -493,7 +520,6 @@ impl Stmt {
match self {
Self::Noop(pos)
| Self::BreakLoop(.., pos)
| Self::Assignment(.., pos)
| Self::FnCall(.., pos)
| Self::If(.., pos)
| Self::Switch(.., pos)
@@ -504,6 +530,8 @@ impl Stmt {
| Self::Var(.., pos)
| Self::TryCatch(.., pos) => *pos = new_pos,
Self::Assignment(x) => x.0.pos = new_pos,
Self::Block(x) => x.set_position(new_pos, x.end_position()),
Self::Expr(x) => {