Skip to content

Commit 77beb78

Browse files
authored
DPL Analysis: modernize expression parsing code (#14185)
1 parent 82782fd commit 77beb78

File tree

2 files changed

+65
-66
lines changed

2 files changed

+65
-66
lines changed

Framework/Core/include/Framework/Expressions.h

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct ExpressionInfo {
6969

7070
namespace o2::framework::expressions
7171
{
72+
void unknownParameterUsed(const char* name);
7273
const char* stringType(atype::type t);
7374

7475
template <typename... T>
@@ -147,7 +148,7 @@ struct PlaceholderNode : LiteralNode {
147148
if constexpr (variant_trait_v<typename std::decay<T>::type> != VariantType::Unknown) {
148149
retrieve = [](InitContext& context, char const* name) { return LiteralNode::var_t{context.options().get<T>(name)}; };
149150
} else {
150-
runtime_error("Unknown parameter used in expression.");
151+
unknownParameterUsed(name.c_str());
151152
}
152153
}
153154

@@ -188,6 +189,19 @@ struct ParameterNode : LiteralNode {
188189
struct ConditionalNode {
189190
};
190191

192+
/// concepts
193+
template <typename T>
194+
concept is_literal_like = std::same_as<T, LiteralNode> || std::same_as<T, PlaceholderNode> || std::same_as<T, ParameterNode>;
195+
196+
template <typename T>
197+
concept is_binding = std::same_as<T, BindingNode>;
198+
199+
template <typename T>
200+
concept is_operation = std::same_as<T, OpNode>;
201+
202+
template <typename T>
203+
concept is_conditional = std::same_as<T, ConditionalNode>;
204+
191205
/// A generic tree node
192206
struct Node {
193207
Node(LiteralNode&& v) : self{std::forward<LiteralNode>(v)}, left{nullptr}, right{nullptr}, condition{nullptr}
@@ -267,7 +281,7 @@ struct NodeRecord {
267281

268282
/// Tree-walker helper
269283
template <typename L>
270-
void walk(Node* head, L const& pred)
284+
void walk(Node* head, L&& pred)
271285
{
272286
std::stack<NodeRecord> path;
273287
path.emplace(head, 0);
@@ -512,16 +526,15 @@ inline Node binned(std::vector<T> const& binning, std::vector<T> const& paramete
512526
}
513527

514528
template <typename T>
515-
Node updateParameters(Node const& pexp, int bins, std::vector<T> const& parameters, int bin)
529+
inline Node updateParameters(Node const& pexp, int bins, std::vector<T> const& parameters, int bin)
516530
{
517531
Node result{pexp};
518-
auto updateParameter = [&bins, &parameters, &bin](Node* node) {
532+
walk(&result, [&bins, &parameters, &bin](Node* node) {
519533
if (node->self.index() == 5) {
520534
auto* n = std::get_if<5>(&node->self);
521535
n->reset(parameters[n->index * bins + bin]);
522536
}
523-
};
524-
walk(&result, updateParameter);
537+
});
525538
return result;
526539
}
527540

@@ -594,12 +607,6 @@ gandiva::ExpressionPtr makeExpression(gandiva::NodePtr node, gandiva::FieldPtr r
594607
/// Update placeholder nodes from context
595608
void updatePlaceholders(Filter& filter, InitContext& context);
596609

597-
template <typename... C>
598-
std::vector<expressions::Projector> makeProjectors(framework::pack<C...>)
599-
{
600-
return {C::Projector()...};
601-
}
602-
603610
std::shared_ptr<gandiva::Projector> createProjectorHelper(size_t nColumns, expressions::Projector* projectors,
604611
std::shared_ptr<arrow::Schema> schema,
605612
std::vector<std::shared_ptr<arrow::Field>> const& fields);

Framework/Core/src/Expressions.cxx

Lines changed: 46 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ using namespace o2::framework;
2424

2525
namespace o2::framework::expressions
2626
{
27+
void unknownParameterUsed(const char* name)
28+
{
29+
runtime_error_f("Unknown parameter used in expression: %s", name);
30+
}
2731

2832
/// a map between BasicOp and gandiva node definitions
2933
/// note that logical 'and' and 'or' are created separately
@@ -89,43 +93,41 @@ size_t Filter::designateSubtrees(Node* node, size_t index)
8993
return index;
9094
}
9195

92-
namespace
96+
template <typename T>
97+
constexpr inline auto makeDatum(T const&)
9398
{
94-
struct LiteralNodeHelper {
95-
DatumSpec operator()(LiteralNode const& node) const
96-
{
97-
return DatumSpec{node.value, node.type};
98-
}
99-
};
99+
return DatumSpec{};
100+
}
100101

101-
struct BindingNodeHelper {
102-
DatumSpec operator()(BindingNode const& node) const
103-
{
104-
return DatumSpec{node.name, node.hash, node.type};
105-
}
106-
};
102+
template <is_literal_like T>
103+
constexpr inline auto makeDatum(T const& node)
104+
{
105+
return DatumSpec{node.value, node.type};
106+
}
107107

108-
struct OpNodeHelper {
109-
ColumnOperationSpec operator()(OpNode const& node) const
110-
{
111-
return ColumnOperationSpec{node.op};
112-
}
113-
};
108+
template <is_binding T>
109+
constexpr inline auto makeDatum(T const& node)
110+
{
111+
return DatumSpec{node.name, node.hash, node.type};
112+
}
114113

115-
struct PlaceholderNodeHelper {
116-
DatumSpec operator()(PlaceholderNode const& node) const
117-
{
118-
return DatumSpec{node.value, node.type};
119-
}
120-
};
114+
template <typename T>
115+
constexpr inline auto makeOp(T const&, size_t const&)
116+
{
117+
return ColumnOperationSpec{};
118+
}
121119

122-
struct ParameterNodeHelper {
123-
DatumSpec operator()(ParameterNode const& node) const
124-
{
125-
return DatumSpec{node.value, node.type};
126-
}
127-
};
128-
} // namespace
120+
template <is_operation T>
121+
constexpr inline auto makeOp(T const& node, size_t const& index)
122+
{
123+
return ColumnOperationSpec{node.op, index};
124+
}
125+
126+
template <is_conditional T>
127+
constexpr inline auto makeOp(T const&, size_t const& index)
128+
{
129+
return ColumnOperationSpec{BasicOp::Conditional, index};
130+
}
129131

130132
std::shared_ptr<arrow::DataType> concreteArrowType(atype::type type)
131133
{
@@ -169,7 +171,7 @@ std::string upcastTo(atype::type f)
169171
case atype::DOUBLE:
170172
return "castFLOAT8";
171173
default:
172-
throw runtime_error_f("Do not know how to cast to %d", f);
174+
throw runtime_error_f("Do not know how to cast to %s", stringType(f));
173175
}
174176
}
175177

@@ -196,13 +198,11 @@ std::ostream& operator<<(std::ostream& os, DatumSpec const& spec)
196198

197199
void updatePlaceholders(Filter& filter, InitContext& context)
198200
{
199-
auto updateNode = [&](Node* node) {
201+
expressions::walk(filter.node.get(), [&](Node* node) {
200202
if (node->self.index() == 3) {
201203
std::get_if<3>(&node->self)->reset(context);
202204
}
203-
};
204-
205-
expressions::walk(filter.node.get(), updateNode);
205+
});
206206
}
207207

208208
const char* stringType(atype::type t)
@@ -246,12 +246,7 @@ Operations createOperations(Filter const& expression)
246246

247247
auto processLeaf = [](Node const* const node) {
248248
return std::visit(
249-
overloaded{
250-
[lh = LiteralNodeHelper{}](LiteralNode const& node) { return lh(node); },
251-
[bh = BindingNodeHelper{}](BindingNode const& node) { return bh(node); },
252-
[ph = PlaceholderNodeHelper{}](PlaceholderNode const& node) { return ph(node); },
253-
[pr = ParameterNodeHelper{}](ParameterNode const& node) { return pr(node); },
254-
[](auto&&) { return DatumSpec{}; }},
249+
[](auto const& n) { return makeDatum(n); },
255250
node->self);
256251
};
257252

@@ -266,10 +261,7 @@ Operations createOperations(Filter const& expression)
266261
// create operation spec, pop the node and add its children
267262
auto operationSpec =
268263
std::visit(
269-
overloaded{
270-
[&](OpNode node) { return ColumnOperationSpec{node.op, top.node_ptr->index}; },
271-
[&](ConditionalNode) { return ColumnOperationSpec{BasicOp::Conditional, top.node_ptr->index}; },
272-
[](auto&&) { return ColumnOperationSpec{}; }},
264+
[&](auto const& n) { return makeOp(n, top.node_ptr->index); },
273265
top.node_ptr->self);
274266

275267
operationSpec.result = DatumSpec{top.index, operationSpec.type};
@@ -623,15 +615,15 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs,
623615
auto rightNode = datumNode(it->right);
624616
auto condNode = datumNode(it->condition);
625617

626-
auto insertUpcastNode = [&](gandiva::NodePtr node, atype::type t) {
627-
if (t != it->type) {
628-
auto upcast = gandiva::TreeExprBuilder::MakeFunction(upcastTo(it->type), {node}, concreteArrowType(it->type));
618+
auto insertUpcastNode = [](gandiva::NodePtr node, atype::type t0, atype::type t) {
619+
if (t != t0) {
620+
auto upcast = gandiva::TreeExprBuilder::MakeFunction(upcastTo(t0), {node}, concreteArrowType(t0));
629621
node = upcast;
630622
}
631623
return node;
632624
};
633625

634-
auto insertEqualizeUpcastNode = [&](gandiva::NodePtr& node1, gandiva::NodePtr& node2, atype::type t1, atype::type t2) {
626+
auto insertEqualizeUpcastNode = [](gandiva::NodePtr& node1, gandiva::NodePtr& node2, atype::type t1, atype::type t2) {
635627
if (t2 > t1) {
636628
auto upcast = gandiva::TreeExprBuilder::MakeFunction(upcastTo(t2), {node1}, concreteArrowType(t2));
637629
node1 = upcast;
@@ -656,14 +648,14 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs,
656648
default:
657649
if (it->op < BasicOp::Sqrt) {
658650
if (it->type != atype::BOOL) {
659-
leftNode = insertUpcastNode(leftNode, it->left.type);
660-
rightNode = insertUpcastNode(rightNode, it->right.type);
651+
leftNode = insertUpcastNode(leftNode, it->type, it->left.type);
652+
rightNode = insertUpcastNode(rightNode, it->type, it->right.type);
661653
} else if (it->op == BasicOp::Equal || it->op == BasicOp::NotEqual) {
662654
insertEqualizeUpcastNode(leftNode, rightNode, it->left.type, it->right.type);
663655
}
664656
temp_node = gandiva::TreeExprBuilder::MakeFunction(basicOperationsMap[it->op], {leftNode, rightNode}, concreteArrowType(it->type));
665657
} else {
666-
leftNode = insertUpcastNode(leftNode, it->left.type);
658+
leftNode = insertUpcastNode(leftNode, it->type, it->left.type);
667659
temp_node = gandiva::TreeExprBuilder::MakeFunction(basicOperationsMap[it->op], {leftNode}, concreteArrowType(it->type));
668660
}
669661
break;

0 commit comments

Comments
 (0)