Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 2 additions & 21 deletions src/uu/expr/src/syntax_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,9 +624,6 @@ pub struct AstNode {
#[derive(Debug, Clone)]
#[cfg_attr(test, derive(Eq, PartialEq))]
pub enum AstNodeInner {
Evaluated {
value: NumOrStr,
},
Leaf {
value: MaybeNonUtf8String,
},
Expand All @@ -650,15 +647,6 @@ impl AstNode {
Parser::new(input).parse()
}

pub fn evaluated(self) -> ExprResult<Self> {
Ok(Self {
id: get_next_id(),
inner: AstNodeInner::Evaluated {
value: self.eval()?,
},
})
}

pub fn eval(&self) -> ExprResult<NumOrStr> {
// This function implements a recursive tree-walking algorithm, but uses an explicit
// stack approach instead of native recursion to avoid potential stack overflow
Expand All @@ -669,9 +657,6 @@ impl AstNode {

while let Some(node) = stack.pop() {
match &node.inner {
AstNodeInner::Evaluated { value, .. } => {
result_stack.insert(node.id, Ok(value.clone()));
}
AstNodeInner::Leaf { value, .. } => {
result_stack.insert(node.id, Ok(value.to_owned().into()));
}
Expand Down Expand Up @@ -896,9 +881,7 @@ impl<'a, S: AsRef<MaybeNonUtf8Str>> Parser<'a, S> {
value: self.next()?.into(),
},
b"(" => {
// Evaluate the node just after parsing to we detect arithmetic
// errors before checking for the closing parenthesis.
let s = self.parse_expression()?.evaluated()?;
let s = self.parse_expression()?;

match self.next() {
Ok(b")") => {}
Expand Down Expand Up @@ -1070,9 +1053,7 @@ mod test {
AstNode::parse(&["(", "1", "+", "2", ")", "*", "3"]),
Ok(op(
BinOp::Numeric(NumericOp::Mul),
op(BinOp::Numeric(NumericOp::Add), "1", "2")
.evaluated()
.unwrap(),
op(BinOp::Numeric(NumericOp::Add), "1", "2"),
"3"
))
);
Expand Down
27 changes: 25 additions & 2 deletions tests/by-util/test_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,29 @@ fn test_and() {
new_ucmd!().args(&["", "&", ""]).fails().stdout_only("0\n");
}

#[test]
fn test_parenthesized_short_circuit_dead_branches() {
new_ucmd!()
.args(&["1", "|", "(", "1", "/", "0", ")"])
.succeeds()
.stdout_only("1\n");

new_ucmd!()
.args(&["0", "&", "(", "1", "/", "0", ")"])
.fails_with_code(1)
.stdout_only("0\n");

new_ucmd!()
.args(&["1", "|", "(", "0", "&", "(", "1", "/", "0", ")", ")"])
.succeeds()
.stdout_only("1\n");

new_ucmd!()
.args(&["0", "&", "(", "1", "|", "(", "1", "/", "0", ")", ")"])
.fails_with_code(1)
.stdout_only("0\n");
}

#[test]
fn test_length_fail() {
new_ucmd!().args(&["length", "αbcdef", "1"]).fails();
Expand Down Expand Up @@ -580,11 +603,11 @@ fn test_num_str_comparison() {
}

#[test]
fn test_eager_evaluation() {
fn test_missing_closing_parenthesis_reports_syntax_error() {
new_ucmd!()
.args(&["(", "1", "/", "0"])
.fails()
.stderr_contains("division by zero");
.stderr_contains("expecting ')' after '0'");
}

#[test]
Expand Down
Loading