Skip to content

Commit

Permalink
[WIP] Revamp unevaluated(Properties|Items) dependency detection
Browse files Browse the repository at this point in the history
Signed-off-by: Juan Cruz Viotti <[email protected]>
  • Loading branch information
jviotti committed Jan 1, 2025
1 parent 584229a commit 4898927
Show file tree
Hide file tree
Showing 15 changed files with 907 additions and 296 deletions.
2 changes: 1 addition & 1 deletion DEPENDENCIES
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
vendorpull https://github.com/sourcemeta/vendorpull dea311b5bfb53b6926a4140267959ae334d3ecf4
noa https://github.com/sourcemeta/noa 99f8b42d5f1a8b0f9b3c024f5957dc399bc0262f
jsontoolkit https://github.com/sourcemeta/jsontoolkit 2e2d2042fe3cb7e7066d29847859d889b2ccab6a
jsontoolkit https://github.com/sourcemeta/jsontoolkit b6ec3463c3abe11c3a507d198c382e9d0bc39ba9
googletest https://github.com/google/googletest a7f443b80b105f940225332ed3c31f2790092f47
googlebenchmark https://github.com/google/benchmark 378fe693a1ef51500db21b11ff05a8018c5f0e55
jsonschema-test-suite https://github.com/json-schema-org/JSON-Schema-Test-Suite c2badb1298a8698f86dadf1aea7b44b3a894e5ac
4 changes: 4 additions & 0 deletions src/compiler/compile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,9 @@ auto compile(const sourcemeta::jsontoolkit::JSON &schema,
}
}

auto unevaluated{sourcemeta::jsontoolkit::unevaluated(
result, frame, references, walker, resolver)};

const Context context{result,
frame,
references,
Expand All @@ -292,6 +295,7 @@ auto compile(const sourcemeta::jsontoolkit::JSON &schema,
compiler,
mode,
uses_dynamic_scopes,
std::move(unevaluated),
unevaluated_properties_schemas,
unevaluated_items_schemas,
std::move(precompiled_static_schemas)};
Expand Down
19 changes: 19 additions & 0 deletions src/compiler/compile_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,25 @@ inline auto make_property(const ValueString &property) -> ValueProperty {
return {property, hasher(property)};
}

inline auto requires_evaluation(const Context &context,
const SchemaContext &schema_context) -> bool {
const auto &entry{static_frame_entry(context, schema_context)};
for (const auto &unevaluated : context.unevaluated) {
if (unevaluated.second.unresolved ||
unevaluated.second.dynamic_dependencies.contains(entry.pointer)) {
return true;
}

for (const auto &dependency : unevaluated.second.dynamic_dependencies) {
if (entry.pointer.starts_with(dependency)) {
return true;
}
}
}

return false;
}

} // namespace sourcemeta::blaze

#endif
33 changes: 8 additions & 25 deletions src/compiler/default_compiler_2019_09.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "compile_helpers.h"
#include "default_compiler_draft4.h"

#include <iostream> // TODO DEBUG

namespace internal {
using namespace sourcemeta::blaze;

Expand Down Expand Up @@ -195,11 +197,12 @@ auto compiler_2019_09_applicator_contains(const Context &context,
auto compiler_2019_09_applicator_additionalproperties(
const Context &context, const SchemaContext &schema_context,
const DynamicContext &dynamic_context, const Instructions &)

-> Instructions {
return compiler_draft4_applicator_additionalproperties_with_options(
context, schema_context, dynamic_context,
context.mode == Mode::Exhaustive,
!context.unevaluated_properties_schemas.empty());
requires_evaluation(context, schema_context));
}

auto compiler_2019_09_applicator_items(const Context &context,
Expand All @@ -209,7 +212,7 @@ auto compiler_2019_09_applicator_items(const Context &context,
return compiler_draft4_applicator_items_with_options(
context, schema_context, dynamic_context,
context.mode == Mode::Exhaustive,
!context.unevaluated_items_schemas.empty());
requires_evaluation(context, schema_context));
}

auto compiler_2019_09_applicator_additionalitems(
Expand All @@ -219,7 +222,7 @@ auto compiler_2019_09_applicator_additionalitems(
return compiler_draft4_applicator_additionalitems_with_options(
context, schema_context, dynamic_context,
context.mode == Mode::Exhaustive,
!context.unevaluated_items_schemas.empty());
requires_evaluation(context, schema_context));
}

auto compiler_2019_09_applicator_unevaluateditems(
Expand Down Expand Up @@ -361,40 +364,20 @@ auto compiler_2019_09_applicator_properties(
const Context &context, const SchemaContext &schema_context,
const DynamicContext &dynamic_context, const Instructions &current)
-> Instructions {
// If there is a sibling `unevaluatedProperties`, then no need
// to track evaluation, as that keyword will statically consider
// these properties through `ValuePropertyFilter`
if (context.unevaluated_properties_schemas.contains(
static_frame_entry(context, schema_context).pointer.initial())) {
return compiler_draft4_applicator_properties_with_options(
context, schema_context, dynamic_context, current,
context.mode == Mode::Exhaustive, false);
}

return compiler_draft4_applicator_properties_with_options(
context, schema_context, dynamic_context, current,
context.mode == Mode::Exhaustive,
!context.unevaluated_properties_schemas.empty());
requires_evaluation(context, schema_context));
}

auto compiler_2019_09_applicator_patternproperties(
const Context &context, const SchemaContext &schema_context,
const DynamicContext &dynamic_context, const Instructions &)
-> Instructions {
// If there is a sibling `unevaluatedProperties`, then no need
// to track evaluation, as that keyword will statically consider
// these properties through `ValuePropertyFilter`
if (context.unevaluated_properties_schemas.contains(
static_frame_entry(context, schema_context).pointer.initial())) {
return compiler_draft4_applicator_patternproperties_with_options(
context, schema_context, dynamic_context,
context.mode == Mode::Exhaustive, false);
}

return compiler_draft4_applicator_patternproperties_with_options(
context, schema_context, dynamic_context,
context.mode == Mode::Exhaustive,
!context.unevaluated_properties_schemas.empty());
requires_evaluation(context, schema_context));
}

} // namespace internal
Expand Down
15 changes: 5 additions & 10 deletions src/compiler/default_compiler_draft4.h
Original file line number Diff line number Diff line change
Expand Up @@ -702,10 +702,8 @@ auto compiler_draft4_applicator_anyof(const Context &context,
}
}

const auto requires_exhaustive{
context.mode == Mode::Exhaustive ||
!context.unevaluated_properties_schemas.empty() ||
!context.unevaluated_items_schemas.empty()};
const auto requires_exhaustive{context.mode == Mode::Exhaustive ||
requires_evaluation(context, schema_context)};

return {make(sourcemeta::blaze::InstructionIndex::LogicalOr, context,
schema_context, dynamic_context,
Expand All @@ -731,10 +729,8 @@ auto compiler_draft4_applicator_oneof(const Context &context,
index)})));
}

const auto requires_exhaustive{
context.mode == Mode::Exhaustive ||
!context.unevaluated_properties_schemas.empty() ||
!context.unevaluated_items_schemas.empty()};
const auto requires_exhaustive{context.mode == Mode::Exhaustive ||
requires_evaluation(context, schema_context)};

return {make(sourcemeta::blaze::InstructionIndex::LogicalXor, context,
schema_context, dynamic_context,
Expand Down Expand Up @@ -1460,8 +1456,7 @@ auto compiler_draft4_applicator_not(const Context &context,
// evaluation if we really need it. If the "not" subschema
// does not define applicators, then that's an easy case
// we can skip
if (subschemas > 0 && (!context.unevaluated_properties_schemas.empty() ||
!context.unevaluated_items_schemas.empty())) {
if (subschemas > 0 && requires_evaluation(context, schema_context)) {
return {make(sourcemeta::blaze::InstructionIndex::LogicalNotEvaluate,
context, schema_context, dynamic_context, ValueNone{},
std::move(children))};
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/include/sourcemeta/blaze/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ struct Context {
const Mode mode;
/// Whether the schema makes use of dynamic scoping
const bool uses_dynamic_scopes;
/// The list of unevaluated entries and their dependencies
const sourcemeta::jsontoolkit::UnevaluatedEntries unevaluated;
/// The list of subschemas that require keeping track of unevaluated
/// properties
const std::set<sourcemeta::jsontoolkit::Pointer>
Expand Down
4 changes: 2 additions & 2 deletions vendor/jsontoolkit/src/jsonschema/CMakeLists.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 4898927

Please sign in to comment.