Skip to content
Draft
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
16 changes: 12 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,6 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "C++ ISO Standard version")
if (CMAKE_CXX_STANDARD LESS 20)
message(FATAL_ERROR "C++ 2020 ISO Standard or higher is required to build SeQuant")
endif ()
# C++20 is only configurable via compile features with cmake 3.12 and older
if (CMAKE_CXX_STANDARD EQUAL 20 AND CMAKE_VERSION VERSION_LESS 3.12.0)
cmake_minimum_required(VERSION 3.12.0)
endif ()
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "Whether to use extensions of C++ ISO Standard version")

Expand Down Expand Up @@ -248,6 +244,9 @@ include(FindOrFetchUtfcpp)
# Eigen
include(FindOrFetchEigen)

# cpp-peglib
include(FindOrFetchCppPeglib)

# embedded bliss-0.73
add_library(SeQuant-bliss
SeQuant/external/bliss/defs.cc
Expand Down Expand Up @@ -341,8 +340,16 @@ set(SeQuant_symb_src
SeQuant/core/io/serialization/v1/ast.hpp
SeQuant/core/io/serialization/v1/ast_conversions.hpp
SeQuant/core/io/serialization/v1/deserialize.cpp
SeQuant/core/io/serialization/v1/error.cpp
SeQuant/core/io/serialization/v1/error.hpp
SeQuant/core/io/serialization/v1/semantic_actions.hpp
SeQuant/core/io/serialization/v1/serialize.cpp
SeQuant/core/io/serialization/v2/ast_conversions.cpp
SeQuant/core/io/serialization/v2/ast_conversions.hpp
SeQuant/core/io/serialization/v2/deserialize.cpp
SeQuant/core/io/serialization/v2/error.cpp
SeQuant/core/io/serialization/v2/error.hpp
SeQuant/core/io/serialization/v2/serialize.cpp
SeQuant/core/ranges.hpp
SeQuant/core/rational.hpp
SeQuant/core/runtime.cpp
Expand Down Expand Up @@ -570,6 +577,7 @@ target_link_libraries(SeQuant-symb
Threads::Threads
libperm::libperm
$<BUILD_LOCAL_INTERFACE:utfcpp>
$<BUILD_LOCAL_INTERFACE:peglib>
Eigen3::Eigen)
if (Boost_IS_MODULARIZED)
target_link_libraries(SeQuant-symb PUBLIC
Expand Down
108 changes: 91 additions & 17 deletions SeQuant/core/io/serialization/serialization.cpp
Original file line number Diff line number Diff line change
@@ -1,41 +1,115 @@
#include <SeQuant/core/expr.hpp>
#include <SeQuant/core/io/serialization/serialization.hpp>
#include <SeQuant/core/utility/exception.hpp>
#include <SeQuant/core/utility/macros.hpp>

#include <concepts>
#include <string_view>

namespace sequant::io::serialization {

SerializationError::SerializationError(std::size_t offset, std::size_t length,
std::string message)
: Exception(std::move(message)), offset(offset), length(length) {}
SerializationError::SerializationError(std::string message)
: Exception(std::move(message)) {}

#define SEQUANT_RESOLVE_DESERIALIZATION_FUNC(stringType, ExprType) \
template <typename StringType, typename ExprType>
concept v1_can_deserialize = requires(StringType input) {
serialization::v1::from_string<ExprType>(input);
};

template <typename StringType, typename ExprType>
concept v2_can_deserialize =
requires(StringType input, DeserializationOptions opts) {
serialization::v2::from_string<ExprType>(input);
};

static_assert(!v2_can_deserialize<std::string, ExprPtr>);

template <typename StringType, typename ExprType>
ExprType from_string_indirection(StringType input,
const DeserializationOptions &options) {
// Note: We need this indirection as the if constexpr construct only works (in
// the way we need) if the condition depends on a template parameter. If it
// didn't, we'd get a bunch of "call to deleted function" errors as the body
// of the if is checked even though the if is false.
switch (options.syntax) {
case SerializationSyntax::V1:
if constexpr (v1_can_deserialize<StringType, ExprType>) {
return serialization::v1::from_string<ExprType>(input, options);
} else {
throw Exception(
"Deserialization of this type is not supported with syntax V1");
}
case SerializationSyntax::V2:
if constexpr (v2_can_deserialize<StringType, ExprType>) {
return serialization::v2::from_string<ExprType>(input, options);
} else {
throw Exception(
"Deserialization of this type is not supported with syntax V2");
}
}

SEQUANT_UNREACHABLE;
}

#define SEQUANT_RESOLVE_DESERIALIZATION_FUNC(StringType, ExprType) \
template <> \
ExprType from_string<ExprType>(stringType input, \
ExprType from_string<ExprType>(StringType input, \
const DeserializationOptions &options) { \
switch (options.syntax) { \
case SerializationSyntax::V1: \
return serialization::v1::from_string<ExprType>(input, options); \
} \
\
SEQUANT_UNREACHABLE; \
return from_string_indirection<StringType, ExprType>(input, options); \
}

SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::wstring_view, ExprPtr)
SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::string_view, ExprPtr)
SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::wstring_view, ResultExpr)
SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::string_view, ResultExpr)
SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::string_view, Constant);
SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::wstring_view, Constant);
SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::string_view, Variable);
SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::wstring_view, Variable);
SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::string_view, Tensor);
SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::wstring_view, Tensor);
SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::string_view, Product);
SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::wstring_view, Product);
SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::string_view, Sum);
SEQUANT_RESOLVE_DESERIALIZATION_FUNC(std::wstring_view, Sum);

template <typename ExprType>
concept v1_can_serialize = requires(const ExprType &expr) {
{ serialization::v1::to_string(expr) } -> std::convertible_to<std::wstring>;
};

template <typename ExprType>
concept v2_can_serialize = requires(const ExprType &expr) {
{ serialization::v2::to_string(expr) } -> std::convertible_to<std::wstring>;
};

template <typename Arg>
std::wstring to_string_indirection(const Arg &arg,
const SerializationOptions &options) {
switch (options.syntax) {
case SerializationSyntax::V1:
if constexpr (v1_can_serialize<Arg>) {
return serialization::v1::to_string(arg, options);
} else {
throw Exception(
"Serialization of this type is not supported with syntax V1");
}
case SerializationSyntax::V2:
if constexpr (v2_can_serialize<Arg>) {
return serialization::v2::to_string(arg, options);
} else {
throw Exception(
"Serialization of this type is not supported with syntax V2");
}
}

SEQUANT_UNREACHABLE;
}

#define SEQUANT_RESOLVE_SERIALIZE_FUNC(argType) \
std::wstring to_string(const argType &arg, \
const SerializationOptions &options) { \
switch (options.syntax) { \
case SerializationSyntax::V1: \
return serialization::v1::to_string(arg, options); \
} \
\
SEQUANT_UNREACHABLE; \
return to_string_indirection<argType>(arg, options); \
}

SEQUANT_RESOLVE_SERIALIZE_FUNC(ResultExpr)
Expand Down
29 changes: 24 additions & 5 deletions SeQuant/core/io/serialization/serialization.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@
namespace sequant::io::serialization {

struct SerializationError : Exception {
std::size_t offset;
std::size_t length;

SerializationError(std::size_t offset, std::size_t length,
std::string message);
SerializationError(std::string message);
};

/// Specifies the syntax of the textual input/representation to use. All
Expand All @@ -32,6 +28,7 @@ struct SerializationError : Exception {
/// and support for it may be removed in future versions.
enum class SerializationSyntax {
V1,
V2,

Latest = V1
};
Expand Down Expand Up @@ -83,6 +80,11 @@ SEQUANT_DECLARE_DESERIALIZATION_FUNC;

SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(ExprPtr);
SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(ResultExpr);
SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(Constant);
SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(Variable);
SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(Tensor);
SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(Product);
SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(Sum);

#define SEQUANT_DECLARE_SERIALIZATION_FUNC \
std::wstring to_string(const ResultExpr &expr, \
Expand Down Expand Up @@ -125,6 +127,23 @@ SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(ResultExpr);
SEQUANT_DECLARE_SERIALIZATION_FUNC
} // namespace v1

namespace v2 {
SEQUANT_DECLARE_DESERIALIZATION_FUNC;

// SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(ExprPtr);
// SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(ResultExpr);
SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(Constant);
// SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(Variable);
// SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(Tensor);
// SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(Product);
// SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION(Sum);

// Dummy
inline void to_string() {}

// SEQUANT_DECLARE_SERIALIZATION_FUNC
} // namespace v2

#undef SEQUANT_DECLARE_DESERIALIZATION_FUNC
#undef SEQUANT_DECLARE_DESERIALIZATION_FUNC_SPECIALIZATION
#undef SEQUANT_DECLARE_SERIALIZATION_FUNC
Expand Down
6 changes: 3 additions & 3 deletions SeQuant/core/io/serialization/v1/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Created by Robert Adam on 2023-09-21
//

#ifndef SEQUANT_CORE_PARSE_V1_AST_HPP
#define SEQUANT_CORE_PARSE_V1_AST_HPP
#ifndef SEQUANT_CORE_IO_SERIALIZATION_V1_AST_HPP
#define SEQUANT_CORE_IO_SERIALIZATION_V1_AST_HPP

#define BOOST_SPIRIT_X3_UNICODE
#include <boost/fusion/include/adapt_struct.hpp>
Expand Down Expand Up @@ -154,4 +154,4 @@ BOOST_FUSION_ADAPT_STRUCT(sequant::io::serialization::v1::ast::Sum, summands);
BOOST_FUSION_ADAPT_STRUCT(sequant::io::serialization::v1::ast::ResultExpr, lhs,
rhs);

#endif // SEQUANT_CORE_PARSE_AST_V1_HPP
#endif // SEQUANT_CORE_IO_SERIALIZATION_V1_AST_HPP
50 changes: 23 additions & 27 deletions SeQuant/core/io/serialization/v1/ast_conversions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
// Created by Robert Adam on 2023-09-22
//

#ifndef SEQUANT_CORE_PARSE_AST_CONVERSIONS_HPP
#define SEQUANT_CORE_PARSE_AST_CONVERSIONS_HPP
#ifndef SEQUANT_CORE_IO_SERIALIZATION_V1_AST_CONVERSIONS_HPP
#define SEQUANT_CORE_IO_SERIALIZATION_V1_AST_CONVERSIONS_HPP

#include <SeQuant/core/container.hpp>
#include <SeQuant/core/expr.hpp>
#include <SeQuant/core/index.hpp>
#include <SeQuant/core/io/serialization/v1/ast.hpp>
#include <SeQuant/core/io/serialization/v1/error.hpp>
#include <SeQuant/core/op.hpp>
#include <SeQuant/core/space.hpp>
#include <SeQuant/core/utility/macros.hpp>
Expand Down Expand Up @@ -49,15 +50,14 @@ Index to_index(const io::serialization::v1::ast::Index &index,
protoIndices.push_back(Index(std::move(label), std::move(space)));
} catch (const IndexSpace::bad_key &) {
auto [offset, length] = get_pos(current, position_cache, begin);
throw SerializationError(offset, length,
"Unknown index space '" + toUtf8(current.label) +
"' in proto index specification");
throw Error(offset, length,
"Unknown index space '" + toUtf8(current.label) +
"' in proto index specification");
} catch (const Exception &e) {
auto [offset, length] = get_pos(current, position_cache, begin);
throw SerializationError(offset, length,
"Invalid index '" + toUtf8(current.label) + "_" +
std::to_string(current.id) + ": " +
e.what());
throw Error(offset, length,
"Invalid index '" + toUtf8(current.label) + "_" +
std::to_string(current.id) + ": " + e.what());
}
}

Expand All @@ -67,16 +67,14 @@ Index to_index(const io::serialization::v1::ast::Index &index,
return Index(std::move(space), index.label.id, std::move(protoIndices));
} catch (const IndexSpace::bad_key &e) {
auto [offset, length] = get_pos(index.label, position_cache, begin);
throw SerializationError(offset, length,
"Unknown index space '" +
toUtf8(index.label.label) +
"' in index specification");
throw Error(offset, length,
"Unknown index space '" + toUtf8(index.label.label) +
"' in index specification");
} catch (const Exception &e) {
auto [offset, length] = get_pos(index.label, position_cache, begin);
throw SerializationError(offset, length,
"Invalid index '" + toUtf8(index.label.label) +
"_" + std::to_string(index.label.id) + ": " +
e.what());
throw Error(offset, length,
"Invalid index '" + toUtf8(index.label.label) + "_" +
std::to_string(index.label.id) + ": " + e.what());
}
}

Expand Down Expand Up @@ -136,8 +134,7 @@ Symmetry to_perm_symmetry(char c, std::size_t offset, const Iterator &,
return Symmetry::Nonsymm;
}

throw SerializationError(
offset, 1, std::string("Invalid symmetry specifier '") + c + "'");
throw Error(offset, 1, std::string("Invalid symmetry specifier '") + c + "'");
}

template <typename Iterator>
Expand All @@ -159,8 +156,8 @@ BraKetSymmetry to_braket_symmetry(char c, std::size_t offset, const Iterator &,
return BraKetSymmetry::Nonsymm;
}

throw SerializationError(
offset, 1, std::string("Invalid BraKet symmetry specifier '") + c + "'");
throw Error(offset, 1,
std::string("Invalid BraKet symmetry specifier '") + c + "'");
}

template <typename Iterator>
Expand All @@ -179,9 +176,8 @@ ColumnSymmetry to_column_symmetry(char c, std::size_t offset, const Iterator &,
return ColumnSymmetry::Nonsymm;
}

throw SerializationError(
offset, 1,
std::string("Invalid particle symmetry specifier '") + c + "'");
throw Error(offset, 1,
std::string("Invalid particle symmetry specifier '") + c + "'");
}

template <typename PositionCache, typename Iterator>
Expand Down Expand Up @@ -412,11 +408,11 @@ ResultExpr ast_to_result(const io::serialization::v1::ast::ResultExpr &result,
return {std::move(lhs.as<Variable>()), std::move(rhs)};
} else {
auto [offset, length] = get_pos(result.lhs, position_cache, begin);
throw SerializationError(
offset, length, "LHS of a ResultExpr must be a Tensor or a Variable");
throw Error(offset, length,
"LHS of a ResultExpr must be a Tensor or a Variable");
}
}

} // namespace sequant::io::serialization::v1::transform

#endif // SEQUANT_CORE_PARSE_AST_CONVERSIONS_HPP
#endif // SEQUANT_CORE_IO_SERIALIZATION_V1_AST_CONVERSIONS_HPP
Loading