Skip to content

Commit

Permalink
Split evaluators into multiple files
Browse files Browse the repository at this point in the history
Signed-off-by: Kunlin Yu <[email protected]>
  • Loading branch information
kunlinyu committed Jan 2, 2025
1 parent 3dac1bf commit d428f67
Show file tree
Hide file tree
Showing 9 changed files with 584 additions and 0 deletions.
5 changes: 5 additions & 0 deletions include/cql2cpp/evaluator.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ using NodeEval =
std::function<bool(const AstNode*, const std::vector<ValueT>&,
const FeatureSource*, ValueT*, std::string* error_msg)>;

class NodeEvaluator {
public:
virtual const std::map<NodeType, std::map<Operator, NodeEval>>& GetEvaluators() const = 0;
};

class TreeEvaluator {
private:
std::map<NodeType, std::map<Operator, NodeEval>> type_evaluator_;
Expand Down
118 changes: 118 additions & 0 deletions include/cql2cpp/evaluator_array.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* File Name: evaluator_array.h
*
* Copyright (c) 2024-2025 IndoorSpatial
*
* Author: Kunlin Yu <[email protected]>
* Create Date: 2025/01/02
*
*/

#pragma once

#include "evaluator.h"

namespace cql2cpp {

template <typename ValueType>
inline bool CheckValueNumberType(const std::string& op, size_t num,
const std::vector<ValueT>& vs,
std::string* errmsg) {
if (vs.size() != num) {
*errmsg = op + " needs two values but we have " + std::to_string(vs.size());
return false;
}
for (size_t i = 0; i < num; i++)
if (not std::holds_alternative<ValueType>(vs.at(i))) {
*errmsg = "value " + std::to_string(i) + " of " + op + " is incorrect";
return false;
}
return true;
}

class EvaluatorArray : public NodeEvaluator {
private:
std::map<NodeType, std::map<Operator, NodeEval>> evaluators_;

public:
EvaluatorArray() {
evaluators_[Array][NullOp] = [](auto n, auto vs, auto fs, auto value,
auto errmsg) -> bool {
ArrayType result;
for (const auto& v : vs) result.emplace_back(Element(v));
*value = result;
return true;
};

evaluators_[ArrayPred][A_Equals] = [this](auto n, auto vs, auto fs,
auto value, auto errmsg) -> bool {
const auto& contains = evaluators_.at(ArrayPred).at(A_Contains);
const auto& contained = evaluators_.at(ArrayPred).at(A_ContainedBy);

bool ret1 = contains.operator()(n, vs, fs, value, errmsg);
bool result_1 = std::get<bool>(*value);
if (not ret1) return false;
bool ret2 = contained.operator()(n, vs, fs, value, errmsg);
bool result_2 = std::get<bool>(*value);
if (not ret2) return false;

*value = result_1 and result_2;
return true;
};

evaluators_[ArrayPred][A_Contains] = [](auto n, auto vs, auto fs,
auto value, auto errmsg) -> bool {
if (not CheckValueNumberType<ArrayType>("Array Op", 2, vs, errmsg))
return false;
const auto& lhs_array = std::get<ArrayType>(vs.at(0));
const auto& rhs_array = std::get<ArrayType>(vs.at(1));
if (lhs_array.size() < rhs_array.size()) {
*value = false;
return true;
}
SetType lhs_set(lhs_array.begin(), lhs_array.end());
SetType rhs_set(rhs_array.begin(), rhs_array.end());
for (const auto& e : rhs_set)
if (lhs_set.find(e) == lhs_set.end()) {
*value = false;
return true;
}
*value = true;
return true;
};

evaluators_[ArrayPred][A_ContainedBy] =
[](auto n, auto vs, auto fs, auto value, auto errmsg) -> bool {
if (not CheckValueNumberType<ArrayType>("Array Op", 2, vs, errmsg))
return false;

const auto& lhs_array = std::get<ArrayType>(vs.at(0));
const auto& rhs_array = std::get<ArrayType>(vs.at(1));
if (lhs_array.size() > rhs_array.size()) {
*value = false;
return true;
}
SetType lhs_set(lhs_array.begin(), lhs_array.end());
SetType rhs_set(rhs_array.begin(), rhs_array.end());
for (const auto& e : lhs_set)
if (rhs_set.find(e) == rhs_set.end()) {
*value = false;
return true;
}
*value = true;
return true;
};

evaluators_[ArrayPred][A_Overlaps] = [](auto n, auto vs, auto fs,
auto value, auto errmsg) -> bool {
// TODO
return false;
};
}
const std::map<NodeType, std::map<Operator, NodeEval>>& GetEvaluators()
const override {
return evaluators_;
}
};
} // namespace cql2cpp

64 changes: 64 additions & 0 deletions include/cql2cpp/evaluator_bool.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* File Name: evaluator_bool.h
*
* Copyright (c) 2024-2025 IndoorSpatial
*
* Author: Kunlin Yu <[email protected]>
* Create Date: 2025/01/02
*
*/

#pragma once

#include "evaluator.h"

namespace cql2cpp {

template <typename ValueType>
inline bool CheckValueNumberType(const std::string& op, size_t num,
const std::vector<ValueT>& vs,
std::string* errmsg) {
if (vs.size() != num) {
*errmsg = op + " needs two values but we have " + std::to_string(vs.size());
return false;
}
for (size_t i = 0; i < num; i++)
if (not std::holds_alternative<ValueType>(vs.at(i))) {
*errmsg = "value " + std::to_string(i) + " of " + op + " is incorrect";
return false;
}
return true;
}

class EvaluatorBool : public NodeEvaluator {
private:
std::map<NodeType, std::map<Operator, NodeEval>> evaluators_;

public:
EvaluatorBool() {
evaluators_[BoolExpression][And] = [](auto n, auto vs, auto fs, auto value,
auto errmsg) -> bool {
if (not CheckValueNumberType<bool>("AND", 2, vs, errmsg)) return false;
*value = std::get<bool>(vs.at(0)) and std::get<bool>(vs.at(1));
return true;
};
evaluators_[BoolExpression][Or] = [](auto n, auto vs, auto fs, auto value,
auto errmsg) -> bool {
if (not CheckValueNumberType<bool>("OR", 2, vs, errmsg)) return false;
*value = std::get<bool>(vs.at(0)) or std::get<bool>(vs.at(1));
return true;
};
evaluators_[BoolExpression][Not] = [](auto n, auto vs, auto fs, auto value,
auto errmsg) -> bool {
if (not CheckValueNumberType<bool>("NOT", 1, vs, errmsg)) return false;
*value = not std::get<bool>(vs.at(0));
return true;
};
}
const std::map<NodeType, std::map<Operator, NodeEval>>& GetEvaluators()
const override {
return evaluators_;
}
};
} // namespace cql2cpp

90 changes: 90 additions & 0 deletions include/cql2cpp/evaluator_compare.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* File Name: evaluator_compare.h
*
* Copyright (c) 2024-2025 IndoorSpatial
*
* Author: Kunlin Yu <[email protected]>
* Create Date: 2025/01/02
*
*/

#pragma once

#include "evaluator.h"
#include "value_compare.h"

namespace cql2cpp {

class EvaluatorCompare : public NodeEvaluator {
private:
std::map<NodeType, std::map<Operator, NodeEval>> evaluators_;

public:
EvaluatorCompare() {
evaluators_[BinCompPred][Greater] = [](auto n, auto vs, auto fs, auto value,
auto errmsg) -> bool {
double left, right;
if (not ComparisonCheck(vs, &left, &right, errmsg)) return false;
*value = (left > right);
return true;
};
evaluators_[BinCompPred][GreaterEqual] =
[](auto n, auto vs, auto fs, auto value, auto errmsg) -> bool {
double left, right;
if (not ComparisonCheck(vs, &left, &right, errmsg)) return false;
*value = (left >= right);
return true;
};
evaluators_[BinCompPred][Lesser] = [](auto n, auto vs, auto fs, auto value,
auto errmsg) -> bool {
double left, right;
if (not ComparisonCheck(vs, &left, &right, errmsg)) return false;
*value = (left < right);
return true;
};
evaluators_[BinCompPred][LesserEqual] =
[](auto n, auto vs, auto fs, auto value, auto errmsg) -> bool {
double left, right;
if (not ComparisonCheck(vs, &left, &right, errmsg)) return false;
*value = (left <= right);
return true;
};
evaluators_[BinCompPred][NotEqual] =
[this](auto n, auto vs, auto fs, auto value, auto errmsg) -> bool {
const NodeEval& equal_lambda = evaluators_.at(BinCompPred).at(Equal);
bool ret = equal_lambda.operator()(n, vs, fs, value, errmsg);
if (ret) *value = not std::get<bool>(*value);
return ret;
};
evaluators_[BinCompPred][Equal] = [](auto n, auto vs, auto fs, auto value,
auto errmsg) -> bool {
if (vs.size() != 2) {
*errmsg = "binary compare needs two values but we have " +
std::to_string(vs.size());
return false;
}
if (std::holds_alternative<bool>(vs.at(0)) and
std::holds_alternative<bool>(vs.at(1))) {
*value = std::get<bool>(vs.at(0)) == std::get<bool>(vs.at(1));
return true;
}
if (std::holds_alternative<std::string>(vs.at(0)) and
std::holds_alternative<std::string>(vs.at(1))) {
*value =
std::get<std::string>(vs.at(0)) == std::get<std::string>(vs.at(1));
return true;
}

double left, right;
if (not ComparisonCheck(vs, &left, &right, errmsg)) return false;
*value = (fabs(left - right) < kEpsilon);
return true;
};
}
const std::map<NodeType, std::map<Operator, NodeEval>>& GetEvaluators()
const override {
return evaluators_;
}
};
} // namespace cql2cpp

73 changes: 73 additions & 0 deletions include/cql2cpp/evaluator_function.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* File Name: evaluator_function.h
*
* Copyright (c) 2024-2025 IndoorSpatial
*
* Author: Kunlin Yu <[email protected]>
* Create Date: 2025/01/02
*
*/

#pragma once

#include "evaluator.h"
#include "function.h"

namespace cql2cpp {

class EvaluatorFunction : public NodeEvaluator {
private:
std::map<NodeType, std::map<Operator, NodeEval>> evaluators_;

public:
EvaluatorFunction() {
evaluators_[Function][NullOp] = [](auto n, auto vs, auto fs, auto value,
auto errmsg) -> bool {
if (vs.empty()) {
*errmsg = "function needs a name and argument list";
return false;
}
if (not std::holds_alternative<std::string>(vs.at(0))) {
*errmsg = "function name should be a string";
return false;
}
std::string function_name = std::get<std::string>(vs.at(0));
if (functions.find(function_name) == functions.end()) {
*errmsg = "can not find function " + function_name;
return false;
}
if (vs.size() == 1)
return functions.at(function_name).operator()({}, value, errmsg);
else if (vs.size() == 2) {
if (not std::holds_alternative<ArrayType>(vs.at(1))) {
*errmsg = "the second value of a function should be argument list";
return false;
}
std::vector<ValueT> vec;
for (const auto& element : std::get<ArrayType>(vs.at(1)))
vec.emplace_back(element.value);

return functions.at(function_name).operator()(vec, value, errmsg);
} else {
*errmsg =
"function needs only two child (name and argument list) but we "
"get " +
std::to_string(vs.size());
return false;
}
};
evaluators_[ArgumentList][NullOp] = [](auto n, auto vs, auto fs, auto value,
auto errmsg) -> bool {
ArrayType result;
for (const auto& v : vs) result.emplace_back(Element(v));
*value = result;
return true;
};
}
const std::map<NodeType, std::map<Operator, NodeEval>>& GetEvaluators()
const override {
return evaluators_;
}
};
} // namespace cql2cpp

Loading

0 comments on commit d428f67

Please sign in to comment.