forked from extern/nushell
Add band
and bor
operator for bit operations (#5936)
* Add `band` and `bor` Operator * Add tests
This commit is contained in:
parent
84caf8859f
commit
b82dccf0bd
@ -118,6 +118,8 @@ impl CustomValue for ExprDb {
|
|||||||
Operator::In
|
Operator::In
|
||||||
| Operator::NotIn
|
| Operator::NotIn
|
||||||
| Operator::Pow
|
| Operator::Pow
|
||||||
|
| Operator::BitOr
|
||||||
|
| Operator::BitAnd
|
||||||
| Operator::ShiftLeft
|
| Operator::ShiftLeft
|
||||||
| Operator::ShiftRight
|
| Operator::ShiftRight
|
||||||
| Operator::StartsWith
|
| Operator::StartsWith
|
||||||
|
@ -438,6 +438,14 @@ pub fn eval_expression(
|
|||||||
let rhs = eval_expression(engine_state, stack, rhs)?;
|
let rhs = eval_expression(engine_state, stack, rhs)?;
|
||||||
lhs.ends_with(op_span, &rhs, expr.span)
|
lhs.ends_with(op_span, &rhs, expr.span)
|
||||||
}
|
}
|
||||||
|
Operator::BitOr => {
|
||||||
|
let rhs = eval_expression(engine_state, stack, rhs)?;
|
||||||
|
lhs.bor(op_span, &rhs, expr.span)
|
||||||
|
}
|
||||||
|
Operator::BitAnd => {
|
||||||
|
let rhs = eval_expression(engine_state, stack, rhs)?;
|
||||||
|
lhs.band(op_span, &rhs, expr.span)
|
||||||
|
}
|
||||||
Operator::ShiftRight => {
|
Operator::ShiftRight => {
|
||||||
let rhs = eval_expression(engine_state, stack, rhs)?;
|
let rhs = eval_expression(engine_state, stack, rhs)?;
|
||||||
lhs.bshr(op_span, &rhs, expr.span)
|
lhs.bshr(op_span, &rhs, expr.span)
|
||||||
|
@ -4106,6 +4106,8 @@ pub fn parse_operator(
|
|||||||
b"in" => Operator::In,
|
b"in" => Operator::In,
|
||||||
b"not-in" => Operator::NotIn,
|
b"not-in" => Operator::NotIn,
|
||||||
b"mod" => Operator::Modulo,
|
b"mod" => Operator::Modulo,
|
||||||
|
b"bor" => Operator::BitOr,
|
||||||
|
b"band" => Operator::BitAnd,
|
||||||
b"bshl" => Operator::ShiftLeft,
|
b"bshl" => Operator::ShiftLeft,
|
||||||
b"bshr" => Operator::ShiftRight,
|
b"bshr" => Operator::ShiftRight,
|
||||||
b"starts-with" => Operator::StartsWith,
|
b"starts-with" => Operator::StartsWith,
|
||||||
|
@ -492,25 +492,27 @@ pub fn math_result_type(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Operator::ShiftLeft | Operator::ShiftRight => match (&lhs.ty, &rhs.ty) {
|
Operator::ShiftLeft | Operator::ShiftRight | Operator::BitAnd | Operator::BitOr => {
|
||||||
(Type::Int, Type::Int) => (Type::Int, None),
|
match (&lhs.ty, &rhs.ty) {
|
||||||
|
(Type::Int, Type::Int) => (Type::Int, None),
|
||||||
|
|
||||||
(Type::Any, _) => (Type::Any, None),
|
(Type::Any, _) => (Type::Any, None),
|
||||||
(_, Type::Any) => (Type::Any, None),
|
(_, Type::Any) => (Type::Any, None),
|
||||||
_ => {
|
_ => {
|
||||||
*op = Expression::garbage(op.span);
|
*op = Expression::garbage(op.span);
|
||||||
(
|
(
|
||||||
Type::Any,
|
Type::Any,
|
||||||
Some(ParseError::UnsupportedOperation(
|
Some(ParseError::UnsupportedOperation(
|
||||||
op.span,
|
op.span,
|
||||||
lhs.span,
|
lhs.span,
|
||||||
lhs.ty.clone(),
|
lhs.ty.clone(),
|
||||||
rhs.span,
|
rhs.span,
|
||||||
rhs.ty.clone(),
|
rhs.ty.clone(),
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
*op = Expression::garbage(op.span);
|
*op = Expression::garbage(op.span);
|
||||||
|
@ -48,6 +48,9 @@ impl Expression {
|
|||||||
| Operator::NotEqual
|
| Operator::NotEqual
|
||||||
| Operator::In
|
| Operator::In
|
||||||
| Operator::NotIn => 80,
|
| Operator::NotIn => 80,
|
||||||
|
Operator::BitAnd => 75,
|
||||||
|
// Operator::BitXor => 70,
|
||||||
|
Operator::BitOr => 60,
|
||||||
Operator::And => 50,
|
Operator::And => 50,
|
||||||
Operator::Or => 40,
|
Operator::Or => 40,
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,8 @@ pub enum Operator {
|
|||||||
Pow,
|
Pow,
|
||||||
StartsWith,
|
StartsWith,
|
||||||
EndsWith,
|
EndsWith,
|
||||||
|
BitOr,
|
||||||
|
BitAnd,
|
||||||
ShiftLeft,
|
ShiftLeft,
|
||||||
ShiftRight,
|
ShiftRight,
|
||||||
}
|
}
|
||||||
@ -50,6 +52,8 @@ impl Display for Operator {
|
|||||||
Operator::And => write!(f, "&&"),
|
Operator::And => write!(f, "&&"),
|
||||||
Operator::Or => write!(f, "||"),
|
Operator::Or => write!(f, "||"),
|
||||||
Operator::Pow => write!(f, "**"),
|
Operator::Pow => write!(f, "**"),
|
||||||
|
Operator::BitOr => write!(f, "bor"),
|
||||||
|
Operator::BitAnd => write!(f, "band"),
|
||||||
Operator::ShiftLeft => write!(f, "bshl"),
|
Operator::ShiftLeft => write!(f, "bshl"),
|
||||||
Operator::ShiftRight => write!(f, "bshr"),
|
Operator::ShiftRight => write!(f, "bshr"),
|
||||||
Operator::LessThanOrEqual => write!(f, "<="),
|
Operator::LessThanOrEqual => write!(f, "<="),
|
||||||
|
@ -2278,6 +2278,44 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bor(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
|
||||||
|
match (self, rhs) {
|
||||||
|
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
|
||||||
|
span,
|
||||||
|
val: *lhs | rhs,
|
||||||
|
}),
|
||||||
|
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||||
|
lhs.operation(*span, Operator::BitOr, op, rhs)
|
||||||
|
}
|
||||||
|
_ => Err(ShellError::OperatorMismatch {
|
||||||
|
op_span: op,
|
||||||
|
lhs_ty: self.get_type(),
|
||||||
|
lhs_span: self.span()?,
|
||||||
|
rhs_ty: rhs.get_type(),
|
||||||
|
rhs_span: rhs.span()?,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn band(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
|
||||||
|
match (self, rhs) {
|
||||||
|
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
|
||||||
|
span,
|
||||||
|
val: *lhs & rhs,
|
||||||
|
}),
|
||||||
|
(Value::CustomValue { val: lhs, span }, rhs) => {
|
||||||
|
lhs.operation(*span, Operator::BitAnd, op, rhs)
|
||||||
|
}
|
||||||
|
_ => Err(ShellError::OperatorMismatch {
|
||||||
|
op_span: op,
|
||||||
|
lhs_ty: self.get_type(),
|
||||||
|
lhs_span: self.span()?,
|
||||||
|
rhs_ty: rhs.get_type(),
|
||||||
|
rhs_span: rhs.span()?,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn modulo(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
|
pub fn modulo(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
|
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
|
||||||
|
@ -55,6 +55,21 @@ fn or() -> TestResult {
|
|||||||
run_test("true || false", "true")
|
run_test("true || false", "true")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn band() -> TestResult {
|
||||||
|
run_test("2 band 4", "0")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bor() -> TestResult {
|
||||||
|
run_test("2 bor 4", "6")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bit_and_or() -> TestResult {
|
||||||
|
run_test("2 bor 4 band 1 + 2", "2")
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pow() -> TestResult {
|
fn pow() -> TestResult {
|
||||||
run_test("3 ** 3", "27")
|
run_test("3 ** 3", "27")
|
||||||
|
Loading…
Reference in New Issue
Block a user