forked from extern/nushell
Add unary not (#5111)
This commit is contained in:
parent
12d3e4e424
commit
591fb4bd36
@ -111,6 +111,7 @@ impl Command for Glob {
|
||||
}
|
||||
};
|
||||
|
||||
#[allow(clippy::needless_collect)]
|
||||
let glob_results: Vec<Value> = glob
|
||||
.walk(path, folder_depth)
|
||||
.flatten()
|
||||
|
@ -195,6 +195,12 @@ fn convert_to_value(
|
||||
"binary operators not supported in nuon".into(),
|
||||
expr.span,
|
||||
)),
|
||||
Expr::UnaryNot(..) => Err(ShellError::OutsideSpannedLabeledError(
|
||||
original_text.to_string(),
|
||||
"Error when loading".into(),
|
||||
"unary operators not supported in nuon".into(),
|
||||
expr.span,
|
||||
)),
|
||||
Expr::Block(..) => Err(ShellError::OutsideSpannedLabeledError(
|
||||
original_text.to_string(),
|
||||
"Error when loading".into(),
|
||||
|
@ -319,6 +319,16 @@ pub fn eval_expression(
|
||||
span: expr.span,
|
||||
}),
|
||||
Expr::Operator(_) => Ok(Value::Nothing { span: expr.span }),
|
||||
Expr::UnaryNot(expr) => {
|
||||
let lhs = eval_expression(engine_state, stack, expr)?;
|
||||
match lhs {
|
||||
Value::Bool { val, .. } => Ok(Value::Bool {
|
||||
val: !val,
|
||||
span: expr.span,
|
||||
}),
|
||||
_ => Err(ShellError::TypeMismatch("bool".to_string(), expr.span)),
|
||||
}
|
||||
}
|
||||
Expr::BinaryOp(lhs, op, rhs) => {
|
||||
let op_span = op.span;
|
||||
let lhs = eval_expression(engine_state, stack, lhs)?;
|
||||
|
@ -88,6 +88,17 @@ pub fn flatten_expression(
|
||||
output.extend(flatten_expression(working_set, rhs));
|
||||
output
|
||||
}
|
||||
Expr::UnaryNot(inner_expr) => {
|
||||
let mut output = vec![(
|
||||
Span {
|
||||
start: expr.span.start,
|
||||
end: expr.span.start + 3,
|
||||
},
|
||||
FlatShape::Operator,
|
||||
)];
|
||||
output.extend(flatten_expression(working_set, inner_expr));
|
||||
output
|
||||
}
|
||||
Expr::Block(block_id) | Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
|
||||
let outer_span = expr.span;
|
||||
|
||||
|
@ -49,7 +49,7 @@ pub fn is_math_expression_like(bytes: &[u8]) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
if bytes == b"true" || bytes == b"false" || bytes == b"null" {
|
||||
if bytes == b"true" || bytes == b"false" || bytes == b"null" || bytes == b"not" {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -872,6 +872,10 @@ pub fn parse_call(
|
||||
let bytes = working_set.get_span_contents(*word_span);
|
||||
|
||||
if is_math_expression_like(bytes)
|
||||
&& bytes != b"true"
|
||||
&& bytes != b"false"
|
||||
&& bytes != b"null"
|
||||
&& bytes != b"not"
|
||||
&& !working_set
|
||||
.permanent_state
|
||||
.external_exceptions
|
||||
@ -4005,6 +4009,40 @@ pub fn parse_math_expression(
|
||||
let mut last_prec = 1000000;
|
||||
|
||||
let mut error = None;
|
||||
|
||||
let first_span = working_set.get_span_contents(spans[0]);
|
||||
|
||||
if first_span == b"not" {
|
||||
if spans.len() > 1 {
|
||||
let (remainder, err) = parse_math_expression(
|
||||
working_set,
|
||||
&spans[1..],
|
||||
lhs_row_var_id,
|
||||
expand_aliases_denylist,
|
||||
);
|
||||
return (
|
||||
Expression {
|
||||
expr: Expr::UnaryNot(Box::new(remainder)),
|
||||
span: span(spans),
|
||||
ty: Type::Bool,
|
||||
custom_completion: None,
|
||||
},
|
||||
err,
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
garbage(spans[0]),
|
||||
Some(ParseError::Expected(
|
||||
"expression".into(),
|
||||
Span {
|
||||
start: spans[0].end,
|
||||
end: spans[0].end,
|
||||
},
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let (mut lhs, err) = parse_value(
|
||||
working_set,
|
||||
spans[0],
|
||||
@ -4716,6 +4754,10 @@ pub fn discover_captures_in_expr(
|
||||
output.extend(&lhs_result);
|
||||
output.extend(&rhs_result);
|
||||
}
|
||||
Expr::UnaryNot(expr) => {
|
||||
let result = discover_captures_in_expr(working_set, expr, seen, seen_blocks);
|
||||
output.extend(&result);
|
||||
}
|
||||
Expr::Block(block_id) => {
|
||||
let block = working_set.get_block(*block_id);
|
||||
let results = {
|
||||
|
@ -22,6 +22,7 @@ pub enum Expr {
|
||||
ExternalCall(Box<Expression>, Vec<Expression>),
|
||||
Operator(Operator),
|
||||
RowCondition(BlockId),
|
||||
UnaryNot(Box<Expression>),
|
||||
BinaryOp(Box<Expression>, Box<Expression>, Box<Expression>), //lhs, op, rhs
|
||||
Subexpression(BlockId),
|
||||
Block(BlockId),
|
||||
|
@ -113,6 +113,7 @@ impl Expression {
|
||||
Expr::BinaryOp(left, _, right) => {
|
||||
left.has_in_variable(working_set) || right.has_in_variable(working_set)
|
||||
}
|
||||
Expr::UnaryNot(expr) => expr.has_in_variable(working_set),
|
||||
Expr::Block(block_id) => {
|
||||
let block = working_set.get_block(*block_id);
|
||||
|
||||
@ -264,6 +265,9 @@ impl Expression {
|
||||
left.replace_in_variable(working_set, new_var_id);
|
||||
right.replace_in_variable(working_set, new_var_id);
|
||||
}
|
||||
Expr::UnaryNot(expr) => {
|
||||
expr.replace_in_variable(working_set, new_var_id);
|
||||
}
|
||||
Expr::Block(block_id) => {
|
||||
let block = working_set.get_block(*block_id);
|
||||
|
||||
@ -425,6 +429,9 @@ impl Expression {
|
||||
left.replace_span(working_set, replaced, new_span);
|
||||
right.replace_span(working_set, replaced, new_span);
|
||||
}
|
||||
Expr::UnaryNot(expr) => {
|
||||
expr.replace_span(working_set, replaced, new_span);
|
||||
}
|
||||
Expr::Block(block_id) => {
|
||||
let mut block = working_set.get_block(*block_id).clone();
|
||||
|
||||
|
@ -375,3 +375,39 @@ fn single_value_row_condition() -> TestResult {
|
||||
"2",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unary_not_1() -> TestResult {
|
||||
run_test(r#"not false"#, "true")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unary_not_2() -> TestResult {
|
||||
run_test(r#"not (false)"#, "true")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unary_not_3() -> TestResult {
|
||||
run_test(r#"(not false)"#, "true")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unary_not_4() -> TestResult {
|
||||
run_test(r#"if not false { "hello" } else { "world" }"#, "hello")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unary_not_5() -> TestResult {
|
||||
run_test(
|
||||
r#"if not not not not false { "hello" } else { "world" }"#,
|
||||
"world",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unary_not_6() -> TestResult {
|
||||
run_test(
|
||||
r#"[[name, present]; [abc, true], [def, false]] | where not present | get name.0"#,
|
||||
"def",
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user