13 #include <llvm/AsmParser/Parser.h> 14 #include <llvm/IR/DIBuilder.h> 15 #include <llvm/IR/DerivedTypes.h> 16 #include <llvm/IR/Verifier.h> 17 #include <llvm/Support/SourceMgr.h> 19 #include <boost/dynamic_bitset.hpp> 20 #include <boost/range/counting_range.hpp> 21 #include <boost/range/join.hpp> 22 #include <boost/uuid/uuid_io.hpp> 26 std::vector<NamedDataType> dataOuts, std::vector<std::string> execIns,
27 std::vector<std::string> execOuts)
29 mContext{&mod.context()},
30 mName{std::move(
name)},
31 mDataInputs(std::move(dataIns)),
32 mDataOutputs(std::move(dataOuts)),
33 mExecInputs(std::move(execIns)),
34 mExecOutputs(std::move(execOuts)) {
39 auto iter =
nodes().find(
id);
40 if (iter !=
nodes().end()) {
return iter->second.get(); }
47 if (matching.size() == 1) {
48 auto& vec = matching[0]->type().dataOutputs();
54 auto foundExecOutputs = matching[0]->type().execOutputs();
56 foundExecOutputs.end())) {
73 res.
addEntry(
"E47",
"Cannot have two nodes with the same ID",
74 {{
"Requested ID", boost::uuids::to_string(
id)}});
78 auto ptr = std::make_unique<NodeInstance>(
this, std::move(type), x, y, id);
80 auto emplaced = mNodes.emplace(
id, std::move(ptr)).first;
82 if (toFill !=
nullptr) { *toFill = emplaced->second.get(); }
88 boost::string_view
name)
const noexcept {
89 std::vector<NodeInstance*> ret;
90 for (
const auto& node : mNodes) {
91 if (node.second->type().module().fullName() ==
module &&
92 node.second->type().name() ==
name) {
93 ret.push_back(node.second.get());
101 boost::string_view typeName,
const nlohmann::json& typeJSON,
102 float x,
float y, boost::uuids::uuid
id,
NodeInstance** toFill) {
106 std::unique_ptr<NodeType> nodeType;
109 if (!res) {
return res; }
110 res +=
insertNode(std::move(nodeType), x, y,
id, toFill);
124 for (
const auto& pair : execSlot) {
125 if (pair.first !=
nullptr) { res +=
disconnectExec(*pair.first, pair.second); }
131 if (pair.first !=
nullptr) { res +=
disconnectExec(nodeToRemove, ID); }
137 if (pair.first !=
nullptr) {
145 for (
const auto& pair : dataSlot) {
146 if (pair.first !=
nullptr) {
disconnectData(nodeToRemove, ID, *pair.first); }
151 nodes().erase(nodeToRemove.
id());
159 nlohmann::json entry = nlohmann::json::object();
161 auto& data = entry[
"data"];
162 data = nlohmann::json::array();
163 for (
auto in :
dataInputs()) { data.push_back({{in.name, in.type.qualifiedName()}}); }
165 auto& exec = entry[
"exec"];
166 exec = nlohmann::json::array();
167 for (
const auto& in :
execInputs()) { exec.push_back(in); }
177 nlohmann::json exit = nlohmann::json::object();
179 auto& data = exit[
"data"];
180 data = nlohmann::json::array();
181 for (
auto out :
dataOutputs()) { data.push_back({{out.name, out.type.qualifiedName()}}); }
183 auto& exec = exit[
"exec"];
184 exec = nlohmann::json::array();
185 for (
const auto& out :
execOutputs()) { exec.push_back(out); }
197 if (toFill !=
nullptr) { *toFill = ent; }
204 std::unique_ptr<NodeType> entryNodeType;
207 res +=
insertNode(std::move(entryNodeType), x, y,
id, toFill);
216 if (addBefore < mDataInputs.size()) {
217 mDataInputs.emplace(mDataInputs.cbegin() + addBefore, std::move(name), type);
219 mDataInputs.emplace_back(std::move(name), type);
228 if (idx < mDataInputs.size()) { mDataInputs.erase(mDataInputs.begin() + idx); }
236 if (idx < mDataInputs.size()) { mDataInputs[idx].name = std::move(newName); }
244 if (idx < mDataInputs.size()) { mDataInputs[idx].type = std::move(newType); }
252 if (addBefore < mDataOutputs.size()) {
253 mDataOutputs.emplace(mDataOutputs.cbegin() + addBefore, std::move(name), type);
255 mDataOutputs.emplace_back(std::move(name), type);
264 if (idx < mDataOutputs.size()) { mDataOutputs.erase(mDataOutputs.begin() + idx); }
272 if (idx < mDataOutputs.size()) { mDataOutputs[idx].name = std::move(newName); }
277 if (idx < mDataOutputs.size()) { mDataOutputs[idx].type = std::move(newType); }
282 std::vector<llvm::Type*> arguments;
286 arguments.push_back(llvm::IntegerType::getInt32Ty(
context().llvmContext()));
288 for (
const auto& p :
dataInputs()) { arguments.push_back(p.type.llvmType()); }
292 arguments.push_back(llvm::PointerType::get(p.type.llvmType(), 0));
295 return llvm::FunctionType::get(llvm::IntegerType::getInt32Ty(
context().llvmContext()),
303 if (addBefore < mExecInputs.size()) {
305 mExecInputs.emplace(mExecInputs.cbegin() + addBefore, std::move(name));
307 mExecInputs.emplace_back(std::move(name));
316 if (idx < mExecInputs.size()) { mExecInputs.erase(mExecInputs.begin() + idx); }
324 if (idx < mExecInputs.size()) { mExecInputs[idx] = std::move(name); }
332 if (addBefore < mExecOutputs.size()) {
334 mExecOutputs.emplace(mExecOutputs.cbegin() + addBefore, std::move(name));
336 mExecOutputs.emplace_back(std::move(name));
345 if (idx < mExecOutputs.size()) { mExecOutputs.erase(mExecOutputs.begin() + idx); }
353 if (idx < mExecOutputs.size()) { mExecOutputs[idx] = std::move(name); }
357 void GraphFunction::updateEntries() {
360 for (
auto entry : matching) {
361 if (entry ==
nullptr) {
return; }
363 std::unique_ptr<NodeType> entryNodeType;
366 entry->setType(std::move(entryNodeType));
370 void GraphFunction::updateExits() {
372 std::unique_ptr<NodeType> exitNodeType;
375 exitNode->setType(std::move(exitNodeType));
380 for (
auto local : mLocalVariables) {
381 if (local.name == name) {
return local; }
392 if (inserted !=
nullptr) { *inserted =
false; }
399 mLocalVariables.emplace_back(name, type);
400 if (inserted !=
nullptr) { *inserted =
true; }
402 return mLocalVariables[mLocalVariables.size() - 1];
406 auto iter = std::find_if(mLocalVariables.begin(), mLocalVariables.end(),
407 [&](
auto& toTest) {
return toTest.name ==
name; });
410 if (iter != mLocalVariables.end()) {
411 mLocalVariables.erase(iter);
414 if (!erased) {
return false; }
421 for (
const auto& node : setNodes) {
removeNode(*node); }
423 for (
const auto& node : getNodes) {
removeNode(*node); }
432 bool setanything =
false;
433 for (
auto& var : mLocalVariables) {
434 if (var.name == oldName) {
443 if (!setanything) {
return; }
447 for (
const auto& node : setNodes) {
449 std::unique_ptr<NodeType> ty;
454 node->setType(std::move(ty));
458 for (
const auto& node : getNodes) {
460 std::unique_ptr<NodeType> ty;
465 node->setType(std::move(ty));
475 for (
auto& var : mLocalVariables) {
476 if (var.name == name) {
477 var.type = std::move(newType);
484 for (
const auto& node : setNodes) {
486 std::unique_ptr<NodeType> ty;
491 node->setType(std::move(ty));
495 for (
const auto& node : getNodes) {
497 std::unique_ptr<NodeType> ty;
502 node->setType(std::move(ty));
507 bool updateReferences) {
511 auto oldName = mName;
512 mName = newName.to_string();
514 if (updateReferences) {
517 for (
auto node : toUpdate) {
518 std::unique_ptr<NodeType> ty;
520 if (!res) {
return {}; }
522 node->setType(std::move(ty));
void addDataOutput(const DataType &type, std::string name, size_t addBefore=(std::numeric_limits< size_t >::max)())
Add an data output to the end of the argument list.
GraphFunction(GraphModule &mod, std::string name, std::vector< NamedDataType > dataIns, std::vector< NamedDataType > dataOuts, std::vector< std::string > execIns, std::vector< std::string > execOuts)
Construct a graph–don't call this directly use GraphModule::getorCreateFunction. ...
void addDataInput(const DataType &type, std::string name, size_t addBefore=(std::numeric_limits< size_t >::max)())
Add an input to the end of the argument list.
Result getOrInsertEntryNode(float x, float y, boost::uuids::uuid id=boost::uuids::random_generator()(), NodeInstance **toFill=nullptr)
Creates an entry node if it doesn't already exist, else just return it.
std::vector< std::vector< std::pair< NodeInstance *, size_t > > > inputExecConnections
The connections that lead to this node, exec.
const std::vector< NamedDataType > & dataOutputs() const
Get the function data outputs in the format {type, docstring}.
Defines functions for validating GraphFunction objects.
void addEntry(const char *ec, const char *overview, nlohmann::json data)
Add a entry to the result, either a warning or an error.
Result nodeTypeFromModule(const boost::filesystem::path &moduleName, boost::string_view typeName, const nlohmann::json &data, std::unique_ptr< NodeType > *toFill) noexcept
Gets a NodeType from the JSON and name.
Result removeNode(NodeInstance &nodeToRemove)
Remove a node from the function.
Result createEntryNodeType(std::unique_ptr< NodeType > *toFill) const
Create a fresh NodeType for an entry.
void retypeDataInput(size_t idx, DataType newType)
Change the type of a data input This also updates the entry node and disconnects invalid connections...
const std::vector< std::string > & execInputs() const
Get the function exec inputs.
Result insertNode(std::unique_ptr< NodeType > type, float x, float y, boost::uuids::uuid id=boost::uuids::random_generator()(), NodeInstance **toFill=nullptr)
Add a node to the graph.
NamedDataType localVariableFromName(boost::string_view name) const
Get a local varaible by name.
const std::vector< std::string > & execOutputs() const
Get the function exec outputs.
Defines the Result class and related functions.
void removeDataInput(size_t idx)
Remove an input from the argument list Also removes invalid connections If idx is out of range...
std::vector< std::vector< std::pair< NodeInstance *, size_t > > > outputDataConnections
The connections that lead out of this node, data.
Context & context() const
Get the context.
void retypeLocalVariable(boost::string_view name, DataType newType)
Set a new type to a local variable.
std::string qualifiedName() const
Get the qualified name of the function Same as module().fullName() + ":" + name();.
std::vector< std::pair< NodeInstance *, size_t > > inputDataConnections
The connections that go into this node, data.
std::vector< NodeInstance * > findInstancesOfType(const boost::filesystem::path &moduleName, boost::string_view typeName) const
Find all uses of a node type in all the loaded modules.
void removeExecOutput(size_t idx)
Remove an exec output from the argument list If idx is out of range, this function does nothing...
Definitions for mangling functions.
GraphModule & module() const
Get the GraphModule that contains this GraphFunction.
void removeDataOutput(size_t idx)
Remove an data output from the argument list Also removes invalid connections If idx is out of range...
Result createExitNodeType(std::unique_ptr< NodeType > *toFill) const
Create a fresh NodeType for an exit.
std::string name() const
Get the name of the function.
Basicaly a std::pair<std::string, DataType>, except it has nicer names.
std::string fullName() const
Get the full name of the module.
void removeExecInput(size_t idx)
Remove an exec input from the argument list If idx is out of range, this function does nothing...
void renameExecInput(size_t idx, std::string name)
Change the name for an exec input If idx is out of range, this function does nothing.
NodeInstance * nodeByID(const boost::uuids::uuid &id) const
Get a node with a given ID.
std::vector< NodeInstance * > setName(boost::string_view newName, bool updateReferences=true)
Set the name of the function.
NodeInstance * entryNode() const noexcept
Gets the node with type lang:entry returns nullptr on failure Also returns nullptr if there are two e...
Result disconnectData(NodeInstance &lhs, size_t lhsConnID, NodeInstance &rhs)
Disconnect a data connection.
void renameExecOutput(size_t idx, std::string name)
Rename an exec output If idx is out of range, this function does nothing.
std::unordered_map< boost::uuids::uuid, std::unique_ptr< NodeInstance > > & nodes()
Get the nodes in the function Usually called by connectData or connectExec or GraphFunction.
void retypeDataOutput(size_t idx, DataType newType)
Change the type of a data output This also updates all exit nodes and disconnects invalid connections...
void renameLocalVariable(std::string oldName, std::string newName)
Rename a local variable.
Defines the NodeType class.
std::string qualifiedName() const
Get the qualified name of the type (module().fullName() + ":" name())
bool removeLocalVariable(boost::string_view name)
Remove a local variable from the function by name.
Defines the DataType class.
void updateLastEditTime(std::time_t newLastEditTime=std::time(nullptr))
Update the last edit time, signifying that it's been edited.
std::vector< NodeInstance * > nodesWithType(const boost::filesystem::path &module, boost::string_view name) const noexcept
Gets the nodes with a given type.
Result nodeTypeFromName(boost::string_view name, const nlohmann::json &jsonData, std::unique_ptr< NodeType > *toFill) override
Create a node type that is in the module from the name and json.
std::vector< std::pair< NodeInstance *, size_t > > outputExecConnections
The connections that go out of this node, exec.
Module that holds graph functions.
Result disconnectExec(NodeInstance &lhs, size_t lhsConnID)
Disconnect a exec connection.
Defines the GraphModule class.
void renameDataOutput(size_t idx, std::string newName)
Modify an data output (change it's type and docstring)
The namespace where chigraph lives.
void addExecOutput(std::string name, size_t addBefore=(std::numeric_limits< size_t >::max)())
Add an exec output to the end of the argument list.
void addExecInput(std::string name, size_t addBefore=(std::numeric_limits< size_t >::max)())
Add an exec input to the end of the argument list.
Defines the Context class and related functions.
A type of data Loose wrapper around llvm::Type*, except it knows which ChiModule it's in and it embed...
const std::vector< NamedDataType > & dataInputs() const
Get the function data inputs in the format {type, docstring}.
llvm::FunctionType * functionType() const
Get the LLVM function type for the function.
boost::uuids::uuid id() const
Get the ID of the instance, unique to the graph.
The result object, used for identifiying errors with good diagnostics.
Declares the GraphFunction class.
NamedDataType getOrCreateLocalVariable(std::string name, DataType type, bool *inserted=nullptr)
Create a new local varaible in the module.
Defines the NodeInstance class and related functions.
void renameDataInput(size_t idx, std::string newName)
Rename a data input This also updates the entry node If idx is out of range, this function does nothi...