1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
#include <format>
#include "Circuit.h"
#include "Exception.h"
#include "NodeFactory.h"
#include "NodeOutputVisitor.h"
using std::format;
void Circuit::create(string label, vector<string> nodes) {
if (nodes.size() == 1 && NodeFactory::has_type(nodes[0]))
return new_node(label, nodes[0]);
new_net(label, nodes);
loops.add_connection(label, nodes);
}
void Circuit::new_node(string label, string type) {
if (nodes.find(label) != nodes.end())
throw CircuitException("node with label \"%s\" already exists!", label.c_str());
Node * node = NodeFactory::create(type);
if (node == nullptr)
throw CircuitException("unknown type \"%s\"", type.c_str());
nodes[label] = node;
}
void Circuit::new_net(string src, vector<string> dests) {
Net * net = new Net();
nets.push_back(net);
Node * node = find_node(src);
if (node == nullptr)
throw CircuitException("unknown source node \"%s\"", src.c_str());
node->setOutput(net);
for (auto dest : dests) {
Node * node = find_node(dest);
if (node == nullptr)
throw CircuitException("unknown destination node \"%s\"", dest.c_str());
node->addInput(net);
}
}
void Circuit::sim() {
for (auto & pair : nodes) {
try {
Node * node = pair.second;
node->sim();
} catch (CircuitException & e) {
const char * label = "???";
Node * node = e.node;
if (node != nullptr) {
auto it = std::find_if(nodes.begin(), nodes.end(),
[node](auto && n) { return n.second == node; });
if (it != nodes.end()) label = it->first.c_str();
}
throw CircuitException("node %s: %s", label, e.what());
}
}
}
Node * Circuit::find_node(string label) {
auto map_index = this->nodes.find(label);
if (map_index == nodes.end()) return nullptr;
return map_index->second;
}
Circuit::~Circuit() {
for (auto & n : nodes)
delete n.second;
for (auto & n : nets)
delete n;
}
string Circuit::result() {
string output;
for (auto & n : nodes) {
NodeOutputVisitor visitor;
n.second->accept(visitor);
if (!visitor.output_node) continue;
output += format("{}: {}\n", n.first, std::to_string(visitor.level));
}
return output;
}
|