Blaze 0.0.1
The ultra high-performance JSON Schema evaluator
Loading...
Searching...
No Matches
compiler.h
1#ifndef SOURCEMETA_BLAZE_COMPILER_COMPILE_H_
2#define SOURCEMETA_BLAZE_COMPILER_COMPILE_H_
3
4#ifndef SOURCEMETA_BLAZE_COMPILER_EXPORT
5#include <sourcemeta/blaze/compiler_export.h>
6#endif
7
8#include <sourcemeta/blaze/compiler_error.h>
9
10#include <sourcemeta/blaze/evaluator.h>
11
12#include <sourcemeta/core/json.h>
13#include <sourcemeta/core/jsonpointer.h>
14#include <sourcemeta/core/jsonschema.h>
15#include <sourcemeta/core/uri.h>
16
17#include <cassert> // assert
18#include <cstddef> // std::size_t
19#include <cstdint> // std::uint8_t, std::uint64_t
20#include <functional> // std::function
21#include <limits> // std::numeric_limits
22#include <map> // std::map
23#include <optional> // std::optional, std::nullopt
24#include <set> // std::set
25#include <string> // std::string
26#include <string_view> // std::string_view
27#include <tuple> // std::tuple
28#include <unordered_map> // std::unordered_map
29#include <unordered_set> // std::unordered_set
30#include <vector> // std::vector
31
35
36namespace sourcemeta::blaze {
37
41 std::set<sourcemeta::core::WeakPointer> static_dependencies;
44 std::set<sourcemeta::core::WeakPointer> dynamic_dependencies;
47 bool unresolved{false};
48};
49
53 std::map<sourcemeta::core::JSON::String, SchemaUnevaluatedEntry>;
54
59 // NOLINTBEGIN(cppcoreguidelines-avoid-const-or-ref-data-members)
61 const sourcemeta::core::WeakPointer &relative_pointer;
63 const sourcemeta::core::JSON &schema;
65 const sourcemeta::core::SchemaVocabularies &vocabularies;
67 const sourcemeta::core::URI &base;
68 // NOLINTEND(cppcoreguidelines-avoid-const-or-ref-data-members)
71};
72
77 // NOLINTBEGIN(cppcoreguidelines-avoid-const-or-ref-data-members)
79 const sourcemeta::core::JSON::String &keyword;
81 const sourcemeta::core::JSON *keyword_value{nullptr};
83 const sourcemeta::core::WeakPointer &base_schema_location;
85 const sourcemeta::core::WeakPointer &base_instance_location;
86 // NOLINTEND(cppcoreguidelines-avoid-const-or-ref-data-members)
87
90 [[nodiscard]] auto value() const -> const sourcemeta::core::JSON & {
91 assert(this->keyword_value != nullptr);
92 return *this->keyword_value;
93 }
94};
95
96#if !defined(DOXYGEN)
97struct Context;
98struct KeywordContext;
99#endif
100
105using Compiler =
106 // TODO(C++23): Use std::move_only_function when available in libc++
107 std::function<Instructions(const KeywordContext &, const Instructions &)>;
108
111enum class Mode : std::uint8_t {
116};
117
123class SOURCEMETA_BLAZE_COMPILER_EXPORT InstructionExtras {
124public:
125 explicit InstructionExtras(const std::uint64_t limit) : limit_{limit} {}
126
128 auto push_back(InstructionExtra &&entry) -> void {
129 if (this->entries_.size() >= this->limit_) [[unlikely]] {
130 throw CompilerInstructionLimitError{this->limit_};
131 }
132
133 this->entries_.push_back(std::move(entry));
134 }
135
136 [[nodiscard]] auto size() const noexcept -> std::size_t {
137 return this->entries_.size();
138 }
139
140 [[nodiscard]] auto operator[](const std::size_t index) const noexcept
141 -> const InstructionExtra & {
142 return this->entries_[index];
143 }
144
145 [[nodiscard]] auto operator[](const std::size_t index) noexcept
146 -> InstructionExtra & {
147 return this->entries_[index];
148 }
149
151 [[nodiscard]] auto release() && -> std::vector<InstructionExtra> {
152 return std::move(this->entries_);
153 }
154
155private:
156// Exporting symbols that depends on the standard C++ library is considered
157// safe.
158// https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-2-c4275?view=msvc-170&redirectedfrom=MSDN
159#if defined(_MSC_VER)
160#pragma warning(disable : 4251 4275)
161#endif
162 std::vector<InstructionExtra> entries_;
163#if defined(_MSC_VER)
164#pragma warning(default : 4251 4275)
165#endif
166 std::uint64_t limit_;
167};
168
171struct Tweaks {
177 std::size_t target_inline_threshold{50};
179 bool format_assertion{false};
183 std::optional<std::unordered_set<sourcemeta::core::JSON::StringView>>
189 std::uint64_t max_instructions{std::numeric_limits<std::uint64_t>::max()};
194 std::uint64_t max_depth{std::numeric_limits<std::uint64_t>::max()};
195};
196
201struct Context {
202 // NOLINTBEGIN(cppcoreguidelines-avoid-const-or-ref-data-members)
204 const sourcemeta::core::JSON &root;
206 const sourcemeta::core::SchemaFrame &frame;
208 const std::vector<std::string> resources;
210 const sourcemeta::core::SchemaWalker &walker;
212 const sourcemeta::core::SchemaResolver &resolver;
216 const Mode mode;
226 const std::map<
227 std::tuple<sourcemeta::core::SchemaReferenceType, std::string_view, bool>,
228 std::pair<std::size_t, const sourcemeta::core::WeakPointer *>>
231 std::uint64_t &depth;
235 std::vector<sourcemeta::core::SchemaVocabularies::URI> &vocabularies;
236 // NOLINTEND(cppcoreguidelines-avoid-const-or-ref-data-members)
237};
238
242const sourcemeta::core::JSON::String EMPTY_KEYWORD;
243
248 // NOLINTBEGIN(cppcoreguidelines-avoid-const-or-ref-data-members)
253 // NOLINTEND(cppcoreguidelines-avoid-const-or-ref-data-members)
257
259 [[nodiscard]] auto keyword() const -> const sourcemeta::core::JSON::String & {
260 return this->target.keyword;
261 }
262
264 [[nodiscard]] auto value() const -> const sourcemeta::core::JSON & {
265 return this->target.value();
266 }
267
269 [[nodiscard]] auto schema() const -> const sourcemeta::core::JSON & {
270 return this->local.schema;
271 }
272
274 [[nodiscard]] auto vocabularies() const
275 -> const sourcemeta::core::SchemaVocabularies & {
276 return this->local.vocabularies;
277 }
278
280 [[nodiscard]] auto base() const -> const sourcemeta::core::URI & {
281 return this->local.base;
282 }
283
285 [[nodiscard]] auto mode() const -> Mode { return this->global.mode; }
286
289 [[nodiscard]] auto relative() const -> KeywordContext {
290 return {
291 .global = this->global,
292 .local = this->local,
293 .target = {.keyword = EMPTY_KEYWORD,
294 .base_schema_location = sourcemeta::core::EMPTY_WEAK_POINTER,
295 .base_instance_location =
296 sourcemeta::core::EMPTY_WEAK_POINTER}};
297 }
298};
299
303auto SOURCEMETA_BLAZE_COMPILER_EXPORT default_schema_compiler(
304 const KeywordContext &, const Instructions &) -> Instructions;
305
336auto SOURCEMETA_BLAZE_COMPILER_EXPORT
337compile(const sourcemeta::core::JSON &schema,
338 const sourcemeta::core::SchemaWalker &walker,
339 const sourcemeta::core::SchemaResolver &resolver,
340 const Compiler &compiler, const Mode mode = Mode::FastValidation,
341 const std::string_view default_dialect = "",
342 const std::string_view default_id = "",
343 const std::string_view entrypoint = "",
344 const std::optional<Tweaks> &tweaks = std::nullopt,
345 std::uint64_t max_locations = std::numeric_limits<std::uint64_t>::max())
346 -> Template;
347
357auto SOURCEMETA_BLAZE_COMPILER_EXPORT compile(
358 const sourcemeta::core::JSON &schema,
359 const sourcemeta::core::SchemaWalker &walker,
360 const sourcemeta::core::SchemaResolver &resolver, const Compiler &compiler,
361 const sourcemeta::core::SchemaFrame &frame,
362 const std::string_view entrypoint, const Mode mode = Mode::FastValidation,
363 const std::optional<Tweaks> &tweaks = std::nullopt) -> Template;
364
373auto SOURCEMETA_BLAZE_COMPILER_EXPORT
374compile(const KeywordContext &context,
375 const sourcemeta::core::WeakPointer &schema_suffix,
376 const sourcemeta::core::WeakPointer &instance_suffix =
377 sourcemeta::core::EMPTY_WEAK_POINTER,
378 std::optional<std::string_view> uri = std::nullopt) -> Instructions;
379
382auto SOURCEMETA_BLAZE_COMPILER_EXPORT to_json(const Template &schema_template)
383 -> sourcemeta::core::JSON;
384
385} // namespace sourcemeta::blaze
386
387#endif
auto relative() const -> KeywordContext
Definition compiler.h:289
auto vocabularies() const -> const sourcemeta::core::SchemaVocabularies &
The vocabularies in force where the keyword is declared.
Definition compiler.h:274
auto value() const -> const sourcemeta::core::JSON &
What the keyword is set to.
Definition compiler.h:264
const Mode mode
The mode of the schema compiler.
Definition compiler.h:216
const sourcemeta::core::JSON * keyword_value
The value of the keyword, null in a context that names none.
Definition compiler.h:81
const Context & global
What holds for the entire compilation.
Definition compiler.h:250
InstructionExtras & extra
Accumulator for instruction extra data during compilation.
Definition compiler.h:233
bool format_assertion
When set, force format to be compiled as an assertion.
Definition compiler.h:179
bool properties_always_unroll
Always unroll properties in a logical AND operation.
Definition compiler.h:173
auto value() const -> const sourcemeta::core::JSON &
Definition compiler.h:90
const sourcemeta::core::WeakPointer & relative_pointer
The schema location relative to the base URI.
Definition compiler.h:61
const sourcemeta::core::WeakPointer & base_schema_location
The schema base keyword path.
Definition compiler.h:83
const sourcemeta::core::SchemaFrame & frame
The reference frame of the entire schema.
Definition compiler.h:206
auto keyword() const -> const sourcemeta::core::JSON::String &
The keyword itself.
Definition compiler.h:259
std::set< sourcemeta::core::WeakPointer > dynamic_dependencies
Definition compiler.h:44
std::vector< sourcemeta::core::SchemaVocabularies::URI > & vocabularies
Accumulator for the vocabularies that instructions refer to.
Definition compiler.h:235
const SchemaUnevaluatedEntries unevaluated
The list of unevaluated entries and their dependencies.
Definition compiler.h:222
const sourcemeta::core::SchemaWalker & walker
The schema walker in use.
Definition compiler.h:210
auto schema() const -> const sourcemeta::core::JSON &
The subschema that declares the keyword.
Definition compiler.h:269
DynamicContext target
Definition compiler.h:256
const sourcemeta::core::JSON & root
The root schema resource.
Definition compiler.h:204
bool properties_reorder
Attempt to re-order properties subschemas to evaluate cheaper ones first.
Definition compiler.h:175
std::uint64_t max_instructions
Definition compiler.h:189
const sourcemeta::core::WeakPointer & base_instance_location
The base instance location that the keyword must be evaluated to.
Definition compiler.h:85
std::size_t target_inline_threshold
Inline jump targets with fewer instructions than this threshold.
Definition compiler.h:177
const sourcemeta::core::SchemaVocabularies & vocabularies
The schema vocabularies in use.
Definition compiler.h:65
const std::map< std::tuple< sourcemeta::core::SchemaReferenceType, std::string_view, bool >, std::pair< std::size_t, const sourcemeta::core::WeakPointer * > > targets
All possible reference targets (key includes is_property_name context).
Definition compiler.h:229
const SchemaContext & local
The subschema that the keyword belongs to.
Definition compiler.h:252
const bool uses_dynamic_scopes
Whether the schema makes use of dynamic scoping.
Definition compiler.h:218
auto release() &&-> std::vector< InstructionExtra >
Hand the accumulated entries over to the template that will own them.
Definition compiler.h:151
const sourcemeta::core::JSON & schema
The current subschema.
Definition compiler.h:63
std::uint64_t & depth
How deep into the schema compilation currently is.
Definition compiler.h:231
const sourcemeta::core::JSON::String & keyword
The schema keyword.
Definition compiler.h:79
const std::vector< std::string > resources
The set of all schema resources in the schema without duplicates.
Definition compiler.h:208
auto push_back(InstructionExtra &&entry) -> void
Make room for another instruction, throwing once out of room.
Definition compiler.h:128
std::uint64_t max_depth
Definition compiler.h:194
auto mode() const -> Mode
The mode the whole schema is being compiled in.
Definition compiler.h:285
const sourcemeta::core::SchemaResolver & resolver
The schema resolver in use.
Definition compiler.h:212
const bool collects_annotations
Whether evaluating the schema may collect at least one annotation.
Definition compiler.h:220
const sourcemeta::core::URI & base
The schema base URI.
Definition compiler.h:67
const Tweaks tweaks
The set of tweaks for the compiler.
Definition compiler.h:224
auto base() const -> const sourcemeta::core::URI &
The base URI of the subschema that declares the keyword.
Definition compiler.h:280
std::optional< std::unordered_set< sourcemeta::core::JSON::StringView > > annotations
Definition compiler.h:184
bool is_property_name
Whether the current schema targets a property name.
Definition compiler.h:70
std::set< sourcemeta::core::WeakPointer > static_dependencies
The absolute pointers of the static keyword dependencies.
Definition compiler.h:41
const Compiler & compiler
The schema compiler in use.
Definition compiler.h:214
bool unresolved
Definition compiler.h:47
Definition compiler.h:123
const sourcemeta::core::JSON::String EMPTY_KEYWORD
Definition compiler.h:242
auto default_schema_compiler(const KeywordContext &, const Instructions &) -> Instructions
std::map< sourcemeta::core::JSON::String, SchemaUnevaluatedEntry > SchemaUnevaluatedEntries
Definition compiler.h:52
auto to_json(const Template &schema_template) -> sourcemeta::core::JSON
std::function< Instructions(const KeywordContext &, const Instructions &)> Compiler
Definition compiler.h:105
Definition compiler.h:201
Definition compiler.h:76
Definition compiler.h:247
Definition compiler.h:58
Definition compiler.h:171
std::vector< Instruction > Instructions
Definition evaluator_instruction.h:282
Mode
Definition compiler.h:111
@ FastValidation
Attempt to get to a boolean result as fast as possible.
Definition compiler.h:113
@ Exhaustive
Perform exhaustive evaluation, including annotations.
Definition compiler.h:115
Definition evaluator_instruction.h:286
Definition evaluator.h:38