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

daisytuner / sdfglib / 16344863968

17 Jul 2025 12:16PM UTC coverage: 64.865% (-0.3%) from 65.184%
16344863968

Pull #147

github

web-flow
Merge afde7955f into 56ea48e3e
Pull Request #147: Adds metadata library node

98 of 189 new or added lines in 9 files covered. (51.85%)

58 existing lines in 3 files now uncovered.

8712 of 13431 relevant lines covered (64.86%)

176.29 hits per line

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

82.4
/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/barrier_local_node.h"
10
#include "sdfg/data_flow/library_nodes/metadata_node.h"
11

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

30
namespace sdfg {
31
namespace serializer {
32

33
FunctionType function_type_from_string(const std::string& str) {
3✔
34
    if (str == FunctionType_CPU.value()) {
3✔
35
        return FunctionType_CPU;
3✔
UNCOV
36
    } else if (str == FunctionType_NV_GLOBAL.value()) {
×
UNCOV
37
        return FunctionType_NV_GLOBAL;
×
38
    }
39

UNCOV
40
    return FunctionType(str);
×
41
}
3✔
42

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

UNCOV
58
    return types::StorageType(str);
×
59
}
31✔
60

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

UNCOV
68
    return structured_control_flow::ScheduleType(str);
×
69
}
1✔
70

71
/*
72
 * * JSONSerializer class
73
 * * Serialization logic
74
 */
75

76
nlohmann::json JSONSerializer::serialize(std::unique_ptr<sdfg::StructuredSDFG>& sdfg) {
3✔
77
    nlohmann::json j;
3✔
78

79
    j["name"] = sdfg->name();
3✔
80
    j["type"] = std::string(sdfg->type().value());
3✔
81

82
    j["structures"] = nlohmann::json::array();
3✔
83
    for (const auto& structure_name : sdfg->structures()) {
3✔
UNCOV
84
        const auto& structure = sdfg->structure(structure_name);
×
UNCOV
85
        nlohmann::json structure_json;
×
86
        structure_definition_to_json(structure_json, structure);
×
87
        j["structures"].push_back(structure_json);
×
88
    }
×
89

90
    j["containers"] = nlohmann::json::object();
3✔
91
    for (const auto& container : sdfg->containers()) {
8✔
92
        nlohmann::json desc;
5✔
93
        type_to_json(desc, sdfg->type(container));
5✔
94
        j["containers"][container] = desc;
5✔
95
    }
5✔
96

97
    j["arguments"] = nlohmann::json::array();
3✔
98
    for (const auto& argument : sdfg->arguments()) {
5✔
99
        j["arguments"].push_back(argument);
2✔
100
    }
101

102
    j["externals"] = nlohmann::json::array();
3✔
103
    for (const auto& external : sdfg->externals()) {
3✔
UNCOV
104
        j["externals"].push_back(external);
×
105
    }
106

107
    j["metadata"] = nlohmann::json::object();
3✔
108
    for (const auto& entry : sdfg->metadata()) {
4✔
109
        j["metadata"][entry.first] = entry.second;
1✔
110
    }
111

112
    // Walk the SDFG
113
    nlohmann::json root_json;
3✔
114
    sequence_to_json(root_json, sdfg->root());
3✔
115
    j["root"] = root_json;
3✔
116

117
    return j;
3✔
118
}
3✔
119

120
void JSONSerializer::dataflow_to_json(nlohmann::json& j, const data_flow::DataFlowGraph& dataflow) {
20✔
121
    j["type"] = "dataflow";
20✔
122
    j["nodes"] = nlohmann::json::array();
20✔
123
    j["edges"] = nlohmann::json::array();
20✔
124

125
    for (auto& node : dataflow.nodes()) {
40✔
126
        nlohmann::json node_json;
20✔
127
        node_json["element_id"] = node.element_id();
20✔
128

129
        node_json["debug_info"] = nlohmann::json::object();
20✔
130
        debug_info_to_json(node_json["debug_info"], node.debug_info());
20✔
131

132
        if (auto tasklet = dynamic_cast<const data_flow::Tasklet*>(&node)) {
20✔
133
            node_json["type"] = "tasklet";
5✔
134
            node_json["code"] = tasklet->code();
5✔
135
            node_json["inputs"] = nlohmann::json::array();
5✔
136
            for (auto& input : tasklet->inputs()) {
15✔
137
                nlohmann::json input_json;
10✔
138
                nlohmann::json type_json;
10✔
139
                type_to_json(type_json, input.second);
10✔
140
                input_json["type"] = type_json;
10✔
141
                input_json["name"] = input.first;
10✔
142
                node_json["inputs"].push_back(input_json);
10✔
143
            }
10✔
144
            node_json["output"] = nlohmann::json::object();
5✔
145
            node_json["output"]["name"] = tasklet->output().first;
5✔
146
            nlohmann::json type_json;
5✔
147
            type_to_json(type_json, tasklet->output().second);
5✔
148
            node_json["output"]["type"] = type_json;
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✔
UNCOV
154
            node_json["type"] = "library_node";
×
155
            auto serializer_fn =
156
                LibraryNodeSerializerRegistry::instance().get_library_node_serializer(lib_node->code().value());
×
UNCOV
157
            if (serializer_fn == nullptr) {
×
158
                throw std::runtime_error("Unknown library node code: " + std::string(lib_node->code().value()));
×
159
            }
160
            auto serializer = serializer_fn();
×
UNCOV
161
            auto lib_node_json = serializer->serialize(*lib_node);
×
162
            node_json.merge_patch(lib_node_json);
×
163
        } else if (auto code_node = dynamic_cast<const data_flow::AccessNode*>(&node)) {
15✔
164
            node_json["type"] = "access_node";
15✔
165
            node_json["data"] = code_node->data();
15✔
166
        } else {
15✔
UNCOV
167
            throw std::runtime_error("Unknown node type");
×
168
        }
169

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

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

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

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

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

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

191
        j["edges"].push_back(edge_json);
15✔
192
    }
15✔
193
}
20✔
194

195
void JSONSerializer::block_to_json(nlohmann::json& j, const structured_control_flow::Block& block) {
18✔
196
    j["type"] = "block";
18✔
197
    j["element_id"] = block.element_id();
18✔
198

199
    j["debug_info"] = nlohmann::json::object();
18✔
200
    debug_info_to_json(j["debug_info"], block.debug_info());
18✔
201

202
    nlohmann::json dataflow_json;
18✔
203
    dataflow_to_json(dataflow_json, block.dataflow());
18✔
204
    j["dataflow"] = dataflow_json;
18✔
205
}
18✔
206

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

211
    j["debug_info"] = nlohmann::json::object();
2✔
212
    debug_info_to_json(j["debug_info"], for_node.debug_info());
2✔
213

214
    j["indvar"] = expression(for_node.indvar());
2✔
215
    j["init"] = expression(for_node.init());
2✔
216
    j["condition"] = expression(for_node.condition());
2✔
217
    j["update"] = expression(for_node.update());
2✔
218

219
    nlohmann::json body_json;
2✔
220
    sequence_to_json(body_json, for_node.root());
2✔
221
    j["root"] = body_json;
2✔
222
}
2✔
223

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

228
    j["debug_info"] = nlohmann::json::object();
2✔
229
    debug_info_to_json(j["debug_info"], if_else_node.debug_info());
2✔
230

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

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

246
    j["debug_info"] = nlohmann::json::object();
5✔
247
    debug_info_to_json(j["debug_info"], while_node.debug_info());
5✔
248

249
    nlohmann::json body_json;
5✔
250
    sequence_to_json(body_json, while_node.root());
5✔
251
    j["root"] = body_json;
5✔
252
}
5✔
253

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

258
    j["debug_info"] = nlohmann::json::object();
2✔
259
    debug_info_to_json(j["debug_info"], break_node.debug_info());
2✔
260
}
2✔
261

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

266
    j["debug_info"] = nlohmann::json::object();
2✔
267
    debug_info_to_json(j["debug_info"], continue_node.debug_info());
2✔
268
}
2✔
269

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

274
    j["debug_info"] = nlohmann::json::object();
2✔
275
    debug_info_to_json(j["debug_info"], map_node.debug_info());
2✔
276

277
    j["indvar"] = expression(map_node.indvar());
2✔
278
    j["init"] = expression(map_node.init());
2✔
279
    j["condition"] = expression(map_node.condition());
2✔
280
    j["update"] = expression(map_node.update());
2✔
281

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

284
    nlohmann::json body_json;
2✔
285
    sequence_to_json(body_json, map_node.root());
2✔
286
    j["root"] = body_json;
2✔
287
}
2✔
288

289
void JSONSerializer::return_node_to_json(nlohmann::json& j, const structured_control_flow::Return& return_node) {
2✔
290
    j["type"] = "return";
2✔
291
    j["element_id"] = return_node.element_id();
2✔
292

293
    j["debug_info"] = nlohmann::json::object();
2✔
294
    debug_info_to_json(j["debug_info"], return_node.debug_info());
2✔
295
}
2✔
296

297
void JSONSerializer::sequence_to_json(nlohmann::json& j, const structured_control_flow::Sequence& sequence) {
19✔
298
    j["type"] = "sequence";
19✔
299
    j["element_id"] = sequence.element_id();
19✔
300

301
    j["debug_info"] = nlohmann::json::object();
19✔
302
    debug_info_to_json(j["debug_info"], sequence.debug_info());
19✔
303

304
    j["children"] = nlohmann::json::array();
19✔
305
    j["transitions"] = nlohmann::json::array();
19✔
306

307
    for (size_t i = 0; i < sequence.size(); i++) {
39✔
308
        nlohmann::json child_json;
20✔
309
        auto& child = sequence.at(i).first;
20✔
310
        auto& transition = sequence.at(i).second;
20✔
311

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

334
        j["children"].push_back(child_json);
20✔
335

336
        // Add transition information
337
        nlohmann::json transition_json;
20✔
338
        transition_json["type"] = "transition";
20✔
339
        transition_json["element_id"] = transition.element_id();
20✔
340

341
        transition_json["debug_info"] = nlohmann::json::object();
20✔
342
        debug_info_to_json(transition_json["debug_info"], transition.debug_info());
20✔
343

344
        transition_json["assignments"] = nlohmann::json::array();
20✔
345
        for (const auto& assignment : transition.assignments()) {
22✔
346
            nlohmann::json assignment_json;
2✔
347
            assignment_json["symbol"] = expression(assignment.first);
2✔
348
            assignment_json["expression"] = expression(assignment.second);
2✔
349
            transition_json["assignments"].push_back(assignment_json);
2✔
350
        }
2✔
351

352
        j["transitions"].push_back(transition_json);
20✔
353
    }
20✔
354
}
19✔
355

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

406
void JSONSerializer::structure_definition_to_json(nlohmann::json& j, const types::StructureDefinition& definition) {
1✔
407
    j["name"] = definition.name();
1✔
408
    j["members"] = nlohmann::json::array();
1✔
409
    for (size_t i = 0; i < definition.num_members(); i++) {
3✔
410
        nlohmann::json member_json;
2✔
411
        type_to_json(member_json, definition.member_type(symbolic::integer(i)));
2✔
412
        j["members"].push_back(member_json);
2✔
413
    }
2✔
414
    j["is_packed"] = definition.is_packed();
1✔
415
}
1✔
416

417
void JSONSerializer::debug_info_to_json(nlohmann::json& j, const DebugInfo& debug_info) {
109✔
418
    j["has"] = debug_info.has();
109✔
419
    j["filename"] = debug_info.filename();
109✔
420
    j["start_line"] = debug_info.start_line();
109✔
421
    j["start_column"] = debug_info.start_column();
109✔
422
    j["end_line"] = debug_info.end_line();
109✔
423
    j["end_column"] = debug_info.end_column();
109✔
424
}
109✔
425

426
/*
427
 * * Deserialization logic
428
 */
429

430
std::unique_ptr<StructuredSDFG> JSONSerializer::deserialize(nlohmann::json& j) {
3✔
431
    assert(j.contains("name"));
3✔
432
    assert(j["name"].is_string());
3✔
433
    assert(j.contains("type"));
3✔
434
    assert(j["type"].is_string());
3✔
435

436
    FunctionType function_type = function_type_from_string(j["type"].get<std::string>());
3✔
437
    builder::StructuredSDFGBuilder builder(j["name"], function_type);
3✔
438

439
    // deserialize structures
440
    assert(j.contains("structures"));
3✔
441
    assert(j["structures"].is_array());
3✔
442
    for (const auto& structure : j["structures"]) {
3✔
UNCOV
443
        assert(structure.contains("name"));
×
UNCOV
444
        assert(structure["name"].is_string());
×
445
        json_to_structure_definition(structure, builder);
×
446
    }
447

448
    nlohmann::json& containers = j["containers"];
3✔
449

450
    // deserialize externals
451
    for (const auto& name : j["externals"]) {
3✔
UNCOV
452
        auto& type_desc = containers.at(name.get<std::string>());
×
UNCOV
453
        auto type = json_to_type(type_desc);
×
454
        builder.add_container(name, *type, false, true);
×
455
    }
×
456

457
    // deserialize arguments
458
    for (const auto& name : j["arguments"]) {
5✔
459
        auto& type_desc = containers.at(name.get<std::string>());
2✔
460
        auto type = json_to_type(type_desc);
2✔
461
        builder.add_container(name, *type, true, false);
2✔
462
    }
2✔
463

464
    // deserialize transients
465
    for (const auto& entry : containers.items()) {
8✔
466
        if (builder.subject().is_argument(entry.key())) {
5✔
467
            continue;
2✔
468
        }
469
        if (builder.subject().is_external(entry.key())) {
3✔
UNCOV
470
            continue;
×
471
        }
472
        auto type = json_to_type(entry.value());
3✔
473
        builder.add_container(entry.key(), *type, false, false);
3✔
474
    }
3✔
475

476
    // deserialize root node
477
    assert(j.contains("root"));
3✔
478
    auto& root = builder.subject().root();
3✔
479
    json_to_sequence(j["root"], builder, root);
3✔
480

481
    // deserialize metadata
482
    assert(j.contains("metadata"));
3✔
483
    assert(j["metadata"].is_object());
3✔
484
    for (const auto& entry : j["metadata"].items()) {
4✔
485
        builder.subject().add_metadata(entry.key(), entry.value());
1✔
486
    }
487

488
    return builder.move();
3✔
489
}
3✔
490

491
void JSONSerializer::json_to_structure_definition(const nlohmann::json& j, builder::StructuredSDFGBuilder& builder) {
1✔
492
    assert(j.contains("name"));
1✔
493
    assert(j["name"].is_string());
1✔
494
    assert(j.contains("members"));
1✔
495
    assert(j["members"].is_array());
1✔
496
    assert(j.contains("is_packed"));
1✔
497
    assert(j["is_packed"].is_boolean());
1✔
498
    auto is_packed = j["is_packed"];
1✔
499
    auto& definition = builder.add_structure(j["name"], is_packed);
1✔
500
    for (const auto& member : j["members"]) {
3✔
501
        nlohmann::json member_json;
2✔
502
        auto member_type = json_to_type(member);
2✔
503
        definition.add_member(*member_type);
2✔
504
    }
2✔
505
}
1✔
506

507
std::vector<std::pair<std::string, types::Scalar>> JSONSerializer::json_to_arguments(const nlohmann::json& j) {
4✔
508
    std::vector<std::pair<std::string, types::Scalar>> arguments;
4✔
509
    for (const auto& argument : j) {
12✔
510
        assert(argument.contains("name"));
8✔
511
        assert(argument["name"].is_string());
8✔
512
        assert(argument.contains("type"));
8✔
513
        assert(argument["type"].is_object());
8✔
514
        std::string name = argument["name"];
8✔
515
        auto type = json_to_type(argument["type"]);
8✔
516
        arguments.emplace_back(name, *dynamic_cast<types::Scalar*>(type.get()));
8✔
517
    }
8✔
518
    return arguments;
4✔
519
}
4✔
520

521
void JSONSerializer::json_to_dataflow(
10✔
522
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Block& parent
523
) {
524
    std::unordered_map<size_t, data_flow::DataFlowNode&> nodes_map;
10✔
525

526
    assert(j.contains("nodes"));
10✔
527
    assert(j["nodes"].is_array());
10✔
528
    for (const auto& node : j["nodes"]) {
26✔
529
        assert(node.contains("type"));
16✔
530
        assert(node["type"].is_string());
16✔
531
        assert(node.contains("element_id"));
16✔
532
        assert(node["element_id"].is_number_integer());
16✔
533
        std::string type = node["type"];
16✔
534
        if (type == "tasklet") {
16✔
535
            assert(node.contains("code"));
4✔
536
            assert(node["code"].is_number_integer());
4✔
537
            assert(node.contains("inputs"));
4✔
538
            assert(node["inputs"].is_array());
4✔
539
            assert(node.contains("output"));
4✔
540
            assert(node["output"].is_object());
4✔
541
            assert(node["output"].contains("name"));
4✔
542
            assert(node["output"].contains("type"));
4✔
543
            auto inputs = json_to_arguments(node["inputs"]);
4✔
544

545
            auto output_name = node["output"]["name"];
4✔
546
            auto output_type = json_to_type(node["output"]["type"]);
4✔
547
            auto& output_type_scalar = dynamic_cast<types::Scalar&>(*output_type);
4✔
548

549
            auto& tasklet = builder.add_tasklet(
8✔
550
                parent, node["code"], {output_name, output_type_scalar}, inputs, json_to_debug_info(node["debug_info"])
4✔
551
            );
552
            tasklet.element_id_ = node["element_id"];
4✔
553
            nodes_map.insert({node["element_id"], tasklet});
4✔
554
        } else if (type == "library_node") {
16✔
UNCOV
555
            assert(node.contains("code"));
×
UNCOV
556
            data_flow::LibraryNodeCode code(node["code"].get<std::string>());
×
557

558
            auto serializer_fn = LibraryNodeSerializerRegistry::instance().get_library_node_serializer(code.value());
×
UNCOV
559
            if (serializer_fn == nullptr) {
×
560
                throw std::runtime_error("Unknown library node code: " + std::string(code.value()));
×
561
            }
562
            auto serializer = serializer_fn();
×
UNCOV
563
            auto& lib_node = serializer->deserialize(node, builder, parent);
×
564
            lib_node.element_id_ = node["element_id"];
×
565
            nodes_map.insert({node["element_id"], lib_node});
×
566
        } else if (type == "access_node") {
12✔
567
            assert(node.contains("data"));
12✔
568
            auto& access_node = builder.add_access(parent, node["data"], json_to_debug_info(node["debug_info"]));
12✔
569
            access_node.element_id_ = node["element_id"];
12✔
570
            nodes_map.insert({node["element_id"], access_node});
12✔
571
        } else {
12✔
UNCOV
572
            throw std::runtime_error("Unknown node type");
×
573
        }
574
    }
16✔
575

576
    assert(j.contains("edges"));
10✔
577
    assert(j["edges"].is_array());
10✔
578
    for (const auto& edge : j["edges"]) {
22✔
579
        assert(edge.contains("src"));
12✔
580
        assert(edge["src"].is_number_integer());
12✔
581
        assert(edge.contains("dst"));
12✔
582
        assert(edge["dst"].is_number_integer());
12✔
583
        assert(edge.contains("src_conn"));
12✔
584
        assert(edge["src_conn"].is_string());
12✔
585
        assert(edge.contains("dst_conn"));
12✔
586
        assert(edge["dst_conn"].is_string());
12✔
587
        assert(edge.contains("subset"));
12✔
588
        assert(edge["subset"].is_array());
12✔
589

590
        assert(nodes_map.find(edge["src"]) != nodes_map.end());
12✔
591
        assert(nodes_map.find(edge["dst"]) != nodes_map.end());
12✔
592
        auto& source = nodes_map.at(edge["src"]);
12✔
593
        auto& target = nodes_map.at(edge["dst"]);
12✔
594

595
        assert(edge.contains("subset"));
12✔
596
        assert(edge["subset"].is_array());
12✔
597
        std::vector<symbolic::Expression> subset;
12✔
598
        for (const auto& subset_str : edge["subset"]) {
16✔
599
            assert(subset_str.is_string());
4✔
600
            SymEngine::Expression subset_expr(subset_str);
4✔
601
            subset.push_back(subset_expr);
4✔
602
        }
4✔
603
        auto& memlet = builder.add_memlet(
24✔
604
            parent, source, edge["src_conn"], target, edge["dst_conn"], subset, json_to_debug_info(edge["debug_info"])
12✔
605
        );
606
        memlet.element_id_ = edge["element_id"];
12✔
607
    }
12✔
608
}
10✔
609

610
void JSONSerializer::json_to_sequence(
12✔
611
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& sequence
612
) {
613
    assert(j.contains("type"));
12✔
614
    assert(j["type"].is_string());
12✔
615
    assert(j.contains("children"));
12✔
616
    assert(j["children"].is_array());
12✔
617
    assert(j.contains("transitions"));
12✔
618
    assert(j["transitions"].is_array());
12✔
619
    assert(j["transitions"].size() == j["children"].size());
12✔
620

621
    sequence.element_id_ = j["element_id"];
12✔
622
    sequence.debug_info_ = json_to_debug_info(j["debug_info"]);
12✔
623

624
    std::string type = j["type"];
12✔
625
    if (type == "sequence") {
12✔
626
        for (size_t i = 0; i < j["children"].size(); i++) {
22✔
627
            auto& child = j["children"][i];
10✔
628
            auto& transition = j["transitions"][i];
10✔
629
            assert(child.contains("type"));
10✔
630
            assert(child["type"].is_string());
10✔
631

632
            assert(transition.contains("type"));
10✔
633
            assert(transition["type"].is_string());
10✔
634
            assert(transition.contains("assignments"));
10✔
635
            assert(transition["assignments"].is_array());
10✔
636
            control_flow::Assignments assignments;
10✔
637
            for (const auto& assignment : transition["assignments"]) {
11✔
638
                assert(assignment.contains("symbol"));
1✔
639
                assert(assignment["symbol"].is_string());
1✔
640
                assert(assignment.contains("expression"));
1✔
641
                assert(assignment["expression"].is_string());
1✔
642
                SymEngine::Expression expr(assignment["expression"]);
1✔
643
                assignments.insert({symbolic::symbol(assignment["symbol"]), expr});
1✔
644
            }
1✔
645

646
            if (child["type"] == "block") {
10✔
647
                json_to_block_node(child, builder, sequence, assignments);
8✔
648
            } else if (child["type"] == "for") {
10✔
UNCOV
649
                json_to_for_node(child, builder, sequence, assignments);
×
650
            } else if (child["type"] == "if_else") {
2✔
651
                json_to_if_else_node(child, builder, sequence, assignments);
×
652
            } else if (child["type"] == "while") {
2✔
653
                json_to_while_node(child, builder, sequence, assignments);
×
654
            } else if (child["type"] == "break") {
2✔
655
                json_to_break_node(child, builder, sequence, assignments);
1✔
656
            } else if (child["type"] == "continue") {
2✔
657
                json_to_continue_node(child, builder, sequence, assignments);
1✔
658
            } else if (child["type"] == "return") {
1✔
UNCOV
659
                json_to_return_node(child, builder, sequence, assignments);
×
UNCOV
660
            } else if (child["type"] == "map") {
×
661
                json_to_map_node(child, builder, sequence, assignments);
×
662
            } else if (child["type"] == "sequence") {
×
663
                auto& subseq = builder.add_sequence(sequence, assignments, json_to_debug_info(child["debug_info"]));
×
664
                json_to_sequence(child, builder, subseq);
×
665
            } else {
×
666
                throw std::runtime_error("Unknown child type");
×
667
            }
668

669
            sequence.at(i).second.debug_info_ = json_to_debug_info(transition["debug_info"]);
10✔
670
            sequence.at(i).second.element_id_ = transition["element_id"];
10✔
671
        }
10✔
672
    } else {
12✔
UNCOV
673
        throw std::runtime_error("expected sequence type");
×
674
    }
675
}
12✔
676

677
void JSONSerializer::json_to_block_node(
9✔
678
    const nlohmann::json& j,
679
    builder::StructuredSDFGBuilder& builder,
680
    structured_control_flow::Sequence& parent,
681
    control_flow::Assignments& assignments
682
) {
683
    assert(j.contains("type"));
9✔
684
    assert(j["type"].is_string());
9✔
685
    assert(j.contains("dataflow"));
9✔
686
    assert(j["dataflow"].is_object());
9✔
687
    auto& block = builder.add_block(parent, assignments, json_to_debug_info(j["debug_info"]));
9✔
688
    block.element_id_ = j["element_id"];
9✔
689
    assert(j["dataflow"].contains("type"));
9✔
690
    assert(j["dataflow"]["type"].is_string());
9✔
691
    std::string type = j["dataflow"]["type"];
9✔
692
    if (type == "dataflow") {
9✔
693
        json_to_dataflow(j["dataflow"], builder, block);
9✔
694
    } else {
9✔
UNCOV
695
        throw std::runtime_error("Unknown dataflow type");
×
696
    }
697
}
9✔
698

699
void JSONSerializer::json_to_for_node(
1✔
700
    const nlohmann::json& j,
701
    builder::StructuredSDFGBuilder& builder,
702
    structured_control_flow::Sequence& parent,
703
    control_flow::Assignments& assignments
704
) {
705
    assert(j.contains("type"));
1✔
706
    assert(j["type"].is_string());
1✔
707
    assert(j.contains("indvar"));
1✔
708
    assert(j["indvar"].is_string());
1✔
709
    assert(j.contains("init"));
1✔
710
    assert(j["init"].is_string());
1✔
711
    assert(j.contains("condition"));
1✔
712
    assert(j["condition"].is_string());
1✔
713
    assert(j.contains("update"));
1✔
714
    assert(j["update"].is_string());
1✔
715
    assert(j.contains("root"));
1✔
716
    assert(j["root"].is_object());
1✔
717

718
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
1✔
719
    SymEngine::Expression init(j["init"]);
1✔
720
    SymEngine::Expression condition_expr(j["condition"]);
1✔
721
    assert(!SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic()).is_null());
1✔
722
    symbolic::Condition condition = SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic());
1✔
723
    SymEngine::Expression update(j["update"]);
1✔
724
    auto& for_node =
1✔
725
        builder.add_for(parent, indvar, condition, init, update, assignments, json_to_debug_info(j["debug_info"]));
1✔
726
    for_node.element_id_ = j["element_id"];
1✔
727

728
    assert(j["root"].contains("type"));
1✔
729
    assert(j["root"]["type"].is_string());
1✔
730
    assert(j["root"]["type"] == "sequence");
1✔
731
    json_to_sequence(j["root"], builder, for_node.root());
1✔
732
}
1✔
733

734
void JSONSerializer::json_to_if_else_node(
1✔
735
    const nlohmann::json& j,
736
    builder::StructuredSDFGBuilder& builder,
737
    structured_control_flow::Sequence& parent,
738
    control_flow::Assignments& assignments
739
) {
740
    assert(j.contains("type"));
1✔
741
    assert(j["type"].is_string());
1✔
742
    assert(j["type"] == "if_else");
1✔
743
    assert(j.contains("branches"));
1✔
744
    assert(j["branches"].is_array());
1✔
745
    auto& if_else_node = builder.add_if_else(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
746
    if_else_node.element_id_ = j["element_id"];
1✔
747
    for (const auto& branch : j["branches"]) {
3✔
748
        assert(branch.contains("condition"));
2✔
749
        assert(branch["condition"].is_string());
2✔
750
        assert(branch.contains("root"));
2✔
751
        assert(branch["root"].is_object());
2✔
752
        SymEngine::Expression condition_expr(branch["condition"]);
2✔
753
        assert(!SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic()).is_null());
2✔
754
        symbolic::Condition condition = SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic()
2✔
755
        );
756
        auto& branch_node = builder.add_case(if_else_node, condition);
2✔
757
        assert(branch["root"].contains("type"));
2✔
758
        assert(branch["root"]["type"].is_string());
2✔
759
        std::string type = branch["root"]["type"];
2✔
760
        if (type == "sequence") {
2✔
761
            json_to_sequence(branch["root"], builder, branch_node);
2✔
762
        } else {
2✔
UNCOV
763
            throw std::runtime_error("Unknown child type");
×
764
        }
765
    }
2✔
766
}
1✔
767

768
void JSONSerializer::json_to_while_node(
3✔
769
    const nlohmann::json& j,
770
    builder::StructuredSDFGBuilder& builder,
771
    structured_control_flow::Sequence& parent,
772
    control_flow::Assignments& assignments
773
) {
774
    assert(j.contains("type"));
3✔
775
    assert(j["type"].is_string());
3✔
776
    assert(j["type"] == "while");
3✔
777
    assert(j.contains("root"));
3✔
778
    assert(j["root"].is_object());
3✔
779

780
    auto& while_node = builder.add_while(parent, assignments, json_to_debug_info(j["debug_info"]));
3✔
781
    while_node.element_id_ = j["element_id"];
3✔
782

783
    assert(j["root"]["type"] == "sequence");
3✔
784
    json_to_sequence(j["root"], builder, while_node.root());
3✔
785
}
3✔
786

787
void JSONSerializer::json_to_break_node(
1✔
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"));
1✔
794
    assert(j["type"].is_string());
1✔
795
    assert(j["type"] == "break");
1✔
796
    auto& node = builder.add_break(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
797
    node.element_id_ = j["element_id"];
1✔
798
}
1✔
799

800
void JSONSerializer::json_to_continue_node(
1✔
801
    const nlohmann::json& j,
802
    builder::StructuredSDFGBuilder& builder,
803
    structured_control_flow::Sequence& parent,
804
    control_flow::Assignments& assignments
805
) {
806
    assert(j.contains("type"));
1✔
807
    assert(j["type"].is_string());
1✔
808
    assert(j["type"] == "continue");
1✔
809
    auto& node = builder.add_continue(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
810
    node.element_id_ = j["element_id"];
1✔
811
}
1✔
812

813
void JSONSerializer::json_to_map_node(
1✔
814
    const nlohmann::json& j,
815
    builder::StructuredSDFGBuilder& builder,
816
    structured_control_flow::Sequence& parent,
817
    control_flow::Assignments& assignments
818
) {
819
    assert(j.contains("type"));
1✔
820
    assert(j["type"].is_string());
1✔
821
    assert(j["type"] == "map");
1✔
822
    assert(j.contains("indvar"));
1✔
823
    assert(j["indvar"].is_string());
1✔
824
    assert(j.contains("init"));
1✔
825
    assert(j["init"].is_string());
1✔
826
    assert(j.contains("condition"));
1✔
827
    assert(j["condition"].is_string());
1✔
828
    assert(j.contains("update"));
1✔
829
    assert(j["update"].is_string());
1✔
830
    assert(j.contains("root"));
1✔
831
    assert(j["root"].is_object());
1✔
832
    assert(j.contains("schedule_type"));
1✔
833
    assert(j["schedule_type"].is_string());
1✔
834

835
    structured_control_flow::ScheduleType schedule_type =
836
        schedule_type_from_string(j["schedule_type"].get<std::string>());
1✔
837

838
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
1✔
839
    SymEngine::Expression init(j["init"]);
1✔
840
    SymEngine::Expression condition_expr(j["condition"]);
1✔
841
    assert(!SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic()).is_null());
1✔
842
    symbolic::Condition condition = SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic());
1✔
843
    SymEngine::Expression update(j["update"]);
1✔
844

845
    auto& map_node = builder.add_map(
2✔
846
        parent, indvar, condition, init, update, schedule_type, assignments, json_to_debug_info(j["debug_info"])
1✔
847
    );
848
    map_node.element_id_ = j["element_id"];
1✔
849

850
    assert(j["root"].contains("type"));
1✔
851
    assert(j["root"]["type"].is_string());
1✔
852
    assert(j["root"]["type"] == "sequence");
1✔
853
    json_to_sequence(j["root"], builder, map_node.root());
1✔
854
}
1✔
855

856
void JSONSerializer::json_to_return_node(
1✔
857
    const nlohmann::json& j,
858
    builder::StructuredSDFGBuilder& builder,
859
    structured_control_flow::Sequence& parent,
860
    control_flow::Assignments& assignments
861
) {
862
    assert(j.contains("type"));
1✔
863
    assert(j["type"].is_string());
1✔
864
    assert(j["type"] == "return");
1✔
865

866
    auto& node = builder.add_return(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
867
    node.element_id_ = j["element_id"];
1✔
868
}
1✔
869

870
std::unique_ptr<types::IType> JSONSerializer::json_to_type(const nlohmann::json& j) {
31✔
871
    if (j.contains("type")) {
31✔
872
        if (j["type"] == "scalar") {
31✔
873
            // Deserialize scalar type
874
            assert(j.contains("primitive_type"));
25✔
875
            types::PrimitiveType primitive_type = j["primitive_type"];
25✔
876
            assert(j.contains("storage_type"));
25✔
877
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
25✔
878
            assert(j.contains("initializer"));
25✔
879
            std::string initializer = j["initializer"];
25✔
880
            assert(j.contains("alignment"));
25✔
881
            size_t alignment = j["alignment"];
25✔
882
            return std::make_unique<types::Scalar>(storage_type, alignment, initializer, primitive_type);
25✔
883
        } else if (j["type"] == "array") {
31✔
884
            // Deserialize array type
885
            assert(j.contains("element_type"));
2✔
886
            std::unique_ptr<types::IType> member_type = json_to_type(j["element_type"]);
2✔
887
            assert(j.contains("num_elements"));
2✔
888
            std::string num_elements_str = j["num_elements"];
2✔
889
            // Convert num_elements_str to symbolic::Expression
890
            SymEngine::Expression num_elements(num_elements_str);
2✔
891
            assert(j.contains("storage_type"));
2✔
892
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
2✔
893
            assert(j.contains("initializer"));
2✔
894
            std::string initializer = j["initializer"];
2✔
895
            assert(j.contains("alignment"));
2✔
896
            size_t alignment = j["alignment"];
2✔
897
            return std::make_unique<types::Array>(storage_type, alignment, initializer, *member_type, num_elements);
2✔
898
        } else if (j["type"] == "pointer") {
6✔
899
            // Deserialize pointer type
900
            assert(j.contains("pointee_type"));
2✔
901
            std::unique_ptr<types::IType> pointee_type = json_to_type(j["pointee_type"]);
2✔
902
            assert(j.contains("storage_type"));
2✔
903
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
2✔
904
            assert(j.contains("initializer"));
2✔
905
            std::string initializer = j["initializer"];
2✔
906
            assert(j.contains("alignment"));
2✔
907
            size_t alignment = j["alignment"];
2✔
908
            return std::make_unique<types::Pointer>(storage_type, alignment, initializer, *pointee_type);
2✔
909
        } else if (j["type"] == "structure") {
4✔
910
            // Deserialize structure type
911
            assert(j.contains("name"));
1✔
912
            std::string name = j["name"];
1✔
913
            assert(j.contains("storage_type"));
1✔
914
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
1✔
915
            assert(j.contains("initializer"));
1✔
916
            std::string initializer = j["initializer"];
1✔
917
            assert(j.contains("alignment"));
1✔
918
            size_t alignment = j["alignment"];
1✔
919
            return std::make_unique<types::Structure>(storage_type, alignment, initializer, name);
1✔
920
        } else if (j["type"] == "function") {
2✔
921
            // Deserialize function type
922
            assert(j.contains("return_type"));
1✔
923
            std::unique_ptr<types::IType> return_type = json_to_type(j["return_type"]);
1✔
924
            assert(j.contains("params"));
1✔
925
            std::vector<std::unique_ptr<types::IType>> params;
1✔
926
            for (const auto& param : j["params"]) {
3✔
927
                params.push_back(json_to_type(param));
2✔
928
            }
929
            assert(j.contains("is_var_arg"));
1✔
930
            bool is_var_arg = j["is_var_arg"];
1✔
931
            assert(j.contains("storage_type"));
1✔
932
            types::StorageType storage_type = storage_type_from_string(j["storage_type"].get<std::string>());
1✔
933
            assert(j.contains("initializer"));
1✔
934
            std::string initializer = j["initializer"];
1✔
935
            assert(j.contains("alignment"));
1✔
936
            size_t alignment = j["alignment"];
1✔
937
            auto function =
938
                std::make_unique<types::Function>(storage_type, alignment, initializer, *return_type, is_var_arg);
1✔
939
            for (const auto& param : params) {
3✔
940
                function->add_param(*param);
2✔
941
            }
942
            return function->clone();
1✔
943

944
        } else {
1✔
UNCOV
945
            throw std::runtime_error("Unknown type");
×
946
        }
947
    } else {
UNCOV
948
        throw std::runtime_error("Type not found");
×
949
    }
950
}
31✔
951

952
DebugInfo JSONSerializer::json_to_debug_info(const nlohmann::json& j) {
68✔
953
    assert(j.contains("has"));
68✔
954
    assert(j["has"].is_boolean());
68✔
955
    if (!j["has"]) {
68✔
956
        return DebugInfo();
68✔
957
    }
UNCOV
958
    assert(j.contains("filename"));
×
UNCOV
959
    assert(j["filename"].is_string());
×
960
    std::string filename = j["filename"];
×
961
    assert(j.contains("start_line"));
×
962
    assert(j["start_line"].is_number_integer());
×
963
    size_t start_line = j["start_line"];
×
964
    assert(j.contains("start_column"));
×
965
    assert(j["start_column"].is_number_integer());
×
966
    size_t start_column = j["start_column"];
×
967
    assert(j.contains("end_line"));
×
968
    assert(j["end_line"].is_number_integer());
×
969
    size_t end_line = j["end_line"];
×
970
    assert(j.contains("end_column"));
×
971
    assert(j["end_column"].is_number_integer());
×
972
    size_t end_column = j["end_column"];
×
973
    return DebugInfo(filename, start_line, start_column, end_line, end_column);
×
974
}
68✔
975

976
std::string JSONSerializer::expression(const symbolic::Expression& expr) {
33✔
977
    JSONSymbolicPrinter printer;
33✔
978
    return printer.apply(expr);
33✔
979
};
33✔
980

UNCOV
981
void JSONSymbolicPrinter::bvisit(const SymEngine::Equality& x) {
×
UNCOV
982
    str_ = apply(x.get_args()[0]) + " == " + apply(x.get_args()[1]);
×
983
    str_ = parenthesize(str_);
×
984
};
×
985

986
void JSONSymbolicPrinter::bvisit(const SymEngine::Unequality& x) {
×
UNCOV
987
    str_ = apply(x.get_args()[0]) + " != " + apply(x.get_args()[1]);
×
988
    str_ = parenthesize(str_);
×
989
};
×
990

991
void JSONSymbolicPrinter::bvisit(const SymEngine::LessThan& x) {
×
UNCOV
992
    str_ = apply(x.get_args()[0]) + " <= " + apply(x.get_args()[1]);
×
993
    str_ = parenthesize(str_);
×
994
};
×
995

996
void JSONSymbolicPrinter::bvisit(const SymEngine::StrictLessThan& x) {
4✔
997
    str_ = apply(x.get_args()[0]) + " < " + apply(x.get_args()[1]);
4✔
998
    str_ = parenthesize(str_);
4✔
999
};
4✔
1000

UNCOV
1001
void JSONSymbolicPrinter::bvisit(const SymEngine::Min& x) {
×
UNCOV
1002
    std::ostringstream s;
×
1003
    auto container = x.get_args();
×
1004
    if (container.size() == 1) {
×
1005
        s << apply(*container.begin());
×
1006
    } else {
×
1007
        s << "min(";
×
1008
        s << apply(*container.begin());
×
1009

1010
        // Recursively apply __daisy_min to the arguments
UNCOV
1011
        SymEngine::vec_basic subargs;
×
UNCOV
1012
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1013
            subargs.push_back(*it);
×
1014
        }
×
1015
        auto submin = SymEngine::min(subargs);
×
1016
        s << ", " << apply(submin);
×
1017

1018
        s << ")";
×
UNCOV
1019
    }
×
1020

1021
    str_ = s.str();
×
UNCOV
1022
};
×
1023

1024
void JSONSymbolicPrinter::bvisit(const SymEngine::Max& x) {
×
UNCOV
1025
    std::ostringstream s;
×
1026
    auto container = x.get_args();
×
1027
    if (container.size() == 1) {
×
1028
        s << apply(*container.begin());
×
1029
    } else {
×
1030
        s << "max(";
×
1031
        s << apply(*container.begin());
×
1032

1033
        // Recursively apply __daisy_max to the arguments
UNCOV
1034
        SymEngine::vec_basic subargs;
×
UNCOV
1035
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1036
            subargs.push_back(*it);
×
1037
        }
×
1038
        auto submax = SymEngine::max(subargs);
×
1039
        s << ", " << apply(submax);
×
1040

1041
        s << ")";
×
UNCOV
1042
    }
×
1043

1044
    str_ = s.str();
×
UNCOV
1045
};
×
1046

1047
void LibraryNodeSerializerRegistry::
1048
    register_library_node_serializer(std::string library_node_code, LibraryNodeSerializerFn fn) {
4✔
1049
    std::lock_guard<std::mutex> lock(mutex_);
4✔
1050
    if (factory_map_.find(library_node_code) != factory_map_.end()) {
4✔
NEW
1051
        throw std::runtime_error(
×
NEW
1052
            "Library node serializer already registered for library node code: " + std::string(library_node_code)
×
1053
        );
1054
    }
1055
    factory_map_[library_node_code] = std::move(fn);
4✔
1056
}
4✔
1057

1058
LibraryNodeSerializerFn LibraryNodeSerializerRegistry::get_library_node_serializer(std::string library_node_code) {
1✔
1059
    auto it = factory_map_.find(library_node_code);
1✔
1060
    if (it != factory_map_.end()) {
1✔
1061
        return it->second;
1✔
1062
    }
NEW
1063
    return nullptr;
×
1064
}
1✔
1065

NEW
1066
size_t LibraryNodeSerializerRegistry::size() const { return factory_map_.size(); }
×
1067

1068
void register_default_serializers() {
2✔
1069
    LibraryNodeSerializerRegistry::instance()
2✔
1070
        .register_library_node_serializer(data_flow::LibraryNodeType_BarrierLocal.value(), []() {
3✔
1071
            return std::make_unique<data_flow::BarrierLocalNodeSerializer>();
1✔
1072
        });
1073
    LibraryNodeSerializerRegistry::instance()
2✔
1074
        .register_library_node_serializer(data_flow::LibraryNodeType_Metadata.value(), []() {
2✔
NEW
1075
            return std::make_unique<data_flow::MetadataNodeSerializer>();
×
1076
        });
1077
    // Add more serializers as needed
1078
}
2✔
1079

1080
} // namespace serializer
1081
} // 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