aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-dataloader/detail/InternalConcepts.hpp
blob: 0c7913d28862299aa4c24ffce4cbf8e138b32b53 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#pragma once

#include <concepts>
#include <utility>

#include <openvic-dataloader/NodeLocation.hpp>
#include <openvic-dataloader/detail/Encoding.hpp>
#include <openvic-dataloader/detail/SymbolIntern.hpp>

#include <lexy/encoding.hpp>
#include <lexy/input/buffer.hpp>

#include <fmt/core.h>

#include <lexy_ext/report_error.hpp>

namespace ovdl::detail {
   template<typename T>
   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<void>;
         { t.location_of(node) } -> std::same_as<NodeLocation>;
      };

   template<typename T>
   concept IsAst =
      requires(
         T t,
         const T ct,
         const typename T::node_type* node,
         NodeLocation loc //
      ) {
         requires IsFile<typename T::file_type>;
         typename T::root_node_type;
         typename T::node_type;
         requires std::derived_from<typename T::root_node_type, typename T::node_type>;
         { t.set_location(node, loc) } -> std::same_as<void>;
         { t.location_of(node) } -> std::same_as<NodeLocation>;
         { t.root() } -> std::same_as<typename T::root_node_type*>;
         { ct.root() } -> std::same_as<const typename T::root_node_type*>;
         { t.file() } -> std::same_as<typename T::file_type&>;
         { ct.file() } -> std::same_as<const typename T::file_type&>;
      };

   template<typename T>
   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<bool>(ct) } -> std::same_as<bool>;
      { ct.errored() } -> std::same_as<bool>;
      { ct.warned() } -> std::same_as<bool>;
      { ct.get_errors() } -> std::same_as<typename T::error_range>;
      { t.intern(str, length) } -> std::same_as<ovdl::SymbolIntern::symbol_type>;
      { t.intern(sv) } -> std::same_as<ovdl::SymbolIntern::symbol_type>;
      { t.intern_cstr(str, length) } -> std::same_as<const char*>;
      { t.intern_cstr(sv) } -> std::same_as<const char*>;
      { t.symbol_interner() } -> std::same_as<SymbolIntern::symbol_interner_type&>;
      { ct.symbol_interner() } -> std::same_as<const SymbolIntern::symbol_interner_type&>;
      { t.error(std::declval<typename T::template format_str<>>()) } -> std::same_as<typename T::Writer>;
      { t.warning(std::declval<typename T::template format_str<>>()) } -> std::same_as<typename T::Writer>;
      { t.note(std::declval<typename T::template format_str<>>()) } -> std::same_as<typename T::Writer>;
      { t.info(std::declval<typename T::template format_str<>>()) } -> std::same_as<typename T::Writer>;
      { t.debug(std::declval<typename T::template format_str<>>()) } -> std::same_as<typename T::Writer>;
      { t.fixit(std::declval<typename T::template format_str<>>()) } -> std::same_as<typename T::Writer>;
      { t.help(std::declval<typename T::template format_str<>>()) } -> std::same_as<typename T::Writer>;
      { t.error(sv) } -> std::same_as<typename T::Writer>;
      { t.warning(sv) } -> std::same_as<typename T::Writer>;
      { t.note(sv) } -> std::same_as<typename T::Writer>;
      { t.info(sv) } -> std::same_as<typename T::Writer>;
      { t.debug(sv) } -> std::same_as<typename T::Writer>;
      { t.fixit(sv) } -> std::same_as<typename T::Writer>;
      { t.help(sv) } -> std::same_as<typename T::Writer>;
      { std::move(t.error_callback().sink()).finish() } -> std::same_as<std::size_t>;
      { t.log(diag_kind, std::declval<typename T::template format_str<>>()) } -> std::same_as<typename T::Writer>;
   };

   template<typename T>
   concept IsParseState = requires(
      T t,
      const T ct,
      typename T::ast_type::file_type&& file,
      lexy::buffer<lexy::default_encoding>&& buffer,
      ovdl::detail::Encoding encoding,
      const char* path //
   ) {
      requires IsAst<typename T::ast_type>;
      requires IsDiagnosticLogger<typename T::diagnostic_logger_type>;
      { T { std::move(file), encoding } } -> std::same_as<T>;
      { T { std::move(buffer), encoding } } -> std::same_as<T>;
      { T { path, std::move(buffer), encoding } } -> std::same_as<T>;
      { t.ast() } -> std::same_as<typename T::ast_type&>;
      { ct.ast() } -> std::same_as<const typename T::ast_type&>;
      { t.logger() } -> std::same_as<typename T::diagnostic_logger_type&>;
      { ct.logger() } -> std::same_as<const typename T::diagnostic_logger_type&>;
   };

   template<typename T>
   concept IsFileParseState = requires(
      T t,
      const T ct,
      typename T::file_type&& file,
      lexy::buffer<lexy::default_encoding>&& buffer,
      ovdl::detail::Encoding encoding,
      const char* path //
   ) {
      requires IsFile<typename T::file_type>;
      requires IsDiagnosticLogger<typename T::diagnostic_logger_type>;
      { T { std::move(file), encoding } } -> std::same_as<T>;
      { T { std::move(buffer), encoding } } -> std::same_as<T>;
      { T { path, std::move(buffer), encoding } } -> std::same_as<T>;
      { t.file() } -> std::same_as<typename T::file_type&>;
      { ct.file() } -> std::same_as<const typename T::file_type&>;
      { t.logger() } -> std::same_as<typename T::diagnostic_logger_type&>;
      { ct.logger() } -> std::same_as<const typename T::diagnostic_logger_type&>;
   };

   template<typename T>
   concept IsStateType = IsParseState<T> || IsFileParseState<T>;
}