• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

daisytuner / sdfglib / 17316805645

29 Aug 2025 06:46AM UTC coverage: 60.01% (+0.2%) from 59.781%
17316805645

Pull #210

github

web-flow
Merge cd9cb386d into 18d34db1e
Pull Request #210: New debug info

351 of 562 new or added lines in 37 files covered. (62.46%)

15 existing lines in 8 files now uncovered.

9574 of 15954 relevant lines covered (60.01%)

115.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.82
/src/serializer/json_serializer.cpp
1
#include "sdfg/serializer/json_serializer.h"
2

3
#include <cassert>
4
#include <memory>
5
#include <unordered_map>
6
#include <utility>
7
#include <vector>
8

9
#include "sdfg/data_flow/library_nodes/math/math.h"
10

11
#include "sdfg/data_flow/library_nodes/barrier_local_node.h"
12
#include "sdfg/data_flow/library_nodes/metadata_node.h"
13

14
#include "sdfg/builder/structured_sdfg_builder.h"
15
#include "sdfg/data_flow/library_node.h"
16
#include "sdfg/debug_info.h"
17
#include "sdfg/element.h"
18
#include "sdfg/structured_control_flow/block.h"
19
#include "sdfg/structured_control_flow/for.h"
20
#include "sdfg/structured_control_flow/if_else.h"
21
#include "sdfg/structured_control_flow/return.h"
22
#include "sdfg/structured_control_flow/sequence.h"
23
#include "sdfg/structured_control_flow/while.h"
24
#include "sdfg/structured_sdfg.h"
25
#include "sdfg/symbolic/symbolic.h"
26
#include "sdfg/types/function.h"
27
#include "sdfg/types/scalar.h"
28
#include "sdfg/types/type.h"
29
#include "symengine/expression.h"
30
#include "symengine/logic.h"
31
#include "symengine/symengine_rcp.h"
32

33
namespace sdfg {
34
namespace serializer {
35

36
FunctionType function_type_from_string(const std::string& str) {
5✔
37
    if (str == FunctionType_CPU.value()) {
5✔
38
        return FunctionType_CPU;
5✔
39
    } else if (str == FunctionType_NV_GLOBAL.value()) {
×
40
        return FunctionType_NV_GLOBAL;
×
41
    }
42

43
    return FunctionType(str);
×
44
}
5✔
45

46
types::StorageType storage_type_from_string(const std::string& str) {
41✔
47
    if (str == types::StorageType_CPU_Heap.value()) {
41✔
48
        return types::StorageType_CPU_Heap;
×
49
    } else if (str == types::StorageType_CPU_Stack.value()) {
41✔
50
        return types::StorageType_CPU_Stack;
41✔
51
    } else if (str == types::StorageType_NV_Global.value()) {
×
52
        return types::StorageType_NV_Global;
×
53
    } else if (str == types::StorageType_NV_Shared.value()) {
×
54
        return types::StorageType_NV_Shared;
×
55
    } else if (str == types::StorageType_NV_Constant.value()) {
×
56
        return types::StorageType_NV_Constant;
×
57
    } else if (str == types::StorageType_NV_Generic.value()) {
×
58
        return types::StorageType_NV_Generic;
×
59
    }
60

61
    return types::StorageType(str);
×
62
}
41✔
63

64
structured_control_flow::ScheduleType schedule_type_from_string(const std::string& str) {
1✔
65
    if (str == structured_control_flow::ScheduleType_Sequential.value()) {
1✔
66
        return structured_control_flow::ScheduleType_Sequential;
1✔
67
    } else if (str == structured_control_flow::ScheduleType_CPU_Parallel.value()) {
×
68
        return structured_control_flow::ScheduleType_CPU_Parallel;
×
69
    }
70

71
    return structured_control_flow::ScheduleType(str);
×
72
}
1✔
73

74
/*
75
 * * JSONSerializer class
76
 * * Serialization logic
77
 */
78

79
nlohmann::json JSONSerializer::serialize(const sdfg::StructuredSDFG& sdfg) {
5✔
80
    nlohmann::json j;
5✔
81

82
    j["name"] = sdfg.name();
5✔
83
    j["element_counter"] = sdfg.element_counter();
5✔
84
    j["type"] = std::string(sdfg.type().value());
5✔
85
    j["debug_info"] = nlohmann::json::object();
5✔
86
    debug_info_to_json(j["debug_info"], sdfg.debug_info());
5✔
87

88
    j["structures"] = nlohmann::json::array();
5✔
89
    for (const auto& structure_name : sdfg.structures()) {
6✔
90
        const auto& structure = sdfg.structure(structure_name);
1✔
91
        nlohmann::json structure_json;
1✔
92
        structure_definition_to_json(structure_json, structure);
1✔
93
        j["structures"].push_back(structure_json);
1✔
94
    }
1✔
95

96
    j["containers"] = nlohmann::json::object();
5✔
97
    for (const auto& container : sdfg.containers()) {
17✔
98
        nlohmann::json desc;
12✔
99
        type_to_json(desc, sdfg.type(container));
12✔
100
        j["containers"][container] = desc;
12✔
101
    }
12✔
102

103
    j["arguments"] = nlohmann::json::array();
5✔
104
    for (const auto& argument : sdfg.arguments()) {
8✔
105
        j["arguments"].push_back(argument);
3✔
106
    }
107

108
    j["externals"] = nlohmann::json::array();
5✔
109
    for (const auto& external : sdfg.externals()) {
9✔
110
        nlohmann::json external_json;
4✔
111
        external_json["name"] = external;
4✔
112
        external_json["linkage_type"] = sdfg.linkage_type(external);
4✔
113
        j["externals"].push_back(external_json);
4✔
114
    }
4✔
115

116
    j["metadata"] = nlohmann::json::object();
5✔
117
    for (const auto& entry : sdfg.metadata()) {
6✔
118
        j["metadata"][entry.first] = entry.second;
1✔
119
    }
120

121
    // Walk the SDFG
122
    nlohmann::json root_json;
5✔
123
    sequence_to_json(root_json, sdfg.root());
5✔
124
    j["root"] = root_json;
5✔
125

126
    return j;
5✔
127
}
5✔
128

129
void JSONSerializer::dataflow_to_json(nlohmann::json& j, const data_flow::DataFlowGraph& dataflow) {
21✔
130
    j["type"] = "dataflow";
21✔
131
    j["nodes"] = nlohmann::json::array();
21✔
132
    j["edges"] = nlohmann::json::array();
21✔
133

134
    for (auto& node : dataflow.nodes()) {
41✔
135
        nlohmann::json node_json;
20✔
136
        node_json["element_id"] = node.element_id();
20✔
137

138
        node_json["debug_info"] = nlohmann::json::object();
20✔
139
        debug_info_region_to_json(node_json["debug_info"], node.debug_info());
20✔
140

141
        if (auto tasklet = dynamic_cast<const data_flow::Tasklet*>(&node)) {
20✔
142
            node_json["type"] = "tasklet";
5✔
143
            node_json["code"] = tasklet->code();
5✔
144
            node_json["inputs"] = nlohmann::json::array();
5✔
145
            for (auto& input : tasklet->inputs()) {
15✔
146
                node_json["inputs"].push_back(input);
10✔
147
            }
148
            node_json["output"] = tasklet->output();
5✔
149
            // node_json["conditional"] = tasklet->is_conditional();
150
            // if (tasklet->is_conditional()) {
151
            //     node_json["condition"] = dumps_expression(tasklet->condition());
152
            // }
153
        } else if (auto lib_node = dynamic_cast<const data_flow::LibraryNode*>(&node)) {
20✔
154
            node_json["type"] = "library_node";
×
155
            node_json["implementation_type"] = std::string(lib_node->implementation_type().value());
×
156
            auto serializer_fn =
157
                LibraryNodeSerializerRegistry::instance().get_library_node_serializer(lib_node->code().value());
×
158
            if (serializer_fn == nullptr) {
×
159
                throw std::runtime_error("Unknown library node code: " + std::string(lib_node->code().value()));
×
160
            }
161
            auto serializer = serializer_fn();
×
162
            auto lib_node_json = serializer->serialize(*lib_node);
×
163
            node_json.merge_patch(lib_node_json);
×
164
        } else if (auto code_node = dynamic_cast<const data_flow::AccessNode*>(&node)) {
15✔
165
            node_json["type"] = "access_node";
15✔
166
            node_json["data"] = code_node->data();
15✔
167
        } else {
15✔
168
            throw std::runtime_error("Unknown node type");
×
169
        }
170

171
        j["nodes"].push_back(node_json);
20✔
172
    }
20✔
173

174
    for (auto& edge : dataflow.edges()) {
36✔
175
        nlohmann::json edge_json;
15✔
176
        edge_json["element_id"] = edge.element_id();
15✔
177

178
        edge_json["debug_info"] = nlohmann::json::object();
15✔
179
        debug_info_region_to_json(edge_json["debug_info"], edge.debug_info());
15✔
180

181
        edge_json["src"] = edge.src().element_id();
15✔
182
        edge_json["dst"] = edge.dst().element_id();
15✔
183

184
        edge_json["src_conn"] = edge.src_conn();
15✔
185
        edge_json["dst_conn"] = edge.dst_conn();
15✔
186

187
        edge_json["subset"] = nlohmann::json::array();
15✔
188
        for (auto& subset : edge.subset()) {
21✔
189
            edge_json["subset"].push_back(expression(subset));
6✔
190
        }
191

192
        edge_json["begin_subset"] = nlohmann::json::array();
15✔
193
        for (auto& subset : edge.begin_subset()) {
21✔
194
            edge_json["begin_subset"].push_back(expression(subset));
6✔
195
        }
196

197
        edge_json["end_subset"] = nlohmann::json::array();
15✔
198
        for (auto& subset : edge.end_subset()) {
21✔
199
            edge_json["end_subset"].push_back(expression(subset));
6✔
200
        }
201

202
        nlohmann::json base_type_json;
15✔
203
        type_to_json(base_type_json, edge.base_type());
15✔
204
        edge_json["base_type"] = base_type_json;
15✔
205

206
        j["edges"].push_back(edge_json);
15✔
207
    }
15✔
208
}
21✔
209

210
void JSONSerializer::block_to_json(nlohmann::json& j, const structured_control_flow::Block& block) {
19✔
211
    j["type"] = "block";
19✔
212
    j["element_id"] = block.element_id();
19✔
213

214
    j["debug_info"] = nlohmann::json::object();
19✔
215
    debug_info_region_to_json(j["debug_info"], block.debug_info());
19✔
216

217
    nlohmann::json dataflow_json;
19✔
218
    dataflow_to_json(dataflow_json, block.dataflow());
19✔
219
    j["dataflow"] = dataflow_json;
19✔
220
}
19✔
221

222
void JSONSerializer::for_to_json(nlohmann::json& j, const structured_control_flow::For& for_node) {
2✔
223
    j["type"] = "for";
2✔
224
    j["element_id"] = for_node.element_id();
2✔
225

226
    j["debug_info"] = nlohmann::json::object();
2✔
227
    debug_info_region_to_json(j["debug_info"], for_node.debug_info());
2✔
228

229
    j["indvar"] = expression(for_node.indvar());
2✔
230
    j["init"] = expression(for_node.init());
2✔
231
    j["condition"] = expression(for_node.condition());
2✔
232
    j["update"] = expression(for_node.update());
2✔
233

234
    nlohmann::json body_json;
2✔
235
    sequence_to_json(body_json, for_node.root());
2✔
236
    j["root"] = body_json;
2✔
237
}
2✔
238

239
void JSONSerializer::if_else_to_json(nlohmann::json& j, const structured_control_flow::IfElse& if_else_node) {
2✔
240
    j["type"] = "if_else";
2✔
241
    j["element_id"] = if_else_node.element_id();
2✔
242

243
    j["debug_info"] = nlohmann::json::object();
2✔
244
    debug_info_region_to_json(j["debug_info"], if_else_node.debug_info());
2✔
245

246
    j["branches"] = nlohmann::json::array();
2✔
247
    for (size_t i = 0; i < if_else_node.size(); i++) {
6✔
248
        nlohmann::json branch_json;
4✔
249
        branch_json["condition"] = expression(if_else_node.at(i).second);
4✔
250
        nlohmann::json body_json;
4✔
251
        sequence_to_json(body_json, if_else_node.at(i).first);
4✔
252
        branch_json["root"] = body_json;
4✔
253
        j["branches"].push_back(branch_json);
4✔
254
    }
4✔
255
}
2✔
256

257
void JSONSerializer::while_node_to_json(nlohmann::json& j, const structured_control_flow::While& while_node) {
5✔
258
    j["type"] = "while";
5✔
259
    j["element_id"] = while_node.element_id();
5✔
260

261
    j["debug_info"] = nlohmann::json::object();
5✔
262
    debug_info_region_to_json(j["debug_info"], while_node.debug_info());
5✔
263

264
    nlohmann::json body_json;
5✔
265
    sequence_to_json(body_json, while_node.root());
5✔
266
    j["root"] = body_json;
5✔
267
}
5✔
268

269
void JSONSerializer::break_node_to_json(nlohmann::json& j, const structured_control_flow::Break& break_node) {
2✔
270
    j["type"] = "break";
2✔
271
    j["element_id"] = break_node.element_id();
2✔
272

273
    j["debug_info"] = nlohmann::json::object();
2✔
274
    debug_info_region_to_json(j["debug_info"], break_node.debug_info());
2✔
275
}
2✔
276

277
void JSONSerializer::continue_node_to_json(nlohmann::json& j, const structured_control_flow::Continue& continue_node) {
2✔
278
    j["type"] = "continue";
2✔
279
    j["element_id"] = continue_node.element_id();
2✔
280

281
    j["debug_info"] = nlohmann::json::object();
2✔
282
    debug_info_region_to_json(j["debug_info"], continue_node.debug_info());
2✔
283
}
2✔
284

285
void JSONSerializer::map_to_json(nlohmann::json& j, const structured_control_flow::Map& map_node) {
2✔
286
    j["type"] = "map";
2✔
287
    j["element_id"] = map_node.element_id();
2✔
288

289
    j["debug_info"] = nlohmann::json::object();
2✔
290
    debug_info_region_to_json(j["debug_info"], map_node.debug_info());
2✔
291

292
    j["indvar"] = expression(map_node.indvar());
2✔
293
    j["init"] = expression(map_node.init());
2✔
294
    j["condition"] = expression(map_node.condition());
2✔
295
    j["update"] = expression(map_node.update());
2✔
296

297
    j["schedule_type"] = std::string(map_node.schedule_type().value());
2✔
298

299
    nlohmann::json body_json;
2✔
300
    sequence_to_json(body_json, map_node.root());
2✔
301
    j["root"] = body_json;
2✔
302
}
2✔
303

304
void JSONSerializer::return_node_to_json(nlohmann::json& j, const structured_control_flow::Return& return_node) {
2✔
305
    j["type"] = "return";
2✔
306
    j["element_id"] = return_node.element_id();
2✔
307

308
    j["debug_info"] = nlohmann::json::object();
2✔
309
    debug_info_region_to_json(j["debug_info"], return_node.debug_info());
2✔
310
}
2✔
311

312
void JSONSerializer::sequence_to_json(nlohmann::json& j, const structured_control_flow::Sequence& sequence) {
21✔
313
    j["type"] = "sequence";
21✔
314
    j["element_id"] = sequence.element_id();
21✔
315

316
    j["debug_info"] = nlohmann::json::object();
21✔
317
    debug_info_region_to_json(j["debug_info"], sequence.debug_info());
21✔
318

319
    j["children"] = nlohmann::json::array();
21✔
320
    j["transitions"] = nlohmann::json::array();
21✔
321

322
    for (size_t i = 0; i < sequence.size(); i++) {
42✔
323
        nlohmann::json child_json;
21✔
324
        auto& child = sequence.at(i).first;
21✔
325
        auto& transition = sequence.at(i).second;
21✔
326

327
        if (auto block = dynamic_cast<const structured_control_flow::Block*>(&child)) {
21✔
328
            block_to_json(child_json, *block);
17✔
329
        } else if (auto for_node = dynamic_cast<const structured_control_flow::For*>(&child)) {
21✔
330
            for_to_json(child_json, *for_node);
×
331
        } else if (auto sequence_node = dynamic_cast<const structured_control_flow::Sequence*>(&child)) {
4✔
332
            sequence_to_json(child_json, *sequence_node);
×
333
        } else if (auto condition_node = dynamic_cast<const structured_control_flow::IfElse*>(&child)) {
4✔
334
            if_else_to_json(child_json, *condition_node);
×
335
        } else if (auto while_node = dynamic_cast<const structured_control_flow::While*>(&child)) {
4✔
336
            while_node_to_json(child_json, *while_node);
×
337
        } else if (auto return_node = dynamic_cast<const structured_control_flow::Return*>(&child)) {
4✔
338
            return_node_to_json(child_json, *return_node);
×
339
        } else if (auto break_node = dynamic_cast<const structured_control_flow::Break*>(&child)) {
4✔
340
            break_node_to_json(child_json, *break_node);
2✔
341
        } else if (auto continue_node = dynamic_cast<const structured_control_flow::Continue*>(&child)) {
4✔
342
            continue_node_to_json(child_json, *continue_node);
2✔
343
        } else if (auto map_node = dynamic_cast<const structured_control_flow::Map*>(&child)) {
2✔
344
            map_to_json(child_json, *map_node);
×
345
        } else {
×
346
            throw std::runtime_error("Unknown child type");
×
347
        }
348

349
        j["children"].push_back(child_json);
21✔
350

351
        // Add transition information
352
        nlohmann::json transition_json;
21✔
353
        transition_json["type"] = "transition";
21✔
354
        transition_json["element_id"] = transition.element_id();
21✔
355

356
        transition_json["debug_info"] = nlohmann::json::object();
21✔
357
        debug_info_region_to_json(transition_json["debug_info"], transition.debug_info());
21✔
358

359
        transition_json["assignments"] = nlohmann::json::array();
21✔
360
        for (const auto& assignment : transition.assignments()) {
24✔
361
            nlohmann::json assignment_json;
3✔
362
            assignment_json["symbol"] = expression(assignment.first);
3✔
363
            assignment_json["expression"] = expression(assignment.second);
3✔
364
            transition_json["assignments"].push_back(assignment_json);
3✔
365
        }
3✔
366

367
        j["transitions"].push_back(transition_json);
21✔
368
    }
21✔
369
}
21✔
370

371
void JSONSerializer::type_to_json(nlohmann::json& j, const types::IType& type) {
55✔
372
    if (auto scalar_type = dynamic_cast<const types::Scalar*>(&type)) {
55✔
373
        j["type"] = "scalar";
38✔
374
        j["primitive_type"] = scalar_type->primitive_type();
38✔
375
        j["storage_type"] = std::string(scalar_type->storage_type().value());
38✔
376
        j["initializer"] = scalar_type->initializer();
38✔
377
        j["alignment"] = scalar_type->alignment();
38✔
378
    } else if (auto array_type = dynamic_cast<const types::Array*>(&type)) {
55✔
379
        j["type"] = "array";
3✔
380
        nlohmann::json element_type_json;
3✔
381
        type_to_json(element_type_json, array_type->element_type());
3✔
382
        j["element_type"] = element_type_json;
3✔
383
        j["num_elements"] = expression(array_type->num_elements());
3✔
384
        j["storage_type"] = std::string(array_type->storage_type().value());
3✔
385
        j["initializer"] = array_type->initializer();
3✔
386
        j["alignment"] = array_type->alignment();
3✔
387
    } else if (auto pointer_type = dynamic_cast<const types::Pointer*>(&type)) {
17✔
388
        j["type"] = "pointer";
9✔
389
        if (pointer_type->has_pointee_type()) {
9✔
390
            nlohmann::json pointee_type_json;
8✔
391
            type_to_json(pointee_type_json, pointer_type->pointee_type());
8✔
392
            j["pointee_type"] = pointee_type_json;
8✔
393
        }
8✔
394
        j["storage_type"] = std::string(pointer_type->storage_type().value());
9✔
395
        j["initializer"] = pointer_type->initializer();
9✔
396
        j["alignment"] = pointer_type->alignment();
9✔
397
    } else if (auto structure_type = dynamic_cast<const types::Structure*>(&type)) {
14✔
398
        j["type"] = "structure";
3✔
399
        j["name"] = structure_type->name();
3✔
400
        j["storage_type"] = std::string(structure_type->storage_type().value());
3✔
401
        j["initializer"] = structure_type->initializer();
3✔
402
        j["alignment"] = structure_type->alignment();
3✔
403
    } else if (auto function_type = dynamic_cast<const types::Function*>(&type)) {
5✔
404
        j["type"] = "function";
2✔
405
        nlohmann::json return_type_json;
2✔
406
        type_to_json(return_type_json, function_type->return_type());
2✔
407
        j["return_type"] = return_type_json;
2✔
408
        j["params"] = nlohmann::json::array();
2✔
409
        for (size_t i = 0; i < function_type->num_params(); i++) {
5✔
410
            nlohmann::json param_json;
3✔
411
            type_to_json(param_json, function_type->param_type(symbolic::integer(i)));
3✔
412
            j["params"].push_back(param_json);
3✔
413
        }
3✔
414
        j["is_var_arg"] = function_type->is_var_arg();
2✔
415
        j["storage_type"] = std::string(function_type->storage_type().value());
2✔
416
        j["initializer"] = function_type->initializer();
2✔
417
        j["alignment"] = function_type->alignment();
2✔
418
    } else {
2✔
419
        throw std::runtime_error("Unknown type");
×
420
    }
421
}
55✔
422

423
void JSONSerializer::structure_definition_to_json(nlohmann::json& j, const types::StructureDefinition& definition) {
2✔
424
    j["name"] = definition.name();
2✔
425
    j["members"] = nlohmann::json::array();
2✔
426
    for (size_t i = 0; i < definition.num_members(); i++) {
4✔
427
        nlohmann::json member_json;
2✔
428
        type_to_json(member_json, definition.member_type(symbolic::integer(i)));
2✔
429
        j["members"].push_back(member_json);
2✔
430
    }
2✔
431
    j["is_packed"] = definition.is_packed();
2✔
432
}
2✔
433

434
void JSONSerializer::debug_loc_to_json(nlohmann::json& j, const DebugLoc& loc) {
7✔
435
    j["has"] = loc.has_;
7✔
436
    if (!loc.has_) {
7✔
NEW
437
        return;
×
438
    }
439
    j["filename"] = loc.filename_;
7✔
440
    j["function"] = loc.function_;
7✔
441
    j["line"] = loc.line_;
7✔
442
    j["column"] = loc.column_;
7✔
443
}
7✔
444

445

446
void JSONSerializer::debug_info_element_to_json(nlohmann::json& j, const DebugInfoElement& debug_info_element) {
3✔
447
    j["has"] = debug_info_element.has();
3✔
448
    if (!debug_info_element.has()) {
3✔
NEW
449
        return;
×
450
    }
451
    j["locations"] = nlohmann::json::array();
3✔
452
    for (const auto& loc : debug_info_element.locations()) {
9✔
453
        nlohmann::json loc_json;
6✔
454
        debug_loc_to_json(loc_json, loc);
6✔
455
        j["locations"].push_back(loc_json);
6✔
456
    }
6✔
457
}
3✔
458

459
void JSONSerializer::debug_info_region_to_json(nlohmann::json& j, const DebugInfoRegion& debug_info) {
115✔
460
    j["has"] = debug_info.has();
115✔
461
    j["filename"] = debug_info.filename();
115✔
462
    j["function"] = debug_info.function();
115✔
463
    j["start_line"] = debug_info.start_line();
115✔
464
    j["start_column"] = debug_info.start_column();
115✔
465
    j["end_line"] = debug_info.end_line();
115✔
466
    j["end_column"] = debug_info.end_column();
115✔
467

468
    j["indices"] = nlohmann::json::array();
115✔
469
    for (const auto& index : debug_info.indices()) {
119✔
470
        j["indices"].push_back(index);
4✔
471
    }
472
}
115✔
473

474
void JSONSerializer::debug_info_to_json(nlohmann::json& j, const DebugInfo& debug_info) {
6✔
475
    j["instructions"] = nlohmann::json::array();
6✔
476
    for (const auto& instruction : debug_info.instructions()) {
8✔
477
        nlohmann::json instruction_json;
2✔
478
        debug_info_element_to_json(instruction_json, instruction);
2✔
479
        j["instructions"].push_back(instruction_json);
2✔
480
    }
2✔
481
}
6✔
482

483
/*
484
 * * Deserialization logic
485
 */
486

487
std::unique_ptr<StructuredSDFG> JSONSerializer::deserialize(nlohmann::json& j) {
5✔
488
    assert(j.contains("name"));
5✔
489
    assert(j["name"].is_string());
5✔
490
    assert(j.contains("type"));
5✔
491
    assert(j["type"].is_string());
5✔
492
    assert(j["element_counter"].is_number_integer());
5✔
493
    assert(j.contains("debug_info"));
5✔
494
    assert(j["debug_info"].is_object());
5✔
495

496
    DebugInfo debug_info = json_to_debug_info(j["debug_info"]);
5✔
497
    debug_info_ = &debug_info;
5✔
498

499
    FunctionType function_type = function_type_from_string(j["type"].get<std::string>());
5✔
500
    builder::StructuredSDFGBuilder builder(j["name"], function_type, debug_info);
5✔
501

502
    size_t element_counter = j["element_counter"];
5✔
503
    builder.set_element_counter(element_counter);
5✔
504

505
    // deserialize structures
506
    assert(j.contains("structures"));
5✔
507
    assert(j["structures"].is_array());
5✔
508
    for (const auto& structure : j["structures"]) {
6✔
509
        assert(structure.contains("name"));
1✔
510
        assert(structure["name"].is_string());
1✔
511
        json_to_structure_definition(structure, builder);
1✔
512
    }
513

514
    nlohmann::json& containers = j["containers"];
5✔
515

516
    // deserialize externals
517
    for (const auto& external : j["externals"]) {
9✔
518
        assert(external.contains("name"));
4✔
519
        assert(external["name"].is_string());
4✔
520
        assert(external.contains("linkage_type"));
4✔
521
        assert(external["linkage_type"].is_number_integer());
4✔
522
        auto& type_desc = containers.at(external["name"].get<std::string>());
4✔
523
        auto type = json_to_type(type_desc);
4✔
524
        builder.add_external(external["name"], *type, LinkageType(external["linkage_type"]));
4✔
525
    }
4✔
526

527
    // deserialize arguments
528
    for (const auto& name : j["arguments"]) {
8✔
529
        auto& type_desc = containers.at(name.get<std::string>());
3✔
530
        auto type = json_to_type(type_desc);
3✔
531
        builder.add_container(name, *type, true, false);
3✔
532
    }
3✔
533

534
    // deserialize transients
535
    for (const auto& entry : containers.items()) {
17✔
536
        if (builder.subject().is_argument(entry.key())) {
12✔
537
            continue;
3✔
538
        }
539
        if (builder.subject().is_external(entry.key())) {
9✔
540
            continue;
4✔
541
        }
542
        auto type = json_to_type(entry.value());
5✔
543
        builder.add_container(entry.key(), *type, false, false);
5✔
544
    }
5✔
545

546
    // deserialize root node
547
    assert(j.contains("root"));
5✔
548
    auto& root = builder.subject().root();
5✔
549
    json_to_sequence(j["root"], builder, root);
5✔
550

551
    // deserialize metadata
552
    assert(j.contains("metadata"));
5✔
553
    assert(j["metadata"].is_object());
5✔
554
    for (const auto& entry : j["metadata"].items()) {
6✔
555
        builder.subject().add_metadata(entry.key(), entry.value());
1✔
556
    }
557

558
    builder.set_element_counter(element_counter);
5✔
559

560
    return builder.move();
5✔
561
}
5✔
562

563
void JSONSerializer::json_to_structure_definition(const nlohmann::json& j, builder::StructuredSDFGBuilder& builder) {
2✔
564
    assert(j.contains("name"));
2✔
565
    assert(j["name"].is_string());
2✔
566
    assert(j.contains("members"));
2✔
567
    assert(j["members"].is_array());
2✔
568
    assert(j.contains("is_packed"));
2✔
569
    assert(j["is_packed"].is_boolean());
2✔
570
    auto is_packed = j["is_packed"];
2✔
571
    auto& definition = builder.add_structure(j["name"], is_packed);
2✔
572
    for (const auto& member : j["members"]) {
4✔
573
        nlohmann::json member_json;
2✔
574
        auto member_type = json_to_type(member);
2✔
575
        definition.add_member(*member_type);
2✔
576
    }
2✔
577
}
2✔
578

579
std::vector<std::pair<std::string, types::Scalar>> JSONSerializer::json_to_arguments(const nlohmann::json& j) {
×
580
    std::vector<std::pair<std::string, types::Scalar>> arguments;
×
581
    for (const auto& argument : j) {
×
582
        assert(argument.contains("name"));
×
583
        assert(argument["name"].is_string());
×
584
        assert(argument.contains("type"));
×
585
        assert(argument["type"].is_object());
×
586
        std::string name = argument["name"];
×
587
        auto type = json_to_type(argument["type"]);
×
588
        arguments.emplace_back(name, *dynamic_cast<types::Scalar*>(type.get()));
×
589
    }
×
590
    return arguments;
×
591
}
×
592

593
void JSONSerializer::json_to_dataflow(
11✔
594
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Block& parent
595
) {
596
    std::unordered_map<size_t, data_flow::DataFlowNode&> nodes_map;
11✔
597

598
    assert(j.contains("nodes"));
11✔
599
    assert(j["nodes"].is_array());
11✔
600
    for (const auto& node : j["nodes"]) {
27✔
601
        assert(node.contains("type"));
16✔
602
        assert(node["type"].is_string());
16✔
603
        assert(node.contains("element_id"));
16✔
604
        assert(node["element_id"].is_number_integer());
16✔
605
        std::string type = node["type"];
16✔
606
        if (type == "tasklet") {
16✔
607
            assert(node.contains("code"));
4✔
608
            assert(node["code"].is_number_integer());
4✔
609
            assert(node.contains("inputs"));
4✔
610
            assert(node["inputs"].is_array());
4✔
611
            assert(node.contains("output"));
4✔
612
            assert(node["output"].is_string());
4✔
613
            auto inputs = node["inputs"].get<std::vector<std::string>>();
4✔
614

615
            auto& tasklet = builder.add_tasklet(
8✔
616
                parent, node["code"], node["output"], inputs, json_to_debug_info_region(node["debug_info"], *debug_info_)
4✔
617
            );
618
            tasklet.element_id_ = node["element_id"];
4✔
619
            nodes_map.insert({node["element_id"], tasklet});
4✔
620
        } else if (type == "library_node") {
16✔
621
            assert(node.contains("code"));
×
622
            data_flow::LibraryNodeCode code(node["code"].get<std::string>());
×
623

624
            auto serializer_fn = LibraryNodeSerializerRegistry::instance().get_library_node_serializer(code.value());
×
625
            if (serializer_fn == nullptr) {
×
626
                throw std::runtime_error("Unknown library node code: " + std::string(code.value()));
×
627
            }
628
            auto serializer = serializer_fn();
×
629
            auto& lib_node = serializer->deserialize(node, builder, parent);
×
630
            lib_node.implementation_type() =
×
631
                data_flow::ImplementationType(node["implementation_type"].get<std::string>());
×
632
            lib_node.element_id_ = node["element_id"];
×
633
            nodes_map.insert({node["element_id"], lib_node});
×
634
        } else if (type == "access_node") {
12✔
635
            assert(node.contains("data"));
12✔
636
            auto& access_node =
12✔
637
                builder.add_access(parent, node["data"], json_to_debug_info_region(node["debug_info"], *debug_info_));
12✔
638
            access_node.element_id_ = node["element_id"];
12✔
639
            nodes_map.insert({node["element_id"], access_node});
12✔
640
        } else {
12✔
641
            throw std::runtime_error("Unknown node type");
×
642
        }
643
    }
16✔
644

645
    assert(j.contains("edges"));
11✔
646
    assert(j["edges"].is_array());
11✔
647
    for (const auto& edge : j["edges"]) {
23✔
648
        assert(edge.contains("src"));
12✔
649
        assert(edge["src"].is_number_integer());
12✔
650
        assert(edge.contains("dst"));
12✔
651
        assert(edge["dst"].is_number_integer());
12✔
652
        assert(edge.contains("src_conn"));
12✔
653
        assert(edge["src_conn"].is_string());
12✔
654
        assert(edge.contains("dst_conn"));
12✔
655
        assert(edge["dst_conn"].is_string());
12✔
656
        assert(edge.contains("subset"));
12✔
657
        assert(edge["subset"].is_array());
12✔
658

659
        assert(nodes_map.find(edge["src"]) != nodes_map.end());
12✔
660
        assert(nodes_map.find(edge["dst"]) != nodes_map.end());
12✔
661
        auto& source = nodes_map.at(edge["src"]);
12✔
662
        auto& target = nodes_map.at(edge["dst"]);
12✔
663

664
        auto base_type = json_to_type(edge["base_type"]);
12✔
665

666
        if (edge.contains("begin_subset") && edge.contains("end_subset")) {
12✔
667
            assert(edge["begin_subset"].is_array());
12✔
668
            assert(edge["end_subset"].is_array());
12✔
669
            std::vector<symbolic::Expression> begin_subset;
12✔
670
            std::vector<symbolic::Expression> end_subset;
12✔
671
            for (const auto& subset_str : edge["begin_subset"]) {
16✔
672
                assert(subset_str.is_string());
4✔
673
                SymEngine::Expression subset_expr(subset_str);
4✔
674
                begin_subset.push_back(subset_expr);
4✔
675
            }
4✔
676
            for (const auto& subset_str : edge["end_subset"]) {
16✔
677
                assert(subset_str.is_string());
4✔
678
                SymEngine::Expression subset_expr(subset_str);
4✔
679
                end_subset.push_back(subset_expr);
4✔
680
            }
4✔
681
            auto& memlet = builder.add_memlet(
24✔
682
                parent,
12✔
683
                source,
12✔
684
                edge["src_conn"],
12✔
685
                target,
12✔
686
                edge["dst_conn"],
12✔
687
                begin_subset,
688
                end_subset,
689
                *base_type,
12✔
690
                json_to_debug_info_region(edge["debug_info"], *debug_info_)
12✔
691
            );
692
            memlet.element_id_ = edge["element_id"];
12✔
693
        } else if (edge.contains("subset")) {
12✔
694
            assert(edge["subset"].is_array());
×
695
            std::vector<symbolic::Expression> subset;
×
696
            for (const auto& subset_str : edge["subset"]) {
×
697
                assert(subset_str.is_string());
×
698
                SymEngine::Expression subset_expr(subset_str);
×
699
                subset.push_back(subset_expr);
×
700
            }
×
701
            auto& memlet = builder.add_memlet(
×
702
                parent,
×
703
                source,
×
704
                edge["src_conn"],
×
705
                target,
×
706
                edge["dst_conn"],
×
707
                subset,
708
                *base_type,
×
NEW
709
                json_to_debug_info_region(edge["debug_info"], *debug_info_)
×
710
            );
711
            memlet.element_id_ = edge["element_id"];
×
712
        } else {
×
713
            throw std::runtime_error("Subsets not specified in json");
×
714
        }
715
    }
12✔
716
}
11✔
717

718
void JSONSerializer::json_to_sequence(
14✔
719
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& sequence
720
) {
721
    assert(j.contains("type"));
14✔
722
    assert(j["type"].is_string());
14✔
723
    assert(j.contains("children"));
14✔
724
    assert(j["children"].is_array());
14✔
725
    assert(j.contains("transitions"));
14✔
726
    assert(j["transitions"].is_array());
14✔
727
    assert(j["transitions"].size() == j["children"].size());
14✔
728

729
    sequence.element_id_ = j["element_id"];
14✔
730
    sequence.debug_info_ = json_to_debug_info_region(j["debug_info"], *debug_info_);
14✔
731

732
    std::string type = j["type"];
14✔
733
    if (type == "sequence") {
14✔
734
        for (size_t i = 0; i < j["children"].size(); i++) {
25✔
735
            auto& child = j["children"][i];
11✔
736
            auto& transition = j["transitions"][i];
11✔
737
            assert(child.contains("type"));
11✔
738
            assert(child["type"].is_string());
11✔
739

740
            assert(transition.contains("type"));
11✔
741
            assert(transition["type"].is_string());
11✔
742
            assert(transition.contains("assignments"));
11✔
743
            assert(transition["assignments"].is_array());
11✔
744
            control_flow::Assignments assignments;
11✔
745
            for (const auto& assignment : transition["assignments"]) {
13✔
746
                assert(assignment.contains("symbol"));
2✔
747
                assert(assignment["symbol"].is_string());
2✔
748
                assert(assignment.contains("expression"));
2✔
749
                assert(assignment["expression"].is_string());
2✔
750
                SymEngine::Expression expr(assignment["expression"]);
2✔
751
                assignments.insert({symbolic::symbol(assignment["symbol"]), expr});
2✔
752
            }
2✔
753

754
            if (child["type"] == "block") {
11✔
755
                json_to_block_node(child, builder, sequence, assignments);
9✔
756
            } else if (child["type"] == "for") {
11✔
757
                json_to_for_node(child, builder, sequence, assignments);
×
758
            } else if (child["type"] == "if_else") {
2✔
759
                json_to_if_else_node(child, builder, sequence, assignments);
×
760
            } else if (child["type"] == "while") {
2✔
761
                json_to_while_node(child, builder, sequence, assignments);
×
762
            } else if (child["type"] == "break") {
2✔
763
                json_to_break_node(child, builder, sequence, assignments);
1✔
764
            } else if (child["type"] == "continue") {
2✔
765
                json_to_continue_node(child, builder, sequence, assignments);
1✔
766
            } else if (child["type"] == "return") {
1✔
767
                json_to_return_node(child, builder, sequence, assignments);
×
768
            } else if (child["type"] == "map") {
×
769
                json_to_map_node(child, builder, sequence, assignments);
×
770
            } else if (child["type"] == "sequence") {
×
NEW
771
                auto& subseq =
×
NEW
772
                    builder
×
NEW
773
                        .add_sequence(sequence, assignments, json_to_debug_info_region(child["debug_info"], *debug_info_));
×
774
                json_to_sequence(child, builder, subseq);
×
775
            } else {
×
776
                throw std::runtime_error("Unknown child type");
×
777
            }
778

779
            sequence.at(i).second.debug_info_ = json_to_debug_info_region(transition["debug_info"], *debug_info_);
11✔
780
            sequence.at(i).second.element_id_ = transition["element_id"];
11✔
781
        }
11✔
782
    } else {
14✔
783
        throw std::runtime_error("expected sequence type");
×
784
    }
785
}
14✔
786

787
void JSONSerializer::json_to_block_node(
10✔
788
    const nlohmann::json& j,
789
    builder::StructuredSDFGBuilder& builder,
790
    structured_control_flow::Sequence& parent,
791
    control_flow::Assignments& assignments
792
) {
793
    assert(j.contains("type"));
10✔
794
    assert(j["type"].is_string());
10✔
795
    assert(j.contains("dataflow"));
10✔
796
    assert(j["dataflow"].is_object());
10✔
797
    auto& block = builder.add_block(parent, assignments, json_to_debug_info_region(j["debug_info"], *debug_info_));
10✔
798
    block.element_id_ = j["element_id"];
10✔
799
    assert(j["dataflow"].contains("type"));
10✔
800
    assert(j["dataflow"]["type"].is_string());
10✔
801
    std::string type = j["dataflow"]["type"];
10✔
802
    if (type == "dataflow") {
10✔
803
        json_to_dataflow(j["dataflow"], builder, block);
10✔
804
    } else {
10✔
805
        throw std::runtime_error("Unknown dataflow type");
×
806
    }
807
}
10✔
808

809
void JSONSerializer::json_to_for_node(
1✔
810
    const nlohmann::json& j,
811
    builder::StructuredSDFGBuilder& builder,
812
    structured_control_flow::Sequence& parent,
813
    control_flow::Assignments& assignments
814
) {
815
    assert(j.contains("type"));
1✔
816
    assert(j["type"].is_string());
1✔
817
    assert(j.contains("indvar"));
1✔
818
    assert(j["indvar"].is_string());
1✔
819
    assert(j.contains("init"));
1✔
820
    assert(j["init"].is_string());
1✔
821
    assert(j.contains("condition"));
1✔
822
    assert(j["condition"].is_string());
1✔
823
    assert(j.contains("update"));
1✔
824
    assert(j["update"].is_string());
1✔
825
    assert(j.contains("root"));
1✔
826
    assert(j["root"].is_object());
1✔
827

828
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
1✔
829
    SymEngine::Expression init(j["init"]);
1✔
830
    SymEngine::Expression condition_expr(j["condition"]);
1✔
831
    assert(!SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic()).is_null());
1✔
832
    symbolic::Condition condition = SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic());
1✔
833
    SymEngine::Expression update(j["update"]);
1✔
834
    auto& for_node = builder.add_for(
2✔
835
        parent, indvar, condition, init, update, assignments, json_to_debug_info_region(j["debug_info"], *debug_info_)
1✔
836
    );
837
    for_node.element_id_ = j["element_id"];
1✔
838

839
    assert(j["root"].contains("type"));
1✔
840
    assert(j["root"]["type"].is_string());
1✔
841
    assert(j["root"]["type"] == "sequence");
1✔
842
    json_to_sequence(j["root"], builder, for_node.root());
1✔
843
}
1✔
844

845
void JSONSerializer::json_to_if_else_node(
1✔
846
    const nlohmann::json& j,
847
    builder::StructuredSDFGBuilder& builder,
848
    structured_control_flow::Sequence& parent,
849
    control_flow::Assignments& assignments
850
) {
851
    assert(j.contains("type"));
1✔
852
    assert(j["type"].is_string());
1✔
853
    assert(j["type"] == "if_else");
1✔
854
    assert(j.contains("branches"));
1✔
855
    assert(j["branches"].is_array());
1✔
856
    auto& if_else_node =
1✔
857
        builder.add_if_else(parent, assignments, json_to_debug_info_region(j["debug_info"], *debug_info_));
1✔
858
    if_else_node.element_id_ = j["element_id"];
1✔
859
    for (const auto& branch : j["branches"]) {
3✔
860
        assert(branch.contains("condition"));
2✔
861
        assert(branch["condition"].is_string());
2✔
862
        assert(branch.contains("root"));
2✔
863
        assert(branch["root"].is_object());
2✔
864
        SymEngine::Expression condition_expr(branch["condition"]);
2✔
865
        assert(!SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic()).is_null());
2✔
866
        symbolic::Condition condition = SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic()
2✔
867
        );
868
        auto& branch_node = builder.add_case(if_else_node, condition);
2✔
869
        assert(branch["root"].contains("type"));
2✔
870
        assert(branch["root"]["type"].is_string());
2✔
871
        std::string type = branch["root"]["type"];
2✔
872
        if (type == "sequence") {
2✔
873
            json_to_sequence(branch["root"], builder, branch_node);
2✔
874
        } else {
2✔
875
            throw std::runtime_error("Unknown child type");
×
876
        }
877
    }
2✔
878
}
1✔
879

880
void JSONSerializer::json_to_while_node(
3✔
881
    const nlohmann::json& j,
882
    builder::StructuredSDFGBuilder& builder,
883
    structured_control_flow::Sequence& parent,
884
    control_flow::Assignments& assignments
885
) {
886
    assert(j.contains("type"));
3✔
887
    assert(j["type"].is_string());
3✔
888
    assert(j["type"] == "while");
3✔
889
    assert(j.contains("root"));
3✔
890
    assert(j["root"].is_object());
3✔
891

892
    auto& while_node = builder.add_while(parent, assignments, json_to_debug_info_region(j["debug_info"], *debug_info_));
3✔
893
    while_node.element_id_ = j["element_id"];
3✔
894

895
    assert(j["root"]["type"] == "sequence");
3✔
896
    json_to_sequence(j["root"], builder, while_node.root());
3✔
897
}
3✔
898

899
void JSONSerializer::json_to_break_node(
1✔
900
    const nlohmann::json& j,
901
    builder::StructuredSDFGBuilder& builder,
902
    structured_control_flow::Sequence& parent,
903
    control_flow::Assignments& assignments
904
) {
905
    assert(j.contains("type"));
1✔
906
    assert(j["type"].is_string());
1✔
907
    assert(j["type"] == "break");
1✔
908
    auto& node = builder.add_break(parent, assignments, json_to_debug_info_region(j["debug_info"], *debug_info_));
1✔
909
    node.element_id_ = j["element_id"];
1✔
910
}
1✔
911

912
void JSONSerializer::json_to_continue_node(
1✔
913
    const nlohmann::json& j,
914
    builder::StructuredSDFGBuilder& builder,
915
    structured_control_flow::Sequence& parent,
916
    control_flow::Assignments& assignments
917
) {
918
    assert(j.contains("type"));
1✔
919
    assert(j["type"].is_string());
1✔
920
    assert(j["type"] == "continue");
1✔
921
    auto& node = builder.add_continue(parent, assignments, json_to_debug_info_region(j["debug_info"], *debug_info_));
1✔
922
    node.element_id_ = j["element_id"];
1✔
923
}
1✔
924

925
void JSONSerializer::json_to_map_node(
1✔
926
    const nlohmann::json& j,
927
    builder::StructuredSDFGBuilder& builder,
928
    structured_control_flow::Sequence& parent,
929
    control_flow::Assignments& assignments
930
) {
931
    assert(j.contains("type"));
1✔
932
    assert(j["type"].is_string());
1✔
933
    assert(j["type"] == "map");
1✔
934
    assert(j.contains("indvar"));
1✔
935
    assert(j["indvar"].is_string());
1✔
936
    assert(j.contains("init"));
1✔
937
    assert(j["init"].is_string());
1✔
938
    assert(j.contains("condition"));
1✔
939
    assert(j["condition"].is_string());
1✔
940
    assert(j.contains("update"));
1✔
941
    assert(j["update"].is_string());
1✔
942
    assert(j.contains("root"));
1✔
943
    assert(j["root"].is_object());
1✔
944
    assert(j.contains("schedule_type"));
1✔
945
    assert(j["schedule_type"].is_string());
1✔
946

947
    structured_control_flow::ScheduleType schedule_type =
948
        schedule_type_from_string(j["schedule_type"].get<std::string>());
1✔
949

950
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
1✔
951
    SymEngine::Expression init(j["init"]);
1✔
952
    SymEngine::Expression condition_expr(j["condition"]);
1✔
953
    assert(!SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic()).is_null());
1✔
954
    symbolic::Condition condition = SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic());
1✔
955
    SymEngine::Expression update(j["update"]);
1✔
956

957
    auto& map_node = builder.add_map(
2✔
958
        parent,
1✔
959
        indvar,
960
        condition,
961
        init,
1✔
962
        update,
1✔
963
        schedule_type,
964
        assignments,
1✔
965
        json_to_debug_info_region(j["debug_info"], *debug_info_)
1✔
966
    );
967
    map_node.element_id_ = j["element_id"];
1✔
968

969
    assert(j["root"].contains("type"));
1✔
970
    assert(j["root"]["type"].is_string());
1✔
971
    assert(j["root"]["type"] == "sequence");
1✔
972
    json_to_sequence(j["root"], builder, map_node.root());
1✔
973
}
1✔
974

975
void JSONSerializer::json_to_return_node(
1✔
976
    const nlohmann::json& j,
977
    builder::StructuredSDFGBuilder& builder,
978
    structured_control_flow::Sequence& parent,
979
    control_flow::Assignments& assignments
980
) {
981
    assert(j.contains("type"));
1✔
982
    assert(j["type"].is_string());
1✔
983
    assert(j["type"] == "return");
1✔
984

985
    auto& node = builder.add_return(parent, assignments, json_to_debug_info_region(j["debug_info"], *debug_info_));
1✔
986
    node.element_id_ = j["element_id"];
1✔
987
}
1✔
988

989
std::unique_ptr<types::IType> JSONSerializer::json_to_type(const nlohmann::json& j) {
41✔
990
    if (j.contains("type")) {
41✔
991
        if (j["type"] == "scalar") {
41✔
992
            // Deserialize scalar type
993
            assert(j.contains("primitive_type"));
30✔
994
            types::PrimitiveType primitive_type = j["primitive_type"];
30✔
995
            assert(j.contains("storage_type"));
30✔
996
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
30✔
997
            assert(j.contains("initializer"));
30✔
998
            std::string initializer = j["initializer"];
30✔
999
            assert(j.contains("alignment"));
30✔
1000
            size_t alignment = j["alignment"];
30✔
1001
            return std::make_unique<types::Scalar>(storage_type, alignment, initializer, primitive_type);
30✔
1002
        } else if (j["type"] == "array") {
41✔
1003
            // Deserialize array type
1004
            assert(j.contains("element_type"));
2✔
1005
            std::unique_ptr<types::IType> member_type = json_to_type(j["element_type"]);
2✔
1006
            assert(j.contains("num_elements"));
2✔
1007
            std::string num_elements_str = j["num_elements"];
2✔
1008
            // Convert num_elements_str to symbolic::Expression
1009
            SymEngine::Expression num_elements(num_elements_str);
2✔
1010
            assert(j.contains("storage_type"));
2✔
1011
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
2✔
1012
            assert(j.contains("initializer"));
2✔
1013
            std::string initializer = j["initializer"];
2✔
1014
            assert(j.contains("alignment"));
2✔
1015
            size_t alignment = j["alignment"];
2✔
1016
            return std::make_unique<types::Array>(storage_type, alignment, initializer, *member_type, num_elements);
2✔
1017
        } else if (j["type"] == "pointer") {
11✔
1018
            // Deserialize pointer type
1019
            std::optional<std::unique_ptr<types::IType>> pointee_type;
6✔
1020
            if (j.contains("pointee_type")) {
6✔
1021
                assert(j.contains("pointee_type"));
5✔
1022
                pointee_type = json_to_type(j["pointee_type"]);
5✔
1023
            } else {
5✔
1024
                pointee_type = std::nullopt;
1✔
1025
            }
1026
            assert(j.contains("storage_type"));
6✔
1027
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
6✔
1028
            assert(j.contains("initializer"));
6✔
1029
            std::string initializer = j["initializer"];
6✔
1030
            assert(j.contains("alignment"));
6✔
1031
            size_t alignment = j["alignment"];
6✔
1032
            if (pointee_type.has_value()) {
6✔
1033
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer, *pointee_type.value());
5✔
1034
            } else {
1035
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer);
1✔
1036
            }
1037
        } else if (j["type"] == "structure") {
9✔
1038
            // Deserialize structure type
1039
            assert(j.contains("name"));
2✔
1040
            std::string name = j["name"];
2✔
1041
            assert(j.contains("storage_type"));
2✔
1042
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
2✔
1043
            assert(j.contains("initializer"));
2✔
1044
            std::string initializer = j["initializer"];
2✔
1045
            assert(j.contains("alignment"));
2✔
1046
            size_t alignment = j["alignment"];
2✔
1047
            return std::make_unique<types::Structure>(storage_type, alignment, initializer, name);
2✔
1048
        } else if (j["type"] == "function") {
3✔
1049
            // Deserialize function type
1050
            assert(j.contains("return_type"));
1✔
1051
            std::unique_ptr<types::IType> return_type = json_to_type(j["return_type"]);
1✔
1052
            assert(j.contains("params"));
1✔
1053
            std::vector<std::unique_ptr<types::IType>> params;
1✔
1054
            for (const auto& param : j["params"]) {
3✔
1055
                params.push_back(json_to_type(param));
2✔
1056
            }
1057
            assert(j.contains("is_var_arg"));
1✔
1058
            bool is_var_arg = j["is_var_arg"];
1✔
1059
            assert(j.contains("storage_type"));
1✔
1060
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
1✔
1061
            assert(j.contains("initializer"));
1✔
1062
            std::string initializer = j["initializer"];
1✔
1063
            assert(j.contains("alignment"));
1✔
1064
            size_t alignment = j["alignment"];
1✔
1065
            auto function =
1066
                std::make_unique<types::Function>(storage_type, alignment, initializer, *return_type, is_var_arg);
1✔
1067
            for (const auto& param : params) {
3✔
1068
                function->add_param(*param);
2✔
1069
            }
1070
            return function->clone();
1✔
1071

1072
        } else {
1✔
1073
            throw std::runtime_error("Unknown type");
×
1074
        }
1075
    } else {
1076
        throw std::runtime_error("Type not found");
×
1077
    }
1078
}
41✔
1079

1080
DebugLoc JSONSerializer::json_to_debug_loc(const nlohmann::json& j) {
7✔
1081
    assert(j.contains("has"));
7✔
1082
    assert(j["has"].is_boolean());
7✔
1083
    if (!j["has"]) {
7✔
NEW
1084
        return DebugLoc();
×
1085
    }
1086
    assert(j.contains("filename"));
7✔
1087
    assert(j["filename"].is_string());
7✔
1088
    std::string filename = j["filename"];
7✔
1089
    assert(j.contains("function"));
7✔
1090
    assert(j["function"].is_string());
7✔
1091
    std::string function = j["function"];
7✔
1092
    assert(j.contains("line"));
7✔
1093
    assert(j["line"].is_number_integer());
7✔
1094
    size_t line = j["line"];
7✔
1095
    assert(j.contains("column"));
7✔
1096
    assert(j["column"].is_number_integer());
7✔
1097
    size_t column = j["column"];
7✔
1098
    return DebugLoc(filename, function, line, column, true);
7✔
1099
}
7✔
1100

1101
DebugInfoElement JSONSerializer::json_to_debug_info_element(const nlohmann::json& j) {
3✔
1102
    assert(j.contains("has"));
3✔
1103
    assert(j["has"].is_boolean());
3✔
1104
    if (!j["has"]) {
3✔
NEW
1105
        return DebugInfoElement();
×
1106
    }
1107
    assert(j.contains("locations"));
3✔
1108
    assert(j["locations"].is_array());
3✔
1109
    std::vector<DebugLoc> locations;
3✔
1110
    for (const auto& loc_json : j["locations"]) {
9✔
1111
        locations.push_back(json_to_debug_loc(loc_json));
6✔
1112
    }
1113
    return DebugInfoElement(locations);
3✔
1114
}
3✔
1115

1116
DebugInfoRegion JSONSerializer::json_to_debug_info_region(const nlohmann::json& j, const DebugInfo& debug_info) {
74✔
1117
    assert(j.contains("has"));
74✔
1118
    assert(j["has"].is_boolean());
74✔
1119
    if (!j["has"]) {
74✔
1120
        return DebugInfoRegion();
72✔
1121
    }
1122

1123
    assert(j.contains("indices"));
2✔
1124
    assert(j["indices"].is_array());
2✔
1125
    std::unordered_set<size_t> indices;
2✔
1126
    for (auto index_json : j["indices"]) {
6✔
1127
        size_t index = index_json;
4✔
1128
        indices.insert(index);
4✔
1129
    }
4✔
1130
    DebugInfoRegion debug_info_region(indices, debug_info.instructions());
2✔
1131
    assert(j.contains("filename"));
2✔
1132
    assert(j["filename"].is_string());
2✔
1133
    std::string filename = j["filename"];
2✔
1134
    assert(filename == debug_info_region.filename());
2✔
1135

1136
    assert(j.contains("function"));
2✔
1137
    assert(j["function"].is_string());
2✔
1138
    std::string function = j["function"];
2✔
1139
    assert(function == debug_info_region.function());
2✔
1140

1141
    assert(j.contains("start_line"));
2✔
1142
    assert(j["start_line"].is_number_integer());
2✔
1143
    size_t start_line = j["start_line"];
2✔
1144
    assert(start_line == debug_info_region.start_line());
2✔
1145

1146
    assert(j.contains("start_column"));
2✔
1147
    assert(j["start_column"].is_number_integer());
2✔
1148
    size_t start_column = j["start_column"];
2✔
1149
    assert(start_column == debug_info_region.start_column());
2✔
1150

1151
    assert(j.contains("end_line"));
2✔
1152
    assert(j["end_line"].is_number_integer());
2✔
1153
    size_t end_line = j["end_line"];
2✔
1154
    assert(end_line == debug_info_region.end_line());
2✔
1155

1156
    assert(j.contains("end_column"));
2✔
1157
    assert(j["end_column"].is_number_integer());
2✔
1158
    size_t end_column = j["end_column"];
2✔
1159
    assert(end_column == debug_info_region.end_column());
2✔
1160

1161
    return debug_info_region;
2✔
1162
}
74✔
1163

1164
DebugInfo JSONSerializer::json_to_debug_info(const nlohmann::json& j) {
6✔
1165
    assert(j.contains("instructions"));
6✔
1166
    assert(j["instructions"].is_array());
6✔
1167
    DebugInfo debug_info;
6✔
1168
    std::vector<DebugInfoElement> instructions;
6✔
1169
    for (const auto& instruction_json : j["instructions"]) {
8✔
1170
        debug_info.add_element(json_to_debug_info_element(instruction_json));
2✔
1171
    }
1172
    return debug_info;
6✔
1173
}
6✔
1174

1175
std::string JSONSerializer::expression(const symbolic::Expression& expr) {
47✔
1176
    JSONSymbolicPrinter printer;
47✔
1177
    return printer.apply(expr);
47✔
1178
};
47✔
1179

1180
void JSONSymbolicPrinter::bvisit(const SymEngine::Equality& x) {
×
1181
    str_ = apply(x.get_args()[0]) + " == " + apply(x.get_args()[1]);
×
1182
    str_ = parenthesize(str_);
×
1183
};
×
1184

1185
void JSONSymbolicPrinter::bvisit(const SymEngine::Unequality& x) {
×
1186
    str_ = apply(x.get_args()[0]) + " != " + apply(x.get_args()[1]);
×
1187
    str_ = parenthesize(str_);
×
1188
};
×
1189

1190
void JSONSymbolicPrinter::bvisit(const SymEngine::LessThan& x) {
×
1191
    str_ = apply(x.get_args()[0]) + " <= " + apply(x.get_args()[1]);
×
1192
    str_ = parenthesize(str_);
×
1193
};
×
1194

1195
void JSONSymbolicPrinter::bvisit(const SymEngine::StrictLessThan& x) {
4✔
1196
    str_ = apply(x.get_args()[0]) + " < " + apply(x.get_args()[1]);
4✔
1197
    str_ = parenthesize(str_);
4✔
1198
};
4✔
1199

1200
void JSONSymbolicPrinter::bvisit(const SymEngine::Min& x) {
×
1201
    std::ostringstream s;
×
1202
    auto container = x.get_args();
×
1203
    if (container.size() == 1) {
×
1204
        s << apply(*container.begin());
×
1205
    } else {
×
1206
        s << "min(";
×
1207
        s << apply(*container.begin());
×
1208

1209
        // Recursively apply __daisy_min to the arguments
1210
        SymEngine::vec_basic subargs;
×
1211
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1212
            subargs.push_back(*it);
×
1213
        }
×
1214
        auto submin = SymEngine::min(subargs);
×
1215
        s << ", " << apply(submin);
×
1216

1217
        s << ")";
×
1218
    }
×
1219

1220
    str_ = s.str();
×
1221
};
×
1222

1223
void JSONSymbolicPrinter::bvisit(const SymEngine::Max& x) {
×
1224
    std::ostringstream s;
×
1225
    auto container = x.get_args();
×
1226
    if (container.size() == 1) {
×
1227
        s << apply(*container.begin());
×
1228
    } else {
×
1229
        s << "max(";
×
1230
        s << apply(*container.begin());
×
1231

1232
        // Recursively apply __daisy_max to the arguments
1233
        SymEngine::vec_basic subargs;
×
1234
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1235
            subargs.push_back(*it);
×
1236
        }
×
1237
        auto submax = SymEngine::max(subargs);
×
1238
        s << ", " << apply(submax);
×
1239

1240
        s << ")";
×
1241
    }
×
1242

1243
    str_ = s.str();
×
1244
};
×
1245

1246
void LibraryNodeSerializerRegistry::
1247
    register_library_node_serializer(std::string library_node_code, LibraryNodeSerializerFn fn) {
58✔
1248
    std::lock_guard<std::mutex> lock(mutex_);
58✔
1249
    if (factory_map_.find(library_node_code) != factory_map_.end()) {
58✔
1250
        throw std::runtime_error(
×
1251
            "Library node serializer already registered for library node code: " + std::string(library_node_code)
×
1252
        );
1253
    }
1254
    factory_map_[library_node_code] = std::move(fn);
58✔
1255
}
58✔
1256

1257
LibraryNodeSerializerFn LibraryNodeSerializerRegistry::get_library_node_serializer(std::string library_node_code) {
1✔
1258
    auto it = factory_map_.find(library_node_code);
1✔
1259
    if (it != factory_map_.end()) {
1✔
1260
        return it->second;
1✔
1261
    }
1262
    return nullptr;
×
1263
}
1✔
1264

1265
size_t LibraryNodeSerializerRegistry::size() const { return factory_map_.size(); }
×
1266

1267
void register_default_serializers() {
2✔
1268
    // Metadata
1269
    LibraryNodeSerializerRegistry::instance()
2✔
1270
        .register_library_node_serializer(data_flow::LibraryNodeType_Metadata.value(), []() {
2✔
1271
            return std::make_unique<data_flow::MetadataNodeSerializer>();
×
1272
        });
1273

1274
    // Barrier
1275
    LibraryNodeSerializerRegistry::instance()
2✔
1276
        .register_library_node_serializer(data_flow::LibraryNodeType_BarrierLocal.value(), []() {
3✔
1277
            return std::make_unique<data_flow::BarrierLocalNodeSerializer>();
1✔
1278
        });
1279

1280
    // ML
1281
    LibraryNodeSerializerRegistry::instance()
2✔
1282
        .register_library_node_serializer(math::ml::LibraryNodeType_Abs.value(), []() {
2✔
1283
            return std::make_unique<math::ml::AbsNodeSerializer>();
×
1284
        });
1285
    LibraryNodeSerializerRegistry::instance()
2✔
1286
        .register_library_node_serializer(math::ml::LibraryNodeType_Add.value(), []() {
2✔
1287
            return std::make_unique<math::ml::AddNodeSerializer>();
×
1288
        });
1289
    LibraryNodeSerializerRegistry::instance()
2✔
1290
        .register_library_node_serializer(math::ml::LibraryNodeType_BatchNormalization.value(), []() {
2✔
1291
            return std::make_unique<math::ml::BatchNormalizationNodeSerializer>();
×
1292
        });
1293
    LibraryNodeSerializerRegistry::instance()
2✔
1294
        .register_library_node_serializer(math::ml::LibraryNodeType_Clip.value(), []() {
2✔
1295
            return std::make_unique<math::ml::ClipNodeSerializer>();
×
1296
        });
1297
    LibraryNodeSerializerRegistry::instance()
2✔
1298
        .register_library_node_serializer(math::ml::LibraryNodeType_Conv.value(), []() {
2✔
1299
            return std::make_unique<math::ml::ConvNodeSerializer>();
×
1300
        });
1301
    LibraryNodeSerializerRegistry::instance()
2✔
1302
        .register_library_node_serializer(math::ml::LibraryNodeType_Div.value(), []() {
2✔
1303
            return std::make_unique<math::ml::DivNodeSerializer>();
×
1304
        });
1305
    LibraryNodeSerializerRegistry::instance()
2✔
1306
        .register_library_node_serializer(math::ml::LibraryNodeType_Dropout.value(), []() {
2✔
1307
            return std::make_unique<math::ml::DropoutSerializer>();
×
1308
        });
1309
    LibraryNodeSerializerRegistry::instance()
2✔
1310
        .register_library_node_serializer(math::ml::LibraryNodeType_Elu.value(), []() {
2✔
1311
            return std::make_unique<math::ml::EluNodeSerializer>();
×
1312
        });
1313
    LibraryNodeSerializerRegistry::instance()
2✔
1314
        .register_library_node_serializer(math::ml::LibraryNodeType_Erf.value(), []() {
2✔
1315
            return std::make_unique<math::ml::ErfNodeSerializer>();
×
1316
        });
1317
    LibraryNodeSerializerRegistry::instance()
2✔
1318
        .register_library_node_serializer(math::ml::LibraryNodeType_Gemm.value(), []() {
2✔
1319
            return std::make_unique<math::ml::GemmNodeSerializer>();
×
1320
        });
1321
    LibraryNodeSerializerRegistry::instance()
2✔
1322
        .register_library_node_serializer(math::ml::LibraryNodeType_HardSigmoid.value(), []() {
2✔
1323
            return std::make_unique<math::ml::HardSigmoidNodeSerializer>();
×
1324
        });
1325
    LibraryNodeSerializerRegistry::instance()
2✔
1326
        .register_library_node_serializer(math::ml::LibraryNodeType_LayerNormalization.value(), []() {
2✔
1327
            return std::make_unique<math::ml::LayerNormalizationNodeSerializer>();
×
1328
        });
1329
    LibraryNodeSerializerRegistry::instance()
2✔
1330
        .register_library_node_serializer(math::ml::LibraryNodeType_LeakyReLU.value(), []() {
2✔
1331
            return std::make_unique<math::ml::LeakyReLUNodeSerializer>();
×
1332
        });
1333
    LibraryNodeSerializerRegistry::instance()
2✔
1334
        .register_library_node_serializer(math::ml::LibraryNodeType_LogSoftmax.value(), []() {
2✔
1335
            return std::make_unique<math::ml::LogSoftmaxNodeSerializer>();
×
1336
        });
1337
    LibraryNodeSerializerRegistry::instance()
2✔
1338
        .register_library_node_serializer(math::ml::LibraryNodeType_MatMul.value(), []() {
2✔
1339
            return std::make_unique<math::ml::MatMulNodeSerializer>();
×
1340
        });
1341
    LibraryNodeSerializerRegistry::instance()
2✔
1342
        .register_library_node_serializer(math::ml::LibraryNodeType_MaxPool.value(), []() {
2✔
1343
            return std::make_unique<math::ml::MaxPoolNodeSerializer>();
×
1344
        });
1345
    LibraryNodeSerializerRegistry::instance()
2✔
1346
        .register_library_node_serializer(math::ml::LibraryNodeType_Mul.value(), []() {
2✔
1347
            return std::make_unique<math::ml::MulNodeSerializer>();
×
1348
        });
1349
    LibraryNodeSerializerRegistry::instance()
2✔
1350
        .register_library_node_serializer(math::ml::LibraryNodeType_Pow.value(), []() {
2✔
1351
            return std::make_unique<math::ml::PowNodeSerializer>();
×
1352
        });
1353
    LibraryNodeSerializerRegistry::instance()
2✔
1354
        .register_library_node_serializer(math::ml::LibraryNodeType_ReduceMean.value(), []() {
2✔
1355
            return std::make_unique<math::ml::ReduceMeanNodeSerializer>();
×
1356
        });
1357
    LibraryNodeSerializerRegistry::instance()
2✔
1358
        .register_library_node_serializer(math::ml::LibraryNodeType_ReLU.value(), []() {
2✔
1359
            return std::make_unique<math::ml::ReLUNodeSerializer>();
×
1360
        });
1361
    LibraryNodeSerializerRegistry::instance()
2✔
1362
        .register_library_node_serializer(math::ml::LibraryNodeType_Sigmoid.value(), []() {
2✔
1363
            return std::make_unique<math::ml::SigmoidNodeSerializer>();
×
1364
        });
1365
    LibraryNodeSerializerRegistry::instance()
2✔
1366
        .register_library_node_serializer(math::ml::LibraryNodeType_Softmax.value(), []() {
2✔
1367
            return std::make_unique<math::ml::SoftmaxNodeSerializer>();
×
1368
        });
1369
    LibraryNodeSerializerRegistry::instance()
2✔
1370
        .register_library_node_serializer(math::ml::LibraryNodeType_Sqrt.value(), []() {
2✔
1371
            return std::make_unique<math::ml::SqrtNodeSerializer>();
×
1372
        });
1373
    LibraryNodeSerializerRegistry::instance()
2✔
1374
        .register_library_node_serializer(math::ml::LibraryNodeType_Sub.value(), []() {
2✔
1375
            return std::make_unique<math::ml::SubNodeSerializer>();
×
1376
        });
1377
    LibraryNodeSerializerRegistry::instance()
2✔
1378
        .register_library_node_serializer(math::ml::LibraryNodeType_Tanh.value(), []() {
2✔
1379
            return std::make_unique<math::ml::TanhNodeSerializer>();
×
1380
        });
1381

1382
    // BLAS
1383
    LibraryNodeSerializerRegistry::instance()
2✔
1384
        .register_library_node_serializer(math::blas::LibraryNodeType_DOT.value(), []() {
2✔
1385
            return std::make_unique<math::blas::DotNodeSerializer>();
×
1386
        });
1387
    LibraryNodeSerializerRegistry::instance()
2✔
1388
        .register_library_node_serializer(math::blas::LibraryNodeType_GEMM.value(), []() {
2✔
1389
            return std::make_unique<math::blas::GEMMNodeSerializer>();
×
1390
        });
1391
}
2✔
1392

1393
} // namespace serializer
1394
} // namespace sdfg
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc