Add additional assignment operators (#7102)

This commit is contained in:
JT 2022-11-12 07:50:43 +13:00 committed by GitHub
parent 69b089845c
commit c1105e945e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 84 additions and 4 deletions

View File

@ -47,3 +47,51 @@ fn mut_a_field() {
assert_eq!(actual.out, "456"); assert_eq!(actual.out, "456");
} }
#[test]
fn mut_add_assign() {
let actual = nu!(
cwd: ".", pipeline(
r#"
mut y = 3; $y += 2; $y
"#
));
assert_eq!(actual.out, "5");
}
#[test]
fn mut_minus_assign() {
let actual = nu!(
cwd: ".", pipeline(
r#"
mut y = 3; $y -= 2; $y
"#
));
assert_eq!(actual.out, "1");
}
#[test]
fn mut_multiply_assign() {
let actual = nu!(
cwd: ".", pipeline(
r#"
mut y = 3; $y *= 2; $y
"#
));
assert_eq!(actual.out, "6");
}
#[test]
fn mut_divide_assign() {
let actual = nu!(
cwd: ".", pipeline(
r#"
mut y = 8; $y /= 2; $y
"#
));
assert_eq!(actual.out, "4");
}

View File

@ -434,9 +434,29 @@ pub fn eval_expression(
Bits::ShiftRight => lhs.bit_shr(op_span, &rhs, expr.span), Bits::ShiftRight => lhs.bit_shr(op_span, &rhs, expr.span),
} }
} }
Operator::Assignment(Assignment::Assign) => { Operator::Assignment(assignment) => {
let rhs = eval_expression(engine_state, stack, rhs)?; let rhs = eval_expression(engine_state, stack, rhs)?;
let rhs = match assignment {
Assignment::Assign => rhs,
Assignment::PlusAssign => {
let lhs = eval_expression(engine_state, stack, lhs)?;
lhs.add(op_span, &rhs, op_span)?
}
Assignment::MinusAssign => {
let lhs = eval_expression(engine_state, stack, lhs)?;
lhs.sub(op_span, &rhs, op_span)?
}
Assignment::MultiplyAssign => {
let lhs = eval_expression(engine_state, stack, lhs)?;
lhs.mul(op_span, &rhs, op_span)?
}
Assignment::DivideAssign => {
let lhs = eval_expression(engine_state, stack, lhs)?;
lhs.div(op_span, &rhs, op_span)?
}
};
match &lhs.expr { match &lhs.expr {
Expr::Var(var_id) | Expr::VarDecl(var_id) => { Expr::Var(var_id) | Expr::VarDecl(var_id) => {
let var_info = engine_state.get_var(*var_id); let var_info = engine_state.get_var(*var_id);

View File

@ -4420,6 +4420,10 @@ pub fn parse_operator(
let operator = match contents { let operator = match contents {
b"=" => Operator::Assignment(Assignment::Assign), b"=" => Operator::Assignment(Assignment::Assign),
b"+=" => Operator::Assignment(Assignment::PlusAssign),
b"-=" => Operator::Assignment(Assignment::MinusAssign),
b"*=" => Operator::Assignment(Assignment::MultiplyAssign),
b"/=" => Operator::Assignment(Assignment::DivideAssign),
b"==" => Operator::Comparison(Comparison::Equal), b"==" => Operator::Comparison(Comparison::Equal),
b"!=" => Operator::Comparison(Comparison::NotEqual), b"!=" => Operator::Comparison(Comparison::NotEqual),
b"<" => Operator::Comparison(Comparison::LessThan), b"<" => Operator::Comparison(Comparison::LessThan),

View File

@ -1,6 +1,6 @@
use crate::ParseError; use crate::ParseError;
use nu_protocol::{ use nu_protocol::{
ast::{Assignment, Bits, Boolean, Comparison, Expr, Expression, Math, Operator}, ast::{Bits, Boolean, Comparison, Expr, Expression, Math, Operator},
engine::StateWorkingSet, engine::StateWorkingSet,
Type, Type,
}; };
@ -555,7 +555,7 @@ pub fn math_result_type(
) )
} }
}, },
Operator::Assignment(Assignment::Assign) => match (&lhs.ty, &rhs.ty) { Operator::Assignment(_) => match (&lhs.ty, &rhs.ty) {
(x, y) if x == y => (Type::Nothing, None), (x, y) if x == y => (Type::Nothing, None),
(Type::Any, _) => (Type::Nothing, None), (Type::Any, _) => (Type::Nothing, None),
(_, Type::Any) => (Type::Nothing, None), (_, Type::Any) => (Type::Nothing, None),

View File

@ -55,7 +55,7 @@ impl Expression {
Operator::Bits(Bits::BitOr) => 60, Operator::Bits(Bits::BitOr) => 60,
Operator::Boolean(Boolean::And) => 50, Operator::Boolean(Boolean::And) => 50,
Operator::Boolean(Boolean::Or) => 40, Operator::Boolean(Boolean::Or) => 40,
Operator::Assignment(Assignment::Assign) => 10, Operator::Assignment(_) => 10,
} }
} }
_ => 0, _ => 0,

View File

@ -49,6 +49,10 @@ pub enum Bits {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Assignment { pub enum Assignment {
Assign, Assign,
PlusAssign,
MinusAssign,
MultiplyAssign,
DivideAssign,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
@ -64,6 +68,10 @@ impl Display for Operator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Operator::Assignment(Assignment::Assign) => write!(f, "="), Operator::Assignment(Assignment::Assign) => write!(f, "="),
Operator::Assignment(Assignment::PlusAssign) => write!(f, "+="),
Operator::Assignment(Assignment::MinusAssign) => write!(f, "-="),
Operator::Assignment(Assignment::MultiplyAssign) => write!(f, "*="),
Operator::Assignment(Assignment::DivideAssign) => write!(f, "/="),
Operator::Comparison(Comparison::Equal) => write!(f, "=="), Operator::Comparison(Comparison::Equal) => write!(f, "=="),
Operator::Comparison(Comparison::NotEqual) => write!(f, "!="), Operator::Comparison(Comparison::NotEqual) => write!(f, "!="),
Operator::Comparison(Comparison::LessThan) => write!(f, "<"), Operator::Comparison(Comparison::LessThan) => write!(f, "<"),