#pragma once #include #include #include #include #include #include #include #include #include namespace ovdl::detail { template concept IsFile = requires(T t, const typename T::node_type* node, NodeLocation location) { typename T::node_type; { t.set_location(node, location) } -> std::same_as; { t.location_of(node) } -> std::same_as; }; template concept IsAst = requires( T t, const T ct, const typename T::node_type* node, NodeLocation loc // ) { requires IsFile; typename T::root_node_type; typename T::node_type; requires std::derived_from; { t.set_location(node, loc) } -> std::same_as; { t.location_of(node) } -> std::same_as; { t.root() } -> std::same_as; { ct.root() } -> std::same_as; { t.file() } -> std::same_as; { ct.file() } -> std::same_as; }; template concept IsDiagnosticLogger = requires( T t, const T ct, const char* str, std::size_t length, std::string_view sv, lexy_ext::diagnostic_kind diag_kind // ) { typename T::error_range; typename T::Writer; { static_cast(ct) } -> std::same_as; { ct.errored() } -> std::same_as; { ct.warned() } -> std::same_as; { ct.get_errors() } -> std::same_as; { t.intern(str, length) } -> std::same_as; { t.intern(sv) } -> std::same_as; { t.intern_cstr(str, length) } -> std::same_as; { t.intern_cstr(sv) } -> std::same_as; { t.symbol_interner() } -> std::same_as; { ct.symbol_interner() } -> std::same_as; { t.error(std::declval>()) } -> std::same_as; { t.warning(std::declval>()) } -> std::same_as; { t.note(std::declval>()) } -> std::same_as; { t.info(std::declval>()) } -> std::same_as; { t.debug(std::declval>()) } -> std::same_as; { t.fixit(std::declval>()) } -> std::same_as; { t.help(std::declval>()) } -> std::same_as; { t.error(sv) } -> std::same_as; { t.warning(sv) } -> std::same_as; { t.note(sv) } -> std::same_as; { t.info(sv) } -> std::same_as; { t.debug(sv) } -> std::same_as; { t.fixit(sv) } -> std::same_as; { t.help(sv) } -> std::same_as; { std::move(t.error_callback().sink()).finish() } -> std::same_as; { t.log(diag_kind, std::declval>()) } -> std::same_as; }; template concept IsParseState = requires( T t, const T ct, typename T::ast_type::file_type&& file, lexy::buffer&& buffer, ovdl::detail::Encoding encoding, const char* path // ) { requires IsAst; requires IsDiagnosticLogger; { T { std::move(file), encoding } } -> std::same_as; { T { std::move(buffer), encoding } } -> std::same_as; { T { path, std::move(buffer), encoding } } -> std::same_as; { t.ast() } -> std::same_as; { ct.ast() } -> std::same_as; { t.logger() } -> std::same_as; { ct.logger() } -> std::same_as; }; template concept IsFileParseState = requires( T t, const T ct, typename T::file_type&& file, lexy::buffer&& buffer, ovdl::detail::Encoding encoding, const char* path // ) { requires IsFile; requires IsDiagnosticLogger; { T { std::move(file), encoding } } -> std::same_as; { T { std::move(buffer), encoding } } -> std::same_as; { T { path, std::move(buffer), encoding } } -> std::same_as; { t.file() } -> std::same_as; { ct.file() } -> std::same_as; { t.logger() } -> std::same_as; { ct.logger() } -> std::same_as; }; template concept IsStateType = IsParseState || IsFileParseState; }