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

daisytuner / docc / 27956659323

22 Jun 2026 01:34PM UTC coverage: 61.757% (-0.03%) from 61.782%
27956659323

Pull #802

github

web-flow
Merge acd09dfa2 into fe87d162b
Pull Request #802: adds reduce as new structured loop type

284 of 481 new or added lines in 14 files covered. (59.04%)

1 existing line in 1 file now uncovered.

37423 of 60597 relevant lines covered (61.76%)

1006.67 hits per line

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

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

3
#include <cassert>
4
#include <memory>
5
#include <sdfg/data_flow/library_nodes/load_const_node.h>
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/call_node.h"
11
#include "sdfg/data_flow/library_nodes/invoke_node.h"
12
#include "sdfg/data_flow/library_nodes/math/math.h"
13
#include "sdfg/data_flow/library_nodes/math/tensor/elementwise_ops/cmath_node.h"
14
#include "sdfg/data_flow/library_nodes/math/tensor/elementwise_ops/tasklet_node.h"
15
#include "sdfg/data_flow/library_nodes/metadata_node.h"
16
#include "sdfg/data_flow/library_nodes/stdlib/stdlib.h"
17

18
#include "sdfg/analysis/users.h"
19
#include "sdfg/builder/structured_sdfg_builder.h"
20
#include "sdfg/data_flow/library_node.h"
21
#include "sdfg/data_flow/library_nodes/math/tensor/batchnorm_node.h"
22
#include "sdfg/element.h"
23
#include "sdfg/structured_control_flow/block.h"
24
#include "sdfg/structured_control_flow/for.h"
25
#include "sdfg/structured_control_flow/if_else.h"
26
#include "sdfg/structured_control_flow/map.h"
27
#include "sdfg/structured_control_flow/reduce.h"
28
#include "sdfg/structured_control_flow/return.h"
29
#include "sdfg/structured_control_flow/sequence.h"
30
#include "sdfg/structured_control_flow/while.h"
31
#include "sdfg/structured_sdfg.h"
32
#include "sdfg/symbolic/symbolic.h"
33
#include "sdfg/types/function.h"
34
#include "sdfg/types/scalar.h"
35
#include "sdfg/types/type.h"
36
#include "symengine/expression.h"
37
#include "symengine/logic.h"
38
#include "symengine/symengine_rcp.h"
39

40
namespace sdfg {
41
namespace serializer {
42

43
FunctionType function_type_from_string(const std::string& str) {
28✔
44
    if (str == FunctionType_CPU.value()) {
28✔
45
        return FunctionType_CPU;
28✔
46
    } else if (str == FunctionType_NV_GLOBAL.value()) {
28✔
47
        return FunctionType_NV_GLOBAL;
×
48
    }
×
49

50
    return FunctionType(str);
×
51
}
28✔
52

53
/*
54
 * * JSONSerializer class
55
 * * Serialization logic
56
 */
57

58
nlohmann::json JSONSerializer::serialize(
59
    const sdfg::StructuredSDFG& sdfg,
60
    analysis::AnalysisManager* analysis_manager,
61
    structured_control_flow::Sequence* root
62
) {
26✔
63
    nlohmann::json j;
26✔
64

65
    j["name"] = sdfg.name();
26✔
66
    j["element_counter"] = sdfg.element_counter();
26✔
67
    j["type"] = std::string(sdfg.type().value());
26✔
68

69
    nlohmann::json return_type_json;
26✔
70
    type_to_json(return_type_json, sdfg.return_type());
26✔
71
    j["return_type"] = return_type_json;
26✔
72

73
    j["structures"] = nlohmann::json::array();
26✔
74
    for (const auto& structure_name : sdfg.structures()) {
26✔
75
        const auto& structure = sdfg.structure(structure_name);
1✔
76
        nlohmann::json structure_json;
1✔
77
        structure_definition_to_json(structure_json, structure);
1✔
78
        j["structures"].push_back(structure_json);
1✔
79
    }
1✔
80

81
    j["containers"] = nlohmann::json::object();
26✔
82
    for (const auto& container : sdfg.containers()) {
146✔
83
        nlohmann::json desc;
146✔
84
        type_to_json(desc, sdfg.type(container));
146✔
85
        j["containers"][container] = desc;
146✔
86
    }
146✔
87

88
    j["arguments"] = nlohmann::json::array();
26✔
89
    for (const auto& argument : sdfg.arguments()) {
31✔
90
        j["arguments"].push_back(argument);
31✔
91
    }
31✔
92

93
    j["externals"] = nlohmann::json::array();
26✔
94
    for (const auto& external : sdfg.externals()) {
26✔
95
        nlohmann::json external_json;
8✔
96
        external_json["name"] = external;
8✔
97
        external_json["linkage_type"] = sdfg.linkage_type(external);
8✔
98
        j["externals"].push_back(external_json);
8✔
99
    }
8✔
100

101
    j["metadata"] = nlohmann::json::object();
26✔
102
    for (const auto& entry : sdfg.metadata()) {
26✔
103
        j["metadata"][entry.first] = entry.second;
1✔
104
    }
1✔
105

106
    // Walk the SDFG
107
    nlohmann::json root_json;
26✔
108
    sequence_to_json(root_json, sdfg.root());
26✔
109
    j["root"] = root_json;
26✔
110

111
    return j;
26✔
112
}
26✔
113

114
void JSONSerializer::dataflow_to_json(nlohmann::json& j, const data_flow::DataFlowGraph& dataflow) {
56✔
115
    j["type"] = "dataflow";
56✔
116
    j["nodes"] = nlohmann::json::array();
56✔
117
    j["edges"] = nlohmann::json::array();
56✔
118

119
    for (auto& node : dataflow.nodes()) {
211✔
120
        nlohmann::json node_json;
211✔
121
        node_json["element_id"] = node.element_id();
211✔
122

123
        node_json["debug_info"] = nlohmann::json::object();
211✔
124
        debug_info_to_json(node_json["debug_info"], node.debug_info());
211✔
125

126
        if (auto tasklet = dynamic_cast<const data_flow::Tasklet*>(&node)) {
211✔
127
            node_json["type"] = "tasklet";
62✔
128
            node_json["code"] = tasklet->code();
62✔
129
            node_json["inputs"] = nlohmann::json::array();
62✔
130
            for (auto& input : tasklet->inputs()) {
104✔
131
                node_json["inputs"].push_back(input);
104✔
132
            }
104✔
133
            node_json["output"] = tasklet->output();
62✔
134
        } else if (auto lib_node = dynamic_cast<const data_flow::LibraryNode*>(&node)) {
149✔
135
            node_json["type"] = "library_node";
8✔
136
            node_json["implementation_type"] = std::string(lib_node->implementation_type().value());
8✔
137
            auto serializer_fn =
8✔
138
                LibraryNodeSerializerRegistry::instance().get_library_node_serializer(lib_node->code().value());
8✔
139
            if (serializer_fn == nullptr) {
8✔
140
                throw std::runtime_error("Unknown library node code: " + std::string(lib_node->code().value()));
×
141
            }
×
142
            auto serializer = serializer_fn();
8✔
143
            auto lib_node_json = serializer->serialize(*lib_node);
8✔
144
            node_json.merge_patch(lib_node_json);
8✔
145
        } else if (auto code_node = dynamic_cast<const data_flow::ConstantNode*>(&node)) {
141✔
146
            node_json["type"] = "constant_node";
×
147
            node_json["data"] = code_node->data();
×
148

149
            nlohmann::json type_json;
×
150
            type_to_json(type_json, code_node->type());
×
151
            node_json["data_type"] = type_json;
×
152
        } else if (auto code_node = dynamic_cast<const data_flow::AccessNode*>(&node)) {
141✔
153
            node_json["type"] = "access_node";
141✔
154
            node_json["data"] = code_node->data();
141✔
155
        } else {
141✔
156
            throw std::runtime_error("Unknown node type");
×
157
        }
×
158

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

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

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

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

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

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

180
        nlohmann::json base_type_json;
186✔
181
        type_to_json(base_type_json, edge.base_type());
186✔
182
        edge_json["base_type"] = base_type_json;
186✔
183

184
        j["edges"].push_back(edge_json);
186✔
185
    }
186✔
186
}
56✔
187

188
void JSONSerializer::block_to_json(nlohmann::json& j, const structured_control_flow::Block& block) {
53✔
189
    j["type"] = "block";
53✔
190
    j["element_id"] = block.element_id();
53✔
191

192
    j["debug_info"] = nlohmann::json::object();
53✔
193
    debug_info_to_json(j["debug_info"], block.debug_info());
53✔
194

195
    nlohmann::json dataflow_json;
53✔
196
    dataflow_to_json(dataflow_json, block.dataflow());
53✔
197
    j["dataflow"] = dataflow_json;
53✔
198
}
53✔
199

200
void JSONSerializer::for_to_json(nlohmann::json& j, const structured_control_flow::For& for_node) {
21✔
201
    j["type"] = "for";
21✔
202
    j["element_id"] = for_node.element_id();
21✔
203

204
    j["debug_info"] = nlohmann::json::object();
21✔
205
    debug_info_to_json(j["debug_info"], for_node.debug_info());
21✔
206

207
    j["indvar"] = expression(for_node.indvar());
21✔
208
    j["init"] = expression(for_node.init());
21✔
209
    j["condition"] = expression(for_node.condition());
21✔
210
    j["update"] = expression(for_node.update());
21✔
211

212
    nlohmann::json body_json;
21✔
213
    sequence_to_json(body_json, for_node.root());
21✔
214
    j["root"] = body_json;
21✔
215
}
21✔
216

217
void JSONSerializer::if_else_to_json(nlohmann::json& j, const structured_control_flow::IfElse& if_else_node) {
2✔
218
    j["type"] = "if_else";
2✔
219
    j["element_id"] = if_else_node.element_id();
2✔
220

221
    j["debug_info"] = nlohmann::json::object();
2✔
222
    debug_info_to_json(j["debug_info"], if_else_node.debug_info());
2✔
223

224
    j["branches"] = nlohmann::json::array();
2✔
225
    for (size_t i = 0; i < if_else_node.size(); i++) {
6✔
226
        nlohmann::json branch_json;
4✔
227
        branch_json["condition"] = expression(if_else_node.at(i).second);
4✔
228
        nlohmann::json body_json;
4✔
229
        sequence_to_json(body_json, if_else_node.at(i).first);
4✔
230
        branch_json["root"] = body_json;
4✔
231
        j["branches"].push_back(branch_json);
4✔
232
    }
4✔
233
}
2✔
234

235
void JSONSerializer::while_node_to_json(nlohmann::json& j, const structured_control_flow::While& while_node) {
5✔
236
    j["type"] = "while";
5✔
237
    j["element_id"] = while_node.element_id();
5✔
238

239
    j["debug_info"] = nlohmann::json::object();
5✔
240
    debug_info_to_json(j["debug_info"], while_node.debug_info());
5✔
241

242
    nlohmann::json body_json;
5✔
243
    sequence_to_json(body_json, while_node.root());
5✔
244
    j["root"] = body_json;
5✔
245
}
5✔
246

247
void JSONSerializer::break_node_to_json(nlohmann::json& j, const structured_control_flow::Break& break_node) {
2✔
248
    j["type"] = "break";
2✔
249
    j["element_id"] = break_node.element_id();
2✔
250

251
    j["debug_info"] = nlohmann::json::object();
2✔
252
    debug_info_to_json(j["debug_info"], break_node.debug_info());
2✔
253
}
2✔
254

255
void JSONSerializer::continue_node_to_json(nlohmann::json& j, const structured_control_flow::Continue& continue_node) {
2✔
256
    j["type"] = "continue";
2✔
257
    j["element_id"] = continue_node.element_id();
2✔
258

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

263
void JSONSerializer::map_to_json(nlohmann::json& j, const structured_control_flow::Map& map_node) {
8✔
264
    j["type"] = "map";
8✔
265
    j["element_id"] = map_node.element_id();
8✔
266

267
    j["debug_info"] = nlohmann::json::object();
8✔
268
    debug_info_to_json(j["debug_info"], map_node.debug_info());
8✔
269

270
    j["indvar"] = expression(map_node.indvar());
8✔
271
    j["init"] = expression(map_node.init());
8✔
272
    j["condition"] = expression(map_node.condition());
8✔
273
    j["update"] = expression(map_node.update());
8✔
274

275
    j["schedule_type"] = nlohmann::json::object();
8✔
276
    schedule_type_to_json(j["schedule_type"], map_node.schedule_type());
8✔
277

278
    nlohmann::json body_json;
8✔
279
    sequence_to_json(body_json, map_node.root());
8✔
280
    j["root"] = body_json;
8✔
281
}
8✔
282

283
void JSONSerializer::reduce_to_json(nlohmann::json& j, const structured_control_flow::Reduce& reduce_node) {
2✔
284
    j["type"] = "reduce";
2✔
285
    j["element_id"] = reduce_node.element_id();
2✔
286

287
    j["debug_info"] = nlohmann::json::object();
2✔
288
    debug_info_to_json(j["debug_info"], reduce_node.debug_info());
2✔
289

290
    j["indvar"] = expression(reduce_node.indvar());
2✔
291
    j["init"] = expression(reduce_node.init());
2✔
292
    j["condition"] = expression(reduce_node.condition());
2✔
293
    j["update"] = expression(reduce_node.update());
2✔
294

295
    j["reductions"] = nlohmann::json::array();
2✔
296
    for (const auto& reduction : reduce_node.reductions()) {
2✔
297
        nlohmann::json reduction_json;
2✔
298
        reduction_json["op"] = structured_control_flow::reduction_operation_to_string(reduction.operation);
2✔
299
        reduction_json["container"] = reduction.container;
2✔
300
        j["reductions"].push_back(reduction_json);
2✔
301
    }
2✔
302

303
    j["schedule_type"] = nlohmann::json::object();
2✔
304
    schedule_type_to_json(j["schedule_type"], reduce_node.schedule_type());
2✔
305

306
    nlohmann::json body_json;
2✔
307
    sequence_to_json(body_json, reduce_node.root());
2✔
308
    j["root"] = body_json;
2✔
309
}
2✔
310

311
void JSONSerializer::return_node_to_json(nlohmann::json& j, const structured_control_flow::Return& return_node) {
2✔
312
    j["type"] = "return";
2✔
313
    j["element_id"] = return_node.element_id();
2✔
314
    j["data"] = return_node.data();
2✔
315

316
    if (return_node.is_constant()) {
2✔
317
        nlohmann::json type_json;
×
318
        type_to_json(type_json, return_node.type());
×
319
        j["data_type"] = type_json;
×
320
    }
×
321

322
    j["debug_info"] = nlohmann::json::object();
2✔
323
    debug_info_to_json(j["debug_info"], return_node.debug_info());
2✔
324
}
2✔
325

326
void JSONSerializer::sequence_to_json(nlohmann::json& j, const structured_control_flow::Sequence& sequence) {
71✔
327
    j["type"] = "sequence";
71✔
328
    j["element_id"] = sequence.element_id();
71✔
329

330
    j["debug_info"] = nlohmann::json::object();
71✔
331
    debug_info_to_json(j["debug_info"], sequence.debug_info());
71✔
332

333
    j["children"] = nlohmann::json::array();
71✔
334
    j["transitions"] = nlohmann::json::array();
71✔
335

336
    for (size_t i = 0; i < sequence.size(); i++) {
151✔
337
        nlohmann::json child_json;
80✔
338
        auto& child = sequence.at(i).first;
80✔
339
        auto& transition = sequence.at(i).second;
80✔
340

341
        if (auto block = dynamic_cast<const structured_control_flow::Block*>(&child)) {
80✔
342
            block_to_json(child_json, *block);
51✔
343
        } else if (auto for_node = dynamic_cast<const structured_control_flow::For*>(&child)) {
51✔
344
            for_to_json(child_json, *for_node);
19✔
345
        } else if (auto sequence_node = dynamic_cast<const structured_control_flow::Sequence*>(&child)) {
19✔
346
            sequence_to_json(child_json, *sequence_node);
×
347
        } else if (auto condition_node = dynamic_cast<const structured_control_flow::IfElse*>(&child)) {
10✔
348
            if_else_to_json(child_json, *condition_node);
×
349
        } else if (auto while_node = dynamic_cast<const structured_control_flow::While*>(&child)) {
10✔
350
            while_node_to_json(child_json, *while_node);
×
351
        } else if (auto return_node = dynamic_cast<const structured_control_flow::Return*>(&child)) {
10✔
352
            return_node_to_json(child_json, *return_node);
×
353
        } else if (auto break_node = dynamic_cast<const structured_control_flow::Break*>(&child)) {
10✔
354
            break_node_to_json(child_json, *break_node);
2✔
355
        } else if (auto continue_node = dynamic_cast<const structured_control_flow::Continue*>(&child)) {
8✔
356
            continue_node_to_json(child_json, *continue_node);
2✔
357
        } else if (auto map_node = dynamic_cast<const structured_control_flow::Map*>(&child)) {
6✔
358
            map_to_json(child_json, *map_node);
6✔
359
        } else if (auto reduce_node = dynamic_cast<const structured_control_flow::Reduce*>(&child)) {
6✔
NEW
360
            reduce_to_json(child_json, *reduce_node);
×
361
        } else {
×
362
            throw std::runtime_error("Unknown child type");
×
363
        }
×
364

365
        j["children"].push_back(child_json);
80✔
366

367
        // Add transition information
368
        nlohmann::json transition_json;
80✔
369
        transition_json["type"] = "transition";
80✔
370
        transition_json["element_id"] = transition.element_id();
80✔
371

372
        transition_json["debug_info"] = nlohmann::json::object();
80✔
373
        debug_info_to_json(transition_json["debug_info"], transition.debug_info());
80✔
374

375
        transition_json["assignments"] = nlohmann::json::array();
80✔
376
        for (const auto& assignment : transition.assignments()) {
80✔
377
            nlohmann::json assignment_json;
3✔
378
            assignment_json["symbol"] = expression(assignment.first);
3✔
379
            assignment_json["expression"] = expression(assignment.second);
3✔
380
            transition_json["assignments"].push_back(assignment_json);
3✔
381
        }
3✔
382

383
        j["transitions"].push_back(transition_json);
80✔
384
    }
80✔
385
}
71✔
386

387
void JSONSerializer::type_to_json(nlohmann::json& j, const types::IType& type) {
574✔
388
    if (auto scalar_type = dynamic_cast<const types::Scalar*>(&type)) {
574✔
389
        j["type"] = "scalar";
417✔
390
        j["primitive_type"] = scalar_type->primitive_type();
417✔
391
        j["storage_type"] = nlohmann::json::object();
417✔
392
        storage_type_to_json(j["storage_type"], scalar_type->storage_type());
417✔
393
        j["initializer"] = scalar_type->initializer();
417✔
394
        j["alignment"] = scalar_type->alignment();
417✔
395
    } else if (auto array_type = dynamic_cast<const types::Array*>(&type)) {
417✔
396
        j["type"] = "array";
79✔
397
        nlohmann::json element_type_json;
79✔
398
        type_to_json(element_type_json, array_type->element_type());
79✔
399
        j["element_type"] = element_type_json;
79✔
400
        j["num_elements"] = expression(array_type->num_elements());
79✔
401
        j["storage_type"] = nlohmann::json::object();
79✔
402
        storage_type_to_json(j["storage_type"], array_type->storage_type());
79✔
403
        j["initializer"] = array_type->initializer();
79✔
404
        j["alignment"] = array_type->alignment();
79✔
405
    } else if (auto pointer_type = dynamic_cast<const types::Pointer*>(&type)) {
79✔
406
        j["type"] = "pointer";
57✔
407
        if (pointer_type->has_pointee_type()) {
57✔
408
            nlohmann::json pointee_type_json;
56✔
409
            type_to_json(pointee_type_json, pointer_type->pointee_type());
56✔
410
            j["pointee_type"] = pointee_type_json;
56✔
411
        }
56✔
412
        j["storage_type"] = nlohmann::json::object();
57✔
413
        storage_type_to_json(j["storage_type"], pointer_type->storage_type());
57✔
414
        j["initializer"] = pointer_type->initializer();
57✔
415
        j["alignment"] = pointer_type->alignment();
57✔
416
    } else if (auto structure_type = dynamic_cast<const types::Structure*>(&type)) {
57✔
417
        j["type"] = "structure";
5✔
418
        j["name"] = structure_type->name();
5✔
419
        j["storage_type"] = nlohmann::json::object();
5✔
420
        storage_type_to_json(j["storage_type"], structure_type->storage_type());
5✔
421
        j["initializer"] = structure_type->initializer();
5✔
422
        j["alignment"] = structure_type->alignment();
5✔
423
    } else if (auto function_type = dynamic_cast<const types::Function*>(&type)) {
16✔
424
        j["type"] = "function";
5✔
425
        nlohmann::json return_type_json;
5✔
426
        type_to_json(return_type_json, function_type->return_type());
5✔
427
        j["return_type"] = return_type_json;
5✔
428
        j["params"] = nlohmann::json::array();
5✔
429
        for (size_t i = 0; i < function_type->num_params(); i++) {
16✔
430
            nlohmann::json param_json;
11✔
431
            type_to_json(param_json, function_type->param_type(symbolic::integer(i)));
11✔
432
            j["params"].push_back(param_json);
11✔
433
        }
11✔
434
        j["is_var_arg"] = function_type->is_var_arg();
5✔
435
        j["storage_type"] = nlohmann::json::object();
5✔
436
        storage_type_to_json(j["storage_type"], function_type->storage_type());
5✔
437
        j["initializer"] = function_type->initializer();
5✔
438
        j["alignment"] = function_type->alignment();
5✔
439
    } else if (auto reference_type = dynamic_cast<const sdfg::codegen::Reference*>(&type)) {
11✔
440
        j["type"] = "reference";
11✔
441
        nlohmann::json reference_type_json;
11✔
442
        type_to_json(reference_type_json, reference_type->reference_type());
11✔
443
        j["reference_type"] = reference_type_json;
11✔
444
    } else if (auto tensor_type = dynamic_cast<const types::Tensor*>(&type)) {
11✔
445
        j["type"] = "tensor";
×
446
        nlohmann::json element_type_json;
×
447
        type_to_json(element_type_json, tensor_type->element_type());
×
448
        j["element_type"] = element_type_json;
×
449
        j["shape"] = nlohmann::json::array();
×
450
        for (const auto& dim : tensor_type->shape()) {
×
451
            j["shape"].push_back(expression(dim));
×
452
        }
×
453
        j["strides"] = nlohmann::json::array();
×
454
        for (const auto& stride : tensor_type->strides()) {
×
455
            j["strides"].push_back(expression(stride));
×
456
        }
×
457
        j["offset"] = expression(tensor_type->offset());
×
458
        j["storage_type"] = nlohmann::json::object();
×
459
        storage_type_to_json(j["storage_type"], tensor_type->storage_type());
×
460
        j["initializer"] = tensor_type->initializer();
×
461
        j["alignment"] = tensor_type->alignment();
×
462
    } else {
×
463
        throw std::runtime_error("Unknown type");
×
464
    }
×
465
}
574✔
466

467
void JSONSerializer::structure_definition_to_json(nlohmann::json& j, const types::StructureDefinition& definition) {
2✔
468
    j["name"] = definition.name();
2✔
469
    j["members"] = nlohmann::json::array();
2✔
470
    for (size_t i = 0; i < definition.num_members(); i++) {
4✔
471
        nlohmann::json member_json;
2✔
472
        type_to_json(member_json, definition.member_type(symbolic::integer(i)));
2✔
473
        j["members"].push_back(member_json);
2✔
474
    }
2✔
475
    j["is_packed"] = definition.is_packed();
2✔
476
}
2✔
477

478
void JSONSerializer::debug_info_to_json(nlohmann::json& j, const DebugInfo& debug_info) {
645✔
479
    j["has"] = debug_info.has();
645✔
480
    j["filename"] = debug_info.filename();
645✔
481
    j["function"] = debug_info.function();
645✔
482
    j["start_line"] = debug_info.start_line();
645✔
483
    j["start_column"] = debug_info.start_column();
645✔
484
    j["end_line"] = debug_info.end_line();
645✔
485
    j["end_column"] = debug_info.end_column();
645✔
486
}
645✔
487

488

489
void JSONSerializer::schedule_type_to_json(nlohmann::json& j, const ScheduleType& schedule_type) {
12✔
490
    j["value"] = schedule_type.value();
12✔
491
    j["category"] = static_cast<int>(schedule_type.category());
12✔
492
    j["properties"] = nlohmann::json::object();
12✔
493
    for (const auto& prop : schedule_type.properties()) {
12✔
494
        j["properties"][prop.first] = prop.second;
4✔
495
    }
4✔
496
}
12✔
497

498
void JSONSerializer::storage_type_to_json(nlohmann::json& j, const types::StorageType& storage_type) {
576✔
499
    j["value"] = storage_type.value();
576✔
500
    j["allocation"] = storage_type.allocation();
576✔
501
    j["deallocation"] = storage_type.deallocation();
576✔
502
    if (!storage_type.allocation_size().is_null()) {
576✔
503
        j["allocation_size"] = expression(storage_type.allocation_size());
×
504
    }
×
505
    const symbolic::Expression& arg1 = storage_type.arg1();
576✔
506
    if (!arg1.is_null()) {
576✔
507
        auto args = nlohmann::json::array();
×
508
        args.push_back(expression(arg1));
×
509
        j["args"] = args;
×
510
    }
×
511
}
576✔
512

513

514
/*
515
 * * Deserialization logic
516
 */
517

518
std::unique_ptr<StructuredSDFG> JSONSerializer::deserialize(nlohmann::json& j) {
28✔
519
    assert(j.contains("name"));
28✔
520
    assert(j["name"].is_string());
28✔
521
    assert(j.contains("type"));
28✔
522
    assert(j["type"].is_string());
28✔
523
    assert(j.contains("element_counter"));
28✔
524
    assert(j["element_counter"].is_number_integer());
28✔
525

526
    std::unique_ptr<types::IType> return_type;
28✔
527
    if (j.contains("return_type")) {
28✔
528
        return_type = json_to_type(j["return_type"]);
28✔
529
    } else {
28✔
530
        return_type = std::make_unique<types::Scalar>(types::PrimitiveType::Void);
×
531
    }
×
532

533
    FunctionType function_type = function_type_from_string(j["type"].get<std::string>());
28✔
534
    builder::StructuredSDFGBuilder builder(j["name"], function_type, *return_type);
28✔
535

536
    size_t element_counter = j["element_counter"];
28✔
537
    builder.set_element_counter(element_counter);
28✔
538

539
    // deserialize structures
540
    assert(j.contains("structures"));
28✔
541
    assert(j["structures"].is_array());
28✔
542
    for (const auto& structure : j["structures"]) {
28✔
543
        assert(structure.contains("name"));
1✔
544
        assert(structure["name"].is_string());
1✔
545
        json_to_structure_definition(structure, builder);
1✔
546
    }
1✔
547

548
    nlohmann::json& containers = j["containers"];
28✔
549

550
    // deserialize externals
551
    for (const auto& external : j["externals"]) {
28✔
552
        assert(external.contains("name"));
9✔
553
        assert(external["name"].is_string());
9✔
554
        assert(external.contains("linkage_type"));
9✔
555
        assert(external["linkage_type"].is_number_integer());
9✔
556
        auto& type_desc = containers.at(external["name"].get<std::string>());
9✔
557
        auto type = json_to_type(type_desc);
9✔
558
        builder.add_external(external["name"], *type, LinkageType(external["linkage_type"]));
9✔
559
    }
9✔
560

561
    // deserialize arguments
562
    for (const auto& name : j["arguments"]) {
36✔
563
        auto& type_desc = containers.at(name.get<std::string>());
36✔
564
        auto type = json_to_type(type_desc);
36✔
565
        builder.add_container(name, *type, true, false);
36✔
566
    }
36✔
567

568
    // deserialize transients
569
    for (const auto& entry : containers.items()) {
156✔
570
        if (builder.subject().is_argument(entry.key())) {
156✔
571
            continue;
36✔
572
        }
36✔
573
        if (builder.subject().is_external(entry.key())) {
120✔
574
            continue;
9✔
575
        }
9✔
576
        auto type = json_to_type(entry.value());
111✔
577
        builder.add_container(entry.key(), *type, false, false);
111✔
578
    }
111✔
579

580
    // deserialize root node
581
    assert(j.contains("root"));
28✔
582
    auto& root = builder.subject().root();
28✔
583
    json_to_sequence(j["root"], builder, root);
28✔
584

585
    // deserialize metadata
586
    assert(j.contains("metadata"));
28✔
587
    assert(j["metadata"].is_object());
28✔
588
    for (const auto& entry : j["metadata"].items()) {
28✔
589
        builder.subject().add_metadata(entry.key(), entry.value());
1✔
590
    }
1✔
591

592
    builder.set_element_counter(element_counter);
28✔
593

594
    return builder.move();
28✔
595
}
28✔
596

597
void JSONSerializer::json_to_structure_definition(const nlohmann::json& j, builder::StructuredSDFGBuilder& builder) {
2✔
598
    assert(j.contains("name"));
2✔
599
    assert(j["name"].is_string());
2✔
600
    assert(j.contains("members"));
2✔
601
    assert(j["members"].is_array());
2✔
602
    assert(j.contains("is_packed"));
2✔
603
    assert(j["is_packed"].is_boolean());
2✔
604
    auto is_packed = j["is_packed"];
2✔
605
    auto& definition = builder.add_structure(j["name"], is_packed);
2✔
606
    for (const auto& member : j["members"]) {
2✔
607
        nlohmann::json member_json;
2✔
608
        auto member_type = json_to_type(member);
2✔
609
        definition.add_member(*member_type);
2✔
610
    }
2✔
611
}
2✔
612

613
std::vector<std::pair<std::string, types::Scalar>> JSONSerializer::json_to_arguments(const nlohmann::json& j) {
×
614
    std::vector<std::pair<std::string, types::Scalar>> arguments;
×
615
    for (const auto& argument : j) {
×
616
        assert(argument.contains("name"));
×
617
        assert(argument["name"].is_string());
×
618
        assert(argument.contains("type"));
×
619
        assert(argument["type"].is_object());
×
620
        std::string name = argument["name"];
×
621
        auto type = json_to_type(argument["type"]);
×
622
        arguments.emplace_back(name, *dynamic_cast<types::Scalar*>(type.get()));
×
623
    }
×
624
    return arguments;
×
625
}
×
626

627
void JSONSerializer::json_to_dataflow(
628
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Block& parent
629
) {
45✔
630
    std::map<size_t, data_flow::DataFlowNode&> nodes_map;
45✔
631

632
    assert(j.contains("nodes"));
45✔
633
    assert(j["nodes"].is_array());
45✔
634
    for (const auto& node : j["nodes"]) {
207✔
635
        assert(node.contains("type"));
207✔
636
        assert(node["type"].is_string());
207✔
637
        assert(node.contains("element_id"));
207✔
638
        assert(node["element_id"].is_number_integer());
207✔
639
        std::string type = node["type"];
207✔
640
        if (type == "tasklet") {
207✔
641
            assert(node.contains("code"));
61✔
642
            assert(node["code"].is_number_integer());
61✔
643
            assert(node.contains("inputs"));
61✔
644
            assert(node["inputs"].is_array());
61✔
645
            assert(node.contains("output"));
61✔
646
            assert(node["output"].is_string());
61✔
647
            auto inputs = node["inputs"].get<std::vector<std::string>>();
61✔
648

649
            auto& tasklet =
61✔
650
                builder
61✔
651
                    .add_tasklet(parent, node["code"], node["output"], inputs, json_to_debug_info(node["debug_info"]));
61✔
652
            tasklet.element_id_ = node["element_id"];
61✔
653
            nodes_map.insert({node["element_id"], tasklet});
61✔
654
        } else if (type == "library_node") {
146✔
655
            assert(node.contains("code"));
8✔
656
            data_flow::LibraryNodeCode code(node["code"].get<std::string>());
8✔
657

658
            auto serializer_fn = LibraryNodeSerializerRegistry::instance().get_library_node_serializer(code.value());
8✔
659
            if (serializer_fn == nullptr) {
8✔
660
                throw std::runtime_error("Unknown library node code: " + std::string(code.value()));
×
661
            }
×
662
            auto serializer = serializer_fn();
8✔
663
            auto& lib_node = serializer->deserialize(node, builder, parent);
8✔
664
            lib_node.implementation_type() =
8✔
665
                data_flow::ImplementationType(node["implementation_type"].get<std::string>());
8✔
666
            lib_node.element_id_ = node["element_id"];
8✔
667
            nodes_map.insert({node["element_id"], lib_node});
8✔
668
        } else if (type == "access_node") {
138✔
669
            assert(node.contains("data"));
138✔
670
            auto& access_node = builder.add_access(parent, node["data"], json_to_debug_info(node["debug_info"]));
138✔
671
            access_node.element_id_ = node["element_id"];
138✔
672
            nodes_map.insert({node["element_id"], access_node});
138✔
673
        } else if (type == "constant_node") {
138✔
674
            assert(node.contains("data"));
×
675
            assert(node.contains("data_type"));
×
676

677
            auto type = json_to_type(node["data_type"]);
×
678

679
            auto& constant_node =
×
680
                builder.add_constant(parent, node["data"], *type, json_to_debug_info(node["debug_info"]));
×
681
            constant_node.element_id_ = node["element_id"];
×
682
            nodes_map.insert({node["element_id"], constant_node});
×
683
        } else {
×
684
            throw std::runtime_error("Unknown node type");
×
685
        }
×
686
    }
207✔
687

688
    assert(j.contains("edges"));
45✔
689
    assert(j["edges"].is_array());
45✔
690
    for (const auto& edge : j["edges"]) {
183✔
691
        assert(edge.contains("src"));
183✔
692
        assert(edge["src"].is_number_integer());
183✔
693
        assert(edge.contains("dst"));
183✔
694
        assert(edge["dst"].is_number_integer());
183✔
695
        assert(edge.contains("src_conn"));
183✔
696
        assert(edge["src_conn"].is_string());
183✔
697
        assert(edge.contains("dst_conn"));
183✔
698
        assert(edge["dst_conn"].is_string());
183✔
699
        assert(edge.contains("subset"));
183✔
700
        assert(edge["subset"].is_array());
183✔
701

702
        assert(nodes_map.find(edge["src"]) != nodes_map.end());
183✔
703
        assert(nodes_map.find(edge["dst"]) != nodes_map.end());
183✔
704
        auto& source = nodes_map.at(edge["src"]);
183✔
705
        auto& target = nodes_map.at(edge["dst"]);
183✔
706

707
        auto base_type = json_to_type(edge["base_type"]);
183✔
708

709
        assert(edge.contains("subset"));
183✔
710
        assert(edge["subset"].is_array());
183✔
711
        std::vector<symbolic::Expression> subset;
183✔
712
        for (const auto& subset_ : edge["subset"]) {
183✔
713
            assert(subset_.is_string());
70✔
714
            std::string subset_str = subset_;
70✔
715
            auto expr = symbolic::parse(subset_str);
70✔
716
            subset.push_back(expr);
70✔
717
        }
70✔
718
        auto& memlet = builder.add_memlet(
183✔
719
            parent,
183✔
720
            source,
183✔
721
            edge["src_conn"],
183✔
722
            target,
183✔
723
            edge["dst_conn"],
183✔
724
            subset,
183✔
725
            *base_type,
183✔
726
            json_to_debug_info(edge["debug_info"])
183✔
727
        );
183✔
728
        memlet.element_id_ = edge["element_id"];
183✔
729
    }
183✔
730
}
45✔
731

732
void JSONSerializer::json_to_sequence(
733
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& sequence
734
) {
63✔
735
    assert(j.contains("type"));
63✔
736
    assert(j["type"].is_string());
63✔
737
    assert(j.contains("children"));
63✔
738
    assert(j["children"].is_array());
63✔
739
    assert(j.contains("transitions"));
63✔
740
    assert(j["transitions"].is_array());
63✔
741
    assert(j["transitions"].size() == j["children"].size());
63✔
742

743
    sequence.element_id_ = j["element_id"];
63✔
744
    sequence.debug_info_ = json_to_debug_info(j["debug_info"]);
63✔
745

746
    std::string type = j["type"];
63✔
747
    if (type == "sequence") {
63✔
748
        for (size_t i = 0; i < j["children"].size(); i++) {
132✔
749
            auto& child = j["children"][i];
69✔
750
            auto& transition = j["transitions"][i];
69✔
751
            assert(child.contains("type"));
69✔
752
            assert(child["type"].is_string());
69✔
753

754
            assert(transition.contains("type"));
69✔
755
            assert(transition["type"].is_string());
69✔
756
            assert(transition.contains("assignments"));
69✔
757
            assert(transition["assignments"].is_array());
69✔
758
            control_flow::Assignments assignments;
69✔
759
            for (const auto& assignment : transition["assignments"]) {
69✔
760
                assert(assignment.contains("symbol"));
2✔
761
                assert(assignment["symbol"].is_string());
2✔
762
                assert(assignment.contains("expression"));
2✔
763
                assert(assignment["expression"].is_string());
2✔
764
                auto expr = symbolic::parse(assignment["expression"].get<std::string>());
2✔
765
                assignments.insert({symbolic::symbol(assignment["symbol"]), expr});
2✔
766
            }
2✔
767

768
            if (child["type"] == "block") {
69✔
769
                json_to_block_node(child, builder, sequence, assignments);
42✔
770
            } else if (child["type"] == "for") {
42✔
771
                json_to_for_node(child, builder, sequence, assignments);
19✔
772
            } else if (child["type"] == "if_else") {
19✔
773
                json_to_if_else_node(child, builder, sequence, assignments);
×
774
            } else if (child["type"] == "while") {
8✔
775
                json_to_while_node(child, builder, sequence, assignments);
×
776
            } else if (child["type"] == "break") {
8✔
777
                json_to_break_node(child, builder, sequence, assignments);
1✔
778
            } else if (child["type"] == "continue") {
7✔
779
                json_to_continue_node(child, builder, sequence, assignments);
1✔
780
            } else if (child["type"] == "return") {
6✔
781
                json_to_return_node(child, builder, sequence, assignments);
×
782
            } else if (child["type"] == "map") {
6✔
783
                json_to_map_node(child, builder, sequence, assignments);
6✔
784
            } else if (child["type"] == "reduce") {
6✔
NEW
785
                json_to_reduce_node(child, builder, sequence, assignments);
×
786
            } else if (child["type"] == "sequence") {
×
787
                auto& subseq = builder.add_sequence(sequence, assignments, json_to_debug_info(child["debug_info"]));
×
788
                json_to_sequence(child, builder, subseq);
×
789
            } else {
×
790
                throw std::runtime_error("Unknown child type");
×
791
            }
×
792

793
            sequence.at(i).second.debug_info_ = json_to_debug_info(transition["debug_info"]);
69✔
794
            sequence.at(i).second.element_id_ = transition["element_id"];
69✔
795
        }
69✔
796
    } else {
63✔
797
        throw std::runtime_error("expected sequence type");
×
798
    }
×
799
}
63✔
800

801
void JSONSerializer::json_to_block_node(
802
    const nlohmann::json& j,
803
    builder::StructuredSDFGBuilder& builder,
804
    structured_control_flow::Sequence& parent,
805
    control_flow::Assignments& assignments
806
) {
43✔
807
    assert(j.contains("type"));
43✔
808
    assert(j["type"].is_string());
43✔
809
    assert(j.contains("dataflow"));
43✔
810
    assert(j["dataflow"].is_object());
43✔
811
    auto& block = builder.add_block(parent, assignments, json_to_debug_info(j["debug_info"]));
43✔
812
    block.element_id_ = j["element_id"];
43✔
813
    assert(j["dataflow"].contains("type"));
43✔
814
    assert(j["dataflow"]["type"].is_string());
43✔
815
    std::string type = j["dataflow"]["type"];
43✔
816
    if (type == "dataflow") {
43✔
817
        json_to_dataflow(j["dataflow"], builder, block);
43✔
818
    } else {
43✔
819
        throw std::runtime_error("Unknown dataflow type");
×
820
    }
×
821
}
43✔
822

823
void JSONSerializer::json_to_for_node(
824
    const nlohmann::json& j,
825
    builder::StructuredSDFGBuilder& builder,
826
    structured_control_flow::Sequence& parent,
827
    control_flow::Assignments& assignments
828
) {
20✔
829
    assert(j.contains("type"));
20✔
830
    assert(j["type"].is_string());
20✔
831
    assert(j.contains("indvar"));
20✔
832
    assert(j["indvar"].is_string());
20✔
833
    assert(j.contains("init"));
20✔
834
    assert(j["init"].is_string());
20✔
835
    assert(j.contains("condition"));
20✔
836
    assert(j["condition"].is_string());
20✔
837
    assert(j.contains("update"));
20✔
838
    assert(j["update"].is_string());
20✔
839
    assert(j.contains("root"));
20✔
840
    assert(j["root"].is_object());
20✔
841

842
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
20✔
843
    auto init = symbolic::parse(j["init"].get<std::string>());
20✔
844
    auto update = symbolic::parse(j["update"].get<std::string>());
20✔
845

846
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
20✔
847
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
20✔
848
    if (condition.is_null()) {
20✔
849
        throw InvalidSDFGException("For loop condition is not a boolean expression");
×
850
    }
×
851

852
    auto& for_node =
20✔
853
        builder.add_for(parent, indvar, condition, init, update, assignments, json_to_debug_info(j["debug_info"]));
20✔
854
    for_node.element_id_ = j["element_id"];
20✔
855

856
    assert(j["root"].contains("type"));
20✔
857
    assert(j["root"]["type"].is_string());
20✔
858
    assert(j["root"]["type"] == "sequence");
20✔
859
    json_to_sequence(j["root"], builder, for_node.root());
20✔
860
}
20✔
861

862
void JSONSerializer::json_to_if_else_node(
863
    const nlohmann::json& j,
864
    builder::StructuredSDFGBuilder& builder,
865
    structured_control_flow::Sequence& parent,
866
    control_flow::Assignments& assignments
867
) {
1✔
868
    assert(j.contains("type"));
1✔
869
    assert(j["type"].is_string());
1✔
870
    assert(j["type"] == "if_else");
1✔
871
    assert(j.contains("branches"));
1✔
872
    assert(j["branches"].is_array());
1✔
873
    auto& if_else_node = builder.add_if_else(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
874
    if_else_node.element_id_ = j["element_id"];
1✔
875
    for (const auto& branch : j["branches"]) {
2✔
876
        assert(branch.contains("condition"));
2✔
877
        assert(branch["condition"].is_string());
2✔
878
        assert(branch.contains("root"));
2✔
879
        assert(branch["root"].is_object());
2✔
880

881
        auto condition_expr = symbolic::parse(branch["condition"].get<std::string>());
2✔
882
        symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
2✔
883
        if (condition.is_null()) {
2✔
884
            throw InvalidSDFGException("If condition is not a boolean expression");
×
885
        }
×
886
        auto& branch_node = builder.add_case(if_else_node, condition);
2✔
887
        assert(branch["root"].contains("type"));
2✔
888
        assert(branch["root"]["type"].is_string());
2✔
889
        std::string type = branch["root"]["type"];
2✔
890
        if (type == "sequence") {
2✔
891
            json_to_sequence(branch["root"], builder, branch_node);
2✔
892
        } else {
2✔
893
            throw std::runtime_error("Unknown child type");
×
894
        }
×
895
    }
2✔
896
}
1✔
897

898
void JSONSerializer::json_to_while_node(
899
    const nlohmann::json& j,
900
    builder::StructuredSDFGBuilder& builder,
901
    structured_control_flow::Sequence& parent,
902
    control_flow::Assignments& assignments
903
) {
3✔
904
    assert(j.contains("type"));
3✔
905
    assert(j["type"].is_string());
3✔
906
    assert(j["type"] == "while");
3✔
907
    assert(j.contains("root"));
3✔
908
    assert(j["root"].is_object());
3✔
909

910
    auto& while_node = builder.add_while(parent, assignments, json_to_debug_info(j["debug_info"]));
3✔
911
    while_node.element_id_ = j["element_id"];
3✔
912

913
    assert(j["root"]["type"] == "sequence");
3✔
914
    json_to_sequence(j["root"], builder, while_node.root());
3✔
915
}
3✔
916

917
void JSONSerializer::json_to_break_node(
918
    const nlohmann::json& j,
919
    builder::StructuredSDFGBuilder& builder,
920
    structured_control_flow::Sequence& parent,
921
    control_flow::Assignments& assignments
922
) {
1✔
923
    assert(j.contains("type"));
1✔
924
    assert(j["type"].is_string());
1✔
925
    assert(j["type"] == "break");
1✔
926
    auto& node = builder.add_break(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
927
    node.element_id_ = j["element_id"];
1✔
928
}
1✔
929

930
void JSONSerializer::json_to_continue_node(
931
    const nlohmann::json& j,
932
    builder::StructuredSDFGBuilder& builder,
933
    structured_control_flow::Sequence& parent,
934
    control_flow::Assignments& assignments
935
) {
1✔
936
    assert(j.contains("type"));
1✔
937
    assert(j["type"].is_string());
1✔
938
    assert(j["type"] == "continue");
1✔
939
    auto& node = builder.add_continue(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
940
    node.element_id_ = j["element_id"];
1✔
941
}
1✔
942

943
void JSONSerializer::json_to_map_node(
944
    const nlohmann::json& j,
945
    builder::StructuredSDFGBuilder& builder,
946
    structured_control_flow::Sequence& parent,
947
    control_flow::Assignments& assignments
948
) {
7✔
949
    assert(j.contains("type"));
7✔
950
    assert(j["type"].is_string());
7✔
951
    assert(j["type"] == "map");
7✔
952
    assert(j.contains("indvar"));
7✔
953
    assert(j["indvar"].is_string());
7✔
954
    assert(j.contains("init"));
7✔
955
    assert(j["init"].is_string());
7✔
956
    assert(j.contains("condition"));
7✔
957
    assert(j["condition"].is_string());
7✔
958
    assert(j.contains("update"));
7✔
959
    assert(j["update"].is_string());
7✔
960
    assert(j.contains("root"));
7✔
961
    assert(j["root"].is_object());
7✔
962
    assert(j.contains("schedule_type"));
7✔
963
    assert(j["schedule_type"].is_object());
7✔
964

965
    structured_control_flow::ScheduleType schedule_type = json_to_schedule_type(j["schedule_type"]);
7✔
966

967
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
7✔
968
    auto init = symbolic::parse(j["init"].get<std::string>());
7✔
969
    auto update = symbolic::parse(j["update"].get<std::string>());
7✔
970
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
7✔
971
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
7✔
972
    if (condition.is_null()) {
7✔
973
        throw InvalidSDFGException("Map condition is not a boolean expression");
×
974
    }
×
975

976
    auto& map_node = builder.add_map(
7✔
977
        parent, indvar, condition, init, update, schedule_type, assignments, json_to_debug_info(j["debug_info"])
7✔
978
    );
7✔
979
    map_node.element_id_ = j["element_id"];
7✔
980

981
    assert(j["root"].contains("type"));
7✔
982
    assert(j["root"]["type"].is_string());
7✔
983
    assert(j["root"]["type"] == "sequence");
7✔
984
    json_to_sequence(j["root"], builder, map_node.root());
7✔
985
}
7✔
986

987
void JSONSerializer::json_to_reduce_node(
988
    const nlohmann::json& j,
989
    builder::StructuredSDFGBuilder& builder,
990
    structured_control_flow::Sequence& parent,
991
    control_flow::Assignments& assignments
992
) {
1✔
993
    assert(j.contains("type"));
1✔
994
    assert(j["type"].is_string());
1✔
995
    assert(j["type"] == "reduce");
1✔
996
    assert(j.contains("indvar"));
1✔
997
    assert(j["indvar"].is_string());
1✔
998
    assert(j.contains("init"));
1✔
999
    assert(j["init"].is_string());
1✔
1000
    assert(j.contains("condition"));
1✔
1001
    assert(j["condition"].is_string());
1✔
1002
    assert(j.contains("update"));
1✔
1003
    assert(j["update"].is_string());
1✔
1004
    assert(j.contains("root"));
1✔
1005
    assert(j["root"].is_object());
1✔
1006
    assert(j.contains("reductions"));
1✔
1007
    assert(j["reductions"].is_array());
1✔
1008
    assert(j.contains("schedule_type"));
1✔
1009
    assert(j["schedule_type"].is_object());
1✔
1010

1011
    std::vector<structured_control_flow::ReductionInfo> reductions;
1✔
1012
    for (const auto& reduction_json : j["reductions"]) {
1✔
1013
        assert(reduction_json.contains("op"));
1✔
1014
        assert(reduction_json["op"].is_string());
1✔
1015
        assert(reduction_json.contains("container"));
1✔
1016
        assert(reduction_json["container"].is_string());
1✔
1017
        reductions.push_back(structured_control_flow::ReductionInfo{
1✔
1018
            structured_control_flow::reduction_operation_from_string(reduction_json["op"].get<std::string>()),
1✔
1019
            reduction_json["container"].get<std::string>()
1✔
1020
        });
1✔
1021
    }
1✔
1022

1023
    structured_control_flow::ScheduleType schedule_type = json_to_schedule_type(j["schedule_type"]);
1✔
1024

1025
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
1✔
1026
    auto init = symbolic::parse(j["init"].get<std::string>());
1✔
1027
    auto update = symbolic::parse(j["update"].get<std::string>());
1✔
1028
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
1✔
1029
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
1✔
1030
    if (condition.is_null()) {
1✔
NEW
1031
        throw InvalidSDFGException("Reduce condition is not a boolean expression");
×
NEW
1032
    }
×
1033

1034
    auto& reduce_node = builder.add_reduce(
1✔
1035
        parent,
1✔
1036
        indvar,
1✔
1037
        condition,
1✔
1038
        init,
1✔
1039
        update,
1✔
1040
        reductions,
1✔
1041
        schedule_type,
1✔
1042
        assignments,
1✔
1043
        json_to_debug_info(j["debug_info"])
1✔
1044
    );
1✔
1045
    reduce_node.element_id_ = j["element_id"];
1✔
1046

1047
    assert(j["root"].contains("type"));
1✔
1048
    assert(j["root"]["type"].is_string());
1✔
1049
    assert(j["root"]["type"] == "sequence");
1✔
1050
    json_to_sequence(j["root"], builder, reduce_node.root());
1✔
1051
}
1✔
1052

1053
void JSONSerializer::json_to_return_node(
1054
    const nlohmann::json& j,
1055
    builder::StructuredSDFGBuilder& builder,
1056
    structured_control_flow::Sequence& parent,
1057
    control_flow::Assignments& assignments
1058
) {
1✔
1059
    assert(j.contains("type"));
1✔
1060
    assert(j["type"].is_string());
1✔
1061
    assert(j["type"] == "return");
1✔
1062

1063
    std::string data = j["data"];
1✔
1064
    std::unique_ptr<types::IType> data_type = nullptr;
1✔
1065
    if (j.contains("data_type")) {
1✔
1066
        data_type = json_to_type(j["data_type"]);
×
1067
    }
×
1068

1069
    if (data_type == nullptr) {
1✔
1070
        auto& node = builder.add_return(parent, data, assignments, json_to_debug_info(j["debug_info"]));
1✔
1071
        node.element_id_ = j["element_id"];
1✔
1072
    } else {
1✔
1073
        auto& node =
×
1074
            builder.add_constant_return(parent, data, *data_type, assignments, json_to_debug_info(j["debug_info"]));
×
1075
        node.element_id_ = j["element_id"];
×
1076
    }
×
1077
}
1✔
1078

1079
std::unique_ptr<types::IType> JSONSerializer::json_to_type(const nlohmann::json& j) {
527✔
1080
    if (j.contains("type")) {
527✔
1081
        if (j["type"] == "scalar") {
527✔
1082
            // Deserialize scalar type
1083
            assert(j.contains("primitive_type"));
385✔
1084
            types::PrimitiveType primitive_type = j["primitive_type"];
385✔
1085
            assert(j.contains("storage_type"));
385✔
1086
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
385✔
1087
            assert(j.contains("initializer"));
385✔
1088
            std::string initializer = j["initializer"];
385✔
1089
            assert(j.contains("alignment"));
385✔
1090
            size_t alignment = j["alignment"];
385✔
1091
            return std::make_unique<types::Scalar>(storage_type, alignment, initializer, primitive_type);
385✔
1092
        } else if (j["type"] == "array") {
385✔
1093
            // Deserialize array type
1094
            assert(j.contains("element_type"));
76✔
1095
            std::unique_ptr<types::IType> member_type = json_to_type(j["element_type"]);
76✔
1096
            assert(j.contains("num_elements"));
76✔
1097
            std::string num_elements_str = j["num_elements"];
76✔
1098
            // Convert num_elements_str to symbolic::Expression
1099
            auto num_elements = symbolic::parse(num_elements_str);
76✔
1100
            assert(j.contains("storage_type"));
76✔
1101
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
76✔
1102
            assert(j.contains("initializer"));
76✔
1103
            std::string initializer = j["initializer"];
76✔
1104
            assert(j.contains("alignment"));
76✔
1105
            size_t alignment = j["alignment"];
76✔
1106
            return std::make_unique<types::Array>(storage_type, alignment, initializer, *member_type, num_elements);
76✔
1107
        } else if (j["type"] == "pointer") {
76✔
1108
            // Deserialize pointer type
1109
            std::optional<std::unique_ptr<types::IType>> pointee_type;
52✔
1110
            if (j.contains("pointee_type")) {
52✔
1111
                assert(j.contains("pointee_type"));
51✔
1112
                pointee_type = json_to_type(j["pointee_type"]);
51✔
1113
            } else {
51✔
1114
                pointee_type = std::nullopt;
1✔
1115
            }
1✔
1116
            assert(j.contains("storage_type"));
52✔
1117
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
52✔
1118
            assert(j.contains("initializer"));
52✔
1119
            std::string initializer = j["initializer"];
52✔
1120
            assert(j.contains("alignment"));
52✔
1121
            size_t alignment = j["alignment"];
52✔
1122
            if (pointee_type.has_value()) {
52✔
1123
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer, *pointee_type.value());
51✔
1124
            } else {
51✔
1125
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer);
1✔
1126
            }
1✔
1127
        } else if (j["type"] == "structure") {
52✔
1128
            // Deserialize structure type
1129
            assert(j.contains("name"));
3✔
1130
            std::string name = j["name"];
3✔
1131
            assert(j.contains("storage_type"));
3✔
1132
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
3✔
1133
            assert(j.contains("initializer"));
3✔
1134
            std::string initializer = j["initializer"];
3✔
1135
            assert(j.contains("alignment"));
3✔
1136
            size_t alignment = j["alignment"];
3✔
1137
            return std::make_unique<types::Structure>(storage_type, alignment, initializer, name);
3✔
1138
        } else if (j["type"] == "function") {
11✔
1139
            // Deserialize function type
1140
            assert(j.contains("return_type"));
4✔
1141
            std::unique_ptr<types::IType> return_type = json_to_type(j["return_type"]);
4✔
1142
            assert(j.contains("params"));
4✔
1143
            std::vector<std::unique_ptr<types::IType>> params;
4✔
1144
            for (const auto& param : j["params"]) {
10✔
1145
                params.push_back(json_to_type(param));
10✔
1146
            }
10✔
1147
            assert(j.contains("is_var_arg"));
4✔
1148
            bool is_var_arg = j["is_var_arg"];
4✔
1149
            assert(j.contains("storage_type"));
4✔
1150
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
4✔
1151
            assert(j.contains("initializer"));
4✔
1152
            std::string initializer = j["initializer"];
4✔
1153
            assert(j.contains("alignment"));
4✔
1154
            size_t alignment = j["alignment"];
4✔
1155
            auto function =
4✔
1156
                std::make_unique<types::Function>(storage_type, alignment, initializer, *return_type, is_var_arg);
4✔
1157
            for (const auto& param : params) {
10✔
1158
                function->add_param(*param);
10✔
1159
            }
10✔
1160
            return function->clone();
4✔
1161
        } else if (j["type"] == "reference") {
7✔
1162
            // Deserialize reference type
1163
            assert(j.contains("reference_type"));
7✔
1164
            std::unique_ptr<types::IType> reference_type = json_to_type(j["reference_type"]);
7✔
1165
            return std::make_unique<sdfg::codegen::Reference>(*reference_type);
7✔
1166
        } else if (j["type"] == "tensor") {
7✔
1167
            // Deserialize tensor type
1168
            assert(j.contains("element_type"));
×
1169
            std::unique_ptr<types::IType> element_type = json_to_type(j["element_type"]);
×
1170
            assert(j.contains("shape"));
×
1171
            std::vector<symbolic::Expression> shape;
×
1172
            for (const auto& dim : j["shape"]) {
×
1173
                assert(dim.is_string());
×
1174
                std::string dim_str = dim;
×
1175
                auto expr = symbolic::parse(dim_str);
×
1176
                shape.push_back(expr);
×
1177
            }
×
1178
            assert(j.contains("strides"));
×
1179
            std::vector<symbolic::Expression> strides;
×
1180
            for (const auto& stride : j["strides"]) {
×
1181
                assert(stride.is_string());
×
1182
                std::string stride_str = stride;
×
1183
                auto expr = symbolic::parse(stride_str);
×
1184
                strides.push_back(expr);
×
1185
            }
×
1186
            assert(j.contains("offset"));
×
1187
            symbolic::Expression offset = symbolic::parse(j["offset"].get<std::string>());
×
1188
            assert(j.contains("storage_type"));
×
1189
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
×
1190
            assert(j.contains("initializer"));
×
1191
            std::string initializer = j["initializer"];
×
1192
            assert(j.contains("alignment"));
×
1193
            size_t alignment = j["alignment"];
×
1194
            return std::make_unique<types::Tensor>(
×
1195
                storage_type, alignment, initializer, dynamic_cast<types::Scalar&>(*element_type), shape, strides, offset
×
1196
            );
×
1197
        } else {
×
1198
            throw std::runtime_error("Unknown type");
×
1199
        }
×
1200
    } else {
527✔
1201
        throw std::runtime_error("Type not found");
×
1202
    }
×
1203
}
527✔
1204

1205
DebugInfo JSONSerializer::json_to_debug_info(const nlohmann::json& j) {
600✔
1206
    assert(j.contains("has"));
600✔
1207
    assert(j["has"].is_boolean());
600✔
1208
    if (!j["has"]) {
600✔
1209
        return DebugInfo();
596✔
1210
    }
596✔
1211
    assert(j.contains("filename"));
600✔
1212
    assert(j["filename"].is_string());
4✔
1213
    std::string filename = j["filename"];
4✔
1214
    assert(j.contains("function"));
4✔
1215
    assert(j["function"].is_string());
4✔
1216
    std::string function = j["function"];
4✔
1217
    assert(j.contains("start_line"));
4✔
1218
    assert(j["start_line"].is_number_integer());
4✔
1219
    size_t start_line = j["start_line"];
4✔
1220
    assert(j.contains("start_column"));
4✔
1221
    assert(j["start_column"].is_number_integer());
4✔
1222
    size_t start_column = j["start_column"];
4✔
1223
    assert(j.contains("end_line"));
4✔
1224
    assert(j["end_line"].is_number_integer());
4✔
1225
    size_t end_line = j["end_line"];
4✔
1226
    assert(j.contains("end_column"));
4✔
1227
    assert(j["end_column"].is_number_integer());
4✔
1228
    size_t end_column = j["end_column"];
4✔
1229
    return DebugInfo(filename, function, start_line, start_column, end_line, end_column);
4✔
1230
}
4✔
1231

1232
ScheduleType JSONSerializer::json_to_schedule_type(const nlohmann::json& j) {
9✔
1233
    assert(j.contains("value"));
9✔
1234
    assert(j["value"].is_string());
9✔
1235
    // assert(j.contains("category"));
1236
    // assert(j["category"].is_number_integer());
1237
    assert(j.contains("properties"));
9✔
1238
    assert(j["properties"].is_object());
9✔
1239
    ScheduleTypeCategory category = ScheduleTypeCategory::None;
9✔
1240
    if (j.contains("category")) {
9✔
1241
        category = static_cast<ScheduleTypeCategory>(j["category"].get<int>());
9✔
1242
    }
9✔
1243
    ScheduleType schedule_type(j["value"].get<std::string>(), category);
9✔
1244
    for (const auto& [key, value] : j["properties"].items()) {
9✔
1245
        assert(value.is_string());
3✔
1246
        schedule_type.set_property(key, value.get<std::string>());
3✔
1247
    }
3✔
1248
    return schedule_type;
9✔
1249
}
9✔
1250

1251
types::StorageType JSONSerializer::json_to_storage_type(const nlohmann::json& j) {
526✔
1252
    if (!j.contains("value")) {
526✔
1253
        return types::StorageType::CPU_Stack();
×
1254
    }
×
1255
    std::string value = j["value"].get<std::string>();
526✔
1256

1257
    symbolic::Expression allocation_size = SymEngine::null;
526✔
1258
    if (j.contains("allocation_size")) {
526✔
1259
        allocation_size = symbolic::parse(j["allocation_size"].get<std::string>());
×
1260
    }
×
1261

1262
    types::StorageType::AllocationType allocation = j["allocation"];
526✔
1263
    types::StorageType::AllocationType deallocation = j["deallocation"];
526✔
1264

1265
    auto storageType = types::StorageType(j["value"].get<std::string>(), allocation_size, allocation, deallocation);
526✔
1266

1267
    if (j.contains("args")) {
526✔
1268
        nlohmann::json::array_t args = j["args"];
×
1269
        if (args.size() > 0) {
×
1270
            storageType.arg1(symbolic::parse(args[0].get<std::string>()));
×
1271
        }
×
1272
    }
×
1273
    return storageType;
526✔
1274
}
526✔
1275

1276
std::string JSONSerializer::expression(const symbolic::Expression expr) {
363✔
1277
    JSONSymbolicPrinter printer;
363✔
1278
    return printer.apply(expr);
363✔
1279
};
363✔
1280

1281
symbolic::Expression JSONSerializer::json_to_expr(const nlohmann::json& j) {
3✔
1282
    return symbolic::parse(j.get<std::string>());
3✔
1283
}
3✔
1284

1285
void JSONSerializer::writeToFile(const StructuredSDFG& sdfg, const std::filesystem::path& file) {
×
1286
    JSONSerializer ser;
×
1287
    auto json = ser.serialize(sdfg);
×
1288

1289
    auto parent_path = file.parent_path();
×
1290
    if (!parent_path.empty()) {
×
1291
        std::filesystem::create_directories(file.parent_path());
×
1292
    }
×
1293

1294
    std::ofstream out(file, std::ofstream::out);
×
1295
    if (!out.is_open()) {
×
1296
        std::cerr << "Could not open file " << file << " for writing JSON output." << std::endl;
×
1297
    }
×
1298
    out << json << std::endl;
×
1299
    out.close();
×
1300
}
×
1301

1302
void JSONSymbolicPrinter::bvisit(const SymEngine::Equality& x) {
×
1303
    str_ = apply(x.get_args()[0]) + " == " + apply(x.get_args()[1]);
×
1304
    str_ = parenthesize(str_);
×
1305
};
×
1306

1307
void JSONSymbolicPrinter::bvisit(const SymEngine::Unequality& x) {
×
1308
    str_ = apply(x.get_args()[0]) + " != " + apply(x.get_args()[1]);
×
1309
    str_ = parenthesize(str_);
×
1310
};
×
1311

1312
void JSONSymbolicPrinter::bvisit(const SymEngine::LessThan& x) {
2✔
1313
    str_ = apply(x.get_args()[0]) + " <= " + apply(x.get_args()[1]);
2✔
1314
    str_ = parenthesize(str_);
2✔
1315
};
2✔
1316

1317
void JSONSymbolicPrinter::bvisit(const SymEngine::StrictLessThan& x) {
29✔
1318
    str_ = apply(x.get_args()[0]) + " < " + apply(x.get_args()[1]);
29✔
1319
    str_ = parenthesize(str_);
29✔
1320
};
29✔
1321

1322
void JSONSymbolicPrinter::bvisit(const SymEngine::Min& x) {
×
1323
    std::ostringstream s;
×
1324
    auto container = x.get_args();
×
1325
    if (container.size() == 1) {
×
1326
        s << apply(*container.begin());
×
1327
    } else {
×
1328
        s << "min(";
×
1329
        s << apply(*container.begin());
×
1330

1331
        // Recursively apply __daisy_min to the arguments
1332
        SymEngine::vec_basic subargs;
×
1333
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1334
            subargs.push_back(*it);
×
1335
        }
×
1336
        auto submin = SymEngine::min(subargs);
×
1337
        s << ", " << apply(submin);
×
1338

1339
        s << ")";
×
1340
    }
×
1341

1342
    str_ = s.str();
×
1343
};
×
1344

1345
void JSONSymbolicPrinter::bvisit(const SymEngine::Max& x) {
×
1346
    std::ostringstream s;
×
1347
    auto container = x.get_args();
×
1348
    if (container.size() == 1) {
×
1349
        s << apply(*container.begin());
×
1350
    } else {
×
1351
        s << "max(";
×
1352
        s << apply(*container.begin());
×
1353

1354
        // Recursively apply __daisy_max to the arguments
1355
        SymEngine::vec_basic subargs;
×
1356
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1357
            subargs.push_back(*it);
×
1358
        }
×
1359
        auto submax = SymEngine::max(subargs);
×
1360
        s << ", " << apply(submax);
×
1361

1362
        s << ")";
×
1363
    }
×
1364

1365
    str_ = s.str();
×
1366
};
×
1367

1368
void LibraryNodeSerializerRegistry::
1369
    register_library_node_serializer(std::string library_node_code, LibraryNodeSerializerFn fn) {
220✔
1370
    std::lock_guard<std::mutex> lock(mutex_);
220✔
1371
    if (factory_map_.find(library_node_code) != factory_map_.end()) {
220✔
1372
        return;
2✔
1373
    }
2✔
1374
    factory_map_[library_node_code] = std::move(fn);
218✔
1375
}
218✔
1376

1377
LibraryNodeSerializerFn LibraryNodeSerializerRegistry::get_library_node_serializer(std::string library_node_code) {
17✔
1378
    auto it = factory_map_.find(library_node_code);
17✔
1379
    if (it != factory_map_.end()) {
17✔
1380
        return it->second;
17✔
1381
    }
17✔
1382
    return nullptr;
×
1383
}
17✔
1384

1385
size_t LibraryNodeSerializerRegistry::size() const { return factory_map_.size(); }
×
1386

1387
void register_default_serializers() {
4✔
1388
    // stdlib
1389
    LibraryNodeSerializerRegistry::instance()
4✔
1390
        .register_library_node_serializer(stdlib::LibraryNodeType_Alloca.value(), []() {
4✔
1391
            return std::make_unique<stdlib::AllocaNodeSerializer>();
×
1392
        });
×
1393
    LibraryNodeSerializerRegistry::instance()
4✔
1394
        .register_library_node_serializer(stdlib::LibraryNodeType_Assert.value(), []() {
4✔
1395
            return std::make_unique<stdlib::AssertNodeSerializer>();
×
1396
        });
×
1397
    LibraryNodeSerializerRegistry::instance()
4✔
1398
        .register_library_node_serializer(stdlib::LibraryNodeType_Calloc.value(), []() {
4✔
1399
            return std::make_unique<stdlib::CallocNodeSerializer>();
×
1400
        });
×
1401
    LibraryNodeSerializerRegistry::instance()
4✔
1402
        .register_library_node_serializer(stdlib::LibraryNodeType_Free.value(), []() {
4✔
1403
            return std::make_unique<stdlib::FreeNodeSerializer>();
×
1404
        });
×
1405
    LibraryNodeSerializerRegistry::instance()
4✔
1406
        .register_library_node_serializer(stdlib::LibraryNodeType_Malloc.value(), []() {
4✔
1407
            return std::make_unique<stdlib::MallocNodeSerializer>();
×
1408
        });
×
1409
    LibraryNodeSerializerRegistry::instance()
4✔
1410
        .register_library_node_serializer(stdlib::LibraryNodeType_Memcpy.value(), []() {
4✔
1411
            return std::make_unique<stdlib::MemcpyNodeSerializer>();
×
1412
        });
×
1413
    LibraryNodeSerializerRegistry::instance()
4✔
1414
        .register_library_node_serializer(stdlib::LibraryNodeType_Memmove.value(), []() {
4✔
1415
            return std::make_unique<stdlib::MemmoveNodeSerializer>();
×
1416
        });
×
1417
    LibraryNodeSerializerRegistry::instance()
4✔
1418
        .register_library_node_serializer(stdlib::LibraryNodeType_Memset.value(), []() {
4✔
1419
            return std::make_unique<stdlib::MemsetNodeSerializer>();
×
1420
        });
×
1421
    LibraryNodeSerializerRegistry::instance()
4✔
1422
        .register_library_node_serializer(stdlib::LibraryNodeType_Trap.value(), []() {
4✔
1423
            return std::make_unique<stdlib::TrapNodeSerializer>();
×
1424
        });
×
1425
    LibraryNodeSerializerRegistry::instance()
4✔
1426
        .register_library_node_serializer(stdlib::LibraryNodeType_Unreachable.value(), []() {
4✔
1427
            return std::make_unique<stdlib::UnreachableNodeSerializer>();
×
1428
        });
×
1429

1430
    // Metadata
1431
    LibraryNodeSerializerRegistry::instance()
4✔
1432
        .register_library_node_serializer(data_flow::LibraryNodeType_Metadata.value(), []() {
4✔
1433
            return std::make_unique<data_flow::MetadataNodeSerializer>();
×
1434
        });
×
1435

1436
    // Barrier
1437
    LibraryNodeSerializerRegistry::instance()
4✔
1438
        .register_library_node_serializer(data_flow::LibraryNodeType_BarrierLocal.value(), []() {
4✔
1439
            return std::make_unique<data_flow::BarrierLocalNodeSerializer>();
1✔
1440
        });
1✔
1441

1442
    // Call Node
1443
    LibraryNodeSerializerRegistry::instance()
4✔
1444
        .register_library_node_serializer(data_flow::LibraryNodeType_Call.value(), []() {
6✔
1445
            return std::make_unique<data_flow::CallNodeSerializer>();
6✔
1446
        });
6✔
1447
    LibraryNodeSerializerRegistry::instance()
4✔
1448
        .register_library_node_serializer(data_flow::LibraryNodeType_Invoke.value(), []() {
4✔
1449
            return std::make_unique<data_flow::InvokeNodeSerializer>();
×
1450
        });
×
1451

1452
    // LoadConst
1453
    LibraryNodeSerializerRegistry::instance()
4✔
1454
        .register_library_node_serializer(data_flow::LibraryNodeType_LoadConst.value(), []() {
4✔
1455
            return std::make_unique<data_flow::LoadConstNodeSerializer>();
2✔
1456
        });
2✔
1457

1458
    // CMath
1459
    LibraryNodeSerializerRegistry::instance()
4✔
1460
        .register_library_node_serializer(math::cmath::LibraryNodeType_CMath.value(), []() {
4✔
1461
            return std::make_unique<math::cmath::CMathNodeSerializer>();
×
1462
        });
×
1463
    // Backward compatibility
1464
    LibraryNodeSerializerRegistry::instance()
4✔
1465
        .register_library_node_serializer(math::cmath::LibraryNodeType_CMath_Deprecated.value(), []() {
4✔
1466
            return std::make_unique<math::cmath::CMathNodeSerializer>();
×
1467
        });
×
1468

1469
    // BLAS
1470
    LibraryNodeSerializerRegistry::instance()
4✔
1471
        .register_library_node_serializer(math::blas::LibraryNodeType_DOT.value(), []() {
4✔
1472
            return std::make_unique<math::blas::DotNodeSerializer>();
×
1473
        });
×
1474
    LibraryNodeSerializerRegistry::instance()
4✔
1475
        .register_library_node_serializer(math::blas::LibraryNodeType_GEMM.value(), []() {
4✔
1476
            return std::make_unique<math::blas::GEMMNodeSerializer>();
×
1477
        });
×
1478
    LibraryNodeSerializerRegistry::instance()
4✔
1479
        .register_library_node_serializer(math::blas::LibraryNodeType_BatchedGEMM.value(), []() {
4✔
1480
            return std::make_unique<math::blas::BatchedGEMMNodeSerializer>();
×
1481
        });
×
1482

1483
    // Tensor
1484

1485
    LibraryNodeSerializerRegistry::instance()
4✔
1486
        .register_library_node_serializer(math::tensor::LibraryNodeType_Broadcast.value(), []() {
4✔
1487
            return std::make_unique<math::tensor::BroadcastNodeSerializer>();
×
1488
        });
×
1489
    LibraryNodeSerializerRegistry::instance()
4✔
1490
        .register_library_node_serializer(math::tensor::LibraryNodeType_Conv.value(), []() {
4✔
1491
            return std::make_unique<math::tensor::ConvNodeSerializer>();
×
1492
        });
×
1493
    LibraryNodeSerializerRegistry::instance()
4✔
1494
        .register_library_node_serializer(math::tensor::LibraryNodeType_Pooling.value(), []() {
4✔
1495
            return std::make_unique<math::tensor::PoolingNodeSerializer>();
×
1496
        });
×
1497
    LibraryNodeSerializerRegistry::instance()
4✔
1498
        .register_library_node_serializer(math::tensor::LibraryNodeType_Transpose.value(), []() {
4✔
1499
            return std::make_unique<math::tensor::TransposeNodeSerializer>();
×
1500
        });
×
1501
    LibraryNodeSerializerRegistry::instance()
4✔
1502
        .register_library_node_serializer(math::tensor::LibraryNodeType_MatMul.value(), []() {
4✔
1503
            return std::make_unique<math::tensor::MatMulNodeSerializer>();
×
1504
        });
×
1505

1506
    // Elementwise
1507
    LibraryNodeSerializerRegistry::instance()
4✔
1508
        .register_library_node_serializer(math::tensor::LibraryNodeType_Abs.value(), []() {
4✔
1509
            return std::make_unique<math::tensor::AbsNodeSerializer>();
×
1510
        });
×
1511
    LibraryNodeSerializerRegistry::instance()
4✔
1512
        .register_library_node_serializer(math::tensor::LibraryNodeType_Add.value(), []() {
4✔
1513
            return std::make_unique<math::tensor::AddNodeSerializer>();
×
1514
        });
×
1515
    LibraryNodeSerializerRegistry::instance()
4✔
1516
        .register_library_node_serializer(math::tensor::LibraryNodeType_Div.value(), []() {
4✔
1517
            return std::make_unique<math::tensor::DivNodeSerializer>();
×
1518
        });
×
1519
    LibraryNodeSerializerRegistry::instance()
4✔
1520
        .register_library_node_serializer(math::tensor::LibraryNodeType_Elu.value(), []() {
4✔
1521
            return std::make_unique<math::tensor::EluNodeSerializer>();
×
1522
        });
×
1523
    LibraryNodeSerializerRegistry::instance()
4✔
1524
        .register_library_node_serializer(math::tensor::LibraryNodeType_Exp.value(), []() {
4✔
1525
            return std::make_unique<math::tensor::ExpNodeSerializer>();
×
1526
        });
×
1527
    LibraryNodeSerializerRegistry::instance()
4✔
1528
        .register_library_node_serializer(math::tensor::LibraryNodeType_Erf.value(), []() {
4✔
1529
            return std::make_unique<math::tensor::ErfNodeSerializer>();
×
1530
        });
×
1531
    LibraryNodeSerializerRegistry::instance()
4✔
1532
        .register_library_node_serializer(math::tensor::LibraryNodeType_HardSigmoid.value(), []() {
4✔
1533
            return std::make_unique<math::tensor::HardSigmoidNodeSerializer>();
×
1534
        });
×
1535
    LibraryNodeSerializerRegistry::instance()
4✔
1536
        .register_library_node_serializer(math::tensor::LibraryNodeType_LeakyReLU.value(), []() {
4✔
1537
            return std::make_unique<math::tensor::LeakyReLUNodeSerializer>();
×
1538
        });
×
1539
    LibraryNodeSerializerRegistry::instance()
4✔
1540
        .register_library_node_serializer(math::tensor::LibraryNodeType_Mul.value(), []() {
4✔
1541
            return std::make_unique<math::tensor::MulNodeSerializer>();
×
1542
        });
×
1543
    LibraryNodeSerializerRegistry::instance()
4✔
1544
        .register_library_node_serializer(math::tensor::LibraryNodeType_Pow.value(), []() {
4✔
1545
            return std::make_unique<math::tensor::PowNodeSerializer>();
×
1546
        });
×
1547
    LibraryNodeSerializerRegistry::instance()
4✔
1548
        .register_library_node_serializer(math::tensor::LibraryNodeType_ReLU.value(), []() {
4✔
1549
            return std::make_unique<math::tensor::ReLUNodeSerializer>();
×
1550
        });
×
1551
    LibraryNodeSerializerRegistry::instance()
4✔
1552
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sigmoid.value(), []() {
4✔
1553
            return std::make_unique<math::tensor::SigmoidNodeSerializer>();
×
1554
        });
×
1555
    LibraryNodeSerializerRegistry::instance()
4✔
1556
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sqrt.value(), []() {
4✔
1557
            return std::make_unique<math::tensor::SqrtNodeSerializer>();
×
1558
        });
×
1559
    LibraryNodeSerializerRegistry::instance()
4✔
1560
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sub.value(), []() {
4✔
1561
            return std::make_unique<math::tensor::SubNodeSerializer>();
×
1562
        });
×
1563
    LibraryNodeSerializerRegistry::instance()
4✔
1564
        .register_library_node_serializer(math::tensor::LibraryNodeType_Tanh.value(), []() {
4✔
1565
            return std::make_unique<math::tensor::TanhNodeSerializer>();
×
1566
        });
×
1567
    LibraryNodeSerializerRegistry::instance()
4✔
1568
        .register_library_node_serializer(math::tensor::LibraryNodeType_Minimum.value(), []() {
4✔
1569
            return std::make_unique<math::tensor::MinimumNodeSerializer>();
×
1570
        });
×
1571
    LibraryNodeSerializerRegistry::instance()
4✔
1572
        .register_library_node_serializer(math::tensor::LibraryNodeType_Maximum.value(), []() {
4✔
1573
            return std::make_unique<math::tensor::MaximumNodeSerializer>();
×
1574
        });
×
1575
    LibraryNodeSerializerRegistry::instance()
4✔
1576
        .register_library_node_serializer(math::tensor::LibraryNodeType_Fill.value(), []() {
4✔
1577
            return std::make_unique<math::tensor::FillNodeSerializer>();
×
1578
        });
×
1579
    LibraryNodeSerializerRegistry::instance()
4✔
1580
        .register_library_node_serializer(math::tensor::LibraryNodeType_TensorTasklet.value(), []() {
4✔
1581
            return std::make_unique<math::tensor::TaskletTensorNodeSerializer>();
×
1582
        });
×
1583
    LibraryNodeSerializerRegistry::instance()
4✔
1584
        .register_library_node_serializer(math::tensor::LibraryNodeType_TensorCMath.value(), []() {
4✔
1585
            return std::make_unique<math::tensor::CMathTensorNodeSerializer>();
×
1586
        });
×
1587
    LibraryNodeSerializerRegistry::instance()
4✔
1588
        .register_library_node_serializer(math::tensor::LibraryNodeType_Cast.value(), []() {
4✔
1589
            return std::make_unique<math::tensor::CastNodeSerializer>();
×
1590
        });
×
1591

1592
    LibraryNodeSerializerRegistry::instance()
4✔
1593
        .register_library_node_serializer(math::tensor::LibraryNodeType_BatchNorm.value(), [] {
4✔
1594
            return std::make_unique<math::tensor::BatchNormNodeSerializer>();
×
1595
        });
×
1596

1597
    // Reduce
1598
    LibraryNodeSerializerRegistry::instance()
4✔
1599
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sum.value(), []() {
4✔
1600
            return std::make_unique<math::tensor::SumNodeSerializer>();
×
1601
        });
×
1602
    LibraryNodeSerializerRegistry::instance()
4✔
1603
        .register_library_node_serializer(math::tensor::LibraryNodeType_Max.value(), []() {
4✔
1604
            return std::make_unique<math::tensor::MaxNodeSerializer>();
×
1605
        });
×
1606
    LibraryNodeSerializerRegistry::instance()
4✔
1607
        .register_library_node_serializer(math::tensor::LibraryNodeType_Min.value(), []() {
4✔
1608
            return std::make_unique<math::tensor::MinNodeSerializer>();
×
1609
        });
×
1610
    LibraryNodeSerializerRegistry::instance()
4✔
1611
        .register_library_node_serializer(math::tensor::LibraryNodeType_Softmax.value(), []() {
4✔
1612
            return std::make_unique<math::tensor::SoftmaxNodeSerializer>();
×
1613
        });
×
1614
    LibraryNodeSerializerRegistry::instance()
4✔
1615
        .register_library_node_serializer(math::tensor::LibraryNodeType_Mean.value(), []() {
4✔
1616
            return std::make_unique<math::tensor::MeanNodeSerializer>();
×
1617
        });
×
1618
    LibraryNodeSerializerRegistry::instance()
4✔
1619
        .register_library_node_serializer(math::tensor::LibraryNodeType_Std.value(), []() {
4✔
1620
            return std::make_unique<math::tensor::StdNodeSerializer>();
×
1621
        });
×
1622

1623
    // Einsum
1624
    LibraryNodeSerializerRegistry::instance()
4✔
1625
        .register_library_node_serializer(math::tensor::LibraryNodeType_Einsum.value(), []() {
4✔
1626
            return std::make_unique<math::tensor::EinsumSerializer>();
×
1627
        });
×
1628
}
4✔
1629

1630
} // namespace serializer
1631
} // 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