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

daisytuner / sdfglib / 17653942017

11 Sep 2025 06:34PM UTC coverage: 59.145% (-0.6%) from 59.755%
17653942017

push

github

web-flow
Merge pull request #224 from daisytuner/revert-210-NewDebugInfo

Revert "New debug info"

313 of 466 new or added lines in 44 files covered. (67.17%)

21 existing lines in 4 files now uncovered.

9274 of 15680 relevant lines covered (59.15%)

115.92 hits per line

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

80.21
/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/element.h"
17
#include "sdfg/structured_control_flow/block.h"
18
#include "sdfg/structured_control_flow/for.h"
19
#include "sdfg/structured_control_flow/if_else.h"
20
#include "sdfg/structured_control_flow/map.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
/*
65
 * * JSONSerializer class
66
 * * Serialization logic
67
 */
68

69
nlohmann::json JSONSerializer::serialize(const sdfg::StructuredSDFG& sdfg) {
5✔
70
    nlohmann::json j;
5✔
71

72
    j["name"] = sdfg.name();
5✔
73
    j["element_counter"] = sdfg.element_counter();
5✔
74
    j["type"] = std::string(sdfg.type().value());
5✔
75

76
    j["structures"] = nlohmann::json::array();
5✔
77
    for (const auto& structure_name : sdfg.structures()) {
6✔
78
        const auto& structure = sdfg.structure(structure_name);
1✔
79
        nlohmann::json structure_json;
1✔
80
        structure_definition_to_json(structure_json, structure);
1✔
81
        j["structures"].push_back(structure_json);
1✔
82
    }
1✔
83

84
    j["containers"] = nlohmann::json::object();
5✔
85
    for (const auto& container : sdfg.containers()) {
17✔
86
        nlohmann::json desc;
12✔
87
        type_to_json(desc, sdfg.type(container));
12✔
88
        j["containers"][container] = desc;
12✔
89
    }
12✔
90

91
    j["arguments"] = nlohmann::json::array();
5✔
92
    for (const auto& argument : sdfg.arguments()) {
8✔
93
        j["arguments"].push_back(argument);
3✔
94
    }
95

96
    j["externals"] = nlohmann::json::array();
5✔
97
    for (const auto& external : sdfg.externals()) {
9✔
98
        nlohmann::json external_json;
4✔
99
        external_json["name"] = external;
4✔
100
        external_json["linkage_type"] = sdfg.linkage_type(external);
4✔
101
        j["externals"].push_back(external_json);
4✔
102
    }
4✔
103

104
    j["metadata"] = nlohmann::json::object();
5✔
105
    for (const auto& entry : sdfg.metadata()) {
6✔
106
        j["metadata"][entry.first] = entry.second;
1✔
107
    }
108

109
    // Walk the SDFG
110
    nlohmann::json root_json;
5✔
111
    sequence_to_json(root_json, sdfg.root());
5✔
112
    j["root"] = root_json;
5✔
113

114
    return j;
5✔
115
}
5✔
116

117
void JSONSerializer::dataflow_to_json(nlohmann::json& j, const data_flow::DataFlowGraph& dataflow) {
21✔
118
    j["type"] = "dataflow";
21✔
119
    j["nodes"] = nlohmann::json::array();
21✔
120
    j["edges"] = nlohmann::json::array();
21✔
121

122
    for (auto& node : dataflow.nodes()) {
41✔
123
        nlohmann::json node_json;
20✔
124
        node_json["element_id"] = node.element_id();
20✔
125

126
        node_json["debug_info"] = nlohmann::json::object();
20✔
127
        debug_info_to_json(node_json["debug_info"], node.debug_info());
20✔
128

129
        if (auto tasklet = dynamic_cast<const data_flow::Tasklet*>(&node)) {
20✔
130
            node_json["type"] = "tasklet";
5✔
131
            node_json["code"] = tasklet->code();
5✔
132
            node_json["inputs"] = nlohmann::json::array();
5✔
133
            for (auto& input : tasklet->inputs()) {
15✔
134
                node_json["inputs"].push_back(input);
10✔
135
            }
136
            node_json["output"] = tasklet->output();
5✔
137
            // node_json["conditional"] = tasklet->is_conditional();
138
            // if (tasklet->is_conditional()) {
139
            //     node_json["condition"] = dumps_expression(tasklet->condition());
140
            // }
141
        } else if (auto lib_node = dynamic_cast<const data_flow::LibraryNode*>(&node)) {
20✔
142
            node_json["type"] = "library_node";
×
143
            node_json["implementation_type"] = std::string(lib_node->implementation_type().value());
×
144
            auto serializer_fn =
145
                LibraryNodeSerializerRegistry::instance().get_library_node_serializer(lib_node->code().value());
×
146
            if (serializer_fn == nullptr) {
×
147
                throw std::runtime_error("Unknown library node code: " + std::string(lib_node->code().value()));
×
148
            }
149
            auto serializer = serializer_fn();
×
150
            auto lib_node_json = serializer->serialize(*lib_node);
×
151
            node_json.merge_patch(lib_node_json);
×
152
        } else if (auto code_node = dynamic_cast<const data_flow::AccessNode*>(&node)) {
15✔
153
            node_json["type"] = "access_node";
15✔
154
            node_json["data"] = code_node->data();
15✔
155
        } else {
15✔
156
            throw std::runtime_error("Unknown node type");
×
157
        }
158

159
        j["nodes"].push_back(node_json);
20✔
160
    }
20✔
161

162
    for (auto& edge : dataflow.edges()) {
36✔
163
        nlohmann::json edge_json;
15✔
164
        edge_json["element_id"] = edge.element_id();
15✔
165

166
        edge_json["debug_info"] = nlohmann::json::object();
15✔
167
        debug_info_to_json(edge_json["debug_info"], edge.debug_info());
15✔
168

169
        edge_json["src"] = edge.src().element_id();
15✔
170
        edge_json["dst"] = edge.dst().element_id();
15✔
171

172
        edge_json["src_conn"] = edge.src_conn();
15✔
173
        edge_json["dst_conn"] = edge.dst_conn();
15✔
174

175
        edge_json["subset"] = nlohmann::json::array();
15✔
176
        for (auto& subset : edge.subset()) {
21✔
177
            edge_json["subset"].push_back(expression(subset));
6✔
178
        }
179

180
        edge_json["begin_subset"] = nlohmann::json::array();
15✔
181
        for (auto& subset : edge.begin_subset()) {
21✔
182
            edge_json["begin_subset"].push_back(expression(subset));
6✔
183
        }
184

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

190
        nlohmann::json base_type_json;
15✔
191
        type_to_json(base_type_json, edge.base_type());
15✔
192
        edge_json["base_type"] = base_type_json;
15✔
193

194
        j["edges"].push_back(edge_json);
15✔
195
    }
15✔
196
}
21✔
197

198
void JSONSerializer::block_to_json(nlohmann::json& j, const structured_control_flow::Block& block) {
19✔
199
    j["type"] = "block";
19✔
200
    j["element_id"] = block.element_id();
19✔
201

202
    j["debug_info"] = nlohmann::json::object();
19✔
203
    debug_info_to_json(j["debug_info"], block.debug_info());
19✔
204

205
    nlohmann::json dataflow_json;
19✔
206
    dataflow_to_json(dataflow_json, block.dataflow());
19✔
207
    j["dataflow"] = dataflow_json;
19✔
208
}
19✔
209

210
void JSONSerializer::for_to_json(nlohmann::json& j, const structured_control_flow::For& for_node) {
2✔
211
    j["type"] = "for";
2✔
212
    j["element_id"] = for_node.element_id();
2✔
213

214
    j["debug_info"] = nlohmann::json::object();
2✔
215
    debug_info_to_json(j["debug_info"], for_node.debug_info());
2✔
216

217
    j["indvar"] = expression(for_node.indvar());
2✔
218
    j["init"] = expression(for_node.init());
2✔
219
    j["condition"] = expression(for_node.condition());
2✔
220
    j["update"] = expression(for_node.update());
2✔
221

222
    nlohmann::json body_json;
2✔
223
    sequence_to_json(body_json, for_node.root());
2✔
224
    j["root"] = body_json;
2✔
225
}
2✔
226

227
void JSONSerializer::if_else_to_json(nlohmann::json& j, const structured_control_flow::IfElse& if_else_node) {
2✔
228
    j["type"] = "if_else";
2✔
229
    j["element_id"] = if_else_node.element_id();
2✔
230

231
    j["debug_info"] = nlohmann::json::object();
2✔
232
    debug_info_to_json(j["debug_info"], if_else_node.debug_info());
2✔
233

234
    j["branches"] = nlohmann::json::array();
2✔
235
    for (size_t i = 0; i < if_else_node.size(); i++) {
6✔
236
        nlohmann::json branch_json;
4✔
237
        branch_json["condition"] = expression(if_else_node.at(i).second);
4✔
238
        nlohmann::json body_json;
4✔
239
        sequence_to_json(body_json, if_else_node.at(i).first);
4✔
240
        branch_json["root"] = body_json;
4✔
241
        j["branches"].push_back(branch_json);
4✔
242
    }
4✔
243
}
2✔
244

245
void JSONSerializer::while_node_to_json(nlohmann::json& j, const structured_control_flow::While& while_node) {
5✔
246
    j["type"] = "while";
5✔
247
    j["element_id"] = while_node.element_id();
5✔
248

249
    j["debug_info"] = nlohmann::json::object();
5✔
250
    debug_info_to_json(j["debug_info"], while_node.debug_info());
5✔
251

252
    nlohmann::json body_json;
5✔
253
    sequence_to_json(body_json, while_node.root());
5✔
254
    j["root"] = body_json;
5✔
255
}
5✔
256

257
void JSONSerializer::break_node_to_json(nlohmann::json& j, const structured_control_flow::Break& break_node) {
2✔
258
    j["type"] = "break";
2✔
259
    j["element_id"] = break_node.element_id();
2✔
260

261
    j["debug_info"] = nlohmann::json::object();
2✔
262
    debug_info_to_json(j["debug_info"], break_node.debug_info());
2✔
263
}
2✔
264

265
void JSONSerializer::continue_node_to_json(nlohmann::json& j, const structured_control_flow::Continue& continue_node) {
2✔
266
    j["type"] = "continue";
2✔
267
    j["element_id"] = continue_node.element_id();
2✔
268

269
    j["debug_info"] = nlohmann::json::object();
2✔
270
    debug_info_to_json(j["debug_info"], continue_node.debug_info());
2✔
271
}
2✔
272

273
void JSONSerializer::map_to_json(nlohmann::json& j, const structured_control_flow::Map& map_node) {
2✔
274
    j["type"] = "map";
2✔
275
    j["element_id"] = map_node.element_id();
2✔
276

277
    j["debug_info"] = nlohmann::json::object();
2✔
278
    debug_info_to_json(j["debug_info"], map_node.debug_info());
2✔
279

280
    j["indvar"] = expression(map_node.indvar());
2✔
281
    j["init"] = expression(map_node.init());
2✔
282
    j["condition"] = expression(map_node.condition());
2✔
283
    j["update"] = expression(map_node.update());
2✔
284

285
    j["schedule_type"] = nlohmann::json::object();
2✔
286
    schedule_type_to_json(j["schedule_type"], map_node.schedule_type());
2✔
287

288
    nlohmann::json body_json;
2✔
289
    sequence_to_json(body_json, map_node.root());
2✔
290
    j["root"] = body_json;
2✔
291
}
2✔
292

293
void JSONSerializer::return_node_to_json(nlohmann::json& j, const structured_control_flow::Return& return_node) {
2✔
294
    j["type"] = "return";
2✔
295
    j["element_id"] = return_node.element_id();
2✔
296

297
    j["debug_info"] = nlohmann::json::object();
2✔
298
    debug_info_to_json(j["debug_info"], return_node.debug_info());
2✔
299
}
2✔
300

301
void JSONSerializer::sequence_to_json(nlohmann::json& j, const structured_control_flow::Sequence& sequence) {
21✔
302
    j["type"] = "sequence";
21✔
303
    j["element_id"] = sequence.element_id();
21✔
304

305
    j["debug_info"] = nlohmann::json::object();
21✔
306
    debug_info_to_json(j["debug_info"], sequence.debug_info());
21✔
307

308
    j["children"] = nlohmann::json::array();
21✔
309
    j["transitions"] = nlohmann::json::array();
21✔
310

311
    for (size_t i = 0; i < sequence.size(); i++) {
42✔
312
        nlohmann::json child_json;
21✔
313
        auto& child = sequence.at(i).first;
21✔
314
        auto& transition = sequence.at(i).second;
21✔
315

316
        if (auto block = dynamic_cast<const structured_control_flow::Block*>(&child)) {
21✔
317
            block_to_json(child_json, *block);
17✔
318
        } else if (auto for_node = dynamic_cast<const structured_control_flow::For*>(&child)) {
21✔
319
            for_to_json(child_json, *for_node);
×
320
        } else if (auto sequence_node = dynamic_cast<const structured_control_flow::Sequence*>(&child)) {
4✔
321
            sequence_to_json(child_json, *sequence_node);
×
322
        } else if (auto condition_node = dynamic_cast<const structured_control_flow::IfElse*>(&child)) {
4✔
323
            if_else_to_json(child_json, *condition_node);
×
324
        } else if (auto while_node = dynamic_cast<const structured_control_flow::While*>(&child)) {
4✔
325
            while_node_to_json(child_json, *while_node);
×
326
        } else if (auto return_node = dynamic_cast<const structured_control_flow::Return*>(&child)) {
4✔
327
            return_node_to_json(child_json, *return_node);
×
328
        } else if (auto break_node = dynamic_cast<const structured_control_flow::Break*>(&child)) {
4✔
329
            break_node_to_json(child_json, *break_node);
2✔
330
        } else if (auto continue_node = dynamic_cast<const structured_control_flow::Continue*>(&child)) {
4✔
331
            continue_node_to_json(child_json, *continue_node);
2✔
332
        } else if (auto map_node = dynamic_cast<const structured_control_flow::Map*>(&child)) {
2✔
333
            map_to_json(child_json, *map_node);
×
334
        } else {
×
335
            throw std::runtime_error("Unknown child type");
×
336
        }
337

338
        j["children"].push_back(child_json);
21✔
339

340
        // Add transition information
341
        nlohmann::json transition_json;
21✔
342
        transition_json["type"] = "transition";
21✔
343
        transition_json["element_id"] = transition.element_id();
21✔
344

345
        transition_json["debug_info"] = nlohmann::json::object();
21✔
346
        debug_info_to_json(transition_json["debug_info"], transition.debug_info());
21✔
347

348
        transition_json["assignments"] = nlohmann::json::array();
21✔
349
        for (const auto& assignment : transition.assignments()) {
24✔
350
            nlohmann::json assignment_json;
3✔
351
            assignment_json["symbol"] = expression(assignment.first);
3✔
352
            assignment_json["expression"] = expression(assignment.second);
3✔
353
            transition_json["assignments"].push_back(assignment_json);
3✔
354
        }
3✔
355

356
        j["transitions"].push_back(transition_json);
21✔
357
    }
21✔
358
}
21✔
359

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

412
void JSONSerializer::structure_definition_to_json(nlohmann::json& j, const types::StructureDefinition& definition) {
2✔
413
    j["name"] = definition.name();
2✔
414
    j["members"] = nlohmann::json::array();
2✔
415
    for (size_t i = 0; i < definition.num_members(); i++) {
4✔
416
        nlohmann::json member_json;
2✔
417
        type_to_json(member_json, definition.member_type(symbolic::integer(i)));
2✔
418
        j["members"].push_back(member_json);
2✔
419
    }
2✔
420
    j["is_packed"] = definition.is_packed();
2✔
421
}
2✔
422

423
void JSONSerializer::debug_info_to_json(nlohmann::json& j, const DebugInfo& debug_info) {
113✔
424
    j["has"] = debug_info.has();
113✔
425
    j["filename"] = debug_info.filename();
113✔
426
    j["function"] = debug_info.function();
113✔
427
    j["start_line"] = debug_info.start_line();
113✔
428
    j["start_column"] = debug_info.start_column();
113✔
429
    j["end_line"] = debug_info.end_line();
113✔
430
    j["end_column"] = debug_info.end_column();
113✔
431
}
113✔
432

433
void JSONSerializer::schedule_type_to_json(nlohmann::json& j, const ScheduleType& schedule_type) {
3✔
434
    j["value"] = schedule_type.value();
3✔
435
    j["properties"] = nlohmann::json::object();
3✔
436
    for (const auto& prop : schedule_type.properties()) {
4✔
437
        j["properties"][prop.first] = prop.second;
1✔
438
    }
439
}
3✔
440

441
/*
442
 * * Deserialization logic
443
 */
444

445
std::unique_ptr<StructuredSDFG> JSONSerializer::deserialize(nlohmann::json& j) {
5✔
446
    assert(j.contains("name"));
5✔
447
    assert(j["name"].is_string());
5✔
448
    assert(j.contains("type"));
5✔
449
    assert(j["type"].is_string());
5✔
450
    assert(j["element_counter"].is_number_integer());
5✔
451

452
    FunctionType function_type = function_type_from_string(j["type"].get<std::string>());
5✔
453
    builder::StructuredSDFGBuilder builder(j["name"], function_type);
5✔
454

455
    size_t element_counter = j["element_counter"];
5✔
456
    builder.set_element_counter(element_counter);
5✔
457

458
    // deserialize structures
459
    assert(j.contains("structures"));
5✔
460
    assert(j["structures"].is_array());
5✔
461
    for (const auto& structure : j["structures"]) {
6✔
462
        assert(structure.contains("name"));
1✔
463
        assert(structure["name"].is_string());
1✔
464
        json_to_structure_definition(structure, builder);
1✔
465
    }
466

467
    nlohmann::json& containers = j["containers"];
5✔
468

469
    // deserialize externals
470
    for (const auto& external : j["externals"]) {
9✔
471
        assert(external.contains("name"));
4✔
472
        assert(external["name"].is_string());
4✔
473
        assert(external.contains("linkage_type"));
4✔
474
        assert(external["linkage_type"].is_number_integer());
4✔
475
        auto& type_desc = containers.at(external["name"].get<std::string>());
4✔
476
        auto type = json_to_type(type_desc);
4✔
477
        builder.add_external(external["name"], *type, LinkageType(external["linkage_type"]));
4✔
478
    }
4✔
479

480
    // deserialize arguments
481
    for (const auto& name : j["arguments"]) {
8✔
482
        auto& type_desc = containers.at(name.get<std::string>());
3✔
483
        auto type = json_to_type(type_desc);
3✔
484
        builder.add_container(name, *type, true, false);
3✔
485
    }
3✔
486

487
    // deserialize transients
488
    for (const auto& entry : containers.items()) {
17✔
489
        if (builder.subject().is_argument(entry.key())) {
12✔
490
            continue;
3✔
491
        }
492
        if (builder.subject().is_external(entry.key())) {
9✔
493
            continue;
4✔
494
        }
495
        auto type = json_to_type(entry.value());
5✔
496
        builder.add_container(entry.key(), *type, false, false);
5✔
497
    }
5✔
498

499
    // deserialize root node
500
    assert(j.contains("root"));
5✔
501
    auto& root = builder.subject().root();
5✔
502
    json_to_sequence(j["root"], builder, root);
5✔
503

504
    // deserialize metadata
505
    assert(j.contains("metadata"));
5✔
506
    assert(j["metadata"].is_object());
5✔
507
    for (const auto& entry : j["metadata"].items()) {
6✔
508
        builder.subject().add_metadata(entry.key(), entry.value());
1✔
509
    }
510

511
    builder.set_element_counter(element_counter);
5✔
512

513
    return builder.move();
5✔
514
}
5✔
515

516
void JSONSerializer::json_to_structure_definition(const nlohmann::json& j, builder::StructuredSDFGBuilder& builder) {
2✔
517
    assert(j.contains("name"));
2✔
518
    assert(j["name"].is_string());
2✔
519
    assert(j.contains("members"));
2✔
520
    assert(j["members"].is_array());
2✔
521
    assert(j.contains("is_packed"));
2✔
522
    assert(j["is_packed"].is_boolean());
2✔
523
    auto is_packed = j["is_packed"];
2✔
524
    auto& definition = builder.add_structure(j["name"], is_packed);
2✔
525
    for (const auto& member : j["members"]) {
4✔
526
        nlohmann::json member_json;
2✔
527
        auto member_type = json_to_type(member);
2✔
528
        definition.add_member(*member_type);
2✔
529
    }
2✔
530
}
2✔
531

532
std::vector<std::pair<std::string, types::Scalar>> JSONSerializer::json_to_arguments(const nlohmann::json& j) {
×
533
    std::vector<std::pair<std::string, types::Scalar>> arguments;
×
534
    for (const auto& argument : j) {
×
535
        assert(argument.contains("name"));
×
536
        assert(argument["name"].is_string());
×
537
        assert(argument.contains("type"));
×
538
        assert(argument["type"].is_object());
×
539
        std::string name = argument["name"];
×
540
        auto type = json_to_type(argument["type"]);
×
541
        arguments.emplace_back(name, *dynamic_cast<types::Scalar*>(type.get()));
×
542
    }
×
543
    return arguments;
×
544
}
×
545

546
void JSONSerializer::json_to_dataflow(
11✔
547
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Block& parent
548
) {
549
    std::unordered_map<size_t, data_flow::DataFlowNode&> nodes_map;
11✔
550

551
    assert(j.contains("nodes"));
11✔
552
    assert(j["nodes"].is_array());
11✔
553
    for (const auto& node : j["nodes"]) {
27✔
554
        assert(node.contains("type"));
16✔
555
        assert(node["type"].is_string());
16✔
556
        assert(node.contains("element_id"));
16✔
557
        assert(node["element_id"].is_number_integer());
16✔
558
        std::string type = node["type"];
16✔
559
        if (type == "tasklet") {
16✔
560
            assert(node.contains("code"));
4✔
561
            assert(node["code"].is_number_integer());
4✔
562
            assert(node.contains("inputs"));
4✔
563
            assert(node["inputs"].is_array());
4✔
564
            assert(node.contains("output"));
4✔
565
            assert(node["output"].is_string());
4✔
566
            auto inputs = node["inputs"].get<std::vector<std::string>>();
4✔
567

568
            auto& tasklet =
4✔
569
                builder
8✔
570
                    .add_tasklet(parent, node["code"], node["output"], inputs, json_to_debug_info(node["debug_info"]));
4✔
571
            tasklet.element_id_ = node["element_id"];
4✔
572
            nodes_map.insert({node["element_id"], tasklet});
4✔
573
        } else if (type == "library_node") {
16✔
574
            assert(node.contains("code"));
×
575
            data_flow::LibraryNodeCode code(node["code"].get<std::string>());
×
576

577
            auto serializer_fn = LibraryNodeSerializerRegistry::instance().get_library_node_serializer(code.value());
×
578
            if (serializer_fn == nullptr) {
×
579
                throw std::runtime_error("Unknown library node code: " + std::string(code.value()));
×
580
            }
581
            auto serializer = serializer_fn();
×
582
            auto& lib_node = serializer->deserialize(node, builder, parent);
×
583
            lib_node.implementation_type() =
×
584
                data_flow::ImplementationType(node["implementation_type"].get<std::string>());
×
585
            lib_node.element_id_ = node["element_id"];
×
586
            nodes_map.insert({node["element_id"], lib_node});
×
587
        } else if (type == "access_node") {
12✔
588
            assert(node.contains("data"));
12✔
589
            auto& access_node = builder.add_access(parent, node["data"], json_to_debug_info(node["debug_info"]));
12✔
590
            access_node.element_id_ = node["element_id"];
12✔
591
            nodes_map.insert({node["element_id"], access_node});
12✔
592
        } else {
12✔
593
            throw std::runtime_error("Unknown node type");
×
594
        }
595
    }
16✔
596

597
    assert(j.contains("edges"));
11✔
598
    assert(j["edges"].is_array());
11✔
599
    for (const auto& edge : j["edges"]) {
23✔
600
        assert(edge.contains("src"));
12✔
601
        assert(edge["src"].is_number_integer());
12✔
602
        assert(edge.contains("dst"));
12✔
603
        assert(edge["dst"].is_number_integer());
12✔
604
        assert(edge.contains("src_conn"));
12✔
605
        assert(edge["src_conn"].is_string());
12✔
606
        assert(edge.contains("dst_conn"));
12✔
607
        assert(edge["dst_conn"].is_string());
12✔
608
        assert(edge.contains("subset"));
12✔
609
        assert(edge["subset"].is_array());
12✔
610

611
        assert(nodes_map.find(edge["src"]) != nodes_map.end());
12✔
612
        assert(nodes_map.find(edge["dst"]) != nodes_map.end());
12✔
613
        auto& source = nodes_map.at(edge["src"]);
12✔
614
        auto& target = nodes_map.at(edge["dst"]);
12✔
615

616
        auto base_type = json_to_type(edge["base_type"]);
12✔
617

618
        if (edge.contains("begin_subset") && edge.contains("end_subset")) {
12✔
619
            assert(edge["begin_subset"].is_array());
12✔
620
            assert(edge["end_subset"].is_array());
12✔
621
            std::vector<symbolic::Expression> begin_subset;
12✔
622
            std::vector<symbolic::Expression> end_subset;
12✔
623
            for (const auto& subset_str : edge["begin_subset"]) {
16✔
624
                assert(subset_str.is_string());
4✔
625
                SymEngine::Expression subset_expr(subset_str);
4✔
626
                begin_subset.push_back(subset_expr);
4✔
627
            }
4✔
628
            for (const auto& subset_str : edge["end_subset"]) {
16✔
629
                assert(subset_str.is_string());
4✔
630
                SymEngine::Expression subset_expr(subset_str);
4✔
631
                end_subset.push_back(subset_expr);
4✔
632
            }
4✔
633
            auto& memlet = builder.add_memlet(
24✔
634
                parent,
12✔
635
                source,
12✔
636
                edge["src_conn"],
12✔
637
                target,
12✔
638
                edge["dst_conn"],
12✔
639
                begin_subset,
640
                end_subset,
641
                *base_type,
12✔
642
                json_to_debug_info(edge["debug_info"])
12✔
643
            );
644
            memlet.element_id_ = edge["element_id"];
12✔
645
        } else if (edge.contains("subset")) {
12✔
646
            assert(edge["subset"].is_array());
×
647
            std::vector<symbolic::Expression> subset;
×
648
            for (const auto& subset_str : edge["subset"]) {
×
649
                assert(subset_str.is_string());
×
650
                SymEngine::Expression subset_expr(subset_str);
×
651
                subset.push_back(subset_expr);
×
652
            }
×
653
            auto& memlet = builder.add_memlet(
×
654
                parent,
×
655
                source,
×
656
                edge["src_conn"],
×
657
                target,
×
658
                edge["dst_conn"],
×
659
                subset,
660
                *base_type,
×
NEW
661
                json_to_debug_info(edge["debug_info"])
×
662
            );
663
            memlet.element_id_ = edge["element_id"];
×
664
        } else {
×
665
            throw std::runtime_error("Subsets not specified in json");
×
666
        }
667
    }
12✔
668
}
11✔
669

670
void JSONSerializer::json_to_sequence(
14✔
671
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& sequence
672
) {
673
    assert(j.contains("type"));
14✔
674
    assert(j["type"].is_string());
14✔
675
    assert(j.contains("children"));
14✔
676
    assert(j["children"].is_array());
14✔
677
    assert(j.contains("transitions"));
14✔
678
    assert(j["transitions"].is_array());
14✔
679
    assert(j["transitions"].size() == j["children"].size());
14✔
680

681
    sequence.element_id_ = j["element_id"];
14✔
682
    sequence.debug_info_ = json_to_debug_info(j["debug_info"]);
14✔
683

684
    std::string type = j["type"];
14✔
685
    if (type == "sequence") {
14✔
686
        for (size_t i = 0; i < j["children"].size(); i++) {
25✔
687
            auto& child = j["children"][i];
11✔
688
            auto& transition = j["transitions"][i];
11✔
689
            assert(child.contains("type"));
11✔
690
            assert(child["type"].is_string());
11✔
691

692
            assert(transition.contains("type"));
11✔
693
            assert(transition["type"].is_string());
11✔
694
            assert(transition.contains("assignments"));
11✔
695
            assert(transition["assignments"].is_array());
11✔
696
            control_flow::Assignments assignments;
11✔
697
            for (const auto& assignment : transition["assignments"]) {
13✔
698
                assert(assignment.contains("symbol"));
2✔
699
                assert(assignment["symbol"].is_string());
2✔
700
                assert(assignment.contains("expression"));
2✔
701
                assert(assignment["expression"].is_string());
2✔
702
                SymEngine::Expression expr(assignment["expression"]);
2✔
703
                assignments.insert({symbolic::symbol(assignment["symbol"]), expr});
2✔
704
            }
2✔
705

706
            if (child["type"] == "block") {
11✔
707
                json_to_block_node(child, builder, sequence, assignments);
9✔
708
            } else if (child["type"] == "for") {
11✔
709
                json_to_for_node(child, builder, sequence, assignments);
×
710
            } else if (child["type"] == "if_else") {
2✔
711
                json_to_if_else_node(child, builder, sequence, assignments);
×
712
            } else if (child["type"] == "while") {
2✔
713
                json_to_while_node(child, builder, sequence, assignments);
×
714
            } else if (child["type"] == "break") {
2✔
715
                json_to_break_node(child, builder, sequence, assignments);
1✔
716
            } else if (child["type"] == "continue") {
2✔
717
                json_to_continue_node(child, builder, sequence, assignments);
1✔
718
            } else if (child["type"] == "return") {
1✔
719
                json_to_return_node(child, builder, sequence, assignments);
×
720
            } else if (child["type"] == "map") {
×
721
                json_to_map_node(child, builder, sequence, assignments);
×
722
            } else if (child["type"] == "sequence") {
×
NEW
723
                auto& subseq = builder.add_sequence(sequence, assignments, json_to_debug_info(child["debug_info"]));
×
724
                json_to_sequence(child, builder, subseq);
×
725
            } else {
×
726
                throw std::runtime_error("Unknown child type");
×
727
            }
728

729
            sequence.at(i).second.debug_info_ = json_to_debug_info(transition["debug_info"]);
11✔
730
            sequence.at(i).second.element_id_ = transition["element_id"];
11✔
731
        }
11✔
732
    } else {
14✔
733
        throw std::runtime_error("expected sequence type");
×
734
    }
735
}
14✔
736

737
void JSONSerializer::json_to_block_node(
10✔
738
    const nlohmann::json& j,
739
    builder::StructuredSDFGBuilder& builder,
740
    structured_control_flow::Sequence& parent,
741
    control_flow::Assignments& assignments
742
) {
743
    assert(j.contains("type"));
10✔
744
    assert(j["type"].is_string());
10✔
745
    assert(j.contains("dataflow"));
10✔
746
    assert(j["dataflow"].is_object());
10✔
747
    auto& block = builder.add_block(parent, assignments, json_to_debug_info(j["debug_info"]));
10✔
748
    block.element_id_ = j["element_id"];
10✔
749
    assert(j["dataflow"].contains("type"));
10✔
750
    assert(j["dataflow"]["type"].is_string());
10✔
751
    std::string type = j["dataflow"]["type"];
10✔
752
    if (type == "dataflow") {
10✔
753
        json_to_dataflow(j["dataflow"], builder, block);
10✔
754
    } else {
10✔
755
        throw std::runtime_error("Unknown dataflow type");
×
756
    }
757
}
10✔
758

759
void JSONSerializer::json_to_for_node(
1✔
760
    const nlohmann::json& j,
761
    builder::StructuredSDFGBuilder& builder,
762
    structured_control_flow::Sequence& parent,
763
    control_flow::Assignments& assignments
764
) {
765
    assert(j.contains("type"));
1✔
766
    assert(j["type"].is_string());
1✔
767
    assert(j.contains("indvar"));
1✔
768
    assert(j["indvar"].is_string());
1✔
769
    assert(j.contains("init"));
1✔
770
    assert(j["init"].is_string());
1✔
771
    assert(j.contains("condition"));
1✔
772
    assert(j["condition"].is_string());
1✔
773
    assert(j.contains("update"));
1✔
774
    assert(j["update"].is_string());
1✔
775
    assert(j.contains("root"));
1✔
776
    assert(j["root"].is_object());
1✔
777

778
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
1✔
779
    SymEngine::Expression init(j["init"]);
1✔
780
    SymEngine::Expression condition_expr(j["condition"]);
1✔
781
    assert(!SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic()).is_null());
1✔
782
    symbolic::Condition condition = SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic());
1✔
783
    SymEngine::Expression update(j["update"]);
1✔
784
    auto& for_node =
1✔
785
        builder.add_for(parent, indvar, condition, init, update, assignments, json_to_debug_info(j["debug_info"]));
1✔
786
    for_node.element_id_ = j["element_id"];
1✔
787

788
    assert(j["root"].contains("type"));
1✔
789
    assert(j["root"]["type"].is_string());
1✔
790
    assert(j["root"]["type"] == "sequence");
1✔
791
    json_to_sequence(j["root"], builder, for_node.root());
1✔
792
}
1✔
793

794
void JSONSerializer::json_to_if_else_node(
1✔
795
    const nlohmann::json& j,
796
    builder::StructuredSDFGBuilder& builder,
797
    structured_control_flow::Sequence& parent,
798
    control_flow::Assignments& assignments
799
) {
800
    assert(j.contains("type"));
1✔
801
    assert(j["type"].is_string());
1✔
802
    assert(j["type"] == "if_else");
1✔
803
    assert(j.contains("branches"));
1✔
804
    assert(j["branches"].is_array());
1✔
805
    auto& if_else_node = builder.add_if_else(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
806
    if_else_node.element_id_ = j["element_id"];
1✔
807
    for (const auto& branch : j["branches"]) {
3✔
808
        assert(branch.contains("condition"));
2✔
809
        assert(branch["condition"].is_string());
2✔
810
        assert(branch.contains("root"));
2✔
811
        assert(branch["root"].is_object());
2✔
812
        SymEngine::Expression condition_expr(branch["condition"]);
2✔
813
        assert(!SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic()).is_null());
2✔
814
        symbolic::Condition condition = SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic()
2✔
815
        );
816
        auto& branch_node = builder.add_case(if_else_node, condition);
2✔
817
        assert(branch["root"].contains("type"));
2✔
818
        assert(branch["root"]["type"].is_string());
2✔
819
        std::string type = branch["root"]["type"];
2✔
820
        if (type == "sequence") {
2✔
821
            json_to_sequence(branch["root"], builder, branch_node);
2✔
822
        } else {
2✔
823
            throw std::runtime_error("Unknown child type");
×
824
        }
825
    }
2✔
826
}
1✔
827

828
void JSONSerializer::json_to_while_node(
3✔
829
    const nlohmann::json& j,
830
    builder::StructuredSDFGBuilder& builder,
831
    structured_control_flow::Sequence& parent,
832
    control_flow::Assignments& assignments
833
) {
834
    assert(j.contains("type"));
3✔
835
    assert(j["type"].is_string());
3✔
836
    assert(j["type"] == "while");
3✔
837
    assert(j.contains("root"));
3✔
838
    assert(j["root"].is_object());
3✔
839

840
    auto& while_node = builder.add_while(parent, assignments, json_to_debug_info(j["debug_info"]));
3✔
841
    while_node.element_id_ = j["element_id"];
3✔
842

843
    assert(j["root"]["type"] == "sequence");
3✔
844
    json_to_sequence(j["root"], builder, while_node.root());
3✔
845
}
3✔
846

847
void JSONSerializer::json_to_break_node(
1✔
848
    const nlohmann::json& j,
849
    builder::StructuredSDFGBuilder& builder,
850
    structured_control_flow::Sequence& parent,
851
    control_flow::Assignments& assignments
852
) {
853
    assert(j.contains("type"));
1✔
854
    assert(j["type"].is_string());
1✔
855
    assert(j["type"] == "break");
1✔
856
    auto& node = builder.add_break(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
857
    node.element_id_ = j["element_id"];
1✔
858
}
1✔
859

860
void JSONSerializer::json_to_continue_node(
1✔
861
    const nlohmann::json& j,
862
    builder::StructuredSDFGBuilder& builder,
863
    structured_control_flow::Sequence& parent,
864
    control_flow::Assignments& assignments
865
) {
866
    assert(j.contains("type"));
1✔
867
    assert(j["type"].is_string());
1✔
868
    assert(j["type"] == "continue");
1✔
869
    auto& node = builder.add_continue(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
870
    node.element_id_ = j["element_id"];
1✔
871
}
1✔
872

873
void JSONSerializer::json_to_map_node(
1✔
874
    const nlohmann::json& j,
875
    builder::StructuredSDFGBuilder& builder,
876
    structured_control_flow::Sequence& parent,
877
    control_flow::Assignments& assignments
878
) {
879
    assert(j.contains("type"));
1✔
880
    assert(j["type"].is_string());
1✔
881
    assert(j["type"] == "map");
1✔
882
    assert(j.contains("indvar"));
1✔
883
    assert(j["indvar"].is_string());
1✔
884
    assert(j.contains("init"));
1✔
885
    assert(j["init"].is_string());
1✔
886
    assert(j.contains("condition"));
1✔
887
    assert(j["condition"].is_string());
1✔
888
    assert(j.contains("update"));
1✔
889
    assert(j["update"].is_string());
1✔
890
    assert(j.contains("root"));
1✔
891
    assert(j["root"].is_object());
1✔
892
    assert(j.contains("schedule_type"));
1✔
893
    assert(j["schedule_type"].is_object());
1✔
894

895
    structured_control_flow::ScheduleType schedule_type = json_to_schedule_type(j["schedule_type"]);
1✔
896

897
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
1✔
898
    SymEngine::Expression init(j["init"]);
1✔
899
    SymEngine::Expression condition_expr(j["condition"]);
1✔
900
    assert(!SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic()).is_null());
1✔
901
    symbolic::Condition condition = SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic());
1✔
902
    SymEngine::Expression update(j["update"]);
1✔
903

904
    auto& map_node = builder.add_map(
2✔
905
        parent, indvar, condition, init, update, schedule_type, assignments, json_to_debug_info(j["debug_info"])
1✔
906
    );
907
    map_node.element_id_ = j["element_id"];
1✔
908

909
    assert(j["root"].contains("type"));
1✔
910
    assert(j["root"]["type"].is_string());
1✔
911
    assert(j["root"]["type"] == "sequence");
1✔
912
    json_to_sequence(j["root"], builder, map_node.root());
1✔
913
}
1✔
914

915
void JSONSerializer::json_to_return_node(
1✔
916
    const nlohmann::json& j,
917
    builder::StructuredSDFGBuilder& builder,
918
    structured_control_flow::Sequence& parent,
919
    control_flow::Assignments& assignments
920
) {
921
    assert(j.contains("type"));
1✔
922
    assert(j["type"].is_string());
1✔
923
    assert(j["type"] == "return");
1✔
924

925
    auto& node = builder.add_return(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
926
    node.element_id_ = j["element_id"];
1✔
927
}
1✔
928

929
std::unique_ptr<types::IType> JSONSerializer::json_to_type(const nlohmann::json& j) {
41✔
930
    if (j.contains("type")) {
41✔
931
        if (j["type"] == "scalar") {
41✔
932
            // Deserialize scalar type
933
            assert(j.contains("primitive_type"));
30✔
934
            types::PrimitiveType primitive_type = j["primitive_type"];
30✔
935
            assert(j.contains("storage_type"));
30✔
936
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
30✔
937
            assert(j.contains("initializer"));
30✔
938
            std::string initializer = j["initializer"];
30✔
939
            assert(j.contains("alignment"));
30✔
940
            size_t alignment = j["alignment"];
30✔
941
            return std::make_unique<types::Scalar>(storage_type, alignment, initializer, primitive_type);
30✔
942
        } else if (j["type"] == "array") {
41✔
943
            // Deserialize array type
944
            assert(j.contains("element_type"));
2✔
945
            std::unique_ptr<types::IType> member_type = json_to_type(j["element_type"]);
2✔
946
            assert(j.contains("num_elements"));
2✔
947
            std::string num_elements_str = j["num_elements"];
2✔
948
            // Convert num_elements_str to symbolic::Expression
949
            SymEngine::Expression num_elements(num_elements_str);
2✔
950
            assert(j.contains("storage_type"));
2✔
951
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
2✔
952
            assert(j.contains("initializer"));
2✔
953
            std::string initializer = j["initializer"];
2✔
954
            assert(j.contains("alignment"));
2✔
955
            size_t alignment = j["alignment"];
2✔
956
            return std::make_unique<types::Array>(storage_type, alignment, initializer, *member_type, num_elements);
2✔
957
        } else if (j["type"] == "pointer") {
11✔
958
            // Deserialize pointer type
959
            std::optional<std::unique_ptr<types::IType>> pointee_type;
6✔
960
            if (j.contains("pointee_type")) {
6✔
961
                assert(j.contains("pointee_type"));
5✔
962
                pointee_type = json_to_type(j["pointee_type"]);
5✔
963
            } else {
5✔
964
                pointee_type = std::nullopt;
1✔
965
            }
966
            assert(j.contains("storage_type"));
6✔
967
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
6✔
968
            assert(j.contains("initializer"));
6✔
969
            std::string initializer = j["initializer"];
6✔
970
            assert(j.contains("alignment"));
6✔
971
            size_t alignment = j["alignment"];
6✔
972
            if (pointee_type.has_value()) {
6✔
973
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer, *pointee_type.value());
5✔
974
            } else {
975
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer);
1✔
976
            }
977
        } else if (j["type"] == "structure") {
9✔
978
            // Deserialize structure type
979
            assert(j.contains("name"));
2✔
980
            std::string name = j["name"];
2✔
981
            assert(j.contains("storage_type"));
2✔
982
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
2✔
983
            assert(j.contains("initializer"));
2✔
984
            std::string initializer = j["initializer"];
2✔
985
            assert(j.contains("alignment"));
2✔
986
            size_t alignment = j["alignment"];
2✔
987
            return std::make_unique<types::Structure>(storage_type, alignment, initializer, name);
2✔
988
        } else if (j["type"] == "function") {
3✔
989
            // Deserialize function type
990
            assert(j.contains("return_type"));
1✔
991
            std::unique_ptr<types::IType> return_type = json_to_type(j["return_type"]);
1✔
992
            assert(j.contains("params"));
1✔
993
            std::vector<std::unique_ptr<types::IType>> params;
1✔
994
            for (const auto& param : j["params"]) {
3✔
995
                params.push_back(json_to_type(param));
2✔
996
            }
997
            assert(j.contains("is_var_arg"));
1✔
998
            bool is_var_arg = j["is_var_arg"];
1✔
999
            assert(j.contains("storage_type"));
1✔
1000
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
1✔
1001
            assert(j.contains("initializer"));
1✔
1002
            std::string initializer = j["initializer"];
1✔
1003
            assert(j.contains("alignment"));
1✔
1004
            size_t alignment = j["alignment"];
1✔
1005
            auto function =
1006
                std::make_unique<types::Function>(storage_type, alignment, initializer, *return_type, is_var_arg);
1✔
1007
            for (const auto& param : params) {
3✔
1008
                function->add_param(*param);
2✔
1009
            }
1010
            return function->clone();
1✔
1011

1012
        } else {
1✔
1013
            throw std::runtime_error("Unknown type");
×
1014
        }
1015
    } else {
1016
        throw std::runtime_error("Type not found");
×
1017
    }
1018
}
41✔
1019

1020
DebugInfo JSONSerializer::json_to_debug_info(const nlohmann::json& j) {
72✔
1021
    assert(j.contains("has"));
72✔
1022
    assert(j["has"].is_boolean());
72✔
1023
    if (!j["has"]) {
72✔
1024
        return DebugInfo();
72✔
1025
    }
UNCOV
1026
    assert(j.contains("filename"));
×
UNCOV
1027
    assert(j["filename"].is_string());
×
UNCOV
1028
    std::string filename = j["filename"];
×
UNCOV
1029
    assert(j.contains("function"));
×
UNCOV
1030
    assert(j["function"].is_string());
×
UNCOV
1031
    std::string function = j["function"];
×
UNCOV
1032
    assert(j.contains("start_line"));
×
UNCOV
1033
    assert(j["start_line"].is_number_integer());
×
UNCOV
1034
    size_t start_line = j["start_line"];
×
UNCOV
1035
    assert(j.contains("start_column"));
×
UNCOV
1036
    assert(j["start_column"].is_number_integer());
×
UNCOV
1037
    size_t start_column = j["start_column"];
×
UNCOV
1038
    assert(j.contains("end_line"));
×
UNCOV
1039
    assert(j["end_line"].is_number_integer());
×
UNCOV
1040
    size_t end_line = j["end_line"];
×
UNCOV
1041
    assert(j.contains("end_column"));
×
UNCOV
1042
    assert(j["end_column"].is_number_integer());
×
UNCOV
1043
    size_t end_column = j["end_column"];
×
NEW
1044
    return DebugInfo(filename, function, start_line, start_column, end_line, end_column);
×
1045
}
72✔
1046

1047
ScheduleType JSONSerializer::json_to_schedule_type(const nlohmann::json& j) {
2✔
1048
    assert(j.contains("value"));
2✔
1049
    assert(j["value"].is_string());
2✔
1050
    assert(j.contains("properties"));
2✔
1051
    assert(j["properties"].is_object());
2✔
1052
    ScheduleType schedule_type(j["value"].get<std::string>());
2✔
1053
    for (const auto& [key, value] : j["properties"].items()) {
4✔
1054
        assert(value.is_string());
1✔
1055
        schedule_type.set_property(key, value.get<std::string>());
1✔
1056
    }
1057
    return schedule_type;
2✔
1058
}
2✔
1059

1060
std::string JSONSerializer::expression(const symbolic::Expression& expr) {
48✔
1061
    JSONSymbolicPrinter printer;
48✔
1062
    return printer.apply(expr);
48✔
1063
};
48✔
1064

1065
void JSONSymbolicPrinter::bvisit(const SymEngine::Equality& x) {
×
1066
    str_ = apply(x.get_args()[0]) + " == " + apply(x.get_args()[1]);
×
1067
    str_ = parenthesize(str_);
×
1068
};
×
1069

1070
void JSONSymbolicPrinter::bvisit(const SymEngine::Unequality& x) {
×
1071
    str_ = apply(x.get_args()[0]) + " != " + apply(x.get_args()[1]);
×
1072
    str_ = parenthesize(str_);
×
1073
};
×
1074

1075
void JSONSymbolicPrinter::bvisit(const SymEngine::LessThan& x) {
×
1076
    str_ = apply(x.get_args()[0]) + " <= " + apply(x.get_args()[1]);
×
1077
    str_ = parenthesize(str_);
×
1078
};
×
1079

1080
void JSONSymbolicPrinter::bvisit(const SymEngine::StrictLessThan& x) {
4✔
1081
    str_ = apply(x.get_args()[0]) + " < " + apply(x.get_args()[1]);
4✔
1082
    str_ = parenthesize(str_);
4✔
1083
};
4✔
1084

1085
void JSONSymbolicPrinter::bvisit(const SymEngine::Min& x) {
×
1086
    std::ostringstream s;
×
1087
    auto container = x.get_args();
×
1088
    if (container.size() == 1) {
×
1089
        s << apply(*container.begin());
×
1090
    } else {
×
1091
        s << "min(";
×
1092
        s << apply(*container.begin());
×
1093

1094
        // Recursively apply __daisy_min to the arguments
1095
        SymEngine::vec_basic subargs;
×
1096
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1097
            subargs.push_back(*it);
×
1098
        }
×
1099
        auto submin = SymEngine::min(subargs);
×
1100
        s << ", " << apply(submin);
×
1101

1102
        s << ")";
×
1103
    }
×
1104

1105
    str_ = s.str();
×
1106
};
×
1107

1108
void JSONSymbolicPrinter::bvisit(const SymEngine::Max& x) {
×
1109
    std::ostringstream s;
×
1110
    auto container = x.get_args();
×
1111
    if (container.size() == 1) {
×
1112
        s << apply(*container.begin());
×
1113
    } else {
×
1114
        s << "max(";
×
1115
        s << apply(*container.begin());
×
1116

1117
        // Recursively apply __daisy_max to the arguments
1118
        SymEngine::vec_basic subargs;
×
1119
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1120
            subargs.push_back(*it);
×
1121
        }
×
1122
        auto submax = SymEngine::max(subargs);
×
1123
        s << ", " << apply(submax);
×
1124

1125
        s << ")";
×
1126
    }
×
1127

1128
    str_ = s.str();
×
1129
};
×
1130

1131
void LibraryNodeSerializerRegistry::
1132
    register_library_node_serializer(std::string library_node_code, LibraryNodeSerializerFn fn) {
58✔
1133
    std::lock_guard<std::mutex> lock(mutex_);
58✔
1134
    if (factory_map_.find(library_node_code) != factory_map_.end()) {
58✔
1135
        throw std::runtime_error(
×
1136
            "Library node serializer already registered for library node code: " + std::string(library_node_code)
×
1137
        );
1138
    }
1139
    factory_map_[library_node_code] = std::move(fn);
58✔
1140
}
58✔
1141

1142
LibraryNodeSerializerFn LibraryNodeSerializerRegistry::get_library_node_serializer(std::string library_node_code) {
1✔
1143
    auto it = factory_map_.find(library_node_code);
1✔
1144
    if (it != factory_map_.end()) {
1✔
1145
        return it->second;
1✔
1146
    }
1147
    return nullptr;
×
1148
}
1✔
1149

1150
size_t LibraryNodeSerializerRegistry::size() const { return factory_map_.size(); }
×
1151

1152
void register_default_serializers() {
2✔
1153
    // Metadata
1154
    LibraryNodeSerializerRegistry::instance()
2✔
1155
        .register_library_node_serializer(data_flow::LibraryNodeType_Metadata.value(), []() {
2✔
1156
            return std::make_unique<data_flow::MetadataNodeSerializer>();
×
1157
        });
1158

1159
    // Barrier
1160
    LibraryNodeSerializerRegistry::instance()
2✔
1161
        .register_library_node_serializer(data_flow::LibraryNodeType_BarrierLocal.value(), []() {
3✔
1162
            return std::make_unique<data_flow::BarrierLocalNodeSerializer>();
1✔
1163
        });
1164

1165
    // ML
1166
    LibraryNodeSerializerRegistry::instance()
2✔
1167
        .register_library_node_serializer(math::ml::LibraryNodeType_Abs.value(), []() {
2✔
1168
            return std::make_unique<math::ml::AbsNodeSerializer>();
×
1169
        });
1170
    LibraryNodeSerializerRegistry::instance()
2✔
1171
        .register_library_node_serializer(math::ml::LibraryNodeType_Add.value(), []() {
2✔
1172
            return std::make_unique<math::ml::AddNodeSerializer>();
×
1173
        });
1174
    LibraryNodeSerializerRegistry::instance()
2✔
1175
        .register_library_node_serializer(math::ml::LibraryNodeType_BatchNormalization.value(), []() {
2✔
1176
            return std::make_unique<math::ml::BatchNormalizationNodeSerializer>();
×
1177
        });
1178
    LibraryNodeSerializerRegistry::instance()
2✔
1179
        .register_library_node_serializer(math::ml::LibraryNodeType_Clip.value(), []() {
2✔
1180
            return std::make_unique<math::ml::ClipNodeSerializer>();
×
1181
        });
1182
    LibraryNodeSerializerRegistry::instance()
2✔
1183
        .register_library_node_serializer(math::ml::LibraryNodeType_Conv.value(), []() {
2✔
1184
            return std::make_unique<math::ml::ConvNodeSerializer>();
×
1185
        });
1186
    LibraryNodeSerializerRegistry::instance()
2✔
1187
        .register_library_node_serializer(math::ml::LibraryNodeType_Div.value(), []() {
2✔
1188
            return std::make_unique<math::ml::DivNodeSerializer>();
×
1189
        });
1190
    LibraryNodeSerializerRegistry::instance()
2✔
1191
        .register_library_node_serializer(math::ml::LibraryNodeType_Dropout.value(), []() {
2✔
1192
            return std::make_unique<math::ml::DropoutSerializer>();
×
1193
        });
1194
    LibraryNodeSerializerRegistry::instance()
2✔
1195
        .register_library_node_serializer(math::ml::LibraryNodeType_Elu.value(), []() {
2✔
1196
            return std::make_unique<math::ml::EluNodeSerializer>();
×
1197
        });
1198
    LibraryNodeSerializerRegistry::instance()
2✔
1199
        .register_library_node_serializer(math::ml::LibraryNodeType_Erf.value(), []() {
2✔
1200
            return std::make_unique<math::ml::ErfNodeSerializer>();
×
1201
        });
1202
    LibraryNodeSerializerRegistry::instance()
2✔
1203
        .register_library_node_serializer(math::ml::LibraryNodeType_Gemm.value(), []() {
2✔
1204
            return std::make_unique<math::ml::GemmNodeSerializer>();
×
1205
        });
1206
    LibraryNodeSerializerRegistry::instance()
2✔
1207
        .register_library_node_serializer(math::ml::LibraryNodeType_HardSigmoid.value(), []() {
2✔
1208
            return std::make_unique<math::ml::HardSigmoidNodeSerializer>();
×
1209
        });
1210
    LibraryNodeSerializerRegistry::instance()
2✔
1211
        .register_library_node_serializer(math::ml::LibraryNodeType_LayerNormalization.value(), []() {
2✔
1212
            return std::make_unique<math::ml::LayerNormalizationNodeSerializer>();
×
1213
        });
1214
    LibraryNodeSerializerRegistry::instance()
2✔
1215
        .register_library_node_serializer(math::ml::LibraryNodeType_LeakyReLU.value(), []() {
2✔
1216
            return std::make_unique<math::ml::LeakyReLUNodeSerializer>();
×
1217
        });
1218
    LibraryNodeSerializerRegistry::instance()
2✔
1219
        .register_library_node_serializer(math::ml::LibraryNodeType_LogSoftmax.value(), []() {
2✔
1220
            return std::make_unique<math::ml::LogSoftmaxNodeSerializer>();
×
1221
        });
1222
    LibraryNodeSerializerRegistry::instance()
2✔
1223
        .register_library_node_serializer(math::ml::LibraryNodeType_MatMul.value(), []() {
2✔
1224
            return std::make_unique<math::ml::MatMulNodeSerializer>();
×
1225
        });
1226
    LibraryNodeSerializerRegistry::instance()
2✔
1227
        .register_library_node_serializer(math::ml::LibraryNodeType_MaxPool.value(), []() {
2✔
1228
            return std::make_unique<math::ml::MaxPoolNodeSerializer>();
×
1229
        });
1230
    LibraryNodeSerializerRegistry::instance()
2✔
1231
        .register_library_node_serializer(math::ml::LibraryNodeType_Mul.value(), []() {
2✔
1232
            return std::make_unique<math::ml::MulNodeSerializer>();
×
1233
        });
1234
    LibraryNodeSerializerRegistry::instance()
2✔
1235
        .register_library_node_serializer(math::ml::LibraryNodeType_Pow.value(), []() {
2✔
1236
            return std::make_unique<math::ml::PowNodeSerializer>();
×
1237
        });
1238
    LibraryNodeSerializerRegistry::instance()
2✔
1239
        .register_library_node_serializer(math::ml::LibraryNodeType_ReduceMean.value(), []() {
2✔
1240
            return std::make_unique<math::ml::ReduceMeanNodeSerializer>();
×
1241
        });
1242
    LibraryNodeSerializerRegistry::instance()
2✔
1243
        .register_library_node_serializer(math::ml::LibraryNodeType_ReLU.value(), []() {
2✔
1244
            return std::make_unique<math::ml::ReLUNodeSerializer>();
×
1245
        });
1246
    LibraryNodeSerializerRegistry::instance()
2✔
1247
        .register_library_node_serializer(math::ml::LibraryNodeType_Sigmoid.value(), []() {
2✔
1248
            return std::make_unique<math::ml::SigmoidNodeSerializer>();
×
1249
        });
1250
    LibraryNodeSerializerRegistry::instance()
2✔
1251
        .register_library_node_serializer(math::ml::LibraryNodeType_Softmax.value(), []() {
2✔
1252
            return std::make_unique<math::ml::SoftmaxNodeSerializer>();
×
1253
        });
1254
    LibraryNodeSerializerRegistry::instance()
2✔
1255
        .register_library_node_serializer(math::ml::LibraryNodeType_Sqrt.value(), []() {
2✔
1256
            return std::make_unique<math::ml::SqrtNodeSerializer>();
×
1257
        });
1258
    LibraryNodeSerializerRegistry::instance()
2✔
1259
        .register_library_node_serializer(math::ml::LibraryNodeType_Sub.value(), []() {
2✔
1260
            return std::make_unique<math::ml::SubNodeSerializer>();
×
1261
        });
1262
    LibraryNodeSerializerRegistry::instance()
2✔
1263
        .register_library_node_serializer(math::ml::LibraryNodeType_Tanh.value(), []() {
2✔
1264
            return std::make_unique<math::ml::TanhNodeSerializer>();
×
1265
        });
1266

1267
    // BLAS
1268
    LibraryNodeSerializerRegistry::instance()
2✔
1269
        .register_library_node_serializer(math::blas::LibraryNodeType_DOT.value(), []() {
2✔
1270
            return std::make_unique<math::blas::DotNodeSerializer>();
×
1271
        });
1272
    LibraryNodeSerializerRegistry::instance()
2✔
1273
        .register_library_node_serializer(math::blas::LibraryNodeType_GEMM.value(), []() {
2✔
1274
            return std::make_unique<math::blas::GEMMNodeSerializer>();
×
1275
        });
1276
}
2✔
1277

1278
} // namespace serializer
1279
} // 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