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

daisytuner / docc / 23906044628

02 Apr 2026 02:40PM UTC coverage: 64.553% (+0.08%) from 64.474%
23906044628

Pull #632

github

web-flow
Merge b2698daab into 3125b927b
Pull Request #632: Separate can_be_applied and apply for GPUTilling during Loop Scheduling

282 of 348 new or added lines in 16 files covered. (81.03%)

29 existing lines in 10 files now uncovered.

28998 of 44921 relevant lines covered (64.55%)

453.01 hits per line

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

75.16
/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 <sdfg/einsum/einsum.h>
7
#include <utility>
8
#include <vector>
9

10
#include "sdfg/data_flow/library_nodes/barrier_local_node.h"
11
#include "sdfg/data_flow/library_nodes/call_node.h"
12
#include "sdfg/data_flow/library_nodes/invoke_node.h"
13
#include "sdfg/data_flow/library_nodes/math/math.h"
14
#include "sdfg/data_flow/library_nodes/math/tensor/elementwise_ops/cmath_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/element.h"
24
#include "sdfg/structured_control_flow/block.h"
25
#include "sdfg/structured_control_flow/for.h"
26
#include "sdfg/structured_control_flow/if_else.h"
27
#include "sdfg/structured_control_flow/map.h"
28
#include "sdfg/structured_control_flow/return.h"
29
#include "sdfg/structured_control_flow/sequence.h"
30
#include "sdfg/structured_control_flow/while.h"
31
#include "sdfg/structured_sdfg.h"
32
#include "sdfg/symbolic/symbolic.h"
33
#include "sdfg/types/function.h"
34
#include "sdfg/types/scalar.h"
35
#include "sdfg/types/type.h"
36
#include "symengine/expression.h"
37
#include "symengine/logic.h"
38
#include "symengine/symengine_rcp.h"
39

40
namespace sdfg {
41
namespace serializer {
42

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

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

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

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

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

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

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

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

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

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

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

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

111
    return j;
24✔
112
}
24✔
113

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

283
void JSONSerializer::return_node_to_json(nlohmann::json& j, const structured_control_flow::Return& return_node) {
2✔
284
    j["type"] = "return";
2✔
285
    j["element_id"] = return_node.element_id();
2✔
286
    j["data"] = return_node.data();
2✔
287

288
    if (return_node.is_constant()) {
2✔
289
        nlohmann::json type_json;
×
290
        type_to_json(type_json, return_node.type());
×
291
        j["data_type"] = type_json;
×
292
    }
×
293

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

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

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

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

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

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

335
        j["children"].push_back(child_json);
71✔
336

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

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

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

353
        j["transitions"].push_back(transition_json);
71✔
354
    }
71✔
355
}
61✔
356

357
void JSONSerializer::type_to_json(nlohmann::json& j, const types::IType& type) {
528✔
358
    if (auto scalar_type = dynamic_cast<const types::Scalar*>(&type)) {
528✔
359
        j["type"] = "scalar";
387✔
360
        j["primitive_type"] = scalar_type->primitive_type();
387✔
361
        j["storage_type"] = nlohmann::json::object();
387✔
362
        storage_type_to_json(j["storage_type"], scalar_type->storage_type());
387✔
363
        j["initializer"] = scalar_type->initializer();
387✔
364
        j["alignment"] = scalar_type->alignment();
387✔
365
    } else if (auto array_type = dynamic_cast<const types::Array*>(&type)) {
387✔
366
        j["type"] = "array";
72✔
367
        nlohmann::json element_type_json;
72✔
368
        type_to_json(element_type_json, array_type->element_type());
72✔
369
        j["element_type"] = element_type_json;
72✔
370
        j["num_elements"] = expression(array_type->num_elements());
72✔
371
        j["storage_type"] = nlohmann::json::object();
72✔
372
        storage_type_to_json(j["storage_type"], array_type->storage_type());
72✔
373
        j["initializer"] = array_type->initializer();
72✔
374
        j["alignment"] = array_type->alignment();
72✔
375
    } else if (auto pointer_type = dynamic_cast<const types::Pointer*>(&type)) {
72✔
376
        j["type"] = "pointer";
51✔
377
        if (pointer_type->has_pointee_type()) {
51✔
378
            nlohmann::json pointee_type_json;
50✔
379
            type_to_json(pointee_type_json, pointer_type->pointee_type());
50✔
380
            j["pointee_type"] = pointee_type_json;
50✔
381
        }
50✔
382
        j["storage_type"] = nlohmann::json::object();
51✔
383
        storage_type_to_json(j["storage_type"], pointer_type->storage_type());
51✔
384
        j["initializer"] = pointer_type->initializer();
51✔
385
        j["alignment"] = pointer_type->alignment();
51✔
386
    } else if (auto structure_type = dynamic_cast<const types::Structure*>(&type)) {
51✔
387
        j["type"] = "structure";
5✔
388
        j["name"] = structure_type->name();
5✔
389
        j["storage_type"] = nlohmann::json::object();
5✔
390
        storage_type_to_json(j["storage_type"], structure_type->storage_type());
5✔
391
        j["initializer"] = structure_type->initializer();
5✔
392
        j["alignment"] = structure_type->alignment();
5✔
393
    } else if (auto function_type = dynamic_cast<const types::Function*>(&type)) {
13✔
394
        j["type"] = "function";
5✔
395
        nlohmann::json return_type_json;
5✔
396
        type_to_json(return_type_json, function_type->return_type());
5✔
397
        j["return_type"] = return_type_json;
5✔
398
        j["params"] = nlohmann::json::array();
5✔
399
        for (size_t i = 0; i < function_type->num_params(); i++) {
16✔
400
            nlohmann::json param_json;
11✔
401
            type_to_json(param_json, function_type->param_type(symbolic::integer(i)));
11✔
402
            j["params"].push_back(param_json);
11✔
403
        }
11✔
404
        j["is_var_arg"] = function_type->is_var_arg();
5✔
405
        j["storage_type"] = nlohmann::json::object();
5✔
406
        storage_type_to_json(j["storage_type"], function_type->storage_type());
5✔
407
        j["initializer"] = function_type->initializer();
5✔
408
        j["alignment"] = function_type->alignment();
5✔
409
    } else if (auto reference_type = dynamic_cast<const sdfg::codegen::Reference*>(&type)) {
8✔
410
        j["type"] = "reference";
8✔
411
        nlohmann::json reference_type_json;
8✔
412
        type_to_json(reference_type_json, reference_type->reference_type());
8✔
413
        j["reference_type"] = reference_type_json;
8✔
414
    } else if (auto tensor_type = dynamic_cast<const types::Tensor*>(&type)) {
8✔
415
        j["type"] = "tensor";
×
416
        nlohmann::json element_type_json;
×
417
        type_to_json(element_type_json, tensor_type->element_type());
×
418
        j["element_type"] = element_type_json;
×
419
        j["shape"] = nlohmann::json::array();
×
420
        for (const auto& dim : tensor_type->shape()) {
×
421
            j["shape"].push_back(expression(dim));
×
422
        }
×
423
        j["strides"] = nlohmann::json::array();
×
424
        for (const auto& stride : tensor_type->strides()) {
×
425
            j["strides"].push_back(expression(stride));
×
426
        }
×
427
        j["offset"] = expression(tensor_type->offset());
×
428
        j["storage_type"] = nlohmann::json::object();
×
429
        storage_type_to_json(j["storage_type"], tensor_type->storage_type());
×
430
        j["initializer"] = tensor_type->initializer();
×
431
        j["alignment"] = tensor_type->alignment();
×
432
    } else {
×
433
        throw std::runtime_error("Unknown type");
×
434
    }
×
435
}
528✔
436

437
void JSONSerializer::structure_definition_to_json(nlohmann::json& j, const types::StructureDefinition& definition) {
2✔
438
    j["name"] = definition.name();
2✔
439
    j["members"] = nlohmann::json::array();
2✔
440
    for (size_t i = 0; i < definition.num_members(); i++) {
4✔
441
        nlohmann::json member_json;
2✔
442
        type_to_json(member_json, definition.member_type(symbolic::integer(i)));
2✔
443
        j["members"].push_back(member_json);
2✔
444
    }
2✔
445
    j["is_packed"] = definition.is_packed();
2✔
446
}
2✔
447

448
void JSONSerializer::debug_info_to_json(nlohmann::json& j, const DebugInfo& debug_info) {
598✔
449
    j["has"] = debug_info.has();
598✔
450
    j["filename"] = debug_info.filename();
598✔
451
    j["function"] = debug_info.function();
598✔
452
    j["start_line"] = debug_info.start_line();
598✔
453
    j["start_column"] = debug_info.start_column();
598✔
454
    j["end_line"] = debug_info.end_line();
598✔
455
    j["end_column"] = debug_info.end_column();
598✔
456
}
598✔
457

458

459
void JSONSerializer::schedule_type_to_json(nlohmann::json& j, const ScheduleType& schedule_type) {
8✔
460
    j["value"] = schedule_type.value();
8✔
461
    j["category"] = static_cast<int>(schedule_type.category());
8✔
462
    j["properties"] = nlohmann::json::object();
8✔
463
    for (const auto& prop : schedule_type.properties()) {
8✔
464
        j["properties"][prop.first] = prop.second;
4✔
465
    }
4✔
466
}
8✔
467

468
void JSONSerializer::storage_type_to_json(nlohmann::json& j, const types::StorageType& storage_type) {
520✔
469
    j["value"] = storage_type.value();
520✔
470
    j["allocation"] = storage_type.allocation();
520✔
471
    j["deallocation"] = storage_type.deallocation();
520✔
472
    if (!storage_type.allocation_size().is_null()) {
520✔
UNCOV
473
        j["allocation_size"] = expression(storage_type.allocation_size());
×
UNCOV
474
    }
×
475
    const symbolic::Expression& arg1 = storage_type.arg1();
520✔
476
    if (!arg1.is_null()) {
520✔
477
        auto args = nlohmann::json::array();
×
478
        args.push_back(expression(arg1));
×
479
        j["args"] = args;
×
480
    }
×
481
}
520✔
482

483

484
/*
485
 * * Deserialization logic
486
 */
487

488
std::unique_ptr<StructuredSDFG> JSONSerializer::deserialize(nlohmann::json& j) {
25✔
489
    assert(j.contains("name"));
25✔
490
    assert(j["name"].is_string());
25✔
491
    assert(j.contains("type"));
25✔
492
    assert(j["type"].is_string());
25✔
493
    assert(j.contains("element_counter"));
25✔
494
    assert(j["element_counter"].is_number_integer());
25✔
495

496
    std::unique_ptr<types::IType> return_type;
25✔
497
    if (j.contains("return_type")) {
25✔
498
        return_type = json_to_type(j["return_type"]);
25✔
499
    } else {
25✔
500
        return_type = std::make_unique<types::Scalar>(types::PrimitiveType::Void);
×
501
    }
×
502

503
    FunctionType function_type = function_type_from_string(j["type"].get<std::string>());
25✔
504
    builder::StructuredSDFGBuilder builder(j["name"], function_type, *return_type);
25✔
505

506
    size_t element_counter = j["element_counter"];
25✔
507
    builder.set_element_counter(element_counter);
25✔
508

509
    // deserialize structures
510
    assert(j.contains("structures"));
25✔
511
    assert(j["structures"].is_array());
25✔
512
    for (const auto& structure : j["structures"]) {
25✔
513
        assert(structure.contains("name"));
1✔
514
        assert(structure["name"].is_string());
1✔
515
        json_to_structure_definition(structure, builder);
1✔
516
    }
1✔
517

518
    nlohmann::json& containers = j["containers"];
25✔
519

520
    // deserialize externals
521
    for (const auto& external : j["externals"]) {
25✔
522
        assert(external.contains("name"));
7✔
523
        assert(external["name"].is_string());
7✔
524
        assert(external.contains("linkage_type"));
7✔
525
        assert(external["linkage_type"].is_number_integer());
7✔
526
        auto& type_desc = containers.at(external["name"].get<std::string>());
7✔
527
        auto type = json_to_type(type_desc);
7✔
528
        builder.add_external(external["name"], *type, LinkageType(external["linkage_type"]));
7✔
529
    }
7✔
530

531
    // deserialize arguments
532
    for (const auto& name : j["arguments"]) {
26✔
533
        auto& type_desc = containers.at(name.get<std::string>());
26✔
534
        auto type = json_to_type(type_desc);
26✔
535
        builder.add_container(name, *type, true, false);
26✔
536
    }
26✔
537

538
    // deserialize transients
539
    for (const auto& entry : containers.items()) {
139✔
540
        if (builder.subject().is_argument(entry.key())) {
139✔
541
            continue;
26✔
542
        }
26✔
543
        if (builder.subject().is_external(entry.key())) {
113✔
544
            continue;
7✔
545
        }
7✔
546
        auto type = json_to_type(entry.value());
106✔
547
        builder.add_container(entry.key(), *type, false, false);
106✔
548
    }
106✔
549

550
    // deserialize root node
551
    assert(j.contains("root"));
25✔
552
    auto& root = builder.subject().root();
25✔
553
    json_to_sequence(j["root"], builder, root);
25✔
554

555
    // deserialize metadata
556
    assert(j.contains("metadata"));
25✔
557
    assert(j["metadata"].is_object());
25✔
558
    for (const auto& entry : j["metadata"].items()) {
25✔
559
        builder.subject().add_metadata(entry.key(), entry.value());
1✔
560
    }
1✔
561

562
    builder.set_element_counter(element_counter);
25✔
563

564
    return builder.move();
25✔
565
}
25✔
566

567
void JSONSerializer::json_to_structure_definition(const nlohmann::json& j, builder::StructuredSDFGBuilder& builder) {
2✔
568
    assert(j.contains("name"));
2✔
569
    assert(j["name"].is_string());
2✔
570
    assert(j.contains("members"));
2✔
571
    assert(j["members"].is_array());
2✔
572
    assert(j.contains("is_packed"));
2✔
573
    assert(j["is_packed"].is_boolean());
2✔
574
    auto is_packed = j["is_packed"];
2✔
575
    auto& definition = builder.add_structure(j["name"], is_packed);
2✔
576
    for (const auto& member : j["members"]) {
2✔
577
        nlohmann::json member_json;
2✔
578
        auto member_type = json_to_type(member);
2✔
579
        definition.add_member(*member_type);
2✔
580
    }
2✔
581
}
2✔
582

583
std::vector<std::pair<std::string, types::Scalar>> JSONSerializer::json_to_arguments(const nlohmann::json& j) {
×
584
    std::vector<std::pair<std::string, types::Scalar>> arguments;
×
585
    for (const auto& argument : j) {
×
586
        assert(argument.contains("name"));
×
587
        assert(argument["name"].is_string());
×
588
        assert(argument.contains("type"));
×
589
        assert(argument["type"].is_object());
×
590
        std::string name = argument["name"];
×
591
        auto type = json_to_type(argument["type"]);
×
592
        arguments.emplace_back(name, *dynamic_cast<types::Scalar*>(type.get()));
×
593
    }
×
594
    return arguments;
×
595
}
×
596

597
void JSONSerializer::json_to_dataflow(
598
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Block& parent
599
) {
42✔
600
    std::map<size_t, data_flow::DataFlowNode&> nodes_map;
42✔
601

602
    assert(j.contains("nodes"));
42✔
603
    assert(j["nodes"].is_array());
42✔
604
    for (const auto& node : j["nodes"]) {
197✔
605
        assert(node.contains("type"));
197✔
606
        assert(node["type"].is_string());
197✔
607
        assert(node.contains("element_id"));
197✔
608
        assert(node["element_id"].is_number_integer());
197✔
609
        std::string type = node["type"];
197✔
610
        if (type == "tasklet") {
197✔
611
            assert(node.contains("code"));
58✔
612
            assert(node["code"].is_number_integer());
58✔
613
            assert(node.contains("inputs"));
58✔
614
            assert(node["inputs"].is_array());
58✔
615
            assert(node.contains("output"));
58✔
616
            assert(node["output"].is_string());
58✔
617
            auto inputs = node["inputs"].get<std::vector<std::string>>();
58✔
618

619
            auto& tasklet =
58✔
620
                builder
58✔
621
                    .add_tasklet(parent, node["code"], node["output"], inputs, json_to_debug_info(node["debug_info"]));
58✔
622
            tasklet.element_id_ = node["element_id"];
58✔
623
            nodes_map.insert({node["element_id"], tasklet});
58✔
624
        } else if (type == "library_node") {
139✔
625
            assert(node.contains("code"));
8✔
626
            data_flow::LibraryNodeCode code(node["code"].get<std::string>());
8✔
627

628
            auto serializer_fn = LibraryNodeSerializerRegistry::instance().get_library_node_serializer(code.value());
8✔
629
            if (serializer_fn == nullptr) {
8✔
630
                throw std::runtime_error("Unknown library node code: " + std::string(code.value()));
×
631
            }
×
632
            auto serializer = serializer_fn();
8✔
633
            auto& lib_node = serializer->deserialize(node, builder, parent);
8✔
634
            lib_node.implementation_type() =
8✔
635
                data_flow::ImplementationType(node["implementation_type"].get<std::string>());
8✔
636
            lib_node.element_id_ = node["element_id"];
8✔
637
            nodes_map.insert({node["element_id"], lib_node});
8✔
638
        } else if (type == "access_node") {
131✔
639
            assert(node.contains("data"));
131✔
640
            auto& access_node = builder.add_access(parent, node["data"], json_to_debug_info(node["debug_info"]));
131✔
641
            access_node.element_id_ = node["element_id"];
131✔
642
            nodes_map.insert({node["element_id"], access_node});
131✔
643
        } else if (type == "constant_node") {
131✔
644
            assert(node.contains("data"));
×
645
            assert(node.contains("data_type"));
×
646

647
            auto type = json_to_type(node["data_type"]);
×
648

649
            auto& constant_node =
×
650
                builder.add_constant(parent, node["data"], *type, json_to_debug_info(node["debug_info"]));
×
651
            constant_node.element_id_ = node["element_id"];
×
652
            nodes_map.insert({node["element_id"], constant_node});
×
653
        } else {
×
654
            throw std::runtime_error("Unknown node type");
×
655
        }
×
656
    }
197✔
657

658
    assert(j.contains("edges"));
42✔
659
    assert(j["edges"].is_array());
42✔
660
    for (const auto& edge : j["edges"]) {
176✔
661
        assert(edge.contains("src"));
176✔
662
        assert(edge["src"].is_number_integer());
176✔
663
        assert(edge.contains("dst"));
176✔
664
        assert(edge["dst"].is_number_integer());
176✔
665
        assert(edge.contains("src_conn"));
176✔
666
        assert(edge["src_conn"].is_string());
176✔
667
        assert(edge.contains("dst_conn"));
176✔
668
        assert(edge["dst_conn"].is_string());
176✔
669
        assert(edge.contains("subset"));
176✔
670
        assert(edge["subset"].is_array());
176✔
671

672
        assert(nodes_map.find(edge["src"]) != nodes_map.end());
176✔
673
        assert(nodes_map.find(edge["dst"]) != nodes_map.end());
176✔
674
        auto& source = nodes_map.at(edge["src"]);
176✔
675
        auto& target = nodes_map.at(edge["dst"]);
176✔
676

677
        auto base_type = json_to_type(edge["base_type"]);
176✔
678

679
        assert(edge.contains("subset"));
176✔
680
        assert(edge["subset"].is_array());
176✔
681
        std::vector<symbolic::Expression> subset;
176✔
682
        for (const auto& subset_ : edge["subset"]) {
176✔
683
            assert(subset_.is_string());
62✔
684
            std::string subset_str = subset_;
62✔
685
            auto expr = symbolic::parse(subset_str);
62✔
686
            subset.push_back(expr);
62✔
687
        }
62✔
688
        auto& memlet = builder.add_memlet(
176✔
689
            parent,
176✔
690
            source,
176✔
691
            edge["src_conn"],
176✔
692
            target,
176✔
693
            edge["dst_conn"],
176✔
694
            subset,
176✔
695
            *base_type,
176✔
696
            json_to_debug_info(edge["debug_info"])
176✔
697
        );
176✔
698
        memlet.element_id_ = edge["element_id"];
176✔
699
    }
176✔
700
}
42✔
701

702
void JSONSerializer::json_to_sequence(
703
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& sequence
704
) {
54✔
705
    assert(j.contains("type"));
54✔
706
    assert(j["type"].is_string());
54✔
707
    assert(j.contains("children"));
54✔
708
    assert(j["children"].is_array());
54✔
709
    assert(j.contains("transitions"));
54✔
710
    assert(j["transitions"].is_array());
54✔
711
    assert(j["transitions"].size() == j["children"].size());
54✔
712

713
    sequence.element_id_ = j["element_id"];
54✔
714
    sequence.debug_info_ = json_to_debug_info(j["debug_info"]);
54✔
715

716
    std::string type = j["type"];
54✔
717
    if (type == "sequence") {
54✔
718
        for (size_t i = 0; i < j["children"].size(); i++) {
115✔
719
            auto& child = j["children"][i];
61✔
720
            auto& transition = j["transitions"][i];
61✔
721
            assert(child.contains("type"));
61✔
722
            assert(child["type"].is_string());
61✔
723

724
            assert(transition.contains("type"));
61✔
725
            assert(transition["type"].is_string());
61✔
726
            assert(transition.contains("assignments"));
61✔
727
            assert(transition["assignments"].is_array());
61✔
728
            control_flow::Assignments assignments;
61✔
729
            for (const auto& assignment : transition["assignments"]) {
61✔
730
                assert(assignment.contains("symbol"));
2✔
731
                assert(assignment["symbol"].is_string());
2✔
732
                assert(assignment.contains("expression"));
2✔
733
                assert(assignment["expression"].is_string());
2✔
734
                auto expr = symbolic::parse(assignment["expression"].get<std::string>());
2✔
735
                assignments.insert({symbolic::symbol(assignment["symbol"]), expr});
2✔
736
            }
2✔
737

738
            if (child["type"] == "block") {
61✔
739
                json_to_block_node(child, builder, sequence, assignments);
39✔
740
            } else if (child["type"] == "for") {
39✔
741
                json_to_for_node(child, builder, sequence, assignments);
16✔
742
            } else if (child["type"] == "if_else") {
16✔
743
                json_to_if_else_node(child, builder, sequence, assignments);
×
744
            } else if (child["type"] == "while") {
6✔
UNCOV
745
                json_to_while_node(child, builder, sequence, assignments);
×
746
            } else if (child["type"] == "break") {
6✔
747
                json_to_break_node(child, builder, sequence, assignments);
1✔
748
            } else if (child["type"] == "continue") {
5✔
749
                json_to_continue_node(child, builder, sequence, assignments);
1✔
750
            } else if (child["type"] == "return") {
4✔
751
                json_to_return_node(child, builder, sequence, assignments);
×
752
            } else if (child["type"] == "map") {
4✔
753
                json_to_map_node(child, builder, sequence, assignments);
4✔
754
            } else if (child["type"] == "sequence") {
4✔
755
                auto& subseq = builder.add_sequence(sequence, assignments, json_to_debug_info(child["debug_info"]));
×
756
                json_to_sequence(child, builder, subseq);
×
757
            } else {
×
758
                throw std::runtime_error("Unknown child type");
×
759
            }
×
760

761
            sequence.at(i).second.debug_info_ = json_to_debug_info(transition["debug_info"]);
61✔
762
            sequence.at(i).second.element_id_ = transition["element_id"];
61✔
763
        }
61✔
764
    } else {
54✔
765
        throw std::runtime_error("expected sequence type");
×
766
    }
×
767
}
54✔
768

769
void JSONSerializer::json_to_block_node(
770
    const nlohmann::json& j,
771
    builder::StructuredSDFGBuilder& builder,
772
    structured_control_flow::Sequence& parent,
773
    control_flow::Assignments& assignments
774
) {
40✔
775
    assert(j.contains("type"));
40✔
776
    assert(j["type"].is_string());
40✔
777
    assert(j.contains("dataflow"));
40✔
778
    assert(j["dataflow"].is_object());
40✔
779
    auto& block = builder.add_block(parent, assignments, json_to_debug_info(j["debug_info"]));
40✔
780
    block.element_id_ = j["element_id"];
40✔
781
    assert(j["dataflow"].contains("type"));
40✔
782
    assert(j["dataflow"]["type"].is_string());
40✔
783
    std::string type = j["dataflow"]["type"];
40✔
784
    if (type == "dataflow") {
40✔
785
        json_to_dataflow(j["dataflow"], builder, block);
40✔
786
    } else {
40✔
787
        throw std::runtime_error("Unknown dataflow type");
×
788
    }
×
789
}
40✔
790

791
void JSONSerializer::json_to_for_node(
792
    const nlohmann::json& j,
793
    builder::StructuredSDFGBuilder& builder,
794
    structured_control_flow::Sequence& parent,
795
    control_flow::Assignments& assignments
796
) {
17✔
797
    assert(j.contains("type"));
17✔
798
    assert(j["type"].is_string());
17✔
799
    assert(j.contains("indvar"));
17✔
800
    assert(j["indvar"].is_string());
17✔
801
    assert(j.contains("init"));
17✔
802
    assert(j["init"].is_string());
17✔
803
    assert(j.contains("condition"));
17✔
804
    assert(j["condition"].is_string());
17✔
805
    assert(j.contains("update"));
17✔
806
    assert(j["update"].is_string());
17✔
807
    assert(j.contains("root"));
17✔
808
    assert(j["root"].is_object());
17✔
809

810
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
17✔
811
    auto init = symbolic::parse(j["init"].get<std::string>());
17✔
812
    auto update = symbolic::parse(j["update"].get<std::string>());
17✔
813

814
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
17✔
815
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
17✔
816
    if (condition.is_null()) {
17✔
817
        throw InvalidSDFGException("For loop condition is not a boolean expression");
×
818
    }
×
819

820
    auto& for_node =
17✔
821
        builder.add_for(parent, indvar, condition, init, update, assignments, json_to_debug_info(j["debug_info"]));
17✔
822
    for_node.element_id_ = j["element_id"];
17✔
823

824
    assert(j["root"].contains("type"));
17✔
825
    assert(j["root"]["type"].is_string());
17✔
826
    assert(j["root"]["type"] == "sequence");
17✔
827
    json_to_sequence(j["root"], builder, for_node.root());
17✔
828
}
17✔
829

830
void JSONSerializer::json_to_if_else_node(
831
    const nlohmann::json& j,
832
    builder::StructuredSDFGBuilder& builder,
833
    structured_control_flow::Sequence& parent,
834
    control_flow::Assignments& assignments
835
) {
1✔
836
    assert(j.contains("type"));
1✔
837
    assert(j["type"].is_string());
1✔
838
    assert(j["type"] == "if_else");
1✔
839
    assert(j.contains("branches"));
1✔
840
    assert(j["branches"].is_array());
1✔
841
    auto& if_else_node = builder.add_if_else(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
842
    if_else_node.element_id_ = j["element_id"];
1✔
843
    for (const auto& branch : j["branches"]) {
2✔
844
        assert(branch.contains("condition"));
2✔
845
        assert(branch["condition"].is_string());
2✔
846
        assert(branch.contains("root"));
2✔
847
        assert(branch["root"].is_object());
2✔
848

849
        auto condition_expr = symbolic::parse(branch["condition"].get<std::string>());
2✔
850
        symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
2✔
851
        if (condition.is_null()) {
2✔
852
            throw InvalidSDFGException("If condition is not a boolean expression");
×
853
        }
×
854
        auto& branch_node = builder.add_case(if_else_node, condition);
2✔
855
        assert(branch["root"].contains("type"));
2✔
856
        assert(branch["root"]["type"].is_string());
2✔
857
        std::string type = branch["root"]["type"];
2✔
858
        if (type == "sequence") {
2✔
859
            json_to_sequence(branch["root"], builder, branch_node);
2✔
860
        } else {
2✔
861
            throw std::runtime_error("Unknown child type");
×
862
        }
×
863
    }
2✔
864
}
1✔
865

866
void JSONSerializer::json_to_while_node(
867
    const nlohmann::json& j,
868
    builder::StructuredSDFGBuilder& builder,
869
    structured_control_flow::Sequence& parent,
870
    control_flow::Assignments& assignments
871
) {
3✔
872
    assert(j.contains("type"));
3✔
873
    assert(j["type"].is_string());
3✔
874
    assert(j["type"] == "while");
3✔
875
    assert(j.contains("root"));
3✔
876
    assert(j["root"].is_object());
3✔
877

878
    auto& while_node = builder.add_while(parent, assignments, json_to_debug_info(j["debug_info"]));
3✔
879
    while_node.element_id_ = j["element_id"];
3✔
880

881
    assert(j["root"]["type"] == "sequence");
3✔
882
    json_to_sequence(j["root"], builder, while_node.root());
3✔
883
}
3✔
884

885
void JSONSerializer::json_to_break_node(
886
    const nlohmann::json& j,
887
    builder::StructuredSDFGBuilder& builder,
888
    structured_control_flow::Sequence& parent,
889
    control_flow::Assignments& assignments
890
) {
1✔
891
    assert(j.contains("type"));
1✔
892
    assert(j["type"].is_string());
1✔
893
    assert(j["type"] == "break");
1✔
894
    auto& node = builder.add_break(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
895
    node.element_id_ = j["element_id"];
1✔
896
}
1✔
897

898
void JSONSerializer::json_to_continue_node(
899
    const nlohmann::json& j,
900
    builder::StructuredSDFGBuilder& builder,
901
    structured_control_flow::Sequence& parent,
902
    control_flow::Assignments& assignments
903
) {
1✔
904
    assert(j.contains("type"));
1✔
905
    assert(j["type"].is_string());
1✔
906
    assert(j["type"] == "continue");
1✔
907
    auto& node = builder.add_continue(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
908
    node.element_id_ = j["element_id"];
1✔
909
}
1✔
910

911
void JSONSerializer::json_to_map_node(
912
    const nlohmann::json& j,
913
    builder::StructuredSDFGBuilder& builder,
914
    structured_control_flow::Sequence& parent,
915
    control_flow::Assignments& assignments
916
) {
5✔
917
    assert(j.contains("type"));
5✔
918
    assert(j["type"].is_string());
5✔
919
    assert(j["type"] == "map");
5✔
920
    assert(j.contains("indvar"));
5✔
921
    assert(j["indvar"].is_string());
5✔
922
    assert(j.contains("init"));
5✔
923
    assert(j["init"].is_string());
5✔
924
    assert(j.contains("condition"));
5✔
925
    assert(j["condition"].is_string());
5✔
926
    assert(j.contains("update"));
5✔
927
    assert(j["update"].is_string());
5✔
928
    assert(j.contains("root"));
5✔
929
    assert(j["root"].is_object());
5✔
930
    assert(j.contains("schedule_type"));
5✔
931
    assert(j["schedule_type"].is_object());
5✔
932

933
    structured_control_flow::ScheduleType schedule_type = json_to_schedule_type(j["schedule_type"]);
5✔
934

935
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
5✔
936
    auto init = symbolic::parse(j["init"].get<std::string>());
5✔
937
    auto update = symbolic::parse(j["update"].get<std::string>());
5✔
938
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
5✔
939
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
5✔
940
    if (condition.is_null()) {
5✔
941
        throw InvalidSDFGException("Map condition is not a boolean expression");
×
942
    }
×
943

944
    auto& map_node = builder.add_map(
5✔
945
        parent, indvar, condition, init, update, schedule_type, assignments, json_to_debug_info(j["debug_info"])
5✔
946
    );
5✔
947
    map_node.element_id_ = j["element_id"];
5✔
948

949
    assert(j["root"].contains("type"));
5✔
950
    assert(j["root"]["type"].is_string());
5✔
951
    assert(j["root"]["type"] == "sequence");
5✔
952
    json_to_sequence(j["root"], builder, map_node.root());
5✔
953
}
5✔
954

955
void JSONSerializer::json_to_return_node(
956
    const nlohmann::json& j,
957
    builder::StructuredSDFGBuilder& builder,
958
    structured_control_flow::Sequence& parent,
959
    control_flow::Assignments& assignments
960
) {
1✔
961
    assert(j.contains("type"));
1✔
962
    assert(j["type"].is_string());
1✔
963
    assert(j["type"] == "return");
1✔
964

965
    std::string data = j["data"];
1✔
966
    std::unique_ptr<types::IType> data_type = nullptr;
1✔
967
    if (j.contains("data_type")) {
1✔
968
        data_type = json_to_type(j["data_type"]);
×
969
    }
×
970

971
    if (data_type == nullptr) {
1✔
972
        auto& node = builder.add_return(parent, data, assignments, json_to_debug_info(j["debug_info"]));
1✔
973
        node.element_id_ = j["element_id"];
1✔
974
    } else {
1✔
975
        auto& node =
×
976
            builder.add_constant_return(parent, data, *data_type, assignments, json_to_debug_info(j["debug_info"]));
×
977
        node.element_id_ = j["element_id"];
×
978
    }
×
979
}
1✔
980

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

1107
DebugInfo JSONSerializer::json_to_debug_info(const nlohmann::json& j) {
557✔
1108
    assert(j.contains("has"));
557✔
1109
    assert(j["has"].is_boolean());
557✔
1110
    if (!j["has"]) {
557✔
1111
        return DebugInfo();
553✔
1112
    }
553✔
1113
    assert(j.contains("filename"));
557✔
1114
    assert(j["filename"].is_string());
4✔
1115
    std::string filename = j["filename"];
4✔
1116
    assert(j.contains("function"));
4✔
1117
    assert(j["function"].is_string());
4✔
1118
    std::string function = j["function"];
4✔
1119
    assert(j.contains("start_line"));
4✔
1120
    assert(j["start_line"].is_number_integer());
4✔
1121
    size_t start_line = j["start_line"];
4✔
1122
    assert(j.contains("start_column"));
4✔
1123
    assert(j["start_column"].is_number_integer());
4✔
1124
    size_t start_column = j["start_column"];
4✔
1125
    assert(j.contains("end_line"));
4✔
1126
    assert(j["end_line"].is_number_integer());
4✔
1127
    size_t end_line = j["end_line"];
4✔
1128
    assert(j.contains("end_column"));
4✔
1129
    assert(j["end_column"].is_number_integer());
4✔
1130
    size_t end_column = j["end_column"];
4✔
1131
    return DebugInfo(filename, function, start_line, start_column, end_line, end_column);
4✔
1132
}
4✔
1133

1134
ScheduleType JSONSerializer::json_to_schedule_type(const nlohmann::json& j) {
6✔
1135
    assert(j.contains("value"));
6✔
1136
    assert(j["value"].is_string());
6✔
1137
    // assert(j.contains("category"));
1138
    // assert(j["category"].is_number_integer());
1139
    assert(j.contains("properties"));
6✔
1140
    assert(j["properties"].is_object());
6✔
1141
    ScheduleTypeCategory category = ScheduleTypeCategory::None;
6✔
1142
    if (j.contains("category")) {
6✔
1143
        category = static_cast<ScheduleTypeCategory>(j["category"].get<int>());
6✔
1144
    }
6✔
1145
    ScheduleType schedule_type(j["value"].get<std::string>(), category);
6✔
1146
    for (const auto& [key, value] : j["properties"].items()) {
6✔
1147
        assert(value.is_string());
3✔
1148
        schedule_type.set_property(key, value.get<std::string>());
3✔
1149
    }
3✔
1150
    return schedule_type;
6✔
1151
}
6✔
1152

1153
types::StorageType JSONSerializer::json_to_storage_type(const nlohmann::json& j) {
480✔
1154
    if (!j.contains("value")) {
480✔
1155
        return types::StorageType::CPU_Stack();
×
1156
    }
×
1157
    std::string value = j["value"].get<std::string>();
480✔
1158

1159
    symbolic::Expression allocation_size = SymEngine::null;
480✔
1160
    if (j.contains("allocation_size")) {
480✔
UNCOV
1161
        allocation_size = symbolic::parse(j["allocation_size"].get<std::string>());
×
UNCOV
1162
    }
×
1163

1164
    types::StorageType::AllocationType allocation = j["allocation"];
480✔
1165
    types::StorageType::AllocationType deallocation = j["deallocation"];
480✔
1166

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

1169
    if (j.contains("args")) {
480✔
1170
        nlohmann::json::array_t args = j["args"];
×
1171
        if (args.size() > 0) {
×
1172
            storageType.arg1(symbolic::parse(args[0].get<std::string>()));
×
1173
        }
×
1174
    }
×
1175
    return storageType;
480✔
1176
}
480✔
1177

1178
std::string JSONSerializer::expression(const symbolic::Expression expr) {
279✔
1179
    JSONSymbolicPrinter printer;
279✔
1180
    return printer.apply(expr);
279✔
1181
};
279✔
1182

1183
void JSONSerializer::writeToFile(const StructuredSDFG& sdfg, const std::filesystem::path& file) {
×
1184
    JSONSerializer ser;
×
1185
    auto json = ser.serialize(sdfg);
×
1186

1187
    auto parent_path = file.parent_path();
×
1188
    if (!parent_path.empty()) {
×
1189
        std::filesystem::create_directories(file.parent_path());
×
1190
    }
×
1191

1192
    std::ofstream out(file, std::ofstream::out);
×
1193
    if (!out.is_open()) {
×
1194
        std::cerr << "Could not open file " << file << " for writing JSON output." << std::endl;
×
1195
    }
×
1196
    out << json << std::endl;
×
1197
    out.close();
×
1198
}
×
1199

1200
void JSONSymbolicPrinter::bvisit(const SymEngine::Equality& x) {
×
1201
    str_ = apply(x.get_args()[0]) + " == " + apply(x.get_args()[1]);
×
1202
    str_ = parenthesize(str_);
×
1203
};
×
1204

1205
void JSONSymbolicPrinter::bvisit(const SymEngine::Unequality& x) {
×
1206
    str_ = apply(x.get_args()[0]) + " != " + apply(x.get_args()[1]);
×
1207
    str_ = parenthesize(str_);
×
1208
};
×
1209

1210
void JSONSymbolicPrinter::bvisit(const SymEngine::LessThan& x) {
2✔
1211
    str_ = apply(x.get_args()[0]) + " <= " + apply(x.get_args()[1]);
2✔
1212
    str_ = parenthesize(str_);
2✔
1213
};
2✔
1214

1215
void JSONSymbolicPrinter::bvisit(const SymEngine::StrictLessThan& x) {
22✔
1216
    str_ = apply(x.get_args()[0]) + " < " + apply(x.get_args()[1]);
22✔
1217
    str_ = parenthesize(str_);
22✔
1218
};
22✔
1219

1220
void JSONSymbolicPrinter::bvisit(const SymEngine::Min& x) {
×
1221
    std::ostringstream s;
×
1222
    auto container = x.get_args();
×
1223
    if (container.size() == 1) {
×
1224
        s << apply(*container.begin());
×
1225
    } else {
×
1226
        s << "min(";
×
1227
        s << apply(*container.begin());
×
1228

1229
        // Recursively apply __daisy_min to the arguments
1230
        SymEngine::vec_basic subargs;
×
1231
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1232
            subargs.push_back(*it);
×
1233
        }
×
1234
        auto submin = SymEngine::min(subargs);
×
1235
        s << ", " << apply(submin);
×
1236

1237
        s << ")";
×
1238
    }
×
1239

1240
    str_ = s.str();
×
1241
};
×
1242

1243
void JSONSymbolicPrinter::bvisit(const SymEngine::Max& x) {
×
1244
    std::ostringstream s;
×
1245
    auto container = x.get_args();
×
1246
    if (container.size() == 1) {
×
1247
        s << apply(*container.begin());
×
1248
    } else {
×
1249
        s << "max(";
×
1250
        s << apply(*container.begin());
×
1251

1252
        // Recursively apply __daisy_max to the arguments
1253
        SymEngine::vec_basic subargs;
×
1254
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1255
            subargs.push_back(*it);
×
1256
        }
×
1257
        auto submax = SymEngine::max(subargs);
×
1258
        s << ", " << apply(submax);
×
1259

1260
        s << ")";
×
1261
    }
×
1262

1263
    str_ = s.str();
×
1264
};
×
1265

1266
void LibraryNodeSerializerRegistry::
1267
    register_library_node_serializer(std::string library_node_code, LibraryNodeSerializerFn fn) {
160✔
1268
    std::lock_guard<std::mutex> lock(mutex_);
160✔
1269
    if (factory_map_.find(library_node_code) != factory_map_.end()) {
160✔
1270
        return;
×
1271
    }
×
1272
    factory_map_[library_node_code] = std::move(fn);
160✔
1273
}
160✔
1274

1275
LibraryNodeSerializerFn LibraryNodeSerializerRegistry::get_library_node_serializer(std::string library_node_code) {
17✔
1276
    auto it = factory_map_.find(library_node_code);
17✔
1277
    if (it != factory_map_.end()) {
17✔
1278
        return it->second;
17✔
1279
    }
17✔
1280
    return nullptr;
×
1281
}
17✔
1282

1283
size_t LibraryNodeSerializerRegistry::size() const { return factory_map_.size(); }
×
1284

1285
void register_default_serializers() {
3✔
1286
    // stdlib
1287
    LibraryNodeSerializerRegistry::instance()
3✔
1288
        .register_library_node_serializer(stdlib::LibraryNodeType_Alloca.value(), []() {
3✔
1289
            return std::make_unique<stdlib::AllocaNodeSerializer>();
×
1290
        });
×
1291
    LibraryNodeSerializerRegistry::instance()
3✔
1292
        .register_library_node_serializer(stdlib::LibraryNodeType_Assert.value(), []() {
3✔
1293
            return std::make_unique<stdlib::AssertNodeSerializer>();
×
1294
        });
×
1295
    LibraryNodeSerializerRegistry::instance()
3✔
1296
        .register_library_node_serializer(stdlib::LibraryNodeType_Calloc.value(), []() {
3✔
1297
            return std::make_unique<stdlib::CallocNodeSerializer>();
×
1298
        });
×
1299
    LibraryNodeSerializerRegistry::instance()
3✔
1300
        .register_library_node_serializer(stdlib::LibraryNodeType_Free.value(), []() {
3✔
1301
            return std::make_unique<stdlib::FreeNodeSerializer>();
×
1302
        });
×
1303
    LibraryNodeSerializerRegistry::instance()
3✔
1304
        .register_library_node_serializer(stdlib::LibraryNodeType_Malloc.value(), []() {
3✔
1305
            return std::make_unique<stdlib::MallocNodeSerializer>();
×
1306
        });
×
1307
    LibraryNodeSerializerRegistry::instance()
3✔
1308
        .register_library_node_serializer(stdlib::LibraryNodeType_Memcpy.value(), []() {
3✔
1309
            return std::make_unique<stdlib::MemcpyNodeSerializer>();
×
1310
        });
×
1311
    LibraryNodeSerializerRegistry::instance()
3✔
1312
        .register_library_node_serializer(stdlib::LibraryNodeType_Memmove.value(), []() {
3✔
1313
            return std::make_unique<stdlib::MemmoveNodeSerializer>();
×
1314
        });
×
1315
    LibraryNodeSerializerRegistry::instance()
3✔
1316
        .register_library_node_serializer(stdlib::LibraryNodeType_Memset.value(), []() {
3✔
1317
            return std::make_unique<stdlib::MemsetNodeSerializer>();
×
1318
        });
×
1319
    LibraryNodeSerializerRegistry::instance()
3✔
1320
        .register_library_node_serializer(stdlib::LibraryNodeType_Trap.value(), []() {
3✔
1321
            return std::make_unique<stdlib::TrapNodeSerializer>();
×
1322
        });
×
1323
    LibraryNodeSerializerRegistry::instance()
3✔
1324
        .register_library_node_serializer(stdlib::LibraryNodeType_Unreachable.value(), []() {
3✔
1325
            return std::make_unique<stdlib::UnreachableNodeSerializer>();
×
1326
        });
×
1327

1328
    // Metadata
1329
    LibraryNodeSerializerRegistry::instance()
3✔
1330
        .register_library_node_serializer(data_flow::LibraryNodeType_Metadata.value(), []() {
3✔
1331
            return std::make_unique<data_flow::MetadataNodeSerializer>();
×
1332
        });
×
1333

1334
    // Barrier
1335
    LibraryNodeSerializerRegistry::instance()
3✔
1336
        .register_library_node_serializer(data_flow::LibraryNodeType_BarrierLocal.value(), []() {
3✔
1337
            return std::make_unique<data_flow::BarrierLocalNodeSerializer>();
1✔
1338
        });
1✔
1339

1340
    // Call Node
1341
    LibraryNodeSerializerRegistry::instance()
3✔
1342
        .register_library_node_serializer(data_flow::LibraryNodeType_Call.value(), []() {
6✔
1343
            return std::make_unique<data_flow::CallNodeSerializer>();
6✔
1344
        });
6✔
1345
    LibraryNodeSerializerRegistry::instance()
3✔
1346
        .register_library_node_serializer(data_flow::LibraryNodeType_Invoke.value(), []() {
3✔
1347
            return std::make_unique<data_flow::InvokeNodeSerializer>();
×
1348
        });
×
1349

1350
    // LoadConst
1351
    LibraryNodeSerializerRegistry::instance()
3✔
1352
        .register_library_node_serializer(data_flow::LibraryNodeType_LoadConst.value(), []() {
3✔
1353
            return std::make_unique<data_flow::LoadConstNodeSerializer>();
2✔
1354
        });
2✔
1355

1356
    // CMath
1357
    LibraryNodeSerializerRegistry::instance()
3✔
1358
        .register_library_node_serializer(math::cmath::LibraryNodeType_CMath.value(), []() {
3✔
1359
            return std::make_unique<math::cmath::CMathNodeSerializer>();
×
1360
        });
×
1361
    // Backward compatibility
1362
    LibraryNodeSerializerRegistry::instance()
3✔
1363
        .register_library_node_serializer(math::cmath::LibraryNodeType_CMath_Deprecated.value(), []() {
3✔
1364
            return std::make_unique<math::cmath::CMathNodeSerializer>();
×
1365
        });
×
1366

1367
    // BLAS
1368
    LibraryNodeSerializerRegistry::instance()
3✔
1369
        .register_library_node_serializer(math::blas::LibraryNodeType_DOT.value(), []() {
3✔
1370
            return std::make_unique<math::blas::DotNodeSerializer>();
×
1371
        });
×
1372
    LibraryNodeSerializerRegistry::instance()
3✔
1373
        .register_library_node_serializer(math::blas::LibraryNodeType_GEMM.value(), []() {
3✔
1374
            return std::make_unique<math::blas::GEMMNodeSerializer>();
×
1375
        });
×
1376

1377
    // Tensor
1378

1379
    LibraryNodeSerializerRegistry::instance()
3✔
1380
        .register_library_node_serializer(math::tensor::LibraryNodeType_Broadcast.value(), []() {
3✔
1381
            return std::make_unique<math::tensor::BroadcastNodeSerializer>();
×
1382
        });
×
1383
    LibraryNodeSerializerRegistry::instance()
3✔
1384
        .register_library_node_serializer(math::tensor::LibraryNodeType_Conv.value(), []() {
3✔
1385
            return std::make_unique<math::tensor::ConvNodeSerializer>();
×
1386
        });
×
1387
    LibraryNodeSerializerRegistry::instance()
3✔
1388
        .register_library_node_serializer(math::tensor::LibraryNodeType_Pooling.value(), []() {
3✔
1389
            return std::make_unique<math::tensor::PoolingNodeSerializer>();
×
1390
        });
×
1391
    LibraryNodeSerializerRegistry::instance()
3✔
1392
        .register_library_node_serializer(math::tensor::LibraryNodeType_Transpose.value(), []() {
3✔
1393
            return std::make_unique<math::tensor::TransposeNodeSerializer>();
×
1394
        });
×
1395
    LibraryNodeSerializerRegistry::instance()
3✔
1396
        .register_library_node_serializer(math::tensor::LibraryNodeType_MatMul.value(), []() {
3✔
1397
            return std::make_unique<math::tensor::MatMulNodeSerializer>();
×
1398
        });
×
1399

1400
    // Elementwise
1401
    LibraryNodeSerializerRegistry::instance()
3✔
1402
        .register_library_node_serializer(math::tensor::LibraryNodeType_Abs.value(), []() {
3✔
1403
            return std::make_unique<math::tensor::AbsNodeSerializer>();
×
1404
        });
×
1405
    LibraryNodeSerializerRegistry::instance()
3✔
1406
        .register_library_node_serializer(math::tensor::LibraryNodeType_Add.value(), []() {
3✔
1407
            return std::make_unique<math::tensor::AddNodeSerializer>();
×
1408
        });
×
1409
    LibraryNodeSerializerRegistry::instance()
3✔
1410
        .register_library_node_serializer(math::tensor::LibraryNodeType_Div.value(), []() {
3✔
1411
            return std::make_unique<math::tensor::DivNodeSerializer>();
×
1412
        });
×
1413
    LibraryNodeSerializerRegistry::instance()
3✔
1414
        .register_library_node_serializer(math::tensor::LibraryNodeType_Elu.value(), []() {
3✔
1415
            return std::make_unique<math::tensor::EluNodeSerializer>();
×
1416
        });
×
1417
    LibraryNodeSerializerRegistry::instance()
3✔
1418
        .register_library_node_serializer(math::tensor::LibraryNodeType_Exp.value(), []() {
3✔
1419
            return std::make_unique<math::tensor::ExpNodeSerializer>();
×
1420
        });
×
1421
    LibraryNodeSerializerRegistry::instance()
3✔
1422
        .register_library_node_serializer(math::tensor::LibraryNodeType_Erf.value(), []() {
3✔
1423
            return std::make_unique<math::tensor::ErfNodeSerializer>();
×
1424
        });
×
1425
    LibraryNodeSerializerRegistry::instance()
3✔
1426
        .register_library_node_serializer(math::tensor::LibraryNodeType_HardSigmoid.value(), []() {
3✔
1427
            return std::make_unique<math::tensor::HardSigmoidNodeSerializer>();
×
1428
        });
×
1429
    LibraryNodeSerializerRegistry::instance()
3✔
1430
        .register_library_node_serializer(math::tensor::LibraryNodeType_LeakyReLU.value(), []() {
3✔
1431
            return std::make_unique<math::tensor::LeakyReLUNodeSerializer>();
×
1432
        });
×
1433
    LibraryNodeSerializerRegistry::instance()
3✔
1434
        .register_library_node_serializer(math::tensor::LibraryNodeType_Mul.value(), []() {
3✔
1435
            return std::make_unique<math::tensor::MulNodeSerializer>();
×
1436
        });
×
1437
    LibraryNodeSerializerRegistry::instance()
3✔
1438
        .register_library_node_serializer(math::tensor::LibraryNodeType_Pow.value(), []() {
3✔
1439
            return std::make_unique<math::tensor::PowNodeSerializer>();
×
1440
        });
×
1441
    LibraryNodeSerializerRegistry::instance()
3✔
1442
        .register_library_node_serializer(math::tensor::LibraryNodeType_ReLU.value(), []() {
3✔
1443
            return std::make_unique<math::tensor::ReLUNodeSerializer>();
×
1444
        });
×
1445
    LibraryNodeSerializerRegistry::instance()
3✔
1446
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sigmoid.value(), []() {
3✔
1447
            return std::make_unique<math::tensor::SigmoidNodeSerializer>();
×
1448
        });
×
1449
    LibraryNodeSerializerRegistry::instance()
3✔
1450
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sqrt.value(), []() {
3✔
1451
            return std::make_unique<math::tensor::SqrtNodeSerializer>();
×
1452
        });
×
1453
    LibraryNodeSerializerRegistry::instance()
3✔
1454
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sub.value(), []() {
3✔
1455
            return std::make_unique<math::tensor::SubNodeSerializer>();
×
1456
        });
×
1457
    LibraryNodeSerializerRegistry::instance()
3✔
1458
        .register_library_node_serializer(math::tensor::LibraryNodeType_Tanh.value(), []() {
3✔
1459
            return std::make_unique<math::tensor::TanhNodeSerializer>();
×
1460
        });
×
1461
    LibraryNodeSerializerRegistry::instance()
3✔
1462
        .register_library_node_serializer(math::tensor::LibraryNodeType_Minimum.value(), []() {
3✔
1463
            return std::make_unique<math::tensor::MinimumNodeSerializer>();
×
1464
        });
×
1465
    LibraryNodeSerializerRegistry::instance()
3✔
1466
        .register_library_node_serializer(math::tensor::LibraryNodeType_Maximum.value(), []() {
3✔
1467
            return std::make_unique<math::tensor::MaximumNodeSerializer>();
×
1468
        });
×
1469
    LibraryNodeSerializerRegistry::instance()
3✔
1470
        .register_library_node_serializer(math::tensor::LibraryNodeType_Fill.value(), []() {
3✔
1471
            return std::make_unique<math::tensor::FillNodeSerializer>();
×
1472
        });
×
1473
    LibraryNodeSerializerRegistry::instance()
3✔
1474
        .register_library_node_serializer(math::tensor::LibraryNodeType_TensorTasklet.value(), []() {
3✔
1475
            return std::make_unique<math::tensor::TaskletTensorNodeSerializer>();
×
1476
        });
×
1477
    LibraryNodeSerializerRegistry::instance()
3✔
1478
        .register_library_node_serializer(math::tensor::LibraryNodeType_TensorCMath.value(), []() {
3✔
1479
            return std::make_unique<math::tensor::CMathTensorNodeSerializer>();
×
1480
        });
×
1481
    LibraryNodeSerializerRegistry::instance()
3✔
1482
        .register_library_node_serializer(math::tensor::LibraryNodeType_Cast.value(), []() {
3✔
1483
            return std::make_unique<math::tensor::CastNodeSerializer>();
×
1484
        });
×
1485

1486
    LibraryNodeSerializerRegistry::instance()
3✔
1487
        .register_library_node_serializer(math::tensor::LibraryNodeType_BatchNorm.value(), [] {
3✔
1488
            return std::make_unique<math::tensor::BatchNormNodeSerializer>();
×
1489
        });
×
1490

1491
    // Reduce
1492
    LibraryNodeSerializerRegistry::instance()
3✔
1493
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sum.value(), []() {
3✔
1494
            return std::make_unique<math::tensor::SumNodeSerializer>();
×
1495
        });
×
1496
    LibraryNodeSerializerRegistry::instance()
3✔
1497
        .register_library_node_serializer(math::tensor::LibraryNodeType_Max.value(), []() {
3✔
1498
            return std::make_unique<math::tensor::MaxNodeSerializer>();
×
1499
        });
×
1500
    LibraryNodeSerializerRegistry::instance()
3✔
1501
        .register_library_node_serializer(math::tensor::LibraryNodeType_Min.value(), []() {
3✔
1502
            return std::make_unique<math::tensor::MinNodeSerializer>();
×
1503
        });
×
1504
    LibraryNodeSerializerRegistry::instance()
3✔
1505
        .register_library_node_serializer(math::tensor::LibraryNodeType_Softmax.value(), []() {
3✔
1506
            return std::make_unique<math::tensor::SoftmaxNodeSerializer>();
×
1507
        });
×
1508
    LibraryNodeSerializerRegistry::instance()
3✔
1509
        .register_library_node_serializer(math::tensor::LibraryNodeType_Mean.value(), []() {
3✔
1510
            return std::make_unique<math::tensor::MeanNodeSerializer>();
×
1511
        });
×
1512
    LibraryNodeSerializerRegistry::instance()
3✔
1513
        .register_library_node_serializer(math::tensor::LibraryNodeType_Std.value(), []() {
3✔
1514
            return std::make_unique<math::tensor::StdNodeSerializer>();
×
1515
        });
×
1516

1517
    // Einsum
1518
    LibraryNodeSerializerRegistry::instance()
3✔
1519
        .register_library_node_serializer(einsum::LibraryNodeType_Einsum.value(), []() {
3✔
1520
            return std::make_unique<einsum::EinsumSerializer>();
×
1521
        });
×
1522
}
3✔
1523

1524
} // namespace serializer
1525
} // 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