| chigraph master Systems programming language written for beginners in LLVM

Result.cpp
Go to the documentation of this file.
1
3 #include "chi/Support/Result.hpp"
4
5 #include <boost/range/adaptor/reversed.hpp>
6
7 namespace {
8
10 void mergeJsonIntoConservative(nlohmann::json& into, const nlohmann::json& from) {
11 for (const auto& j : nlohmann::json::iterator_wrapper(from)) {
12 if (into.find(j.key()) == into.end()) { into[j.key()] = j.value(); }
13 }
14 }
15
16 std::string prettyPrintJson(const nlohmann::json& j, int indentLevel) {
17 std::string indentString(indentLevel * 2, ' ');
18
19 std::string ret;
20 if (j.is_array()) {
21 ret += indentString + "[\n";
22
23 for (const auto& elem : j) {
24 ret += prettyPrintJson(elem, indentLevel + 1);
25 ret += ",\n";
26 }
27 ret += indentString + "]";
28
29 } else if (j.is_string()) {
30 std::string str = j;
31
32 // replace find and indent them
33 for (auto idx = str.find('\n'); idx < str.length(); idx = str.find('\n', idx + 1)) {
34 str.insert(idx + 1, indentString); // + 1 because it inserts before
35 }
36 ret += indentString + str;
37 } else if (j.is_number()) {
38 ret += indentString + j.dump();
39 } else if (j.is_object()) {
40 for (auto iter = j.begin(); iter != j.end(); ++iter) {
41 ret += indentString + iter.key() + "\n";
42 ret += prettyPrintJson(iter.value(), indentLevel + 1) + "\n";
43 }
44 }
45 return ret;
46 }
47
48 } // anonymous namespace
49
50 namespace chi {
51
52 void Result::addEntry(const char* ec, const char* overview, nlohmann::json data) {
53 assert((ec[0] == 'E' || ec[0] == 'I' || ec[0] == 'W') &&
54 "error code passed to addEntry must start with E, I , or W");
55 assert((data.is_object() || data.is_null()) &&
56 "data passed to addEntry must be a json object or {}");
57
58 mergeJsonIntoConservative(data, contextJson());
59
60 result_json.push_back(
61 nlohmann::json({{"errorcode", ec}, {"overview", overview}, {"data", data}}));
62 if (ec[0] == 'E') mSuccess = false;
63 }
64
65 std::string Result::dump() const {
66 std::string ret;
67 if (result_json.size() != 0) {
68 for (auto error : result_json) {
69 if (error.find("errorcode") == error.end() || !error["errorcode"].is_string() ||
70 error.find("overview") == error.end() || !error["overview"].is_string()) {
71 return "";
72 }
73 std::string ec = error["errorcode"];
74 std::string desc = error["overview"];
75 ret += ec + ": " + desc + "\n";
76 // recursively display children
77 auto& data = error["data"];
78 ret += prettyPrintJson(data, 1);
79 }
80 }
81 return ret;
82 }
83
84 int Result::addContext(const nlohmann::json& data) {
85 assert(data.is_object() && "Json added to context must be an object");
86
87 static int ctxId = 0;
88
89 mContexts.emplace(ctxId, data);
90 return ctxId++;
91 }
92
93 void chi::Result::removeContext(int id) { mContexts.erase(id); }
94
95 nlohmann::json Result::contextJson() const {
96 // merge all the contexts
97 auto merged = nlohmann::json::object();
98
99 for (const auto& ctx : mContexts | boost::adaptors::reversed) {
100 mergeJsonIntoConservative(merged, ctx.second);
101 }
102
103 return merged;
104 }
105
106 Result operator+(const Result& lhs, const Result& rhs) {
107 Result ret;
108 ret.mSuccess = lhs.success() && rhs.success(); // if either of them are false, then result is
109
110 // copy each of the results in
111 std::transform(lhs.result_json.begin(), lhs.result_json.end(),
112 std::back_inserter(ret.result_json), [&](nlohmann::json j) {
113 // apply the context
114 mergeJsonIntoConservative(j["data"], rhs.contextJson());
115 return j;
116 });
117 std::transform(rhs.result_json.begin(), rhs.result_json.end(),
118 std::back_inserter(ret.result_json), [&](nlohmann::json j) {
119 // apply context
120 mergeJsonIntoConservative(j["data"], lhs.contextJson());
121 return j;
122 });
123
124 return ret;
125 }
126
127 Result& operator+=(Result& lhs, const Result& rhs) {
128 lhs.mSuccess = lhs.success() && rhs.success(); // if either of them are false, then result is
129
130 // change the existing entires in lhs to have rhs's context
131 for (auto& entry : lhs.result_json) {
132 mergeJsonIntoConservative(entry["data"], rhs.contextJson());
133 }
134
135 // copy each of the results in and fix context
136 std::transform(rhs.result_json.begin(), rhs.result_json.end(),
137 std::back_inserter(lhs.result_json), [&](nlohmann::json j) {
138 mergeJsonIntoConservative(j["data"], lhs.contextJson());
139 return j;
140 });
141
142 return lhs;
143 }
144
145 } // namespace chi
chi::Result::dump
std::string dump() const
Dump to a pretty-printed error message.
Definition: Result.cpp:65
chi::Result::addEntry
void addEntry(const char *ec, const char *overview, nlohmann::json data)
Add a entry to the result, either a warning or an error.
Definition: Result.cpp:52
chi::Result::contextJson
nlohmann::json contextJson() const
Get the JSON associated with the context that&#39;s been added.
Definition: Result.cpp:95
chi::Result::mSuccess
bool mSuccess
If it&#39;s successful.
Definition: Result.hpp:155
chi::Result::result_json
nlohmann::json result_json
The result JSON.
Definition: Result.hpp:152
Result.hpp
Defines the Result class and related functions.
chi::Result::operator+
Result operator+(const Result &lhs, const Result &rhs)
Append two Result objects.
Definition: Result.cpp:106
chi::Result::addContext
int addContext(const nlohmann::json &data)
Add some json that will ALWAYS be merged with entries that are added and when results are added to th...
Definition: Result.cpp:84
chi::Result::success
bool success() const
Success test.
Definition: Result.hpp:141
chi::Result::operator+=
Result & operator+=(Result &lhs, const Result &rhs)
Append one result to an existing one.
Definition: Result.cpp:127
chi
The namespace where chigraph lives.
Definition: BitcodeParser.hpp:12
chi::Result
The result object, used for identifiying errors with good diagnostics.
Definition: Result.hpp:72
chi::Result::removeContext
void removeContext(int id)
Removes a previously added context.
Definition: Result.cpp:93