Skip to content

Commit 77502dc

Browse files
authored
xpath: Clean up the expression AST a bit (servo#39788)
The current AST has different nodes for additive, multiplicative, relational (etc) expressions. That is not a useful distinction, as they are all treated more or less the same. Instead, I've unified these as `Expression::Binary(lhs, binary_operator, rhs)`. There are also some silly things that can be removed, like ```rust enum UnaryOp { Minus } ``` This change is in preparation for an upcoming PR which will address servo#39602 . Testing: Covered by existing tests Part of servo#34527 Signed-off-by: Simon Wülker <[email protected]>
1 parent 44c2365 commit 77502dc

File tree

2 files changed

+105
-143
lines changed

2 files changed

+105
-143
lines changed

components/xpath/src/eval.rs

Lines changed: 43 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
use markup5ever::{LocalName, Namespace, Prefix, QualName, local_name, namespace_prefix, ns};
66

77
use super::parser::{
8-
AdditiveOp, Axis, EqualityOp, Expr, FilterExpr, KindTest, Literal, MultiplicativeOp, NodeTest,
9-
NumericLiteral, PathExpr, PredicateListExpr, PrimaryExpr, RelationalOp, StepExpr, UnaryOp,
8+
Axis, BinaryOperator, Expr, FilterExpr, KindTest, Literal, NodeTest, PathExpr,
9+
PredicateListExpr, PrimaryExpr, StepExpr,
1010
};
1111
use super::{EvaluationCtx, Value};
1212
use crate::context::PredicateCtx;
@@ -25,75 +25,56 @@ impl Expr {
2525
context: &EvaluationCtx<D>,
2626
) -> Result<Value<D::Node>, Error<D::JsError>> {
2727
match self {
28-
Expr::And(left, right) => {
28+
// And/Or expression are seperated because they can sometimes be evaluated
29+
// without evaluating both operands.
30+
Expr::Binary(left, BinaryOperator::And, right) => {
2931
let left_bool = left.evaluate(context)?.boolean();
3032
let v = left_bool && right.evaluate(context)?.boolean();
3133
Ok(Value::Boolean(v))
3234
},
33-
Expr::Or(left, right) => {
35+
Expr::Binary(left, BinaryOperator::Or, right) => {
3436
let left_bool = left.evaluate(context)?.boolean();
3537
let v = left_bool || right.evaluate(context)?.boolean();
3638
Ok(Value::Boolean(v))
3739
},
38-
Expr::Equality(left, equality_op, right) => {
39-
let left_val = left.evaluate(context)?;
40-
let right_val = right.evaluate(context)?;
41-
42-
let v = match equality_op {
43-
EqualityOp::Eq => left_val == right_val,
44-
EqualityOp::NotEq => left_val != right_val,
45-
};
46-
47-
Ok(Value::Boolean(v))
48-
},
49-
Expr::Relational(left, relational_op, right) => {
50-
let left_val = left.evaluate(context)?.number();
51-
let right_val = right.evaluate(context)?.number();
52-
53-
let v = match relational_op {
54-
RelationalOp::Lt => left_val < right_val,
55-
RelationalOp::Gt => left_val > right_val,
56-
RelationalOp::LtEq => left_val <= right_val,
57-
RelationalOp::GtEq => left_val >= right_val,
58-
};
59-
Ok(Value::Boolean(v))
60-
},
61-
Expr::Additive(left, additive_op, right) => {
62-
let left_val = left.evaluate(context)?.number();
63-
let right_val = right.evaluate(context)?.number();
64-
65-
let v = match additive_op {
66-
AdditiveOp::Add => left_val + right_val,
67-
AdditiveOp::Sub => left_val - right_val,
68-
};
69-
Ok(Value::Number(v))
70-
},
71-
Expr::Multiplicative(left, multiplicative_op, right) => {
72-
let left_val = left.evaluate(context)?.number();
73-
let right_val = right.evaluate(context)?.number();
74-
75-
let v = match multiplicative_op {
76-
MultiplicativeOp::Mul => left_val * right_val,
77-
MultiplicativeOp::Div => left_val / right_val,
78-
MultiplicativeOp::Mod => left_val % right_val,
40+
Expr::Binary(left, binary_operator, right) => {
41+
let left_value = left.evaluate(context)?;
42+
let right_value = right.evaluate(context)?;
43+
44+
let value = match binary_operator {
45+
BinaryOperator::Equal => (left_value == right_value).into(),
46+
BinaryOperator::NotEqual => (left_value != right_value).into(),
47+
BinaryOperator::LessThan => (left_value.number() < right_value.number()).into(),
48+
BinaryOperator::GreaterThan => {
49+
(left_value.number() > right_value.number()).into()
50+
},
51+
BinaryOperator::LessThanOrEqual => {
52+
(left_value.number() <= right_value.number()).into()
53+
},
54+
BinaryOperator::GreaterThanOrEqual => {
55+
(left_value.number() >= right_value.number()).into()
56+
},
57+
BinaryOperator::Add => (left_value.number() + right_value.number()).into(),
58+
BinaryOperator::Subtract => (left_value.number() - right_value.number()).into(),
59+
BinaryOperator::Multiply => (left_value.number() * right_value.number()).into(),
60+
BinaryOperator::Divide => (left_value.number() / right_value.number()).into(),
61+
BinaryOperator::Modulo => (left_value.number() % right_value.number()).into(),
62+
BinaryOperator::Union => {
63+
let as_nodes = |e: &Expr| e.evaluate(context).and_then(try_extract_nodeset);
64+
let mut left_nodes = as_nodes(left)?;
65+
let right_nodes = as_nodes(right)?;
66+
67+
left_nodes.extend(right_nodes);
68+
Value::Nodeset(left_nodes)
69+
},
70+
_ => unreachable!("And/Or were handled above"),
7971
};
80-
Ok(Value::Number(v))
81-
},
82-
Expr::Unary(unary_op, expr) => {
83-
let v = expr.evaluate(context)?.number();
8472

85-
match unary_op {
86-
UnaryOp::Minus => Ok(Value::Number(-v)),
87-
}
73+
Ok(value)
8874
},
89-
Expr::Union(left, right) => {
90-
let as_nodes = |e: &Expr| e.evaluate(context).and_then(try_extract_nodeset);
91-
92-
let mut left_nodes = as_nodes(left)?;
93-
let right_nodes = as_nodes(right)?;
94-
95-
left_nodes.extend(right_nodes);
96-
Ok(Value::Nodeset(left_nodes))
75+
Expr::Negate(expr) => {
76+
let value = -expr.evaluate(context)?.number();
77+
Ok(value.into())
9778
},
9879
Expr::Path(path_expr) => path_expr.evaluate(context),
9980
}
@@ -450,11 +431,8 @@ impl Literal {
450431
_context: &EvaluationCtx<D>,
451432
) -> Result<Value<D::Node>, Error<D::JsError>> {
452433
match self {
453-
Literal::Numeric(numeric_literal) => match numeric_literal {
454-
// We currently make no difference between ints and floats
455-
NumericLiteral::Integer(v) => Ok(Value::Number(*v as f64)),
456-
NumericLiteral::Decimal(v) => Ok(Value::Number(*v)),
457-
},
434+
Literal::Integer(integer) => Ok(Value::Number(*integer as f64)),
435+
Literal::Decimal(decimal) => Ok(Value::Number(*decimal)),
458436
Literal::String(s) => Ok(Value::String(s.into())),
459437
}
460438
}

0 commit comments

Comments
 (0)