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

daisytuner / sdfglib / 20561412006

29 Dec 2025 12:03AM UTC coverage: 40.369% (+1.4%) from 38.976%
20561412006

Pull #409

github

web-flow
Merge d082d4d04 into eec4d6f74
Pull Request #409: restructures library nodes

14299 of 45900 branches covered (31.15%)

Branch coverage included in aggregate %.

259 of 388 new or added lines in 19 files covered. (66.75%)

27 existing lines in 1 file now uncovered.

12248 of 19861 relevant lines covered (61.67%)

89.05 hits per line

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

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

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

8
#include "sdfg/data_flow/library_nodes/barrier_local_node.h"
9
#include "sdfg/data_flow/library_nodes/call_node.h"
10
#include "sdfg/data_flow/library_nodes/invoke_node.h"
11
#include "sdfg/data_flow/library_nodes/math/math.h"
12
#include "sdfg/data_flow/library_nodes/metadata_node.h"
13
#include "sdfg/data_flow/library_nodes/stdlib/stdlib.h"
14

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

34
namespace sdfg {
35
namespace serializer {
36

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

44
    return FunctionType(str);
×
45
}
7✔
46

47
/*
48
 * * JSONSerializer class
49
 * * Serialization logic
50
 */
51

52
nlohmann::json JSONSerializer::serialize(const sdfg::StructuredSDFG& sdfg) {
7✔
53
    nlohmann::json j;
7✔
54

55
    j["name"] = sdfg.name();
7!
56
    j["element_counter"] = sdfg.element_counter();
7!
57
    j["type"] = std::string(sdfg.type().value());
7!
58

59
    nlohmann::json return_type_json;
7✔
60
    type_to_json(return_type_json, sdfg.return_type());
7!
61
    j["return_type"] = return_type_json;
7!
62

63
    j["structures"] = nlohmann::json::array();
7!
64
    for (const auto& structure_name : sdfg.structures()) {
8!
65
        const auto& structure = sdfg.structure(structure_name);
1!
66
        nlohmann::json structure_json;
1✔
67
        structure_definition_to_json(structure_json, structure);
1!
68
        j["structures"].push_back(structure_json);
1!
69
    }
1✔
70

71
    j["containers"] = nlohmann::json::object();
7!
72
    for (const auto& container : sdfg.containers()) {
61!
73
        nlohmann::json desc;
54✔
74
        type_to_json(desc, sdfg.type(container));
54!
75
        j["containers"][container] = desc;
54!
76
    }
54✔
77

78
    j["arguments"] = nlohmann::json::array();
7!
79
    for (const auto& argument : sdfg.arguments()) {
30!
80
        j["arguments"].push_back(argument);
23!
81
    }
82

83
    j["externals"] = nlohmann::json::array();
7!
84
    for (const auto& external : sdfg.externals()) {
11!
85
        nlohmann::json external_json;
4✔
86
        external_json["name"] = external;
4!
87
        external_json["linkage_type"] = sdfg.linkage_type(external);
4!
88
        j["externals"].push_back(external_json);
4!
89
    }
4✔
90

91
    j["metadata"] = nlohmann::json::object();
7!
92
    for (const auto& entry : sdfg.metadata()) {
8!
93
        j["metadata"][entry.first] = entry.second;
1!
94
    }
95

96
    // Walk the SDFG
97
    nlohmann::json root_json;
7✔
98
    sequence_to_json(root_json, sdfg.root());
7!
99
    j["root"] = root_json;
7!
100

101
    return j;
7✔
102
}
7!
103

104
void JSONSerializer::dataflow_to_json(nlohmann::json& j, const data_flow::DataFlowGraph& dataflow) {
33✔
105
    j["type"] = "dataflow";
33!
106
    j["nodes"] = nlohmann::json::array();
33!
107
    j["edges"] = nlohmann::json::array();
33!
108

109
    for (auto& node : dataflow.nodes()) {
111✔
110
        nlohmann::json node_json;
78✔
111
        node_json["element_id"] = node.element_id();
78!
112

113
        node_json["debug_info"] = nlohmann::json::object();
78!
114
        debug_info_to_json(node_json["debug_info"], node.debug_info());
78!
115

116
        if (auto tasklet = dynamic_cast<const data_flow::Tasklet*>(&node)) {
78!
117
            node_json["type"] = "tasklet";
19!
118
            node_json["code"] = tasklet->code();
19!
119
            node_json["inputs"] = nlohmann::json::array();
19!
120
            for (auto& input : tasklet->inputs()) {
61!
121
                node_json["inputs"].push_back(input);
42!
122
            }
123
            node_json["output"] = tasklet->output();
19!
124
        } else if (auto lib_node = dynamic_cast<const data_flow::LibraryNode*>(&node)) {
78!
125
            node_json["type"] = "library_node";
×
126
            node_json["implementation_type"] = std::string(lib_node->implementation_type().value());
×
127
            auto serializer_fn =
128
                LibraryNodeSerializerRegistry::instance().get_library_node_serializer(lib_node->code().value());
×
129
            if (serializer_fn == nullptr) {
×
130
                throw std::runtime_error("Unknown library node code: " + std::string(lib_node->code().value()));
×
131
            }
132
            auto serializer = serializer_fn();
×
133
            auto lib_node_json = serializer->serialize(*lib_node);
×
134
            node_json.merge_patch(lib_node_json);
×
135
        } else if (auto code_node = dynamic_cast<const data_flow::ConstantNode*>(&node)) {
59!
136
            node_json["type"] = "constant_node";
×
137
            node_json["data"] = code_node->data();
×
138

139
            nlohmann::json type_json;
×
140
            type_to_json(type_json, code_node->type());
×
141
            node_json["data_type"] = type_json;
×
142
        } else if (auto code_node = dynamic_cast<const data_flow::AccessNode*>(&node)) {
59!
143
            node_json["type"] = "access_node";
59!
144
            node_json["data"] = code_node->data();
59!
145
        } else {
59✔
146
            throw std::runtime_error("Unknown node type");
×
147
        }
148

149
        j["nodes"].push_back(node_json);
78!
150
    }
78✔
151

152
    for (auto& edge : dataflow.edges()) {
94✔
153
        nlohmann::json edge_json;
61✔
154
        edge_json["element_id"] = edge.element_id();
61!
155

156
        edge_json["debug_info"] = nlohmann::json::object();
61!
157
        debug_info_to_json(edge_json["debug_info"], edge.debug_info());
61!
158

159
        edge_json["src"] = edge.src().element_id();
61!
160
        edge_json["dst"] = edge.dst().element_id();
61!
161

162
        edge_json["src_conn"] = edge.src_conn();
61!
163
        edge_json["dst_conn"] = edge.dst_conn();
61!
164

165
        edge_json["subset"] = nlohmann::json::array();
61!
166
        for (auto& subset : edge.subset()) {
109!
167
            edge_json["subset"].push_back(expression(subset));
48!
168
        }
169

170
        nlohmann::json base_type_json;
61✔
171
        type_to_json(base_type_json, edge.base_type());
61!
172
        edge_json["base_type"] = base_type_json;
61!
173

174
        j["edges"].push_back(edge_json);
61!
175
    }
61✔
176
}
33✔
177

178
void JSONSerializer::block_to_json(nlohmann::json& j, const structured_control_flow::Block& block) {
31✔
179
    j["type"] = "block";
31!
180
    j["element_id"] = block.element_id();
31!
181

182
    j["debug_info"] = nlohmann::json::object();
31!
183
    debug_info_to_json(j["debug_info"], block.debug_info());
31✔
184

185
    nlohmann::json dataflow_json;
31✔
186
    dataflow_to_json(dataflow_json, block.dataflow());
31!
187
    j["dataflow"] = dataflow_json;
31!
188
}
31✔
189

190
void JSONSerializer::for_to_json(nlohmann::json& j, const structured_control_flow::For& for_node) {
16✔
191
    j["type"] = "for";
16!
192
    j["element_id"] = for_node.element_id();
16!
193

194
    j["debug_info"] = nlohmann::json::object();
16!
195
    debug_info_to_json(j["debug_info"], for_node.debug_info());
16✔
196

197
    j["indvar"] = expression(for_node.indvar());
16!
198
    j["init"] = expression(for_node.init());
16!
199
    j["condition"] = expression(for_node.condition());
16!
200
    j["update"] = expression(for_node.update());
16!
201

202
    nlohmann::json body_json;
16✔
203
    sequence_to_json(body_json, for_node.root());
16!
204
    j["root"] = body_json;
16!
205
}
16✔
206

207
void JSONSerializer::if_else_to_json(nlohmann::json& j, const structured_control_flow::IfElse& if_else_node) {
2✔
208
    j["type"] = "if_else";
2!
209
    j["element_id"] = if_else_node.element_id();
2!
210

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

214
    j["branches"] = nlohmann::json::array();
2!
215
    for (size_t i = 0; i < if_else_node.size(); i++) {
6✔
216
        nlohmann::json branch_json;
4✔
217
        branch_json["condition"] = expression(if_else_node.at(i).second);
4!
218
        nlohmann::json body_json;
4✔
219
        sequence_to_json(body_json, if_else_node.at(i).first);
4!
220
        branch_json["root"] = body_json;
4!
221
        j["branches"].push_back(branch_json);
4!
222
    }
4✔
223
}
2✔
224

225
void JSONSerializer::while_node_to_json(nlohmann::json& j, const structured_control_flow::While& while_node) {
5✔
226
    j["type"] = "while";
5!
227
    j["element_id"] = while_node.element_id();
5!
228

229
    j["debug_info"] = nlohmann::json::object();
5!
230
    debug_info_to_json(j["debug_info"], while_node.debug_info());
5✔
231

232
    nlohmann::json body_json;
5✔
233
    sequence_to_json(body_json, while_node.root());
5!
234
    j["root"] = body_json;
5!
235
}
5✔
236

237
void JSONSerializer::break_node_to_json(nlohmann::json& j, const structured_control_flow::Break& break_node) {
2✔
238
    j["type"] = "break";
2!
239
    j["element_id"] = break_node.element_id();
2!
240

241
    j["debug_info"] = nlohmann::json::object();
2!
242
    debug_info_to_json(j["debug_info"], break_node.debug_info());
2✔
243
}
2✔
244

245
void JSONSerializer::continue_node_to_json(nlohmann::json& j, const structured_control_flow::Continue& continue_node) {
2✔
246
    j["type"] = "continue";
2!
247
    j["element_id"] = continue_node.element_id();
2!
248

249
    j["debug_info"] = nlohmann::json::object();
2!
250
    debug_info_to_json(j["debug_info"], continue_node.debug_info());
2✔
251
}
2✔
252

253
void JSONSerializer::map_to_json(nlohmann::json& j, const structured_control_flow::Map& map_node) {
2✔
254
    j["type"] = "map";
2!
255
    j["element_id"] = map_node.element_id();
2!
256

257
    j["debug_info"] = nlohmann::json::object();
2!
258
    debug_info_to_json(j["debug_info"], map_node.debug_info());
2✔
259

260
    j["indvar"] = expression(map_node.indvar());
2!
261
    j["init"] = expression(map_node.init());
2!
262
    j["condition"] = expression(map_node.condition());
2!
263
    j["update"] = expression(map_node.update());
2!
264

265
    j["schedule_type"] = nlohmann::json::object();
2!
266
    schedule_type_to_json(j["schedule_type"], map_node.schedule_type());
2✔
267

268
    nlohmann::json body_json;
2✔
269
    sequence_to_json(body_json, map_node.root());
2!
270
    j["root"] = body_json;
2!
271
}
2✔
272

273
void JSONSerializer::return_node_to_json(nlohmann::json& j, const structured_control_flow::Return& return_node) {
2✔
274
    j["type"] = "return";
2!
275
    j["element_id"] = return_node.element_id();
2!
276
    j["data"] = return_node.data();
2!
277

278
    if (return_node.is_constant()) {
2!
279
        nlohmann::json type_json;
×
280
        type_to_json(type_json, return_node.type());
×
281
        j["data_type"] = type_json;
×
282
    }
×
283

284
    j["debug_info"] = nlohmann::json::object();
2!
285
    debug_info_to_json(j["debug_info"], return_node.debug_info());
2✔
286
}
2✔
287

288
void JSONSerializer::sequence_to_json(nlohmann::json& j, const structured_control_flow::Sequence& sequence) {
37✔
289
    j["type"] = "sequence";
37!
290
    j["element_id"] = sequence.element_id();
37!
291

292
    j["debug_info"] = nlohmann::json::object();
37!
293
    debug_info_to_json(j["debug_info"], sequence.debug_info());
37✔
294

295
    j["children"] = nlohmann::json::array();
37!
296
    j["transitions"] = nlohmann::json::array();
37!
297

298
    for (size_t i = 0; i < sequence.size(); i++) {
84✔
299
        nlohmann::json child_json;
47✔
300
        auto& child = sequence.at(i).first;
47!
301
        auto& transition = sequence.at(i).second;
47!
302

303
        if (auto block = dynamic_cast<const structured_control_flow::Block*>(&child)) {
47!
304
            block_to_json(child_json, *block);
29!
305
        } else if (auto for_node = dynamic_cast<const structured_control_flow::For*>(&child)) {
47!
306
            for_to_json(child_json, *for_node);
14!
307
        } else if (auto sequence_node = dynamic_cast<const structured_control_flow::Sequence*>(&child)) {
18!
308
            sequence_to_json(child_json, *sequence_node);
×
309
        } else if (auto condition_node = dynamic_cast<const structured_control_flow::IfElse*>(&child)) {
4!
310
            if_else_to_json(child_json, *condition_node);
×
311
        } else if (auto while_node = dynamic_cast<const structured_control_flow::While*>(&child)) {
4!
312
            while_node_to_json(child_json, *while_node);
×
313
        } else if (auto return_node = dynamic_cast<const structured_control_flow::Return*>(&child)) {
4!
314
            return_node_to_json(child_json, *return_node);
×
315
        } else if (auto break_node = dynamic_cast<const structured_control_flow::Break*>(&child)) {
4!
316
            break_node_to_json(child_json, *break_node);
2!
317
        } else if (auto continue_node = dynamic_cast<const structured_control_flow::Continue*>(&child)) {
4!
318
            continue_node_to_json(child_json, *continue_node);
2!
319
        } else if (auto map_node = dynamic_cast<const structured_control_flow::Map*>(&child)) {
2!
320
            map_to_json(child_json, *map_node);
×
321
        } else {
×
322
            throw std::runtime_error("Unknown child type");
×
323
        }
324

325
        j["children"].push_back(child_json);
47!
326

327
        // Add transition information
328
        nlohmann::json transition_json;
47✔
329
        transition_json["type"] = "transition";
47!
330
        transition_json["element_id"] = transition.element_id();
47!
331

332
        transition_json["debug_info"] = nlohmann::json::object();
47!
333
        debug_info_to_json(transition_json["debug_info"], transition.debug_info());
47!
334

335
        transition_json["assignments"] = nlohmann::json::array();
47!
336
        for (const auto& assignment : transition.assignments()) {
50!
337
            nlohmann::json assignment_json;
3✔
338
            assignment_json["symbol"] = expression(assignment.first);
3!
339
            assignment_json["expression"] = expression(assignment.second);
3!
340
            transition_json["assignments"].push_back(assignment_json);
3!
341
        }
3✔
342

343
        j["transitions"].push_back(transition_json);
47!
344
    }
47✔
345
}
37✔
346

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

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

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

425
void JSONSerializer::schedule_type_to_json(nlohmann::json& j, const ScheduleType& schedule_type) {
3✔
426
    j["value"] = schedule_type.value();
3!
427
    j["properties"] = nlohmann::json::object();
3!
428
    for (const auto& prop : schedule_type.properties()) {
4✔
429
        j["properties"][prop.first] = prop.second;
1!
430
    }
431
}
3✔
432

433
void JSONSerializer::storage_type_to_json(nlohmann::json& j, const types::StorageType& storage_type) {
212✔
434
    j["value"] = storage_type.value();
212!
435
    j["allocation"] = storage_type.allocation();
212!
436
    j["deallocation"] = storage_type.deallocation();
212!
437
    if (!storage_type.allocation_size().is_null()) {
212!
438
        j["allocation_size"] = expression(storage_type.allocation_size());
×
439
    }
×
440
    const symbolic::Expression& arg1 = storage_type.arg1();
212✔
441
    if (!arg1.is_null()) {
212!
442
        auto args = nlohmann::json::array();
×
443
        args.push_back(expression(arg1));
×
444
        j["args"] = args;
×
445
    }
×
446
}
212✔
447

448

449
/*
450
 * * Deserialization logic
451
 */
452

453
std::unique_ptr<StructuredSDFG> JSONSerializer::deserialize(nlohmann::json& j) {
7✔
454
    assert(j.contains("name"));
7!
455
    assert(j["name"].is_string());
7!
456
    assert(j.contains("type"));
7!
457
    assert(j["type"].is_string());
7!
458
    assert(j.contains("element_counter"));
7!
459
    assert(j["element_counter"].is_number_integer());
7!
460

461
    std::unique_ptr<types::IType> return_type;
7✔
462
    if (j.contains("return_type")) {
7!
463
        return_type = json_to_type(j["return_type"]);
7!
464
    } else {
7✔
465
        return_type = std::make_unique<types::Scalar>(types::PrimitiveType::Void);
×
466
    }
467

468
    FunctionType function_type = function_type_from_string(j["type"].get<std::string>());
7!
469
    builder::StructuredSDFGBuilder builder(j["name"], function_type, *return_type);
7!
470

471
    size_t element_counter = j["element_counter"];
7!
472
    builder.set_element_counter(element_counter);
7!
473

474
    // deserialize structures
475
    assert(j.contains("structures"));
7!
476
    assert(j["structures"].is_array());
7!
477
    for (const auto& structure : j["structures"]) {
8!
478
        assert(structure.contains("name"));
1!
479
        assert(structure["name"].is_string());
1!
480
        json_to_structure_definition(structure, builder);
1!
481
    }
482

483
    nlohmann::json& containers = j["containers"];
7!
484

485
    // deserialize externals
486
    for (const auto& external : j["externals"]) {
11!
487
        assert(external.contains("name"));
4!
488
        assert(external["name"].is_string());
4!
489
        assert(external.contains("linkage_type"));
4!
490
        assert(external["linkage_type"].is_number_integer());
4!
491
        auto& type_desc = containers.at(external["name"].get<std::string>());
4!
492
        auto type = json_to_type(type_desc);
4!
493
        builder.add_external(external["name"], *type, LinkageType(external["linkage_type"]));
4!
494
    }
4✔
495

496
    // deserialize arguments
497
    for (const auto& name : j["arguments"]) {
30!
498
        auto& type_desc = containers.at(name.get<std::string>());
23!
499
        auto type = json_to_type(type_desc);
23!
500
        builder.add_container(name, *type, true, false);
23!
501
    }
23✔
502

503
    // deserialize transients
504
    for (const auto& entry : containers.items()) {
61!
505
        if (builder.subject().is_argument(entry.key())) {
54!
506
            continue;
23✔
507
        }
508
        if (builder.subject().is_external(entry.key())) {
31!
509
            continue;
4✔
510
        }
511
        auto type = json_to_type(entry.value());
27!
512
        builder.add_container(entry.key(), *type, false, false);
27!
513
    }
27✔
514

515
    // deserialize root node
516
    assert(j.contains("root"));
7!
517
    auto& root = builder.subject().root();
7!
518
    json_to_sequence(j["root"], builder, root);
7!
519

520
    // deserialize metadata
521
    assert(j.contains("metadata"));
7!
522
    assert(j["metadata"].is_object());
7!
523
    for (const auto& entry : j["metadata"].items()) {
8!
524
        builder.subject().add_metadata(entry.key(), entry.value());
1!
525
    }
526

527
    builder.set_element_counter(element_counter);
7!
528

529
    return builder.move();
7!
530
}
7✔
531

532
void JSONSerializer::json_to_structure_definition(const nlohmann::json& j, builder::StructuredSDFGBuilder& builder) {
2✔
533
    assert(j.contains("name"));
2!
534
    assert(j["name"].is_string());
2!
535
    assert(j.contains("members"));
2!
536
    assert(j["members"].is_array());
2!
537
    assert(j.contains("is_packed"));
2!
538
    assert(j["is_packed"].is_boolean());
2!
539
    auto is_packed = j["is_packed"];
2✔
540
    auto& definition = builder.add_structure(j["name"], is_packed);
2!
541
    for (const auto& member : j["members"]) {
4!
542
        nlohmann::json member_json;
2✔
543
        auto member_type = json_to_type(member);
2!
544
        definition.add_member(*member_type);
2!
545
    }
2✔
546
}
2✔
547

548
std::vector<std::pair<std::string, types::Scalar>> JSONSerializer::json_to_arguments(const nlohmann::json& j) {
×
549
    std::vector<std::pair<std::string, types::Scalar>> arguments;
×
550
    for (const auto& argument : j) {
×
551
        assert(argument.contains("name"));
×
552
        assert(argument["name"].is_string());
×
553
        assert(argument.contains("type"));
×
554
        assert(argument["type"].is_object());
×
555
        std::string name = argument["name"];
×
556
        auto type = json_to_type(argument["type"]);
×
557
        arguments.emplace_back(name, *dynamic_cast<types::Scalar*>(type.get()));
×
558
    }
×
559
    return arguments;
×
560
}
×
561

562
void JSONSerializer::json_to_dataflow(
23✔
563
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Block& parent
564
) {
565
    std::map<size_t, data_flow::DataFlowNode&> nodes_map;
23✔
566

567
    assert(j.contains("nodes"));
23!
568
    assert(j["nodes"].is_array());
23!
569
    for (const auto& node : j["nodes"]) {
97!
570
        assert(node.contains("type"));
74!
571
        assert(node["type"].is_string());
74!
572
        assert(node.contains("element_id"));
74!
573
        assert(node["element_id"].is_number_integer());
74!
574
        std::string type = node["type"];
74!
575
        if (type == "tasklet") {
74!
576
            assert(node.contains("code"));
18!
577
            assert(node["code"].is_number_integer());
18!
578
            assert(node.contains("inputs"));
18!
579
            assert(node["inputs"].is_array());
18!
580
            assert(node.contains("output"));
18!
581
            assert(node["output"].is_string());
18!
582
            auto inputs = node["inputs"].get<std::vector<std::string>>();
18!
583

584
            auto& tasklet =
18✔
585
                builder
36✔
586
                    .add_tasklet(parent, node["code"], node["output"], inputs, json_to_debug_info(node["debug_info"]));
18!
587
            tasklet.element_id_ = node["element_id"];
18!
588
            nodes_map.insert({node["element_id"], tasklet});
18!
589
        } else if (type == "library_node") {
74!
590
            assert(node.contains("code"));
×
591
            data_flow::LibraryNodeCode code(node["code"].get<std::string>());
×
592

593
            auto serializer_fn = LibraryNodeSerializerRegistry::instance().get_library_node_serializer(code.value());
×
594
            if (serializer_fn == nullptr) {
×
595
                throw std::runtime_error("Unknown library node code: " + std::string(code.value()));
×
596
            }
597
            auto serializer = serializer_fn();
×
598
            auto& lib_node = serializer->deserialize(node, builder, parent);
×
599
            lib_node.implementation_type() =
×
600
                data_flow::ImplementationType(node["implementation_type"].get<std::string>());
×
601
            lib_node.element_id_ = node["element_id"];
×
602
            nodes_map.insert({node["element_id"], lib_node});
×
603
        } else if (type == "access_node") {
56!
604
            assert(node.contains("data"));
56!
605
            auto& access_node = builder.add_access(parent, node["data"], json_to_debug_info(node["debug_info"]));
56!
606
            access_node.element_id_ = node["element_id"];
56!
607
            nodes_map.insert({node["element_id"], access_node});
56!
608
        } else if (type == "constant_node") {
56!
609
            assert(node.contains("data"));
×
610
            assert(node.contains("data_type"));
×
611

612
            auto type = json_to_type(node["data_type"]);
×
613

614
            auto& constant_node =
×
615
                builder.add_constant(parent, node["data"], *type, json_to_debug_info(node["debug_info"]));
×
616
            constant_node.element_id_ = node["element_id"];
×
617
            nodes_map.insert({node["element_id"], constant_node});
×
618
        } else {
×
619
            throw std::runtime_error("Unknown node type");
×
620
        }
621
    }
74✔
622

623
    assert(j.contains("edges"));
23!
624
    assert(j["edges"].is_array());
23!
625
    for (const auto& edge : j["edges"]) {
81!
626
        assert(edge.contains("src"));
58!
627
        assert(edge["src"].is_number_integer());
58!
628
        assert(edge.contains("dst"));
58!
629
        assert(edge["dst"].is_number_integer());
58!
630
        assert(edge.contains("src_conn"));
58!
631
        assert(edge["src_conn"].is_string());
58!
632
        assert(edge.contains("dst_conn"));
58!
633
        assert(edge["dst_conn"].is_string());
58!
634
        assert(edge.contains("subset"));
58!
635
        assert(edge["subset"].is_array());
58!
636

637
        assert(nodes_map.find(edge["src"]) != nodes_map.end());
58!
638
        assert(nodes_map.find(edge["dst"]) != nodes_map.end());
58!
639
        auto& source = nodes_map.at(edge["src"]);
58!
640
        auto& target = nodes_map.at(edge["dst"]);
58!
641

642
        auto base_type = json_to_type(edge["base_type"]);
58!
643

644
        assert(edge.contains("subset"));
58!
645
        assert(edge["subset"].is_array());
58!
646
        std::vector<symbolic::Expression> subset;
58✔
647
        for (const auto& subset_ : edge["subset"]) {
104!
648
            assert(subset_.is_string());
46!
649
            std::string subset_str = subset_;
46!
650
            auto expr = symbolic::parse(subset_str);
46!
651
            subset.push_back(expr);
46!
652
        }
46✔
653
        auto& memlet = builder.add_memlet(
116!
654
            parent,
58✔
655
            source,
58✔
656
            edge["src_conn"],
58!
657
            target,
58✔
658
            edge["dst_conn"],
58!
659
            subset,
660
            *base_type,
58✔
661
            json_to_debug_info(edge["debug_info"])
58!
662
        );
663
        memlet.element_id_ = edge["element_id"];
58!
664
    }
58✔
665
}
23✔
666

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

678
    sequence.element_id_ = j["element_id"];
30✔
679
    sequence.debug_info_ = json_to_debug_info(j["debug_info"]);
30✔
680

681
    std::string type = j["type"];
30✔
682
    if (type == "sequence") {
30!
683
        for (size_t i = 0; i < j["children"].size(); i++) {
67!
684
            auto& child = j["children"][i];
37!
685
            auto& transition = j["transitions"][i];
37!
686
            assert(child.contains("type"));
37!
687
            assert(child["type"].is_string());
37!
688

689
            assert(transition.contains("type"));
37!
690
            assert(transition["type"].is_string());
37!
691
            assert(transition.contains("assignments"));
37!
692
            assert(transition["assignments"].is_array());
37!
693
            control_flow::Assignments assignments;
37✔
694
            for (const auto& assignment : transition["assignments"]) {
39!
695
                assert(assignment.contains("symbol"));
2!
696
                assert(assignment["symbol"].is_string());
2!
697
                assert(assignment.contains("expression"));
2!
698
                assert(assignment["expression"].is_string());
2!
699
                auto expr = symbolic::parse(assignment["expression"].get<std::string>());
2!
700
                assignments.insert({symbolic::symbol(assignment["symbol"]), expr});
2!
701
            }
2✔
702

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

726
            sequence.at(i).second.debug_info_ = json_to_debug_info(transition["debug_info"]);
37!
727
            sequence.at(i).second.element_id_ = transition["element_id"];
37!
728
        }
37✔
729
    } else {
30✔
730
        throw std::runtime_error("expected sequence type");
×
731
    }
732
}
30✔
733

734
void JSONSerializer::json_to_block_node(
22✔
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"));
22!
741
    assert(j["type"].is_string());
22!
742
    assert(j.contains("dataflow"));
22!
743
    assert(j["dataflow"].is_object());
22!
744
    auto& block = builder.add_block(parent, assignments, json_to_debug_info(j["debug_info"]));
22!
745
    block.element_id_ = j["element_id"];
22✔
746
    assert(j["dataflow"].contains("type"));
22!
747
    assert(j["dataflow"]["type"].is_string());
22!
748
    std::string type = j["dataflow"]["type"];
22✔
749
    if (type == "dataflow") {
22!
750
        json_to_dataflow(j["dataflow"], builder, block);
22!
751
    } else {
22✔
752
        throw std::runtime_error("Unknown dataflow type");
×
753
    }
754
}
22✔
755

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

775
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
15!
776
    auto init = symbolic::parse(j["init"].get<std::string>());
15!
777
    auto update = symbolic::parse(j["update"].get<std::string>());
15!
778

779
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
15!
780
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
15!
781
    if (condition.is_null()) {
15!
782
        throw InvalidSDFGException("For loop condition is not a boolean expression");
×
783
    }
784

785
    auto& for_node =
15✔
786
        builder.add_for(parent, indvar, condition, init, update, assignments, json_to_debug_info(j["debug_info"]));
15!
787
    for_node.element_id_ = j["element_id"];
15!
788

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

795
void JSONSerializer::json_to_if_else_node(
1✔
796
    const nlohmann::json& j,
797
    builder::StructuredSDFGBuilder& builder,
798
    structured_control_flow::Sequence& parent,
799
    control_flow::Assignments& assignments
800
) {
801
    assert(j.contains("type"));
1!
802
    assert(j["type"].is_string());
1!
803
    assert(j["type"] == "if_else");
1!
804
    assert(j.contains("branches"));
1!
805
    assert(j["branches"].is_array());
1!
806
    auto& if_else_node = builder.add_if_else(parent, assignments, json_to_debug_info(j["debug_info"]));
1!
807
    if_else_node.element_id_ = j["element_id"];
1✔
808
    for (const auto& branch : j["branches"]) {
3✔
809
        assert(branch.contains("condition"));
2!
810
        assert(branch["condition"].is_string());
2!
811
        assert(branch.contains("root"));
2!
812
        assert(branch["root"].is_object());
2!
813

814
        auto condition_expr = symbolic::parse(branch["condition"].get<std::string>());
2!
815
        symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
2!
816
        if (condition.is_null()) {
2!
817
            throw InvalidSDFGException("If condition is not a boolean expression");
×
818
        }
819
        auto& branch_node = builder.add_case(if_else_node, condition);
2!
820
        assert(branch["root"].contains("type"));
2!
821
        assert(branch["root"]["type"].is_string());
2!
822
        std::string type = branch["root"]["type"];
2!
823
        if (type == "sequence") {
2!
824
            json_to_sequence(branch["root"], builder, branch_node);
2!
825
        } else {
2✔
826
            throw std::runtime_error("Unknown child type");
×
827
        }
828
    }
2✔
829
}
1✔
830

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

843
    auto& while_node = builder.add_while(parent, assignments, json_to_debug_info(j["debug_info"]));
3!
844
    while_node.element_id_ = j["element_id"];
3✔
845

846
    assert(j["root"]["type"] == "sequence");
3!
847
    json_to_sequence(j["root"], builder, while_node.root());
3✔
848
}
3✔
849

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

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

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

898
    structured_control_flow::ScheduleType schedule_type = json_to_schedule_type(j["schedule_type"]);
1✔
899

900
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
1!
901
    auto init = symbolic::parse(j["init"].get<std::string>());
1!
902
    auto update = symbolic::parse(j["update"].get<std::string>());
1!
903
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
1!
904
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
1!
905
    if (condition.is_null()) {
1!
906
        throw InvalidSDFGException("Map condition is not a boolean expression");
×
907
    }
908

909
    auto& map_node = builder.add_map(
2!
910
        parent, indvar, condition, init, update, schedule_type, assignments, json_to_debug_info(j["debug_info"])
1!
911
    );
912
    map_node.element_id_ = j["element_id"];
1!
913

914
    assert(j["root"].contains("type"));
1!
915
    assert(j["root"]["type"].is_string());
1!
916
    assert(j["root"]["type"] == "sequence");
1!
917
    json_to_sequence(j["root"], builder, map_node.root());
1!
918
}
1✔
919

920
void JSONSerializer::json_to_return_node(
1✔
921
    const nlohmann::json& j,
922
    builder::StructuredSDFGBuilder& builder,
923
    structured_control_flow::Sequence& parent,
924
    control_flow::Assignments& assignments
925
) {
926
    assert(j.contains("type"));
1!
927
    assert(j["type"].is_string());
1!
928
    assert(j["type"] == "return");
1!
929

930
    std::string data = j["data"];
1✔
931
    std::unique_ptr<types::IType> data_type = nullptr;
1✔
932
    if (j.contains("data_type")) {
1!
933
        data_type = json_to_type(j["data_type"]);
×
934
    }
×
935

936
    if (data_type == nullptr) {
1!
937
        auto& node = builder.add_return(parent, data, assignments, json_to_debug_info(j["debug_info"]));
1!
938
        node.element_id_ = j["element_id"];
1!
939
    } else {
1✔
940
        auto& node =
×
941
            builder.add_constant_return(parent, data, *data_type, assignments, json_to_debug_info(j["debug_info"]));
×
942
        node.element_id_ = j["element_id"];
×
943
    }
944
}
1✔
945

946
std::unique_ptr<types::IType> JSONSerializer::json_to_type(const nlohmann::json& j) {
198✔
947
    if (j.contains("type")) {
198!
948
        if (j["type"] == "scalar") {
198✔
949
            // Deserialize scalar type
950
            assert(j.contains("primitive_type"));
125!
951
            types::PrimitiveType primitive_type = j["primitive_type"];
125✔
952
            assert(j.contains("storage_type"));
125!
953
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
125✔
954
            assert(j.contains("initializer"));
125!
955
            std::string initializer = j["initializer"];
125!
956
            assert(j.contains("alignment"));
125!
957
            size_t alignment = j["alignment"];
125!
958
            return std::make_unique<types::Scalar>(storage_type, alignment, initializer, primitive_type);
125!
959
        } else if (j["type"] == "array") {
198✔
960
            // Deserialize array type
961
            assert(j.contains("element_type"));
54!
962
            std::unique_ptr<types::IType> member_type = json_to_type(j["element_type"]);
54✔
963
            assert(j.contains("num_elements"));
54!
964
            std::string num_elements_str = j["num_elements"];
54!
965
            // Convert num_elements_str to symbolic::Expression
966
            auto num_elements = symbolic::parse(num_elements_str);
54!
967
            assert(j.contains("storage_type"));
54!
968
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
54!
969
            assert(j.contains("initializer"));
54!
970
            std::string initializer = j["initializer"];
54!
971
            assert(j.contains("alignment"));
54!
972
            size_t alignment = j["alignment"];
54!
973
            return std::make_unique<types::Array>(storage_type, alignment, initializer, *member_type, num_elements);
54!
974
        } else if (j["type"] == "pointer") {
73✔
975
            // Deserialize pointer type
976
            std::optional<std::unique_ptr<types::IType>> pointee_type;
16✔
977
            if (j.contains("pointee_type")) {
16!
978
                assert(j.contains("pointee_type"));
15!
979
                pointee_type = json_to_type(j["pointee_type"]);
15!
980
            } else {
15✔
981
                pointee_type = std::nullopt;
1✔
982
            }
983
            assert(j.contains("storage_type"));
16!
984
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
16!
985
            assert(j.contains("initializer"));
16!
986
            std::string initializer = j["initializer"];
16!
987
            assert(j.contains("alignment"));
16!
988
            size_t alignment = j["alignment"];
16!
989
            if (pointee_type.has_value()) {
16✔
990
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer, *pointee_type.value());
15!
991
            } else {
992
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer);
1!
993
            }
994
        } else if (j["type"] == "structure") {
19✔
995
            // Deserialize structure type
996
            assert(j.contains("name"));
2!
997
            std::string name = j["name"];
2✔
998
            assert(j.contains("storage_type"));
2!
999
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
2!
1000
            assert(j.contains("initializer"));
2!
1001
            std::string initializer = j["initializer"];
2!
1002
            assert(j.contains("alignment"));
2!
1003
            size_t alignment = j["alignment"];
2!
1004
            return std::make_unique<types::Structure>(storage_type, alignment, initializer, name);
2!
1005
        } else if (j["type"] == "function") {
3!
1006
            // Deserialize function type
1007
            assert(j.contains("return_type"));
1!
1008
            std::unique_ptr<types::IType> return_type = json_to_type(j["return_type"]);
1✔
1009
            assert(j.contains("params"));
1!
1010
            std::vector<std::unique_ptr<types::IType>> params;
1✔
1011
            for (const auto& param : j["params"]) {
3!
1012
                params.push_back(json_to_type(param));
2!
1013
            }
1014
            assert(j.contains("is_var_arg"));
1!
1015
            bool is_var_arg = j["is_var_arg"];
1!
1016
            assert(j.contains("storage_type"));
1!
1017
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
1!
1018
            assert(j.contains("initializer"));
1!
1019
            std::string initializer = j["initializer"];
1!
1020
            assert(j.contains("alignment"));
1!
1021
            size_t alignment = j["alignment"];
1!
1022
            auto function =
1023
                std::make_unique<types::Function>(storage_type, alignment, initializer, *return_type, is_var_arg);
1!
1024
            for (const auto& param : params) {
3✔
1025
                function->add_param(*param);
2!
1026
            }
1027
            return function->clone();
1!
1028

1029
        } else {
1✔
1030
            throw std::runtime_error("Unknown type");
×
1031
        }
1032
    } else {
1033
        throw std::runtime_error("Type not found");
×
1034
    }
1035
}
198✔
1036

1037
DebugInfo JSONSerializer::json_to_debug_info(const nlohmann::json& j) {
244✔
1038
    assert(j.contains("has"));
244!
1039
    assert(j["has"].is_boolean());
244!
1040
    if (!j["has"]) {
244!
1041
        return DebugInfo();
244✔
1042
    }
1043
    assert(j.contains("filename"));
×
1044
    assert(j["filename"].is_string());
×
1045
    std::string filename = j["filename"];
×
1046
    assert(j.contains("function"));
×
1047
    assert(j["function"].is_string());
×
1048
    std::string function = j["function"];
×
1049
    assert(j.contains("start_line"));
×
1050
    assert(j["start_line"].is_number_integer());
×
1051
    size_t start_line = j["start_line"];
×
1052
    assert(j.contains("start_column"));
×
1053
    assert(j["start_column"].is_number_integer());
×
1054
    size_t start_column = j["start_column"];
×
1055
    assert(j.contains("end_line"));
×
1056
    assert(j["end_line"].is_number_integer());
×
1057
    size_t end_line = j["end_line"];
×
1058
    assert(j.contains("end_column"));
×
1059
    assert(j["end_column"].is_number_integer());
×
1060
    size_t end_column = j["end_column"];
×
1061
    return DebugInfo(filename, function, start_line, start_column, end_line, end_column);
×
1062
}
244✔
1063

1064
ScheduleType JSONSerializer::json_to_schedule_type(const nlohmann::json& j) {
2✔
1065
    assert(j.contains("value"));
2!
1066
    assert(j["value"].is_string());
2!
1067
    assert(j.contains("properties"));
2!
1068
    assert(j["properties"].is_object());
2!
1069
    ScheduleType schedule_type(j["value"].get<std::string>());
2!
1070
    for (const auto& [key, value] : j["properties"].items()) {
4!
1071
        assert(value.is_string());
1!
1072
        schedule_type.set_property(key, value.get<std::string>());
1!
1073
    }
1074
    return schedule_type;
2✔
1075
}
2!
1076

1077
types::StorageType JSONSerializer::json_to_storage_type(const nlohmann::json& j) {
198✔
1078
    if (!j.contains("value")) {
198!
1079
        return types::StorageType::CPU_Stack();
×
1080
    }
1081
    std::string value = j["value"].get<std::string>();
198✔
1082

1083
    symbolic::Expression allocation_size = SymEngine::null;
198!
1084
    if (j.contains("allocation_size")) {
198!
1085
        allocation_size = symbolic::parse(j["allocation_size"].get<std::string>());
×
1086
    }
×
1087

1088
    types::StorageType::AllocationType allocation = j["allocation"];
198!
1089
    types::StorageType::AllocationType deallocation = j["deallocation"];
198!
1090

1091
    auto storageType = types::StorageType(j["value"].get<std::string>(), allocation_size, allocation, deallocation);
198!
1092

1093
    if (j.contains("args")) {
198!
1094
        nlohmann::json::array_t args = j["args"];
×
1095
        if (args.size() > 0) {
×
1096
            storageType.arg1(symbolic::parse(args[0].get<std::string>()));
×
1097
        }
×
1098
    }
×
1099
    return storageType;
198✔
1100
}
198!
1101

1102
std::string JSONSerializer::expression(const symbolic::Expression expr) {
187✔
1103
    JSONSymbolicPrinter printer;
187✔
1104
    return printer.apply(expr);
187!
1105
};
187✔
1106

1107
void JSONSymbolicPrinter::bvisit(const SymEngine::Equality& x) {
×
1108
    str_ = apply(x.get_args()[0]) + " == " + apply(x.get_args()[1]);
×
1109
    str_ = parenthesize(str_);
×
1110
};
×
1111

1112
void JSONSymbolicPrinter::bvisit(const SymEngine::Unequality& x) {
×
1113
    str_ = apply(x.get_args()[0]) + " != " + apply(x.get_args()[1]);
×
1114
    str_ = parenthesize(str_);
×
1115
};
×
1116

1117
void JSONSymbolicPrinter::bvisit(const SymEngine::LessThan& x) {
×
1118
    str_ = apply(x.get_args()[0]) + " <= " + apply(x.get_args()[1]);
×
1119
    str_ = parenthesize(str_);
×
1120
};
×
1121

1122
void JSONSymbolicPrinter::bvisit(const SymEngine::StrictLessThan& x) {
18✔
1123
    str_ = apply(x.get_args()[0]) + " < " + apply(x.get_args()[1]);
18!
1124
    str_ = parenthesize(str_);
18✔
1125
};
18✔
1126

1127
void JSONSymbolicPrinter::bvisit(const SymEngine::Min& x) {
×
1128
    std::ostringstream s;
×
1129
    auto container = x.get_args();
×
1130
    if (container.size() == 1) {
×
1131
        s << apply(*container.begin());
×
1132
    } else {
×
1133
        s << "min(";
×
1134
        s << apply(*container.begin());
×
1135

1136
        // Recursively apply __daisy_min to the arguments
1137
        SymEngine::vec_basic subargs;
×
1138
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1139
            subargs.push_back(*it);
×
1140
        }
×
1141
        auto submin = SymEngine::min(subargs);
×
1142
        s << ", " << apply(submin);
×
1143

1144
        s << ")";
×
1145
    }
×
1146

1147
    str_ = s.str();
×
1148
};
×
1149

1150
void JSONSymbolicPrinter::bvisit(const SymEngine::Max& x) {
×
1151
    std::ostringstream s;
×
1152
    auto container = x.get_args();
×
1153
    if (container.size() == 1) {
×
1154
        s << apply(*container.begin());
×
1155
    } else {
×
1156
        s << "max(";
×
1157
        s << apply(*container.begin());
×
1158

1159
        // Recursively apply __daisy_max to the arguments
1160
        SymEngine::vec_basic subargs;
×
1161
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1162
            subargs.push_back(*it);
×
1163
        }
×
1164
        auto submax = SymEngine::max(subargs);
×
1165
        s << ", " << apply(submax);
×
1166

1167
        s << ")";
×
1168
    }
×
1169

1170
    str_ = s.str();
×
1171
};
×
1172

1173
void LibraryNodeSerializerRegistry::
1174
    register_library_node_serializer(std::string library_node_code, LibraryNodeSerializerFn fn) {
62✔
1175
    std::lock_guard<std::mutex> lock(mutex_);
62✔
1176
    if (factory_map_.find(library_node_code) != factory_map_.end()) {
62!
1177
        throw std::runtime_error(
×
1178
            "Library node serializer already registered for library node code: " + std::string(library_node_code)
×
1179
        );
1180
    }
1181
    factory_map_[library_node_code] = std::move(fn);
62!
1182
}
62✔
1183

1184
LibraryNodeSerializerFn LibraryNodeSerializerRegistry::get_library_node_serializer(std::string library_node_code) {
1✔
1185
    auto it = factory_map_.find(library_node_code);
1✔
1186
    if (it != factory_map_.end()) {
1!
1187
        return it->second;
1✔
1188
    }
1189
    return nullptr;
×
1190
}
1✔
1191

1192
size_t LibraryNodeSerializerRegistry::size() const { return factory_map_.size(); }
×
1193

1194
void register_default_serializers() {
2✔
1195
    // stdlib
1196
    LibraryNodeSerializerRegistry::instance()
2✔
1197
        .register_library_node_serializer(stdlib::LibraryNodeType_Alloca.value(), []() {
2!
1198
            return std::make_unique<stdlib::AllocaNodeSerializer>();
×
1199
        });
1200
    LibraryNodeSerializerRegistry::instance()
2✔
1201
        .register_library_node_serializer(stdlib::LibraryNodeType_Calloc.value(), []() {
2!
1202
            return std::make_unique<stdlib::CallocNodeSerializer>();
×
1203
        });
1204
    LibraryNodeSerializerRegistry::instance()
2✔
1205
        .register_library_node_serializer(stdlib::LibraryNodeType_Free.value(), []() {
2!
1206
            return std::make_unique<stdlib::FreeNodeSerializer>();
×
1207
        });
1208
    LibraryNodeSerializerRegistry::instance()
2✔
1209
        .register_library_node_serializer(stdlib::LibraryNodeType_Malloc.value(), []() {
2!
1210
            return std::make_unique<stdlib::MallocNodeSerializer>();
×
1211
        });
1212
    LibraryNodeSerializerRegistry::instance()
2✔
1213
        .register_library_node_serializer(stdlib::LibraryNodeType_Memcpy.value(), []() {
2!
1214
            return std::make_unique<stdlib::MemcpyNodeSerializer>();
×
1215
        });
1216
    LibraryNodeSerializerRegistry::instance()
2✔
1217
        .register_library_node_serializer(stdlib::LibraryNodeType_Memmove.value(), []() {
2!
1218
            return std::make_unique<stdlib::MemmoveNodeSerializer>();
×
1219
        });
1220
    LibraryNodeSerializerRegistry::instance()
2✔
1221
        .register_library_node_serializer(stdlib::LibraryNodeType_Memset.value(), []() {
2!
1222
            return std::make_unique<stdlib::MemsetNodeSerializer>();
×
1223
        });
1224
    LibraryNodeSerializerRegistry::instance()
2✔
1225
        .register_library_node_serializer(stdlib::LibraryNodeType_Trap.value(), []() {
2!
1226
            return std::make_unique<stdlib::TrapNodeSerializer>();
×
1227
        });
1228
    LibraryNodeSerializerRegistry::instance()
2✔
1229
        .register_library_node_serializer(stdlib::LibraryNodeType_Unreachable.value(), []() {
2!
1230
            return std::make_unique<stdlib::UnreachableNodeSerializer>();
×
1231
        });
1232

1233
    // Metadata
1234
    LibraryNodeSerializerRegistry::instance()
2✔
1235
        .register_library_node_serializer(data_flow::LibraryNodeType_Metadata.value(), []() {
2!
1236
            return std::make_unique<data_flow::MetadataNodeSerializer>();
×
1237
        });
1238

1239
    // Barrier
1240
    LibraryNodeSerializerRegistry::instance()
2✔
1241
        .register_library_node_serializer(data_flow::LibraryNodeType_BarrierLocal.value(), []() {
3!
1242
            return std::make_unique<data_flow::BarrierLocalNodeSerializer>();
1✔
1243
        });
1244

1245
    // Call Node
1246
    LibraryNodeSerializerRegistry::instance()
2✔
1247
        .register_library_node_serializer(data_flow::LibraryNodeType_Call.value(), []() {
2!
1248
            return std::make_unique<data_flow::CallNodeSerializer>();
×
1249
        });
1250
    LibraryNodeSerializerRegistry::instance()
2✔
1251
        .register_library_node_serializer(data_flow::LibraryNodeType_Invoke.value(), []() {
2!
1252
            return std::make_unique<data_flow::InvokeNodeSerializer>();
×
1253
        });
1254

1255
    // CMath
1256
    LibraryNodeSerializerRegistry::instance()
2✔
1257
        .register_library_node_serializer(math::cmath::LibraryNodeType_CMath.value(), []() {
2!
NEW
1258
            return std::make_unique<math::cmath::CMathNodeSerializer>();
×
1259
        });
1260

1261
    // BLAS
1262
    LibraryNodeSerializerRegistry::instance()
2✔
1263
        .register_library_node_serializer(math::blas::LibraryNodeType_DOT.value(), []() {
2!
1264
            return std::make_unique<math::blas::DotNodeSerializer>();
×
1265
        });
1266
    LibraryNodeSerializerRegistry::instance()
2✔
1267
        .register_library_node_serializer(math::blas::LibraryNodeType_GEMM.value(), []() {
2!
1268
            return std::make_unique<math::blas::GEMMNodeSerializer>();
×
1269
        });
1270

1271
    // Tensor
1272

1273
    // Elementwise
1274
    LibraryNodeSerializerRegistry::instance()
2✔
1275
        .register_library_node_serializer(math::tensor::LibraryNodeType_Abs.value(), []() {
2!
NEW
1276
            return std::make_unique<math::tensor::AbsNodeSerializer>();
×
1277
        });
1278
    LibraryNodeSerializerRegistry::instance()
2✔
1279
        .register_library_node_serializer(math::tensor::LibraryNodeType_Add.value(), []() {
2!
NEW
1280
            return std::make_unique<math::tensor::AddNodeSerializer>();
×
1281
        });
1282
    LibraryNodeSerializerRegistry::instance()
2✔
1283
        .register_library_node_serializer(math::tensor::LibraryNodeType_Div.value(), []() {
2!
NEW
1284
            return std::make_unique<math::tensor::DivNodeSerializer>();
×
1285
        });
1286
    LibraryNodeSerializerRegistry::instance()
2✔
1287
        .register_library_node_serializer(math::tensor::LibraryNodeType_Elu.value(), []() {
2!
NEW
1288
            return std::make_unique<math::tensor::EluNodeSerializer>();
×
1289
        });
1290
    LibraryNodeSerializerRegistry::instance()
2✔
1291
        .register_library_node_serializer(math::tensor::LibraryNodeType_Erf.value(), []() {
2!
NEW
1292
            return std::make_unique<math::tensor::ErfNodeSerializer>();
×
1293
        });
1294
    LibraryNodeSerializerRegistry::instance()
2✔
1295
        .register_library_node_serializer(math::tensor::LibraryNodeType_HardSigmoid.value(), []() {
2!
NEW
1296
            return std::make_unique<math::tensor::HardSigmoidNodeSerializer>();
×
1297
        });
1298
    LibraryNodeSerializerRegistry::instance()
2✔
1299
        .register_library_node_serializer(math::tensor::LibraryNodeType_LeakyReLU.value(), []() {
2!
NEW
1300
            return std::make_unique<math::tensor::LeakyReLUNodeSerializer>();
×
1301
        });
1302
    LibraryNodeSerializerRegistry::instance()
2✔
1303
        .register_library_node_serializer(math::tensor::LibraryNodeType_Mul.value(), []() {
2!
NEW
1304
            return std::make_unique<math::tensor::MulNodeSerializer>();
×
1305
        });
1306
    LibraryNodeSerializerRegistry::instance()
2✔
1307
        .register_library_node_serializer(math::tensor::LibraryNodeType_Pow.value(), []() {
2!
NEW
1308
            return std::make_unique<math::tensor::PowNodeSerializer>();
×
1309
        });
1310
    LibraryNodeSerializerRegistry::instance()
2✔
1311
        .register_library_node_serializer(math::tensor::LibraryNodeType_ReLU.value(), []() {
2!
NEW
1312
            return std::make_unique<math::tensor::ReLUNodeSerializer>();
×
1313
        });
1314
    LibraryNodeSerializerRegistry::instance()
2✔
1315
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sigmoid.value(), []() {
2!
NEW
1316
            return std::make_unique<math::tensor::SigmoidNodeSerializer>();
×
1317
        });
1318
    LibraryNodeSerializerRegistry::instance()
2✔
1319
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sqrt.value(), []() {
2!
NEW
1320
            return std::make_unique<math::tensor::SqrtNodeSerializer>();
×
1321
        });
1322
    LibraryNodeSerializerRegistry::instance()
2✔
1323
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sub.value(), []() {
2!
NEW
1324
            return std::make_unique<math::tensor::SubNodeSerializer>();
×
1325
        });
1326
    LibraryNodeSerializerRegistry::instance()
2✔
1327
        .register_library_node_serializer(math::tensor::LibraryNodeType_Tanh.value(), []() {
2!
NEW
1328
            return std::make_unique<math::tensor::TanhNodeSerializer>();
×
1329
        });
1330

1331
    // Reduce
1332
    LibraryNodeSerializerRegistry::instance()
2✔
1333
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sum.value(), []() {
2!
NEW
1334
            return std::make_unique<math::tensor::SumNodeSerializer>();
×
1335
        });
1336
}
2✔
1337

1338
} // namespace serializer
1339
} // 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

© 2025 Coveralls, Inc