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

daisytuner / sdfglib / 15518226219

08 Jun 2025 12:03PM UTC coverage: 61.652% (-0.8%) from 62.447%
15518226219

push

github

web-flow
Merge pull request #65 from daisytuner/lib-nodes-plugins

Adds registry for library node dispatchers

41 of 77 new or added lines in 5 files covered. (53.25%)

124 existing lines in 10 files now uncovered.

7249 of 11758 relevant lines covered (61.65%)

125.57 hits per line

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

82.35
/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/builder/structured_sdfg_builder.h"
10
#include "sdfg/data_flow/library_node.h"
11
#include "sdfg/element.h"
12
#include "sdfg/structured_control_flow/block.h"
13
#include "sdfg/structured_control_flow/for.h"
14
#include "sdfg/structured_control_flow/if_else.h"
15
#include "sdfg/structured_control_flow/return.h"
16
#include "sdfg/structured_control_flow/sequence.h"
17
#include "sdfg/structured_control_flow/while.h"
18
#include "sdfg/structured_sdfg.h"
19
#include "sdfg/symbolic/symbolic.h"
20
#include "sdfg/types/function.h"
21
#include "sdfg/types/scalar.h"
22
#include "sdfg/types/type.h"
23
#include "symengine/expression.h"
24
#include "symengine/logic.h"
25
#include "symengine/symengine_rcp.h"
26

27
namespace sdfg {
28
namespace serializer {
29

30
/*
31
 * * JSONSerializer class
32
 * * Serialization logic
33
 */
34

35
nlohmann::json JSONSerializer::serialize(std::unique_ptr<sdfg::StructuredSDFG>& sdfg) {
3✔
36
    nlohmann::json j;
3✔
37

38
    j["name"] = sdfg->name();
3✔
39
    j["type"] = std::string(sdfg->type().value());
3✔
40

41
    j["structures"] = nlohmann::json::array();
3✔
42
    for (const auto& structure_name : sdfg->structures()) {
3✔
43
        const auto& structure = sdfg->structure(structure_name);
×
44
        nlohmann::json structure_json;
×
45
        structure_definition_to_json(structure_json, structure);
×
46
        j["structures"].push_back(structure_json);
×
47
    }
×
48

49
    j["containers"] = nlohmann::json::object();
3✔
50
    for (const auto& container : sdfg->containers()) {
8✔
51
        nlohmann::json desc;
5✔
52
        type_to_json(desc, sdfg->type(container));
5✔
53
        j["containers"][container] = desc;
5✔
54
    }
5✔
55

56
    j["arguments"] = nlohmann::json::array();
3✔
57
    for (const auto& argument : sdfg->arguments()) {
5✔
58
        j["arguments"].push_back(argument);
2✔
59
    }
60

61
    j["externals"] = nlohmann::json::array();
3✔
62
    for (const auto& external : sdfg->externals()) {
3✔
63
        j["externals"].push_back(external);
×
64
    }
65

66
    j["metadata"] = nlohmann::json::object();
3✔
67
    for (const auto& entry : sdfg->metadata()) {
4✔
68
        j["metadata"][entry.first] = entry.second;
1✔
69
    }
70

71
    // Walk the SDFG
72
    nlohmann::json root_json;
3✔
73
    sequence_to_json(root_json, sdfg->root());
3✔
74
    j["root"] = root_json;
3✔
75

76
    return j;
3✔
77
}
3✔
78

79
void JSONSerializer::dataflow_to_json(nlohmann::json& j, const data_flow::DataFlowGraph& dataflow) {
20✔
80
    j["type"] = "dataflow";
20✔
81
    j["nodes"] = nlohmann::json::array();
20✔
82
    j["edges"] = nlohmann::json::array();
20✔
83

84
    for (auto& node : dataflow.nodes()) {
40✔
85
        nlohmann::json node_json;
20✔
86
        node_json["element_id"] = node.element_id();
20✔
87

88
        node_json["debug_info"] = nlohmann::json::object();
20✔
89
        debug_info_to_json(node_json["debug_info"], node.debug_info());
20✔
90

91
        if (auto tasklet = dynamic_cast<const data_flow::Tasklet*>(&node)) {
20✔
92
            node_json["type"] = "tasklet";
5✔
93
            node_json["code"] = tasklet->code();
5✔
94
            node_json["inputs"] = nlohmann::json::array();
5✔
95
            for (auto& input : tasklet->inputs()) {
15✔
96
                nlohmann::json input_json;
10✔
97
                nlohmann::json type_json;
10✔
98
                type_to_json(type_json, input.second);
10✔
99
                input_json["type"] = type_json;
10✔
100
                input_json["name"] = input.first;
10✔
101
                node_json["inputs"].push_back(input_json);
10✔
102
            }
10✔
103
            node_json["output"] = nlohmann::json::object();
5✔
104
            node_json["output"]["name"] = tasklet->output().first;
5✔
105
            nlohmann::json type_json;
5✔
106
            type_to_json(type_json, tasklet->output().second);
5✔
107
            node_json["output"]["type"] = type_json;
5✔
108
            // node_json["conditional"] = tasklet->is_conditional();
109
            // if (tasklet->is_conditional()) {
110
            //     node_json["condition"] = dumps_expression(tasklet->condition());
111
            // }
112
        } else if (auto lib_node = dynamic_cast<const data_flow::LibraryNode*>(&node)) {
20✔
113
            node_json["type"] = "library_node";
×
NEW
114
            node_json["code"] = std::string(lib_node->code().value());
×
115
            node_json["side_effect"] = lib_node->side_effect();
×
116
            node_json["inputs"] = nlohmann::json::array();
×
117
            for (auto& input : lib_node->inputs()) {
×
118
                node_json["inputs"].push_back(input);
×
119
            }
120
            node_json["outputs"] = nlohmann::json::array();
×
121
            for (auto& output : lib_node->outputs()) {
×
122
                node_json["outputs"].push_back(output);
×
123
            }
124
        } else if (auto code_node = dynamic_cast<const data_flow::AccessNode*>(&node)) {
15✔
125
            node_json["type"] = "access_node";
15✔
126
            node_json["data"] = code_node->data();
15✔
127
        } else {
15✔
128
            throw std::runtime_error("Unknown node type");
×
129
        }
130

131
        j["nodes"].push_back(node_json);
20✔
132
    }
20✔
133

134
    for (auto& edge : dataflow.edges()) {
35✔
135
        nlohmann::json edge_json;
15✔
136
        edge_json["element_id"] = edge.element_id();
15✔
137

138
        edge_json["debug_info"] = nlohmann::json::object();
15✔
139
        debug_info_to_json(edge_json["debug_info"], edge.debug_info());
15✔
140

141
        edge_json["src"] = edge.src().element_id();
15✔
142
        edge_json["dst"] = edge.dst().element_id();
15✔
143

144
        edge_json["src_conn"] = edge.src_conn();
15✔
145
        edge_json["dst_conn"] = edge.dst_conn();
15✔
146

147
        edge_json["subset"] = nlohmann::json::array();
15✔
148
        for (auto& subset : edge.subset()) {
21✔
149
            edge_json["subset"].push_back(expression(subset));
6✔
150
        }
151

152
        j["edges"].push_back(edge_json);
15✔
153
    }
15✔
154
}
20✔
155

156
void JSONSerializer::block_to_json(nlohmann::json& j, const structured_control_flow::Block& block) {
18✔
157
    j["type"] = "block";
18✔
158
    j["element_id"] = block.element_id();
18✔
159

160
    j["debug_info"] = nlohmann::json::object();
18✔
161
    debug_info_to_json(j["debug_info"], block.debug_info());
18✔
162

163
    nlohmann::json dataflow_json;
18✔
164
    dataflow_to_json(dataflow_json, block.dataflow());
18✔
165
    j["dataflow"] = dataflow_json;
18✔
166
}
18✔
167

168
void JSONSerializer::for_to_json(nlohmann::json& j, const structured_control_flow::For& for_node) {
2✔
169
    j["type"] = "for";
2✔
170
    j["element_id"] = for_node.element_id();
2✔
171

172
    j["debug_info"] = nlohmann::json::object();
2✔
173
    debug_info_to_json(j["debug_info"], for_node.debug_info());
2✔
174

175
    j["indvar"] = expression(for_node.indvar());
2✔
176
    j["init"] = expression(for_node.init());
2✔
177
    j["condition"] = expression(for_node.condition());
2✔
178
    j["update"] = expression(for_node.update());
2✔
179

180
    nlohmann::json body_json;
2✔
181
    sequence_to_json(body_json, for_node.root());
2✔
182
    j["root"] = body_json;
2✔
183
}
2✔
184

185
void JSONSerializer::if_else_to_json(nlohmann::json& j,
2✔
186
                                     const structured_control_flow::IfElse& if_else_node) {
187
    j["type"] = "if_else";
2✔
188
    j["element_id"] = if_else_node.element_id();
2✔
189

190
    j["debug_info"] = nlohmann::json::object();
2✔
191
    debug_info_to_json(j["debug_info"], if_else_node.debug_info());
2✔
192

193
    j["branches"] = nlohmann::json::array();
2✔
194
    for (size_t i = 0; i < if_else_node.size(); i++) {
6✔
195
        nlohmann::json branch_json;
4✔
196
        branch_json["condition"] = expression(if_else_node.at(i).second);
4✔
197
        nlohmann::json body_json;
4✔
198
        sequence_to_json(body_json, if_else_node.at(i).first);
4✔
199
        branch_json["root"] = body_json;
4✔
200
        j["branches"].push_back(branch_json);
4✔
201
    }
4✔
202
}
2✔
203

204
void JSONSerializer::while_node_to_json(nlohmann::json& j,
5✔
205
                                        const structured_control_flow::While& while_node) {
206
    j["type"] = "while";
5✔
207
    j["element_id"] = while_node.element_id();
5✔
208

209
    j["debug_info"] = nlohmann::json::object();
5✔
210
    debug_info_to_json(j["debug_info"], while_node.debug_info());
5✔
211

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

217
void JSONSerializer::break_node_to_json(nlohmann::json& j,
2✔
218
                                        const structured_control_flow::Break& break_node) {
219
    j["type"] = "break";
2✔
220
    j["element_id"] = break_node.element_id();
2✔
221

222
    j["debug_info"] = nlohmann::json::object();
2✔
223
    debug_info_to_json(j["debug_info"], break_node.debug_info());
2✔
224
}
2✔
225

226
void JSONSerializer::continue_node_to_json(nlohmann::json& j,
2✔
227
                                           const structured_control_flow::Continue& continue_node) {
228
    j["type"] = "continue";
2✔
229
    j["element_id"] = continue_node.element_id();
2✔
230

231
    j["debug_info"] = nlohmann::json::object();
2✔
232
    debug_info_to_json(j["debug_info"], continue_node.debug_info());
2✔
233
}
2✔
234

235
void JSONSerializer::map_to_json(nlohmann::json& j, const structured_control_flow::Map& map_node) {
2✔
236
    j["type"] = "map";
2✔
237
    j["element_id"] = map_node.element_id();
2✔
238

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

242
    j["indvar"] = expression(map_node.indvar());
2✔
243
    j["num_iterations"] = expression(map_node.num_iterations());
2✔
244
    j["schedule_type"] = std::string(map_node.schedule_type().value());
2✔
245

246
    nlohmann::json body_json;
2✔
247
    sequence_to_json(body_json, map_node.root());
2✔
248
    j["root"] = body_json;
2✔
249
}
2✔
250

251
void JSONSerializer::return_node_to_json(nlohmann::json& j,
2✔
252
                                         const structured_control_flow::Return& return_node) {
253
    j["type"] = "return";
2✔
254
    j["element_id"] = return_node.element_id();
2✔
255

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

260
void JSONSerializer::sequence_to_json(nlohmann::json& j,
19✔
261
                                      const structured_control_flow::Sequence& sequence) {
262
    j["type"] = "sequence";
19✔
263
    j["element_id"] = sequence.element_id();
19✔
264

265
    j["debug_info"] = nlohmann::json::object();
19✔
266
    debug_info_to_json(j["debug_info"], sequence.debug_info());
19✔
267

268
    j["children"] = nlohmann::json::array();
19✔
269
    j["transitions"] = nlohmann::json::array();
19✔
270

271
    for (size_t i = 0; i < sequence.size(); i++) {
39✔
272
        nlohmann::json child_json;
20✔
273
        auto& child = sequence.at(i).first;
20✔
274
        auto& transition = sequence.at(i).second;
20✔
275

276
        if (auto block = dynamic_cast<const structured_control_flow::Block*>(&child)) {
20✔
277
            block_to_json(child_json, *block);
16✔
278
        } else if (auto for_node = dynamic_cast<const structured_control_flow::For*>(&child)) {
20✔
279
            for_to_json(child_json, *for_node);
×
280
        } else if (auto sequence_node =
4✔
281
                       dynamic_cast<const structured_control_flow::Sequence*>(&child)) {
4✔
282
            sequence_to_json(child_json, *sequence_node);
×
283
        } else if (auto condition_node =
4✔
284
                       dynamic_cast<const structured_control_flow::IfElse*>(&child)) {
4✔
285
            if_else_to_json(child_json, *condition_node);
×
286
        } else if (auto while_node = dynamic_cast<const structured_control_flow::While*>(&child)) {
4✔
287
            while_node_to_json(child_json, *while_node);
×
288
        } else if (auto return_node =
4✔
289
                       dynamic_cast<const structured_control_flow::Return*>(&child)) {
4✔
290
            return_node_to_json(child_json, *return_node);
×
291
        } else if (auto break_node = dynamic_cast<const structured_control_flow::Break*>(&child)) {
4✔
292
            break_node_to_json(child_json, *break_node);
2✔
293
        } else if (auto continue_node =
4✔
294
                       dynamic_cast<const structured_control_flow::Continue*>(&child)) {
2✔
295
            continue_node_to_json(child_json, *continue_node);
2✔
296
        } else if (auto map_node = dynamic_cast<const structured_control_flow::Map*>(&child)) {
2✔
297
            map_to_json(child_json, *map_node);
×
298
        } else {
×
299
            throw std::runtime_error("Unknown child type");
×
300
        }
301

302
        j["children"].push_back(child_json);
20✔
303

304
        // Add transition information
305
        nlohmann::json transition_json;
20✔
306
        transition_json["type"] = "transition";
20✔
307
        transition_json["element_id"] = transition.element_id();
20✔
308

309
        transition_json["debug_info"] = nlohmann::json::object();
20✔
310
        debug_info_to_json(transition_json["debug_info"], transition.debug_info());
20✔
311

312
        transition_json["assignments"] = nlohmann::json::array();
20✔
313
        for (const auto& assignment : transition.assignments()) {
22✔
314
            nlohmann::json assignment_json;
2✔
315
            assignment_json["symbol"] = expression(assignment.first);
2✔
316
            assignment_json["expression"] = expression(assignment.second);
2✔
317
            transition_json["assignments"].push_back(assignment_json);
2✔
318
        }
2✔
319

320
        j["transitions"].push_back(transition_json);
20✔
321
    }
20✔
322
}
19✔
323

324
void JSONSerializer::type_to_json(nlohmann::json& j, const types::IType& type) {
43✔
325
    if (auto scalar_type = dynamic_cast<const types::Scalar*>(&type)) {
43✔
326
        j["type"] = "scalar";
33✔
327
        j["primitive_type"] = scalar_type->primitive_type();
33✔
328
        j["storage_type"] = std::string(scalar_type->storage_type().value());
33✔
329
        j["initializer"] = scalar_type->initializer();
33✔
330
        j["alignment"] = scalar_type->alignment();
33✔
331
    } else if (auto array_type = dynamic_cast<const types::Array*>(&type)) {
43✔
332
        j["type"] = "array";
3✔
333
        nlohmann::json element_type_json;
3✔
334
        type_to_json(element_type_json, array_type->element_type());
3✔
335
        j["element_type"] = element_type_json;
3✔
336
        j["num_elements"] = expression(array_type->num_elements());
3✔
337
        j["storage_type"] = std::string(array_type->storage_type().value());
3✔
338
        j["initializer"] = array_type->initializer();
3✔
339
        j["alignment"] = array_type->alignment();
3✔
340
    } else if (auto pointer_type = dynamic_cast<const types::Pointer*>(&type)) {
10✔
341
        j["type"] = "pointer";
3✔
342
        nlohmann::json pointee_type_json;
3✔
343
        type_to_json(pointee_type_json, pointer_type->pointee_type());
3✔
344
        j["pointee_type"] = pointee_type_json;
3✔
345
        j["storage_type"] = std::string(pointer_type->storage_type().value());
3✔
346
        j["initializer"] = pointer_type->initializer();
3✔
347
        j["alignment"] = pointer_type->alignment();
3✔
348
    } else if (auto structure_type = dynamic_cast<const types::Structure*>(&type)) {
7✔
349
        j["type"] = "structure";
2✔
350
        j["name"] = structure_type->name();
2✔
351
        j["storage_type"] = std::string(structure_type->storage_type().value());
2✔
352
        j["initializer"] = structure_type->initializer();
2✔
353
        j["alignment"] = structure_type->alignment();
2✔
354
    } else if (auto function_type = dynamic_cast<const types::Function*>(&type)) {
4✔
355
        j["type"] = "function";
2✔
356
        nlohmann::json return_type_json;
2✔
357
        type_to_json(return_type_json, function_type->return_type());
2✔
358
        j["return_type"] = return_type_json;
2✔
359
        j["params"] = nlohmann::json::array();
2✔
360
        for (size_t i = 0; i < function_type->num_params(); i++) {
5✔
361
            nlohmann::json param_json;
3✔
362
            type_to_json(param_json, function_type->param_type(symbolic::integer(i)));
3✔
363
            j["params"].push_back(param_json);
3✔
364
        }
3✔
365
        j["is_var_arg"] = function_type->is_var_arg();
2✔
366
        j["storage_type"] = std::string(function_type->storage_type().value());
2✔
367
        j["initializer"] = function_type->initializer();
2✔
368
        j["alignment"] = function_type->alignment();
2✔
369
    } else {
2✔
370
        throw std::runtime_error("Unknown type");
×
371
    }
372
}
43✔
373

374
void JSONSerializer::structure_definition_to_json(nlohmann::json& j,
1✔
375
                                                  const types::StructureDefinition& definition) {
376
    j["name"] = definition.name();
1✔
377
    j["members"] = nlohmann::json::array();
1✔
378
    for (size_t i = 0; i < definition.num_members(); i++) {
3✔
379
        nlohmann::json member_json;
2✔
380
        type_to_json(member_json, definition.member_type(symbolic::integer(i)));
2✔
381
        j["members"].push_back(member_json);
2✔
382
    }
2✔
383
    j["is_packed"] = definition.is_packed();
1✔
384
}
1✔
385

386
void JSONSerializer::debug_info_to_json(nlohmann::json& j, const DebugInfo& debug_info) {
109✔
387
    j["has"] = debug_info.has();
109✔
388
    j["filename"] = debug_info.filename();
109✔
389
    j["start_line"] = debug_info.start_line();
109✔
390
    j["start_column"] = debug_info.start_column();
109✔
391
    j["end_line"] = debug_info.end_line();
109✔
392
    j["end_column"] = debug_info.end_column();
109✔
393
}
109✔
394

395
/*
396
 * * Deserialization logic
397
 */
398

399
std::unique_ptr<StructuredSDFG> JSONSerializer::deserialize(nlohmann::json& j) {
3✔
400
    assert(j.contains("name"));
3✔
401
    assert(j["name"].is_string());
3✔
402
    assert(j.contains("type"));
3✔
403
    assert(j["type"].is_string());
3✔
404

405
    FunctionType type{"Unknown"};
3✔
406
    if (j["type"] == FunctionType_CPU.value()) {
3✔
407
        type = FunctionType_CPU;
3✔
408
    } else if (j["type"] == FunctionType_NV_GLOBAL.value()) {
3✔
409
        type = FunctionType_NV_GLOBAL;
×
410
    } else {
×
411
        throw std::runtime_error("Unknown function type");
×
412
    }
413
    builder::StructuredSDFGBuilder builder(j["name"], type);
3✔
414

415
    // deserialize structures
416
    assert(j.contains("structures"));
3✔
417
    assert(j["structures"].is_array());
3✔
418
    for (const auto& structure : j["structures"]) {
3✔
419
        assert(structure.contains("name"));
×
420
        assert(structure["name"].is_string());
×
421
        json_to_structure_definition(structure, builder);
×
422
    }
423

424
    nlohmann::json& containers = j["containers"];
3✔
425

426
    // deserialize externals
427
    for (const auto& name : j["externals"]) {
3✔
428
        auto& type_desc = containers.at(name.get<std::string>());
×
429
        auto type = json_to_type(type_desc);
×
430
        builder.add_container(name, *type, false, true);
×
431
    }
×
432

433
    // deserialize arguments
434
    for (const auto& name : j["arguments"]) {
5✔
435
        auto& type_desc = containers.at(name.get<std::string>());
2✔
436
        auto type = json_to_type(type_desc);
2✔
437
        builder.add_container(name, *type, true, false);
2✔
438
    }
2✔
439

440
    // deserialize transients
441
    for (const auto& entry : containers.items()) {
8✔
442
        if (builder.subject().is_argument(entry.key())) {
5✔
443
            continue;
2✔
444
        }
445
        if (builder.subject().is_external(entry.key())) {
3✔
446
            continue;
×
447
        }
448
        auto type = json_to_type(entry.value());
3✔
449
        builder.add_container(entry.key(), *type, false, false);
3✔
450
    }
3✔
451

452
    // deserialize root node
453
    assert(j.contains("root"));
3✔
454
    auto& root = builder.subject().root();
3✔
455
    json_to_sequence(j["root"], builder, root);
3✔
456

457
    // deserialize metadata
458
    assert(j.contains("metadata"));
3✔
459
    assert(j["metadata"].is_object());
3✔
460
    for (const auto& entry : j["metadata"].items()) {
4✔
461
        builder.subject().add_metadata(entry.key(), entry.value());
1✔
462
    }
463

464
    return builder.move();
3✔
465
}
3✔
466

467
void JSONSerializer::json_to_structure_definition(const nlohmann::json& j,
1✔
468
                                                  builder::StructuredSDFGBuilder& builder) {
469
    assert(j.contains("name"));
1✔
470
    assert(j["name"].is_string());
1✔
471
    assert(j.contains("members"));
1✔
472
    assert(j["members"].is_array());
1✔
473
    assert(j.contains("is_packed"));
1✔
474
    assert(j["is_packed"].is_boolean());
1✔
475
    auto is_packed = j["is_packed"];
1✔
476
    auto& definition = builder.add_structure(j["name"], is_packed);
1✔
477
    for (const auto& member : j["members"]) {
3✔
478
        nlohmann::json member_json;
2✔
479
        auto member_type = json_to_type(member);
2✔
480
        definition.add_member(*member_type);
2✔
481
    }
2✔
482
}
1✔
483

484
std::vector<std::pair<std::string, types::Scalar>> JSONSerializer::json_to_arguments(
4✔
485
    const nlohmann::json& j) {
486
    std::vector<std::pair<std::string, types::Scalar>> arguments;
4✔
487
    for (const auto& argument : j) {
12✔
488
        assert(argument.contains("name"));
8✔
489
        assert(argument["name"].is_string());
8✔
490
        assert(argument.contains("type"));
8✔
491
        assert(argument["type"].is_object());
8✔
492
        std::string name = argument["name"];
8✔
493
        auto type = json_to_type(argument["type"]);
8✔
494
        arguments.emplace_back(name, *dynamic_cast<types::Scalar*>(type.get()));
8✔
495
    }
8✔
496
    return arguments;
4✔
497
}
4✔
498

499
void JSONSerializer::json_to_dataflow(const nlohmann::json& j,
10✔
500
                                      builder::StructuredSDFGBuilder& builder,
501
                                      structured_control_flow::Block& parent) {
502
    std::unordered_map<std::string, data_flow::DataFlowNode&> nodes_map;
10✔
503

504
    assert(j.contains("nodes"));
10✔
505
    assert(j["nodes"].is_array());
10✔
506
    for (const auto& node : j["nodes"]) {
26✔
507
        assert(node.contains("type"));
16✔
508
        assert(node["type"].is_string());
16✔
509
        assert(node.contains("element_id"));
16✔
510
        assert(node["element_id"].is_string());
16✔
511
        std::string type = node["type"];
16✔
512
        if (type == "tasklet") {
16✔
513
            assert(node.contains("code"));
4✔
514
            assert(node["code"].is_number_integer());
4✔
515
            assert(node.contains("inputs"));
4✔
516
            assert(node["inputs"].is_array());
4✔
517
            assert(node.contains("output"));
4✔
518
            assert(node["output"].is_object());
4✔
519
            assert(node["output"].contains("name"));
4✔
520
            assert(node["output"].contains("type"));
4✔
521
            auto inputs = json_to_arguments(node["inputs"]);
4✔
522

523
            auto output_name = node["output"]["name"];
4✔
524
            auto output_type = json_to_type(node["output"]["type"]);
4✔
525
            auto& output_type_scalar = dynamic_cast<types::Scalar&>(*output_type);
4✔
526

527
            auto& tasklet =
4✔
528
                builder.add_tasklet(parent, node["code"], {output_name, output_type_scalar}, inputs,
8✔
529
                                    json_to_debug_info(node["debug_info"]));
4✔
530
            tasklet.element_id_ = node["element_id"];
4✔
531
            nodes_map.insert({node["element_id"], tasklet});
4✔
532
        } else if (type == "library_node") {
16✔
533
            assert(node.contains("code"));
×
534
            assert(node.contains("inputs"));
×
535
            assert(node["inputs"].is_array());
×
536
            assert(node.contains("outputs"));
×
537
            assert(node["outputs"].is_array());
×
538
            std::vector<std::string> outputs;
×
539
            for (const auto& output : node["outputs"]) {
×
540
                assert(output.is_string());
×
541
                outputs.push_back(output);
×
542
            }
543
            std::vector<std::string> inputs;
×
544
            for (const auto& input : node["inputs"]) {
×
545
                assert(input.is_string());
×
546
                inputs.push_back(input);
×
547
            }
NEW
548
            data_flow::LibraryNodeCode code(node["code"].get<std::string_view>());
×
549
            auto& lib_node =
×
NEW
550
                builder.add_library_node(parent, code, outputs, inputs, node["side_effect"],
×
551
                                         json_to_debug_info(node["debug_info"]));
×
552
            lib_node.element_id_ = node["element_id"];
×
553
            nodes_map.insert({node["element_id"], lib_node});
×
554
        } else if (type == "access_node") {
12✔
555
            assert(node.contains("data"));
12✔
556
            auto& access_node =
12✔
557
                builder.add_access(parent, node["data"], json_to_debug_info(node["debug_info"]));
12✔
558
            access_node.element_id_ = node["element_id"];
12✔
559
            nodes_map.insert({node["element_id"], access_node});
12✔
560
        } else {
12✔
561
            throw std::runtime_error("Unknown node type");
×
562
        }
563
    }
16✔
564

565
    assert(j.contains("edges"));
10✔
566
    assert(j["edges"].is_array());
10✔
567
    for (const auto& edge : j["edges"]) {
22✔
568
        assert(edge.contains("src"));
12✔
569
        assert(edge["src"].is_string());
12✔
570
        assert(edge.contains("dst"));
12✔
571
        assert(edge["dst"].is_string());
12✔
572
        assert(edge.contains("src_conn"));
12✔
573
        assert(edge["src_conn"].is_string());
12✔
574
        assert(edge.contains("dst_conn"));
12✔
575
        assert(edge["dst_conn"].is_string());
12✔
576
        assert(edge.contains("subset"));
12✔
577
        assert(edge["subset"].is_array());
12✔
578

579
        assert(nodes_map.find(edge["src"]) != nodes_map.end());
12✔
580
        assert(nodes_map.find(edge["dst"]) != nodes_map.end());
12✔
581
        auto& source = nodes_map.at(edge["src"]);
12✔
582
        auto& target = nodes_map.at(edge["dst"]);
12✔
583

584
        assert(edge.contains("subset"));
12✔
585
        assert(edge["subset"].is_array());
12✔
586
        std::vector<symbolic::Expression> subset;
12✔
587
        for (const auto& subset_str : edge["subset"]) {
16✔
588
            assert(subset_str.is_string());
4✔
589
            SymEngine::Expression subset_expr(subset_str);
4✔
590
            subset.push_back(subset_expr);
4✔
591
        }
4✔
592
        auto& memlet =
12✔
593
            builder.add_memlet(parent, source, edge["src_conn"], target, edge["dst_conn"], subset,
24✔
594
                               json_to_debug_info(edge["debug_info"]));
12✔
595
        memlet.element_id_ = edge["element_id"];
12✔
596
    }
12✔
597
}
10✔
598

599
void JSONSerializer::json_to_sequence(const nlohmann::json& j,
12✔
600
                                      builder::StructuredSDFGBuilder& builder,
601
                                      structured_control_flow::Sequence& sequence) {
602
    assert(j.contains("type"));
12✔
603
    assert(j["type"].is_string());
12✔
604
    assert(j.contains("children"));
12✔
605
    assert(j["children"].is_array());
12✔
606
    assert(j.contains("transitions"));
12✔
607
    assert(j["transitions"].is_array());
12✔
608
    assert(j["transitions"].size() == j["children"].size());
12✔
609

610
    sequence.element_id_ = j["element_id"];
12✔
611
    sequence.debug_info_ = json_to_debug_info(j["debug_info"]);
12✔
612

613
    std::string type = j["type"];
12✔
614
    if (type == "sequence") {
12✔
615
        for (size_t i = 0; i < j["children"].size(); i++) {
22✔
616
            auto& child = j["children"][i];
10✔
617
            auto& transition = j["transitions"][i];
10✔
618
            assert(child.contains("type"));
10✔
619
            assert(child["type"].is_string());
10✔
620

621
            assert(transition.contains("type"));
10✔
622
            assert(transition["type"].is_string());
10✔
623
            assert(transition.contains("assignments"));
10✔
624
            assert(transition["assignments"].is_array());
10✔
625
            symbolic::Assignments assignments;
10✔
626
            for (const auto& assignment : transition["assignments"]) {
11✔
627
                assert(assignment.contains("symbol"));
1✔
628
                assert(assignment["symbol"].is_string());
1✔
629
                assert(assignment.contains("expression"));
1✔
630
                assert(assignment["expression"].is_string());
1✔
631
                SymEngine::Expression expr(assignment["expression"]);
1✔
632
                assignments.insert({symbolic::symbol(assignment["symbol"]), expr});
1✔
633
            }
1✔
634

635
            if (child["type"] == "block") {
10✔
636
                json_to_block_node(child, builder, sequence, assignments);
8✔
637
            } else if (child["type"] == "for") {
10✔
638
                json_to_for_node(child, builder, sequence, assignments);
×
639
            } else if (child["type"] == "if_else") {
2✔
640
                json_to_if_else_node(child, builder, sequence, assignments);
×
641
            } else if (child["type"] == "while") {
2✔
642
                json_to_while_node(child, builder, sequence, assignments);
×
643
            } else if (child["type"] == "break") {
2✔
644
                json_to_break_node(child, builder, sequence, assignments);
1✔
645
            } else if (child["type"] == "continue") {
2✔
646
                json_to_continue_node(child, builder, sequence, assignments);
1✔
647
            } else if (child["type"] == "return") {
1✔
648
                json_to_return_node(child, builder, sequence, assignments);
×
649
            } else if (child["type"] == "map") {
×
650
                json_to_map_node(child, builder, sequence, assignments);
×
651
            } else if (child["type"] == "sequence") {
×
652
                auto& subseq = builder.add_sequence(sequence, assignments,
×
653
                                                    json_to_debug_info(child["debug_info"]));
×
654
                json_to_sequence(child, builder, subseq);
×
655
            } else {
×
656
                throw std::runtime_error("Unknown child type");
×
657
            }
658

659
            sequence.at(i).second.debug_info_ = json_to_debug_info(transition["debug_info"]);
10✔
660
            sequence.at(i).second.element_id_ = transition["element_id"];
10✔
661
        }
10✔
662
    } else {
12✔
663
        throw std::runtime_error("expected sequence type");
×
664
    }
665
}
12✔
666

667
void JSONSerializer::json_to_block_node(const nlohmann::json& j,
9✔
668
                                        builder::StructuredSDFGBuilder& builder,
669
                                        structured_control_flow::Sequence& parent,
670
                                        symbolic::Assignments& assignments) {
671
    assert(j.contains("type"));
9✔
672
    assert(j["type"].is_string());
9✔
673
    assert(j.contains("dataflow"));
9✔
674
    assert(j["dataflow"].is_object());
9✔
675
    auto& block = builder.add_block(parent, assignments, json_to_debug_info(j["debug_info"]));
9✔
676
    block.element_id_ = j["element_id"];
9✔
677
    assert(j["dataflow"].contains("type"));
9✔
678
    assert(j["dataflow"]["type"].is_string());
9✔
679
    std::string type = j["dataflow"]["type"];
9✔
680
    if (type == "dataflow") {
9✔
681
        json_to_dataflow(j["dataflow"], builder, block);
9✔
682
    } else {
9✔
683
        throw std::runtime_error("Unknown dataflow type");
×
684
    }
685
}
9✔
686

687
void JSONSerializer::json_to_for_node(const nlohmann::json& j,
1✔
688
                                      builder::StructuredSDFGBuilder& builder,
689
                                      structured_control_flow::Sequence& parent,
690
                                      symbolic::Assignments& assignments) {
691
    assert(j.contains("type"));
1✔
692
    assert(j["type"].is_string());
1✔
693
    assert(j.contains("indvar"));
1✔
694
    assert(j["indvar"].is_string());
1✔
695
    assert(j.contains("init"));
1✔
696
    assert(j["init"].is_string());
1✔
697
    assert(j.contains("condition"));
1✔
698
    assert(j["condition"].is_string());
1✔
699
    assert(j.contains("update"));
1✔
700
    assert(j["update"].is_string());
1✔
701
    assert(j.contains("root"));
1✔
702
    assert(j["root"].is_object());
1✔
703

704
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
1✔
705
    SymEngine::Expression init(j["init"]);
1✔
706
    SymEngine::Expression condition_expr(j["condition"]);
1✔
707
    assert(!SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic())
1✔
708
                .is_null());
709
    symbolic::Condition condition =
710
        SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic());
1✔
711
    SymEngine::Expression update(j["update"]);
1✔
712
    auto& for_node = builder.add_for(parent, indvar, condition, init, update, assignments,
2✔
713
                                     json_to_debug_info(j["debug_info"]));
1✔
714
    for_node.element_id_ = j["element_id"];
1✔
715

716
    assert(j["root"].contains("type"));
1✔
717
    assert(j["root"]["type"].is_string());
1✔
718
    assert(j["root"]["type"] == "sequence");
1✔
719
    json_to_sequence(j["root"], builder, for_node.root());
1✔
720
}
1✔
721

722
void JSONSerializer::json_to_if_else_node(const nlohmann::json& j,
1✔
723
                                          builder::StructuredSDFGBuilder& builder,
724
                                          structured_control_flow::Sequence& parent,
725
                                          symbolic::Assignments& assignments) {
726
    assert(j.contains("type"));
1✔
727
    assert(j["type"].is_string());
1✔
728
    assert(j["type"] == "if_else");
1✔
729
    assert(j.contains("branches"));
1✔
730
    assert(j["branches"].is_array());
1✔
731
    auto& if_else_node =
1✔
732
        builder.add_if_else(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
733
    if_else_node.element_id_ = j["element_id"];
1✔
734
    for (const auto& branch : j["branches"]) {
3✔
735
        assert(branch.contains("condition"));
2✔
736
        assert(branch["condition"].is_string());
2✔
737
        assert(branch.contains("root"));
2✔
738
        assert(branch["root"].is_object());
2✔
739
        SymEngine::Expression condition_expr(branch["condition"]);
2✔
740
        assert(!SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic())
2✔
741
                    .is_null());
742
        symbolic::Condition condition =
743
            SymEngine::rcp_static_cast<const SymEngine::Boolean>(condition_expr.get_basic());
2✔
744
        auto& branch_node = builder.add_case(if_else_node, condition);
2✔
745
        assert(branch["root"].contains("type"));
2✔
746
        assert(branch["root"]["type"].is_string());
2✔
747
        std::string type = branch["root"]["type"];
2✔
748
        if (type == "sequence") {
2✔
749
            json_to_sequence(branch["root"], builder, branch_node);
2✔
750
        } else {
2✔
751
            throw std::runtime_error("Unknown child type");
×
752
        }
753
    }
2✔
754
}
1✔
755

756
void JSONSerializer::json_to_while_node(const nlohmann::json& j,
3✔
757
                                        builder::StructuredSDFGBuilder& builder,
758
                                        structured_control_flow::Sequence& parent,
759
                                        symbolic::Assignments& assignments) {
760
    assert(j.contains("type"));
3✔
761
    assert(j["type"].is_string());
3✔
762
    assert(j["type"] == "while");
3✔
763
    assert(j.contains("root"));
3✔
764
    assert(j["root"].is_object());
3✔
765

766
    auto& while_node = builder.add_while(parent, assignments, json_to_debug_info(j["debug_info"]));
3✔
767
    while_node.element_id_ = j["element_id"];
3✔
768

769
    assert(j["root"]["type"] == "sequence");
3✔
770
    json_to_sequence(j["root"], builder, while_node.root());
3✔
771
}
3✔
772

773
void JSONSerializer::json_to_break_node(const nlohmann::json& j,
1✔
774
                                        builder::StructuredSDFGBuilder& builder,
775
                                        structured_control_flow::Sequence& parent,
776
                                        symbolic::Assignments& assignments) {
777
    assert(j.contains("type"));
1✔
778
    assert(j["type"].is_string());
1✔
779
    assert(j["type"] == "break");
1✔
780
    auto& node = builder.add_break(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
781
    node.element_id_ = j["element_id"];
1✔
782
}
1✔
783

784
void JSONSerializer::json_to_continue_node(const nlohmann::json& j,
1✔
785
                                           builder::StructuredSDFGBuilder& builder,
786
                                           structured_control_flow::Sequence& parent,
787
                                           symbolic::Assignments& assignments) {
788
    assert(j.contains("type"));
1✔
789
    assert(j["type"].is_string());
1✔
790
    assert(j["type"] == "continue");
1✔
791
    auto& node = builder.add_continue(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
792
    node.element_id_ = j["element_id"];
1✔
793
}
1✔
794

795
void JSONSerializer::json_to_map_node(const nlohmann::json& j,
1✔
796
                                      builder::StructuredSDFGBuilder& builder,
797
                                      structured_control_flow::Sequence& parent,
798
                                      symbolic::Assignments& assignments) {
799
    assert(j.contains("type"));
1✔
800
    assert(j["type"].is_string());
1✔
801
    assert(j["type"] == "map");
1✔
802
    assert(j.contains("indvar"));
1✔
803
    assert(j["indvar"].is_string());
1✔
804
    assert(j.contains("num_iterations"));
1✔
805
    assert(j["num_iterations"].is_string());
1✔
806
    assert(j.contains("root"));
1✔
807
    assert(j["root"].is_object());
1✔
808
    assert(j.contains("schedule_type"));
1✔
809
    assert(j["schedule_type"].is_string());
1✔
810
    structured_control_flow::ScheduleType schedule_type{j["schedule_type"].get<std::string_view>()};
1✔
811
    symbolic::Symbol indvar = symbolic::symbol(j["indvar"]);
1✔
812
    SymEngine::Expression num_iterations(j["num_iterations"]);
1✔
813

814
    auto& map_node = builder.add_map(parent, indvar, num_iterations, schedule_type, assignments,
2✔
815
                                     json_to_debug_info(j["debug_info"]));
1✔
816
    map_node.element_id_ = j["element_id"];
1✔
817

818
    assert(j["root"].contains("type"));
1✔
819
    assert(j["root"]["type"].is_string());
1✔
820
    assert(j["root"]["type"] == "sequence");
1✔
821
    json_to_sequence(j["root"], builder, map_node.root());
1✔
822
}
1✔
823

824
void JSONSerializer::json_to_return_node(const nlohmann::json& j,
1✔
825
                                         builder::StructuredSDFGBuilder& builder,
826
                                         structured_control_flow::Sequence& parent,
827
                                         symbolic::Assignments& assignments) {
828
    assert(j.contains("type"));
1✔
829
    assert(j["type"].is_string());
1✔
830
    assert(j["type"] == "return");
1✔
831

832
    auto& node = builder.add_return(parent, assignments, json_to_debug_info(j["debug_info"]));
1✔
833
    node.element_id_ = j["element_id"];
1✔
834
}
1✔
835

836
std::unique_ptr<types::IType> JSONSerializer::json_to_type(const nlohmann::json& j) {
31✔
837
    if (j.contains("type")) {
31✔
838
        if (j["type"] == "scalar") {
31✔
839
            // Deserialize scalar type
840
            assert(j.contains("primitive_type"));
25✔
841
            types::PrimitiveType primitive_type = j["primitive_type"];
25✔
842
            assert(j.contains("storage_type"));
25✔
843
            types::StorageType storage_type{j["storage_type"].get<std::string_view>()};
25✔
844
            assert(j.contains("initializer"));
25✔
845
            std::string initializer = j["initializer"];
25✔
846
            assert(j.contains("alignment"));
25✔
847
            size_t alignment = j["alignment"];
25✔
848
            return std::make_unique<types::Scalar>(storage_type, alignment, initializer,
25✔
849
                                                   primitive_type);
850
        } else if (j["type"] == "array") {
31✔
851
            // Deserialize array type
852
            assert(j.contains("element_type"));
2✔
853
            std::unique_ptr<types::IType> member_type = json_to_type(j["element_type"]);
2✔
854
            assert(j.contains("num_elements"));
2✔
855
            std::string num_elements_str = j["num_elements"];
2✔
856
            // Convert num_elements_str to symbolic::Expression
857
            SymEngine::Expression num_elements(num_elements_str);
2✔
858
            assert(j.contains("storage_type"));
2✔
859
            types::StorageType storage_type{j["storage_type"].get<std::string_view>()};
2✔
860
            assert(j.contains("initializer"));
2✔
861
            std::string initializer = j["initializer"];
2✔
862
            assert(j.contains("alignment"));
2✔
863
            size_t alignment = j["alignment"];
2✔
864
            return std::make_unique<types::Array>(storage_type, alignment, initializer,
2✔
865
                                                  *member_type, num_elements);
2✔
866
        } else if (j["type"] == "pointer") {
6✔
867
            // Deserialize pointer type
868
            assert(j.contains("pointee_type"));
2✔
869
            std::unique_ptr<types::IType> pointee_type = json_to_type(j["pointee_type"]);
2✔
870
            assert(j.contains("storage_type"));
2✔
871
            types::StorageType storage_type{j["storage_type"].get<std::string_view>()};
2✔
872
            assert(j.contains("initializer"));
2✔
873
            std::string initializer = j["initializer"];
2✔
874
            assert(j.contains("alignment"));
2✔
875
            size_t alignment = j["alignment"];
2✔
876
            return std::make_unique<types::Pointer>(storage_type, alignment, initializer,
2✔
877
                                                    *pointee_type);
2✔
878
        } else if (j["type"] == "structure") {
4✔
879
            // Deserialize structure type
880
            assert(j.contains("name"));
1✔
881
            std::string name = j["name"];
1✔
882
            assert(j.contains("storage_type"));
1✔
883
            types::StorageType storage_type{j["storage_type"].get<std::string_view>()};
1✔
884
            assert(j.contains("initializer"));
1✔
885
            std::string initializer = j["initializer"];
1✔
886
            assert(j.contains("alignment"));
1✔
887
            size_t alignment = j["alignment"];
1✔
888
            return std::make_unique<types::Structure>(storage_type, alignment, initializer, name);
1✔
889
        } else if (j["type"] == "function") {
2✔
890
            // Deserialize function type
891
            assert(j.contains("return_type"));
1✔
892
            std::unique_ptr<types::IType> return_type = json_to_type(j["return_type"]);
1✔
893
            assert(j.contains("params"));
1✔
894
            std::vector<std::unique_ptr<types::IType>> params;
1✔
895
            for (const auto& param : j["params"]) {
3✔
896
                params.push_back(json_to_type(param));
2✔
897
            }
898
            assert(j.contains("is_var_arg"));
1✔
899
            bool is_var_arg = j["is_var_arg"];
1✔
900
            assert(j.contains("storage_type"));
1✔
901
            types::StorageType storage_type{j["storage_type"].get<std::string_view>()};
1✔
902
            assert(j.contains("initializer"));
1✔
903
            std::string initializer = j["initializer"];
1✔
904
            assert(j.contains("alignment"));
1✔
905
            size_t alignment = j["alignment"];
1✔
906
            auto function = std::make_unique<types::Function>(storage_type, alignment, initializer,
1✔
907
                                                              *return_type, is_var_arg);
1✔
908
            for (const auto& param : params) {
3✔
909
                function->add_param(*param);
2✔
910
            }
911
            return function->clone();
1✔
912

913
        } else {
1✔
914
            throw std::runtime_error("Unknown type");
×
915
        }
916
    } else {
917
        throw std::runtime_error("Type not found");
×
918
    }
919
}
31✔
920

921
DebugInfo JSONSerializer::json_to_debug_info(const nlohmann::json& j) {
68✔
922
    assert(j.contains("has"));
68✔
923
    assert(j["has"].is_boolean());
68✔
924
    if (!j["has"]) {
68✔
925
        return DebugInfo();
68✔
926
    }
927
    assert(j.contains("filename"));
×
928
    assert(j["filename"].is_string());
×
929
    std::string filename = j["filename"];
×
930
    assert(j.contains("start_line"));
×
931
    assert(j["start_line"].is_number_integer());
×
932
    size_t start_line = j["start_line"];
×
933
    assert(j.contains("start_column"));
×
934
    assert(j["start_column"].is_number_integer());
×
935
    size_t start_column = j["start_column"];
×
936
    assert(j.contains("end_line"));
×
937
    assert(j["end_line"].is_number_integer());
×
938
    size_t end_line = j["end_line"];
×
939
    assert(j.contains("end_column"));
×
940
    assert(j["end_column"].is_number_integer());
×
941
    size_t end_column = j["end_column"];
×
942
    return DebugInfo(filename, start_line, start_column, end_line, end_column);
×
943
}
68✔
944

945
std::string JSONSerializer::expression(const symbolic::Expression& expr) {
29✔
946
    JSONSymbolicPrinter printer;
29✔
947
    return printer.apply(expr);
29✔
948
};
29✔
949

950
void JSONSymbolicPrinter::bvisit(const SymEngine::Equality& x) {
×
951
    str_ = apply(x.get_args()[0]) + " == " + apply(x.get_args()[1]);
×
952
    str_ = parenthesize(str_);
×
953
};
×
954

955
void JSONSymbolicPrinter::bvisit(const SymEngine::Unequality& x) {
×
956
    str_ = apply(x.get_args()[0]) + " != " + apply(x.get_args()[1]);
×
957
    str_ = parenthesize(str_);
×
958
};
×
959

960
void JSONSymbolicPrinter::bvisit(const SymEngine::LessThan& x) {
×
961
    str_ = apply(x.get_args()[0]) + " <= " + apply(x.get_args()[1]);
×
962
    str_ = parenthesize(str_);
×
963
};
×
964

965
void JSONSymbolicPrinter::bvisit(const SymEngine::StrictLessThan& x) {
2✔
966
    str_ = apply(x.get_args()[0]) + " < " + apply(x.get_args()[1]);
2✔
967
    str_ = parenthesize(str_);
2✔
968
};
2✔
969

970
void JSONSymbolicPrinter::bvisit(const SymEngine::Min& x) {
×
971
    std::ostringstream s;
×
972
    auto container = x.get_args();
×
973
    if (container.size() == 1) {
×
974
        s << apply(*container.begin());
×
975
    } else {
×
976
        s << "min(";
×
977
        s << apply(*container.begin());
×
978

979
        // Recursively apply __daisy_min to the arguments
980
        SymEngine::vec_basic subargs;
×
981
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
982
            subargs.push_back(*it);
×
983
        }
×
984
        auto submin = SymEngine::min(subargs);
×
985
        s << ", " << apply(submin);
×
986

987
        s << ")";
×
988
    }
×
989

990
    str_ = s.str();
×
991
};
×
992

993
void JSONSymbolicPrinter::bvisit(const SymEngine::Max& x) {
×
994
    std::ostringstream s;
×
995
    auto container = x.get_args();
×
996
    if (container.size() == 1) {
×
997
        s << apply(*container.begin());
×
998
    } else {
×
999
        s << "max(";
×
1000
        s << apply(*container.begin());
×
1001

1002
        // Recursively apply __daisy_max to the arguments
1003
        SymEngine::vec_basic subargs;
×
1004
        for (auto it = ++(container.begin()); it != container.end(); ++it) {
×
1005
            subargs.push_back(*it);
×
1006
        }
×
1007
        auto submax = SymEngine::max(subargs);
×
1008
        s << ", " << apply(submax);
×
1009

1010
        s << ")";
×
1011
    }
×
1012

1013
    str_ = s.str();
×
1014
};
×
1015

1016
}  // namespace serializer
1017
}  // 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