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

daisytuner / sdfglib / 19525173698

19 Nov 2025 09:22AM UTC coverage: 62.105% (-0.08%) from 62.184%
19525173698

push

github

web-flow
Merge pull request #354 from daisytuner/tenstorrent-transform

Tenstorrent transform

52 of 95 new or added lines in 15 files covered. (54.74%)

28 existing lines in 8 files now uncovered.

11141 of 17939 relevant lines covered (62.1%)

112.03 hits per line

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

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

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

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

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

35
namespace sdfg {
36
namespace serializer {
37

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

45
    return FunctionType(str);
×
46
}
7✔
47

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

53
nlohmann::json JSONSerializer::serialize(const sdfg::StructuredSDFG& sdfg) {
7✔
54
    nlohmann::json j;
7✔
55

56
    j["name"] = sdfg.name();
7✔
57
    j["element_counter"] = sdfg.element_counter();
7✔
58
    j["type"] = std::string(sdfg.type().value());
7✔
59

60
    nlohmann::json return_type_json;
7✔
61
    type_to_json(return_type_json, sdfg.return_type());
7✔
62
    j["return_type"] = return_type_json;
7✔
63

64
    j["structures"] = nlohmann::json::array();
7✔
65
    for (const auto& structure_name : sdfg.structures()) {
8✔
66
        const auto& structure = sdfg.structure(structure_name);
1✔
67
        nlohmann::json structure_json;
1✔
68
        structure_definition_to_json(structure_json, structure);
1✔
69
        j["structures"].push_back(structure_json);
1✔
70
    }
1✔
71

72
    j["containers"] = nlohmann::json::object();
7✔
73
    for (const auto& container : sdfg.containers()) {
61✔
74
        nlohmann::json desc;
54✔
75
        type_to_json(desc, sdfg.type(container));
54✔
76
        j["containers"][container] = desc;
54✔
77
    }
54✔
78

79
    j["arguments"] = nlohmann::json::array();
7✔
80
    for (const auto& argument : sdfg.arguments()) {
30✔
81
        j["arguments"].push_back(argument);
23✔
82
    }
83

84
    j["externals"] = nlohmann::json::array();
7✔
85
    for (const auto& external : sdfg.externals()) {
11✔
86
        nlohmann::json external_json;
4✔
87
        external_json["name"] = external;
4✔
88
        external_json["linkage_type"] = sdfg.linkage_type(external);
4✔
89
        j["externals"].push_back(external_json);
4✔
90
    }
4✔
91

92
    j["metadata"] = nlohmann::json::object();
7✔
93
    for (const auto& entry : sdfg.metadata()) {
8✔
94
        j["metadata"][entry.first] = entry.second;
1✔
95
    }
96

97
    // Walk the SDFG
98
    nlohmann::json root_json;
7✔
99
    sequence_to_json(root_json, sdfg.root());
7✔
100
    j["root"] = root_json;
7✔
101

102
    return j;
7✔
103
}
7✔
104

105
void JSONSerializer::dataflow_to_json(nlohmann::json& j, const data_flow::DataFlowGraph& dataflow) {
33✔
106
    j["type"] = "dataflow";
33✔
107
    j["nodes"] = nlohmann::json::array();
33✔
108
    j["edges"] = nlohmann::json::array();
33✔
109

110
    for (auto& node : dataflow.nodes()) {
111✔
111
        nlohmann::json node_json;
78✔
112
        node_json["element_id"] = node.element_id();
78✔
113

114
        node_json["debug_info"] = nlohmann::json::object();
78✔
115
        debug_info_to_json(node_json["debug_info"], node.debug_info());
78✔
116

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

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

150
        j["nodes"].push_back(node_json);
78✔
151
    }
78✔
152

153
    for (auto& edge : dataflow.edges()) {
94✔
154
        nlohmann::json edge_json;
61✔
155
        edge_json["element_id"] = edge.element_id();
61✔
156

157
        edge_json["debug_info"] = nlohmann::json::object();
61✔
158
        debug_info_to_json(edge_json["debug_info"], edge.debug_info());
61✔
159

160
        edge_json["src"] = edge.src().element_id();
61✔
161
        edge_json["dst"] = edge.dst().element_id();
61✔
162

163
        edge_json["src_conn"] = edge.src_conn();
61✔
164
        edge_json["dst_conn"] = edge.dst_conn();
61✔
165

166
        edge_json["subset"] = nlohmann::json::array();
61✔
167
        for (auto& subset : edge.subset()) {
109✔
168
            edge_json["subset"].push_back(expression(subset));
48✔
169
        }
170

171
        nlohmann::json base_type_json;
61✔
172
        type_to_json(base_type_json, edge.base_type());
61✔
173
        edge_json["base_type"] = base_type_json;
61✔
174

175
        j["edges"].push_back(edge_json);
61✔
176
    }
61✔
177
}
33✔
178

179
void JSONSerializer::block_to_json(nlohmann::json& j, const structured_control_flow::Block& block) {
31✔
180
    j["type"] = "block";
31✔
181
    j["element_id"] = block.element_id();
31✔
182

183
    j["debug_info"] = nlohmann::json::object();
31✔
184
    debug_info_to_json(j["debug_info"], block.debug_info());
31✔
185

186
    nlohmann::json dataflow_json;
31✔
187
    dataflow_to_json(dataflow_json, block.dataflow());
31✔
188
    j["dataflow"] = dataflow_json;
31✔
189
}
31✔
190

191
void JSONSerializer::for_to_json(nlohmann::json& j, const structured_control_flow::For& for_node) {
16✔
192
    j["type"] = "for";
16✔
193
    j["element_id"] = for_node.element_id();
16✔
194

195
    j["debug_info"] = nlohmann::json::object();
16✔
196
    debug_info_to_json(j["debug_info"], for_node.debug_info());
16✔
197

198
    j["indvar"] = expression(for_node.indvar());
16✔
199
    j["init"] = expression(for_node.init());
16✔
200
    j["condition"] = expression(for_node.condition());
16✔
201
    j["update"] = expression(for_node.update());
16✔
202

203
    nlohmann::json body_json;
16✔
204
    sequence_to_json(body_json, for_node.root());
16✔
205
    j["root"] = body_json;
16✔
206
}
16✔
207

208
void JSONSerializer::if_else_to_json(nlohmann::json& j, const structured_control_flow::IfElse& if_else_node) {
2✔
209
    j["type"] = "if_else";
2✔
210
    j["element_id"] = if_else_node.element_id();
2✔
211

212
    j["debug_info"] = nlohmann::json::object();
2✔
213
    debug_info_to_json(j["debug_info"], if_else_node.debug_info());
2✔
214

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

226
void JSONSerializer::while_node_to_json(nlohmann::json& j, const structured_control_flow::While& while_node) {
5✔
227
    j["type"] = "while";
5✔
228
    j["element_id"] = while_node.element_id();
5✔
229

230
    j["debug_info"] = nlohmann::json::object();
5✔
231
    debug_info_to_json(j["debug_info"], while_node.debug_info());
5✔
232

233
    nlohmann::json body_json;
5✔
234
    sequence_to_json(body_json, while_node.root());
5✔
235
    j["root"] = body_json;
5✔
236
}
5✔
237

238
void JSONSerializer::break_node_to_json(nlohmann::json& j, const structured_control_flow::Break& break_node) {
2✔
239
    j["type"] = "break";
2✔
240
    j["element_id"] = break_node.element_id();
2✔
241

242
    j["debug_info"] = nlohmann::json::object();
2✔
243
    debug_info_to_json(j["debug_info"], break_node.debug_info());
2✔
244
}
2✔
245

246
void JSONSerializer::continue_node_to_json(nlohmann::json& j, const structured_control_flow::Continue& continue_node) {
2✔
247
    j["type"] = "continue";
2✔
248
    j["element_id"] = continue_node.element_id();
2✔
249

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

254
void JSONSerializer::map_to_json(nlohmann::json& j, const structured_control_flow::Map& map_node) {
2✔
255
    j["type"] = "map";
2✔
256
    j["element_id"] = map_node.element_id();
2✔
257

258
    j["debug_info"] = nlohmann::json::object();
2✔
259
    debug_info_to_json(j["debug_info"], map_node.debug_info());
2✔
260

261
    j["indvar"] = expression(map_node.indvar());
2✔
262
    j["init"] = expression(map_node.init());
2✔
263
    j["condition"] = expression(map_node.condition());
2✔
264
    j["update"] = expression(map_node.update());
2✔
265

266
    j["schedule_type"] = nlohmann::json::object();
2✔
267
    schedule_type_to_json(j["schedule_type"], map_node.schedule_type());
2✔
268

269
    nlohmann::json body_json;
2✔
270
    sequence_to_json(body_json, map_node.root());
2✔
271
    j["root"] = body_json;
2✔
272
}
2✔
273

274
void JSONSerializer::return_node_to_json(nlohmann::json& j, const structured_control_flow::Return& return_node) {
2✔
275
    j["type"] = "return";
2✔
276
    j["element_id"] = return_node.element_id();
2✔
277
    j["data"] = return_node.data();
2✔
278

279
    if (return_node.is_constant()) {
2✔
280
        nlohmann::json type_json;
×
281
        type_to_json(type_json, return_node.type());
×
282
        j["data_type"] = type_json;
×
283
    }
×
284

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

289
void JSONSerializer::sequence_to_json(nlohmann::json& j, const structured_control_flow::Sequence& sequence) {
37✔
290
    j["type"] = "sequence";
37✔
291
    j["element_id"] = sequence.element_id();
37✔
292

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

296
    j["children"] = nlohmann::json::array();
37✔
297
    j["transitions"] = nlohmann::json::array();
37✔
298

299
    for (size_t i = 0; i < sequence.size(); i++) {
84✔
300
        nlohmann::json child_json;
47✔
301
        auto& child = sequence.at(i).first;
47✔
302
        auto& transition = sequence.at(i).second;
47✔
303

304
        if (auto block = dynamic_cast<const structured_control_flow::Block*>(&child)) {
47✔
305
            block_to_json(child_json, *block);
29✔
306
        } else if (auto for_node = dynamic_cast<const structured_control_flow::For*>(&child)) {
47✔
307
            for_to_json(child_json, *for_node);
14✔
308
        } else if (auto sequence_node = dynamic_cast<const structured_control_flow::Sequence*>(&child)) {
18✔
309
            sequence_to_json(child_json, *sequence_node);
×
310
        } else if (auto condition_node = dynamic_cast<const structured_control_flow::IfElse*>(&child)) {
4✔
311
            if_else_to_json(child_json, *condition_node);
×
312
        } else if (auto while_node = dynamic_cast<const structured_control_flow::While*>(&child)) {
4✔
313
            while_node_to_json(child_json, *while_node);
×
314
        } else if (auto return_node = dynamic_cast<const structured_control_flow::Return*>(&child)) {
4✔
315
            return_node_to_json(child_json, *return_node);
×
316
        } else if (auto break_node = dynamic_cast<const structured_control_flow::Break*>(&child)) {
4✔
317
            break_node_to_json(child_json, *break_node);
2✔
318
        } else if (auto continue_node = dynamic_cast<const structured_control_flow::Continue*>(&child)) {
4✔
319
            continue_node_to_json(child_json, *continue_node);
2✔
320
        } else if (auto map_node = dynamic_cast<const structured_control_flow::Map*>(&child)) {
2✔
321
            map_to_json(child_json, *map_node);
×
322
        } else {
×
323
            throw std::runtime_error("Unknown child type");
×
324
        }
325

326
        j["children"].push_back(child_json);
47✔
327

328
        // Add transition information
329
        nlohmann::json transition_json;
47✔
330
        transition_json["type"] = "transition";
47✔
331
        transition_json["element_id"] = transition.element_id();
47✔
332

333
        transition_json["debug_info"] = nlohmann::json::object();
47✔
334
        debug_info_to_json(transition_json["debug_info"], transition.debug_info());
47✔
335

336
        transition_json["assignments"] = nlohmann::json::array();
47✔
337
        for (const auto& assignment : transition.assignments()) {
50✔
338
            nlohmann::json assignment_json;
3✔
339
            assignment_json["symbol"] = expression(assignment.first);
3✔
340
            assignment_json["expression"] = expression(assignment.second);
3✔
341
            transition_json["assignments"].push_back(assignment_json);
3✔
342
        }
3✔
343

344
        j["transitions"].push_back(transition_json);
47✔
345
    }
47✔
346
}
37✔
347

348
void JSONSerializer::type_to_json(nlohmann::json& j, const types::IType& type) {
212✔
349
    if (auto scalar_type = dynamic_cast<const types::Scalar*>(&type)) {
212✔
350
        j["type"] = "scalar";
133✔
351
        j["primitive_type"] = scalar_type->primitive_type();
133✔
352
        j["storage_type"] = nlohmann::json::object();
133✔
353
        storage_type_to_json(j["storage_type"], scalar_type->storage_type());
133✔
354
        j["initializer"] = scalar_type->initializer();
133✔
355
        j["alignment"] = scalar_type->alignment();
133✔
356
    } else if (auto array_type = dynamic_cast<const types::Array*>(&type)) {
212✔
357
        j["type"] = "array";
55✔
358
        nlohmann::json element_type_json;
55✔
359
        type_to_json(element_type_json, array_type->element_type());
55✔
360
        j["element_type"] = element_type_json;
55✔
361
        j["num_elements"] = expression(array_type->num_elements());
55✔
362
        j["storage_type"] = nlohmann::json::object();
55✔
363
        storage_type_to_json(j["storage_type"], array_type->storage_type());
55✔
364
        j["initializer"] = array_type->initializer();
55✔
365
        j["alignment"] = array_type->alignment();
55✔
366
    } else if (auto pointer_type = dynamic_cast<const types::Pointer*>(&type)) {
79✔
367
        j["type"] = "pointer";
19✔
368
        if (pointer_type->has_pointee_type()) {
19✔
369
            nlohmann::json pointee_type_json;
18✔
370
            type_to_json(pointee_type_json, pointer_type->pointee_type());
18✔
371
            j["pointee_type"] = pointee_type_json;
18✔
372
        }
18✔
373
        j["storage_type"] = nlohmann::json::object();
19✔
374
        storage_type_to_json(j["storage_type"], pointer_type->storage_type());
19✔
375
        j["initializer"] = pointer_type->initializer();
19✔
376
        j["alignment"] = pointer_type->alignment();
19✔
377
    } else if (auto structure_type = dynamic_cast<const types::Structure*>(&type)) {
24✔
378
        j["type"] = "structure";
3✔
379
        j["name"] = structure_type->name();
3✔
380
        j["storage_type"] = nlohmann::json::object();
3✔
381
        storage_type_to_json(j["storage_type"], structure_type->storage_type());
3✔
382
        j["initializer"] = structure_type->initializer();
3✔
383
        j["alignment"] = structure_type->alignment();
3✔
384
    } else if (auto function_type = dynamic_cast<const types::Function*>(&type)) {
5✔
385
        j["type"] = "function";
2✔
386
        nlohmann::json return_type_json;
2✔
387
        type_to_json(return_type_json, function_type->return_type());
2✔
388
        j["return_type"] = return_type_json;
2✔
389
        j["params"] = nlohmann::json::array();
2✔
390
        for (size_t i = 0; i < function_type->num_params(); i++) {
5✔
391
            nlohmann::json param_json;
3✔
392
            type_to_json(param_json, function_type->param_type(symbolic::integer(i)));
3✔
393
            j["params"].push_back(param_json);
3✔
394
        }
3✔
395
        j["is_var_arg"] = function_type->is_var_arg();
2✔
396
        j["storage_type"] = nlohmann::json::object();
2✔
397
        storage_type_to_json(j["storage_type"], function_type->storage_type());
2✔
398
        j["initializer"] = function_type->initializer();
2✔
399
        j["alignment"] = function_type->alignment();
2✔
400
    } else {
2✔
401
        throw std::runtime_error("Unknown type");
×
402
    }
403
}
212✔
404

405
void JSONSerializer::structure_definition_to_json(nlohmann::json& j, const types::StructureDefinition& definition) {
2✔
406
    j["name"] = definition.name();
2✔
407
    j["members"] = nlohmann::json::array();
2✔
408
    for (size_t i = 0; i < definition.num_members(); i++) {
4✔
409
        nlohmann::json member_json;
2✔
410
        type_to_json(member_json, definition.member_type(symbolic::integer(i)));
2✔
411
        j["members"].push_back(member_json);
2✔
412
    }
2✔
413
    j["is_packed"] = definition.is_packed();
2✔
414
}
2✔
415

416
void JSONSerializer::debug_info_to_json(nlohmann::json& j, const DebugInfo& debug_info) {
285✔
417
    j["has"] = debug_info.has();
285✔
418
    j["filename"] = debug_info.filename();
285✔
419
    j["function"] = debug_info.function();
285✔
420
    j["start_line"] = debug_info.start_line();
285✔
421
    j["start_column"] = debug_info.start_column();
285✔
422
    j["end_line"] = debug_info.end_line();
285✔
423
    j["end_column"] = debug_info.end_column();
285✔
424
}
285✔
425

426
void JSONSerializer::schedule_type_to_json(nlohmann::json& j, const ScheduleType& schedule_type) {
3✔
427
    j["value"] = schedule_type.value();
3✔
428
    j["properties"] = nlohmann::json::object();
3✔
429
    for (const auto& prop : schedule_type.properties()) {
4✔
430
        j["properties"][prop.first] = prop.second;
1✔
431
    }
432
}
3✔
433

434
void JSONSerializer::storage_type_to_json(nlohmann::json& j, const types::StorageType& storage_type) {
212✔
435
    j["value"] = storage_type.value();
212✔
436
    j["allocation"] = storage_type.allocation();
212✔
437
    j["deallocation"] = storage_type.deallocation();
212✔
438
    if (!storage_type.allocation_size().is_null()) {
212✔
439
        j["allocation_size"] = expression(storage_type.allocation_size());
×
440
    }
×
441
    const symbolic::Expression& arg1 = storage_type.arg1();
212✔
442
    if (!arg1.is_null()) {
212✔
NEW
443
        auto args = nlohmann::json::array();
×
NEW
444
        args.push_back(expression(arg1));
×
NEW
445
        j["args"] = args;
×
NEW
446
    }
×
447
}
212✔
448

449

450
/*
451
 * * Deserialization logic
452
 */
453

454
std::unique_ptr<StructuredSDFG> JSONSerializer::deserialize(nlohmann::json& j) {
7✔
455
    assert(j.contains("name"));
7✔
456
    assert(j["name"].is_string());
7✔
457
    assert(j.contains("type"));
7✔
458
    assert(j["type"].is_string());
7✔
459
    assert(j.contains("element_counter"));
7✔
460
    assert(j["element_counter"].is_number_integer());
7✔
461

462
    std::unique_ptr<types::IType> return_type;
7✔
463
    if (j.contains("return_type")) {
7✔
464
        return_type = json_to_type(j["return_type"]);
7✔
465
    } else {
7✔
466
        return_type = std::make_unique<types::Scalar>(types::PrimitiveType::Void);
×
467
    }
468

469
    FunctionType function_type = function_type_from_string(j["type"].get<std::string>());
7✔
470
    builder::StructuredSDFGBuilder builder(j["name"], function_type, *return_type);
7✔
471

472
    size_t element_counter = j["element_counter"];
7✔
473
    builder.set_element_counter(element_counter);
7✔
474

475
    // deserialize structures
476
    assert(j.contains("structures"));
7✔
477
    assert(j["structures"].is_array());
7✔
478
    for (const auto& structure : j["structures"]) {
8✔
479
        assert(structure.contains("name"));
1✔
480
        assert(structure["name"].is_string());
1✔
481
        json_to_structure_definition(structure, builder);
1✔
482
    }
483

484
    nlohmann::json& containers = j["containers"];
7✔
485

486
    // deserialize externals
487
    for (const auto& external : j["externals"]) {
11✔
488
        assert(external.contains("name"));
4✔
489
        assert(external["name"].is_string());
4✔
490
        assert(external.contains("linkage_type"));
4✔
491
        assert(external["linkage_type"].is_number_integer());
4✔
492
        auto& type_desc = containers.at(external["name"].get<std::string>());
4✔
493
        auto type = json_to_type(type_desc);
4✔
494
        builder.add_external(external["name"], *type, LinkageType(external["linkage_type"]));
4✔
495
    }
4✔
496

497
    // deserialize arguments
498
    for (const auto& name : j["arguments"]) {
30✔
499
        auto& type_desc = containers.at(name.get<std::string>());
23✔
500
        auto type = json_to_type(type_desc);
23✔
501
        builder.add_container(name, *type, true, false);
23✔
502
    }
23✔
503

504
    // deserialize transients
505
    for (const auto& entry : containers.items()) {
61✔
506
        if (builder.subject().is_argument(entry.key())) {
54✔
507
            continue;
23✔
508
        }
509
        if (builder.subject().is_external(entry.key())) {
31✔
510
            continue;
4✔
511
        }
512
        auto type = json_to_type(entry.value());
27✔
513
        builder.add_container(entry.key(), *type, false, false);
27✔
514
    }
27✔
515

516
    // deserialize root node
517
    assert(j.contains("root"));
7✔
518
    auto& root = builder.subject().root();
7✔
519
    json_to_sequence(j["root"], builder, root);
7✔
520

521
    // deserialize metadata
522
    assert(j.contains("metadata"));
7✔
523
    assert(j["metadata"].is_object());
7✔
524
    for (const auto& entry : j["metadata"].items()) {
8✔
525
        builder.subject().add_metadata(entry.key(), entry.value());
1✔
526
    }
527

528
    builder.set_element_counter(element_counter);
7✔
529

530
    return builder.move();
7✔
531
}
7✔
532

533
void JSONSerializer::json_to_structure_definition(const nlohmann::json& j, builder::StructuredSDFGBuilder& builder) {
2✔
534
    assert(j.contains("name"));
2✔
535
    assert(j["name"].is_string());
2✔
536
    assert(j.contains("members"));
2✔
537
    assert(j["members"].is_array());
2✔
538
    assert(j.contains("is_packed"));
2✔
539
    assert(j["is_packed"].is_boolean());
2✔
540
    auto is_packed = j["is_packed"];
2✔
541
    auto& definition = builder.add_structure(j["name"], is_packed);
2✔
542
    for (const auto& member : j["members"]) {
4✔
543
        nlohmann::json member_json;
2✔
544
        auto member_type = json_to_type(member);
2✔
545
        definition.add_member(*member_type);
2✔
546
    }
2✔
547
}
2✔
548

549
std::vector<std::pair<std::string, types::Scalar>> JSONSerializer::json_to_arguments(const nlohmann::json& j) {
×
550
    std::vector<std::pair<std::string, types::Scalar>> arguments;
×
551
    for (const auto& argument : j) {
×
552
        assert(argument.contains("name"));
×
553
        assert(argument["name"].is_string());
×
554
        assert(argument.contains("type"));
×
555
        assert(argument["type"].is_object());
×
556
        std::string name = argument["name"];
×
557
        auto type = json_to_type(argument["type"]);
×
558
        arguments.emplace_back(name, *dynamic_cast<types::Scalar*>(type.get()));
×
559
    }
×
560
    return arguments;
×
561
}
×
562

563
void JSONSerializer::json_to_dataflow(
23✔
564
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Block& parent
565
) {
566
    std::unordered_map<size_t, data_flow::DataFlowNode&> nodes_map;
23✔
567

568
    assert(j.contains("nodes"));
23✔
569
    assert(j["nodes"].is_array());
23✔
570
    for (const auto& node : j["nodes"]) {
97✔
571
        assert(node.contains("type"));
74✔
572
        assert(node["type"].is_string());
74✔
573
        assert(node.contains("element_id"));
74✔
574
        assert(node["element_id"].is_number_integer());
74✔
575
        std::string type = node["type"];
74✔
576
        if (type == "tasklet") {
74✔
577
            assert(node.contains("code"));
18✔
578
            assert(node["code"].is_number_integer());
18✔
579
            assert(node.contains("inputs"));
18✔
580
            assert(node["inputs"].is_array());
18✔
581
            assert(node.contains("output"));
18✔
582
            assert(node["output"].is_string());
18✔
583
            auto inputs = node["inputs"].get<std::vector<std::string>>();
18✔
584

585
            auto& tasklet =
18✔
586
                builder
36✔
587
                    .add_tasklet(parent, node["code"], node["output"], inputs, json_to_debug_info(node["debug_info"]));
18✔
588
            tasklet.element_id_ = node["element_id"];
18✔
589
            nodes_map.insert({node["element_id"], tasklet});
18✔
590
        } else if (type == "library_node") {
74✔
591
            assert(node.contains("code"));
×
592
            data_flow::LibraryNodeCode code(node["code"].get<std::string>());
×
593

594
            auto serializer_fn = LibraryNodeSerializerRegistry::instance().get_library_node_serializer(code.value());
×
595
            if (serializer_fn == nullptr) {
×
596
                throw std::runtime_error("Unknown library node code: " + std::string(code.value()));
×
597
            }
598
            auto serializer = serializer_fn();
×
599
            auto& lib_node = serializer->deserialize(node, builder, parent);
×
600
            lib_node.implementation_type() =
×
601
                data_flow::ImplementationType(node["implementation_type"].get<std::string>());
×
602
            lib_node.element_id_ = node["element_id"];
×
603
            nodes_map.insert({node["element_id"], lib_node});
×
604
        } else if (type == "access_node") {
56✔
605
            assert(node.contains("data"));
56✔
606
            auto& access_node = builder.add_access(parent, node["data"], json_to_debug_info(node["debug_info"]));
56✔
607
            access_node.element_id_ = node["element_id"];
56✔
608
            nodes_map.insert({node["element_id"], access_node});
56✔
609
        } else if (type == "constant_node") {
56✔
610
            assert(node.contains("data"));
×
611
            assert(node.contains("data_type"));
×
612

613
            auto type = json_to_type(node["data_type"]);
×
614

615
            auto& constant_node =
×
616
                builder.add_constant(parent, node["data"], *type, json_to_debug_info(node["debug_info"]));
×
617
            constant_node.element_id_ = node["element_id"];
×
618
            nodes_map.insert({node["element_id"], constant_node});
×
619
        } else {
×
620
            throw std::runtime_error("Unknown node type");
×
621
        }
622
    }
74✔
623

624
    assert(j.contains("edges"));
23✔
625
    assert(j["edges"].is_array());
23✔
626
    for (const auto& edge : j["edges"]) {
81✔
627
        assert(edge.contains("src"));
58✔
628
        assert(edge["src"].is_number_integer());
58✔
629
        assert(edge.contains("dst"));
58✔
630
        assert(edge["dst"].is_number_integer());
58✔
631
        assert(edge.contains("src_conn"));
58✔
632
        assert(edge["src_conn"].is_string());
58✔
633
        assert(edge.contains("dst_conn"));
58✔
634
        assert(edge["dst_conn"].is_string());
58✔
635
        assert(edge.contains("subset"));
58✔
636
        assert(edge["subset"].is_array());
58✔
637

638
        assert(nodes_map.find(edge["src"]) != nodes_map.end());
58✔
639
        assert(nodes_map.find(edge["dst"]) != nodes_map.end());
58✔
640
        auto& source = nodes_map.at(edge["src"]);
58✔
641
        auto& target = nodes_map.at(edge["dst"]);
58✔
642

643
        auto base_type = json_to_type(edge["base_type"]);
58✔
644

645
        assert(edge.contains("subset"));
58✔
646
        assert(edge["subset"].is_array());
58✔
647
        std::vector<symbolic::Expression> subset;
58✔
648
        for (const auto& subset_ : edge["subset"]) {
104✔
649
            assert(subset_.is_string());
46✔
650
            std::string subset_str = subset_;
46✔
651
            auto expr = symbolic::parse(subset_str);
46✔
652
            subset.push_back(expr);
46✔
653
        }
46✔
654
        auto& memlet = builder.add_memlet(
116✔
655
            parent,
58✔
656
            source,
58✔
657
            edge["src_conn"],
58✔
658
            target,
58✔
659
            edge["dst_conn"],
58✔
660
            subset,
661
            *base_type,
58✔
662
            json_to_debug_info(edge["debug_info"])
58✔
663
        );
664
        memlet.element_id_ = edge["element_id"];
58✔
665
    }
58✔
666
}
23✔
667

668
void JSONSerializer::json_to_sequence(
30✔
669
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Sequence& sequence
670
) {
671
    assert(j.contains("type"));
30✔
672
    assert(j["type"].is_string());
30✔
673
    assert(j.contains("children"));
30✔
674
    assert(j["children"].is_array());
30✔
675
    assert(j.contains("transitions"));
30✔
676
    assert(j["transitions"].is_array());
30✔
677
    assert(j["transitions"].size() == j["children"].size());
30✔
678

679
    sequence.element_id_ = j["element_id"];
30✔
680
    sequence.debug_info_ = json_to_debug_info(j["debug_info"]);
30✔
681

682
    std::string type = j["type"];
30✔
683
    if (type == "sequence") {
30✔
684
        for (size_t i = 0; i < j["children"].size(); i++) {
67✔
685
            auto& child = j["children"][i];
37✔
686
            auto& transition = j["transitions"][i];
37✔
687
            assert(child.contains("type"));
37✔
688
            assert(child["type"].is_string());
37✔
689

690
            assert(transition.contains("type"));
37✔
691
            assert(transition["type"].is_string());
37✔
692
            assert(transition.contains("assignments"));
37✔
693
            assert(transition["assignments"].is_array());
37✔
694
            control_flow::Assignments assignments;
37✔
695
            for (const auto& assignment : transition["assignments"]) {
39✔
696
                assert(assignment.contains("symbol"));
2✔
697
                assert(assignment["symbol"].is_string());
2✔
698
                assert(assignment.contains("expression"));
2✔
699
                assert(assignment["expression"].is_string());
2✔
700
                auto expr = symbolic::parse(assignment["expression"].get<std::string>());
2✔
701
                assignments.insert({symbolic::symbol(assignment["symbol"]), expr});
2✔
702
            }
2✔
703

704
            if (child["type"] == "block") {
37✔
705
                json_to_block_node(child, builder, sequence, assignments);
21✔
706
            } else if (child["type"] == "for") {
37✔
707
                json_to_for_node(child, builder, sequence, assignments);
14✔
708
            } else if (child["type"] == "if_else") {
16✔
709
                json_to_if_else_node(child, builder, sequence, assignments);
×
710
            } else if (child["type"] == "while") {
2✔
711
                json_to_while_node(child, builder, sequence, assignments);
×
712
            } else if (child["type"] == "break") {
2✔
713
                json_to_break_node(child, builder, sequence, assignments);
1✔
714
            } else if (child["type"] == "continue") {
2✔
715
                json_to_continue_node(child, builder, sequence, assignments);
1✔
716
            } else if (child["type"] == "return") {
1✔
717
                json_to_return_node(child, builder, sequence, assignments);
×
718
            } else if (child["type"] == "map") {
×
719
                json_to_map_node(child, builder, sequence, assignments);
×
720
            } else if (child["type"] == "sequence") {
×
721
                auto& subseq = builder.add_sequence(sequence, assignments, json_to_debug_info(child["debug_info"]));
×
722
                json_to_sequence(child, builder, subseq);
×
723
            } else {
×
724
                throw std::runtime_error("Unknown child type");
×
725
            }
726

727
            sequence.at(i).second.debug_info_ = json_to_debug_info(transition["debug_info"]);
37✔
728
            sequence.at(i).second.element_id_ = transition["element_id"];
37✔
729
        }
37✔
730
    } else {
30✔
731
        throw std::runtime_error("expected sequence type");
×
732
    }
733
}
30✔
734

735
void JSONSerializer::json_to_block_node(
22✔
736
    const nlohmann::json& j,
737
    builder::StructuredSDFGBuilder& builder,
738
    structured_control_flow::Sequence& parent,
739
    control_flow::Assignments& assignments
740
) {
741
    assert(j.contains("type"));
22✔
742
    assert(j["type"].is_string());
22✔
743
    assert(j.contains("dataflow"));
22✔
744
    assert(j["dataflow"].is_object());
22✔
745
    auto& block = builder.add_block(parent, assignments, json_to_debug_info(j["debug_info"]));
22✔
746
    block.element_id_ = j["element_id"];
22✔
747
    assert(j["dataflow"].contains("type"));
22✔
748
    assert(j["dataflow"]["type"].is_string());
22✔
749
    std::string type = j["dataflow"]["type"];
22✔
750
    if (type == "dataflow") {
22✔
751
        json_to_dataflow(j["dataflow"], builder, block);
22✔
752
    } else {
22✔
753
        throw std::runtime_error("Unknown dataflow type");
×
754
    }
755
}
22✔
756

757
void JSONSerializer::json_to_for_node(
15✔
758
    const nlohmann::json& j,
759
    builder::StructuredSDFGBuilder& builder,
760
    structured_control_flow::Sequence& parent,
761
    control_flow::Assignments& assignments
762
) {
763
    assert(j.contains("type"));
15✔
764
    assert(j["type"].is_string());
15✔
765
    assert(j.contains("indvar"));
15✔
766
    assert(j["indvar"].is_string());
15✔
767
    assert(j.contains("init"));
15✔
768
    assert(j["init"].is_string());
15✔
769
    assert(j.contains("condition"));
15✔
770
    assert(j["condition"].is_string());
15✔
771
    assert(j.contains("update"));
15✔
772
    assert(j["update"].is_string());
15✔
773
    assert(j.contains("root"));
15✔
774
    assert(j["root"].is_object());
15✔
775

776
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
15✔
777
    auto init = symbolic::parse(j["init"].get<std::string>());
15✔
778
    auto update = symbolic::parse(j["update"].get<std::string>());
15✔
779

780
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
15✔
781
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
15✔
782
    if (condition.is_null()) {
15✔
783
        throw InvalidSDFGException("For loop condition is not a boolean expression");
×
784
    }
785

786
    auto& for_node =
15✔
787
        builder.add_for(parent, indvar, condition, init, update, assignments, json_to_debug_info(j["debug_info"]));
15✔
788
    for_node.element_id_ = j["element_id"];
15✔
789

790
    assert(j["root"].contains("type"));
15✔
791
    assert(j["root"]["type"].is_string());
15✔
792
    assert(j["root"]["type"] == "sequence");
15✔
793
    json_to_sequence(j["root"], builder, for_node.root());
15✔
794
}
15✔
795

796
void JSONSerializer::json_to_if_else_node(
1✔
797
    const nlohmann::json& j,
798
    builder::StructuredSDFGBuilder& builder,
799
    structured_control_flow::Sequence& parent,
800
    control_flow::Assignments& assignments
801
) {
802
    assert(j.contains("type"));
1✔
803
    assert(j["type"].is_string());
1✔
804
    assert(j["type"] == "if_else");
1✔
805
    assert(j.contains("branches"));
1✔
806
    assert(j["branches"].is_array());
1✔
807
    auto& if_else_node = builder.add_if_else(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
808
    if_else_node.element_id_ = j["element_id"];
1✔
809
    for (const auto& branch : j["branches"]) {
3✔
810
        assert(branch.contains("condition"));
2✔
811
        assert(branch["condition"].is_string());
2✔
812
        assert(branch.contains("root"));
2✔
813
        assert(branch["root"].is_object());
2✔
814

815
        auto condition_expr = symbolic::parse(branch["condition"].get<std::string>());
2✔
816
        symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
2✔
817
        if (condition.is_null()) {
2✔
818
            throw InvalidSDFGException("If condition is not a boolean expression");
×
819
        }
820
        auto& branch_node = builder.add_case(if_else_node, condition);
2✔
821
        assert(branch["root"].contains("type"));
2✔
822
        assert(branch["root"]["type"].is_string());
2✔
823
        std::string type = branch["root"]["type"];
2✔
824
        if (type == "sequence") {
2✔
825
            json_to_sequence(branch["root"], builder, branch_node);
2✔
826
        } else {
2✔
827
            throw std::runtime_error("Unknown child type");
×
828
        }
829
    }
2✔
830
}
1✔
831

832
void JSONSerializer::json_to_while_node(
3✔
833
    const nlohmann::json& j,
834
    builder::StructuredSDFGBuilder& builder,
835
    structured_control_flow::Sequence& parent,
836
    control_flow::Assignments& assignments
837
) {
838
    assert(j.contains("type"));
3✔
839
    assert(j["type"].is_string());
3✔
840
    assert(j["type"] == "while");
3✔
841
    assert(j.contains("root"));
3✔
842
    assert(j["root"].is_object());
3✔
843

844
    auto& while_node = builder.add_while(parent, assignments, json_to_debug_info(j["debug_info"]));
3✔
845
    while_node.element_id_ = j["element_id"];
3✔
846

847
    assert(j["root"]["type"] == "sequence");
3✔
848
    json_to_sequence(j["root"], builder, while_node.root());
3✔
849
}
3✔
850

851
void JSONSerializer::json_to_break_node(
1✔
852
    const nlohmann::json& j,
853
    builder::StructuredSDFGBuilder& builder,
854
    structured_control_flow::Sequence& parent,
855
    control_flow::Assignments& assignments
856
) {
857
    assert(j.contains("type"));
1✔
858
    assert(j["type"].is_string());
1✔
859
    assert(j["type"] == "break");
1✔
860
    auto& node = builder.add_break(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
861
    node.element_id_ = j["element_id"];
1✔
862
}
1✔
863

864
void JSONSerializer::json_to_continue_node(
1✔
865
    const nlohmann::json& j,
866
    builder::StructuredSDFGBuilder& builder,
867
    structured_control_flow::Sequence& parent,
868
    control_flow::Assignments& assignments
869
) {
870
    assert(j.contains("type"));
1✔
871
    assert(j["type"].is_string());
1✔
872
    assert(j["type"] == "continue");
1✔
873
    auto& node = builder.add_continue(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
874
    node.element_id_ = j["element_id"];
1✔
875
}
1✔
876

877
void JSONSerializer::json_to_map_node(
1✔
878
    const nlohmann::json& j,
879
    builder::StructuredSDFGBuilder& builder,
880
    structured_control_flow::Sequence& parent,
881
    control_flow::Assignments& assignments
882
) {
883
    assert(j.contains("type"));
1✔
884
    assert(j["type"].is_string());
1✔
885
    assert(j["type"] == "map");
1✔
886
    assert(j.contains("indvar"));
1✔
887
    assert(j["indvar"].is_string());
1✔
888
    assert(j.contains("init"));
1✔
889
    assert(j["init"].is_string());
1✔
890
    assert(j.contains("condition"));
1✔
891
    assert(j["condition"].is_string());
1✔
892
    assert(j.contains("update"));
1✔
893
    assert(j["update"].is_string());
1✔
894
    assert(j.contains("root"));
1✔
895
    assert(j["root"].is_object());
1✔
896
    assert(j.contains("schedule_type"));
1✔
897
    assert(j["schedule_type"].is_object());
1✔
898

899
    structured_control_flow::ScheduleType schedule_type = json_to_schedule_type(j["schedule_type"]);
1✔
900

901
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
1✔
902
    auto init = symbolic::parse(j["init"].get<std::string>());
1✔
903
    auto update = symbolic::parse(j["update"].get<std::string>());
1✔
904
    auto condition_expr = symbolic::parse(j["condition"].get<std::string>());
1✔
905
    symbolic::Condition condition = SymEngine::rcp_dynamic_cast<const SymEngine::Boolean>(condition_expr);
1✔
906
    if (condition.is_null()) {
1✔
907
        throw InvalidSDFGException("Map condition is not a boolean expression");
×
908
    }
909

910
    auto& map_node = builder.add_map(
2✔
911
        parent, indvar, condition, init, update, schedule_type, assignments, json_to_debug_info(j["debug_info"])
1✔
912
    );
913
    map_node.element_id_ = j["element_id"];
1✔
914

915
    assert(j["root"].contains("type"));
1✔
916
    assert(j["root"]["type"].is_string());
1✔
917
    assert(j["root"]["type"] == "sequence");
1✔
918
    json_to_sequence(j["root"], builder, map_node.root());
1✔
919
}
1✔
920

921
void JSONSerializer::json_to_return_node(
1✔
922
    const nlohmann::json& j,
923
    builder::StructuredSDFGBuilder& builder,
924
    structured_control_flow::Sequence& parent,
925
    control_flow::Assignments& assignments
926
) {
927
    assert(j.contains("type"));
1✔
928
    assert(j["type"].is_string());
1✔
929
    assert(j["type"] == "return");
1✔
930

931
    std::string data = j["data"];
1✔
932
    std::unique_ptr<types::IType> data_type = nullptr;
1✔
933
    if (j.contains("data_type")) {
1✔
934
        data_type = json_to_type(j["data_type"]);
×
935
    }
×
936

937
    if (data_type == nullptr) {
1✔
938
        auto& node = builder.add_return(parent, data, assignments, json_to_debug_info(j["debug_info"]));
1✔
939
        node.element_id_ = j["element_id"];
1✔
940
    } else {
1✔
941
        auto& node =
×
942
            builder.add_constant_return(parent, data, *data_type, assignments, json_to_debug_info(j["debug_info"]));
×
943
        node.element_id_ = j["element_id"];
×
944
    }
945
}
1✔
946

947
std::unique_ptr<types::IType> JSONSerializer::json_to_type(const nlohmann::json& j) {
198✔
948
    if (j.contains("type")) {
198✔
949
        if (j["type"] == "scalar") {
198✔
950
            // Deserialize scalar type
951
            assert(j.contains("primitive_type"));
125✔
952
            types::PrimitiveType primitive_type = j["primitive_type"];
125✔
953
            assert(j.contains("storage_type"));
125✔
954
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
125✔
955
            assert(j.contains("initializer"));
125✔
956
            std::string initializer = j["initializer"];
125✔
957
            assert(j.contains("alignment"));
125✔
958
            size_t alignment = j["alignment"];
125✔
959
            return std::make_unique<types::Scalar>(storage_type, alignment, initializer, primitive_type);
125✔
960
        } else if (j["type"] == "array") {
198✔
961
            // Deserialize array type
962
            assert(j.contains("element_type"));
54✔
963
            std::unique_ptr<types::IType> member_type = json_to_type(j["element_type"]);
54✔
964
            assert(j.contains("num_elements"));
54✔
965
            std::string num_elements_str = j["num_elements"];
54✔
966
            // Convert num_elements_str to symbolic::Expression
967
            auto num_elements = symbolic::parse(num_elements_str);
54✔
968
            assert(j.contains("storage_type"));
54✔
969
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
54✔
970
            assert(j.contains("initializer"));
54✔
971
            std::string initializer = j["initializer"];
54✔
972
            assert(j.contains("alignment"));
54✔
973
            size_t alignment = j["alignment"];
54✔
974
            return std::make_unique<types::Array>(storage_type, alignment, initializer, *member_type, num_elements);
54✔
975
        } else if (j["type"] == "pointer") {
73✔
976
            // Deserialize pointer type
977
            std::optional<std::unique_ptr<types::IType>> pointee_type;
16✔
978
            if (j.contains("pointee_type")) {
16✔
979
                assert(j.contains("pointee_type"));
15✔
980
                pointee_type = json_to_type(j["pointee_type"]);
15✔
981
            } else {
15✔
982
                pointee_type = std::nullopt;
1✔
983
            }
984
            assert(j.contains("storage_type"));
16✔
985
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
16✔
986
            assert(j.contains("initializer"));
16✔
987
            std::string initializer = j["initializer"];
16✔
988
            assert(j.contains("alignment"));
16✔
989
            size_t alignment = j["alignment"];
16✔
990
            if (pointee_type.has_value()) {
16✔
991
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer, *pointee_type.value());
15✔
992
            } else {
993
                return std::make_unique<types::Pointer>(storage_type, alignment, initializer);
1✔
994
            }
995
        } else if (j["type"] == "structure") {
19✔
996
            // Deserialize structure type
997
            assert(j.contains("name"));
2✔
998
            std::string name = j["name"];
2✔
999
            assert(j.contains("storage_type"));
2✔
1000
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
2✔
1001
            assert(j.contains("initializer"));
2✔
1002
            std::string initializer = j["initializer"];
2✔
1003
            assert(j.contains("alignment"));
2✔
1004
            size_t alignment = j["alignment"];
2✔
1005
            return std::make_unique<types::Structure>(storage_type, alignment, initializer, name);
2✔
1006
        } else if (j["type"] == "function") {
3✔
1007
            // Deserialize function type
1008
            assert(j.contains("return_type"));
1✔
1009
            std::unique_ptr<types::IType> return_type = json_to_type(j["return_type"]);
1✔
1010
            assert(j.contains("params"));
1✔
1011
            std::vector<std::unique_ptr<types::IType>> params;
1✔
1012
            for (const auto& param : j["params"]) {
3✔
1013
                params.push_back(json_to_type(param));
2✔
1014
            }
1015
            assert(j.contains("is_var_arg"));
1✔
1016
            bool is_var_arg = j["is_var_arg"];
1✔
1017
            assert(j.contains("storage_type"));
1✔
1018
            types::StorageType storage_type = json_to_storage_type(j["storage_type"]);
1✔
1019
            assert(j.contains("initializer"));
1✔
1020
            std::string initializer = j["initializer"];
1✔
1021
            assert(j.contains("alignment"));
1✔
1022
            size_t alignment = j["alignment"];
1✔
1023
            auto function =
1024
                std::make_unique<types::Function>(storage_type, alignment, initializer, *return_type, is_var_arg);
1✔
1025
            for (const auto& param : params) {
3✔
1026
                function->add_param(*param);
2✔
1027
            }
1028
            return function->clone();
1✔
1029

1030
        } else {
1✔
1031
            throw std::runtime_error("Unknown type");
×
1032
        }
1033
    } else {
1034
        throw std::runtime_error("Type not found");
×
1035
    }
1036
}
198✔
1037

1038
DebugInfo JSONSerializer::json_to_debug_info(const nlohmann::json& j) {
244✔
1039
    assert(j.contains("has"));
244✔
1040
    assert(j["has"].is_boolean());
244✔
1041
    if (!j["has"]) {
244✔
1042
        return DebugInfo();
244✔
1043
    }
1044
    assert(j.contains("filename"));
×
1045
    assert(j["filename"].is_string());
×
1046
    std::string filename = j["filename"];
×
1047
    assert(j.contains("function"));
×
1048
    assert(j["function"].is_string());
×
1049
    std::string function = j["function"];
×
1050
    assert(j.contains("start_line"));
×
1051
    assert(j["start_line"].is_number_integer());
×
1052
    size_t start_line = j["start_line"];
×
1053
    assert(j.contains("start_column"));
×
1054
    assert(j["start_column"].is_number_integer());
×
1055
    size_t start_column = j["start_column"];
×
1056
    assert(j.contains("end_line"));
×
1057
    assert(j["end_line"].is_number_integer());
×
1058
    size_t end_line = j["end_line"];
×
1059
    assert(j.contains("end_column"));
×
1060
    assert(j["end_column"].is_number_integer());
×
1061
    size_t end_column = j["end_column"];
×
1062
    return DebugInfo(filename, function, start_line, start_column, end_line, end_column);
×
1063
}
244✔
1064

1065
ScheduleType JSONSerializer::json_to_schedule_type(const nlohmann::json& j) {
2✔
1066
    assert(j.contains("value"));
2✔
1067
    assert(j["value"].is_string());
2✔
1068
    assert(j.contains("properties"));
2✔
1069
    assert(j["properties"].is_object());
2✔
1070
    ScheduleType schedule_type(j["value"].get<std::string>());
2✔
1071
    for (const auto& [key, value] : j["properties"].items()) {
4✔
1072
        assert(value.is_string());
1✔
1073
        schedule_type.set_property(key, value.get<std::string>());
1✔
1074
    }
1075
    return schedule_type;
2✔
1076
}
2✔
1077

1078
types::StorageType JSONSerializer::json_to_storage_type(const nlohmann::json& j) {
198✔
1079
    if (!j.contains("value")) {
198✔
1080
        return types::StorageType::CPU_Stack();
×
1081
    }
1082
    std::string value = j["value"].get<std::string>();
198✔
1083

1084
    symbolic::Expression allocation_size = SymEngine::null;
198✔
1085
    if (j.contains("allocation_size")) {
198✔
1086
        allocation_size = symbolic::parse(j["allocation_size"].get<std::string>());
×
1087
    }
×
1088

1089
    types::StorageType::AllocationType allocation = j["allocation"];
198✔
1090
    types::StorageType::AllocationType deallocation = j["deallocation"];
198✔
1091

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

1094
    if (j.contains("args")) {
198✔
NEW
1095
        nlohmann::json::array_t args = j["args"];
×
NEW
1096
        if (args.size() > 0) {
×
NEW
1097
            storageType.arg1(symbolic::parse(args[0].get<std::string>()));
×
NEW
1098
        }
×
NEW
1099
    }
×
1100
    return storageType;
198✔
1101
}
198✔
1102

1103
std::string JSONSerializer::expression(const symbolic::Expression expr) {
187✔
1104
    JSONSymbolicPrinter printer;
187✔
1105
    return printer.apply(expr);
187✔
1106
};
187✔
1107

1108
void JSONSymbolicPrinter::bvisit(const SymEngine::Equality& x) {
×
1109
    str_ = apply(x.get_args()[0]) + " == " + apply(x.get_args()[1]);
×
1110
    str_ = parenthesize(str_);
×
1111
};
×
1112

1113
void JSONSymbolicPrinter::bvisit(const SymEngine::Unequality& x) {
×
1114
    str_ = apply(x.get_args()[0]) + " != " + apply(x.get_args()[1]);
×
1115
    str_ = parenthesize(str_);
×
1116
};
×
1117

1118
void JSONSymbolicPrinter::bvisit(const SymEngine::LessThan& x) {
×
1119
    str_ = apply(x.get_args()[0]) + " <= " + apply(x.get_args()[1]);
×
1120
    str_ = parenthesize(str_);
×
1121
};
×
1122

1123
void JSONSymbolicPrinter::bvisit(const SymEngine::StrictLessThan& x) {
18✔
1124
    str_ = apply(x.get_args()[0]) + " < " + apply(x.get_args()[1]);
18✔
1125
    str_ = parenthesize(str_);
18✔
1126
};
18✔
1127

1128
void JSONSymbolicPrinter::bvisit(const SymEngine::Min& x) {
×
1129
    std::ostringstream s;
×
1130
    auto container = x.get_args();
×
1131
    if (container.size() == 1) {
×
1132
        s << apply(*container.begin());
×
1133
    } else {
×
1134
        s << "min(";
×
1135
        s << apply(*container.begin());
×
1136

1137
        // Recursively apply __daisy_min to the arguments
1138
        SymEngine::vec_basic subargs;
×
1139
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1140
            subargs.push_back(*it);
×
1141
        }
×
1142
        auto submin = SymEngine::min(subargs);
×
1143
        s << ", " << apply(submin);
×
1144

1145
        s << ")";
×
1146
    }
×
1147

1148
    str_ = s.str();
×
1149
};
×
1150

1151
void JSONSymbolicPrinter::bvisit(const SymEngine::Max& x) {
×
1152
    std::ostringstream s;
×
1153
    auto container = x.get_args();
×
1154
    if (container.size() == 1) {
×
1155
        s << apply(*container.begin());
×
1156
    } else {
×
1157
        s << "max(";
×
1158
        s << apply(*container.begin());
×
1159

1160
        // Recursively apply __daisy_max to the arguments
1161
        SymEngine::vec_basic subargs;
×
1162
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1163
            subargs.push_back(*it);
×
1164
        }
×
1165
        auto submax = SymEngine::max(subargs);
×
1166
        s << ", " << apply(submax);
×
1167

1168
        s << ")";
×
1169
    }
×
1170

1171
    str_ = s.str();
×
1172
};
×
1173

1174
void LibraryNodeSerializerRegistry::
1175
    register_library_node_serializer(std::string library_node_code, LibraryNodeSerializerFn fn) {
60✔
1176
    std::lock_guard<std::mutex> lock(mutex_);
60✔
1177
    if (factory_map_.find(library_node_code) != factory_map_.end()) {
60✔
1178
        throw std::runtime_error(
×
1179
            "Library node serializer already registered for library node code: " + std::string(library_node_code)
×
1180
        );
1181
    }
1182
    factory_map_[library_node_code] = std::move(fn);
60✔
1183
}
60✔
1184

1185
LibraryNodeSerializerFn LibraryNodeSerializerRegistry::get_library_node_serializer(std::string library_node_code) {
1✔
1186
    auto it = factory_map_.find(library_node_code);
1✔
1187
    if (it != factory_map_.end()) {
1✔
1188
        return it->second;
1✔
1189
    }
1190
    return nullptr;
×
1191
}
1✔
1192

1193
size_t LibraryNodeSerializerRegistry::size() const { return factory_map_.size(); }
×
1194

1195
void register_default_serializers() {
2✔
1196
    // stdlib
1197
    LibraryNodeSerializerRegistry::instance()
2✔
1198
        .register_library_node_serializer(stdlib::LibraryNodeType_Alloca.value(), []() {
2✔
1199
            return std::make_unique<stdlib::AllocaNodeSerializer>();
×
1200
        });
1201
    LibraryNodeSerializerRegistry::instance()
2✔
1202
        .register_library_node_serializer(stdlib::LibraryNodeType_Calloc.value(), []() {
2✔
1203
            return std::make_unique<stdlib::CallocNodeSerializer>();
×
1204
        });
1205
    LibraryNodeSerializerRegistry::instance()
2✔
1206
        .register_library_node_serializer(stdlib::LibraryNodeType_Free.value(), []() {
2✔
1207
            return std::make_unique<stdlib::FreeNodeSerializer>();
×
1208
        });
1209
    LibraryNodeSerializerRegistry::instance()
2✔
1210
        .register_library_node_serializer(stdlib::LibraryNodeType_Malloc.value(), []() {
2✔
1211
            return std::make_unique<stdlib::MallocNodeSerializer>();
×
1212
        });
1213
    LibraryNodeSerializerRegistry::instance()
2✔
1214
        .register_library_node_serializer(stdlib::LibraryNodeType_Memcpy.value(), []() {
2✔
1215
            return std::make_unique<stdlib::MemcpyNodeSerializer>();
×
1216
        });
1217
    LibraryNodeSerializerRegistry::instance()
2✔
1218
        .register_library_node_serializer(stdlib::LibraryNodeType_Memmove.value(), []() {
2✔
1219
            return std::make_unique<stdlib::MemmoveNodeSerializer>();
×
1220
        });
1221
    LibraryNodeSerializerRegistry::instance()
2✔
1222
        .register_library_node_serializer(stdlib::LibraryNodeType_Memset.value(), []() {
2✔
1223
            return std::make_unique<stdlib::MemsetNodeSerializer>();
×
1224
        });
1225
    LibraryNodeSerializerRegistry::instance()
2✔
1226
        .register_library_node_serializer(stdlib::LibraryNodeType_Trap.value(), []() {
2✔
1227
            return std::make_unique<stdlib::TrapNodeSerializer>();
×
1228
        });
1229
    LibraryNodeSerializerRegistry::instance()
2✔
1230
        .register_library_node_serializer(stdlib::LibraryNodeType_Unreachable.value(), []() {
2✔
1231
            return std::make_unique<stdlib::UnreachableNodeSerializer>();
×
1232
        });
1233

1234
    // Metadata
1235
    LibraryNodeSerializerRegistry::instance()
2✔
1236
        .register_library_node_serializer(data_flow::LibraryNodeType_Metadata.value(), []() {
2✔
1237
            return std::make_unique<data_flow::MetadataNodeSerializer>();
×
1238
        });
1239

1240
    // Barrier
1241
    LibraryNodeSerializerRegistry::instance()
2✔
1242
        .register_library_node_serializer(data_flow::LibraryNodeType_BarrierLocal.value(), []() {
3✔
1243
            return std::make_unique<data_flow::BarrierLocalNodeSerializer>();
1✔
1244
        });
1245

1246
    // Call Node
1247
    LibraryNodeSerializerRegistry::instance()
2✔
1248
        .register_library_node_serializer(data_flow::LibraryNodeType_Call.value(), []() {
2✔
1249
            return std::make_unique<data_flow::CallNodeSerializer>();
×
1250
        });
1251
    LibraryNodeSerializerRegistry::instance()
2✔
1252
        .register_library_node_serializer(data_flow::LibraryNodeType_Invoke.value(), []() {
2✔
1253
            return std::make_unique<data_flow::InvokeNodeSerializer>();
×
1254
        });
1255

1256
    // Intrinsic
1257
    LibraryNodeSerializerRegistry::instance()
2✔
1258
        .register_library_node_serializer(math::LibraryNodeType_Intrinsic.value(), []() {
2✔
1259
            return std::make_unique<math::IntrinsicNodeSerializer>();
×
1260
        });
1261

1262
    // BLAS
1263
    LibraryNodeSerializerRegistry::instance()
2✔
1264
        .register_library_node_serializer(math::blas::LibraryNodeType_DOT.value(), []() {
2✔
1265
            return std::make_unique<math::blas::DotNodeSerializer>();
×
1266
        });
1267
    LibraryNodeSerializerRegistry::instance()
2✔
1268
        .register_library_node_serializer(math::blas::LibraryNodeType_GEMM.value(), []() {
2✔
1269
            return std::make_unique<math::blas::GEMMNodeSerializer>();
×
1270
        });
1271

1272
    // ML
1273
    LibraryNodeSerializerRegistry::instance()
2✔
1274
        .register_library_node_serializer(math::ml::LibraryNodeType_Abs.value(), []() {
2✔
1275
            return std::make_unique<math::ml::AbsNodeSerializer>();
×
1276
        });
1277
    LibraryNodeSerializerRegistry::instance()
2✔
1278
        .register_library_node_serializer(math::ml::LibraryNodeType_Add.value(), []() {
2✔
1279
            return std::make_unique<math::ml::AddNodeSerializer>();
×
1280
        });
1281
    LibraryNodeSerializerRegistry::instance()
2✔
1282
        .register_library_node_serializer(math::ml::LibraryNodeType_Div.value(), []() {
2✔
1283
            return std::make_unique<math::ml::DivNodeSerializer>();
×
1284
        });
1285
    LibraryNodeSerializerRegistry::instance()
2✔
1286
        .register_library_node_serializer(math::ml::LibraryNodeType_Elu.value(), []() {
2✔
1287
            return std::make_unique<math::ml::EluNodeSerializer>();
×
1288
        });
1289
    LibraryNodeSerializerRegistry::instance()
2✔
1290
        .register_library_node_serializer(math::ml::LibraryNodeType_Erf.value(), []() {
2✔
1291
            return std::make_unique<math::ml::ErfNodeSerializer>();
×
1292
        });
1293
    LibraryNodeSerializerRegistry::instance()
2✔
1294
        .register_library_node_serializer(math::ml::LibraryNodeType_HardSigmoid.value(), []() {
2✔
1295
            return std::make_unique<math::ml::HardSigmoidNodeSerializer>();
×
1296
        });
1297
    LibraryNodeSerializerRegistry::instance()
2✔
1298
        .register_library_node_serializer(math::ml::LibraryNodeType_LeakyReLU.value(), []() {
2✔
1299
            return std::make_unique<math::ml::LeakyReLUNodeSerializer>();
×
1300
        });
1301
    LibraryNodeSerializerRegistry::instance()
2✔
1302
        .register_library_node_serializer(math::ml::LibraryNodeType_Mul.value(), []() {
2✔
1303
            return std::make_unique<math::ml::MulNodeSerializer>();
×
1304
        });
1305
    LibraryNodeSerializerRegistry::instance()
2✔
1306
        .register_library_node_serializer(math::ml::LibraryNodeType_Pow.value(), []() {
2✔
1307
            return std::make_unique<math::ml::PowNodeSerializer>();
×
1308
        });
1309
    LibraryNodeSerializerRegistry::instance()
2✔
1310
        .register_library_node_serializer(math::ml::LibraryNodeType_ReLU.value(), []() {
2✔
1311
            return std::make_unique<math::ml::ReLUNodeSerializer>();
×
1312
        });
1313
    LibraryNodeSerializerRegistry::instance()
2✔
1314
        .register_library_node_serializer(math::ml::LibraryNodeType_Sigmoid.value(), []() {
2✔
1315
            return std::make_unique<math::ml::SigmoidNodeSerializer>();
×
1316
        });
1317
    LibraryNodeSerializerRegistry::instance()
2✔
1318
        .register_library_node_serializer(math::ml::LibraryNodeType_Sqrt.value(), []() {
2✔
1319
            return std::make_unique<math::ml::SqrtNodeSerializer>();
×
1320
        });
1321
    LibraryNodeSerializerRegistry::instance()
2✔
1322
        .register_library_node_serializer(math::ml::LibraryNodeType_Sub.value(), []() {
2✔
1323
            return std::make_unique<math::ml::SubNodeSerializer>();
×
1324
        });
1325
    LibraryNodeSerializerRegistry::instance()
2✔
1326
        .register_library_node_serializer(math::ml::LibraryNodeType_Tanh.value(), []() {
2✔
1327
            return std::make_unique<math::ml::TanhNodeSerializer>();
×
1328
        });
1329
}
2✔
1330

1331
} // namespace serializer
1332
} // 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