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

daisytuner / docc / 22358227628

24 Feb 2026 03:43PM UTC coverage: 64.545% (-0.03%) from 64.577%
22358227628

Pull #542

github

web-flow
Merge 57f720ccb into b1c26c8f1
Pull Request #542: [MLIR] Added TaskletTensorNode & Map linalg.add to it

127 of 260 new or added lines in 2 files covered. (48.85%)

23828 of 36917 relevant lines covered (64.54%)

376.84 hits per line

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

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

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

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

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

36
namespace sdfg {
37
namespace serializer {
38

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

46
    return FunctionType(str);
×
47
}
27✔
48

49
/*
50
 * * JSONSerializer class
51
 * * Serialization logic
52
 */
53

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

61
    j["name"] = sdfg.name();
26✔
62
    j["element_counter"] = sdfg.element_counter();
26✔
63
    j["type"] = std::string(sdfg.type().value());
26✔
64

65
    nlohmann::json return_type_json;
26✔
66
    type_to_json(return_type_json, sdfg.return_type());
26✔
67
    j["return_type"] = return_type_json;
26✔
68

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

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

84
    j["arguments"] = nlohmann::json::array();
26✔
85
    for (const auto& argument : sdfg.arguments()) {
30✔
86
        j["arguments"].push_back(argument);
30✔
87
    }
30✔
88

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

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

102
    // Walk the SDFG
103
    nlohmann::json root_json;
26✔
104
    sequence_to_json(root_json, sdfg.root());
26✔
105
    j["root"] = root_json;
26✔
106

107
    return j;
26✔
108
}
26✔
109

110
void JSONSerializer::dataflow_to_json(nlohmann::json& j, const data_flow::DataFlowGraph& dataflow) {
57✔
111
    j["type"] = "dataflow";
57✔
112
    j["nodes"] = nlohmann::json::array();
57✔
113
    j["edges"] = nlohmann::json::array();
57✔
114

115
    for (auto& node : dataflow.nodes()) {
217✔
116
        nlohmann::json node_json;
217✔
117
        node_json["element_id"] = node.element_id();
217✔
118

119
        node_json["debug_info"] = nlohmann::json::object();
217✔
120
        debug_info_to_json(node_json["debug_info"], node.debug_info());
217✔
121

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

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

155
        j["nodes"].push_back(node_json);
217✔
156
    }
217✔
157

158
    for (auto& edge : dataflow.edges()) {
190✔
159
        nlohmann::json edge_json;
190✔
160
        edge_json["element_id"] = edge.element_id();
190✔
161

162
        edge_json["debug_info"] = nlohmann::json::object();
190✔
163
        debug_info_to_json(edge_json["debug_info"], edge.debug_info());
190✔
164

165
        edge_json["src"] = edge.src().element_id();
190✔
166
        edge_json["dst"] = edge.dst().element_id();
190✔
167

168
        edge_json["src_conn"] = edge.src_conn();
190✔
169
        edge_json["dst_conn"] = edge.dst_conn();
190✔
170

171
        edge_json["subset"] = nlohmann::json::array();
190✔
172
        for (auto& subset : edge.subset()) {
190✔
173
            edge_json["subset"].push_back(expression(subset));
72✔
174
        }
72✔
175

176
        nlohmann::json base_type_json;
190✔
177
        type_to_json(base_type_json, edge.base_type());
190✔
178
        edge_json["base_type"] = base_type_json;
190✔
179

180
        j["edges"].push_back(edge_json);
190✔
181
    }
190✔
182
}
57✔
183

184
void JSONSerializer::block_to_json(nlohmann::json& j, const structured_control_flow::Block& block) {
55✔
185
    j["type"] = "block";
55✔
186
    j["element_id"] = block.element_id();
55✔
187

188
    j["debug_info"] = nlohmann::json::object();
55✔
189
    debug_info_to_json(j["debug_info"], block.debug_info());
55✔
190

191
    nlohmann::json dataflow_json;
55✔
192
    dataflow_to_json(dataflow_json, block.dataflow());
55✔
193
    j["dataflow"] = dataflow_json;
55✔
194
}
55✔
195

196
void JSONSerializer::for_to_json(nlohmann::json& j, const structured_control_flow::For& for_node) {
18✔
197
    j["type"] = "for";
18✔
198
    j["element_id"] = for_node.element_id();
18✔
199

200
    j["debug_info"] = nlohmann::json::object();
18✔
201
    debug_info_to_json(j["debug_info"], for_node.debug_info());
18✔
202

203
    j["indvar"] = expression(for_node.indvar());
18✔
204
    j["init"] = expression(for_node.init());
18✔
205
    j["condition"] = expression(for_node.condition());
18✔
206
    j["update"] = expression(for_node.update());
18✔
207

208
    nlohmann::json body_json;
18✔
209
    sequence_to_json(body_json, for_node.root());
18✔
210
    j["root"] = body_json;
18✔
211
}
18✔
212

213
void JSONSerializer::if_else_to_json(nlohmann::json& j, const structured_control_flow::IfElse& if_else_node) {
2✔
214
    j["type"] = "if_else";
2✔
215
    j["element_id"] = if_else_node.element_id();
2✔
216

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

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

231
void JSONSerializer::while_node_to_json(nlohmann::json& j, const structured_control_flow::While& while_node) {
6✔
232
    j["type"] = "while";
6✔
233
    j["element_id"] = while_node.element_id();
6✔
234

235
    j["debug_info"] = nlohmann::json::object();
6✔
236
    debug_info_to_json(j["debug_info"], while_node.debug_info());
6✔
237

238
    nlohmann::json body_json;
6✔
239
    sequence_to_json(body_json, while_node.root());
6✔
240
    j["root"] = body_json;
6✔
241
}
6✔
242

243
void JSONSerializer::break_node_to_json(nlohmann::json& j, const structured_control_flow::Break& break_node) {
2✔
244
    j["type"] = "break";
2✔
245
    j["element_id"] = break_node.element_id();
2✔
246

247
    j["debug_info"] = nlohmann::json::object();
2✔
248
    debug_info_to_json(j["debug_info"], break_node.debug_info());
2✔
249
}
2✔
250

251
void JSONSerializer::continue_node_to_json(nlohmann::json& j, const structured_control_flow::Continue& continue_node) {
2✔
252
    j["type"] = "continue";
2✔
253
    j["element_id"] = continue_node.element_id();
2✔
254

255
    j["debug_info"] = nlohmann::json::object();
2✔
256
    debug_info_to_json(j["debug_info"], continue_node.debug_info());
2✔
257
}
2✔
258

259
void JSONSerializer::map_to_json(nlohmann::json& j, const structured_control_flow::Map& map_node) {
10✔
260
    j["type"] = "map";
10✔
261
    j["element_id"] = map_node.element_id();
10✔
262

263
    j["debug_info"] = nlohmann::json::object();
10✔
264
    debug_info_to_json(j["debug_info"], map_node.debug_info());
10✔
265

266
    j["indvar"] = expression(map_node.indvar());
10✔
267
    j["init"] = expression(map_node.init());
10✔
268
    j["condition"] = expression(map_node.condition());
10✔
269
    j["update"] = expression(map_node.update());
10✔
270

271
    j["schedule_type"] = nlohmann::json::object();
10✔
272
    schedule_type_to_json(j["schedule_type"], map_node.schedule_type());
10✔
273

274
    nlohmann::json body_json;
10✔
275
    sequence_to_json(body_json, map_node.root());
10✔
276
    j["root"] = body_json;
10✔
277
}
10✔
278

279
void JSONSerializer::return_node_to_json(nlohmann::json& j, const structured_control_flow::Return& return_node) {
2✔
280
    j["type"] = "return";
2✔
281
    j["element_id"] = return_node.element_id();
2✔
282
    j["data"] = return_node.data();
2✔
283

284
    if (return_node.is_constant()) {
2✔
285
        nlohmann::json type_json;
×
286
        type_to_json(type_json, return_node.type());
×
287
        j["data_type"] = type_json;
×
288
    }
×
289

290
    j["debug_info"] = nlohmann::json::object();
2✔
291
    debug_info_to_json(j["debug_info"], return_node.debug_info());
2✔
292
}
2✔
293

294
void JSONSerializer::sequence_to_json(nlohmann::json& j, const structured_control_flow::Sequence& sequence) {
68✔
295
    j["type"] = "sequence";
68✔
296
    j["element_id"] = sequence.element_id();
68✔
297

298
    j["debug_info"] = nlohmann::json::object();
68✔
299
    debug_info_to_json(j["debug_info"], sequence.debug_info());
68✔
300

301
    j["children"] = nlohmann::json::array();
68✔
302
    j["transitions"] = nlohmann::json::array();
68✔
303

304
    for (size_t i = 0; i < sequence.size(); i++) {
150✔
305
        nlohmann::json child_json;
82✔
306
        auto& child = sequence.at(i).first;
82✔
307
        auto& transition = sequence.at(i).second;
82✔
308

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

331
        j["children"].push_back(child_json);
82✔
332

333
        // Add transition information
334
        nlohmann::json transition_json;
82✔
335
        transition_json["type"] = "transition";
82✔
336
        transition_json["element_id"] = transition.element_id();
82✔
337

338
        transition_json["debug_info"] = nlohmann::json::object();
82✔
339
        debug_info_to_json(transition_json["debug_info"], transition.debug_info());
82✔
340

341
        transition_json["assignments"] = nlohmann::json::array();
82✔
342
        for (const auto& assignment : transition.assignments()) {
82✔
343
            nlohmann::json assignment_json;
3✔
344
            assignment_json["symbol"] = expression(assignment.first);
3✔
345
            assignment_json["expression"] = expression(assignment.second);
3✔
346
            transition_json["assignments"].push_back(assignment_json);
3✔
347
        }
3✔
348

349
        j["transitions"].push_back(transition_json);
82✔
350
    }
82✔
351
}
68✔
352

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

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

444
void JSONSerializer::debug_info_to_json(nlohmann::json& j, const DebugInfo& debug_info) {
654✔
445
    j["has"] = debug_info.has();
654✔
446
    j["filename"] = debug_info.filename();
654✔
447
    j["function"] = debug_info.function();
654✔
448
    j["start_line"] = debug_info.start_line();
654✔
449
    j["start_column"] = debug_info.start_column();
654✔
450
    j["end_line"] = debug_info.end_line();
654✔
451
    j["end_column"] = debug_info.end_column();
654✔
452
}
654✔
453

454

455
void JSONSerializer::schedule_type_to_json(nlohmann::json& j, const ScheduleType& schedule_type) {
12✔
456
    j["value"] = schedule_type.value();
12✔
457
    j["category"] = static_cast<int>(schedule_type.category());
12✔
458
    j["properties"] = nlohmann::json::object();
12✔
459
    for (const auto& prop : schedule_type.properties()) {
12✔
460
        j["properties"][prop.first] = prop.second;
12✔
461
    }
12✔
462
}
12✔
463

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

479

480
/*
481
 * * Deserialization logic
482
 */
483

484
std::unique_ptr<StructuredSDFG> JSONSerializer::deserialize(nlohmann::json& j) {
27✔
485
    assert(j.contains("name"));
27✔
486
    assert(j["name"].is_string());
27✔
487
    assert(j.contains("type"));
27✔
488
    assert(j["type"].is_string());
27✔
489
    assert(j.contains("element_counter"));
27✔
490
    assert(j["element_counter"].is_number_integer());
27✔
491

492
    std::unique_ptr<types::IType> return_type;
27✔
493
    if (j.contains("return_type")) {
27✔
494
        return_type = json_to_type(j["return_type"]);
27✔
495
    } else {
27✔
496
        return_type = std::make_unique<types::Scalar>(types::PrimitiveType::Void);
×
497
    }
×
498

499
    FunctionType function_type = function_type_from_string(j["type"].get<std::string>());
27✔
500
    builder::StructuredSDFGBuilder builder(j["name"], function_type, *return_type);
27✔
501

502
    size_t element_counter = j["element_counter"];
27✔
503
    builder.set_element_counter(element_counter);
27✔
504

505
    // deserialize structures
506
    assert(j.contains("structures"));
27✔
507
    assert(j["structures"].is_array());
27✔
508
    for (const auto& structure : j["structures"]) {
27✔
509
        assert(structure.contains("name"));
1✔
510
        assert(structure["name"].is_string());
1✔
511
        json_to_structure_definition(structure, builder);
1✔
512
    }
1✔
513

514
    nlohmann::json& containers = j["containers"];
27✔
515

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

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

534
    // deserialize transients
535
    for (const auto& entry : containers.items()) {
153✔
536
        if (builder.subject().is_argument(entry.key())) {
153✔
537
            continue;
33✔
538
        }
33✔
539
        if (builder.subject().is_external(entry.key())) {
120✔
540
            continue;
7✔
541
        }
7✔
542
        auto type = json_to_type(entry.value());
113✔
543
        builder.add_container(entry.key(), *type, false, false);
113✔
544
    }
113✔
545

546
    // deserialize root node
547
    assert(j.contains("root"));
27✔
548
    auto& root = builder.subject().root();
27✔
549
    json_to_sequence(j["root"], builder, root);
27✔
550

551
    // deserialize metadata
552
    assert(j.contains("metadata"));
27✔
553
    assert(j["metadata"].is_object());
27✔
554
    for (const auto& entry : j["metadata"].items()) {
27✔
555
        builder.subject().add_metadata(entry.key(), entry.value());
1✔
556
    }
1✔
557

558
    builder.set_element_counter(element_counter);
27✔
559

560
    return builder.move();
27✔
561
}
27✔
562

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

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

593
void JSONSerializer::json_to_dataflow(
594
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Block& parent
595
) {
47✔
596
    std::map<size_t, data_flow::DataFlowNode&> nodes_map;
47✔
597

598
    assert(j.contains("nodes"));
47✔
599
    assert(j["nodes"].is_array());
47✔
600
    for (const auto& node : j["nodes"]) {
213✔
601
        assert(node.contains("type"));
213✔
602
        assert(node["type"].is_string());
213✔
603
        assert(node.contains("element_id"));
213✔
604
        assert(node["element_id"].is_number_integer());
213✔
605
        std::string type = node["type"];
213✔
606
        if (type == "tasklet") {
213✔
607
            assert(node.contains("code"));
60✔
608
            assert(node["code"].is_number_integer());
60✔
609
            assert(node.contains("inputs"));
60✔
610
            assert(node["inputs"].is_array());
60✔
611
            assert(node.contains("output"));
60✔
612
            assert(node["output"].is_string());
60✔
613
            auto inputs = node["inputs"].get<std::vector<std::string>>();
60✔
614

615
            auto& tasklet =
60✔
616
                builder
60✔
617
                    .add_tasklet(parent, node["code"], node["output"], inputs, json_to_debug_info(node["debug_info"]));
60✔
618
            tasklet.element_id_ = node["element_id"];
60✔
619
            nodes_map.insert({node["element_id"], tasklet});
60✔
620
        } else if (type == "library_node") {
153✔
621
            assert(node.contains("code"));
11✔
622
            data_flow::LibraryNodeCode code(node["code"].get<std::string>());
11✔
623

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

643
            auto type = json_to_type(node["data_type"]);
×
644

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

654
    assert(j.contains("edges"));
47✔
655
    assert(j["edges"].is_array());
47✔
656
    for (const auto& edge : j["edges"]) {
187✔
657
        assert(edge.contains("src"));
187✔
658
        assert(edge["src"].is_number_integer());
187✔
659
        assert(edge.contains("dst"));
187✔
660
        assert(edge["dst"].is_number_integer());
187✔
661
        assert(edge.contains("src_conn"));
187✔
662
        assert(edge["src_conn"].is_string());
187✔
663
        assert(edge.contains("dst_conn"));
187✔
664
        assert(edge["dst_conn"].is_string());
187✔
665
        assert(edge.contains("subset"));
187✔
666
        assert(edge["subset"].is_array());
187✔
667

668
        assert(nodes_map.find(edge["src"]) != nodes_map.end());
187✔
669
        assert(nodes_map.find(edge["dst"]) != nodes_map.end());
187✔
670
        auto& source = nodes_map.at(edge["src"]);
187✔
671
        auto& target = nodes_map.at(edge["dst"]);
187✔
672

673
        auto base_type = json_to_type(edge["base_type"]);
187✔
674

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

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

709
    sequence.element_id_ = j["element_id"];
61✔
710
    sequence.debug_info_ = json_to_debug_info(j["debug_info"]);
61✔
711

712
    std::string type = j["type"];
61✔
713
    if (type == "sequence") {
61✔
714
        for (size_t i = 0; i < j["children"].size(); i++) {
133✔
715
            auto& child = j["children"][i];
72✔
716
            auto& transition = j["transitions"][i];
72✔
717
            assert(child.contains("type"));
72✔
718
            assert(child["type"].is_string());
72✔
719

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

734
            if (child["type"] == "block") {
72✔
735
                json_to_block_node(child, builder, sequence, assignments);
45✔
736
            } else if (child["type"] == "for") {
45✔
737
                json_to_for_node(child, builder, sequence, assignments);
16✔
738
            } else if (child["type"] == "if_else") {
16✔
739
                json_to_if_else_node(child, builder, sequence, assignments);
×
740
            } else if (child["type"] == "while") {
11✔
741
                json_to_while_node(child, builder, sequence, assignments);
1✔
742
            } else if (child["type"] == "break") {
10✔
743
                json_to_break_node(child, builder, sequence, assignments);
1✔
744
            } else if (child["type"] == "continue") {
9✔
745
                json_to_continue_node(child, builder, sequence, assignments);
1✔
746
            } else if (child["type"] == "return") {
8✔
747
                json_to_return_node(child, builder, sequence, assignments);
×
748
            } else if (child["type"] == "map") {
8✔
749
                json_to_map_node(child, builder, sequence, assignments);
8✔
750
            } else if (child["type"] == "sequence") {
8✔
751
                auto& subseq = builder.add_sequence(sequence, assignments, json_to_debug_info(child["debug_info"]));
×
752
                json_to_sequence(child, builder, subseq);
×
753
            } else {
×
754
                throw std::runtime_error("Unknown child type");
×
755
            }
×
756

757
            sequence.at(i).second.debug_info_ = json_to_debug_info(transition["debug_info"]);
72✔
758
            sequence.at(i).second.element_id_ = transition["element_id"];
72✔
759
        }
72✔
760
    } else {
61✔
761
        throw std::runtime_error("expected sequence type");
×
762
    }
×
763
}
61✔
764

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

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

806
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
17✔
807
    auto init = symbolic::parse(j["init"].get<std::string>());
17✔
808
    auto update = symbolic::parse(j["update"].get<std::string>());
17✔
809

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

816
    auto& for_node =
17✔
817
        builder.add_for(parent, indvar, condition, init, update, assignments, json_to_debug_info(j["debug_info"]));
17✔
818
    for_node.element_id_ = j["element_id"];
17✔
819

820
    assert(j["root"].contains("type"));
17✔
821
    assert(j["root"]["type"].is_string());
17✔
822
    assert(j["root"]["type"] == "sequence");
17✔
823
    json_to_sequence(j["root"], builder, for_node.root());
17✔
824
}
17✔
825

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

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

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

874
    auto& while_node = builder.add_while(parent, assignments, json_to_debug_info(j["debug_info"]));
4✔
875
    while_node.element_id_ = j["element_id"];
4✔
876

877
    assert(j["root"]["type"] == "sequence");
4✔
878
    json_to_sequence(j["root"], builder, while_node.root());
4✔
879
}
4✔
880

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

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

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

929
    structured_control_flow::ScheduleType schedule_type = json_to_schedule_type(j["schedule_type"]);
9✔
930

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

940
    auto& map_node = builder.add_map(
9✔
941
        parent, indvar, condition, init, update, schedule_type, assignments, json_to_debug_info(j["debug_info"])
9✔
942
    );
9✔
943
    map_node.element_id_ = j["element_id"];
9✔
944

945
    assert(j["root"].contains("type"));
9✔
946
    assert(j["root"]["type"].is_string());
9✔
947
    assert(j["root"]["type"] == "sequence");
9✔
948
    json_to_sequence(j["root"], builder, map_node.root());
9✔
949
}
9✔
950

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

961
    std::string data = j["data"];
1✔
962
    std::unique_ptr<types::IType> data_type = nullptr;
1✔
963
    if (j.contains("data_type")) {
1✔
964
        data_type = json_to_type(j["data_type"]);
×
965
    }
×
966

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

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

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

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

1149
types::StorageType JSONSerializer::json_to_storage_type(const nlohmann::json& j) {
512✔
1150
    if (!j.contains("value")) {
512✔
1151
        return types::StorageType::CPU_Stack();
×
1152
    }
×
1153
    std::string value = j["value"].get<std::string>();
512✔
1154

1155
    symbolic::Expression allocation_size = SymEngine::null;
512✔
1156
    if (j.contains("allocation_size")) {
512✔
1157
        allocation_size = symbolic::parse(j["allocation_size"].get<std::string>());
6✔
1158
    }
6✔
1159

1160
    types::StorageType::AllocationType allocation = j["allocation"];
512✔
1161
    types::StorageType::AllocationType deallocation = j["deallocation"];
512✔
1162

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

1165
    if (j.contains("args")) {
512✔
1166
        nlohmann::json::array_t args = j["args"];
×
1167
        if (args.size() > 0) {
×
1168
            storageType.arg1(symbolic::parse(args[0].get<std::string>()));
×
1169
        }
×
1170
    }
×
1171
    return storageType;
512✔
1172
}
512✔
1173

1174
std::string JSONSerializer::expression(const symbolic::Expression expr) {
321✔
1175
    JSONSymbolicPrinter printer;
321✔
1176
    return printer.apply(expr);
321✔
1177
};
321✔
1178

1179
void JSONSymbolicPrinter::bvisit(const SymEngine::Equality& x) {
×
1180
    str_ = apply(x.get_args()[0]) + " == " + apply(x.get_args()[1]);
×
1181
    str_ = parenthesize(str_);
×
1182
};
×
1183

1184
void JSONSymbolicPrinter::bvisit(const SymEngine::Unequality& x) {
×
1185
    str_ = apply(x.get_args()[0]) + " != " + apply(x.get_args()[1]);
×
1186
    str_ = parenthesize(str_);
×
1187
};
×
1188

1189
void JSONSymbolicPrinter::bvisit(const SymEngine::LessThan& x) {
2✔
1190
    str_ = apply(x.get_args()[0]) + " <= " + apply(x.get_args()[1]);
2✔
1191
    str_ = parenthesize(str_);
2✔
1192
};
2✔
1193

1194
void JSONSymbolicPrinter::bvisit(const SymEngine::StrictLessThan& x) {
26✔
1195
    str_ = apply(x.get_args()[0]) + " < " + apply(x.get_args()[1]);
26✔
1196
    str_ = parenthesize(str_);
26✔
1197
};
26✔
1198

1199
void JSONSymbolicPrinter::bvisit(const SymEngine::Min& x) {
×
1200
    std::ostringstream s;
×
1201
    auto container = x.get_args();
×
1202
    if (container.size() == 1) {
×
1203
        s << apply(*container.begin());
×
1204
    } else {
×
1205
        s << "min(";
×
1206
        s << apply(*container.begin());
×
1207

1208
        // Recursively apply __daisy_min to the arguments
1209
        SymEngine::vec_basic subargs;
×
1210
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1211
            subargs.push_back(*it);
×
1212
        }
×
1213
        auto submin = SymEngine::min(subargs);
×
1214
        s << ", " << apply(submin);
×
1215

1216
        s << ")";
×
1217
    }
×
1218

1219
    str_ = s.str();
×
1220
};
×
1221

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

1231
        // Recursively apply __daisy_max to the arguments
1232
        SymEngine::vec_basic subargs;
×
1233
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1234
            subargs.push_back(*it);
×
1235
        }
×
1236
        auto submax = SymEngine::max(subargs);
×
1237
        s << ", " << apply(submax);
×
1238

1239
        s << ")";
×
1240
    }
×
1241

1242
    str_ = s.str();
×
1243
};
×
1244

1245
void LibraryNodeSerializerRegistry::
1246
    register_library_node_serializer(std::string library_node_code, LibraryNodeSerializerFn fn) {
89✔
1247
    std::lock_guard<std::mutex> lock(mutex_);
89✔
1248
    if (factory_map_.find(library_node_code) != factory_map_.end()) {
89✔
1249
        return;
×
1250
    }
×
1251
    factory_map_[library_node_code] = std::move(fn);
89✔
1252
}
89✔
1253

1254
LibraryNodeSerializerFn LibraryNodeSerializerRegistry::get_library_node_serializer(std::string library_node_code) {
23✔
1255
    auto it = factory_map_.find(library_node_code);
23✔
1256
    if (it != factory_map_.end()) {
23✔
1257
        return it->second;
23✔
1258
    }
23✔
1259
    return nullptr;
×
1260
}
23✔
1261

1262
size_t LibraryNodeSerializerRegistry::size() const { return factory_map_.size(); }
×
1263

1264
void register_default_serializers() {
2✔
1265
    // stdlib
1266
    LibraryNodeSerializerRegistry::instance()
2✔
1267
        .register_library_node_serializer(stdlib::LibraryNodeType_Alloca.value(), []() {
2✔
1268
            return std::make_unique<stdlib::AllocaNodeSerializer>();
×
1269
        });
×
1270
    LibraryNodeSerializerRegistry::instance()
2✔
1271
        .register_library_node_serializer(stdlib::LibraryNodeType_Calloc.value(), []() {
2✔
1272
            return std::make_unique<stdlib::CallocNodeSerializer>();
×
1273
        });
×
1274
    LibraryNodeSerializerRegistry::instance()
2✔
1275
        .register_library_node_serializer(stdlib::LibraryNodeType_Free.value(), []() {
2✔
1276
            return std::make_unique<stdlib::FreeNodeSerializer>();
×
1277
        });
×
1278
    LibraryNodeSerializerRegistry::instance()
2✔
1279
        .register_library_node_serializer(stdlib::LibraryNodeType_Malloc.value(), []() {
2✔
1280
            return std::make_unique<stdlib::MallocNodeSerializer>();
×
1281
        });
×
1282
    LibraryNodeSerializerRegistry::instance()
2✔
1283
        .register_library_node_serializer(stdlib::LibraryNodeType_Memcpy.value(), []() {
2✔
1284
            return std::make_unique<stdlib::MemcpyNodeSerializer>();
×
1285
        });
×
1286
    LibraryNodeSerializerRegistry::instance()
2✔
1287
        .register_library_node_serializer(stdlib::LibraryNodeType_Memmove.value(), []() {
2✔
1288
            return std::make_unique<stdlib::MemmoveNodeSerializer>();
×
1289
        });
×
1290
    LibraryNodeSerializerRegistry::instance()
2✔
1291
        .register_library_node_serializer(stdlib::LibraryNodeType_Memset.value(), []() {
2✔
1292
            return std::make_unique<stdlib::MemsetNodeSerializer>();
×
1293
        });
×
1294
    LibraryNodeSerializerRegistry::instance()
2✔
1295
        .register_library_node_serializer(stdlib::LibraryNodeType_Trap.value(), []() {
2✔
1296
            return std::make_unique<stdlib::TrapNodeSerializer>();
×
1297
        });
×
1298
    LibraryNodeSerializerRegistry::instance()
2✔
1299
        .register_library_node_serializer(stdlib::LibraryNodeType_Unreachable.value(), []() {
2✔
1300
            return std::make_unique<stdlib::UnreachableNodeSerializer>();
×
1301
        });
×
1302

1303
    // Metadata
1304
    LibraryNodeSerializerRegistry::instance()
2✔
1305
        .register_library_node_serializer(data_flow::LibraryNodeType_Metadata.value(), []() {
2✔
1306
            return std::make_unique<data_flow::MetadataNodeSerializer>();
×
1307
        });
×
1308

1309
    // Barrier
1310
    LibraryNodeSerializerRegistry::instance()
2✔
1311
        .register_library_node_serializer(data_flow::LibraryNodeType_BarrierLocal.value(), []() {
2✔
1312
            return std::make_unique<data_flow::BarrierLocalNodeSerializer>();
1✔
1313
        });
1✔
1314

1315
    // Call Node
1316
    LibraryNodeSerializerRegistry::instance()
2✔
1317
        .register_library_node_serializer(data_flow::LibraryNodeType_Call.value(), []() {
6✔
1318
            return std::make_unique<data_flow::CallNodeSerializer>();
6✔
1319
        });
6✔
1320
    LibraryNodeSerializerRegistry::instance()
2✔
1321
        .register_library_node_serializer(data_flow::LibraryNodeType_Invoke.value(), []() {
2✔
1322
            return std::make_unique<data_flow::InvokeNodeSerializer>();
×
1323
        });
×
1324

1325
    // CMath
1326
    LibraryNodeSerializerRegistry::instance()
2✔
1327
        .register_library_node_serializer(math::cmath::LibraryNodeType_CMath.value(), []() {
2✔
1328
            return std::make_unique<math::cmath::CMathNodeSerializer>();
×
1329
        });
×
1330
    // Backward compatibility
1331
    LibraryNodeSerializerRegistry::instance()
2✔
1332
        .register_library_node_serializer(math::cmath::LibraryNodeType_CMath_Deprecated.value(), []() {
2✔
1333
            return std::make_unique<math::cmath::CMathNodeSerializer>();
×
1334
        });
×
1335

1336
    // BLAS
1337
    LibraryNodeSerializerRegistry::instance()
2✔
1338
        .register_library_node_serializer(math::blas::LibraryNodeType_DOT.value(), []() {
2✔
1339
            return std::make_unique<math::blas::DotNodeSerializer>();
×
1340
        });
×
1341
    LibraryNodeSerializerRegistry::instance()
2✔
1342
        .register_library_node_serializer(math::blas::LibraryNodeType_GEMM.value(), []() {
2✔
1343
            return std::make_unique<math::blas::GEMMNodeSerializer>();
×
1344
        });
×
1345

1346
    // Tensor
1347

1348
    LibraryNodeSerializerRegistry::instance()
2✔
1349
        .register_library_node_serializer(math::tensor::LibraryNodeType_Broadcast.value(), []() {
2✔
1350
            return std::make_unique<math::tensor::BroadcastNodeSerializer>();
×
1351
        });
×
1352
    LibraryNodeSerializerRegistry::instance()
2✔
1353
        .register_library_node_serializer(math::tensor::LibraryNodeType_Conv.value(), []() {
2✔
1354
            return std::make_unique<math::tensor::ConvNodeSerializer>();
×
1355
        });
×
1356
    LibraryNodeSerializerRegistry::instance()
2✔
1357
        .register_library_node_serializer(math::tensor::LibraryNodeType_Transpose.value(), []() {
2✔
1358
            return std::make_unique<math::tensor::TransposeNodeSerializer>();
×
1359
        });
×
1360

1361
    // Elementwise
1362
    LibraryNodeSerializerRegistry::instance()
2✔
1363
        .register_library_node_serializer(math::tensor::LibraryNodeType_Abs.value(), []() {
2✔
1364
            return std::make_unique<math::tensor::AbsNodeSerializer>();
×
1365
        });
×
1366
    LibraryNodeSerializerRegistry::instance()
2✔
1367
        .register_library_node_serializer(math::tensor::LibraryNodeType_Add.value(), []() {
2✔
1368
            return std::make_unique<math::tensor::AddNodeSerializer>();
×
1369
        });
×
1370
    LibraryNodeSerializerRegistry::instance()
2✔
1371
        .register_library_node_serializer(math::tensor::LibraryNodeType_Div.value(), []() {
2✔
1372
            return std::make_unique<math::tensor::DivNodeSerializer>();
×
1373
        });
×
1374
    LibraryNodeSerializerRegistry::instance()
2✔
1375
        .register_library_node_serializer(math::tensor::LibraryNodeType_Elu.value(), []() {
2✔
1376
            return std::make_unique<math::tensor::EluNodeSerializer>();
×
1377
        });
×
1378
    LibraryNodeSerializerRegistry::instance()
2✔
1379
        .register_library_node_serializer(math::tensor::LibraryNodeType_Exp.value(), []() {
2✔
1380
            return std::make_unique<math::tensor::ExpNodeSerializer>();
×
1381
        });
×
1382
    LibraryNodeSerializerRegistry::instance()
2✔
1383
        .register_library_node_serializer(math::tensor::LibraryNodeType_Erf.value(), []() {
2✔
1384
            return std::make_unique<math::tensor::ErfNodeSerializer>();
×
1385
        });
×
1386
    LibraryNodeSerializerRegistry::instance()
2✔
1387
        .register_library_node_serializer(math::tensor::LibraryNodeType_HardSigmoid.value(), []() {
2✔
1388
            return std::make_unique<math::tensor::HardSigmoidNodeSerializer>();
×
1389
        });
×
1390
    LibraryNodeSerializerRegistry::instance()
2✔
1391
        .register_library_node_serializer(math::tensor::LibraryNodeType_LeakyReLU.value(), []() {
2✔
1392
            return std::make_unique<math::tensor::LeakyReLUNodeSerializer>();
×
1393
        });
×
1394
    LibraryNodeSerializerRegistry::instance()
2✔
1395
        .register_library_node_serializer(math::tensor::LibraryNodeType_Mul.value(), []() {
2✔
1396
            return std::make_unique<math::tensor::MulNodeSerializer>();
×
1397
        });
×
1398
    LibraryNodeSerializerRegistry::instance()
2✔
1399
        .register_library_node_serializer(math::tensor::LibraryNodeType_Pow.value(), []() {
2✔
1400
            return std::make_unique<math::tensor::PowNodeSerializer>();
×
1401
        });
×
1402
    LibraryNodeSerializerRegistry::instance()
2✔
1403
        .register_library_node_serializer(math::tensor::LibraryNodeType_ReLU.value(), []() {
2✔
1404
            return std::make_unique<math::tensor::ReLUNodeSerializer>();
×
1405
        });
×
1406
    LibraryNodeSerializerRegistry::instance()
2✔
1407
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sigmoid.value(), []() {
2✔
1408
            return std::make_unique<math::tensor::SigmoidNodeSerializer>();
×
1409
        });
×
1410
    LibraryNodeSerializerRegistry::instance()
2✔
1411
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sqrt.value(), []() {
2✔
1412
            return std::make_unique<math::tensor::SqrtNodeSerializer>();
×
1413
        });
×
1414
    LibraryNodeSerializerRegistry::instance()
2✔
1415
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sub.value(), []() {
2✔
1416
            return std::make_unique<math::tensor::SubNodeSerializer>();
×
1417
        });
×
1418
    LibraryNodeSerializerRegistry::instance()
2✔
1419
        .register_library_node_serializer(math::tensor::LibraryNodeType_Tanh.value(), []() {
2✔
1420
            return std::make_unique<math::tensor::TanhNodeSerializer>();
×
1421
        });
×
1422
    LibraryNodeSerializerRegistry::instance()
2✔
1423
        .register_library_node_serializer(math::tensor::LibraryNodeType_Minimum.value(), []() {
2✔
1424
            return std::make_unique<math::tensor::MinimumNodeSerializer>();
×
1425
        });
×
1426
    LibraryNodeSerializerRegistry::instance()
2✔
1427
        .register_library_node_serializer(math::tensor::LibraryNodeType_Maximum.value(), []() {
2✔
1428
            return std::make_unique<math::tensor::MaximumNodeSerializer>();
×
1429
        });
×
1430
    LibraryNodeSerializerRegistry::instance()
2✔
1431
        .register_library_node_serializer(math::tensor::LibraryNodeType_TensorTasklet.value(), []() {
2✔
NEW
1432
            return std::make_unique<math::tensor::TaskletTensorNodeSerializer>();
×
NEW
1433
        });
×
1434

1435
    // Reduce
1436
    LibraryNodeSerializerRegistry::instance()
2✔
1437
        .register_library_node_serializer(math::tensor::LibraryNodeType_Sum.value(), []() {
2✔
1438
            return std::make_unique<math::tensor::SumNodeSerializer>();
×
1439
        });
×
1440
    LibraryNodeSerializerRegistry::instance()
2✔
1441
        .register_library_node_serializer(math::tensor::LibraryNodeType_Max.value(), []() {
2✔
1442
            return std::make_unique<math::tensor::MaxNodeSerializer>();
×
1443
        });
×
1444
    LibraryNodeSerializerRegistry::instance()
2✔
1445
        .register_library_node_serializer(math::tensor::LibraryNodeType_Min.value(), []() {
2✔
1446
            return std::make_unique<math::tensor::MinNodeSerializer>();
×
1447
        });
×
1448
    LibraryNodeSerializerRegistry::instance()
2✔
1449
        .register_library_node_serializer(math::tensor::LibraryNodeType_Softmax.value(), []() {
2✔
1450
            return std::make_unique<math::tensor::SoftmaxNodeSerializer>();
×
1451
        });
×
1452
    LibraryNodeSerializerRegistry::instance()
2✔
1453
        .register_library_node_serializer(math::tensor::LibraryNodeType_Mean.value(), []() {
2✔
1454
            return std::make_unique<math::tensor::MeanNodeSerializer>();
×
1455
        });
×
1456
    LibraryNodeSerializerRegistry::instance()
2✔
1457
        .register_library_node_serializer(math::tensor::LibraryNodeType_Std.value(), []() {
2✔
1458
            return std::make_unique<math::tensor::StdNodeSerializer>();
×
1459
        });
×
1460
}
2✔
1461

1462
} // namespace serializer
1463
} // 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