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

daisytuner / docc / 30435107092

29 Jul 2026 08:20AM UTC coverage: 64.53% (+0.006%) from 64.524%
30435107092

Pull #898

github

web-flow
Merge c1227a8cf into f1a0f70d9
Pull Request #898: [PyTorch] Add support for aten.neg

26 of 38 new or added lines in 4 files covered. (68.42%)

43882 of 68002 relevant lines covered (64.53%)

722.06 hits per line

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

83.77
/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/logical_not_node.h"
15
#include "sdfg/data_flow/library_nodes/math/tensor/elementwise_ops/tasklet_node.h"
16
#include "sdfg/data_flow/library_nodes/metadata_node.h"
17
#include "sdfg/data_flow/library_nodes/stdlib/stdlib.h"
18

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

42
namespace sdfg {
43
namespace serializer {
44

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

52
    return FunctionType(str);
×
53
}
33✔
54

55
/*
56
 * * JSONSerializer class
57
 * * Serialization logic
58
 */
59

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

67
    j["name"] = sdfg.name();
31✔
68
    j["element_counter"] = sdfg.element_counter();
31✔
69
    j["type"] = std::string(sdfg.type().value());
31✔
70

71
    nlohmann::json return_type_json;
31✔
72
    type_to_json(return_type_json, sdfg.return_type());
31✔
73
    j["return_type"] = return_type_json;
31✔
74

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

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

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

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

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

108
    // Walk the SDFG
109
    if (this->recurse_) {
31✔
110
        nlohmann::json root_json;
31✔
111
        sequence_to_json(root_json, sdfg.root());
31✔
112
        j["root"] = root_json;
31✔
113
    }
31✔
114

115
    return j;
31✔
116
}
31✔
117

118
void JSONSerializer::serialize_node(nlohmann::json& j, const structured_control_flow::ControlFlowNode& node) {
225✔
119
    if (auto block = dynamic_cast<const structured_control_flow::Block*>(&node)) {
225✔
120
        block_to_json(j, *block);
53✔
121
    } else if (auto assignment_block = dynamic_cast<const structured_control_flow::AssignmentBlock*>(&node)) {
172✔
122
        assignment_block_to_json(j, *assignment_block);
3✔
123
    } else if (auto sequence_node = dynamic_cast<const structured_control_flow::Sequence*>(&node)) {
169✔
124
        sequence_to_json(j, *sequence_node);
×
125
    } else if (auto condition_node = dynamic_cast<const structured_control_flow::IfElse*>(&node)) {
169✔
126
        if_else_to_json(j, *condition_node);
×
127
    } else if (auto while_node = dynamic_cast<const structured_control_flow::While*>(&node)) {
169✔
128
        while_node_to_json(j, *while_node);
×
129
    } else if (auto return_node = dynamic_cast<const structured_control_flow::Return*>(&node)) {
169✔
130
        return_node_to_json(j, *return_node);
×
131
    } else if (auto break_node = dynamic_cast<const structured_control_flow::Break*>(&node)) {
169✔
132
        break_node_to_json(j, *break_node);
2✔
133
    } else if (auto continue_node = dynamic_cast<const structured_control_flow::Continue*>(&node)) {
167✔
134
        continue_node_to_json(j, *continue_node);
2✔
135
    } else if (auto loop_node = dynamic_cast<const structured_control_flow::StructuredLoop*>(&node)) {
165✔
136
        structured_loop_to_json(j, *loop_node);
165✔
137
    } else {
165✔
138
        throw std::runtime_error("Unknown child type");
×
139
    }
×
140
}
225✔
141

142
void JSONSerializer::dataflow_to_json(nlohmann::json& j, const data_flow::DataFlowGraph& dataflow) {
58✔
143
    j["type"] = "dataflow";
58✔
144
    j["nodes"] = nlohmann::json::array();
58✔
145
    j["edges"] = nlohmann::json::array();
58✔
146

147
    for (auto& node : dataflow.nodes()) {
230✔
148
        nlohmann::json node_json;
230✔
149
        node_json["element_id"] = node.element_id();
230✔
150

151
        node_json["debug_info"] = nlohmann::json::object();
230✔
152
        debug_info_to_json(node_json["debug_info"], node.debug_info());
230✔
153

154
        if (auto tasklet = dynamic_cast<const data_flow::Tasklet*>(&node)) {
230✔
155
            node_json["type"] = "tasklet";
62✔
156
            node_json["code"] = tasklet->code();
62✔
157
            node_json["inputs"] = nlohmann::json::array();
62✔
158
            for (auto& input : tasklet->inputs()) {
104✔
159
                node_json["inputs"].push_back(input);
104✔
160
            }
104✔
161
            node_json["output"] = tasklet->output();
62✔
162
        } else if (auto lib_node = dynamic_cast<const data_flow::LibraryNode*>(&node)) {
168✔
163
            node_json["type"] = "library_node";
13✔
164
            node_json["implementation_type"] = std::string(lib_node->implementation_type().value());
13✔
165
            auto serializer_fn =
13✔
166
                LibraryNodeSerializerRegistry::instance().get_library_node_serializer(lib_node->code().value());
13✔
167
            if (serializer_fn == nullptr) {
13✔
168
                throw std::runtime_error("Unknown library node code: " + std::string(lib_node->code().value()));
×
169
            }
×
170
            auto serializer = serializer_fn();
13✔
171
            auto lib_node_json = serializer->serialize(*lib_node);
13✔
172
            node_json.merge_patch(lib_node_json);
13✔
173
        } else if (auto code_node = dynamic_cast<const data_flow::ConstantNode*>(&node)) {
155✔
174
            node_json["type"] = "constant_node";
1✔
175
            node_json["data"] = code_node->data();
1✔
176

177
            nlohmann::json type_json;
1✔
178
            type_to_json(type_json, code_node->type());
1✔
179
            node_json["data_type"] = type_json;
1✔
180
        } else if (auto code_node = dynamic_cast<const data_flow::AccessNode*>(&node)) {
154✔
181
            node_json["type"] = "access_node";
154✔
182
            node_json["data"] = code_node->data();
154✔
183
        } else {
154✔
184
            throw std::runtime_error("Unknown node type");
×
185
        }
×
186

187
        j["nodes"].push_back(node_json);
230✔
188
    }
230✔
189

190
    for (auto& edge : dataflow.edges()) {
200✔
191
        nlohmann::json edge_json;
200✔
192
        edge_json["element_id"] = edge.element_id();
200✔
193

194
        edge_json["debug_info"] = nlohmann::json::object();
200✔
195
        debug_info_to_json(edge_json["debug_info"], edge.debug_info());
200✔
196

197
        edge_json["src"] = edge.src().element_id();
200✔
198
        edge_json["dst"] = edge.dst().element_id();
200✔
199

200
        edge_json["src_conn"] = edge.src_conn();
200✔
201
        edge_json["dst_conn"] = edge.dst_conn();
200✔
202

203
        edge_json["subset"] = nlohmann::json::array();
200✔
204
        for (auto& subset : edge.subset()) {
200✔
205
            edge_json["subset"].push_back(expression(subset));
72✔
206
        }
72✔
207

208
        nlohmann::json base_type_json;
200✔
209
        type_to_json(base_type_json, edge.base_type());
200✔
210
        edge_json["base_type"] = base_type_json;
200✔
211

212
        j["edges"].push_back(edge_json);
200✔
213
    }
200✔
214
}
58✔
215

216
void JSONSerializer::block_to_json(nlohmann::json& j, const structured_control_flow::Block& block) {
55✔
217
    j["type"] = "block";
55✔
218
    j["element_id"] = block.element_id();
55✔
219

220
    j["debug_info"] = nlohmann::json::object();
55✔
221
    debug_info_to_json(j["debug_info"], block.debug_info());
55✔
222

223
    if (this->recurse_) {
55✔
224
        nlohmann::json dataflow_json;
55✔
225
        dataflow_to_json(dataflow_json, block.dataflow());
55✔
226
        j["dataflow"] = dataflow_json;
55✔
227
    }
55✔
228
}
55✔
229

230
void JSONSerializer::assignment_block_to_json(nlohmann::json& j, const structured_control_flow::AssignmentBlock& block) {
3✔
231
    j["type"] = "assignment_block";
3✔
232
    j["element_id"] = block.element_id();
3✔
233
    j["debug_info"] = nlohmann::json::object();
3✔
234
    debug_info_to_json(j["debug_info"], block.debug_info());
3✔
235

236
    if (this->recurse_) {
3✔
237
        auto arr = nlohmann::json::array();
3✔
238
        for (const auto& assignment : block.assignments()) {
3✔
239
            nlohmann::json assignment_json;
3✔
240
            assignment_json["symbol"] = expression(assignment.first);
3✔
241
            assignment_json["expression"] = expression(assignment.second);
3✔
242
            arr.push_back(assignment_json);
3✔
243
        }
3✔
244
        j["assignments"] = arr;
3✔
245
    }
3✔
246
}
3✔
247

248
void JSONSerializer::structured_loop_to_json(nlohmann::json& j, const structured_control_flow::StructuredLoop& for_node) {
171✔
249
    j["type"] = "for";
171✔
250
    // Backward compatibility (now encapsulated in sub_type)
251
    if (dynamic_cast<const structured_control_flow::Map*>(&for_node)) {
171✔
252
        j["type"] = "map";
64✔
253
    }
64✔
254

255
    j["element_id"] = for_node.element_id();
171✔
256
    j["debug_info"] = nlohmann::json::object();
171✔
257
    debug_info_to_json(j["debug_info"], for_node.debug_info());
171✔
258

259
    j["indvar"] = expression(for_node.indvar());
171✔
260
    j["init"] = expression(for_node.init());
171✔
261
    j["condition"] = expression(for_node.condition());
171✔
262
    j["update"] = expression(for_node.update());
171✔
263

264
    j["schedule_type"] = nlohmann::json::object();
171✔
265
    schedule_type_to_json(j["schedule_type"], for_node.schedule_type());
171✔
266

267
    j["sub_type"] = "for";
171✔
268
    if (dynamic_cast<const structured_control_flow::Map*>(&for_node)) {
171✔
269
        j["sub_type"] = "map";
64✔
270
    } else if (dynamic_cast<const structured_control_flow::Reduce*>(&for_node)) {
107✔
271
        j["sub_type"] = "reduce";
2✔
272
        j["reductions"] = nlohmann::json::array();
2✔
273
        const auto& reduce_node = dynamic_cast<const structured_control_flow::Reduce&>(for_node);
2✔
274
        for (const auto& reduction : reduce_node.reductions()) {
2✔
275
            nlohmann::json reduction_json;
2✔
276
            reduction_json["op"] = structured_control_flow::reduction_operation_to_string(reduction.operation);
2✔
277
            reduction_json["container"] = reduction.container;
2✔
278
            j["reductions"].push_back(reduction_json);
2✔
279
        }
2✔
280
    }
2✔
281

282
    if (this->recurse_) {
171✔
283
        nlohmann::json body_json;
31✔
284
        sequence_to_json(body_json, for_node.root());
31✔
285
        j["root"] = body_json;
31✔
286
    }
31✔
287
}
171✔
288

289
void JSONSerializer::if_else_to_json(nlohmann::json& j, const structured_control_flow::IfElse& if_else_node) {
2✔
290
    j["type"] = "if_else";
2✔
291
    j["element_id"] = if_else_node.element_id();
2✔
292

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

296
    j["branches"] = nlohmann::json::array();
2✔
297
    for (size_t i = 0; i < if_else_node.size(); i++) {
6✔
298
        nlohmann::json branch_json;
4✔
299
        branch_json["condition"] = expression(if_else_node.at(i).second);
4✔
300
        if (this->recurse_) {
4✔
301
            nlohmann::json body_json;
4✔
302
            sequence_to_json(body_json, if_else_node.at(i).first);
4✔
303
            branch_json["root"] = body_json;
4✔
304
        }
4✔
305
        j["branches"].push_back(branch_json);
4✔
306
    }
4✔
307
}
2✔
308

309
void JSONSerializer::while_node_to_json(nlohmann::json& j, const structured_control_flow::While& while_node) {
5✔
310
    j["type"] = "while";
5✔
311
    j["element_id"] = while_node.element_id();
5✔
312

313
    j["debug_info"] = nlohmann::json::object();
5✔
314
    debug_info_to_json(j["debug_info"], while_node.debug_info());
5✔
315

316
    if (this->recurse_) {
5✔
317
        nlohmann::json body_json;
5✔
318
        sequence_to_json(body_json, while_node.root());
5✔
319
        j["root"] = body_json;
5✔
320
    }
5✔
321
}
5✔
322

323
void JSONSerializer::break_node_to_json(nlohmann::json& j, const structured_control_flow::Break& break_node) {
2✔
324
    j["type"] = "break";
2✔
325
    j["element_id"] = break_node.element_id();
2✔
326

327
    j["debug_info"] = nlohmann::json::object();
2✔
328
    debug_info_to_json(j["debug_info"], break_node.debug_info());
2✔
329
}
2✔
330

331
void JSONSerializer::continue_node_to_json(nlohmann::json& j, const structured_control_flow::Continue& continue_node) {
2✔
332
    j["type"] = "continue";
2✔
333
    j["element_id"] = continue_node.element_id();
2✔
334

335
    j["debug_info"] = nlohmann::json::object();
2✔
336
    debug_info_to_json(j["debug_info"], continue_node.debug_info());
2✔
337
}
2✔
338

339
void JSONSerializer::return_node_to_json(nlohmann::json& j, const structured_control_flow::Return& return_node) {
2✔
340
    j["type"] = "return";
2✔
341
    j["element_id"] = return_node.element_id();
2✔
342
    j["data"] = return_node.data();
2✔
343

344
    if (return_node.is_constant()) {
2✔
345
        nlohmann::json type_json;
×
346
        type_to_json(type_json, return_node.type());
×
347
        j["data_type"] = type_json;
×
348
    }
×
349

350
    j["debug_info"] = nlohmann::json::object();
2✔
351
    debug_info_to_json(j["debug_info"], return_node.debug_info());
2✔
352
}
2✔
353

354
void JSONSerializer::sequence_to_json(nlohmann::json& j, const structured_control_flow::Sequence& sequence) {
76✔
355
    j["type"] = "sequence";
76✔
356
    j["element_id"] = sequence.element_id();
76✔
357

358
    j["debug_info"] = nlohmann::json::object();
76✔
359
    debug_info_to_json(j["debug_info"], sequence.debug_info());
76✔
360

361
    if (!this->recurse_) {
76✔
362
        return;
×
363
    }
×
364

365
    j["children"] = nlohmann::json::array();
76✔
366
    for (size_t i = 0; i < sequence.size(); i++) {
161✔
367
        nlohmann::json child_json;
85✔
368
        auto& child = sequence.at(i);
85✔
369

370
        this->serialize_node(child_json, child);
85✔
371
        j["children"].push_back(child_json);
85✔
372
    }
85✔
373
}
76✔
374

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

455
void JSONSerializer::structure_definition_to_json(nlohmann::json& j, const types::StructureDefinition& definition) {
2✔
456
    j["name"] = definition.name();
2✔
457
    j["members"] = nlohmann::json::array();
2✔
458
    for (size_t i = 0; i < definition.num_members(); i++) {
4✔
459
        nlohmann::json member_json;
2✔
460
        type_to_json(member_json, definition.member_type(symbolic::integer(i)));
2✔
461
        j["members"].push_back(member_json);
2✔
462
    }
2✔
463
    j["is_packed"] = definition.is_packed();
2✔
464
}
2✔
465

466
void JSONSerializer::debug_info_to_json(nlohmann::json& j, const DebugInfo& debug_info) {
748✔
467
    j["has"] = debug_info.has();
748✔
468
    j["filename"] = debug_info.filename();
748✔
469
    j["function"] = debug_info.function();
748✔
470
    j["start_line"] = debug_info.start_line();
748✔
471
    j["start_column"] = debug_info.start_column();
748✔
472
    j["end_line"] = debug_info.end_line();
748✔
473
    j["end_column"] = debug_info.end_column();
748✔
474
}
748✔
475

476

477
void JSONSerializer::schedule_type_to_json(nlohmann::json& j, const ScheduleType& schedule_type) {
173✔
478
    j["value"] = schedule_type.value();
173✔
479
    j["category"] = static_cast<int>(schedule_type.category());
173✔
480
    j["properties"] = nlohmann::json::object();
173✔
481
    for (const auto& prop : schedule_type.properties()) {
173✔
482
        j["properties"][prop.first] = prop.second;
4✔
483
    }
4✔
484
}
173✔
485

486
void JSONSerializer::storage_type_to_json(nlohmann::json& j, const types::StorageType& storage_type) {
635✔
487
    j["value"] = storage_type.value();
635✔
488
    j["allocation"] = storage_type.allocation();
635✔
489
    j["deallocation"] = storage_type.deallocation();
635✔
490
    if (!storage_type.allocation_size().is_null()) {
635✔
491
        j["allocation_size"] = expression(storage_type.allocation_size());
×
492
    }
×
493
    const symbolic::Expression& arg1 = storage_type.arg1();
635✔
494
    if (!arg1.is_null()) {
635✔
495
        auto args = nlohmann::json::array();
×
496
        args.push_back(expression(arg1));
×
497
        j["args"] = args;
×
498
    }
×
499
}
635✔
500

501

502
/*
503
 * * Deserialization logic
504
 */
505

506
std::unique_ptr<StructuredSDFG> JSONSerializer::deserialize(nlohmann::json& j) {
33✔
507
    assert(j.contains("name"));
33✔
508
    assert(j["name"].is_string());
33✔
509
    assert(j.contains("type"));
33✔
510
    assert(j["type"].is_string());
33✔
511
    assert(j.contains("element_counter"));
33✔
512
    assert(j["element_counter"].is_number_integer());
33✔
513

514
    std::unique_ptr<types::IType> return_type;
33✔
515
    if (j.contains("return_type")) {
33✔
516
        return_type = json_to_type(j["return_type"]);
33✔
517
    } else {
33✔
518
        return_type = std::make_unique<types::Scalar>(types::PrimitiveType::Void);
×
519
    }
×
520

521
    FunctionType function_type = function_type_from_string(j["type"].get<std::string>());
33✔
522
    builder::StructuredSDFGBuilder builder(j["name"], function_type, *return_type);
33✔
523

524
    size_t element_counter = j["element_counter"];
33✔
525
    builder.set_element_counter(element_counter);
33✔
526

527
    // deserialize structures
528
    assert(j.contains("structures"));
33✔
529
    assert(j["structures"].is_array());
33✔
530
    for (const auto& structure : j["structures"]) {
33✔
531
        assert(structure.contains("name"));
1✔
532
        assert(structure["name"].is_string());
1✔
533
        json_to_structure_definition(structure, builder);
1✔
534
    }
1✔
535

536
    nlohmann::json& containers = j["containers"];
33✔
537

538
    // deserialize externals
539
    for (const auto& external : j["externals"]) {
33✔
540
        assert(external.contains("name"));
9✔
541
        assert(external["name"].is_string());
9✔
542
        assert(external.contains("linkage_type"));
9✔
543
        assert(external["linkage_type"].is_number_integer());
9✔
544
        auto& type_desc = containers.at(external["name"].get<std::string>());
9✔
545
        auto type = json_to_type(type_desc);
9✔
546
        builder.add_external(external["name"], *type, LinkageType(external["linkage_type"]));
9✔
547
    }
9✔
548

549
    // deserialize arguments
550
    for (const auto& name : j["arguments"]) {
49✔
551
        auto& type_desc = containers.at(name.get<std::string>());
49✔
552
        auto type = json_to_type(type_desc);
49✔
553
        builder.add_container(name, *type, true, false);
49✔
554
    }
49✔
555

556
    // deserialize transients
557
    for (const auto& entry : containers.items()) {
169✔
558
        if (builder.subject().is_argument(entry.key())) {
169✔
559
            continue;
49✔
560
        }
49✔
561
        if (builder.subject().is_external(entry.key())) {
120✔
562
            continue;
9✔
563
        }
9✔
564
        auto type = json_to_type(entry.value());
111✔
565
        builder.add_container(entry.key(), *type, false, false);
111✔
566
    }
111✔
567

568
    // deserialize root node
569
    assert(j.contains("root"));
33✔
570
    auto& root = builder.subject().root();
33✔
571
    json_to_sequence(j["root"], builder, root);
33✔
572

573
    // deserialize metadata
574
    assert(j.contains("metadata"));
33✔
575
    assert(j["metadata"].is_object());
33✔
576
    for (const auto& entry : j["metadata"].items()) {
33✔
577
        builder.subject().add_metadata(entry.key(), entry.value());
1✔
578
    }
1✔
579

580
    builder.set_element_counter(element_counter);
33✔
581

582
    return builder.move();
33✔
583
}
33✔
584

585
void JSONSerializer::json_to_structure_definition(const nlohmann::json& j, builder::StructuredSDFGBuilder& builder) {
2✔
586
    assert(j.contains("name"));
2✔
587
    assert(j["name"].is_string());
2✔
588
    assert(j.contains("members"));
2✔
589
    assert(j["members"].is_array());
2✔
590
    assert(j.contains("is_packed"));
2✔
591
    assert(j["is_packed"].is_boolean());
2✔
592
    auto is_packed = j["is_packed"];
2✔
593
    auto& definition = builder.add_structure(j["name"], is_packed);
2✔
594
    for (const auto& member : j["members"]) {
2✔
595
        nlohmann::json member_json;
2✔
596
        auto member_type = json_to_type(member);
2✔
597
        definition.add_member(*member_type);
2✔
598
    }
2✔
599
}
2✔
600

601
std::vector<std::pair<std::string, types::Scalar>> JSONSerializer::json_to_arguments(const nlohmann::json& j) {
×
602
    std::vector<std::pair<std::string, types::Scalar>> arguments;
×
603
    for (const auto& argument : j) {
×
604
        assert(argument.contains("name"));
×
605
        assert(argument["name"].is_string());
×
606
        assert(argument.contains("type"));
×
607
        assert(argument["type"].is_object());
×
608
        std::string name = argument["name"];
×
609
        auto type = json_to_type(argument["type"]);
×
610
        arguments.emplace_back(name, *dynamic_cast<types::Scalar*>(type.get()));
×
611
    }
×
612
    return arguments;
×
613
}
×
614

615
void JSONSerializer::json_to_dataflow(
616
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Block& parent
617
) {
50✔
618
    std::map<size_t, data_flow::DataFlowNode&> nodes_map;
50✔
619

620
    assert(j.contains("nodes"));
50✔
621
    assert(j["nodes"].is_array());
50✔
622
    for (const auto& node : j["nodes"]) {
226✔
623
        assert(node.contains("type"));
226✔
624
        assert(node["type"].is_string());
226✔
625
        assert(node.contains("element_id"));
226✔
626
        assert(node["element_id"].is_number_integer());
226✔
627
        std::string type = node["type"];
226✔
628
        if (type == "tasklet") {
226✔
629
            assert(node.contains("code"));
61✔
630
            assert(node["code"].is_number_integer());
61✔
631
            assert(node.contains("inputs"));
61✔
632
            assert(node["inputs"].is_array());
61✔
633
            assert(node.contains("output"));
61✔
634
            assert(node["output"].is_string());
61✔
635
            auto inputs = node["inputs"].get<std::vector<std::string>>();
61✔
636

637
            auto& tasklet =
61✔
638
                builder
61✔
639
                    .add_tasklet(parent, node["code"], node["output"], inputs, json_to_debug_info(node["debug_info"]));
61✔
640
            tasklet.element_id_ = node["element_id"];
61✔
641
            nodes_map.insert({node["element_id"], tasklet});
61✔
642
        } else if (type == "library_node") {
165✔
643
            assert(node.contains("code"));
13✔
644
            data_flow::LibraryNodeCode code(node["code"].get<std::string>());
13✔
645

646
            auto serializer_fn = LibraryNodeSerializerRegistry::instance().get_library_node_serializer(code.value());
13✔
647
            if (serializer_fn == nullptr) {
13✔
648
                throw std::runtime_error("Unknown library node code: " + std::string(code.value()));
×
649
            }
×
650
            auto serializer = serializer_fn();
13✔
651
            auto& lib_node = serializer->deserialize(node, builder, parent);
13✔
652
            lib_node.implementation_type() =
13✔
653
                data_flow::ImplementationType(node["implementation_type"].get<std::string>());
13✔
654
            lib_node.element_id_ = node["element_id"];
13✔
655
            nodes_map.insert({node["element_id"], lib_node});
13✔
656
        } else if (type == "access_node") {
152✔
657
            assert(node.contains("data"));
151✔
658
            auto& access_node = builder.add_access(parent, node["data"], json_to_debug_info(node["debug_info"]));
151✔
659
            access_node.element_id_ = node["element_id"];
151✔
660
            nodes_map.insert({node["element_id"], access_node});
151✔
661
        } else if (type == "constant_node") {
151✔
662
            assert(node.contains("data"));
1✔
663
            assert(node.contains("data_type"));
1✔
664

665
            auto type = json_to_type(node["data_type"]);
1✔
666

667
            auto& constant_node =
1✔
668
                builder.add_constant(parent, node["data"], *type, json_to_debug_info(node["debug_info"]));
1✔
669
            constant_node.element_id_ = node["element_id"];
1✔
670
            nodes_map.insert({node["element_id"], constant_node});
1✔
671
        } else {
1✔
672
            throw std::runtime_error("Unknown node type");
×
673
        }
×
674
    }
226✔
675

676
    assert(j.contains("edges"));
50✔
677
    assert(j["edges"].is_array());
50✔
678
    for (const auto& edge : j["edges"]) {
197✔
679
        assert(edge.contains("src"));
197✔
680
        assert(edge["src"].is_number_integer());
197✔
681
        assert(edge.contains("dst"));
197✔
682
        assert(edge["dst"].is_number_integer());
197✔
683
        assert(edge.contains("src_conn"));
197✔
684
        assert(edge["src_conn"].is_string());
197✔
685
        assert(edge.contains("dst_conn"));
197✔
686
        assert(edge["dst_conn"].is_string());
197✔
687
        assert(edge.contains("subset"));
197✔
688
        assert(edge["subset"].is_array());
197✔
689

690
        assert(nodes_map.find(edge["src"]) != nodes_map.end());
197✔
691
        assert(nodes_map.find(edge["dst"]) != nodes_map.end());
197✔
692
        auto& source = nodes_map.at(edge["src"]);
197✔
693
        auto& target = nodes_map.at(edge["dst"]);
197✔
694

695
        auto base_type = json_to_type(edge["base_type"]);
197✔
696

697
        assert(edge.contains("subset"));
197✔
698
        assert(edge["subset"].is_array());
197✔
699
        std::vector<symbolic::Expression> subset;
197✔
700
        for (const auto& subset_ : edge["subset"]) {
197✔
701
            assert(subset_.is_string());
70✔
702
            std::string subset_str = subset_;
70✔
703
            auto expr = symbolic::parse(subset_str);
70✔
704
            subset.push_back(expr);
70✔
705
        }
70✔
706
        auto& memlet = builder.add_memlet(
197✔
707
            parent,
197✔
708
            source,
197✔
709
            edge["src_conn"],
197✔
710
            target,
197✔
711
            edge["dst_conn"],
197✔
712
            subset,
197✔
713
            *base_type,
197✔
714
            json_to_debug_info(edge["debug_info"])
197✔
715
        );
197✔
716
        memlet.element_id_ = edge["element_id"];
197✔
717
    }
197✔
718
}
50✔
719

720
control_flow::Assignments JSONSerializer::parse_assignments(const nlohmann::json& assignments_arr) {
4✔
721
    assert(assignments_arr.is_array());
4✔
722

723
    control_flow::Assignments assignments;
4✔
724
    for (const auto& assignment : assignments_arr) {
4✔
725
        assert(assignment.contains("symbol"));
3✔
726
        assert(assignment["symbol"].is_string());
3✔
727
        assert(assignment.contains("expression"));
3✔
728
        assert(assignment["expression"].is_string());
3✔
729
        auto expr = symbolic::parse(assignment["expression"].get<std::string>());
3✔
730
        assignments.insert({symbolic::symbol(assignment["symbol"]), expr});
3✔
731
    }
3✔
732

733
    return std::move(assignments);
4✔
734
}
4✔
735

736
void JSONSerializer::parse_legacy_transition_to_assignment_block(
737
    const nlohmann::json& j,
738
    sdfg::builder::StructuredSDFGBuilder& builder,
739
    sdfg::structured_control_flow::Sequence& parent
740
) {
2✔
741
    assert(j.contains("type"));
2✔
742
    assert(j["type"].is_string());
2✔
743
    assert(j["type"] == "transition");
2✔
744
    assert(j.contains("assignments"));
2✔
745
    auto& assignments_arr = j["assignments"];
2✔
746

747
    auto assignments = parse_assignments(assignments_arr);
2✔
748

749
    if (!skip_empty_transitions || !assignments.empty()) {
2✔
750
        auto& block = builder.add_assignments(parent, assignments, json_to_debug_info(j["debug_info"]));
2✔
751
        block.element_id_ = j["element_id"];
2✔
752
    }
2✔
753
}
2✔
754

755
void JSONSerializer::json_to_sequence(
756
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& sequence
757
) {
69✔
758
    assert(j.contains("type"));
69✔
759
    assert(j["type"].is_string());
69✔
760
    assert(j.contains("children"));
69✔
761
    assert(j["children"].is_array());
69✔
762
    auto child_count = j["children"].size();
69✔
763

764
    sequence.element_id_ = j["element_id"];
69✔
765
    sequence.debug_info_ = json_to_debug_info(j["debug_info"]);
69✔
766

767
    std::string type = j["type"];
69✔
768
    if (type == "sequence") {
69✔
769
        auto transition_it = j.find("transitions");
69✔
770
        const nlohmann::json* transition_arr = nullptr;
69✔
771
        if (transition_it != j.end()) {
69✔
772
            auto& transitions = *transition_it;
1✔
773
            if (transitions.is_array() && transitions.size() == child_count) {
1✔
774
                transition_arr = &transitions;
1✔
775
            } else {
1✔
776
                throw std::runtime_error(
×
777
                    "Contains legacy transitions, but count differs from chil count: " +
×
778
                    std::to_string(transitions.size()) + " vs. " + std::to_string(child_count)
×
779
                );
×
780
            }
×
781
        }
1✔
782

783
        for (size_t i = 0; i < child_count; i++) {
145✔
784
            auto& child = j["children"][i];
76✔
785

786
            auto child_type = child["type"];
76✔
787
            if (child_type == "block") {
76✔
788
                json_to_block_node(child, builder, sequence);
47✔
789
            } else if (child_type == "assignment_block") {
47✔
790
                json_to_assignment_block(child, builder, sequence);
2✔
791
            } else if (child_type == "if_else") {
27✔
792
                json_to_if_else_node(child, builder, sequence);
×
793
            } else if (child_type == "while") {
27✔
794
                json_to_while_node(child, builder, sequence);
×
795
            } else if (child_type == "break") {
27✔
796
                json_to_break_node(child, builder, sequence);
1✔
797
            } else if (child_type == "continue") {
26✔
798
                json_to_continue_node(child, builder, sequence);
1✔
799
            } else if (child_type == "return") {
25✔
800
                json_to_return_node(child, builder, sequence);
×
801
            } else if (child_type == "for" || child_type == "map") {
25✔
802
                json_to_structured_loop_node(child, builder, sequence);
25✔
803
            } else if (child_type == "sequence") {
25✔
804
                auto& subseq = builder.add_sequence(sequence, json_to_debug_info(child["debug_info"]));
×
805
                json_to_sequence(child, builder, subseq);
×
806
            } else {
×
807
                throw std::runtime_error("Unknown child type");
×
808
            }
×
809

810
            if (transition_arr) {
76✔
811
                // parses the transition after having already added its element
812
                // will then add the Transitions as a AssignmentBlock instead
813
                // keeps the original order of instructions, but changes sequence element count
814
                parse_legacy_transition_to_assignment_block(transition_arr->at(i), builder, sequence);
2✔
815
            }
2✔
816
        }
76✔
817
    } else {
69✔
818
        throw std::runtime_error("expected sequence type");
×
819
    }
×
820
}
69✔
821

822
void JSONSerializer::json_to_block_node(
823
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& parent
824
) {
48✔
825
    assert(j.contains("type"));
48✔
826
    assert(j["type"].is_string());
48✔
827
    assert(j.contains("dataflow"));
48✔
828
    assert(j["dataflow"].is_object());
48✔
829
    auto& block = builder.add_block(parent, json_to_debug_info(j["debug_info"]));
48✔
830
    block.element_id_ = j["element_id"];
48✔
831
    assert(j["dataflow"].contains("type"));
48✔
832
    assert(j["dataflow"]["type"].is_string());
48✔
833
    std::string type = j["dataflow"]["type"];
48✔
834
    if (type == "dataflow") {
48✔
835
        json_to_dataflow(j["dataflow"], builder, block);
48✔
836
    } else {
48✔
837
        throw std::runtime_error("Unknown dataflow type");
×
838
    }
×
839
}
48✔
840

841
void JSONSerializer::json_to_assignment_block(
842
    const nlohmann::json& j,
843
    sdfg::builder::StructuredSDFGBuilder& builder,
844
    sdfg::structured_control_flow::Sequence& parent
845
) {
2✔
846
    assert(j.contains("type"));
2✔
847
    assert(j["type"].is_string());
2✔
848
    assert(j["type"] == "assignment_block");
2✔
849
    assert(j.contains("assignments"));
2✔
850
    auto assignments_arr = j["assignments"];
2✔
851
    assert(assignments_arr.is_array());
2✔
852

853
    control_flow::Assignments assignments = parse_assignments(assignments_arr);
2✔
854

855
    auto& block = builder.add_assignments(parent, assignments, json_to_debug_info(j["debug_info"]));
2✔
856
    block.element_id_ = j["element_id"];
2✔
857
}
2✔
858

859
void JSONSerializer::json_to_structured_loop_node(
860
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& parent
861
) {
28✔
862
    // Backward compatibility: if the type is "map"
863
    if (j["type"] == "map") {
28✔
864
        json_to_map_node(j, builder, parent);
7✔
865
        return;
7✔
866
    }
7✔
867
    // Sub types
868
    if (j.contains("sub_type")) {
21✔
869
        std::string sub_type = j["sub_type"];
21✔
870
        if (sub_type == "map") {
21✔
871
            json_to_map_node(j, builder, parent);
×
872
            return;
×
873
        } else if (sub_type == "reduce") {
21✔
874
            json_to_reduce_node(j, builder, parent);
1✔
875
            return;
1✔
876
        }
1✔
877
    }
21✔
878

879
    assert(j.contains("type"));
21✔
880
    assert(j["type"].is_string());
20✔
881
    assert(j.contains("indvar"));
20✔
882
    assert(j["indvar"].is_string());
20✔
883
    assert(j.contains("init"));
20✔
884
    assert(j["init"].is_string());
20✔
885
    assert(j.contains("condition"));
20✔
886
    assert(j["condition"].is_string());
20✔
887
    assert(j.contains("update"));
20✔
888
    assert(j["update"].is_string());
20✔
889
    assert(j.contains("root"));
20✔
890
    assert(j["root"].is_object());
20✔
891

892
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
20✔
893
    auto init = symbolic::parse(j["init"].get<std::string>());
20✔
894
    auto update = symbolic::parse(j["update"].get<std::string>());
20✔
895

896
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
20✔
897
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
20✔
898
    if (condition.is_null()) {
20✔
899
        throw InvalidSDFGException("For loop condition is not a boolean expression");
×
900
    }
×
901

902
    auto& for_node = builder.add_for(parent, indvar, condition, init, update, json_to_debug_info(j["debug_info"]));
20✔
903
    for_node.element_id_ = j["element_id"];
20✔
904

905
    assert(j["root"].contains("type"));
20✔
906
    assert(j["root"]["type"].is_string());
20✔
907
    assert(j["root"]["type"] == "sequence");
20✔
908
    json_to_sequence(j["root"], builder, for_node.root());
20✔
909
}
20✔
910

911
void JSONSerializer::json_to_if_else_node(
912
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& parent
913
) {
1✔
914
    assert(j.contains("type"));
1✔
915
    assert(j["type"].is_string());
1✔
916
    assert(j["type"] == "if_else");
1✔
917
    assert(j.contains("branches"));
1✔
918
    assert(j["branches"].is_array());
1✔
919
    auto& if_else_node = builder.add_if_else(parent, json_to_debug_info(j["debug_info"]));
1✔
920
    if_else_node.element_id_ = j["element_id"];
1✔
921
    for (const auto& branch : j["branches"]) {
2✔
922
        assert(branch.contains("condition"));
2✔
923
        assert(branch["condition"].is_string());
2✔
924
        assert(branch.contains("root"));
2✔
925
        assert(branch["root"].is_object());
2✔
926

927
        auto condition_expr = symbolic::parse(branch["condition"].get<std::string>());
2✔
928
        symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
2✔
929
        if (condition.is_null()) {
2✔
930
            throw InvalidSDFGException("If condition is not a boolean expression");
×
931
        }
×
932
        auto& branch_node = builder.add_case(if_else_node, condition);
2✔
933
        assert(branch["root"].contains("type"));
2✔
934
        assert(branch["root"]["type"].is_string());
2✔
935
        std::string type = branch["root"]["type"];
2✔
936
        if (type == "sequence") {
2✔
937
            json_to_sequence(branch["root"], builder, branch_node);
2✔
938
        } else {
2✔
939
            throw std::runtime_error("Unknown child type");
×
940
        }
×
941
    }
2✔
942
}
1✔
943

944
void JSONSerializer::json_to_while_node(
945
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& parent
946
) {
3✔
947
    assert(j.contains("type"));
3✔
948
    assert(j["type"].is_string());
3✔
949
    assert(j["type"] == "while");
3✔
950
    assert(j.contains("root"));
3✔
951
    assert(j["root"].is_object());
3✔
952

953
    auto& while_node = builder.add_while(parent, json_to_debug_info(j["debug_info"]));
3✔
954
    while_node.element_id_ = j["element_id"];
3✔
955

956
    assert(j["root"]["type"] == "sequence");
3✔
957
    json_to_sequence(j["root"], builder, while_node.root());
3✔
958
}
3✔
959

960
void JSONSerializer::json_to_break_node(
961
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& parent
962
) {
1✔
963
    assert(j.contains("type"));
1✔
964
    assert(j["type"].is_string());
1✔
965
    assert(j["type"] == "break");
1✔
966
    auto& node = builder.add_break(parent, json_to_debug_info(j["debug_info"]));
1✔
967
    node.element_id_ = j["element_id"];
1✔
968
}
1✔
969

970
void JSONSerializer::json_to_continue_node(
971
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& parent
972
) {
1✔
973
    assert(j.contains("type"));
1✔
974
    assert(j["type"].is_string());
1✔
975
    assert(j["type"] == "continue");
1✔
976
    auto& node = builder.add_continue(parent, json_to_debug_info(j["debug_info"]));
1✔
977
    node.element_id_ = j["element_id"];
1✔
978
}
1✔
979

980
void JSONSerializer::json_to_map_node(
981
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& parent
982
) {
7✔
983
    assert(j.contains("type"));
7✔
984
    assert(j["type"].is_string());
7✔
985
    assert(j["type"] == "map");
7✔
986
    assert(j.contains("indvar"));
7✔
987
    assert(j["indvar"].is_string());
7✔
988
    assert(j.contains("init"));
7✔
989
    assert(j["init"].is_string());
7✔
990
    assert(j.contains("condition"));
7✔
991
    assert(j["condition"].is_string());
7✔
992
    assert(j.contains("update"));
7✔
993
    assert(j["update"].is_string());
7✔
994
    assert(j.contains("root"));
7✔
995
    assert(j["root"].is_object());
7✔
996
    assert(j.contains("schedule_type"));
7✔
997
    assert(j["schedule_type"].is_object());
7✔
998

999
    structured_control_flow::ScheduleType schedule_type = json_to_schedule_type(j["schedule_type"]);
7✔
1000

1001
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
7✔
1002
    auto init = symbolic::parse(j["init"].get<std::string>());
7✔
1003
    auto update = symbolic::parse(j["update"].get<std::string>());
7✔
1004
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
7✔
1005
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
7✔
1006
    if (condition.is_null()) {
7✔
1007
        throw InvalidSDFGException("Map condition is not a boolean expression");
×
1008
    }
×
1009

1010
    auto& map_node =
7✔
1011
        builder.add_map(parent, indvar, condition, init, update, schedule_type, json_to_debug_info(j["debug_info"]));
7✔
1012
    map_node.element_id_ = j["element_id"];
7✔
1013

1014
    assert(j["root"].contains("type"));
7✔
1015
    assert(j["root"]["type"].is_string());
7✔
1016
    assert(j["root"]["type"] == "sequence");
7✔
1017
    json_to_sequence(j["root"], builder, map_node.root());
7✔
1018
}
7✔
1019

1020
void JSONSerializer::json_to_reduce_node(
1021
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& parent
1022
) {
1✔
1023
    assert(j.contains("type"));
1✔
1024
    assert(j["type"].is_string());
1✔
1025
    assert(j["type"] == "for");
1✔
1026
    assert(j.contains("sub_type"));
1✔
1027
    assert(j["sub_type"].is_string());
1✔
1028
    assert(j["sub_type"] == "reduce");
1✔
1029
    assert(j.contains("indvar"));
1✔
1030
    assert(j["indvar"].is_string());
1✔
1031
    assert(j.contains("init"));
1✔
1032
    assert(j["init"].is_string());
1✔
1033
    assert(j.contains("condition"));
1✔
1034
    assert(j["condition"].is_string());
1✔
1035
    assert(j.contains("update"));
1✔
1036
    assert(j["update"].is_string());
1✔
1037
    assert(j.contains("root"));
1✔
1038
    assert(j["root"].is_object());
1✔
1039
    assert(j.contains("reductions"));
1✔
1040
    assert(j["reductions"].is_array());
1✔
1041
    assert(j.contains("schedule_type"));
1✔
1042
    assert(j["schedule_type"].is_object());
1✔
1043

1044
    std::vector<structured_control_flow::ReductionInfo> reductions;
1✔
1045
    for (const auto& reduction_json : j["reductions"]) {
1✔
1046
        assert(reduction_json.contains("op"));
1✔
1047
        assert(reduction_json["op"].is_string());
1✔
1048
        assert(reduction_json.contains("container"));
1✔
1049
        assert(reduction_json["container"].is_string());
1✔
1050
        reductions.push_back(structured_control_flow::ReductionInfo{
1✔
1051
            structured_control_flow::reduction_operation_from_string(reduction_json["op"].get<std::string>()),
1✔
1052
            reduction_json["container"].get<std::string>()
1✔
1053
        });
1✔
1054
    }
1✔
1055

1056
    structured_control_flow::ScheduleType schedule_type = json_to_schedule_type(j["schedule_type"]);
1✔
1057

1058
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
1✔
1059
    auto init = symbolic::parse(j["init"].get<std::string>());
1✔
1060
    auto update = symbolic::parse(j["update"].get<std::string>());
1✔
1061
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
1✔
1062
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
1✔
1063
    if (condition.is_null()) {
1✔
1064
        throw InvalidSDFGException("Reduce condition is not a boolean expression");
×
1065
    }
×
1066

1067
    auto& reduce_node = builder.add_reduce(
1✔
1068
        parent, indvar, condition, init, update, reductions, schedule_type, json_to_debug_info(j["debug_info"])
1✔
1069
    );
1✔
1070
    reduce_node.element_id_ = j["element_id"];
1✔
1071

1072
    assert(j["root"].contains("type"));
1✔
1073
    assert(j["root"]["type"].is_string());
1✔
1074
    assert(j["root"]["type"] == "sequence");
1✔
1075
    json_to_sequence(j["root"], builder, reduce_node.root());
1✔
1076
}
1✔
1077

1078
void JSONSerializer::json_to_return_node(
1079
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& parent
1080
) {
1✔
1081
    assert(j.contains("type"));
1✔
1082
    assert(j["type"].is_string());
1✔
1083
    assert(j["type"] == "return");
1✔
1084

1085
    std::string data = j["data"];
1✔
1086
    std::unique_ptr<types::IType> data_type = nullptr;
1✔
1087
    if (j.contains("data_type")) {
1✔
1088
        data_type = json_to_type(j["data_type"]);
×
1089
    }
×
1090

1091
    if (data_type == nullptr) {
1✔
1092
        auto& node = builder.add_return(parent, data, json_to_debug_info(j["debug_info"]));
1✔
1093
        node.element_id_ = j["element_id"];
1✔
1094
    } else {
1✔
1095
        auto& node = builder.add_constant_return(parent, data, *data_type, json_to_debug_info(j["debug_info"]));
×
1096
        node.element_id_ = j["element_id"];
×
1097
    }
×
1098
}
1✔
1099

1100
std::unique_ptr<types::IType> JSONSerializer::json_to_type(const nlohmann::json& j) {
584✔
1101
    if (j.contains("type")) {
584✔
1102
        if (j["type"] == "scalar") {
584✔
1103
            // Deserialize scalar type
1104
            assert(j.contains("primitive_type"));
418✔
1105
            types::PrimitiveType primitive_type = j["primitive_type"];
418✔
1106
            assert(j.contains("storage_type"));
418✔
1107
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
418✔
1108
            assert(j.contains("initializer"));
418✔
1109
            std::string initializer = j["initializer"];
418✔
1110
            assert(j.contains("alignment"));
418✔
1111
            size_t alignment = j["alignment"];
418✔
1112
            return std::make_unique<types::Scalar>(storage_type, alignment, initializer, primitive_type);
418✔
1113
        } else if (j["type"] == "array") {
418✔
1114
            // Deserialize array type
1115
            assert(j.contains("element_type"));
76✔
1116
            std::unique_ptr<types::IType> member_type = json_to_type(j["element_type"]);
76✔
1117
            assert(j.contains("num_elements"));
76✔
1118
            std::string num_elements_str = j["num_elements"];
76✔
1119
            // Convert num_elements_str to symbolic::Expression
1120
            auto num_elements = symbolic::parse(num_elements_str);
76✔
1121
            assert(j.contains("storage_type"));
76✔
1122
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
76✔
1123
            assert(j.contains("initializer"));
76✔
1124
            std::string initializer = j["initializer"];
76✔
1125
            assert(j.contains("alignment"));
76✔
1126
            size_t alignment = j["alignment"];
76✔
1127
            return std::make_unique<types::Array>(storage_type, alignment, initializer, *member_type, num_elements);
76✔
1128
        } else if (j["type"] == "pointer") {
90✔
1129
            // Deserialize pointer type
1130
            std::optional<std::unique_ptr<types::IType>> pointee_type;
65✔
1131
            if (j.contains("pointee_type")) {
65✔
1132
                assert(j.contains("pointee_type"));
64✔
1133
                pointee_type = json_to_type(j["pointee_type"]);
64✔
1134
            } else {
64✔
1135
                pointee_type = std::nullopt;
1✔
1136
            }
1✔
1137
            assert(j.contains("storage_type"));
65✔
1138
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
65✔
1139
            assert(j.contains("initializer"));
65✔
1140
            std::string initializer = j["initializer"];
65✔
1141
            assert(j.contains("alignment"));
65✔
1142
            size_t alignment = j["alignment"];
65✔
1143
            if (pointee_type.has_value()) {
65✔
1144
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer, *pointee_type.value());
64✔
1145
            } else {
64✔
1146
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer);
1✔
1147
            }
1✔
1148
        } else if (j["type"] == "structure") {
65✔
1149
            // Deserialize structure type
1150
            assert(j.contains("name"));
3✔
1151
            std::string name = j["name"];
3✔
1152
            assert(j.contains("storage_type"));
3✔
1153
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
3✔
1154
            assert(j.contains("initializer"));
3✔
1155
            std::string initializer = j["initializer"];
3✔
1156
            assert(j.contains("alignment"));
3✔
1157
            size_t alignment = j["alignment"];
3✔
1158
            return std::make_unique<types::Structure>(storage_type, alignment, initializer, name);
3✔
1159
        } else if (j["type"] == "function") {
22✔
1160
            // Deserialize function type
1161
            assert(j.contains("return_type"));
4✔
1162
            std::unique_ptr<types::IType> return_type = json_to_type(j["return_type"]);
4✔
1163
            assert(j.contains("params"));
4✔
1164
            std::vector<std::unique_ptr<types::IType>> params;
4✔
1165
            for (const auto& param : j["params"]) {
10✔
1166
                params.push_back(json_to_type(param));
10✔
1167
            }
10✔
1168
            assert(j.contains("is_var_arg"));
4✔
1169
            bool is_var_arg = j["is_var_arg"];
4✔
1170
            assert(j.contains("storage_type"));
4✔
1171
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
4✔
1172
            assert(j.contains("initializer"));
4✔
1173
            std::string initializer = j["initializer"];
4✔
1174
            assert(j.contains("alignment"));
4✔
1175
            size_t alignment = j["alignment"];
4✔
1176
            auto function =
4✔
1177
                std::make_unique<types::Function>(storage_type, alignment, initializer, *return_type, is_var_arg);
4✔
1178
            for (const auto& param : params) {
10✔
1179
                function->add_param(*param);
10✔
1180
            }
10✔
1181
            return function->clone();
4✔
1182
        } else if (j["type"] == "reference") {
18✔
1183
            // Deserialize reference type
1184
            assert(j.contains("reference_type"));
5✔
1185
            std::unique_ptr<types::IType> reference_type = json_to_type(j["reference_type"]);
5✔
1186
            return std::make_unique<sdfg::codegen::Reference>(*reference_type);
5✔
1187
        } else if (j["type"] == "tensor") {
13✔
1188
            // Deserialize tensor type
1189
            assert(j.contains("element_type"));
13✔
1190
            std::unique_ptr<types::IType> element_type = json_to_type(j["element_type"]);
13✔
1191
            assert(j.contains("shape"));
13✔
1192
            std::vector<symbolic::Expression> shape;
13✔
1193
            for (const auto& dim : j["shape"]) {
27✔
1194
                assert(dim.is_string());
27✔
1195
                std::string dim_str = dim;
27✔
1196
                auto expr = symbolic::parse(dim_str);
27✔
1197
                shape.push_back(expr);
27✔
1198
            }
27✔
1199
            assert(j.contains("strides"));
13✔
1200
            std::vector<symbolic::Expression> strides;
13✔
1201
            for (const auto& stride : j["strides"]) {
27✔
1202
                assert(stride.is_string());
27✔
1203
                std::string stride_str = stride;
27✔
1204
                auto expr = symbolic::parse(stride_str);
27✔
1205
                strides.push_back(expr);
27✔
1206
            }
27✔
1207
            assert(j.contains("offset"));
13✔
1208
            symbolic::Expression offset = symbolic::parse(j["offset"].get<std::string>());
13✔
1209
            assert(j.contains("storage_type"));
13✔
1210
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
13✔
1211
            assert(j.contains("initializer"));
13✔
1212
            std::string initializer = j["initializer"];
13✔
1213
            assert(j.contains("alignment"));
13✔
1214
            size_t alignment = j["alignment"];
13✔
1215
            return std::make_unique<types::Tensor>(
13✔
1216
                storage_type, alignment, initializer, dynamic_cast<types::Scalar&>(*element_type), shape, strides, offset
13✔
1217
            );
13✔
1218
        } else {
13✔
1219
            throw std::runtime_error("Unknown type");
×
1220
        }
×
1221
    } else {
584✔
1222
        throw std::runtime_error("Type not found");
×
1223
    }
×
1224
}
584✔
1225

1226
DebugInfo JSONSerializer::json_to_debug_info(const nlohmann::json& j) {
579✔
1227
    assert(j.contains("has"));
579✔
1228
    assert(j["has"].is_boolean());
579✔
1229
    if (!j["has"]) {
579✔
1230
        return DebugInfo();
570✔
1231
    }
570✔
1232
    assert(j.contains("filename"));
579✔
1233
    assert(j["filename"].is_string());
9✔
1234
    std::string filename = j["filename"];
9✔
1235
    assert(j.contains("function"));
9✔
1236
    assert(j["function"].is_string());
9✔
1237
    std::string function = j["function"];
9✔
1238
    assert(j.contains("start_line"));
9✔
1239
    assert(j["start_line"].is_number_integer());
9✔
1240
    size_t start_line = j["start_line"];
9✔
1241
    assert(j.contains("start_column"));
9✔
1242
    assert(j["start_column"].is_number_integer());
9✔
1243
    size_t start_column = j["start_column"];
9✔
1244
    assert(j.contains("end_line"));
9✔
1245
    assert(j["end_line"].is_number_integer());
9✔
1246
    size_t end_line = j["end_line"];
9✔
1247
    assert(j.contains("end_column"));
9✔
1248
    assert(j["end_column"].is_number_integer());
9✔
1249
    size_t end_column = j["end_column"];
9✔
1250
    return DebugInfo(filename, function, start_line, start_column, end_line, end_column);
9✔
1251
}
9✔
1252

1253
ScheduleType JSONSerializer::json_to_schedule_type(const nlohmann::json& j) {
9✔
1254
    assert(j.contains("value"));
9✔
1255
    assert(j["value"].is_string());
9✔
1256
    // assert(j.contains("category"));
1257
    // assert(j["category"].is_number_integer());
1258
    assert(j.contains("properties"));
9✔
1259
    assert(j["properties"].is_object());
9✔
1260
    ScheduleTypeCategory category = ScheduleTypeCategory::None;
9✔
1261
    if (j.contains("category")) {
9✔
1262
        category = static_cast<ScheduleTypeCategory>(j["category"].get<int>());
9✔
1263
    }
9✔
1264
    ScheduleType schedule_type(j["value"].get<std::string>(), category);
9✔
1265
    for (const auto& [key, value] : j["properties"].items()) {
9✔
1266
        assert(value.is_string());
3✔
1267
        schedule_type.set_property(key, value.get<std::string>());
3✔
1268
    }
3✔
1269
    return schedule_type;
9✔
1270
}
9✔
1271

1272
types::StorageType JSONSerializer::json_to_storage_type(const nlohmann::json& j) {
585✔
1273
    if (!j.contains("value")) {
585✔
1274
        return types::StorageType::CPU_Stack();
×
1275
    }
×
1276
    std::string value = j["value"].get<std::string>();
585✔
1277

1278
    symbolic::Expression allocation_size = SymEngine::null;
585✔
1279
    if (j.contains("allocation_size")) {
585✔
1280
        allocation_size = symbolic::parse(j["allocation_size"].get<std::string>());
×
1281
    }
×
1282

1283
    types::StorageType::AllocationType allocation = j["allocation"];
585✔
1284
    types::StorageType::AllocationType deallocation = j["deallocation"];
585✔
1285

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

1288
    if (j.contains("args")) {
585✔
1289
        nlohmann::json::array_t args = j["args"];
×
1290
        if (args.size() > 0) {
×
1291
            storageType.arg1(symbolic::parse(args[0].get<std::string>()));
×
1292
        }
×
1293
    }
×
1294
    return storageType;
585✔
1295
}
585✔
1296

1297
std::string JSONSerializer::expression(const symbolic::Expression expr) {
1,041✔
1298
    JSONSymbolicPrinter printer;
1,041✔
1299
    return printer.apply(expr);
1,041✔
1300
};
1,041✔
1301

1302
symbolic::Expression JSONSerializer::json_to_expr(const nlohmann::json& j) {
3✔
1303
    return symbolic::parse(j.get<std::string>());
3✔
1304
}
3✔
1305

1306
void JSONSerializer::writeToFile(const StructuredSDFG& sdfg, const std::filesystem::path& file) {
×
1307
    JSONSerializer ser;
×
1308
    auto json = ser.serialize(sdfg);
×
1309

1310
    auto parent_path = file.parent_path();
×
1311
    if (!parent_path.empty()) {
×
1312
        std::filesystem::create_directories(file.parent_path());
×
1313
    }
×
1314

1315
    std::ofstream out(file, std::ofstream::out);
×
1316
    if (!out.is_open()) {
×
1317
        std::cerr << "Could not open file " << file << " for writing JSON output." << std::endl;
×
1318
    }
×
1319
    out << json << std::endl;
×
1320
    out.close();
×
1321
}
×
1322

1323
void JSONSymbolicPrinter::bvisit(const SymEngine::Equality& x) {
×
1324
    str_ = apply(x.get_args()[0]) + " == " + apply(x.get_args()[1]);
×
1325
    str_ = parenthesize(str_);
×
1326
};
×
1327

1328
void JSONSymbolicPrinter::bvisit(const SymEngine::Unequality& x) {
×
1329
    str_ = apply(x.get_args()[0]) + " != " + apply(x.get_args()[1]);
×
1330
    str_ = parenthesize(str_);
×
1331
};
×
1332

1333
void JSONSymbolicPrinter::bvisit(const SymEngine::LessThan& x) {
4✔
1334
    str_ = apply(x.get_args()[0]) + " <= " + apply(x.get_args()[1]);
4✔
1335
    str_ = parenthesize(str_);
4✔
1336
};
4✔
1337

1338
void JSONSymbolicPrinter::bvisit(const SymEngine::StrictLessThan& x) {
194✔
1339
    str_ = apply(x.get_args()[0]) + " < " + apply(x.get_args()[1]);
194✔
1340
    str_ = parenthesize(str_);
194✔
1341
};
194✔
1342

1343
void JSONSymbolicPrinter::bvisit(const SymEngine::Min& x) {
2✔
1344
    std::ostringstream s;
2✔
1345
    auto container = x.get_args();
2✔
1346
    if (container.size() == 1) {
2✔
1347
        s << apply(*container.begin());
×
1348
    } else {
2✔
1349
        s << "min(";
2✔
1350
        s << apply(*container.begin());
2✔
1351

1352
        // Recursively apply __daisy_min to the arguments
1353
        SymEngine::vec_basic subargs;
2✔
1354
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
4✔
1355
            subargs.push_back(*it);
2✔
1356
        }
2✔
1357
        auto submin = SymEngine::min(subargs);
2✔
1358
        s << ", " << apply(submin);
2✔
1359

1360
        s << ")";
2✔
1361
    }
2✔
1362

1363
    str_ = s.str();
2✔
1364
};
2✔
1365

1366
void JSONSymbolicPrinter::bvisit(const SymEngine::Max& x) {
4✔
1367
    std::ostringstream s;
4✔
1368
    auto container = x.get_args();
4✔
1369
    if (container.size() == 1) {
4✔
1370
        s << apply(*container.begin());
×
1371
    } else {
4✔
1372
        s << "max(";
4✔
1373
        s << apply(*container.begin());
4✔
1374

1375
        // Recursively apply __daisy_max to the arguments
1376
        SymEngine::vec_basic subargs;
4✔
1377
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
8✔
1378
            subargs.push_back(*it);
4✔
1379
        }
4✔
1380
        auto submax = SymEngine::max(subargs);
4✔
1381
        s << ", " << apply(submax);
4✔
1382

1383
        s << ")";
4✔
1384
    }
4✔
1385

1386
    str_ = s.str();
4✔
1387
};
4✔
1388

1389
void LibraryNodeSerializerRegistry::
1390
    register_library_node_serializer(std::string library_node_code, LibraryNodeSerializerFn fn) {
246✔
1391
    std::lock_guard<std::mutex> lock(mutex_);
246✔
1392
    if (factory_map_.find(library_node_code) != factory_map_.end()) {
246✔
1393
        return;
8✔
1394
    }
8✔
1395
    factory_map_[library_node_code] = std::move(fn);
238✔
1396
}
238✔
1397

1398
LibraryNodeSerializerFn LibraryNodeSerializerRegistry::get_library_node_serializer(std::string library_node_code) {
27✔
1399
    auto it = factory_map_.find(library_node_code);
27✔
1400
    if (it != factory_map_.end()) {
27✔
1401
        return it->second;
27✔
1402
    }
27✔
1403
    return nullptr;
×
1404
}
27✔
1405

1406
size_t LibraryNodeSerializerRegistry::size() const { return factory_map_.size(); }
×
1407

1408
void register_default_serializers() {
4✔
1409
    // stdlib
1410
    LibraryNodeSerializerRegistry::instance()
4✔
1411
        .register_library_node_serializer(stdlib::LibraryNodeType_Alloca.value(), []() {
4✔
1412
            return std::make_unique<stdlib::AllocaNodeSerializer>();
×
1413
        });
×
1414
    LibraryNodeSerializerRegistry::instance()
4✔
1415
        .register_library_node_serializer(stdlib::LibraryNodeType_Assert.value(), []() {
4✔
1416
            return std::make_unique<stdlib::AssertNodeSerializer>();
×
1417
        });
×
1418
    LibraryNodeSerializerRegistry::instance()
4✔
1419
        .register_library_node_serializer(stdlib::LibraryNodeType_Calloc.value(), []() {
4✔
1420
            return std::make_unique<stdlib::CallocNodeSerializer>();
×
1421
        });
×
1422
    LibraryNodeSerializerRegistry::instance()
4✔
1423
        .register_library_node_serializer(stdlib::LibraryNodeType_Free.value(), []() {
4✔
1424
            return std::make_unique<stdlib::FreeNodeSerializer>();
×
1425
        });
×
1426
    LibraryNodeSerializerRegistry::instance()
4✔
1427
        .register_library_node_serializer(stdlib::LibraryNodeType_Malloc.value(), []() {
4✔
1428
            return std::make_unique<stdlib::MallocNodeSerializer>();
×
1429
        });
×
1430
    LibraryNodeSerializerRegistry::instance()
4✔
1431
        .register_library_node_serializer(stdlib::LibraryNodeType_Memcpy.value(), []() {
4✔
1432
            return std::make_unique<stdlib::MemcpyNodeSerializer>();
×
1433
        });
×
1434
    LibraryNodeSerializerRegistry::instance()
4✔
1435
        .register_library_node_serializer(stdlib::LibraryNodeType_Memmove.value(), []() {
4✔
1436
            return std::make_unique<stdlib::MemmoveNodeSerializer>();
×
1437
        });
×
1438
    LibraryNodeSerializerRegistry::instance()
4✔
1439
        .register_library_node_serializer(stdlib::LibraryNodeType_Memset.value(), []() {
4✔
1440
            return std::make_unique<stdlib::MemsetNodeSerializer>();
×
1441
        });
×
1442
    LibraryNodeSerializerRegistry::instance()
4✔
1443
        .register_library_node_serializer(stdlib::LibraryNodeType_Trap.value(), []() {
4✔
1444
            return std::make_unique<stdlib::TrapNodeSerializer>();
×
1445
        });
×
1446
    LibraryNodeSerializerRegistry::instance()
4✔
1447
        .register_library_node_serializer(stdlib::LibraryNodeType_Unreachable.value(), []() {
4✔
1448
            return std::make_unique<stdlib::UnreachableNodeSerializer>();
×
1449
        });
×
1450

1451
    // Metadata
1452
    LibraryNodeSerializerRegistry::instance()
4✔
1453
        .register_library_node_serializer(data_flow::LibraryNodeType_Metadata.value(), []() {
4✔
1454
            return std::make_unique<data_flow::MetadataNodeSerializer>();
×
1455
        });
×
1456

1457
    // Barrier
1458
    LibraryNodeSerializerRegistry::instance()
4✔
1459
        .register_library_node_serializer(data_flow::LibraryNodeType_BarrierLocal.value(), []() {
4✔
1460
            return std::make_unique<data_flow::BarrierLocalNodeSerializer>();
1✔
1461
        });
1✔
1462

1463
    // Call Node
1464
    LibraryNodeSerializerRegistry::instance()
4✔
1465
        .register_library_node_serializer(data_flow::LibraryNodeType_Call.value(), []() {
6✔
1466
            return std::make_unique<data_flow::CallNodeSerializer>();
6✔
1467
        });
6✔
1468
    LibraryNodeSerializerRegistry::instance()
4✔
1469
        .register_library_node_serializer(data_flow::LibraryNodeType_Invoke.value(), []() {
4✔
1470
            return std::make_unique<data_flow::InvokeNodeSerializer>();
×
1471
        });
×
1472

1473
    // LoadConst
1474
    LibraryNodeSerializerRegistry::instance()
4✔
1475
        .register_library_node_serializer(data_flow::LibraryNodeType_LoadConst.value(), []() {
4✔
1476
            return std::make_unique<data_flow::LoadConstNodeSerializer>();
2✔
1477
        });
2✔
1478

1479
    // CMath
1480
    LibraryNodeSerializerRegistry::instance()
4✔
1481
        .register_library_node_serializer(math::cmath::LibraryNodeType_CMath.value(), []() {
4✔
1482
            return std::make_unique<math::cmath::CMathNodeSerializer>();
×
1483
        });
×
1484
    // Backward compatibility
1485
    LibraryNodeSerializerRegistry::instance()
4✔
1486
        .register_library_node_serializer(math::cmath::LibraryNodeType_CMath_Deprecated.value(), []() {
4✔
1487
            return std::make_unique<math::cmath::CMathNodeSerializer>();
×
1488
        });
×
1489

1490
    // BLAS
1491
    LibraryNodeSerializerRegistry::instance()
4✔
1492
        .register_library_node_serializer(math::blas::LibraryNodeType_DOT.value(), []() {
4✔
1493
            return std::make_unique<math::blas::DotNodeSerializer>();
×
1494
        });
×
1495
    LibraryNodeSerializerRegistry::instance()
4✔
1496
        .register_library_node_serializer(math::blas::LibraryNodeType_GEMM.value(), []() {
4✔
1497
            return std::make_unique<math::blas::GEMMNodeSerializer>();
×
1498
        });
×
1499
    LibraryNodeSerializerRegistry::instance()
4✔
1500
        .register_library_node_serializer(math::blas::LibraryNodeType_BatchedGEMM.value(), []() {
4✔
1501
            return std::make_unique<math::blas::BatchedGEMMNodeSerializer>();
×
1502
        });
×
1503

1504
    // Tensor
1505

1506
    LibraryNodeSerializerRegistry::instance()
4✔
1507
        .register_library_node_serializer(math::tensor::LibraryNodeType_Broadcast.value(), []() {
4✔
1508
            return std::make_unique<math::tensor::BroadcastNodeSerializer>();
×
1509
        });
×
1510
    LibraryNodeSerializerRegistry::instance()
4✔
1511
        .register_library_node_serializer(math::tensor::LibraryNodeType_Conv.value(), []() {
4✔
1512
            return std::make_unique<math::tensor::ConvNodeSerializer>();
×
1513
        });
×
1514
    LibraryNodeSerializerRegistry::instance()
4✔
1515
        .register_library_node_serializer(math::tensor::LibraryNodeType_Pooling.value(), []() {
4✔
1516
            return std::make_unique<math::tensor::PoolingNodeSerializer>();
×
1517
        });
×
1518
    LibraryNodeSerializerRegistry::instance()
4✔
1519
        .register_library_node_serializer(math::tensor::LibraryNodeType_MatMul.value(), []() {
4✔
1520
            return std::make_unique<math::tensor::MatMulNodeSerializer>();
×
1521
        });
×
1522
    LibraryNodeSerializerRegistry::instance()
4✔
1523
        .register_library_node_serializer(math::tensor::LibraryNodeType_TensorCopy.value(), []() {
4✔
1524
            return std::make_unique<math::tensor::TensorCopyNodeSerializer>();
2✔
1525
        });
2✔
1526
    LibraryNodeSerializerRegistry::instance()
4✔
1527
        .register_library_node_serializer(math::tensor::LibraryNodeType_TensorConcat.value(), []() {
4✔
1528
            return std::make_unique<math::tensor::ConcatNodeSerializer>();
2✔
1529
        });
2✔
1530

1531
    // Elementwise
1532
    LibraryNodeSerializerRegistry::instance()
4✔
1533
        .register_library_node_serializer(math::tensor::LibraryNodeType_Abs.value(), []() {
4✔
1534
            return std::make_unique<math::tensor::AbsNodeSerializer>();
×
1535
        });
×
1536
    LibraryNodeSerializerRegistry::instance()
4✔
1537
        .register_library_node_serializer(math::tensor::LibraryNodeType_Add.value(), []() {
4✔
1538
            return std::make_unique<math::tensor::AddNodeSerializer>();
×
1539
        });
×
1540
    LibraryNodeSerializerRegistry::instance()
4✔
1541
        .register_library_node_serializer(math::tensor::LibraryNodeType_Div.value(), []() {
4✔
1542
            return std::make_unique<math::tensor::DivNodeSerializer>();
×
1543
        });
×
1544
    LibraryNodeSerializerRegistry::instance()
4✔
1545
        .register_library_node_serializer(math::tensor::LibraryNodeType_Elu.value(), []() {
4✔
1546
            return std::make_unique<math::tensor::EluNodeSerializer>();
×
1547
        });
×
1548
    LibraryNodeSerializerRegistry::instance()
4✔
1549
        .register_library_node_serializer(math::tensor::LibraryNodeType_Exp.value(), []() {
4✔
1550
            return std::make_unique<math::tensor::ExpNodeSerializer>();
×
1551
        });
×
1552
    LibraryNodeSerializerRegistry::instance()
4✔
1553
        .register_library_node_serializer(math::tensor::LibraryNodeType_Erf.value(), []() {
4✔
1554
            return std::make_unique<math::tensor::ErfNodeSerializer>();
×
1555
        });
×
1556
    LibraryNodeSerializerRegistry::instance()
4✔
1557
        .register_library_node_serializer(math::tensor::LibraryNodeType_HardSigmoid.value(), []() {
4✔
1558
            return std::make_unique<math::tensor::HardSigmoidNodeSerializer>();
×
1559
        });
×
1560
    LibraryNodeSerializerRegistry::instance()
4✔
1561
        .register_library_node_serializer(math::tensor::LibraryNodeType_LeakyReLU.value(), []() {
4✔
1562
            return std::make_unique<math::tensor::LeakyReLUNodeSerializer>();
×
1563
        });
×
1564
    LibraryNodeSerializerRegistry::instance()
4✔
1565
        .register_library_node_serializer(math::tensor::LibraryNodeType_LogicalNot.value(), []() {
4✔
1566
            return std::make_unique<math::tensor::LogicalNotNodeSerializer>();
×
1567
        });
×
1568
    LibraryNodeSerializerRegistry::instance()
4✔
1569
        .register_library_node_serializer(math::tensor::LibraryNodeType_Neg.value(), []() {
4✔
NEW
1570
            return std::make_unique<math::tensor::NegNodeSerializer>();
×
NEW
1571
        });
×
1572
    LibraryNodeSerializerRegistry::instance()
4✔
1573
        .register_library_node_serializer(math::tensor::LibraryNodeType_Mul.value(), []() {
4✔
1574
            return std::make_unique<math::tensor::MulNodeSerializer>();
×
1575
        });
×
1576
    LibraryNodeSerializerRegistry::instance()
4✔
1577
        .register_library_node_serializer(math::tensor::LibraryNodeType_Pow.value(), []() {
4✔
1578
            return std::make_unique<math::tensor::PowNodeSerializer>();
×
1579
        });
×
1580
    LibraryNodeSerializerRegistry::instance()
4✔
1581
        .register_library_node_serializer(math::tensor::LibraryNodeType_ReLU.value(), []() {
4✔
1582
            return std::make_unique<math::tensor::ReLUNodeSerializer>();
×
1583
        });
×
1584
    LibraryNodeSerializerRegistry::instance()
4✔
1585
        .register_library_node_serializer(math::tensor::LibraryNodeType_GELU.value(), []() {
4✔
1586
            return std::make_unique<math::tensor::GELUNodeSerializer>();
4✔
1587
        });
4✔
1588
    LibraryNodeSerializerRegistry::instance()
4✔
1589
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sigmoid.value(), []() {
4✔
1590
            return std::make_unique<math::tensor::SigmoidNodeSerializer>();
×
1591
        });
×
1592
    LibraryNodeSerializerRegistry::instance()
4✔
1593
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sqrt.value(), []() {
4✔
1594
            return std::make_unique<math::tensor::SqrtNodeSerializer>();
×
1595
        });
×
1596
    LibraryNodeSerializerRegistry::instance()
4✔
1597
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sub.value(), []() {
4✔
1598
            return std::make_unique<math::tensor::SubNodeSerializer>();
×
1599
        });
×
1600
    LibraryNodeSerializerRegistry::instance()
4✔
1601
        .register_library_node_serializer(math::tensor::LibraryNodeType_Tanh.value(), []() {
4✔
1602
            return std::make_unique<math::tensor::TanhNodeSerializer>();
×
1603
        });
×
1604
    LibraryNodeSerializerRegistry::instance()
4✔
1605
        .register_library_node_serializer(math::tensor::LibraryNodeType_Minimum.value(), []() {
4✔
1606
            return std::make_unique<math::tensor::MinimumNodeSerializer>();
×
1607
        });
×
1608
    LibraryNodeSerializerRegistry::instance()
4✔
1609
        .register_library_node_serializer(math::tensor::LibraryNodeType_Maximum.value(), []() {
4✔
1610
            return std::make_unique<math::tensor::MaximumNodeSerializer>();
×
1611
        });
×
1612
    LibraryNodeSerializerRegistry::instance()
4✔
1613
        .register_library_node_serializer(math::tensor::LibraryNodeType_Fill.value(), []() {
4✔
1614
            return std::make_unique<math::tensor::FillNodeSerializer>();
×
1615
        });
×
1616
    LibraryNodeSerializerRegistry::instance()
4✔
1617
        .register_library_node_serializer(math::tensor::LibraryNodeType_TensorTasklet.value(), []() {
4✔
1618
            return std::make_unique<math::tensor::TaskletTensorNodeSerializer>();
×
1619
        });
×
1620
    LibraryNodeSerializerRegistry::instance()
4✔
1621
        .register_library_node_serializer(math::tensor::LibraryNodeType_TensorCMath.value(), []() {
4✔
1622
            return std::make_unique<math::tensor::CMathTensorNodeSerializer>();
×
1623
        });
×
1624
    LibraryNodeSerializerRegistry::instance()
4✔
1625
        .register_library_node_serializer(math::tensor::LibraryNodeType_Cast.value(), []() {
4✔
1626
            return std::make_unique<math::tensor::CastNodeSerializer>();
×
1627
        });
×
1628

1629
    LibraryNodeSerializerRegistry::instance()
4✔
1630
        .register_library_node_serializer(math::tensor::LibraryNodeType_BatchNorm.value(), [] {
4✔
1631
            return std::make_unique<math::tensor::BatchNormNodeSerializer>();
×
1632
        });
×
1633

1634
    LibraryNodeSerializerRegistry::instance()
4✔
1635
        .register_library_node_serializer(math::tensor::LibraryNodeType_LayerNorm.value(), [] {
4✔
1636
            return std::make_unique<math::tensor::LayerNormNodeSerializer>();
2✔
1637
        });
2✔
1638

1639
    // Reduce
1640
    LibraryNodeSerializerRegistry::instance()
4✔
1641
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sum.value(), []() {
4✔
1642
            return std::make_unique<math::tensor::SumNodeSerializer>();
×
1643
        });
×
1644
    LibraryNodeSerializerRegistry::instance()
4✔
1645
        .register_library_node_serializer(math::tensor::LibraryNodeType_Max.value(), []() {
4✔
1646
            return std::make_unique<math::tensor::MaxNodeSerializer>();
×
1647
        });
×
1648
    LibraryNodeSerializerRegistry::instance()
4✔
1649
        .register_library_node_serializer(math::tensor::LibraryNodeType_Min.value(), []() {
4✔
1650
            return std::make_unique<math::tensor::MinNodeSerializer>();
×
1651
        });
×
1652
    LibraryNodeSerializerRegistry::instance()
4✔
1653
        .register_library_node_serializer(math::tensor::LibraryNodeType_Softmax.value(), []() {
4✔
1654
            return std::make_unique<math::tensor::SoftmaxNodeSerializer>();
×
1655
        });
×
1656
    LibraryNodeSerializerRegistry::instance()
4✔
1657
        .register_library_node_serializer(math::tensor::LibraryNodeType_Mean.value(), []() {
4✔
1658
            return std::make_unique<math::tensor::MeanNodeSerializer>();
×
1659
        });
×
1660
    LibraryNodeSerializerRegistry::instance()
4✔
1661
        .register_library_node_serializer(math::tensor::LibraryNodeType_Std.value(), []() {
4✔
1662
            return std::make_unique<math::tensor::StdNodeSerializer>();
×
1663
        });
×
1664

1665
    // Einsum
1666
    LibraryNodeSerializerRegistry::instance()
4✔
1667
        .register_library_node_serializer(math::tensor::LibraryNodeType_Einsum.value(), []() {
4✔
1668
            return std::make_unique<math::tensor::EinsumSerializer>();
×
1669
        });
×
1670
}
4✔
1671

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

© 2026 Coveralls, Inc