Skip to content

Commit b10c861

Browse files
authored
Support converting Instruction to JSON (#453)
Signed-off-by: Juan Cruz Viotti <[email protected]>
1 parent ca9b508 commit b10c861

File tree

18 files changed

+246
-82
lines changed

18 files changed

+246
-82
lines changed

DEPENDENCIES

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
vendorpull https://github.com/sourcemeta/vendorpull dea311b5bfb53b6926a4140267959ae334d3ecf4
2-
core https://github.com/sourcemeta/core 435c78ca85510b428840c3ca06be7e9eeb838cd5
2+
core https://github.com/sourcemeta/core 2aab6820e4b4ff7062954c7ee4f55aea04112496
33
jsonschema-test-suite https://github.com/json-schema-org/JSON-Schema-Test-Suite 48461fc3568972801b40eaccc428a31bce338f6e

src/compiler/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ sourcemeta_library(NAMESPACE sourcemeta PROJECT blaze NAME compiler
22
FOLDER "Blaze/Compiler"
33
PRIVATE_HEADERS error.h output.h unevaluated.h
44
SOURCES
5-
compile.cc compile_describe.cc
5+
compile.cc compile_describe.cc compile_json.cc
66
compile_output_simple.cc compile_output_trace.cc
77
compile_helpers.h default_compiler.cc unevaluated.cc
88
default_compiler_2020_12.h

src/compiler/compile_json.cc

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include <sourcemeta/blaze/compiler.h>
2+
3+
#include <variant> // std::visit
4+
5+
namespace sourcemeta::core {
6+
template <typename T>
7+
requires std::is_same_v<T, sourcemeta::blaze::ValueNone>
8+
auto to_json(const T &) -> JSON {
9+
return JSON{nullptr};
10+
}
11+
template <typename T>
12+
requires std::is_same_v<T, typename sourcemeta::blaze::ValueRegex::first_type>
13+
auto to_json(const T &) -> JSON {
14+
return JSON{nullptr};
15+
}
16+
template <typename T>
17+
requires std::is_same_v<T, sourcemeta::blaze::ValueRegex>
18+
auto to_json(const T &value) -> JSON {
19+
return JSON{value.second};
20+
}
21+
} // namespace sourcemeta::core
22+
23+
namespace sourcemeta::blaze {
24+
25+
auto to_json(const Instruction &instruction) -> sourcemeta::core::JSON {
26+
auto result{sourcemeta::core::JSON::make_object()};
27+
// We use single characters to save space, as this serialised format
28+
// is not meant to be human-readable anyway
29+
result.assign("t", sourcemeta::core::to_json(instruction.type));
30+
result.assign(
31+
"s", sourcemeta::core::to_json(instruction.relative_schema_location));
32+
result.assign(
33+
"i", sourcemeta::core::to_json(instruction.relative_instance_location));
34+
result.assign("k", sourcemeta::core::to_json(instruction.keyword_location));
35+
result.assign("r", sourcemeta::core::to_json(instruction.schema_resource));
36+
37+
auto value{sourcemeta::core::JSON::make_object()};
38+
value.assign("t", sourcemeta::core::to_json(instruction.value.index()));
39+
value.assign("v", std::visit(
40+
[](const auto &variant) {
41+
return sourcemeta::core::to_json(variant);
42+
},
43+
instruction.value));
44+
result.assign("v", std::move(value));
45+
46+
assert(result.at("v").is_object());
47+
assert(result.at("v").size() == 2);
48+
assert(result.at("v").defines("t"));
49+
assert(result.at("v").defines("v"));
50+
assert(result.at("v").at("t").is_integer());
51+
52+
auto children_json{sourcemeta::core::JSON::make_array()};
53+
result.assign("c", sourcemeta::core::to_json(instruction.children,
54+
[](const auto &subinstruction) {
55+
return to_json(subinstruction);
56+
}));
57+
return result;
58+
}
59+
60+
auto to_json(const Template &schema_template) -> sourcemeta::core::JSON {
61+
auto result{sourcemeta::core::JSON::make_object()};
62+
result.assign("dynamic", sourcemeta::core::JSON{schema_template.dynamic});
63+
result.assign("track", sourcemeta::core::JSON{schema_template.track});
64+
result.assign("instructions",
65+
sourcemeta::core::to_json(schema_template.instructions,
66+
[](const auto &instruction) {
67+
return to_json(instruction);
68+
}));
69+
return result;
70+
}
71+
72+
} // namespace sourcemeta::blaze

src/compiler/include/sourcemeta/blaze/compiler.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,16 @@ compile(const Context &context, const SchemaContext &schema_context,
185185
sourcemeta::core::empty_pointer,
186186
const std::optional<std::string> &uri = std::nullopt) -> Instructions;
187187

188+
/// @ingroup compiler
189+
/// Serialise an instruction as JSON
190+
auto SOURCEMETA_BLAZE_COMPILER_EXPORT to_json(const Instruction &instruction)
191+
-> sourcemeta::core::JSON;
192+
193+
/// @ingroup compiler
194+
/// Serialise a template as JSON
195+
auto SOURCEMETA_BLAZE_COMPILER_EXPORT to_json(const Template &schema_template)
196+
-> sourcemeta::core::JSON;
197+
188198
} // namespace sourcemeta::blaze
189199

190200
#endif

src/evaluator/include/sourcemeta/blaze/evaluator_string_set.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ class SOURCEMETA_BLAZE_EVALUATOR_EXPORT StringSet {
4545
inline auto cbegin() const -> const_iterator { return this->data.cbegin(); }
4646
inline auto cend() const -> const_iterator { return this->data.cend(); }
4747

48+
auto to_json() const -> sourcemeta::core::JSON {
49+
return sourcemeta::core::to_json(this->data, [](const auto &item) {
50+
return sourcemeta::core::to_json(item.first);
51+
});
52+
}
53+
4854
private:
4955
// Exporting symbols that depends on the standard C++ library is considered
5056
// safe.

test/compiler/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ sourcemeta_googletest(NAMESPACE sourcemeta PROJECT blaze NAME compiler
55
compiler_output_trace_test.cc
66
compiler_unevaluated_2019_09_test.cc
77
compiler_unevaluated_2020_12_test.cc
8+
compiler_json_test.cc
89
compiler_test_utils.h)
910

1011
target_link_libraries(sourcemeta_blaze_compiler_unit
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#include <gtest/gtest.h>
2+
3+
#include <sourcemeta/blaze/compiler.h>
4+
5+
// TODO: Eventually test parsing the JSON back and asserting that it equals the
6+
// original template, using a helper macro to define each test
7+
8+
TEST(Compiler_JSON, example_1) {
9+
const sourcemeta::core::JSON schema{sourcemeta::core::parse_json(R"JSON({
10+
"$schema": "https://json-schema.org/draft/2020-12/schema",
11+
"type": "string"
12+
})JSON")};
13+
14+
const auto schema_template{sourcemeta::blaze::compile(
15+
schema, sourcemeta::core::schema_official_walker,
16+
sourcemeta::core::schema_official_resolver,
17+
sourcemeta::blaze::default_schema_compiler)};
18+
19+
const auto result{sourcemeta::blaze::to_json(schema_template)};
20+
21+
const sourcemeta::core::JSON expected{sourcemeta::core::parse_json(R"JSON({
22+
"dynamic": false,
23+
"track": false,
24+
"instructions": [
25+
{
26+
"t": 11,
27+
"s": "/type",
28+
"i": "",
29+
"k": "#/type",
30+
"r": 0,
31+
"v": {
32+
"t": 8,
33+
"v": 4
34+
},
35+
"c": []
36+
}
37+
]
38+
})JSON")};
39+
40+
EXPECT_EQ(result, expected);
41+
}
42+
43+
TEST(Compiler_JSON, example_2) {
44+
const sourcemeta::core::JSON schema{sourcemeta::core::parse_json(R"JSON({
45+
"$schema": "https://json-schema.org/draft/2020-12/schema",
46+
"additionalProperties": {
47+
"type": [ "number", "string" ],
48+
"multipleOf": 2
49+
}
50+
})JSON")};
51+
52+
const auto schema_template{sourcemeta::blaze::compile(
53+
schema, sourcemeta::core::schema_official_walker,
54+
sourcemeta::core::schema_official_resolver,
55+
sourcemeta::blaze::default_schema_compiler)};
56+
57+
const auto result{sourcemeta::blaze::to_json(schema_template)};
58+
59+
const sourcemeta::core::JSON expected{sourcemeta::core::parse_json(R"JSON({
60+
"dynamic": false,
61+
"track": false,
62+
"instructions": [
63+
{
64+
"t": 61,
65+
"s": "/additionalProperties",
66+
"i": "",
67+
"k": "#/additionalProperties",
68+
"r": 0,
69+
"v": {
70+
"t": 0,
71+
"v": null
72+
},
73+
"c": [
74+
{
75+
"t": 34,
76+
"s": "/multipleOf",
77+
"i": "",
78+
"k": "#/additionalProperties/multipleOf",
79+
"r": 0,
80+
"v": {
81+
"t": 1,
82+
"v": 2
83+
},
84+
"c": []
85+
},
86+
{
87+
"t": 10,
88+
"s": "/type",
89+
"i": "",
90+
"k": "#/additionalProperties/type",
91+
"r": 0,
92+
"v": {
93+
"t": 7,
94+
"v": [ 2, 3, 4 ]
95+
},
96+
"c": []
97+
}
98+
]
99+
}
100+
]
101+
})JSON")};
102+
103+
EXPECT_EQ(result, expected);
104+
}

vendor/core/cmake/common/targets/clang-tidy.config

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/core/src/core/json/include/sourcemeta/core/json_auto.h

Lines changed: 31 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/core/src/core/json/include/sourcemeta/core/json_value.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)