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

daisytuner / docc / 28106147644

24 Jun 2026 02:32PM UTC coverage: 61.922% (+0.1%) from 61.779%
28106147644

Pull #806

github

web-flow
Merge 2be414d54 into 57cc1db99
Pull Request #806: Map Collapse for Multiple targets in a neste sequence

165 of 185 new or added lines in 2 files covered. (89.19%)

419 existing lines in 30 files now uncovered.

37705 of 60891 relevant lines covered (61.92%)

1004.4 hits per line

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

78.2
/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/return.h"
28
#include "sdfg/structured_control_flow/sequence.h"
29
#include "sdfg/structured_control_flow/while.h"
30
#include "sdfg/structured_sdfg.h"
31
#include "sdfg/symbolic/symbolic.h"
32
#include "sdfg/types/function.h"
33
#include "sdfg/types/scalar.h"
34
#include "sdfg/types/type.h"
35
#include "symengine/expression.h"
36
#include "symengine/logic.h"
37
#include "symengine/symengine_rcp.h"
38

39
namespace sdfg {
40
namespace serializer {
41

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

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

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

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

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

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

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

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

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

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

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

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

112
    return j;
26✔
113
}
26✔
114

115
void JSONSerializer::serialize_node(nlohmann::json& j, const structured_control_flow::ControlFlowNode& node) {
219✔
116
    if (auto block = dynamic_cast<const structured_control_flow::Block*>(&node)) {
219✔
117
        block_to_json(j, *block);
50✔
118
    } else if (auto for_node = dynamic_cast<const structured_control_flow::For*>(&node)) {
169✔
119
        for_to_json(j, *for_node);
103✔
120
    } else if (auto sequence_node = dynamic_cast<const structured_control_flow::Sequence*>(&node)) {
103✔
UNCOV
121
        sequence_to_json(j, *sequence_node);
×
122
    } else if (auto condition_node = dynamic_cast<const structured_control_flow::IfElse*>(&node)) {
66✔
UNCOV
123
        if_else_to_json(j, *condition_node);
×
124
    } else if (auto while_node = dynamic_cast<const structured_control_flow::While*>(&node)) {
66✔
UNCOV
125
        while_node_to_json(j, *while_node);
×
126
    } else if (auto return_node = dynamic_cast<const structured_control_flow::Return*>(&node)) {
66✔
UNCOV
127
        return_node_to_json(j, *return_node);
×
128
    } else if (auto break_node = dynamic_cast<const structured_control_flow::Break*>(&node)) {
66✔
129
        break_node_to_json(j, *break_node);
2✔
130
    } else if (auto continue_node = dynamic_cast<const structured_control_flow::Continue*>(&node)) {
64✔
131
        continue_node_to_json(j, *continue_node);
2✔
132
    } else if (auto map_node = dynamic_cast<const structured_control_flow::Map*>(&node)) {
62✔
133
        map_to_json(j, *map_node);
62✔
134
    } else {
62✔
UNCOV
135
        throw std::runtime_error("Unknown child type");
×
UNCOV
136
    }
×
137
}
219✔
138

139
void JSONSerializer::dataflow_to_json(nlohmann::json& j, const data_flow::DataFlowGraph& dataflow) {
55✔
140
    j["type"] = "dataflow";
55✔
141
    j["nodes"] = nlohmann::json::array();
55✔
142
    j["edges"] = nlohmann::json::array();
55✔
143

144
    for (auto& node : dataflow.nodes()) {
211✔
145
        nlohmann::json node_json;
211✔
146
        node_json["element_id"] = node.element_id();
211✔
147

148
        node_json["debug_info"] = nlohmann::json::object();
211✔
149
        debug_info_to_json(node_json["debug_info"], node.debug_info());
211✔
150

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

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

184
        j["nodes"].push_back(node_json);
211✔
185
    }
211✔
186

187
    for (auto& edge : dataflow.edges()) {
186✔
188
        nlohmann::json edge_json;
186✔
189
        edge_json["element_id"] = edge.element_id();
186✔
190

191
        edge_json["debug_info"] = nlohmann::json::object();
186✔
192
        debug_info_to_json(edge_json["debug_info"], edge.debug_info());
186✔
193

194
        edge_json["src"] = edge.src().element_id();
186✔
195
        edge_json["dst"] = edge.dst().element_id();
186✔
196

197
        edge_json["src_conn"] = edge.src_conn();
186✔
198
        edge_json["dst_conn"] = edge.dst_conn();
186✔
199

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

205
        nlohmann::json base_type_json;
186✔
206
        type_to_json(base_type_json, edge.base_type());
186✔
207
        edge_json["base_type"] = base_type_json;
186✔
208

209
        j["edges"].push_back(edge_json);
186✔
210
    }
186✔
211
}
55✔
212

213
void JSONSerializer::block_to_json(nlohmann::json& j, const structured_control_flow::Block& block) {
52✔
214
    j["type"] = "block";
52✔
215
    j["element_id"] = block.element_id();
52✔
216

217
    j["debug_info"] = nlohmann::json::object();
52✔
218
    debug_info_to_json(j["debug_info"], block.debug_info());
52✔
219

220
    if (this->recurse_) {
52✔
221
        nlohmann::json dataflow_json;
52✔
222
        dataflow_to_json(dataflow_json, block.dataflow());
52✔
223
        j["dataflow"] = dataflow_json;
52✔
224
    }
52✔
225
}
52✔
226

227
void JSONSerializer::for_to_json(nlohmann::json& j, const structured_control_flow::For& for_node) {
105✔
228
    j["type"] = "for";
105✔
229
    j["element_id"] = for_node.element_id();
105✔
230

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

234
    j["indvar"] = expression(for_node.indvar());
105✔
235
    j["init"] = expression(for_node.init());
105✔
236
    j["condition"] = expression(for_node.condition());
105✔
237
    j["update"] = expression(for_node.update());
105✔
238

239
    if (this->recurse_) {
105✔
240
        nlohmann::json body_json;
21✔
241
        sequence_to_json(body_json, for_node.root());
21✔
242
        j["root"] = body_json;
21✔
243
    }
21✔
244
}
105✔
245

246
void JSONSerializer::if_else_to_json(nlohmann::json& j, const structured_control_flow::IfElse& if_else_node) {
2✔
247
    j["type"] = "if_else";
2✔
248
    j["element_id"] = if_else_node.element_id();
2✔
249

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

253
    j["branches"] = nlohmann::json::array();
2✔
254
    for (size_t i = 0; i < if_else_node.size(); i++) {
6✔
255
        nlohmann::json branch_json;
4✔
256
        branch_json["condition"] = expression(if_else_node.at(i).second);
4✔
257
        if (this->recurse_) {
4✔
258
            nlohmann::json body_json;
4✔
259
            sequence_to_json(body_json, if_else_node.at(i).first);
4✔
260
            branch_json["root"] = body_json;
4✔
261
        }
4✔
262
        j["branches"].push_back(branch_json);
4✔
263
    }
4✔
264
}
2✔
265

266
void JSONSerializer::while_node_to_json(nlohmann::json& j, const structured_control_flow::While& while_node) {
5✔
267
    j["type"] = "while";
5✔
268
    j["element_id"] = while_node.element_id();
5✔
269

270
    j["debug_info"] = nlohmann::json::object();
5✔
271
    debug_info_to_json(j["debug_info"], while_node.debug_info());
5✔
272

273
    if (this->recurse_) {
5✔
274
        nlohmann::json body_json;
5✔
275
        sequence_to_json(body_json, while_node.root());
5✔
276
        j["root"] = body_json;
5✔
277
    }
5✔
278
}
5✔
279

280
void JSONSerializer::break_node_to_json(nlohmann::json& j, const structured_control_flow::Break& break_node) {
2✔
281
    j["type"] = "break";
2✔
282
    j["element_id"] = break_node.element_id();
2✔
283

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

288
void JSONSerializer::continue_node_to_json(nlohmann::json& j, const structured_control_flow::Continue& continue_node) {
2✔
289
    j["type"] = "continue";
2✔
290
    j["element_id"] = continue_node.element_id();
2✔
291

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

296
void JSONSerializer::map_to_json(nlohmann::json& j, const structured_control_flow::Map& map_node) {
64✔
297
    j["type"] = "map";
64✔
298
    j["element_id"] = map_node.element_id();
64✔
299

300
    j["debug_info"] = nlohmann::json::object();
64✔
301
    debug_info_to_json(j["debug_info"], map_node.debug_info());
64✔
302

303
    j["indvar"] = expression(map_node.indvar());
64✔
304
    j["init"] = expression(map_node.init());
64✔
305
    j["condition"] = expression(map_node.condition());
64✔
306
    j["update"] = expression(map_node.update());
64✔
307

308
    j["schedule_type"] = nlohmann::json::object();
64✔
309
    schedule_type_to_json(j["schedule_type"], map_node.schedule_type());
64✔
310

311
    if (this->recurse_) {
64✔
312
        nlohmann::json body_json;
8✔
313
        sequence_to_json(body_json, map_node.root());
8✔
314
        j["root"] = body_json;
8✔
315
    }
8✔
316
}
64✔
317

318
void JSONSerializer::return_node_to_json(nlohmann::json& j, const structured_control_flow::Return& return_node) {
2✔
319
    j["type"] = "return";
2✔
320
    j["element_id"] = return_node.element_id();
2✔
321
    j["data"] = return_node.data();
2✔
322

323
    if (return_node.is_constant()) {
2✔
UNCOV
324
        nlohmann::json type_json;
×
UNCOV
325
        type_to_json(type_json, return_node.type());
×
UNCOV
326
        j["data_type"] = type_json;
×
UNCOV
327
    }
×
328

329
    j["debug_info"] = nlohmann::json::object();
2✔
330
    debug_info_to_json(j["debug_info"], return_node.debug_info());
2✔
331
}
2✔
332

333
void JSONSerializer::sequence_to_json(nlohmann::json& j, const structured_control_flow::Sequence& sequence) {
69✔
334
    j["type"] = "sequence";
69✔
335
    j["element_id"] = sequence.element_id();
69✔
336

337
    j["debug_info"] = nlohmann::json::object();
69✔
338
    debug_info_to_json(j["debug_info"], sequence.debug_info());
69✔
339

340
    if (!this->recurse_) {
69✔
UNCOV
341
        return;
×
UNCOV
342
    }
×
343

344
    j["children"] = nlohmann::json::array();
69✔
345
    j["transitions"] = nlohmann::json::array();
69✔
346
    for (size_t i = 0; i < sequence.size(); i++) {
148✔
347
        nlohmann::json child_json;
79✔
348
        auto& child = sequence.at(i).first;
79✔
349
        auto& transition = sequence.at(i).second;
79✔
350

351
        this->serialize_node(child_json, child);
79✔
352
        j["children"].push_back(child_json);
79✔
353

354
        // Add transition information
355
        nlohmann::json transition_json;
79✔
356
        transition_json["type"] = "transition";
79✔
357
        transition_json["element_id"] = transition.element_id();
79✔
358

359
        transition_json["debug_info"] = nlohmann::json::object();
79✔
360
        debug_info_to_json(transition_json["debug_info"], transition.debug_info());
79✔
361

362
        transition_json["assignments"] = nlohmann::json::array();
79✔
363
        for (const auto& assignment : transition.assignments()) {
79✔
364
            nlohmann::json assignment_json;
3✔
365
            assignment_json["symbol"] = expression(assignment.first);
3✔
366
            assignment_json["expression"] = expression(assignment.second);
3✔
367
            transition_json["assignments"].push_back(assignment_json);
3✔
368
        }
3✔
369

370
        j["transitions"].push_back(transition_json);
79✔
371
    }
79✔
372
}
69✔
373

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

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

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

475

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

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

500

501
/*
502
 * * Deserialization logic
503
 */
504

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

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

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

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

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

535
    nlohmann::json& containers = j["containers"];
28✔
536

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

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

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

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

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

579
    builder.set_element_counter(element_counter);
28✔
580

581
    return builder.move();
28✔
582
}
28✔
583

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

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

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

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

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

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

UNCOV
664
            auto type = json_to_type(node["data_type"]);
×
665

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

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

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

694
        auto base_type = json_to_type(edge["base_type"]);
183✔
695

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

719
void JSONSerializer::json_to_sequence(
720
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& sequence
721
) {
62✔
722
    assert(j.contains("type"));
62✔
723
    assert(j["type"].is_string());
62✔
724
    assert(j.contains("children"));
62✔
725
    assert(j["children"].is_array());
62✔
726
    assert(j.contains("transitions"));
62✔
727
    assert(j["transitions"].is_array());
62✔
728
    assert(j["transitions"].size() == j["children"].size());
62✔
729

730
    sequence.element_id_ = j["element_id"];
62✔
731
    sequence.debug_info_ = json_to_debug_info(j["debug_info"]);
62✔
732

733
    std::string type = j["type"];
62✔
734
    if (type == "sequence") {
62✔
735
        for (size_t i = 0; i < j["children"].size(); i++) {
131✔
736
            auto& child = j["children"][i];
69✔
737
            auto& transition = j["transitions"][i];
69✔
738
            assert(child.contains("type"));
69✔
739
            assert(child["type"].is_string());
69✔
740

741
            assert(transition.contains("type"));
69✔
742
            assert(transition["type"].is_string());
69✔
743
            assert(transition.contains("assignments"));
69✔
744
            assert(transition["assignments"].is_array());
69✔
745
            control_flow::Assignments assignments;
69✔
746
            for (const auto& assignment : transition["assignments"]) {
69✔
747
                assert(assignment.contains("symbol"));
2✔
748
                assert(assignment["symbol"].is_string());
2✔
749
                assert(assignment.contains("expression"));
2✔
750
                assert(assignment["expression"].is_string());
2✔
751
                auto expr = symbolic::parse(assignment["expression"].get<std::string>());
2✔
752
                assignments.insert({symbolic::symbol(assignment["symbol"]), expr});
2✔
753
            }
2✔
754

755
            if (child["type"] == "block") {
69✔
756
                json_to_block_node(child, builder, sequence, assignments);
42✔
757
            } else if (child["type"] == "for") {
42✔
758
                json_to_for_node(child, builder, sequence, assignments);
19✔
759
            } else if (child["type"] == "if_else") {
19✔
UNCOV
760
                json_to_if_else_node(child, builder, sequence, assignments);
×
761
            } else if (child["type"] == "while") {
8✔
UNCOV
762
                json_to_while_node(child, builder, sequence, assignments);
×
763
            } else if (child["type"] == "break") {
8✔
764
                json_to_break_node(child, builder, sequence, assignments);
1✔
765
            } else if (child["type"] == "continue") {
7✔
766
                json_to_continue_node(child, builder, sequence, assignments);
1✔
767
            } else if (child["type"] == "return") {
6✔
UNCOV
768
                json_to_return_node(child, builder, sequence, assignments);
×
769
            } else if (child["type"] == "map") {
6✔
770
                json_to_map_node(child, builder, sequence, assignments);
6✔
771
            } else if (child["type"] == "sequence") {
6✔
UNCOV
772
                auto& subseq = builder.add_sequence(sequence, assignments, json_to_debug_info(child["debug_info"]));
×
UNCOV
773
                json_to_sequence(child, builder, subseq);
×
UNCOV
774
            } else {
×
UNCOV
775
                throw std::runtime_error("Unknown child type");
×
UNCOV
776
            }
×
777

778
            sequence.at(i).second.debug_info_ = json_to_debug_info(transition["debug_info"]);
69✔
779
            sequence.at(i).second.element_id_ = transition["element_id"];
69✔
780
        }
69✔
781
    } else {
62✔
UNCOV
782
        throw std::runtime_error("expected sequence type");
×
UNCOV
783
    }
×
784
}
62✔
785

786
void JSONSerializer::json_to_block_node(
787
    const nlohmann::json& j,
788
    builder::StructuredSDFGBuilder& builder,
789
    structured_control_flow::Sequence& parent,
790
    control_flow::Assignments& assignments
791
) {
43✔
792
    assert(j.contains("type"));
43✔
793
    assert(j["type"].is_string());
43✔
794
    assert(j.contains("dataflow"));
43✔
795
    assert(j["dataflow"].is_object());
43✔
796
    auto& block = builder.add_block(parent, assignments, json_to_debug_info(j["debug_info"]));
43✔
797
    block.element_id_ = j["element_id"];
43✔
798
    assert(j["dataflow"].contains("type"));
43✔
799
    assert(j["dataflow"]["type"].is_string());
43✔
800
    std::string type = j["dataflow"]["type"];
43✔
801
    if (type == "dataflow") {
43✔
802
        json_to_dataflow(j["dataflow"], builder, block);
43✔
803
    } else {
43✔
UNCOV
804
        throw std::runtime_error("Unknown dataflow type");
×
UNCOV
805
    }
×
806
}
43✔
807

808
void JSONSerializer::json_to_for_node(
809
    const nlohmann::json& j,
810
    builder::StructuredSDFGBuilder& builder,
811
    structured_control_flow::Sequence& parent,
812
    control_flow::Assignments& assignments
813
) {
20✔
814
    assert(j.contains("type"));
20✔
815
    assert(j["type"].is_string());
20✔
816
    assert(j.contains("indvar"));
20✔
817
    assert(j["indvar"].is_string());
20✔
818
    assert(j.contains("init"));
20✔
819
    assert(j["init"].is_string());
20✔
820
    assert(j.contains("condition"));
20✔
821
    assert(j["condition"].is_string());
20✔
822
    assert(j.contains("update"));
20✔
823
    assert(j["update"].is_string());
20✔
824
    assert(j.contains("root"));
20✔
825
    assert(j["root"].is_object());
20✔
826

827
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
20✔
828
    auto init = symbolic::parse(j["init"].get<std::string>());
20✔
829
    auto update = symbolic::parse(j["update"].get<std::string>());
20✔
830

831
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
20✔
832
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
20✔
833
    if (condition.is_null()) {
20✔
UNCOV
834
        throw InvalidSDFGException("For loop condition is not a boolean expression");
×
UNCOV
835
    }
×
836

837
    auto& for_node =
20✔
838
        builder.add_for(parent, indvar, condition, init, update, assignments, json_to_debug_info(j["debug_info"]));
20✔
839
    for_node.element_id_ = j["element_id"];
20✔
840

841
    assert(j["root"].contains("type"));
20✔
842
    assert(j["root"]["type"].is_string());
20✔
843
    assert(j["root"]["type"] == "sequence");
20✔
844
    json_to_sequence(j["root"], builder, for_node.root());
20✔
845
}
20✔
846

847
void JSONSerializer::json_to_if_else_node(
848
    const nlohmann::json& j,
849
    builder::StructuredSDFGBuilder& builder,
850
    structured_control_flow::Sequence& parent,
851
    control_flow::Assignments& assignments
852
) {
1✔
853
    assert(j.contains("type"));
1✔
854
    assert(j["type"].is_string());
1✔
855
    assert(j["type"] == "if_else");
1✔
856
    assert(j.contains("branches"));
1✔
857
    assert(j["branches"].is_array());
1✔
858
    auto& if_else_node = builder.add_if_else(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
859
    if_else_node.element_id_ = j["element_id"];
1✔
860
    for (const auto& branch : j["branches"]) {
2✔
861
        assert(branch.contains("condition"));
2✔
862
        assert(branch["condition"].is_string());
2✔
863
        assert(branch.contains("root"));
2✔
864
        assert(branch["root"].is_object());
2✔
865

866
        auto condition_expr = symbolic::parse(branch["condition"].get<std::string>());
2✔
867
        symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
2✔
868
        if (condition.is_null()) {
2✔
UNCOV
869
            throw InvalidSDFGException("If condition is not a boolean expression");
×
UNCOV
870
        }
×
871
        auto& branch_node = builder.add_case(if_else_node, condition);
2✔
872
        assert(branch["root"].contains("type"));
2✔
873
        assert(branch["root"]["type"].is_string());
2✔
874
        std::string type = branch["root"]["type"];
2✔
875
        if (type == "sequence") {
2✔
876
            json_to_sequence(branch["root"], builder, branch_node);
2✔
877
        } else {
2✔
UNCOV
878
            throw std::runtime_error("Unknown child type");
×
UNCOV
879
        }
×
880
    }
2✔
881
}
1✔
882

883
void JSONSerializer::json_to_while_node(
884
    const nlohmann::json& j,
885
    builder::StructuredSDFGBuilder& builder,
886
    structured_control_flow::Sequence& parent,
887
    control_flow::Assignments& assignments
888
) {
3✔
889
    assert(j.contains("type"));
3✔
890
    assert(j["type"].is_string());
3✔
891
    assert(j["type"] == "while");
3✔
892
    assert(j.contains("root"));
3✔
893
    assert(j["root"].is_object());
3✔
894

895
    auto& while_node = builder.add_while(parent, assignments, json_to_debug_info(j["debug_info"]));
3✔
896
    while_node.element_id_ = j["element_id"];
3✔
897

898
    assert(j["root"]["type"] == "sequence");
3✔
899
    json_to_sequence(j["root"], builder, while_node.root());
3✔
900
}
3✔
901

902
void JSONSerializer::json_to_break_node(
903
    const nlohmann::json& j,
904
    builder::StructuredSDFGBuilder& builder,
905
    structured_control_flow::Sequence& parent,
906
    control_flow::Assignments& assignments
907
) {
1✔
908
    assert(j.contains("type"));
1✔
909
    assert(j["type"].is_string());
1✔
910
    assert(j["type"] == "break");
1✔
911
    auto& node = builder.add_break(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
912
    node.element_id_ = j["element_id"];
1✔
913
}
1✔
914

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

928
void JSONSerializer::json_to_map_node(
929
    const nlohmann::json& j,
930
    builder::StructuredSDFGBuilder& builder,
931
    structured_control_flow::Sequence& parent,
932
    control_flow::Assignments& assignments
933
) {
7✔
934
    assert(j.contains("type"));
7✔
935
    assert(j["type"].is_string());
7✔
936
    assert(j["type"] == "map");
7✔
937
    assert(j.contains("indvar"));
7✔
938
    assert(j["indvar"].is_string());
7✔
939
    assert(j.contains("init"));
7✔
940
    assert(j["init"].is_string());
7✔
941
    assert(j.contains("condition"));
7✔
942
    assert(j["condition"].is_string());
7✔
943
    assert(j.contains("update"));
7✔
944
    assert(j["update"].is_string());
7✔
945
    assert(j.contains("root"));
7✔
946
    assert(j["root"].is_object());
7✔
947
    assert(j.contains("schedule_type"));
7✔
948
    assert(j["schedule_type"].is_object());
7✔
949

950
    structured_control_flow::ScheduleType schedule_type = json_to_schedule_type(j["schedule_type"]);
7✔
951

952
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
7✔
953
    auto init = symbolic::parse(j["init"].get<std::string>());
7✔
954
    auto update = symbolic::parse(j["update"].get<std::string>());
7✔
955
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
7✔
956
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
7✔
957
    if (condition.is_null()) {
7✔
UNCOV
958
        throw InvalidSDFGException("Map condition is not a boolean expression");
×
UNCOV
959
    }
×
960

961
    auto& map_node = builder.add_map(
7✔
962
        parent, indvar, condition, init, update, schedule_type, assignments, json_to_debug_info(j["debug_info"])
7✔
963
    );
7✔
964
    map_node.element_id_ = j["element_id"];
7✔
965

966
    assert(j["root"].contains("type"));
7✔
967
    assert(j["root"]["type"].is_string());
7✔
968
    assert(j["root"]["type"] == "sequence");
7✔
969
    json_to_sequence(j["root"], builder, map_node.root());
7✔
970
}
7✔
971

972
void JSONSerializer::json_to_return_node(
973
    const nlohmann::json& j,
974
    builder::StructuredSDFGBuilder& builder,
975
    structured_control_flow::Sequence& parent,
976
    control_flow::Assignments& assignments
977
) {
1✔
978
    assert(j.contains("type"));
1✔
979
    assert(j["type"].is_string());
1✔
980
    assert(j["type"] == "return");
1✔
981

982
    std::string data = j["data"];
1✔
983
    std::unique_ptr<types::IType> data_type = nullptr;
1✔
984
    if (j.contains("data_type")) {
1✔
UNCOV
985
        data_type = json_to_type(j["data_type"]);
×
UNCOV
986
    }
×
987

988
    if (data_type == nullptr) {
1✔
989
        auto& node = builder.add_return(parent, data, assignments, json_to_debug_info(j["debug_info"]));
1✔
990
        node.element_id_ = j["element_id"];
1✔
991
    } else {
1✔
UNCOV
992
        auto& node =
×
UNCOV
993
            builder.add_constant_return(parent, data, *data_type, assignments, json_to_debug_info(j["debug_info"]));
×
UNCOV
994
        node.element_id_ = j["element_id"];
×
UNCOV
995
    }
×
996
}
1✔
997

998
std::unique_ptr<types::IType> JSONSerializer::json_to_type(const nlohmann::json& j) {
527✔
999
    if (j.contains("type")) {
527✔
1000
        if (j["type"] == "scalar") {
527✔
1001
            // Deserialize scalar type
1002
            assert(j.contains("primitive_type"));
385✔
1003
            types::PrimitiveType primitive_type = j["primitive_type"];
385✔
1004
            assert(j.contains("storage_type"));
385✔
1005
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
385✔
1006
            assert(j.contains("initializer"));
385✔
1007
            std::string initializer = j["initializer"];
385✔
1008
            assert(j.contains("alignment"));
385✔
1009
            size_t alignment = j["alignment"];
385✔
1010
            return std::make_unique<types::Scalar>(storage_type, alignment, initializer, primitive_type);
385✔
1011
        } else if (j["type"] == "array") {
385✔
1012
            // Deserialize array type
1013
            assert(j.contains("element_type"));
76✔
1014
            std::unique_ptr<types::IType> member_type = json_to_type(j["element_type"]);
76✔
1015
            assert(j.contains("num_elements"));
76✔
1016
            std::string num_elements_str = j["num_elements"];
76✔
1017
            // Convert num_elements_str to symbolic::Expression
1018
            auto num_elements = symbolic::parse(num_elements_str);
76✔
1019
            assert(j.contains("storage_type"));
76✔
1020
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
76✔
1021
            assert(j.contains("initializer"));
76✔
1022
            std::string initializer = j["initializer"];
76✔
1023
            assert(j.contains("alignment"));
76✔
1024
            size_t alignment = j["alignment"];
76✔
1025
            return std::make_unique<types::Array>(storage_type, alignment, initializer, *member_type, num_elements);
76✔
1026
        } else if (j["type"] == "pointer") {
76✔
1027
            // Deserialize pointer type
1028
            std::optional<std::unique_ptr<types::IType>> pointee_type;
52✔
1029
            if (j.contains("pointee_type")) {
52✔
1030
                assert(j.contains("pointee_type"));
51✔
1031
                pointee_type = json_to_type(j["pointee_type"]);
51✔
1032
            } else {
51✔
1033
                pointee_type = std::nullopt;
1✔
1034
            }
1✔
1035
            assert(j.contains("storage_type"));
52✔
1036
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
52✔
1037
            assert(j.contains("initializer"));
52✔
1038
            std::string initializer = j["initializer"];
52✔
1039
            assert(j.contains("alignment"));
52✔
1040
            size_t alignment = j["alignment"];
52✔
1041
            if (pointee_type.has_value()) {
52✔
1042
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer, *pointee_type.value());
51✔
1043
            } else {
51✔
1044
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer);
1✔
1045
            }
1✔
1046
        } else if (j["type"] == "structure") {
52✔
1047
            // Deserialize structure type
1048
            assert(j.contains("name"));
3✔
1049
            std::string name = j["name"];
3✔
1050
            assert(j.contains("storage_type"));
3✔
1051
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
3✔
1052
            assert(j.contains("initializer"));
3✔
1053
            std::string initializer = j["initializer"];
3✔
1054
            assert(j.contains("alignment"));
3✔
1055
            size_t alignment = j["alignment"];
3✔
1056
            return std::make_unique<types::Structure>(storage_type, alignment, initializer, name);
3✔
1057
        } else if (j["type"] == "function") {
11✔
1058
            // Deserialize function type
1059
            assert(j.contains("return_type"));
4✔
1060
            std::unique_ptr<types::IType> return_type = json_to_type(j["return_type"]);
4✔
1061
            assert(j.contains("params"));
4✔
1062
            std::vector<std::unique_ptr<types::IType>> params;
4✔
1063
            for (const auto& param : j["params"]) {
10✔
1064
                params.push_back(json_to_type(param));
10✔
1065
            }
10✔
1066
            assert(j.contains("is_var_arg"));
4✔
1067
            bool is_var_arg = j["is_var_arg"];
4✔
1068
            assert(j.contains("storage_type"));
4✔
1069
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
4✔
1070
            assert(j.contains("initializer"));
4✔
1071
            std::string initializer = j["initializer"];
4✔
1072
            assert(j.contains("alignment"));
4✔
1073
            size_t alignment = j["alignment"];
4✔
1074
            auto function =
4✔
1075
                std::make_unique<types::Function>(storage_type, alignment, initializer, *return_type, is_var_arg);
4✔
1076
            for (const auto& param : params) {
10✔
1077
                function->add_param(*param);
10✔
1078
            }
10✔
1079
            return function->clone();
4✔
1080
        } else if (j["type"] == "reference") {
7✔
1081
            // Deserialize reference type
1082
            assert(j.contains("reference_type"));
7✔
1083
            std::unique_ptr<types::IType> reference_type = json_to_type(j["reference_type"]);
7✔
1084
            return std::make_unique<sdfg::codegen::Reference>(*reference_type);
7✔
1085
        } else if (j["type"] == "tensor") {
7✔
1086
            // Deserialize tensor type
1087
            assert(j.contains("element_type"));
×
1088
            std::unique_ptr<types::IType> element_type = json_to_type(j["element_type"]);
×
1089
            assert(j.contains("shape"));
×
1090
            std::vector<symbolic::Expression> shape;
×
1091
            for (const auto& dim : j["shape"]) {
×
1092
                assert(dim.is_string());
×
1093
                std::string dim_str = dim;
×
1094
                auto expr = symbolic::parse(dim_str);
×
1095
                shape.push_back(expr);
×
1096
            }
×
1097
            assert(j.contains("strides"));
×
1098
            std::vector<symbolic::Expression> strides;
×
1099
            for (const auto& stride : j["strides"]) {
×
1100
                assert(stride.is_string());
×
UNCOV
1101
                std::string stride_str = stride;
×
1102
                auto expr = symbolic::parse(stride_str);
×
1103
                strides.push_back(expr);
×
UNCOV
1104
            }
×
UNCOV
1105
            assert(j.contains("offset"));
×
UNCOV
1106
            symbolic::Expression offset = symbolic::parse(j["offset"].get<std::string>());
×
UNCOV
1107
            assert(j.contains("storage_type"));
×
UNCOV
1108
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
×
UNCOV
1109
            assert(j.contains("initializer"));
×
UNCOV
1110
            std::string initializer = j["initializer"];
×
UNCOV
1111
            assert(j.contains("alignment"));
×
UNCOV
1112
            size_t alignment = j["alignment"];
×
UNCOV
1113
            return std::make_unique<types::Tensor>(
×
UNCOV
1114
                storage_type, alignment, initializer, dynamic_cast<types::Scalar&>(*element_type), shape, strides, offset
×
UNCOV
1115
            );
×
UNCOV
1116
        } else {
×
UNCOV
1117
            throw std::runtime_error("Unknown type");
×
UNCOV
1118
        }
×
1119
    } else {
527✔
UNCOV
1120
        throw std::runtime_error("Type not found");
×
UNCOV
1121
    }
×
1122
}
527✔
1123

1124
DebugInfo JSONSerializer::json_to_debug_info(const nlohmann::json& j) {
598✔
1125
    assert(j.contains("has"));
598✔
1126
    assert(j["has"].is_boolean());
598✔
1127
    if (!j["has"]) {
598✔
1128
        return DebugInfo();
594✔
1129
    }
594✔
1130
    assert(j.contains("filename"));
598✔
1131
    assert(j["filename"].is_string());
4✔
1132
    std::string filename = j["filename"];
4✔
1133
    assert(j.contains("function"));
4✔
1134
    assert(j["function"].is_string());
4✔
1135
    std::string function = j["function"];
4✔
1136
    assert(j.contains("start_line"));
4✔
1137
    assert(j["start_line"].is_number_integer());
4✔
1138
    size_t start_line = j["start_line"];
4✔
1139
    assert(j.contains("start_column"));
4✔
1140
    assert(j["start_column"].is_number_integer());
4✔
1141
    size_t start_column = j["start_column"];
4✔
1142
    assert(j.contains("end_line"));
4✔
1143
    assert(j["end_line"].is_number_integer());
4✔
1144
    size_t end_line = j["end_line"];
4✔
1145
    assert(j.contains("end_column"));
4✔
1146
    assert(j["end_column"].is_number_integer());
4✔
1147
    size_t end_column = j["end_column"];
4✔
1148
    return DebugInfo(filename, function, start_line, start_column, end_line, end_column);
4✔
1149
}
4✔
1150

1151
ScheduleType JSONSerializer::json_to_schedule_type(const nlohmann::json& j) {
8✔
1152
    assert(j.contains("value"));
8✔
1153
    assert(j["value"].is_string());
8✔
1154
    // assert(j.contains("category"));
1155
    // assert(j["category"].is_number_integer());
1156
    assert(j.contains("properties"));
8✔
1157
    assert(j["properties"].is_object());
8✔
1158
    ScheduleTypeCategory category = ScheduleTypeCategory::None;
8✔
1159
    if (j.contains("category")) {
8✔
1160
        category = static_cast<ScheduleTypeCategory>(j["category"].get<int>());
8✔
1161
    }
8✔
1162
    ScheduleType schedule_type(j["value"].get<std::string>(), category);
8✔
1163
    for (const auto& [key, value] : j["properties"].items()) {
8✔
1164
        assert(value.is_string());
3✔
1165
        schedule_type.set_property(key, value.get<std::string>());
3✔
1166
    }
3✔
1167
    return schedule_type;
8✔
1168
}
8✔
1169

1170
types::StorageType JSONSerializer::json_to_storage_type(const nlohmann::json& j) {
526✔
1171
    if (!j.contains("value")) {
526✔
1172
        return types::StorageType::CPU_Stack();
×
1173
    }
×
1174
    std::string value = j["value"].get<std::string>();
526✔
1175

1176
    symbolic::Expression allocation_size = SymEngine::null;
526✔
1177
    if (j.contains("allocation_size")) {
526✔
UNCOV
1178
        allocation_size = symbolic::parse(j["allocation_size"].get<std::string>());
×
UNCOV
1179
    }
×
1180

1181
    types::StorageType::AllocationType allocation = j["allocation"];
526✔
1182
    types::StorageType::AllocationType deallocation = j["deallocation"];
526✔
1183

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

1186
    if (j.contains("args")) {
526✔
1187
        nlohmann::json::array_t args = j["args"];
×
1188
        if (args.size() > 0) {
×
UNCOV
1189
            storageType.arg1(symbolic::parse(args[0].get<std::string>()));
×
1190
        }
×
1191
    }
×
1192
    return storageType;
526✔
1193
}
526✔
1194

1195
std::string JSONSerializer::expression(const symbolic::Expression expr) {
914✔
1196
    JSONSymbolicPrinter printer;
914✔
1197
    return printer.apply(expr);
914✔
1198
};
914✔
1199

1200
symbolic::Expression JSONSerializer::json_to_expr(const nlohmann::json& j) {
3✔
1201
    return symbolic::parse(j.get<std::string>());
3✔
1202
}
3✔
1203

1204
void JSONSerializer::writeToFile(const StructuredSDFG& sdfg, const std::filesystem::path& file) {
×
1205
    JSONSerializer ser;
×
1206
    auto json = ser.serialize(sdfg);
×
1207

1208
    auto parent_path = file.parent_path();
×
1209
    if (!parent_path.empty()) {
×
1210
        std::filesystem::create_directories(file.parent_path());
×
1211
    }
×
1212

UNCOV
1213
    std::ofstream out(file, std::ofstream::out);
×
UNCOV
1214
    if (!out.is_open()) {
×
UNCOV
1215
        std::cerr << "Could not open file " << file << " for writing JSON output." << std::endl;
×
UNCOV
1216
    }
×
UNCOV
1217
    out << json << std::endl;
×
UNCOV
1218
    out.close();
×
UNCOV
1219
}
×
1220

UNCOV
1221
void JSONSymbolicPrinter::bvisit(const SymEngine::Equality& x) {
×
UNCOV
1222
    str_ = apply(x.get_args()[0]) + " == " + apply(x.get_args()[1]);
×
1223
    str_ = parenthesize(str_);
×
1224
};
×
1225

1226
void JSONSymbolicPrinter::bvisit(const SymEngine::Unequality& x) {
×
1227
    str_ = apply(x.get_args()[0]) + " != " + apply(x.get_args()[1]);
×
1228
    str_ = parenthesize(str_);
×
1229
};
×
1230

1231
void JSONSymbolicPrinter::bvisit(const SymEngine::LessThan& x) {
4✔
1232
    str_ = apply(x.get_args()[0]) + " <= " + apply(x.get_args()[1]);
4✔
1233
    str_ = parenthesize(str_);
4✔
1234
};
4✔
1235

1236
void JSONSymbolicPrinter::bvisit(const SymEngine::StrictLessThan& x) {
192✔
1237
    str_ = apply(x.get_args()[0]) + " < " + apply(x.get_args()[1]);
192✔
1238
    str_ = parenthesize(str_);
192✔
1239
};
192✔
1240

1241
void JSONSymbolicPrinter::bvisit(const SymEngine::Min& x) {
2✔
1242
    std::ostringstream s;
2✔
1243
    auto container = x.get_args();
2✔
1244
    if (container.size() == 1) {
2✔
UNCOV
1245
        s << apply(*container.begin());
×
1246
    } else {
2✔
1247
        s << "min(";
2✔
1248
        s << apply(*container.begin());
2✔
1249

1250
        // Recursively apply __daisy_min to the arguments
1251
        SymEngine::vec_basic subargs;
2✔
1252
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
4✔
1253
            subargs.push_back(*it);
2✔
1254
        }
2✔
1255
        auto submin = SymEngine::min(subargs);
2✔
1256
        s << ", " << apply(submin);
2✔
1257

1258
        s << ")";
2✔
1259
    }
2✔
1260

1261
    str_ = s.str();
2✔
1262
};
2✔
1263

1264
void JSONSymbolicPrinter::bvisit(const SymEngine::Max& x) {
4✔
1265
    std::ostringstream s;
4✔
1266
    auto container = x.get_args();
4✔
1267
    if (container.size() == 1) {
4✔
UNCOV
1268
        s << apply(*container.begin());
×
1269
    } else {
4✔
1270
        s << "max(";
4✔
1271
        s << apply(*container.begin());
4✔
1272

1273
        // Recursively apply __daisy_max to the arguments
1274
        SymEngine::vec_basic subargs;
4✔
1275
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
8✔
1276
            subargs.push_back(*it);
4✔
1277
        }
4✔
1278
        auto submax = SymEngine::max(subargs);
4✔
1279
        s << ", " << apply(submax);
4✔
1280

1281
        s << ")";
4✔
1282
    }
4✔
1283

1284
    str_ = s.str();
4✔
1285
};
4✔
1286

1287
void LibraryNodeSerializerRegistry::
1288
    register_library_node_serializer(std::string library_node_code, LibraryNodeSerializerFn fn) {
226✔
1289
    std::lock_guard<std::mutex> lock(mutex_);
226✔
1290
    if (factory_map_.find(library_node_code) != factory_map_.end()) {
226✔
1291
        return;
8✔
1292
    }
8✔
1293
    factory_map_[library_node_code] = std::move(fn);
218✔
1294
}
218✔
1295

1296
LibraryNodeSerializerFn LibraryNodeSerializerRegistry::get_library_node_serializer(std::string library_node_code) {
17✔
1297
    auto it = factory_map_.find(library_node_code);
17✔
1298
    if (it != factory_map_.end()) {
17✔
1299
        return it->second;
17✔
1300
    }
17✔
1301
    return nullptr;
×
1302
}
17✔
1303

1304
size_t LibraryNodeSerializerRegistry::size() const { return factory_map_.size(); }
×
1305

1306
void register_default_serializers() {
4✔
1307
    // stdlib
1308
    LibraryNodeSerializerRegistry::instance()
4✔
1309
        .register_library_node_serializer(stdlib::LibraryNodeType_Alloca.value(), []() {
4✔
UNCOV
1310
            return std::make_unique<stdlib::AllocaNodeSerializer>();
×
UNCOV
1311
        });
×
1312
    LibraryNodeSerializerRegistry::instance()
4✔
1313
        .register_library_node_serializer(stdlib::LibraryNodeType_Assert.value(), []() {
4✔
UNCOV
1314
            return std::make_unique<stdlib::AssertNodeSerializer>();
×
UNCOV
1315
        });
×
1316
    LibraryNodeSerializerRegistry::instance()
4✔
1317
        .register_library_node_serializer(stdlib::LibraryNodeType_Calloc.value(), []() {
4✔
UNCOV
1318
            return std::make_unique<stdlib::CallocNodeSerializer>();
×
UNCOV
1319
        });
×
1320
    LibraryNodeSerializerRegistry::instance()
4✔
1321
        .register_library_node_serializer(stdlib::LibraryNodeType_Free.value(), []() {
4✔
UNCOV
1322
            return std::make_unique<stdlib::FreeNodeSerializer>();
×
UNCOV
1323
        });
×
1324
    LibraryNodeSerializerRegistry::instance()
4✔
1325
        .register_library_node_serializer(stdlib::LibraryNodeType_Malloc.value(), []() {
4✔
UNCOV
1326
            return std::make_unique<stdlib::MallocNodeSerializer>();
×
UNCOV
1327
        });
×
1328
    LibraryNodeSerializerRegistry::instance()
4✔
1329
        .register_library_node_serializer(stdlib::LibraryNodeType_Memcpy.value(), []() {
4✔
UNCOV
1330
            return std::make_unique<stdlib::MemcpyNodeSerializer>();
×
UNCOV
1331
        });
×
1332
    LibraryNodeSerializerRegistry::instance()
4✔
1333
        .register_library_node_serializer(stdlib::LibraryNodeType_Memmove.value(), []() {
4✔
1334
            return std::make_unique<stdlib::MemmoveNodeSerializer>();
×
1335
        });
×
1336
    LibraryNodeSerializerRegistry::instance()
4✔
1337
        .register_library_node_serializer(stdlib::LibraryNodeType_Memset.value(), []() {
4✔
UNCOV
1338
            return std::make_unique<stdlib::MemsetNodeSerializer>();
×
UNCOV
1339
        });
×
1340
    LibraryNodeSerializerRegistry::instance()
4✔
1341
        .register_library_node_serializer(stdlib::LibraryNodeType_Trap.value(), []() {
4✔
UNCOV
1342
            return std::make_unique<stdlib::TrapNodeSerializer>();
×
UNCOV
1343
        });
×
1344
    LibraryNodeSerializerRegistry::instance()
4✔
1345
        .register_library_node_serializer(stdlib::LibraryNodeType_Unreachable.value(), []() {
4✔
UNCOV
1346
            return std::make_unique<stdlib::UnreachableNodeSerializer>();
×
UNCOV
1347
        });
×
1348

1349
    // Metadata
1350
    LibraryNodeSerializerRegistry::instance()
4✔
1351
        .register_library_node_serializer(data_flow::LibraryNodeType_Metadata.value(), []() {
4✔
UNCOV
1352
            return std::make_unique<data_flow::MetadataNodeSerializer>();
×
UNCOV
1353
        });
×
1354

1355
    // Barrier
1356
    LibraryNodeSerializerRegistry::instance()
4✔
1357
        .register_library_node_serializer(data_flow::LibraryNodeType_BarrierLocal.value(), []() {
4✔
1358
            return std::make_unique<data_flow::BarrierLocalNodeSerializer>();
1✔
1359
        });
1✔
1360

1361
    // Call Node
1362
    LibraryNodeSerializerRegistry::instance()
4✔
1363
        .register_library_node_serializer(data_flow::LibraryNodeType_Call.value(), []() {
6✔
1364
            return std::make_unique<data_flow::CallNodeSerializer>();
6✔
1365
        });
6✔
1366
    LibraryNodeSerializerRegistry::instance()
4✔
1367
        .register_library_node_serializer(data_flow::LibraryNodeType_Invoke.value(), []() {
4✔
1368
            return std::make_unique<data_flow::InvokeNodeSerializer>();
×
UNCOV
1369
        });
×
1370

1371
    // LoadConst
1372
    LibraryNodeSerializerRegistry::instance()
4✔
1373
        .register_library_node_serializer(data_flow::LibraryNodeType_LoadConst.value(), []() {
4✔
1374
            return std::make_unique<data_flow::LoadConstNodeSerializer>();
2✔
1375
        });
2✔
1376

1377
    // CMath
1378
    LibraryNodeSerializerRegistry::instance()
4✔
1379
        .register_library_node_serializer(math::cmath::LibraryNodeType_CMath.value(), []() {
4✔
UNCOV
1380
            return std::make_unique<math::cmath::CMathNodeSerializer>();
×
1381
        });
×
1382
    // Backward compatibility
1383
    LibraryNodeSerializerRegistry::instance()
4✔
1384
        .register_library_node_serializer(math::cmath::LibraryNodeType_CMath_Deprecated.value(), []() {
4✔
UNCOV
1385
            return std::make_unique<math::cmath::CMathNodeSerializer>();
×
UNCOV
1386
        });
×
1387

1388
    // BLAS
1389
    LibraryNodeSerializerRegistry::instance()
4✔
1390
        .register_library_node_serializer(math::blas::LibraryNodeType_DOT.value(), []() {
4✔
UNCOV
1391
            return std::make_unique<math::blas::DotNodeSerializer>();
×
1392
        });
×
1393
    LibraryNodeSerializerRegistry::instance()
4✔
1394
        .register_library_node_serializer(math::blas::LibraryNodeType_GEMM.value(), []() {
4✔
UNCOV
1395
            return std::make_unique<math::blas::GEMMNodeSerializer>();
×
1396
        });
×
1397
    LibraryNodeSerializerRegistry::instance()
4✔
1398
        .register_library_node_serializer(math::blas::LibraryNodeType_BatchedGEMM.value(), []() {
4✔
UNCOV
1399
            return std::make_unique<math::blas::BatchedGEMMNodeSerializer>();
×
1400
        });
×
1401

1402
    // Tensor
1403

1404
    LibraryNodeSerializerRegistry::instance()
4✔
1405
        .register_library_node_serializer(math::tensor::LibraryNodeType_Broadcast.value(), []() {
4✔
UNCOV
1406
            return std::make_unique<math::tensor::BroadcastNodeSerializer>();
×
UNCOV
1407
        });
×
1408
    LibraryNodeSerializerRegistry::instance()
4✔
1409
        .register_library_node_serializer(math::tensor::LibraryNodeType_Conv.value(), []() {
4✔
1410
            return std::make_unique<math::tensor::ConvNodeSerializer>();
×
1411
        });
×
1412
    LibraryNodeSerializerRegistry::instance()
4✔
1413
        .register_library_node_serializer(math::tensor::LibraryNodeType_Pooling.value(), []() {
4✔
1414
            return std::make_unique<math::tensor::PoolingNodeSerializer>();
×
1415
        });
×
1416
    LibraryNodeSerializerRegistry::instance()
4✔
1417
        .register_library_node_serializer(math::tensor::LibraryNodeType_Transpose.value(), []() {
4✔
1418
            return std::make_unique<math::tensor::TransposeNodeSerializer>();
×
1419
        });
×
1420
    LibraryNodeSerializerRegistry::instance()
4✔
1421
        .register_library_node_serializer(math::tensor::LibraryNodeType_MatMul.value(), []() {
4✔
1422
            return std::make_unique<math::tensor::MatMulNodeSerializer>();
×
1423
        });
×
1424

1425
    // Elementwise
1426
    LibraryNodeSerializerRegistry::instance()
4✔
1427
        .register_library_node_serializer(math::tensor::LibraryNodeType_Abs.value(), []() {
4✔
UNCOV
1428
            return std::make_unique<math::tensor::AbsNodeSerializer>();
×
UNCOV
1429
        });
×
1430
    LibraryNodeSerializerRegistry::instance()
4✔
1431
        .register_library_node_serializer(math::tensor::LibraryNodeType_Add.value(), []() {
4✔
UNCOV
1432
            return std::make_unique<math::tensor::AddNodeSerializer>();
×
UNCOV
1433
        });
×
1434
    LibraryNodeSerializerRegistry::instance()
4✔
1435
        .register_library_node_serializer(math::tensor::LibraryNodeType_Div.value(), []() {
4✔
UNCOV
1436
            return std::make_unique<math::tensor::DivNodeSerializer>();
×
UNCOV
1437
        });
×
1438
    LibraryNodeSerializerRegistry::instance()
4✔
1439
        .register_library_node_serializer(math::tensor::LibraryNodeType_Elu.value(), []() {
4✔
UNCOV
1440
            return std::make_unique<math::tensor::EluNodeSerializer>();
×
UNCOV
1441
        });
×
1442
    LibraryNodeSerializerRegistry::instance()
4✔
1443
        .register_library_node_serializer(math::tensor::LibraryNodeType_Exp.value(), []() {
4✔
UNCOV
1444
            return std::make_unique<math::tensor::ExpNodeSerializer>();
×
UNCOV
1445
        });
×
1446
    LibraryNodeSerializerRegistry::instance()
4✔
1447
        .register_library_node_serializer(math::tensor::LibraryNodeType_Erf.value(), []() {
4✔
UNCOV
1448
            return std::make_unique<math::tensor::ErfNodeSerializer>();
×
UNCOV
1449
        });
×
1450
    LibraryNodeSerializerRegistry::instance()
4✔
1451
        .register_library_node_serializer(math::tensor::LibraryNodeType_HardSigmoid.value(), []() {
4✔
UNCOV
1452
            return std::make_unique<math::tensor::HardSigmoidNodeSerializer>();
×
UNCOV
1453
        });
×
1454
    LibraryNodeSerializerRegistry::instance()
4✔
1455
        .register_library_node_serializer(math::tensor::LibraryNodeType_LeakyReLU.value(), []() {
4✔
UNCOV
1456
            return std::make_unique<math::tensor::LeakyReLUNodeSerializer>();
×
UNCOV
1457
        });
×
1458
    LibraryNodeSerializerRegistry::instance()
4✔
1459
        .register_library_node_serializer(math::tensor::LibraryNodeType_Mul.value(), []() {
4✔
UNCOV
1460
            return std::make_unique<math::tensor::MulNodeSerializer>();
×
UNCOV
1461
        });
×
1462
    LibraryNodeSerializerRegistry::instance()
4✔
1463
        .register_library_node_serializer(math::tensor::LibraryNodeType_Pow.value(), []() {
4✔
UNCOV
1464
            return std::make_unique<math::tensor::PowNodeSerializer>();
×
UNCOV
1465
        });
×
1466
    LibraryNodeSerializerRegistry::instance()
4✔
1467
        .register_library_node_serializer(math::tensor::LibraryNodeType_ReLU.value(), []() {
4✔
UNCOV
1468
            return std::make_unique<math::tensor::ReLUNodeSerializer>();
×
UNCOV
1469
        });
×
1470
    LibraryNodeSerializerRegistry::instance()
4✔
1471
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sigmoid.value(), []() {
4✔
UNCOV
1472
            return std::make_unique<math::tensor::SigmoidNodeSerializer>();
×
UNCOV
1473
        });
×
1474
    LibraryNodeSerializerRegistry::instance()
4✔
1475
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sqrt.value(), []() {
4✔
UNCOV
1476
            return std::make_unique<math::tensor::SqrtNodeSerializer>();
×
UNCOV
1477
        });
×
1478
    LibraryNodeSerializerRegistry::instance()
4✔
1479
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sub.value(), []() {
4✔
UNCOV
1480
            return std::make_unique<math::tensor::SubNodeSerializer>();
×
UNCOV
1481
        });
×
1482
    LibraryNodeSerializerRegistry::instance()
4✔
1483
        .register_library_node_serializer(math::tensor::LibraryNodeType_Tanh.value(), []() {
4✔
UNCOV
1484
            return std::make_unique<math::tensor::TanhNodeSerializer>();
×
UNCOV
1485
        });
×
1486
    LibraryNodeSerializerRegistry::instance()
4✔
1487
        .register_library_node_serializer(math::tensor::LibraryNodeType_Minimum.value(), []() {
4✔
UNCOV
1488
            return std::make_unique<math::tensor::MinimumNodeSerializer>();
×
UNCOV
1489
        });
×
1490
    LibraryNodeSerializerRegistry::instance()
4✔
1491
        .register_library_node_serializer(math::tensor::LibraryNodeType_Maximum.value(), []() {
4✔
UNCOV
1492
            return std::make_unique<math::tensor::MaximumNodeSerializer>();
×
UNCOV
1493
        });
×
1494
    LibraryNodeSerializerRegistry::instance()
4✔
1495
        .register_library_node_serializer(math::tensor::LibraryNodeType_Fill.value(), []() {
4✔
1496
            return std::make_unique<math::tensor::FillNodeSerializer>();
×
UNCOV
1497
        });
×
1498
    LibraryNodeSerializerRegistry::instance()
4✔
1499
        .register_library_node_serializer(math::tensor::LibraryNodeType_TensorTasklet.value(), []() {
4✔
UNCOV
1500
            return std::make_unique<math::tensor::TaskletTensorNodeSerializer>();
×
1501
        });
×
1502
    LibraryNodeSerializerRegistry::instance()
4✔
1503
        .register_library_node_serializer(math::tensor::LibraryNodeType_TensorCMath.value(), []() {
4✔
UNCOV
1504
            return std::make_unique<math::tensor::CMathTensorNodeSerializer>();
×
1505
        });
×
1506
    LibraryNodeSerializerRegistry::instance()
4✔
1507
        .register_library_node_serializer(math::tensor::LibraryNodeType_Cast.value(), []() {
4✔
UNCOV
1508
            return std::make_unique<math::tensor::CastNodeSerializer>();
×
1509
        });
×
1510

1511
    LibraryNodeSerializerRegistry::instance()
4✔
1512
        .register_library_node_serializer(math::tensor::LibraryNodeType_BatchNorm.value(), [] {
4✔
1513
            return std::make_unique<math::tensor::BatchNormNodeSerializer>();
×
1514
        });
×
1515

1516
    // Reduce
1517
    LibraryNodeSerializerRegistry::instance()
4✔
1518
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sum.value(), []() {
4✔
UNCOV
1519
            return std::make_unique<math::tensor::SumNodeSerializer>();
×
UNCOV
1520
        });
×
1521
    LibraryNodeSerializerRegistry::instance()
4✔
1522
        .register_library_node_serializer(math::tensor::LibraryNodeType_Max.value(), []() {
4✔
UNCOV
1523
            return std::make_unique<math::tensor::MaxNodeSerializer>();
×
UNCOV
1524
        });
×
1525
    LibraryNodeSerializerRegistry::instance()
4✔
1526
        .register_library_node_serializer(math::tensor::LibraryNodeType_Min.value(), []() {
4✔
1527
            return std::make_unique<math::tensor::MinNodeSerializer>();
×
1528
        });
×
1529
    LibraryNodeSerializerRegistry::instance()
4✔
1530
        .register_library_node_serializer(math::tensor::LibraryNodeType_Softmax.value(), []() {
4✔
UNCOV
1531
            return std::make_unique<math::tensor::SoftmaxNodeSerializer>();
×
UNCOV
1532
        });
×
1533
    LibraryNodeSerializerRegistry::instance()
4✔
1534
        .register_library_node_serializer(math::tensor::LibraryNodeType_Mean.value(), []() {
4✔
UNCOV
1535
            return std::make_unique<math::tensor::MeanNodeSerializer>();
×
UNCOV
1536
        });
×
1537
    LibraryNodeSerializerRegistry::instance()
4✔
1538
        .register_library_node_serializer(math::tensor::LibraryNodeType_Std.value(), []() {
4✔
UNCOV
1539
            return std::make_unique<math::tensor::StdNodeSerializer>();
×
UNCOV
1540
        });
×
1541

1542
    // Einsum
1543
    LibraryNodeSerializerRegistry::instance()
4✔
1544
        .register_library_node_serializer(math::tensor::LibraryNodeType_Einsum.value(), []() {
4✔
UNCOV
1545
            return std::make_unique<math::tensor::EinsumSerializer>();
×
UNCOV
1546
        });
×
1547
}
4✔
1548

1549
} // namespace serializer
1550
} // 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