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
|
let glob_results: Vec<Value> = glob
|
||||||
.walk(path, folder_depth)
|
.walk(path, folder_depth)
|
||||||
.flatten()
|
.flatten()
|
||||||
|
@ -195,6 +195,12 @@ fn convert_to_value(
|
|||||||
"binary operators not supported in nuon".into(),
|
"binary operators not supported in nuon".into(),
|
||||||
expr.span,
|
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(
|
Expr::Block(..) => Err(ShellError::OutsideSpannedLabeledError(
|
||||||
original_text.to_string(),
|
original_text.to_string(),
|
||||||
"Error when loading".into(),
|
"Error when loading".into(),
|
||||||
|
@ -319,6 +319,16 @@ pub fn eval_expression(
|
|||||||
span: expr.span,
|
span: expr.span,
|
||||||
}),
|
}),
|
||||||
Expr::Operator(_) => Ok(Value::Nothing { 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) => {
|
Expr::BinaryOp(lhs, op, rhs) => {
|
||||||
let op_span = op.span;
|
let op_span = op.span;
|
||||||
let lhs = eval_expression(engine_state, stack, lhs)?;
|
let lhs = eval_expression(engine_state, stack, lhs)?;
|
||||||
|
@ -88,6 +88,17 @@ pub fn flatten_expression(
|
|||||||
output.extend(flatten_expression(working_set, rhs));
|
output.extend(flatten_expression(working_set, rhs));
|
||||||
output
|
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) => {
|
Expr::Block(block_id) | Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
|
||||||
let outer_span = expr.span;
|
let outer_span = expr.span;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ pub fn is_math_expression_like(bytes: &[u8]) -> bool {
|
|||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -872,6 +872,10 @@ pub fn parse_call(
|
|||||||
let bytes = working_set.get_span_contents(*word_span);
|
let bytes = working_set.get_span_contents(*word_span);
|
||||||
|
|
||||||
if is_math_expression_like(bytes)
|
if is_math_expression_like(bytes)
|
||||||
|
&& bytes != b"true"
|
||||||
|
&& bytes != b"false"
|
||||||
|
&& bytes != b"null"
|
||||||
|
&& bytes != b"not"
|
||||||
&& !working_set
|
&& !working_set
|
||||||
.permanent_state
|
.permanent_state
|
||||||
.external_exceptions
|
.external_exceptions
|
||||||
@ -4005,6 +4009,40 @@ pub fn parse_math_expression(
|
|||||||
let mut last_prec = 1000000;
|
let mut last_prec = 1000000;
|
||||||
|
|
||||||
let mut error = None;
|
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(
|
let (mut lhs, err) = parse_value(
|
||||||
working_set,
|
working_set,
|
||||||
spans[0],
|
spans[0],
|
||||||
@ -4716,6 +4754,10 @@ pub fn discover_captures_in_expr(
|
|||||||
output.extend(&lhs_result);
|
output.extend(&lhs_result);
|
||||||
output.extend(&rhs_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) => {
|
Expr::Block(block_id) => {
|
||||||
let block = working_set.get_block(*block_id);
|
let block = working_set.get_block(*block_id);
|
||||||
let results = {
|
let results = {
|
||||||
|
@ -22,6 +22,7 @@ pub enum Expr {
|
|||||||
ExternalCall(Box<Expression>, Vec<Expression>),
|
ExternalCall(Box<Expression>, Vec<Expression>),
|
||||||
Operator(Operator),
|
Operator(Operator),
|
||||||
RowCondition(BlockId),
|
RowCondition(BlockId),
|
||||||
|
UnaryNot(Box<Expression>),
|
||||||
BinaryOp(Box<Expression>, Box<Expression>, Box<Expression>), //lhs, op, rhs
|
BinaryOp(Box<Expression>, Box<Expression>, Box<Expression>), //lhs, op, rhs
|
||||||
Subexpression(BlockId),
|
Subexpression(BlockId),
|
||||||
Block(BlockId),
|
Block(BlockId),
|
||||||
|
@ -113,6 +113,7 @@ impl Expression {
|
|||||||
Expr::BinaryOp(left, _, right) => {
|
Expr::BinaryOp(left, _, right) => {
|
||||||
left.has_in_variable(working_set) || right.has_in_variable(working_set)
|
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) => {
|
Expr::Block(block_id) => {
|
||||||
let block = working_set.get_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);
|
left.replace_in_variable(working_set, new_var_id);
|
||||||
right.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) => {
|
Expr::Block(block_id) => {
|
||||||
let block = working_set.get_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);
|
left.replace_span(working_set, replaced, new_span);
|
||||||
right.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) => {
|
Expr::Block(block_id) => {
|
||||||
let mut block = working_set.get_block(*block_id).clone();
|
let mut block = working_set.get_block(*block_id).clone();
|
||||||
|
|
||||||
|
@ -375,3 +375,39 @@ fn single_value_row_condition() -> TestResult {
|
|||||||
"2",
|
"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