-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathir.cc
More file actions
85 lines (68 loc) · 3.45 KB
/
ir.cc
File metadata and controls
85 lines (68 loc) · 3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <sourcemeta/codegen/ir.h>
#include <sourcemeta/core/alterschema.h>
#include <algorithm> // std::ranges::sort
#include <cassert> // assert
#include <unordered_set> // std::unordered_set
#include "ir_default_compiler.h"
namespace sourcemeta::codegen {
auto compile(const sourcemeta::core::JSON &input,
const sourcemeta::core::SchemaWalker &walker,
const sourcemeta::core::SchemaResolver &resolver,
const Compiler &compiler, const std::string_view default_dialect,
const std::string_view default_id) -> IRResult {
// --------------------------------------------------------------------------
// (1) Bundle the schema to resolve external references
// --------------------------------------------------------------------------
auto schema{sourcemeta::core::bundle(input, walker, resolver, default_dialect,
default_id)};
// --------------------------------------------------------------------------
// (2) Canonicalize the schema for easier analysis
// --------------------------------------------------------------------------
sourcemeta::core::SchemaTransformer canonicalizer;
sourcemeta::core::add(canonicalizer,
sourcemeta::core::AlterSchemaMode::Canonicalizer);
[[maybe_unused]] const auto canonicalized{canonicalizer.apply(
schema, walker, resolver,
[](const auto &, const auto, const auto, const auto &) { assert(false); },
default_dialect, default_id)};
assert(canonicalized.first);
// --------------------------------------------------------------------------
// (3) Frame the resulting schema with instance location information
// --------------------------------------------------------------------------
sourcemeta::core::SchemaFrame frame{
sourcemeta::core::SchemaFrame::Mode::References};
frame.analyse(schema, walker, resolver, default_dialect, default_id);
// --------------------------------------------------------------------------
// (4) Convert every subschema into a code generation object
// --------------------------------------------------------------------------
std::unordered_set<sourcemeta::core::WeakPointer> visited;
IRResult result;
for (const auto &[key, location] : frame.locations()) {
if (location.type !=
sourcemeta::core::SchemaFrame::LocationType::Resource &&
location.type !=
sourcemeta::core::SchemaFrame::LocationType::Subschema) {
continue;
}
// Framing may report resource twice or more given default identifiers and
// nested resources
const auto [visited_iterator, inserted] = visited.insert(location.pointer);
if (!inserted) {
continue;
}
const auto &subschema{sourcemeta::core::get(schema, location.pointer)};
result.push_back(compiler(schema, frame, location, resolver, subschema));
}
// --------------------------------------------------------------------------
// (5) Sort entries so that dependencies come before dependents
// --------------------------------------------------------------------------
std::ranges::sort(
result, [](const IREntity &left, const IREntity &right) -> bool {
return std::visit([](const auto &entry) { return entry.pointer; },
right) <
std::visit([](const auto &entry) { return entry.pointer; },
left);
});
return result;
}
} // namespace sourcemeta::codegen