mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-01 05:27:45 +00:00
Merge pull request #5365 from Luv-Ray/fix-expr
`expr`: short-circuit evaluation for `|`
This commit is contained in:
commit
94f5fa9487
2 changed files with 34 additions and 2 deletions
|
@ -52,7 +52,7 @@ impl AstNode {
|
|||
operands,
|
||||
} => {
|
||||
println!(
|
||||
"Node( {} ) at #{} (evaluate -> {:?})",
|
||||
"Node( {} ) at #{} ( evaluate -> {:?} )",
|
||||
op_type,
|
||||
token_idx,
|
||||
self.evaluate()
|
||||
|
@ -155,8 +155,25 @@ impl AstNode {
|
|||
}
|
||||
}
|
||||
pub fn operand_values(&self) -> Result<Vec<String>, String> {
|
||||
if let Self::Node { operands, .. } = self {
|
||||
if let Self::Node {
|
||||
operands, op_type, ..
|
||||
} = self
|
||||
{
|
||||
let mut out = Vec::with_capacity(operands.len());
|
||||
let mut operands = operands.iter();
|
||||
// check the first value before `|`, stop evaluate and return directly if it is true.
|
||||
// push dummy to pass the check of `len() == 2`
|
||||
if op_type == "|" {
|
||||
if let Some(value) = operands.next() {
|
||||
let value = value.evaluate()?;
|
||||
out.push(value.clone());
|
||||
if value_as_bool(&value) {
|
||||
out.push(String::from("dummy"));
|
||||
return Ok(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for operand in operands {
|
||||
let value = operand.evaluate()?;
|
||||
out.push(value);
|
||||
|
|
|
@ -123,6 +123,21 @@ fn test_or() {
|
|||
.args(&["-14", "|", "1"])
|
||||
.succeeds()
|
||||
.stdout_only("-14\n");
|
||||
|
||||
new_ucmd!()
|
||||
.args(&["1", "|", "a", "/", "5"])
|
||||
.succeeds()
|
||||
.stdout_only("1\n");
|
||||
|
||||
new_ucmd!()
|
||||
.args(&["foo", "|", "a", "/", "5"])
|
||||
.succeeds()
|
||||
.stdout_only("foo\n");
|
||||
|
||||
new_ucmd!()
|
||||
.args(&["0", "|", "10", "/", "5"])
|
||||
.succeeds()
|
||||
.stdout_only("2\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue