Skip to main content

GraphDsl.h File

Lightweight DSL helpers for wiring graphs. More...

Included Headers

#include "graph/Graph.h" #include <stdexcept> #include <string> #include <utility> #include <vector>

Namespaces Index

namespacesimaai
namespaceneat
namespacegraph
namespacedsl

Classes Index

structPortRef

Handle to a specific port on a node within a runtime Graph, used by the DSL. More...

structNodeRef

Handle to a node within a runtime Graph, used by the fluent DSL. More...

Description

Lightweight DSL helpers for wiring graphs.

File Listing

The file content with the documentation metadata removed is:

1
6#pragma once
7
8#include "graph/Graph.h"
9
10#include <stdexcept>
11#include <string>
12#include <utility>
13#include <vector>
14
16
27struct PortRef {
28 Graph* g = nullptr;
29 NodeId node = kInvalidNode;
30 PortId port = kInvalidPort;
31 bool is_output = true;
32};
33
43struct NodeRef {
44 Graph* g = nullptr;
45 NodeId id = kInvalidNode;
46
48 operator NodeId() const {
49 return id;
50 }
51
53 PortRef out() const;
55 PortRef out(const std::string& name) const;
57 PortRef in() const;
59 PortRef in(const std::string& name) const;
61 PortRef operator[](const std::string& name) const;
63 PortRef operator[](const char* name) const {
64 return (*this)[std::string(name)];
65 }
66};
67
69inline NodeRef ref(Graph& g, NodeId id) {
70 return NodeRef{&g, id};
71}
72
74inline NodeRef add(Graph& g, Graph::NodePtr node) {
75 return NodeRef{&g, g.add(std::move(node))};
76}
77
79inline bool has_port(const std::vector<PortDesc>& ports, const std::string& name) {
80 for (const auto& p : ports) {
81 if (p.name == name)
82 return true;
83 }
84 return false;
85}
86
88inline void ensure_graph(const Graph* g, const char* what) {
89 if (!g)
90 throw std::runtime_error(std::string("GraphDsl: null graph in ") + what);
91}
92
94inline const std::shared_ptr<Node>& get_node(const Graph* g, NodeId id, const char* what) {
95 if (!g)
96 throw std::runtime_error(std::string("GraphDsl: null graph in ") + what);
97 return g->node(id);
98}
99
100inline PortRef NodeRef::out() const {
101 const auto& node = get_node(g, id, "out()");
102 const auto ports = node->output_ports();
103 if (ports.size() != 1) {
104 throw std::runtime_error("GraphDsl: out() requires exactly one output port");
105 }
106 return out(ports.front().name);
107}
108
109inline PortRef NodeRef::out(const std::string& name) const {
110 const auto& node = get_node(g, id, "out(name)");
111 const auto ports = node->output_ports();
112 if (!has_port(ports, name)) {
113 throw std::runtime_error("GraphDsl: unknown output port: " + name);
114 }
115 return PortRef{g, id, g->intern_port(name), true};
116}
117
118inline PortRef NodeRef::in() const {
119 const auto& node = get_node(g, id, "in()");
120 const auto ports = node->input_ports();
121 if (ports.size() != 1) {
122 throw std::runtime_error("GraphDsl: in() requires exactly one input port");
123 }
124 return in(ports.front().name);
125}
126
127inline PortRef NodeRef::in(const std::string& name) const {
128 const auto& node = get_node(g, id, "in(name)");
129 const auto ports = node->input_ports();
130 if (!has_port(ports, name)) {
131 throw std::runtime_error("GraphDsl: unknown input port: " + name);
132 }
133 return PortRef{g, id, g->intern_port(name), false};
134}
135
136inline PortRef NodeRef::operator[](const std::string& name) const {
137 const auto& node = get_node(g, id, "operator[]");
138 const auto in_ports = node->input_ports();
139 const auto out_ports = node->output_ports();
140 const bool has_in = has_port(in_ports, name);
141 const bool has_out = has_port(out_ports, name);
142
143 if (has_out && !has_in)
144 return out(name);
145 if (has_in && !has_out)
146 return in(name);
147
148 if (!has_in && !has_out) {
149 throw std::runtime_error("GraphDsl: unknown port: " + name);
150 }
151 throw std::runtime_error("GraphDsl: ambiguous port name (use .in or .out): " + name);
152}
153
155inline void connect_ports(const PortRef& from, const PortRef& to) {
156 ensure_graph(from.g, "connect_ports(from)");
157 ensure_graph(to.g, "connect_ports(to)");
158 if (from.g != to.g) {
159 throw std::runtime_error("GraphDsl: cannot connect ports from different graphs");
160 }
161 if (!from.is_output) {
162 throw std::runtime_error("GraphDsl: left side is not an output port");
163 }
164 if (to.is_output) {
165 throw std::runtime_error("GraphDsl: right side is not an input port");
166 }
167 from.g->connect(from.node, to.node, from.g->port_name(from.port), to.g->port_name(to.port));
168}
169
171inline NodeRef operator>>(const NodeRef& from, const NodeRef& to) {
172 connect_ports(from.out(), to.in());
173 return to;
174}
175
177inline NodeRef operator>>(const PortRef& from, const NodeRef& to) {
178 connect_ports(from, to.in());
179 return to;
180}
181
183inline NodeRef operator>>(const NodeRef& from, const PortRef& to) {
184 connect_ports(from.out(), to);
185 return NodeRef{to.g, to.node};
186}
187
189inline NodeRef operator>>(const PortRef& from, const PortRef& to) {
190 connect_ports(from, to);
191 return NodeRef{to.g, to.node};
192}
193
194} // namespace simaai::neat::graph::dsl

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.9.8.