1#ifndef SOURCEMETA_BLAZE_EVALUATOR_DISPATCH_H_
2#define SOURCEMETA_BLAZE_EVALUATOR_DISPATCH_H_
5#include <sourcemeta/blaze/evaluator.h>
7#include <sourcemeta/core/crypto.h>
8#include <sourcemeta/core/css.h>
9#include <sourcemeta/core/dns.h>
10#include <sourcemeta/core/email.h>
11#include <sourcemeta/core/ip.h>
12#include <sourcemeta/core/regex.h>
13#include <sourcemeta/core/time.h>
14#include <sourcemeta/core/uritemplate.h>
21#define SOURCEMETA_ASSUME(x) \
25#define SOURCEMETA_ASSUME(x) assert(x)
28#define SOURCEMETA_STRINGIFY(x) #x
30#define EVALUATE_PUSH() \
31 if constexpr (Track) { \
32 context.evaluator->evaluate_path.push_back( \
33 context.schema->extra[instruction.extra_index] \
34 .relative_schema_location); \
36 if constexpr (HasCallback) { \
37 context.evaluator->instance_location.push_back( \
38 instruction.relative_instance_location); \
40 if constexpr (Dynamic) { \
41 context.evaluator->resources.push_back( \
42 context.schema->extra[instruction.extra_index].schema_resource); \
44 if constexpr (HasCallback) { \
45 (*context.callback)(EvaluationType::Pre, true, instruction, \
46 context.schema->extra[instruction.extra_index], \
47 context.evaluator->evaluate_path, \
48 context.evaluator->instance_location, \
49 Evaluator::NULL_VALUE); \
52#define EVALUATE_POP() \
53 if constexpr (HasCallback) { \
54 (*context.callback)(EvaluationType::Post, result, instruction, \
55 context.schema->extra[instruction.extra_index], \
56 context.evaluator->evaluate_path, \
57 context.evaluator->instance_location, \
58 Evaluator::NULL_VALUE); \
60 if constexpr (Track) { \
61 context.evaluator->evaluate_path.pop_back( \
62 context.schema->extra[instruction.extra_index] \
63 .relative_schema_location.size()); \
65 if constexpr (HasCallback) { \
66 context.evaluator->instance_location.pop_back( \
67 instruction.relative_instance_location.size()); \
69 if constexpr (Dynamic) { \
70 context.evaluator->resources.pop_back(); \
73#define EVALUATE_BEGIN(instruction_type, precondition) \
74 assert(instruction.type == InstructionIndex::instruction_type); \
75 const auto &target{resolve_target( \
76 context.property_target, \
77 resolve_instance(instance, instruction.relative_instance_location))}; \
78 if (!(precondition)) [[unlikely]] { \
81 [[maybe_unused]] constexpr bool track{Track || HasCallback}; \
85#define EVALUATE_BEGIN_NON_STRING(instruction_type, precondition) \
86 assert(instruction.type == InstructionIndex::instruction_type); \
88 resolve_instance(instance, instruction.relative_instance_location)}; \
89 if (!(precondition)) [[unlikely]] { \
92 [[maybe_unused]] constexpr bool track{Track || HasCallback}; \
96#define EVALUATE_BEGIN_IF_STRING(instruction_type) \
97 assert(instruction.type == InstructionIndex::instruction_type); \
98 const auto *maybe_target{ \
99 resolve_string_target(context.property_target, instance, \
100 instruction.relative_instance_location)}; \
101 if (!maybe_target) [[unlikely]] { \
105 const auto &target{*maybe_target}; \
108#define EVALUATE_BEGIN_TRY_TARGET(instruction_type) \
109 assert(instruction.type == InstructionIndex::instruction_type); \
110 const auto &target{instance}; \
111 if (!target.is_object()) [[unlikely]] { \
114 assert(!instruction.relative_instance_location.empty()); \
115 const auto *target_check{ \
116 instruction.relative_instance_location.size() == 1 \
118 instruction.relative_instance_location.at(0).to_property(), \
119 instruction.relative_instance_location.at(0).property_hash()) \
120 : try_get(target, instruction.relative_instance_location)}; \
121 if (!target_check) [[unlikely]] { \
127#define EVALUATE_BEGIN_NO_PRECONDITION(instruction_type) \
128 assert(instruction.type == InstructionIndex::instruction_type); \
129 [[maybe_unused]] constexpr bool track{Track || HasCallback}; \
133#define EVALUATE_BEGIN_NO_PRECONDITION_AND_NO_PUSH(instruction_type) \
134 assert(instruction.type == InstructionIndex::instruction_type); \
135 if constexpr (HasCallback) { \
136 (*context.callback)(EvaluationType::Pre, true, instruction, \
137 context.schema->extra[instruction.extra_index], \
138 context.evaluator->evaluate_path, \
139 context.evaluator->instance_location, \
140 Evaluator::NULL_VALUE); \
144#define EVALUATE_BEGIN_PASS_THROUGH(instruction_type) \
145 assert(instruction.type == InstructionIndex::instruction_type); \
148#define EVALUATE_END(instruction_type) \
152#define EVALUATE_END_NO_POP(instruction_type) \
153 if constexpr (HasCallback) { \
154 (*context.callback)(EvaluationType::Post, result, instruction, \
155 context.schema->extra[instruction.extra_index], \
156 context.evaluator->evaluate_path, \
157 context.evaluator->instance_location, \
158 Evaluator::NULL_VALUE); \
162#define EVALUATE_END_PASS_THROUGH(instruction_type) return result;
164#define EVALUATE_ANNOTATION(instruction_type, destination, annotation_value) \
165 if constexpr (HasCallback) { \
166 context.evaluator->evaluate_path.push_back( \
167 context.schema->extra[instruction.extra_index] \
168 .relative_schema_location); \
169 context.evaluator->instance_location.push_back( \
170 instruction.relative_instance_location); \
171 const auto &reported_location{destination}; \
172 (*context.callback)(EvaluationType::Pre, true, instruction, \
173 context.schema->extra[instruction.extra_index], \
174 context.evaluator->evaluate_path, reported_location, \
175 Evaluator::NULL_VALUE); \
176 (*context.callback)(EvaluationType::Post, true, instruction, \
177 context.schema->extra[instruction.extra_index], \
178 context.evaluator->evaluate_path, reported_location, \
180 context.evaluator->evaluate_path.pop_back( \
181 context.schema->extra[instruction.extra_index] \
182 .relative_schema_location.size()); \
183 context.evaluator->instance_location.pop_back( \
184 instruction.relative_instance_location.size()); \
188#define EVALUATE_RECURSE(child, target) \
189 evaluate_instruction(child, target, depth + 1, context)
190#define EVALUATE_RECURSE_ON_PROPERTY_NAME(child, target, name) \
191 evaluate_instruction_with_property(child, target, depth + 1, context, name)
193namespace sourcemeta::blaze::dispatch {
194using namespace sourcemeta::core;
197constexpr auto DEPTH_LIMIT{300};
199inline auto resolve_target(
const JSON::String *property_target,
200 const JSON &instance)
noexcept ->
const JSON & {
201 if (property_target !=
nullptr) [[unlikely]] {
202 return Evaluator::EMPTY_STRING;
209inline auto resolve_instance(
const JSON &instance,
210 const Pointer &relative_instance_location)
212 if (relative_instance_location.empty()) {
220 if (relative_instance_location.size() == 1 &&
221 relative_instance_location.at(0).is_property()) {
222 return instance.at(relative_instance_location.at(0).to_property(),
223 relative_instance_location.at(0).property_hash());
226 return get(instance, relative_instance_location);
230resolve_string_target(
const JSON::String *property_target,
const JSON &instance,
231 const Pointer &relative_instance_location)
noexcept
232 ->
const JSON::String * {
233 if (property_target !=
nullptr) [[unlikely]] {
234 return property_target;
237 const auto &target{resolve_instance(instance, relative_instance_location)};
238 if (!target.is_string()) [[unlikely]] {
241 return &target.to_string();
246 const JSON::String &name,
247 const JSON::Object::hash_type &name_hash)
noexcept
251 std::size_t first{1};
252 std::size_t last{indexes.first.size()};
253 if (!indexes.second.empty()) {
256 if (name.size() >= indexes.second.size()) {
260 const auto &bounds{indexes.second[name.size()]};
261 if (bounds.second == 0) {
265 first = bounds.first;
266 last = bounds.second;
273 constexpr sourcemeta::core::PropertyHashJSON<JSON::String> HASHER{};
274 if (HASHER.is_perfect(name_hash)) {
275 for (
auto position = first; position <= last; position++) {
276 const auto &entry{indexes.first[position - 1]};
277 if (std::get<0>(entry) == name_hash) {
278 return &std::get<1>(entry);
282 for (
auto position = first; position <= last; position++) {
283 const auto &entry{indexes.first[position - 1]};
284 if (std::get<0>(entry) == name_hash && std::get<2>(entry) == name) {
285 return &std::get<1>(entry);
297inline auto type_set_test(
const ValueTypes &types,
298 const JSON::Type type)
noexcept ->
bool {
299 assert(std::to_underlying(type) < types.size());
300 return types[std::to_underlying(type)];
303inline auto effective_type_strict_real(
const JSON &instance)
noexcept
305 const auto real_type{instance.type()};
307 case JSON::Type::Decimal:
308 return instance.to_decimal().is_integer() ? JSON::Type::Integer
326inline auto type_set_spans_numbers(
const ValueTypes &types)
noexcept ->
bool {
327 const auto integer{types[std::to_underlying(JSON::Type::Integer)]};
328 return types[std::to_underlying(JSON::Type::Real)] == integer &&
329 types[std::to_underlying(JSON::Type::Decimal)] == integer;
332template <
bool Normalise>
333inline auto type_in_set(
const JSON &instance,
const ValueTypes &types)
noexcept
335 if constexpr (Normalise) {
336 return type_set_test(types, effective_type_strict_real(instance));
338 return type_set_test(types, instance.type());
342template <
bool Normalise>
343inline auto array_items_in_type_set(
const JSON &target,
345 for (
const auto &entry : target.as_array()) {
346 if (!type_in_set<Normalise>(entry, types)) [[unlikely]] {
354template <
bool Normalise>
355inline auto object_values_in_type_set(
const JSON &target,
358 for (
const auto &entry : target.as_object()) {
359 if (!type_in_set<Normalise>(entry.second, types)) [[unlikely]] {
367template <
bool Normalise>
368inline auto items_are_bounded_arrays_in_type_set(
369 const JSON &target,
const ValueTypes &types,
const std::size_t minimum,
370 const std::optional<std::size_t> &maximum)
noexcept ->
bool {
371 for (
const auto &item : target.as_array()) {
372 if (item.type() != JSON::Type::Array || item.array_size() < minimum ||
373 (maximum.has_value() && item.array_size() > maximum.value()))
378 if (!array_items_in_type_set<Normalise>(item, types)) [[unlikely]] {
386inline auto as_decimal(
const JSON &instance) -> Decimal {
387 assert(instance.is_integral());
388 return instance.is_decimal() ? instance.to_decimal()
389 : Decimal::exact_from(instance.to_real());
392inline auto integer_within_bounds(
const JSON &target,
394 if (target.is_integer()) {
395 const auto integer{target.to_integer()};
396 return integer >= value.first && integer <= value.second;
399 if (target.is_integral()) {
400 const auto decimal{as_decimal(target)};
401 return decimal >= Decimal{value.first} && decimal <= Decimal{value.second};
408inline auto assume_value(
const Value &variant)
noexcept ->
const T & {
409 const auto *pointer{std::get_if<T>(&variant)};
410 SOURCEMETA_ASSUME(pointer !=
nullptr);
415inline auto assume_value_copy(
const Value &variant)
noexcept -> T {
416 const auto *pointer{std::get_if<T>(&variant)};
417 SOURCEMETA_ASSUME(pointer !=
nullptr);
425 const sourcemeta::core::JSON::String *property_target;
428template <
bool Track,
bool Dynamic,
bool HasCallback>
431 const sourcemeta::core::JSON &instance,
432 const std::uint64_t depth,
436template <
bool Track,
bool Dynamic,
bool HasCallback>
437inline auto evaluate_instruction_with_property(
439 const sourcemeta::core::JSON &instance,
const std::uint64_t depth,
441 const sourcemeta::core::JSON::String &name) -> bool;
443#define INSTRUCTION_HANDLER(name) \
444 template <bool Track, bool Dynamic, bool HasCallback> \
445 static inline auto name( \
446 [[maybe_unused]] const sourcemeta::blaze::Instruction &instruction, \
447 [[maybe_unused]] const sourcemeta::core::JSON &instance, \
448 [[maybe_unused]] const std::uint64_t depth, \
449 [[maybe_unused]] DispatchContext<Track, Dynamic, HasCallback> &context) \
452#define INSTRUCTION_DIRECT(name, value_type) \
453 SOURCEMETA_FORCEINLINE inline auto DIRECT_##name( \
454 const sourcemeta::core::JSON &target, const value_type &value) \
457#define INSTRUCTION_DIRECT_COPY(name, value_type) \
458 SOURCEMETA_FORCEINLINE inline auto DIRECT_##name( \
459 const sourcemeta::core::JSON &target, const value_type value) \
462#define DIRECT(name, target, value) DIRECT_##name(target, value)
470INSTRUCTION_HANDLER(AssertionFail) {
471 EVALUATE_BEGIN_NO_PRECONDITION(AssertionFail);
472 EVALUATE_END(AssertionFail);
475INSTRUCTION_HANDLER(AssertionDefines) {
476 EVALUATE_BEGIN_NON_STRING(AssertionDefines, target.is_object());
477 const auto &value{assume_value<ValueProperty>(instruction.value)};
478 result = target.defines(value.first, value.second);
479 EVALUATE_END(AssertionDefines);
482INSTRUCTION_HANDLER(AssertionDefinesStrict) {
483 EVALUATE_BEGIN_NO_PRECONDITION(AssertionDefinesStrict);
485 resolve_instance(instance, instruction.relative_instance_location)};
486 const auto &value{assume_value<ValueProperty>(instruction.value)};
487 result = target.is_object() && target.defines(value.first, value.second);
488 EVALUATE_END(AssertionDefinesStrict);
491INSTRUCTION_HANDLER(AssertionDefinesAll) {
492 EVALUATE_BEGIN_NON_STRING(AssertionDefinesAll, target.is_object());
493 const auto &value{assume_value<ValueStringSet>(instruction.value)};
495 assert(value.size() > 1);
498 if (value.size() <= target.object_size()) [[likely]] {
500 const auto &
object{target.as_object()};
501 for (
const auto &property : value) {
502 if (!
object.defines(property.first, property.second)) [[unlikely]] {
509 EVALUATE_END(AssertionDefinesAll);
512INSTRUCTION_HANDLER(AssertionDefinesAllStrict) {
513 EVALUATE_BEGIN_NO_PRECONDITION(AssertionDefinesAllStrict);
515 resolve_instance(instance, instruction.relative_instance_location)};
516 const auto &value{assume_value<ValueStringSet>(instruction.value)};
518 assert(value.size() > 1);
521 if (target.is_object() && value.size() <= target.object_size()) [[likely]] {
523 const auto &
object{target.as_object()};
524 for (
const auto &property : value) {
525 if (!
object.defines(property.first, property.second)) [[unlikely]] {
532 EVALUATE_END(AssertionDefinesAllStrict);
535INSTRUCTION_HANDLER(AssertionDefinesExactly) {
536 EVALUATE_BEGIN_NON_STRING(AssertionDefinesExactly, target.is_object());
537 const auto &value{assume_value<ValueStringSet>(instruction.value)};
539 assert(value.size() > 1);
540 const auto &
object{target.as_object()};
542 if (value.size() ==
object.size()) [[likely]] {
544 for (
const auto &property : value) {
545 if (!
object.defines(property.first, property.second)) [[unlikely]] {
552 EVALUATE_END(AssertionDefinesExactly);
555INSTRUCTION_HANDLER(AssertionDefinesExactlyStrict) {
556 EVALUATE_BEGIN_NO_PRECONDITION(AssertionDefinesExactlyStrict);
558 resolve_instance(instance, instruction.relative_instance_location)};
559 if (target.is_object()) [[likely]] {
560 const auto &value{assume_value<ValueStringSet>(instruction.value)};
562 assert(value.size() > 1);
563 const auto &
object{target.as_object()};
565 if (value.size() ==
object.size()) [[likely]] {
567 for (
const auto &property : value) {
568 if (!
object.defines(property.first, property.second)) [[unlikely]] {
576 EVALUATE_END(AssertionDefinesExactlyStrict);
579INSTRUCTION_HANDLER(AssertionDefinesExactlyStrictHash3) {
580 EVALUATE_BEGIN_NO_PRECONDITION(AssertionDefinesExactlyStrictHash3);
582 resolve_instance(instance, instruction.relative_instance_location)};
583 if (target.is_object()) [[likely]] {
586 const auto &value{assume_value<ValueStringHashes>(instruction.value)};
587 assert(value.first.size() == 3);
588 const auto &
object{target.as_object()};
594 object.size() == 3 && ((value.first.at(0).first ==
object.at(0).hash &&
595 value.first.at(1).first ==
object.at(1).hash &&
596 value.first.at(2).first ==
object.at(2).hash) ||
597 (value.first.at(0).first ==
object.at(0).hash &&
598 value.first.at(1).first ==
object.at(2).hash &&
599 value.first.at(2).first ==
object.at(1).hash) ||
600 (value.first.at(0).first ==
object.at(1).hash &&
601 value.first.at(1).first ==
object.at(0).hash &&
602 value.first.at(2).first ==
object.at(2).hash) ||
603 (value.first.at(0).first ==
object.at(1).hash &&
604 value.first.at(1).first ==
object.at(2).hash &&
605 value.first.at(2).first ==
object.at(0).hash) ||
606 (value.first.at(0).first ==
object.at(2).hash &&
607 value.first.at(1).first ==
object.at(0).hash &&
608 value.first.at(2).first ==
object.at(1).hash) ||
609 (value.first.at(0).first ==
object.at(2).hash &&
610 value.first.at(1).first ==
object.at(1).hash &&
611 value.first.at(2).first ==
object.at(0).hash));
614 EVALUATE_END(AssertionDefinesExactlyStrictHash3);
617INSTRUCTION_HANDLER(AssertionPropertyDependencies) {
618 EVALUATE_BEGIN_NON_STRING(AssertionPropertyDependencies, target.is_object());
619 const auto &value{assume_value<ValueStringMap>(instruction.value)};
621 assert(!value.empty());
623 const auto &
object{target.as_object()};
624 const sourcemeta::core::PropertyHashJSON<ValueString> hasher;
625 for (
const auto &entry : value) {
626 if (!
object.defines(entry.first, entry.hash)) {
630 assert(!entry.second.empty());
631 for (
const auto &dependency : entry.second) {
632 if (!
object.defines(dependency, hasher(dependency))) [[unlikely]] {
634 EVALUATE_END(AssertionPropertyDependencies);
639 EVALUATE_END(AssertionPropertyDependencies);
642INSTRUCTION_DIRECT_COPY(AssertionType,
ValueType) {
645 return target.type() == value ||
646 (value == JSON::Type::Integer && target.is_integral());
649INSTRUCTION_HANDLER(AssertionType) {
650 EVALUATE_BEGIN_NO_PRECONDITION(AssertionType);
652 resolve_instance(instance, instruction.relative_instance_location)};
653 const auto value{assume_value_copy<ValueType>(instruction.value)};
656 assert(value == JSON::Type::Integer);
657 SOURCEMETA_ASSUME(value == JSON::Type::Integer);
658 result = DIRECT(AssertionType, target, value);
659 EVALUATE_END(AssertionType);
662INSTRUCTION_DIRECT(AssertionTypeAny,
ValueTypes) {
665 return type_set_test(value, target.type()) ||
666 (type_set_test(value, JSON::Type::Integer) && target.is_integral());
669INSTRUCTION_HANDLER(AssertionTypeAny) {
670 EVALUATE_BEGIN_NO_PRECONDITION(AssertionTypeAny);
671 const auto value{assume_value_copy<ValueTypes>(instruction.value)};
674 resolve_instance(instance, instruction.relative_instance_location)};
675 result = DIRECT(AssertionTypeAny, target, value);
676 EVALUATE_END(AssertionTypeAny);
679INSTRUCTION_DIRECT_COPY(AssertionTypeStrict,
ValueType) {
680 return effective_type_strict_real(target) == value;
683INSTRUCTION_HANDLER(AssertionTypeStrict) {
684 EVALUATE_BEGIN_NO_PRECONDITION(AssertionTypeStrict);
686 resolve_instance(instance, instruction.relative_instance_location)};
687 const auto value{assume_value_copy<ValueType>(instruction.value)};
688 result = DIRECT(AssertionTypeStrict, target, value);
689 EVALUATE_END(AssertionTypeStrict);
692INSTRUCTION_DIRECT(AssertionTypeStrictAny,
ValueTypes) {
693 return type_set_test(value, effective_type_strict_real(target));
696INSTRUCTION_HANDLER(AssertionTypeStrictAny) {
697 EVALUATE_BEGIN_NO_PRECONDITION(AssertionTypeStrictAny);
698 const auto value{assume_value_copy<ValueTypes>(instruction.value)};
701 resolve_instance(instance, instruction.relative_instance_location)};
702 result = DIRECT(AssertionTypeStrictAny, target, value);
703 EVALUATE_END(AssertionTypeStrictAny);
706INSTRUCTION_DIRECT(AssertionNotTypeStrictAny,
ValueTypes) {
707 return !type_set_test(value, effective_type_strict_real(target));
710INSTRUCTION_HANDLER(AssertionNotTypeStrictAny) {
711 EVALUATE_BEGIN_NO_PRECONDITION(AssertionNotTypeStrictAny);
712 const auto value{assume_value_copy<ValueTypes>(instruction.value)};
715 resolve_instance(instance, instruction.relative_instance_location)};
716 result = DIRECT(AssertionNotTypeStrictAny, target, value);
717 EVALUATE_END(AssertionNotTypeStrictAny);
720INSTRUCTION_DIRECT(AssertionTypeStringBounded,
ValueRange) {
721 const auto &[minimum, maximum, exhaustive] = value;
722 return target.type() == JSON::Type::String &&
723 target.string_size() >= minimum &&
724 (!maximum.has_value() || target.string_size() <= maximum.value());
727INSTRUCTION_HANDLER(AssertionTypeStringBounded) {
728 EVALUATE_BEGIN_NO_PRECONDITION(AssertionTypeStringBounded);
730 resolve_instance(instance, instruction.relative_instance_location)};
731 const auto &value{assume_value<ValueRange>(instruction.value)};
732 assert(!std::get<1>(value).has_value() ||
733 std::get<1>(value).value() >= std::get<0>(value));
734 assert(!std::get<2>(value));
735 result = DIRECT(AssertionTypeStringBounded, target, value);
736 EVALUATE_END(AssertionTypeStringBounded);
739INSTRUCTION_HANDLER(AssertionTypeStringUpper) {
740 EVALUATE_BEGIN_NO_PRECONDITION(AssertionTypeStringUpper);
742 resolve_instance(instance, instruction.relative_instance_location)};
743 const auto value{assume_value_copy<ValueUnsignedInteger>(instruction.value)};
744 result = target.is_string() && target.string_size() <= value;
745 EVALUATE_END(AssertionTypeStringUpper);
748INSTRUCTION_DIRECT(AssertionTypeArrayBounded,
ValueRange) {
749 const auto &[minimum, maximum, exhaustive] = value;
752 SOURCEMETA_ASSUME(!exhaustive);
753 return target.type() == JSON::Type::Array && target.array_size() >= minimum &&
754 (!maximum.has_value() || target.array_size() <= maximum.value());
757INSTRUCTION_HANDLER(AssertionTypeArrayBounded) {
758 EVALUATE_BEGIN_NO_PRECONDITION(AssertionTypeArrayBounded);
760 resolve_instance(instance, instruction.relative_instance_location)};
761 const auto &value{assume_value<ValueRange>(instruction.value)};
762 assert(!std::get<1>(value).has_value() ||
763 std::get<1>(value).value() >= std::get<0>(value));
764 result = DIRECT(AssertionTypeArrayBounded, target, value);
765 EVALUATE_END(AssertionTypeArrayBounded);
768INSTRUCTION_HANDLER(AssertionTypeArrayUpper) {
769 EVALUATE_BEGIN_NO_PRECONDITION(AssertionTypeArrayUpper);
771 resolve_instance(instance, instruction.relative_instance_location)};
772 const auto value{assume_value_copy<ValueUnsignedInteger>(instruction.value)};
773 result = target.is_array() && target.array_size() <= value;
774 EVALUATE_END(AssertionTypeArrayUpper);
777INSTRUCTION_HANDLER(AssertionTypeObjectBounded) {
778 EVALUATE_BEGIN_NO_PRECONDITION(AssertionTypeObjectBounded);
780 resolve_instance(instance, instruction.relative_instance_location)};
781 const auto &value{assume_value<ValueRange>(instruction.value)};
782 const auto &[minimum, maximum, exhaustive] = value;
783 assert(!maximum.has_value() || maximum.value() >= minimum);
786 SOURCEMETA_ASSUME(!exhaustive);
787 result = target.type() == JSON::Type::Object &&
788 target.object_size() >= minimum &&
789 (!maximum.has_value() || target.object_size() <= maximum.value());
790 EVALUATE_END(AssertionTypeObjectBounded);
793INSTRUCTION_HANDLER(AssertionTypeObjectUpper) {
794 EVALUATE_BEGIN_NO_PRECONDITION(AssertionTypeObjectUpper);
796 resolve_instance(instance, instruction.relative_instance_location)};
797 const auto value{assume_value_copy<ValueUnsignedInteger>(instruction.value)};
798 result = target.is_object() && target.object_size() <= value;
799 EVALUATE_END(AssertionTypeObjectUpper);
802INSTRUCTION_HANDLER(AssertionRegex) {
803 EVALUATE_BEGIN_IF_STRING(AssertionRegex);
804 const auto &value{assume_value<ValueRegex>(instruction.value)};
805 result = matches(value.first, target);
806 EVALUATE_END(AssertionRegex);
809INSTRUCTION_HANDLER(AssertionStringSizeLess) {
810 EVALUATE_BEGIN_IF_STRING(AssertionStringSizeLess);
811 const auto value{assume_value_copy<ValueUnsignedInteger>(instruction.value)};
812 result = (JSON::size(target) < value);
813 EVALUATE_END(AssertionStringSizeLess);
816INSTRUCTION_HANDLER(AssertionStringSizeGreater) {
817 EVALUATE_BEGIN_IF_STRING(AssertionStringSizeGreater);
818 const auto value{assume_value_copy<ValueUnsignedInteger>(instruction.value)};
819 result = (JSON::size(target) > value);
820 EVALUATE_END(AssertionStringSizeGreater);
823INSTRUCTION_HANDLER(AssertionArraySizeLess) {
824 EVALUATE_BEGIN_NON_STRING(AssertionArraySizeLess, target.is_array());
825 const auto value{assume_value_copy<ValueUnsignedInteger>(instruction.value)};
826 result = (target.array_size() < value);
827 EVALUATE_END(AssertionArraySizeLess);
830INSTRUCTION_HANDLER(AssertionArraySizeGreater) {
831 EVALUATE_BEGIN_NON_STRING(AssertionArraySizeGreater, target.is_array());
832 const auto value{assume_value_copy<ValueUnsignedInteger>(instruction.value)};
833 result = (target.array_size() > value);
834 EVALUATE_END(AssertionArraySizeGreater);
837INSTRUCTION_HANDLER(AssertionObjectSizeLess) {
838 EVALUATE_BEGIN_NON_STRING(AssertionObjectSizeLess, target.is_object());
839 const auto value{assume_value_copy<ValueUnsignedInteger>(instruction.value)};
840 result = (target.object_size() < value);
841 EVALUATE_END(AssertionObjectSizeLess);
844INSTRUCTION_HANDLER(AssertionObjectSizeGreater) {
845 EVALUATE_BEGIN_NON_STRING(AssertionObjectSizeGreater, target.is_object());
846 const auto value{assume_value_copy<ValueUnsignedInteger>(instruction.value)};
847 result = (target.object_size() > value);
848 EVALUATE_END(AssertionObjectSizeGreater);
851INSTRUCTION_DIRECT(AssertionEqual,
ValueJSON) {
return target == value; }
853INSTRUCTION_HANDLER(AssertionEqual) {
854 EVALUATE_BEGIN_NO_PRECONDITION(AssertionEqual);
855 const auto &value{assume_value<ValueJSON>(instruction.value)};
857 if (context.property_target) [[unlikely]] {
858 result = value.is_string() && value.to_string() == *context.property_target;
861 resolve_instance(instance, instruction.relative_instance_location)};
862 result = DIRECT(AssertionEqual, target, value);
865 EVALUATE_END(AssertionEqual);
868INSTRUCTION_DIRECT(AssertionEqualsAny,
ValueSet) {
869 return value.contains(target);
872INSTRUCTION_HANDLER(AssertionEqualsAny) {
873 EVALUATE_BEGIN_NO_PRECONDITION(AssertionEqualsAny);
874 const auto &value{assume_value<ValueSet>(instruction.value)};
876 if (context.property_target) [[unlikely]] {
878 result = value.contains(JSON{*context.property_target});
881 resolve_instance(instance, instruction.relative_instance_location)};
882 result = DIRECT(AssertionEqualsAny, target, value);
885 EVALUATE_END(AssertionEqualsAny);
889 if (!target.is_string()) [[unlikely]] {
892 const auto &target_string{target.to_string()};
893 const auto string_size{target_string.size()};
894 const sourcemeta::core::PropertyHashJSON<ValueString> hasher;
895 const auto value_hash{hasher(target_string)};
896 if (string_size < value.second.size()) [[likely]] {
897 const auto &hint{value.second[string_size]};
898 if (hint.second != 0) [[likely]] {
899 for (std::size_t index = hint.first - 1; index < hint.second; index++) {
900 if (value.first[index].first == value_hash) {
909INSTRUCTION_HANDLER(AssertionEqualsAnyStringHash) {
910 EVALUATE_BEGIN_NO_PRECONDITION(AssertionEqualsAnyStringHash);
911 const auto &value{assume_value<ValueStringHashes>(instruction.value)};
913 if (context.property_target) [[unlikely]] {
914 const sourcemeta::core::PropertyHashJSON<ValueString> hasher;
915 const auto value_hash{hasher(*context.property_target)};
916 const auto string_size{context.property_target->size()};
917 if (string_size < value.second.size()) [[likely]] {
918 const auto &hint{value.second[string_size]};
919 assert(hint.first <= hint.second);
920 SOURCEMETA_ASSUME(hint.first <= hint.second);
921 if (hint.second != 0) [[likely]] {
922 for (std::size_t index = hint.first - 1; index < hint.second; index++) {
923 assert(hasher.is_perfect(value.first[index].first));
924 if (value.first[index].first == value_hash) {
933 resolve_instance(instance, instruction.relative_instance_location)};
934 result = DIRECT(AssertionEqualsAnyStringHash, target, value);
937 EVALUATE_END(AssertionEqualsAnyStringHash);
940INSTRUCTION_HANDLER(AssertionGreaterEqual) {
941 EVALUATE_BEGIN_NON_STRING(AssertionGreaterEqual, target.is_number());
942 const auto &value{assume_value<ValueJSON>(instruction.value)};
943 result = target >= value;
944 EVALUATE_END(AssertionGreaterEqual);
947INSTRUCTION_HANDLER(AssertionLessEqual) {
948 EVALUATE_BEGIN_NON_STRING(AssertionLessEqual, target.is_number());
949 const auto &value{assume_value<ValueJSON>(instruction.value)};
950 result = target <= value;
951 EVALUATE_END(AssertionLessEqual);
954INSTRUCTION_HANDLER(AssertionGreater) {
955 EVALUATE_BEGIN_NON_STRING(AssertionGreater, target.is_number());
956 const auto &value{assume_value<ValueJSON>(instruction.value)};
957 result = target > value;
958 EVALUATE_END(AssertionGreater);
961INSTRUCTION_HANDLER(AssertionLess) {
962 EVALUATE_BEGIN_NON_STRING(AssertionLess, target.is_number());
963 const auto &value{assume_value<ValueJSON>(instruction.value)};
964 result = target < value;
965 EVALUATE_END(AssertionLess);
968INSTRUCTION_HANDLER(AssertionUnique) {
969 EVALUATE_BEGIN_NON_STRING(AssertionUnique, target.is_array());
970 result = target.unique();
971 EVALUATE_END(AssertionUnique);
974INSTRUCTION_HANDLER(AssertionDivisible) {
975 EVALUATE_BEGIN_NON_STRING(AssertionDivisible, target.is_number());
976 const auto &value{assume_value<ValueJSON>(instruction.value)};
977 assert(value.is_number());
978 result = target.divisible_by(value);
979 EVALUATE_END(AssertionDivisible);
983 return integer_within_bounds(target, value);
986INSTRUCTION_HANDLER(AssertionTypeIntegerBounded) {
987 EVALUATE_BEGIN_NON_STRING(AssertionTypeIntegerBounded,
true);
988 result = DIRECT(AssertionTypeIntegerBounded, target,
989 assume_value_copy<ValueIntegerBounds>(instruction.value));
990 EVALUATE_END(AssertionTypeIntegerBounded);
994 if (target.is_integer()) {
995 const auto integer{target.to_integer()};
996 return integer >= value.first && integer <= value.second;
1001INSTRUCTION_HANDLER(AssertionTypeIntegerBoundedStrict) {
1002 EVALUATE_BEGIN_NON_STRING(AssertionTypeIntegerBoundedStrict,
true);
1003 result = DIRECT(AssertionTypeIntegerBoundedStrict, target,
1004 assume_value_copy<ValueIntegerBounds>(instruction.value));
1005 EVALUATE_END(AssertionTypeIntegerBoundedStrict);
1009 if (target.is_integer()) {
1010 return target.to_integer() >= value.first;
1012 if (target.is_integral()) {
1013 return as_decimal(target) >= Decimal{value.first};
1018INSTRUCTION_HANDLER(AssertionTypeIntegerLowerBound) {
1019 EVALUATE_BEGIN_NON_STRING(AssertionTypeIntegerLowerBound,
true);
1020 result = DIRECT(AssertionTypeIntegerLowerBound, target,
1021 assume_value_copy<ValueIntegerBounds>(instruction.value));
1022 EVALUATE_END(AssertionTypeIntegerLowerBound);
1026 if (target.is_integer()) {
1027 return target.to_integer() >= value.first;
1033 if (effective_type_strict_real(target) == JSON::Type::Integer) {
1034 return target.to_decimal() >= Decimal{value.first};
1039INSTRUCTION_HANDLER(AssertionTypeIntegerLowerBoundStrict) {
1040 EVALUATE_BEGIN_NON_STRING(AssertionTypeIntegerLowerBoundStrict,
true);
1041 result = DIRECT(AssertionTypeIntegerLowerBoundStrict, target,
1042 assume_value_copy<ValueIntegerBounds>(instruction.value));
1043 EVALUATE_END(AssertionTypeIntegerLowerBoundStrict);
1047 return integer_within_bounds(target, value);
1050INSTRUCTION_HANDLER(AssertionNumberIntegerBounded) {
1051 EVALUATE_BEGIN_NON_STRING(AssertionNumberIntegerBounded, target.is_number());
1052 result = DIRECT(AssertionNumberIntegerBounded, target,
1053 assume_value_copy<ValueIntegerBounds>(instruction.value));
1054 EVALUATE_END(AssertionNumberIntegerBounded);
1057INSTRUCTION_HANDLER(AssertionNumberType) {
1058 EVALUATE_BEGIN_NON_STRING(AssertionNumberType, target.is_number());
1059 switch (assume_value_copy<ValueNumberType>(instruction.value)) {
1060 case ValueNumberType::Float:
1061 result = target.is_float();
1063 case ValueNumberType::Double:
1064 result = target.is_double();
1067 EVALUATE_END(AssertionNumberType);
1070INSTRUCTION_HANDLER(AssertionStringType) {
1071 EVALUATE_BEGIN_IF_STRING(AssertionStringType);
1072 const auto value{assume_value_copy<ValueStringType>(instruction.value)};
1074 case ValueStringType::URI:
1075 result = URI::is_uri(target);
1077 case ValueStringType::URIReference:
1078 result = URI::is_uri_reference(target);
1080 case ValueStringType::URITemplate:
1081 result = URITemplate::is_uritemplate(target);
1083 case ValueStringType::IRI:
1084 result = URI::is_iri(target);
1086 case ValueStringType::IRIReference:
1087 result = URI::is_iri_reference(target);
1089 case ValueStringType::Email:
1090 result = is_email(target);
1092 case ValueStringType::IDNEmail:
1093 result = is_idn_email_uts46(target);
1095 case ValueStringType::IPv4:
1096 result = is_ipv4(target);
1098 case ValueStringType::IPv6:
1099 result = is_ipv6(target);
1101 case ValueStringType::Hostname:
1102 result = is_hostname(target);
1104 case ValueStringType::IDNHostname:
1105 result = is_idn_hostname(target);
1107 case ValueStringType::DateTime:
1108 result = is_rfc3339_datetime(target);
1110 case ValueStringType::Date:
1111 result = is_rfc3339_fulldate(target);
1113 case ValueStringType::Time:
1114 result = is_rfc3339_fulltime(target);
1116 case ValueStringType::PartialTime:
1117 result = is_rfc3339_partialtime_no_secfrac(target);
1119 case ValueStringType::Duration:
1120 result = is_rfc3339_duration(target);
1122 case ValueStringType::JSONPointer:
1123 result = is_pointer(target);
1125 case ValueStringType::RelativeJSONPointer:
1126 result = is_relative_pointer(target);
1128 case ValueStringType::UUID:
1129 result = is_uuid_like(target);
1131 case ValueStringType::Regex:
1132 result = is_regex_ecma(target);
1134 case ValueStringType::Color:
1135 result = is_css2_color(target);
1137 case ValueStringType::Base64:
1138 result = sourcemeta::core::is_base64(target);
1144 EVALUATE_END(AssertionStringType);
1147INSTRUCTION_HANDLER(AssertionPropertyType) {
1148 EVALUATE_BEGIN_TRY_TARGET(AssertionPropertyType);
1150 const auto value{assume_value_copy<ValueType>(instruction.value)};
1153 result = target_check->type() == value ||
1154 (value == JSON::Type::Integer && target_check->is_integral());
1155 EVALUATE_END(AssertionPropertyType);
1158INSTRUCTION_HANDLER(AssertionPropertyTypeEvaluate) {
1159 EVALUATE_BEGIN_TRY_TARGET(AssertionPropertyTypeEvaluate);
1161 const auto value{assume_value_copy<ValueType>(instruction.value)};
1164 result = target_check->type() == value ||
1165 (value == JSON::Type::Integer && target_check->is_integral());
1168 context.evaluator->evaluate(target_check);
1171 EVALUATE_END(AssertionPropertyTypeEvaluate);
1174INSTRUCTION_HANDLER(AssertionPropertyTypeStrict) {
1175 EVALUATE_BEGIN_TRY_TARGET(AssertionPropertyTypeStrict);
1177 const auto value{assume_value_copy<ValueType>(instruction.value)};
1178 result = effective_type_strict_real(*target_check) == value;
1179 EVALUATE_END(AssertionPropertyTypeStrict);
1182INSTRUCTION_HANDLER(AssertionPropertyTypeStrictEvaluate) {
1183 EVALUATE_BEGIN_TRY_TARGET(AssertionPropertyTypeStrictEvaluate);
1185 const auto value{assume_value_copy<ValueType>(instruction.value)};
1186 result = effective_type_strict_real(*target_check) == value;
1189 context.evaluator->evaluate(target_check);
1192 EVALUATE_END(AssertionPropertyTypeStrictEvaluate);
1195INSTRUCTION_HANDLER(AssertionPropertyEqual) {
1196 EVALUATE_BEGIN_TRY_TARGET(AssertionPropertyEqual);
1197 const auto &value{assume_value<ValueJSON>(instruction.value)};
1199 result = DIRECT(AssertionEqual, *target_check, value);
1200 EVALUATE_END(AssertionPropertyEqual);
1203INSTRUCTION_HANDLER(AssertionPropertyTypeStrictAny) {
1204 EVALUATE_BEGIN_TRY_TARGET(AssertionPropertyTypeStrictAny);
1205 const auto value{assume_value_copy<ValueTypes>(instruction.value)};
1206 assert(value.any());
1208 result = type_set_test(value, effective_type_strict_real(*target_check));
1209 EVALUATE_END(AssertionPropertyTypeStrictAny);
1212INSTRUCTION_HANDLER(AssertionPropertyTypeStrictAnyEvaluate) {
1213 EVALUATE_BEGIN_TRY_TARGET(AssertionPropertyTypeStrictAnyEvaluate);
1214 const auto value{assume_value_copy<ValueTypes>(instruction.value)};
1215 assert(value.any());
1217 result = type_set_test(value, effective_type_strict_real(*target_check));
1220 context.evaluator->evaluate(target_check);
1223 EVALUATE_END(AssertionPropertyTypeStrictAnyEvaluate);
1226INSTRUCTION_HANDLER(AssertionObjectPropertiesSimple) {
1227 EVALUATE_BEGIN_NON_STRING(AssertionObjectPropertiesSimple,
true);
1228 if (!target.is_object()) {
1229 EVALUATE_END(AssertionObjectPropertiesSimple);
1232 const auto &value{assume_value<ValueObjectProperties>(instruction.value)};
1233 assert(value.size() >= instruction.children.size());
1234 assert(value.size() <= 32);
1235 static constexpr sourcemeta::core::PropertyHashJSON<ValueString>
1237 const auto &
object{target.as_object()};
1238 const auto schema_size{value.size()};
1239 std::uint32_t seen{0};
1242 for (
const auto &instance_entry :
object) {
1243 const auto &instance_hash{instance_entry.hash};
1244 for (std::size_t schema_index = 0; schema_index < schema_size;
1246 const auto &schema_hash{std::get<1>(value[schema_index])};
1249 if (schema_hash == instance_hash &&
1250 (PROPERTY_HASHER.is_perfect(instance_hash) ||
1251 instance_entry.first == std::get<0>(value[schema_index]))) {
1252 seen |= (
static_cast<std::uint32_t
>(1) << schema_index);
1253 if (schema_index < instruction.children.size()) {
1254 const auto &child{instruction.children[schema_index]};
1255 const auto &property_value{instance_entry.second};
1256 bool child_ok{
false};
1259#define CHILD_DIRECT(name, accessor, value_type) \
1262 DIRECT(name, property_value, accessor<value_type>(child.value)); \
1265 switch (child.type) {
1266 using enum InstructionIndex;
1267 CHILD_DIRECT(AssertionTypeStrict, assume_value_copy,
ValueType);
1268 CHILD_DIRECT(AssertionType, assume_value_copy,
ValueType);
1269 CHILD_DIRECT(AssertionTypeStrictAny, assume_value,
ValueTypes);
1270 CHILD_DIRECT(AssertionTypeAny, assume_value,
ValueTypes);
1271 CHILD_DIRECT(AssertionTypeStringBounded, assume_value,
ValueRange);
1272 CHILD_DIRECT(AssertionEqual, assume_value,
ValueJSON);
1273 CHILD_DIRECT(AssertionEqualsAny, assume_value,
ValueSet);
1274 CHILD_DIRECT(AssertionEqualsAnyStringHash, assume_value,
1276 CHILD_DIRECT(AssertionTypeIntegerBounded, assume_value_copy,
1278 CHILD_DIRECT(AssertionTypeIntegerBoundedStrict, assume_value_copy,
1280 CHILD_DIRECT(AssertionTypeIntegerLowerBound, assume_value_copy,
1282 CHILD_DIRECT(AssertionTypeIntegerLowerBoundStrict,
1284 CHILD_DIRECT(LoopItemsIntegerBounded, assume_value_copy,
1287 child_ok = evaluate_instruction_without_callback(
1288 child, property_value, depth + 1, context);
1295 if (!child_ok) [[unlikely]] {
1297 EVALUATE_END(AssertionObjectPropertiesSimple);
1307 const auto all_seen{schema_size == 32
1309 : (std::uint32_t{1} << schema_size) - 1};
1310 if (seen != all_seen) [[unlikely]] {
1311 for (std::size_t schema_index = 0; schema_index < schema_size;
1313 if (std::get<2>(value[schema_index]) &&
1314 !(seen & (
static_cast<std::uint32_t
>(1) << schema_index))) {
1316 EVALUATE_END(AssertionObjectPropertiesSimple);
1321 EVALUATE_END(AssertionObjectPropertiesSimple);
1324INSTRUCTION_HANDLER(AssertionArrayPrefix) {
1325 EVALUATE_BEGIN_NON_STRING(AssertionArrayPrefix, target.is_array());
1327 assert(!instruction.children.empty());
1328 result = target.empty();
1329 const auto prefixes{instruction.children.size() - 1};
1330 const auto array_size{target.array_size()};
1331 if (!result) [[likely]] {
1333 array_size == prefixes ? prefixes : std::min(array_size, prefixes) - 1};
1334 const auto &entry{instruction.children[pointer]};
1336 assert(entry.type == sourcemeta::blaze::InstructionIndex::ControlGroup);
1337 SOURCEMETA_ASSUME(entry.type ==
1338 sourcemeta::blaze::InstructionIndex::ControlGroup);
1339 for (
const auto &child : entry.children) {
1340 if (!EVALUATE_RECURSE(child, target)) [[unlikely]] {
1347 EVALUATE_END(AssertionArrayPrefix);
1350INSTRUCTION_HANDLER(AssertionArrayPrefixEvaluate) {
1351 EVALUATE_BEGIN_NON_STRING(AssertionArrayPrefixEvaluate, target.is_array());
1353 assert(!instruction.children.empty());
1354 result = target.empty();
1355 const auto prefixes{instruction.children.size() - 1};
1356 const auto array_size{target.array_size()};
1357 if (!result) [[likely]] {
1359 array_size == prefixes ? prefixes : std::min(array_size, prefixes) - 1};
1360 const auto &entry{instruction.children[pointer]};
1362 assert(entry.type == sourcemeta::blaze::InstructionIndex::ControlGroup);
1363 SOURCEMETA_ASSUME(entry.type ==
1364 sourcemeta::blaze::InstructionIndex::ControlGroup);
1365 for (
const auto &child : entry.children) {
1366 if (!EVALUATE_RECURSE(child, target)) [[unlikely]] {
1368 EVALUATE_END(AssertionArrayPrefixEvaluate);
1373 SOURCEMETA_ASSUME(result);
1374 if (array_size == prefixes) {
1375 context.evaluator->evaluate(&target);
1377 for (std::size_t cursor = 0; cursor <= pointer; cursor++) {
1378 context.evaluator->evaluate(&target.at(cursor));
1383 EVALUATE_END(AssertionArrayPrefixEvaluate);
1386INSTRUCTION_HANDLER(LogicalOr) {
1387 EVALUATE_BEGIN_NO_PRECONDITION(LogicalOr);
1388 result = instruction.children.empty();
1390 resolve_instance(instance, instruction.relative_instance_location)};
1391 const auto value{assume_value_copy<ValueBoolean>(instruction.value)};
1395 for (
const auto &child : instruction.children) {
1399 [[maybe_unused]] std::size_t checkpoint{0};
1400 if constexpr (Track) {
1401 checkpoint = context.evaluator->checkpoint();
1404 if (EVALUATE_RECURSE(child, target)) {
1407 if constexpr (Track) {
1408 context.evaluator->rewind(checkpoint);
1413 for (
const auto &child : instruction.children) {
1414 [[maybe_unused]] std::size_t checkpoint{0};
1415 if constexpr (Track) {
1416 checkpoint = context.evaluator->checkpoint();
1419 if (EVALUATE_RECURSE(child, target)) {
1424 if constexpr (Track) {
1425 context.evaluator->rewind(checkpoint);
1430 EVALUATE_END(LogicalOr);
1433INSTRUCTION_HANDLER(LogicalAnd) {
1434 EVALUATE_BEGIN_NO_PRECONDITION(LogicalAnd);
1437 resolve_instance(instance, instruction.relative_instance_location)};
1438 for (
const auto &child : instruction.children) {
1439 if (!EVALUATE_RECURSE(child, target)) [[unlikely]] {
1445 EVALUATE_END(LogicalAnd);
1448INSTRUCTION_HANDLER(LogicalWhenType) {
1449 const auto value{assume_value_copy<ValueType>(instruction.value)};
1453 assert(value != JSON::Type::Integer);
1454 SOURCEMETA_ASSUME(value != JSON::Type::Integer);
1455 assert(value != JSON::Type::Real);
1456 SOURCEMETA_ASSUME(value != JSON::Type::Real);
1457 assert(value != JSON::Type::Decimal);
1458 SOURCEMETA_ASSUME(value != JSON::Type::Decimal);
1460 EVALUATE_BEGIN(LogicalWhenType, target.type() == value);
1462 for (
const auto &child : instruction.children) {
1463 if (!EVALUATE_RECURSE(child, target)) [[unlikely]] {
1469 EVALUATE_END(LogicalWhenType);
1472INSTRUCTION_HANDLER(LogicalWhenDefines) {
1473 const auto &value{assume_value<ValueProperty>(instruction.value)};
1474 EVALUATE_BEGIN_NON_STRING(LogicalWhenDefines,
1475 target.is_object() &&
1476 target.defines(value.first, value.second));
1478 for (
const auto &child : instruction.children) {
1479 if (!EVALUATE_RECURSE(child, target)) [[unlikely]] {
1485 EVALUATE_END(LogicalWhenDefines);
1488INSTRUCTION_HANDLER(LogicalWhenArraySizeGreater) {
1489 const auto value{assume_value_copy<ValueUnsignedInteger>(instruction.value)};
1490 EVALUATE_BEGIN_NON_STRING(LogicalWhenArraySizeGreater,
1491 target.is_array() && target.array_size() > value);
1493 for (
const auto &child : instruction.children) {
1494 if (!EVALUATE_RECURSE(child, target)) [[unlikely]] {
1500 EVALUATE_END(LogicalWhenArraySizeGreater);
1503INSTRUCTION_HANDLER(LogicalXor) {
1504 EVALUATE_BEGIN_NO_PRECONDITION(LogicalXor);
1506 bool has_matched{
false};
1508 resolve_instance(instance, instruction.relative_instance_location)};
1509 const auto value{assume_value_copy<ValueBoolean>(instruction.value)};
1510 for (
const auto &child : instruction.children) {
1513 [[maybe_unused]] std::size_t checkpoint{0};
1514 if constexpr (Track) {
1515 checkpoint = context.evaluator->checkpoint();
1518 if (EVALUATE_RECURSE(child, target)) {
1519 if (has_matched) [[unlikely]] {
1529 if constexpr (Track) {
1530 context.evaluator->rewind(checkpoint);
1535 result = result && has_matched;
1536 EVALUATE_END(LogicalXor);
1539INSTRUCTION_HANDLER(LogicalCondition) {
1540 EVALUATE_BEGIN_NO_PRECONDITION(LogicalCondition);
1542 const auto value{assume_value_copy<ValueIndexPair>(instruction.value)};
1543 const auto children_size{instruction.children.size()};
1544 assert(children_size >= value.first);
1545 SOURCEMETA_ASSUME(children_size >= value.first);
1546 assert(children_size >= value.second);
1547 SOURCEMETA_ASSUME(children_size >= value.second);
1553 resolve_instance(instance, instruction.relative_instance_location)};
1557 [[maybe_unused]] std::size_t checkpoint{0};
1558 if constexpr (Track) {
1559 checkpoint = context.evaluator->checkpoint();
1562 for (std::size_t cursor = 0; cursor < value.first; cursor++) {
1563 if (!EVALUATE_RECURSE(instruction.children[cursor], target)) {
1570 if constexpr (Track) {
1571 context.evaluator->rewind(checkpoint);
1577 std::size_t consequence_start;
1578 std::size_t consequence_end;
1580 consequence_start = value.first;
1581 consequence_end = value.second > 0 ? value.second : children_size;
1583 consequence_start = value.second;
1584 consequence_end = value.second > 0 ? children_size : value.second;
1588 if (consequence_start < consequence_end) {
1589 if constexpr (Track || HasCallback) {
1591 context.evaluator->evaluate_path.pop_back(
1592 context.schema->extra[instruction.extra_index]
1593 .relative_schema_location.size());
1597 for (
auto cursor = consequence_start; cursor < consequence_end; cursor++) {
1598 if (!EVALUATE_RECURSE(instruction.children[cursor], target)) {
1604 if constexpr (Track || HasCallback) {
1606 context.evaluator->evaluate_path.push_back(
1607 context.schema->extra[instruction.extra_index]
1608 .relative_schema_location);
1613 EVALUATE_END(LogicalCondition);
1616INSTRUCTION_HANDLER(ControlGroup) {
1617 EVALUATE_BEGIN_PASS_THROUGH(ControlGroup);
1618 for (
const auto &child : instruction.children) {
1619 if (!EVALUATE_RECURSE(child, instance)) [[unlikely]] {
1625 EVALUATE_END_PASS_THROUGH(ControlGroup);
1628INSTRUCTION_HANDLER(ControlGroupWhenDefines) {
1629 EVALUATE_BEGIN_PASS_THROUGH(ControlGroupWhenDefines);
1630 assert(!instruction.children.empty());
1632 assert(!instruction.relative_instance_location.empty());
1634 resolve_instance(instance, instruction.relative_instance_location)};
1635 const auto &value{assume_value<ValueProperty>(instruction.value)};
1636 if (target.is_object() && target.defines(value.first, value.second)) {
1637 for (
const auto &child : instruction.children) {
1640 if (!EVALUATE_RECURSE(child, instance)) [[unlikely]] {
1647 EVALUATE_END_PASS_THROUGH(ControlGroupWhenDefines);
1650INSTRUCTION_HANDLER(ControlGroupWhenDefinesDirect) {
1651 EVALUATE_BEGIN_PASS_THROUGH(ControlGroupWhenDefinesDirect);
1652 assert(!instruction.children.empty());
1653 assert(instruction.relative_instance_location.empty());
1654 const auto &value{assume_value<ValueProperty>(instruction.value)};
1656 if (instance.is_object() && instance.defines(value.first, value.second)) {
1657 for (
const auto &child : instruction.children) {
1658 if (!EVALUATE_RECURSE(child, instance)) [[unlikely]] {
1665 EVALUATE_END_PASS_THROUGH(ControlGroupWhenDefinesDirect);
1668INSTRUCTION_HANDLER(ControlGroupWhenType) {
1669 EVALUATE_BEGIN_PASS_THROUGH(ControlGroupWhenType);
1670 assert(!instruction.children.empty());
1671 assert(instruction.relative_instance_location.empty());
1672 const auto value{assume_value_copy<ValueType>(instruction.value)};
1676 assert(value != JSON::Type::Integer);
1677 SOURCEMETA_ASSUME(value != JSON::Type::Integer);
1678 assert(value != JSON::Type::Real);
1679 SOURCEMETA_ASSUME(value != JSON::Type::Real);
1680 assert(value != JSON::Type::Decimal);
1681 SOURCEMETA_ASSUME(value != JSON::Type::Decimal);
1683 if (instance.type() == value) [[likely]] {
1684 for (
const auto &child : instruction.children) {
1685 if (!EVALUATE_RECURSE(child, instance)) [[unlikely]] {
1692 EVALUATE_END_PASS_THROUGH(ControlGroupWhenType);
1695INSTRUCTION_HANDLER(ControlEvaluate) {
1696 EVALUATE_BEGIN_PASS_THROUGH(ControlEvaluate);
1697 const auto &value{assume_value<ValuePointer>(instruction.value)};
1698 context.evaluator->evaluate(&get(instance, value));
1699 EVALUATE_END_PASS_THROUGH(ControlEvaluate);
1702INSTRUCTION_HANDLER(ControlDynamicAnchorJump) {
1703 EVALUATE_BEGIN_NO_PRECONDITION(ControlDynamicAnchorJump);
1706 resolve_instance(instance, instruction.relative_instance_location)};
1707 const auto &value{assume_value<ValueString>(instruction.value)};
1708 for (
const auto &resource : context.evaluator->resources) {
1709 const auto label{Evaluator::hash(resource, value)};
1710 const auto match{std::ranges::find_if(
1711 context.schema->labels,
1712 [&label](
const auto &entry) ->
bool { return entry.first == label; })};
1713 if (match != context.schema->labels.cend()) [[likely]] {
1715 assert(match->second < context.schema->targets.size());
1716 for (
const auto &child : context.schema->targets[match->second]) {
1717 if (!EVALUATE_RECURSE(child, target)) [[unlikely]] {
1719 EVALUATE_END(ControlDynamicAnchorJump);
1727 EVALUATE_END(ControlDynamicAnchorJump);
1730INSTRUCTION_HANDLER(ControlJump) {
1731 EVALUATE_BEGIN_NO_PRECONDITION(ControlJump);
1733 const auto value{assume_value_copy<ValueUnsignedInteger>(instruction.value)};
1734 assert(context.schema->targets.size() > value);
1735 const auto &target{resolve_target(
1736 context.property_target,
1737 resolve_instance(instance, instruction.relative_instance_location))};
1738 for (
const auto &child : context.schema->targets[value]) {
1739 if (!EVALUATE_RECURSE(child, target)) [[unlikely]] {
1745 EVALUATE_END(ControlJump);
1748INSTRUCTION_HANDLER(AnnotationEmit) {
1749 const auto &value{assume_value<ValueJSON>(instruction.value)};
1750 EVALUATE_ANNOTATION(AnnotationEmit, context.evaluator->instance_location,
1754INSTRUCTION_HANDLER(AnnotationEmitWrapped) {
1755 const auto &value{assume_value<ValueJSON>(instruction.value)};
1756 EVALUATE_ANNOTATION(AnnotationEmitWrapped,
1757 context.evaluator->instance_location, value);
1760INSTRUCTION_HANDLER(AnnotationToParent) {
1761 const auto &value{assume_value<ValueJSON>(instruction.value)};
1762 EVALUATE_ANNOTATION(
1765 context.evaluator->instance_location.initial(), value);
1768INSTRUCTION_HANDLER(AnnotationBasenameToParent) {
1769 EVALUATE_ANNOTATION(
1770 AnnotationBasenameToParent,
1772 context.evaluator->instance_location.initial(),
1773 context.evaluator->instance_location.back().to_json());
1776INSTRUCTION_HANDLER(Evaluate) {
1777 EVALUATE_BEGIN_NO_PRECONDITION(Evaluate);
1779 resolve_instance(instance, instruction.relative_instance_location)};
1780 context.evaluator->evaluate(&target);
1782 EVALUATE_END(Evaluate);
1785INSTRUCTION_HANDLER(LogicalNot) {
1786 EVALUATE_BEGIN_NO_PRECONDITION(LogicalNot);
1789 resolve_instance(instance, instruction.relative_instance_location)};
1790 for (
const auto &child : instruction.children) {
1791 if (!EVALUATE_RECURSE(child, target)) [[likely]] {
1797 EVALUATE_END(LogicalNot);
1800INSTRUCTION_HANDLER(LogicalNotEvaluate) {
1801 EVALUATE_BEGIN_NO_PRECONDITION(LogicalNotEvaluate);
1804 resolve_instance(instance, instruction.relative_instance_location)};
1805 for (
const auto &child : instruction.children) {
1806 if (!EVALUATE_RECURSE(child, target)) [[likely]] {
1812 context.evaluator->unevaluate();
1814 EVALUATE_END(LogicalNotEvaluate);
1817INSTRUCTION_HANDLER(LoopPropertiesUnevaluated) {
1818 EVALUATE_BEGIN_NON_STRING(LoopPropertiesUnevaluated, target.is_object());
1819 assert(!instruction.children.empty());
1822 if (!context.evaluator->is_evaluated(&target)) {
1823 for (
const auto &entry : target.as_object()) {
1824 if (context.evaluator->is_evaluated(&entry.second)) {
1828 if constexpr (HasCallback) {
1829 context.evaluator->instance_location.push_back(entry.first);
1831 for (
const auto &child : instruction.children) {
1832 if (!EVALUATE_RECURSE(child, entry.second)) [[unlikely]] {
1834 if constexpr (HasCallback) {
1835 context.evaluator->instance_location.pop_back();
1837 EVALUATE_END(LoopPropertiesUnevaluated);
1841 if constexpr (HasCallback) {
1842 context.evaluator->instance_location.pop_back();
1846 context.evaluator->evaluate(&target);
1849 EVALUATE_END(LoopPropertiesUnevaluated);
1852INSTRUCTION_HANDLER(LoopPropertiesUnevaluatedExcept) {
1853 EVALUATE_BEGIN_NON_STRING(LoopPropertiesUnevaluatedExcept,
1854 target.is_object());
1855 assert(!instruction.children.empty());
1856 const auto &value{assume_value<ValuePropertyFilter>(instruction.value)};
1857 const auto &[filter_strings, filter_prefixes, filter_regexes] = value;
1860 assert(!filter_strings.empty() || !filter_prefixes.empty() ||
1861 !filter_regexes.empty());
1863 if (!context.evaluator->is_evaluated(&target)) {
1864 for (
const auto &entry : target.as_object()) {
1865 if (filter_strings.contains(entry.first, entry.hash)) {
1869 if (std::ranges::any_of(filter_prefixes,
1870 [&entry](
const auto &prefix) ->
bool {
1871 return entry.first.starts_with(prefix);
1876 if (std::ranges::any_of(filter_regexes,
1877 [&entry](
const auto &pattern) ->
bool {
1878 return matches(pattern.first, entry.first);
1883 if (context.evaluator->is_evaluated(&entry.second)) {
1887 if constexpr (HasCallback) {
1888 context.evaluator->instance_location.push_back(entry.first);
1890 for (
const auto &child : instruction.children) {
1891 if (!EVALUATE_RECURSE(child, entry.second)) [[unlikely]] {
1893 if constexpr (HasCallback) {
1894 context.evaluator->instance_location.pop_back();
1896 EVALUATE_END(LoopPropertiesUnevaluatedExcept);
1900 if constexpr (HasCallback) {
1901 context.evaluator->instance_location.pop_back();
1905 context.evaluator->evaluate(&target);
1908 EVALUATE_END(LoopPropertiesUnevaluatedExcept);
1911INSTRUCTION_HANDLER(LoopPropertiesMatch) {
1912 EVALUATE_BEGIN_NON_STRING(LoopPropertiesMatch, target.is_object());
1913 const auto &value{assume_value<ValueNamedIndexes>(instruction.value)};
1914 assert(!value.first.empty());
1924 const auto direct_children{!Track && !HasCallback && !Dynamic &&
1925 depth < DEPTH_LIMIT};
1926 for (
const auto &entry : target.as_object()) {
1927 const auto *index{named_index(value, entry.first, entry.hash)};
1932 const auto &subinstruction{instruction.children[*index]};
1933 assert(subinstruction.type ==
1934 sourcemeta::blaze::InstructionIndex::ControlGroup);
1935 for (
const auto &child : subinstruction.children) {
1940 if (direct_children && child.relative_instance_location.size() == 1)
1942 switch (child.type) {
1943 case InstructionIndex::AssertionPropertyTypeStrict:
1944 child_ok = DIRECT(AssertionTypeStrict, entry.second,
1945 assume_value_copy<ValueType>(child.value));
1947 case InstructionIndex::AssertionPropertyType:
1948 child_ok = DIRECT(AssertionType, entry.second,
1949 assume_value_copy<ValueType>(child.value));
1951 case InstructionIndex::AssertionPropertyTypeStrictAny:
1952 child_ok = DIRECT(AssertionTypeStrictAny, entry.second,
1953 assume_value<ValueTypes>(child.value));
1956 child_ok = EVALUATE_RECURSE(child, target);
1960 child_ok = EVALUATE_RECURSE(child, target);
1963 if (!child_ok) [[unlikely]] {
1965 EVALUATE_END(LoopPropertiesMatch);
1970 EVALUATE_END(LoopPropertiesMatch);
1973INSTRUCTION_HANDLER(LoopPropertiesMatchClosed) {
1974 EVALUATE_BEGIN_NON_STRING(LoopPropertiesMatchClosed, target.is_object());
1975 const auto &value{assume_value<ValueNamedIndexes>(instruction.value)};
1976 assert(!value.first.empty());
1986 const auto direct_children{!Track && !HasCallback && !Dynamic &&
1987 depth < DEPTH_LIMIT};
1988 for (
const auto &entry : target.as_object()) {
1989 const auto *index{named_index(value, entry.first, entry.hash)};
1990 if (!index) [[unlikely]] {
1995 const auto &subinstruction{instruction.children[*index]};
1996 assert(subinstruction.type ==
1997 sourcemeta::blaze::InstructionIndex::ControlGroup);
1998 for (
const auto &child : subinstruction.children) {
2003 if (direct_children && child.relative_instance_location.size() == 1)
2005 switch (child.type) {
2006 case InstructionIndex::AssertionPropertyTypeStrict:
2007 child_ok = DIRECT(AssertionTypeStrict, entry.second,
2008 assume_value_copy<ValueType>(child.value));
2010 case InstructionIndex::AssertionPropertyType:
2011 child_ok = DIRECT(AssertionType, entry.second,
2012 assume_value_copy<ValueType>(child.value));
2014 case InstructionIndex::AssertionPropertyTypeStrictAny:
2015 child_ok = DIRECT(AssertionTypeStrictAny, entry.second,
2016 assume_value<ValueTypes>(child.value));
2019 child_ok = EVALUATE_RECURSE(child, target);
2023 child_ok = EVALUATE_RECURSE(child, target);
2026 if (!child_ok) [[unlikely]] {
2028 EVALUATE_END(LoopPropertiesMatchClosed);
2033 EVALUATE_END(LoopPropertiesMatchClosed);
2036INSTRUCTION_HANDLER(LoopProperties) {
2037 EVALUATE_BEGIN_NON_STRING(LoopProperties, target.is_object());
2038 assert(!instruction.children.empty());
2040 for (
const auto &entry : target.as_object()) {
2041 if constexpr (HasCallback) {
2043 context.evaluator->instance_location.push_back(entry.first);
2047 for (
const auto &child : instruction.children) {
2048 if (!EVALUATE_RECURSE(child, entry.second)) [[unlikely]] {
2051 if constexpr (HasCallback) {
2053 context.evaluator->instance_location.pop_back();
2057 EVALUATE_END(LoopProperties);
2061 if constexpr (HasCallback) {
2063 context.evaluator->instance_location.pop_back();
2068 EVALUATE_END(LoopProperties);
2071INSTRUCTION_HANDLER(LoopPropertiesEvaluate) {
2072 EVALUATE_BEGIN_NON_STRING(LoopPropertiesEvaluate, target.is_object());
2076 for (
const auto &entry : target.as_object()) {
2077 if constexpr (HasCallback) {
2079 context.evaluator->instance_location.push_back(entry.first);
2083 for (
const auto &child : instruction.children) {
2084 if (!EVALUATE_RECURSE(child, entry.second)) [[unlikely]] {
2087 if constexpr (HasCallback) {
2089 context.evaluator->instance_location.pop_back();
2093 EVALUATE_END(LoopPropertiesEvaluate);
2097 if constexpr (HasCallback) {
2099 context.evaluator->instance_location.pop_back();
2104 context.evaluator->evaluate(&target);
2105 EVALUATE_END(LoopPropertiesEvaluate);
2108INSTRUCTION_HANDLER(LoopPropertiesRegex) {
2109 EVALUATE_BEGIN_NON_STRING(LoopPropertiesRegex, target.is_object());
2110 assert(!instruction.children.empty());
2111 const auto &value{assume_value<ValueRegex>(instruction.value)};
2113 for (
const auto &entry : target.as_object()) {
2114 if (!matches(value.first, entry.first)) {
2118 if constexpr (HasCallback) {
2120 context.evaluator->instance_location.push_back(entry.first);
2124 for (
const auto &child : instruction.children) {
2125 if (!EVALUATE_RECURSE(child, entry.second)) [[unlikely]] {
2128 if constexpr (HasCallback) {
2130 context.evaluator->instance_location.pop_back();
2134 EVALUATE_END(LoopPropertiesRegex);
2138 if constexpr (HasCallback) {
2140 context.evaluator->instance_location.pop_back();
2145 EVALUATE_END(LoopPropertiesRegex);
2148INSTRUCTION_HANDLER(LoopPropertiesRegexClosed) {
2149 EVALUATE_BEGIN_NON_STRING(LoopPropertiesRegexClosed, target.is_object());
2151 const auto &value{assume_value<ValueRegex>(instruction.value)};
2152 for (
const auto &entry : target.as_object()) {
2153 if (!matches(value.first, entry.first)) [[unlikely]] {
2158 if (instruction.children.empty()) {
2162 if constexpr (HasCallback) {
2164 context.evaluator->instance_location.push_back(entry.first);
2168 for (
const auto &child : instruction.children) {
2169 if (!EVALUATE_RECURSE(child, entry.second)) [[unlikely]] {
2172 if constexpr (HasCallback) {
2174 context.evaluator->instance_location.pop_back();
2178 EVALUATE_END(LoopPropertiesRegexClosed);
2182 if constexpr (HasCallback) {
2184 context.evaluator->instance_location.pop_back();
2189 EVALUATE_END(LoopPropertiesRegexClosed);
2192INSTRUCTION_HANDLER(LoopPropertiesStartsWith) {
2193 EVALUATE_BEGIN_NON_STRING(LoopPropertiesStartsWith, target.is_object());
2194 assert(!instruction.children.empty());
2196 const auto &value{assume_value<ValueString>(instruction.value)};
2197 for (
const auto &entry : target.as_object()) {
2198 if (!entry.first.starts_with(value)) {
2202 if constexpr (HasCallback) {
2204 context.evaluator->instance_location.push_back(entry.first);
2208 for (
const auto &child : instruction.children) {
2209 if (!EVALUATE_RECURSE(child, entry.second)) [[unlikely]] {
2212 if constexpr (HasCallback) {
2214 context.evaluator->instance_location.pop_back();
2218 EVALUATE_END(LoopPropertiesStartsWith);
2222 if constexpr (HasCallback) {
2224 context.evaluator->instance_location.pop_back();
2229 EVALUATE_END(LoopPropertiesStartsWith);
2232INSTRUCTION_HANDLER(LoopPropertiesExcept) {
2233 EVALUATE_BEGIN_NON_STRING(LoopPropertiesExcept, target.is_object());
2234 assert(!instruction.children.empty());
2236 const auto &value{assume_value<ValuePropertyFilter>(instruction.value)};
2237 const auto &[filter_strings, filter_prefixes, filter_regexes] = value;
2239 assert(!filter_strings.empty() || !filter_prefixes.empty() ||
2240 !filter_regexes.empty());
2242 for (
const auto &entry : target.as_object()) {
2243 if (filter_strings.contains(entry.first, entry.hash)) {
2247 if (std::ranges::any_of(filter_prefixes,
2248 [&entry](
const auto &prefix) ->
bool {
2249 return entry.first.starts_with(prefix);
2254 if (std::ranges::any_of(filter_regexes,
2255 [&entry](
const auto &pattern) ->
bool {
2256 return matches(pattern.first, entry.first);
2261 if constexpr (HasCallback) {
2263 context.evaluator->instance_location.push_back(entry.first);
2267 for (
const auto &child : instruction.children) {
2268 if (!EVALUATE_RECURSE(child, entry.second)) [[unlikely]] {
2271 if constexpr (HasCallback) {
2273 context.evaluator->instance_location.pop_back();
2277 EVALUATE_END(LoopPropertiesExcept);
2281 if constexpr (HasCallback) {
2283 context.evaluator->instance_location.pop_back();
2288 EVALUATE_END(LoopPropertiesExcept);
2291INSTRUCTION_HANDLER(LoopPropertiesType) {
2292 EVALUATE_BEGIN_NON_STRING(LoopPropertiesType, target.is_object());
2294 const auto value{assume_value_copy<ValueType>(instruction.value)};
2295 for (
const auto &entry : target.as_object()) {
2296 if (entry.second.type() != value &&
2299 (value != JSON::Type::Integer || !entry.second.is_integral()))
2306 EVALUATE_END(LoopPropertiesType);
2309INSTRUCTION_HANDLER(LoopPropertiesTypeEvaluate) {
2310 EVALUATE_BEGIN_NON_STRING(LoopPropertiesTypeEvaluate, target.is_object());
2312 const auto value{assume_value_copy<ValueType>(instruction.value)};
2313 for (
const auto &entry : target.as_object()) {
2314 if (entry.second.type() != value &&
2317 (value != JSON::Type::Integer || !entry.second.is_integral()))
2320 EVALUATE_END(LoopPropertiesTypeEvaluate);
2324 context.evaluator->evaluate(&target);
2325 EVALUATE_END(LoopPropertiesTypeEvaluate);
2328INSTRUCTION_HANDLER(LoopPropertiesExactlyTypeStrict) {
2329 EVALUATE_BEGIN_NO_PRECONDITION(LoopPropertiesExactlyTypeStrict);
2331 resolve_instance(instance, instruction.relative_instance_location)};
2332 const auto &value{assume_value<ValueTypedProperties>(instruction.value)};
2333 if (!target.is_object()) [[unlikely]] {
2334 EVALUATE_END(LoopPropertiesExactlyTypeStrict);
2337 const auto &
object{target.as_object()};
2338 if (
object.size() == value.second.size()) [[likely]] {
2340 assert(!value.second.empty());
2342 for (
const auto &entry :
object) {
2346 if (!value.second.contains(entry.first, entry.hash) ||
2347 effective_type_strict_real(entry.second) != value.first)
2355 EVALUATE_END(LoopPropertiesExactlyTypeStrict);
2358INSTRUCTION_HANDLER(LoopPropertiesExactlyTypeStrictHash) {
2359 EVALUATE_BEGIN_NO_PRECONDITION(LoopPropertiesExactlyTypeStrictHash);
2361 resolve_instance(instance, instruction.relative_instance_location)};
2363 const auto &value{assume_value<ValueTypedHashes>(instruction.value)};
2365 if (!target.is_object()) [[unlikely]] {
2366 EVALUATE_END(LoopPropertiesExactlyTypeStrictHash);
2369 const auto &
object{target.as_object()};
2370 const auto size{
object.size()};
2371 if (size == value.second.first.size()) [[likely]] {
2373 assert(!value.second.first.empty());
2379 std::size_t index{0};
2380 for (
const auto &entry :
object) {
2381 if (effective_type_strict_real(entry.second) != value.first) {
2382 EVALUATE_END(LoopPropertiesExactlyTypeStrictHash);
2387 if (entry.hash != value.second.first[index].first ||
2388 entry.first != value.second.first[index].second) {
2397 auto iterator =
object.cbegin();
2399 std::advance(iterator, index);
2400 for (; iterator !=
object.cend(); ++iterator) {
2401 if (effective_type_strict_real(iterator->second) != value.first) {
2407 if (std::ranges::none_of(value.second.first,
2408 [&iterator](
const auto &entry) ->
bool {
2409 return entry.first == iterator->hash &&
2410 entry.second == iterator->first;
2419 EVALUATE_END(LoopPropertiesExactlyTypeStrictHash);
2422INSTRUCTION_HANDLER(LoopPropertiesTypeStrict) {
2423 EVALUATE_BEGIN_NON_STRING(LoopPropertiesTypeStrict, target.is_object());
2425 const auto value{assume_value_copy<ValueType>(instruction.value)};
2426 for (
const auto &entry : target.as_object()) {
2427 if (effective_type_strict_real(entry.second) != value) [[unlikely]] {
2433 EVALUATE_END(LoopPropertiesTypeStrict);
2436INSTRUCTION_HANDLER(LoopPropertiesTypeStrictEvaluate) {
2437 EVALUATE_BEGIN_NON_STRING(LoopPropertiesTypeStrictEvaluate,
2438 target.is_object());
2440 const auto value{assume_value_copy<ValueType>(instruction.value)};
2441 for (
const auto &entry : target.as_object()) {
2442 if (effective_type_strict_real(entry.second) != value) [[unlikely]] {
2444 EVALUATE_END(LoopPropertiesTypeStrictEvaluate);
2448 context.evaluator->evaluate(&target);
2449 EVALUATE_END(LoopPropertiesTypeStrictEvaluate);
2452INSTRUCTION_HANDLER(LoopPropertiesTypeStrictAny) {
2453 EVALUATE_BEGIN_NON_STRING(LoopPropertiesTypeStrictAny, target.is_object());
2455 const auto value{assume_value_copy<ValueTypes>(instruction.value)};
2456 assert(value.any());
2457 result = type_set_spans_numbers(value)
2458 ? object_values_in_type_set<false>(target, value)
2459 : object_values_in_type_set<true>(target, value);
2461 EVALUATE_END(LoopPropertiesTypeStrictAny);
2464INSTRUCTION_HANDLER(LoopPropertiesTypeStrictAnyEvaluate) {
2465 EVALUATE_BEGIN_NON_STRING(LoopPropertiesTypeStrictAnyEvaluate,
2466 target.is_object());
2468 const auto value{assume_value_copy<ValueTypes>(instruction.value)};
2469 assert(value.any());
2470 result = type_set_spans_numbers(value)
2471 ? object_values_in_type_set<false>(target, value)
2472 : object_values_in_type_set<true>(target, value);
2473 if (!result) [[unlikely]] {
2474 EVALUATE_END(LoopPropertiesTypeStrictAnyEvaluate);
2477 context.evaluator->evaluate(&target);
2478 EVALUATE_END(LoopPropertiesTypeStrictAnyEvaluate);
2481INSTRUCTION_HANDLER(LoopKeys) {
2482 EVALUATE_BEGIN_NON_STRING(LoopKeys, target.is_object());
2483 assert(!instruction.children.empty());
2485 for (
const auto &entry : target.as_object()) {
2486 if constexpr (HasCallback) {
2488 context.evaluator->instance_location.push_back(entry.first);
2492 for (
const auto &child : instruction.children) {
2493 if (!EVALUATE_RECURSE_ON_PROPERTY_NAME(child, Evaluator::NULL_VALUE,
2494 entry.first)) [[unlikely]] {
2497 if constexpr (HasCallback) {
2499 context.evaluator->instance_location.pop_back();
2503 EVALUATE_END(LoopKeys);
2507 if constexpr (HasCallback) {
2509 context.evaluator->instance_location.pop_back();
2514 EVALUATE_END(LoopKeys);
2517INSTRUCTION_HANDLER(LoopItems) {
2518 EVALUATE_BEGIN_NON_STRING(LoopItems, target.is_array());
2519 assert(!instruction.children.empty());
2523 if constexpr (!Track && !HasCallback) {
2528 const auto direct_children{!Dynamic && depth < DEPTH_LIMIT};
2529 for (
const auto &new_instance : target.as_array()) {
2530 for (
const auto &child : instruction.children) {
2532 if (direct_children) [[likely]] {
2533 switch (child.type) {
2534 case InstructionIndex::AssertionTypeArrayBounded:
2536 DIRECT(AssertionTypeArrayBounded,
2537 resolve_instance(new_instance,
2538 child.relative_instance_location),
2539 assume_value<ValueRange>(child.value));
2542 child_ok = EVALUATE_RECURSE(child, new_instance);
2546 child_ok = EVALUATE_RECURSE(child, new_instance);
2549 if (!child_ok) [[unlikely]] {
2551 EVALUATE_END(LoopItems);
2556 for (std::size_t index = 0; index < target.array_size(); index++) {
2557 if constexpr (HasCallback) {
2559 context.evaluator->instance_location.push_back(index);
2563 const auto &new_instance{target.at(index)};
2564 for (
const auto &child : instruction.children) {
2565 if (!EVALUATE_RECURSE(child, new_instance)) [[unlikely]] {
2568 if constexpr (HasCallback) {
2570 context.evaluator->instance_location.pop_back();
2574 EVALUATE_END(LoopItems);
2578 if constexpr (HasCallback) {
2580 context.evaluator->instance_location.pop_back();
2586 EVALUATE_END(LoopItems);
2589INSTRUCTION_HANDLER(LoopItemsFrom) {
2590 const auto value{assume_value_copy<ValueUnsignedInteger>(instruction.value)};
2591 EVALUATE_BEGIN_NON_STRING(LoopItemsFrom,
2592 target.is_array() && value < target.array_size());
2593 assert(!instruction.children.empty());
2595 for (std::size_t index = value; index < target.array_size(); index++) {
2596 if constexpr (HasCallback) {
2598 context.evaluator->instance_location.push_back(index);
2602 const auto &new_instance{target.at(index)};
2603 for (
const auto &child : instruction.children) {
2604 if (!EVALUATE_RECURSE(child, new_instance)) [[unlikely]] {
2607 if constexpr (HasCallback) {
2609 context.evaluator->instance_location.pop_back();
2613 EVALUATE_END(LoopItemsFrom);
2617 if constexpr (HasCallback) {
2619 context.evaluator->instance_location.pop_back();
2624 EVALUATE_END(LoopItemsFrom);
2627INSTRUCTION_HANDLER(LoopItemsUnevaluated) {
2628 EVALUATE_BEGIN_NON_STRING(LoopItemsUnevaluated, target.is_array());
2633 if (!context.evaluator->is_evaluated(&target)) {
2634 for (std::size_t index = 0; index < target.array_size(); index++) {
2635 const auto &new_instance{target.at(index)};
2636 if (context.evaluator->is_evaluated(&new_instance)) {
2640 if constexpr (HasCallback) {
2641 context.evaluator->instance_location.push_back(index);
2643 for (
const auto &child : instruction.children) {
2644 if (!EVALUATE_RECURSE(child, new_instance)) [[unlikely]] {
2646 if constexpr (HasCallback) {
2647 context.evaluator->instance_location.pop_back();
2649 EVALUATE_END(LoopItemsUnevaluated);
2653 if constexpr (HasCallback) {
2654 context.evaluator->instance_location.pop_back();
2658 context.evaluator->evaluate(&target);
2661 EVALUATE_END(LoopItemsUnevaluated);
2664INSTRUCTION_HANDLER(LoopItemsType) {
2665 EVALUATE_BEGIN_NON_STRING(LoopItemsType, target.is_array());
2667 const auto value{assume_value_copy<ValueType>(instruction.value)};
2668 for (
const auto &entry : target.as_array()) {
2669 if (entry.type() != value &&
2672 (value != JSON::Type::Integer || !entry.is_integral())) [[unlikely]] {
2678 EVALUATE_END(LoopItemsType);
2681INSTRUCTION_HANDLER(LoopItemsTypeStrict) {
2682 EVALUATE_BEGIN_NON_STRING(LoopItemsTypeStrict, target.is_array());
2684 const auto value{assume_value_copy<ValueType>(instruction.value)};
2685 for (
const auto &entry : target.as_array()) {
2686 if (effective_type_strict_real(entry) != value) [[unlikely]] {
2692 EVALUATE_END(LoopItemsTypeStrict);
2695INSTRUCTION_HANDLER(LoopItemsTypeStrictAny) {
2696 EVALUATE_BEGIN_NON_STRING(LoopItemsTypeStrictAny, target.is_array());
2697 const auto value{assume_value_copy<ValueTypes>(instruction.value)};
2698 assert(value.any());
2700 result = type_set_spans_numbers(value)
2701 ? array_items_in_type_set<false>(target, value)
2702 : array_items_in_type_set<true>(target, value);
2704 EVALUATE_END(LoopItemsTypeStrictAny);
2707INSTRUCTION_HANDLER(LoopItemsPropertiesExactlyTypeStrictHash) {
2708 EVALUATE_BEGIN_NO_PRECONDITION(LoopItemsPropertiesExactlyTypeStrictHash);
2710 resolve_instance(instance, instruction.relative_instance_location)};
2712 const auto &value{assume_value<ValueTypedHashes>(instruction.value)};
2714 assert(!value.second.first.empty());
2718 if (!target.is_array()) [[unlikely]] {
2719 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash);
2722 const auto hashes_size{value.second.first.size()};
2723 for (
const auto &item : target.as_array()) {
2724 if (!item.is_object()) [[unlikely]] {
2726 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash);
2729 const auto &
object{item.as_object()};
2730 const auto size{
object.size()};
2731 if (size != hashes_size) [[unlikely]] {
2733 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash);
2739 if (hashes_size == 3) {
2740 for (
const auto &entry :
object) {
2741 if (effective_type_strict_real(entry.second) != value.first)
2745 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash);
2746 }
else if (!(entry.hash == value.second.first[0].first ||
2747 entry.hash == value.second.first[1].first ||
2748 entry.hash == value.second.first[2].first)) {
2750 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash);
2753 }
else if (hashes_size == 2) {
2754 for (
const auto &entry :
object) {
2755 if (effective_type_strict_real(entry.second) != value.first)
2759 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash);
2760 }
else if (!(entry.hash == value.second.first[0].first ||
2761 entry.hash == value.second.first[1].first)) {
2763 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash);
2766 }
else if (hashes_size == 1) {
2767 const auto &entry{*
object.cbegin()};
2768 if (effective_type_strict_real(entry.second) != value.first ||
2769 entry.hash != value.second.first[0].first) [[unlikely]] {
2771 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash);
2774 std::size_t index{0};
2775 for (
const auto &entry :
object) {
2776 if (effective_type_strict_real(entry.second) != value.first)
2780 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash);
2781 }
else if (entry.hash == value.second.first[index].first) {
2784 }
else if (!std::ranges::any_of(
2786 [&entry](
const auto &hash_entry) ->
bool {
2787 return hash_entry.first == entry.hash;
2790 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash);
2798 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash);
2801INSTRUCTION_HANDLER(LoopItemsPropertiesExactlyTypeStrictHash3) {
2802 EVALUATE_BEGIN_NO_PRECONDITION(LoopItemsPropertiesExactlyTypeStrictHash3);
2804 resolve_instance(instance, instruction.relative_instance_location)};
2806 const auto &value{assume_value<ValueTypedHashes>(instruction.value)};
2807 assert(value.second.first.size() == 3);
2809 assert(!value.second.first.empty());
2811 if (!target.is_array()) [[unlikely]] {
2813 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash3);
2816 for (
const auto &item : target.as_array()) {
2817 if (!item.is_object()) [[unlikely]] {
2818 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash3);
2821 const auto &
object{item.as_object()};
2822 if (
object.size() != 3) [[unlikely]] {
2823 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash3);
2826 const auto &value_1{
object.at(0)};
2827 const auto &value_2{
object.at(1)};
2828 const auto &value_3{
object.at(2)};
2830 if (effective_type_strict_real(value_1.second) != value.first ||
2831 effective_type_strict_real(value_2.second) != value.first ||
2832 effective_type_strict_real(value_3.second) != value.first)
2834 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash3);
2840 if ((value_1.hash == value.second.first[0].first &&
2841 value_2.hash == value.second.first[1].first &&
2842 value_3.hash == value.second.first[2].first) ||
2843 (value_1.hash == value.second.first[0].first &&
2844 value_2.hash == value.second.first[2].first &&
2845 value_3.hash == value.second.first[1].first) ||
2846 (value_1.hash == value.second.first[1].first &&
2847 value_2.hash == value.second.first[0].first &&
2848 value_3.hash == value.second.first[2].first) ||
2849 (value_1.hash == value.second.first[1].first &&
2850 value_2.hash == value.second.first[2].first &&
2851 value_3.hash == value.second.first[0].first) ||
2852 (value_1.hash == value.second.first[2].first &&
2853 value_2.hash == value.second.first[0].first &&
2854 value_3.hash == value.second.first[1].first) ||
2855 (value_1.hash == value.second.first[2].first &&
2856 value_2.hash == value.second.first[1].first &&
2857 value_3.hash == value.second.first[0].first)) {
2860 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash3);
2864 EVALUATE_END(LoopItemsPropertiesExactlyTypeStrictHash3);
2868 if (!target.is_array() || target.empty()) {
2871 for (
const auto &element : target.as_array()) {
2872 if (!element.is_number()) [[unlikely]] {
2876 if (element.is_integer()) {
2877 const auto integer{element.to_integer()};
2878 if (integer < value.first || integer > value.second) [[unlikely]] {
2881 }
else if (element.is_real()) {
2882 const auto real{element.to_real()};
2883 if (real <
static_cast<double>(value.first) ||
2884 real >
static_cast<double>(value.second)) [[unlikely]] {
2888 const auto real{element.to_decimal().to_double()};
2889 if (real <
static_cast<double>(value.first) ||
2890 real >
static_cast<double>(value.second)) [[unlikely]] {
2898INSTRUCTION_HANDLER(LoopItemsIntegerBounded) {
2899 EVALUATE_BEGIN_NON_STRING(LoopItemsIntegerBounded,
2900 target.is_array() && !target.empty());
2901 result = DIRECT(LoopItemsIntegerBounded, target,
2902 assume_value_copy<ValueIntegerBounds>(instruction.value));
2903 EVALUATE_END(LoopItemsIntegerBounded);
2906INSTRUCTION_HANDLER(LoopItemsIntegerBoundedSized) {
2908 assume_value<ValueIntegerBoundsWithSize>(instruction.value)};
2909 const auto &integer_bounds{value.first};
2910 const auto minimum_size{std::get<0>(value.second)};
2911 const auto &maximum_size{std::get<1>(value.second)};
2912 EVALUATE_BEGIN_NON_STRING(LoopItemsIntegerBoundedSized,
true);
2913 if (!target.is_array() || target.array_size() < minimum_size ||
2914 (maximum_size.has_value() &&
2915 target.array_size() > maximum_size.value())) {
2916 EVALUATE_END(LoopItemsIntegerBoundedSized);
2920 for (
const auto &element : target.as_array()) {
2921 if (!element.is_number()) [[unlikely]] {
2926 if (element.is_integer()) {
2927 const auto integer{element.to_integer()};
2928 if (integer < integer_bounds.first || integer > integer_bounds.second)
2933 }
else if (element.is_real()) {
2934 const auto real{element.to_real()};
2935 if (real <
static_cast<double>(integer_bounds.first) ||
2936 real >
static_cast<double>(integer_bounds.second)) [[unlikely]] {
2941 const auto real{element.to_decimal().to_double()};
2942 if (real <
static_cast<double>(integer_bounds.first) ||
2943 real >
static_cast<double>(integer_bounds.second)) [[unlikely]] {
2950 EVALUATE_END(LoopItemsIntegerBoundedSized);
2957INSTRUCTION_HANDLER(LoopItemsArrayBoundedTypeStrictAny) {
2958 EVALUATE_BEGIN_NON_STRING(LoopItemsArrayBoundedTypeStrictAny,
2960 const auto &value{assume_value<ValueTypesWithSize>(instruction.value)};
2961 const auto types{value.first};
2962 const auto minimum{std::get<0>(value.second)};
2963 const auto &maximum{std::get<1>(value.second)};
2964 assert(types.any());
2966 assert(!std::get<2>(value.second));
2967 result = type_set_spans_numbers(types)
2968 ? items_are_bounded_arrays_in_type_set<false>(target, types,
2970 : items_are_bounded_arrays_in_type_set<true>(target, types,
2973 EVALUATE_END(LoopItemsArrayBoundedTypeStrictAny);
2976INSTRUCTION_HANDLER(LoopContains) {
2977 EVALUATE_BEGIN_NON_STRING(LoopContains, target.is_array());
2980 const auto &value{assume_value<ValueRange>(instruction.value)};
2981 const auto &[minimum, maximum, is_exhaustive] = value;
2984 result = minimum == 0;
2986 std::numeric_limits<std::remove_cvref_t<
decltype(minimum)>>::min()};
2988 for (std::size_t index = 0; index < target.array_size(); index++) {
2989 if constexpr (HasCallback) {
2991 context.evaluator->instance_location.push_back(index);
2995 const auto &new_instance{target.at(index)};
2996 bool subresult{
true};
2997 for (
const auto &child : instruction.children) {
2998 if (!EVALUATE_RECURSE(child, new_instance)) {
3004 if constexpr (HasCallback) {
3006 context.evaluator->instance_location.pop_back();
3014 if (maximum.has_value() && match_count > maximum.value()) {
3023 if (match_count >= minimum) {
3028 if (!maximum.has_value() && !is_exhaustive) {
3035 EVALUATE_END(LoopContains);
3039#undef INSTRUCTION_HANDLER
3041template <
bool Track,
bool Dynamic,
bool HasCallback>
3042using DispatchHandler = bool (*)(
3043 const sourcemeta::blaze::Instruction &,
const sourcemeta::core::JSON &,
3046template <
bool Track,
bool Dynamic,
bool HasCallback>
3049static constexpr DispatchHandler<Track, Dynamic, HasCallback> HANDLERS[105] = {
3052 AssertionDefinesStrict,
3053 AssertionDefinesAll,
3054 AssertionDefinesAllStrict,
3055 AssertionDefinesExactly,
3056 AssertionDefinesExactlyStrict,
3057 AssertionDefinesExactlyStrictHash3,
3058 AssertionPropertyDependencies,
3061 AssertionTypeStrict,
3062 AssertionTypeStrictAny,
3063 AssertionNotTypeStrictAny,
3064 AssertionTypeStringBounded,
3065 AssertionTypeStringUpper,
3066 AssertionTypeArrayBounded,
3067 AssertionTypeArrayUpper,
3068 AssertionTypeObjectBounded,
3069 AssertionTypeObjectUpper,
3071 AssertionStringSizeLess,
3072 AssertionStringSizeGreater,
3073 AssertionArraySizeLess,
3074 AssertionArraySizeGreater,
3075 AssertionObjectSizeLess,
3076 AssertionObjectSizeGreater,
3079 AssertionEqualsAnyStringHash,
3080 AssertionGreaterEqual,
3086 AssertionTypeIntegerBounded,
3087 AssertionTypeIntegerBoundedStrict,
3088 AssertionTypeIntegerLowerBound,
3089 AssertionTypeIntegerLowerBoundStrict,
3090 AssertionNumberIntegerBounded,
3091 AssertionNumberType,
3092 AssertionStringType,
3093 AssertionPropertyType,
3094 AssertionPropertyTypeEvaluate,
3095 AssertionPropertyTypeStrict,
3096 AssertionPropertyTypeStrictEvaluate,
3097 AssertionPropertyTypeStrictAny,
3098 AssertionPropertyTypeStrictAnyEvaluate,
3099 AssertionPropertyEqual,
3100 AssertionArrayPrefix,
3101 AssertionArrayPrefixEvaluate,
3102 AssertionObjectPropertiesSimple,
3104 AnnotationEmitWrapped,
3106 AnnotationBasenameToParent,
3116 LogicalWhenArraySizeGreater,
3117 LoopPropertiesUnevaluated,
3118 LoopPropertiesUnevaluatedExcept,
3119 LoopPropertiesMatch,
3120 LoopPropertiesMatchClosed,
3122 LoopPropertiesEvaluate,
3123 LoopPropertiesRegex,
3124 LoopPropertiesRegexClosed,
3125 LoopPropertiesStartsWith,
3126 LoopPropertiesExcept,
3128 LoopPropertiesTypeEvaluate,
3129 LoopPropertiesExactlyTypeStrict,
3130 LoopPropertiesExactlyTypeStrictHash,
3131 LoopPropertiesTypeStrict,
3132 LoopPropertiesTypeStrictEvaluate,
3133 LoopPropertiesTypeStrictAny,
3134 LoopPropertiesTypeStrictAnyEvaluate,
3138 LoopItemsUnevaluated,
3140 LoopItemsTypeStrict,
3141 LoopItemsTypeStrictAny,
3142 LoopItemsPropertiesExactlyTypeStrictHash,
3143 LoopItemsPropertiesExactlyTypeStrictHash3,
3144 LoopItemsIntegerBounded,
3145 LoopItemsIntegerBoundedSized,
3146 LoopItemsArrayBoundedTypeStrictAny,
3149 ControlGroupWhenDefines,
3150 ControlGroupWhenDefinesDirect,
3151 ControlGroupWhenType,
3153 ControlDynamicAnchorJump,
3156template <
bool Track,
bool Dynamic,
bool HasCallback>
3158evaluate_instruction(
const sourcemeta::blaze::Instruction &instruction,
3159 const sourcemeta::core::JSON &instance,
3160 const std::uint64_t depth,
3163 if (depth > DEPTH_LIMIT) [[unlikely]] {
3164 throw EvaluationError(
"The evaluation path depth limit was reached "
3165 "likely due to infinite recursion");
3168 return HANDLERS<Track, Dynamic, HasCallback>[std::to_underlying(
3169 instruction.type)](instruction, instance, depth, context);
3172template <
bool Track,
bool Dynamic,
bool HasCallback>
3173inline auto evaluate_instruction_without_callback(
3174 const sourcemeta::blaze::Instruction &instruction,
3175 const sourcemeta::core::JSON &instance,
const std::uint64_t depth,
3177 if (depth > DEPTH_LIMIT) [[unlikely]] {
3178 throw EvaluationError(
"The evaluation path depth limit was reached "
3179 "likely due to infinite recursion");
3183 context.schema, context.callback, context.evaluator,
3184 context.property_target};
3185 return HANDLERS<false, Dynamic, false>[std::to_underlying(instruction.type)](
3186 instruction, instance, depth, plain_context);
3189template <
bool Track,
bool Dynamic,
bool HasCallback>
3190inline auto evaluate_instruction_with_property(
3191 const sourcemeta::blaze::Instruction &instruction,
3192 const sourcemeta::core::JSON &instance,
const std::uint64_t depth,
3194 const sourcemeta::core::JSON::String &name) ->
bool {
3195 const auto *previous = context.property_target;
3196 context.property_target = &name;
3198 evaluate_instruction(instruction, instance, depth, context);
3199 context.property_target = previous;
3207#undef EVALUATE_BEGIN
3208#undef EVALUATE_BEGIN_NON_STRING
3209#undef EVALUATE_BEGIN_IF_STRING
3210#undef EVALUATE_BEGIN_TRY_TARGET
3211#undef EVALUATE_BEGIN_NO_PRECONDITION
3212#undef EVALUATE_BEGIN_NO_PRECONDITION_AND_NO_PUSH
3213#undef EVALUATE_BEGIN_PASS_THROUGH
3215#undef EVALUATE_END_NO_POP
3216#undef EVALUATE_END_PASS_THROUGH
3217#undef EVALUATE_ANNOTATION
3218#undef EVALUATE_RECURSE
3219#undef EVALUATE_RECURSE_ON_PROPERTY_NAME
3220#undef SOURCEMETA_ASSUME
3221#undef SOURCEMETA_STRINGIFY
std::pair< std::vector< std::pair< ValueStringSet::hash_type, ValueString > >, std::vector< ValueIndexPair > > ValueStringHashes
Definition evaluator_value.h:180
sourcemeta::core::JSON::Type ValueType
Definition evaluator_value.h:64
std::function< void( const EvaluationType, bool, const Instruction &, const InstructionExtra &, const sourcemeta::core::WeakPointer &, const sourcemeta::core::WeakPointer &, const sourcemeta::core::JSON &)> Callback
Definition evaluator.h:77
sourcemeta::core::JSON ValueJSON
Definition evaluator_value.h:33
sourcemeta::core::JSON::TypeSet ValueTypes
Definition evaluator_value.h:60
std::pair< std::vector< ValueNamedIndex >, std::vector< ValueIndexPair > > ValueNamedIndexes
Definition evaluator_value.h:171
std::size_t ValueUnsignedInteger
Definition evaluator_value.h:101
std::tuple< std::size_t, std::optional< std::size_t >, bool > ValueRange
Definition evaluator_value.h:107
std::pair< std::int64_t, std::int64_t > ValueIntegerBounds
Definition evaluator_value.h:190
std::unordered_set< sourcemeta::core::JSON, sourcemeta::core::HashJSON< sourcemeta::core::JSON > > ValueSet
Definition evaluator_value.h:37
Definition evaluator_dispatch.h:421