Skip to content

Commit

Permalink
Merge branch 'master' into cxx17_concepts_sparqlExpressions
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/backports/concepts.h
  • Loading branch information
joka921 committed Feb 14, 2025
2 parents c1a1af7 + 1570033 commit ed92968
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 61 deletions.
44 changes: 44 additions & 0 deletions src/backports/cppTemplate2.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,47 @@

#define CPP_member_def_sfinae \
template <bool (&CPP_true_fn)(::concepts::detail::xNil)>

#define CPP_LAMBDA_20(...) [__VA_ARGS__] CPP_LAMBDA_ARGS

#define CPP_TEMPLATE_LAMBDA_20(...) [__VA_ARGS__] CPP_TEMPLATE_LAMBDA_ARGS

// The internals of the `CPP_lambda` template
#define CPP_LAMBDA_SFINAE_ARGS(...) \
(__VA_ARGS__ CPP_LAMBDA_SFINAE_AUX_

#define CPP_LAMBDA_SFINAE_AUX_WHICH_(FIRST, ...) \
CPP_PP_EVAL(CPP_PP_CHECK, CPP_PP_CAT(CPP_LAMBDA_SFINAE_PROBE_CONCEPT_, FIRST))

#define CPP_LAMBDA_SFINAE_AUX_(...) \
CPP_PP_CAT(CPP_LAMBDA_SFINAE_AUX_, \
CPP_LAMBDA_SFINAE_AUX_WHICH_(__VA_ARGS__, )) \
(__VA_ARGS__)

#define CPP_LAMBDA_SFINAE_AUX_0(...) , \
std::enable_if_t< \
CPP_PP_CAT(CPP_LAMBDA_SFINAE_AUX_3_, __VA_ARGS__) \
>* = nullptr)

#define CPP_lambda_sfinae(...) \
CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN \
[__VA_ARGS__] CPP_LAMBDA_SFINAE_ARGS

#define CPP_TEMPLATE_LAMBDA_ARGS_sfinae(...) \
<__VA_ARGS__> CPP_LAMBDA_SFINAE_ARGS

#define CPP_template_lambda_sfinae(...) \
[__VA_ARGS__] CPP_TEMPLATE_LAMBDA_ARGS_sfinae

#define CPP_LAMBDA_SFINAE_AUX_3_requires

#define CPP_LAMBDA_ARGS(...) (__VA_ARGS__) CPP_LAMBDA_AUX_

#define CPP_LAMBDA_AUX_(...) \
CPP_PP_CAT(CPP_LAMBDA_AUX_, CPP_LAMBDA_AUX_WHICH_(__VA_ARGS__, ))(__VA_ARGS__)

#define CPP_LAMBDA_AUX_WHICH_(FIRST, ...) CPP_PP_EVAL(CPP_PP_CHECK, FIRST)

#define CPP_LAMBDA_AUX_0(...) __VA_ARGS__

#define CPP_TEMPLATE_LAMBDA_ARGS(...) <__VA_ARGS__> CPP_LAMBDA_ARGS
5 changes: 3 additions & 2 deletions src/parser/GeoPoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ class GeoPoint {
public:
using T = uint64_t;

template <typename H>
friend H AbslHashValue(H h, const std::same_as<GeoPoint> auto& g) {
CPP_template(typename H,
typename G)(requires std::same_as<G, GeoPoint>) friend H
AbslHashValue(H h, const G& g) {
return H::combine(std::move(h), g.lat_, g.lng_);
}

Expand Down
5 changes: 3 additions & 2 deletions src/parser/Iri.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <string_view>

#include "backports/concepts.h"
#include "parser/NormalizedString.h"

namespace ad_utility::triple_component {
Expand All @@ -30,8 +31,8 @@ class Iri {
public:
// A default constructed IRI is empty.
Iri() = default;
template <typename H>
friend H AbslHashValue(H h, const std::same_as<Iri> auto& iri) {
CPP_template(typename H, typename I)(requires std::same_as<I, Iri>) friend H
AbslHashValue(H h, const I& iri) {
return H::combine(std::move(h), iri.iri_);
}
bool operator==(const Iri&) const = default;
Expand Down
6 changes: 4 additions & 2 deletions src/parser/Literal.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <optional>
#include <variant>

#include "backports/concepts.h"
#include "parser/Iri.h"
#include "parser/NormalizedString.h"

Expand Down Expand Up @@ -41,8 +42,9 @@ class Literal {
}

public:
template <typename H>
friend H AbslHashValue(H h, const std::same_as<Literal> auto& literal) {
CPP_template(typename H,
typename L)(requires std::same_as<L, Literal>) friend H
AbslHashValue(H h, const L& literal) {
return H::combine(std::move(h), literal.content_);
}
bool operator==(const Literal&) const = default;
Expand Down
6 changes: 3 additions & 3 deletions src/parser/LiteralOrIri.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ class alignas(16) LiteralOrIri {
return LiteralOrIri{Iri::fromStringRepresentation(std::move(internal))};
}
}
template <typename H>
friend H AbslHashValue(H h,
const std::same_as<LiteralOrIri> auto& literalOrIri) {
CPP_template(typename H,
typename L)(requires std::same_as<L, LiteralOrIri>) friend H
AbslHashValue(H h, const L& literalOrIri) {
return H::combine(std::move(h), literalOrIri.data_);
}
bool operator==(const LiteralOrIri&) const = default;
Expand Down
18 changes: 13 additions & 5 deletions src/parser/ParallelParseBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ using std::array;
using std::string;
using std::vector;

namespace ad_utility::detail {

template <typename Parser>
CPP_requires(ParserGetBatchRequires, requires(Parser& p)(p.getBatch()));

template <typename Parser>
CPP_concept ParserGetBatch = CPP_requires_ref(ParserGetBatchRequires, Parser);

} // namespace ad_utility::detail

/**
* A wrapper to make the different Parsers interfaces compatible with the
* parallel pipeline
Expand Down Expand Up @@ -57,11 +67,9 @@ class ParserBatcher {
}
}

// The second requires evaluates to `true` only if the `Parser` type has a
// getBatch() member function. The first requires enables this function only
// if the second "requires" evaluates to true
std::optional<std::vector<TurtleTriple>> getBatch()
requires requires(Parser& p) { p.getBatch(); } {
CPP_member auto getBatch()
-> CPP_ret(std::optional<std::vector<TurtleTriple>>)(
requires ad_utility::detail::ParserGetBatch<Parser>) {
if (m_numTriplesAlreadyParsed >= m_maxNumTriples) {
return std::nullopt;
}
Expand Down
5 changes: 3 additions & 2 deletions src/parser/RdfParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,9 @@ class NQuadParser : public TurtleParser<Tokenizer_T> {
* Parses turtle from std::string. Used to perform unit tests for
* the different parser rules
*/
template <std::derived_from<RdfParserBase> Parser>
class RdfStringParser : public Parser {
CPP_template(typename Parser)(
requires std::derived_from<Parser, RdfParserBase>) class RdfStringParser
: public Parser {
public:
using Parser::getLine;
using Parser::prefixMap_;
Expand Down
1 change: 1 addition & 0 deletions src/parser/TokenizerCtre.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ class TokenizerCtre : public SkipWhitespaceAndCommentsMixin<TokenizerCtre> {
* <true, matchContent> on success and <false, emptyStringView> on failure
*/
struct Matcher {
// TODO<C++17, joka921>: Template-value feature not available in C++17
template <auto& regex>
static std::pair<bool, std::string_view> process(
std::string_view data) noexcept {
Expand Down
40 changes: 27 additions & 13 deletions src/parser/TripleComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@
#include "util/Exception.h"
#include "util/Forward.h"

namespace ad_utility::detail {

template <typename T, typename U>
CPP_requires(MoveAssignableWithRequires, requires(T t, U&& u)(t = u));

template <typename T, typename U>
CPP_concept MoveAssignableWith =
CPP_requires_ref(MoveAssignableWithRequires, T, U);

} // namespace ad_utility::detail

/// A wrapper around a `std::variant` that can hold the different types that the
/// subject, predicate, or object of a triple can have in the Turtle Parser.
/// Those currently are `double` (xsd:double and xsd:decimal), `int64_t`
Expand Down Expand Up @@ -56,10 +67,11 @@ class TripleComponent {
TripleComponent() = default;
/// Construct from anything that is able to construct the underlying
/// `Variant`.
template <typename FirstArg, typename... Args>
requires(!std::same_as<std::remove_cvref_t<FirstArg>, TripleComponent> &&
std::is_constructible_v<Variant, FirstArg &&, Args && ...>)
TripleComponent(FirstArg&& firstArg, Args&&... args)
CPP_template(typename FirstArg, typename... Args)(
requires CPP_NOT(
std::same_as<std::remove_cvref_t<FirstArg>, TripleComponent>) &&
std::is_constructible_v<Variant, FirstArg&&, Args&&...>)
TripleComponent(FirstArg&& firstArg, Args&&... args)
: _variant(AD_FWD(firstArg), AD_FWD(args)...) {
if (isString()) {
// Storing variables and literals as strings is deprecated. The following
Expand All @@ -83,9 +95,9 @@ class TripleComponent {

/// Assignment for types that can be directly assigned to the underlying
/// variant.
template <typename T>
requires requires(Variant v, T&& t) { _variant = t; }
TripleComponent& operator=(T&& value) {
CPP_template(typename T)(requires std::is_assignable_v<Variant, T&&>)
TripleComponent&
operator=(T&& value) {
_variant = AD_FWD(value);
checkThatStringIsValid();
return *this;
Expand All @@ -103,10 +115,11 @@ class TripleComponent {
TripleComponent& operator=(TripleComponent&&) = default;

/// Make a `TripleComponent` directly comparable to the underlying types.
template <typename T>
requires requires(T&& t) { _variant == t; }
bool operator==(const T& other) const {
return _variant == other;
CPP_template(typename T)(
requires ad_utility::SameAsAnyTypeIn<T, Variant>) bool
operator==(const T& other) const {
auto ptr = std::get_if<T>(&_variant);
return ptr && *ptr == other;
}

/// Equality comparison between two `TripleComponent`s.
Expand All @@ -117,8 +130,9 @@ class TripleComponent {
/// overload would also be eligible for the contained types that are
/// implicitly convertible to `TripleComponent` which would lead to strange
/// bugs.
template <typename H>
friend H AbslHashValue(H h, const std::same_as<TripleComponent> auto& tc) {
CPP_template(typename H,
typename TC)(requires std::same_as<TC, TripleComponent>) friend H
AbslHashValue(H h, const TC& tc) {
return H::combine(std::move(h), tc._variant);
}

Expand Down
51 changes: 28 additions & 23 deletions src/parser/sparqlParser/SparqlQleverVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

#include "parser/sparqlParser/SparqlQleverVisitor.h"

#include <absl/strings/str_join.h>
#include <absl/strings/str_split.h>

#include <string>
Expand Down Expand Up @@ -2308,20 +2307,22 @@ ExpressionPtr Visitor::visit([[maybe_unused]] Parser::BuiltInCallContext* ctx) {
using namespace sparqlExpression;
// Create the expression using the matching factory function from
// `NaryExpression.h`.
auto createUnary = [&argList]<typename Function>(Function function)
requires std::is_invocable_r_v<ExpressionPtr, Function, ExpressionPtr> {
auto createUnary = CPP_template_lambda(&argList)(typename F)(F function)(
requires std::is_invocable_r_v<ExpressionPtr, F, ExpressionPtr>) {
AD_CORRECTNESS_CHECK(argList.size() == 1, argList.size());
return function(std::move(argList[0]));
};
auto createBinary = [&argList]<typename Function>(Function function)
requires std::is_invocable_r_v<ExpressionPtr, Function, ExpressionPtr,
ExpressionPtr> {

auto createBinary = CPP_template_lambda(&argList)(typename F)(F function)(
requires std::is_invocable_r_v<ExpressionPtr, F, ExpressionPtr,
ExpressionPtr>) {
AD_CORRECTNESS_CHECK(argList.size() == 2);
return function(std::move(argList[0]), std::move(argList[1]));
};
auto createTernary = [&argList]<typename Function>(Function function)
requires std::is_invocable_r_v<ExpressionPtr, Function, ExpressionPtr,
ExpressionPtr, ExpressionPtr> {

auto createTernary = CPP_template_lambda(&argList)(typename F)(F function)(
requires std::is_invocable_r_v<ExpressionPtr, F, ExpressionPtr,
ExpressionPtr, ExpressionPtr>) {
AD_CORRECTNESS_CHECK(argList.size() == 3);
return function(std::move(argList[0]), std::move(argList[1]),
std::move(argList[2]));
Expand Down Expand Up @@ -2475,9 +2476,11 @@ SparqlExpression::Ptr Visitor::visit(Parser::StrReplaceExpressionContext* ctx) {
reportError(
ctx,
"REPLACE expressions with four arguments (including regex flags) are "
"currently not supported by QLever. You can however incorporate flags "
"currently not supported by QLever. You can however incorporate "
"flags "
"directly into a regex by prepending `(?<flags>)` to your regex. For "
"example `(?i)[ei]` will match the regex `[ei]` in a case-insensitive "
"example `(?i)[ei]` will match the regex `[ei]` in a "
"case-insensitive "
"way.");
}
return sparqlExpression::makeReplaceExpression(std::move(children.at(0)),
Expand Down Expand Up @@ -2535,8 +2538,8 @@ ExpressionPtr Visitor::visit(Parser::AggregateContext* ctx) {
std::string separator;
if (ctx->string()) {
// TODO: The string rule also allow triple quoted strings with different
// escaping rules. These are currently not handled. They should be parsed
// into a typesafe format with a unique representation.
// escaping rules. These are currently not handled. They should be
// parsed into a typesafe format with a unique representation.
separator = visit(ctx->string()).get();
// If there was a separator, we have to strip the quotation marks
AD_CONTRACT_CHECK(separator.size() >= 2);
Expand Down Expand Up @@ -2652,19 +2655,20 @@ GraphTerm Visitor::visit(Parser::BlankNodeContext* ctx) {
}

// ____________________________________________________________________________________
template <typename Ctx>
void Visitor::visitVector(const std::vector<Ctx*>& childContexts)
requires voidWhenVisited<Visitor, Ctx> {
CPP_template_def(typename Ctx)(
requires Visitor::voidWhenVisited<Visitor, Ctx>) void Visitor::
visitVector(const vector<Ctx*>& childContexts) {
for (const auto& child : childContexts) {
visit(child);
}
}

// ____________________________________________________________________________________
template <typename Ctx>
[[nodiscard]] auto Visitor::visitVector(const std::vector<Ctx*>& childContexts)
-> std::vector<decltype(visit(childContexts[0]))>
requires(!voidWhenVisited<Visitor, Ctx>) {
CPP_template_def(typename Ctx)(
requires CPP_NOT(Visitor::voidWhenVisited<Visitor, Ctx>))
[[nodiscard]] auto Visitor::visitVector(
const std::vector<Ctx*>& childContexts)
-> std::vector<decltype(visit(childContexts[0]))> {
std::vector<decltype(visit(childContexts[0]))> children;
for (const auto& child : childContexts) {
children.emplace_back(visit(child));
Expand All @@ -2681,7 +2685,8 @@ Out Visitor::visitAlternative(Contexts*... ctxs) {
(..., visitIf(ctxs));
} else {
std::optional<Out> out;
// Visit the one `context` which is not null and write the result to `out`.
// Visit the one `context` which is not null and write the result to
// `out`.
(..., visitIf<std::optional<Out>, Out>(&out, ctxs));
return std::move(out.value());
}
Expand All @@ -2706,8 +2711,8 @@ void Visitor::visitIf(Target* target, Ctx* ctx) {
}

// _____________________________________________________________________________
template <typename Ctx>
void Visitor::visitIf(Ctx* ctx) requires voidWhenVisited<Visitor, Ctx> {
CPP_template_def(typename Ctx)(requires Visitor::voidWhenVisited<
Visitor, Ctx>) void Visitor::visitIf(Ctx* ctx) {
if (ctx) {
visit(ctx);
}
Expand Down
20 changes: 11 additions & 9 deletions src/parser/sparqlParser/SparqlQleverVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -534,16 +534,18 @@ class SparqlQleverVisitor {
std::array<ExpressionPtr, sizeof...(children)>{std::move(children)...});
}

template <typename Ctx>
void visitVector(const std::vector<Ctx*>& childContexts)
requires voidWhenVisited<SparqlQleverVisitor, Ctx>;
CPP_template(typename Ctx)(
requires SparqlQleverVisitor::voidWhenVisited<
SparqlQleverVisitor, Ctx>) void visitVector(const std::vector<Ctx*>&
childContexts);

// Call `visit` for each of the `childContexts` and return the results of
// those calls as a `vector`.
template <typename Ctx>
auto visitVector(const std::vector<Ctx*>& childContexts)
-> std::vector<decltype(visit(childContexts[0]))>
requires(!voidWhenVisited<SparqlQleverVisitor, Ctx>);
CPP_template(typename Ctx)(requires CPP_NOT(
SparqlQleverVisitor::voidWhenVisited<
SparqlQleverVisitor, Ctx>)) auto visitVector(const std::vector<Ctx*>&
childContexts)
-> std::vector<decltype(visit(childContexts[0]))>;

// Check that exactly one of the `ctxs` is not `null`, visit that context,
// cast the result to `Out` and return it. Requires that for all of the
Expand All @@ -566,8 +568,8 @@ class SparqlQleverVisitor {
template <typename Target, typename Intermediate = Target, typename Ctx>
void visitIf(Target* target, Ctx* ctx);

template <typename Ctx>
void visitIf(Ctx* ctx) requires voidWhenVisited<SparqlQleverVisitor, Ctx>;
CPP_template(typename Ctx)(requires SparqlQleverVisitor::voidWhenVisited<
SparqlQleverVisitor, Ctx>) void visitIf(Ctx* ctx);

public:
[[noreturn]] static void reportError(const antlr4::ParserRuleContext* ctx,
Expand Down
Loading

0 comments on commit ed92968

Please sign in to comment.