GeNN  4.0.0
GPU enhanced Neuronal Networks (GeNN)
substitutions.h
Go to the documentation of this file.
1 #pragma once
2 
3 // Standard C++ includes
4 #include <map>
5 #include <stdexcept>
6 #include <string>
7 
8 // Standard C includes
9 #include <cassert>
10 
11 // GeNN code generator includes
12 #include "codeGenUtils.h"
13 
14 //--------------------------------------------------------------------------
15 // Substitutions
16 //--------------------------------------------------------------------------
17 namespace CodeGenerator
18 {
20 {
21 public:
22  Substitutions(const Substitutions *parent = nullptr) : m_Parent(parent)
23  {
24  assert(m_Parent != this);
25  }
26 
27  Substitutions(const std::vector<FunctionTemplate> &functions, const std::string &ftype) : m_Parent(nullptr)
28  {
29  // Loop through functions and add as substitutions
30  for(const auto &f: functions) {
31  const std::string &funcTemplate = (ftype == "double") ? f.doublePrecisionTemplate : f.singlePrecisionTemplate;
32  addFuncSubstitution(f.genericName, f.numArguments, funcTemplate);
33  }
34  }
35 
36  //--------------------------------------------------------------------------
37  // Public API
38  //--------------------------------------------------------------------------
39  void addVarSubstitution(const std::string &source, const std::string &destionation, bool allowOverride = false)
40  {
41  auto res = m_VarSubstitutions.emplace(source, destionation);
42  if(!allowOverride && !res.second) {
43  throw std::runtime_error("'" + source + "' already has a variable substitution");
44  }
45  }
46 
47  void addFuncSubstitution(const std::string &source, unsigned int numArguments, const std::string &funcTemplate, bool allowOverride = false)
48  {
49  auto res = m_FuncSubstitutions.emplace(std::piecewise_construct,
50  std::forward_as_tuple(source),
51  std::forward_as_tuple(numArguments, funcTemplate));
52  if(!allowOverride && !res.second) {
53  throw std::runtime_error("'" + source + "' already has a function substitution");
54  }
55  }
56 
57  bool hasVarSubstitution(const std::string &source) const
58  {
59  return (m_VarSubstitutions.find(source) != m_VarSubstitutions.end());
60  }
61 
62  const std::string &getVarSubstitution(const std::string &source) const
63  {
64  auto var = m_VarSubstitutions.find(source);
65  if(var != m_VarSubstitutions.end()) {
66  return var->second;
67  }
68  else if(m_Parent) {
69  return m_Parent->getVarSubstitution(source);
70  }
71  else {
72  throw std::runtime_error("Nothing to substitute for '" + source + "'");
73  }
74  }
75 
76  void apply(std::string &code) const
77  {
78  // Apply function and variable substitutions
79  // **NOTE** functions may contain variables so evaluate ALL functions first
80  applyFuncs(code);
81  applyVars(code);
82  }
83 
84  //--------------------------------------------------------------------------
85  // Public API
86  //--------------------------------------------------------------------------
87  const std::string operator[] (const std::string &source) const
88  {
89  return getVarSubstitution(source);
90  }
91 
92 private:
93  //--------------------------------------------------------------------------
94  // Private API
95  //--------------------------------------------------------------------------
96  void applyFuncs(std::string &code) const
97  {
98  // Apply function substitutions
99  for(const auto &f : m_FuncSubstitutions) {
100  functionSubstitute(code, f.first, f.second.first, f.second.second);
101  }
102 
103  // If we have a parent, apply their function substitutions too
104  if(m_Parent) {
105  m_Parent->applyFuncs(code);
106  }
107  }
108 
109  void applyVars(std::string &code) const
110  {
111  // Apply variable substitutions
112  for(const auto &v : m_VarSubstitutions) {
113  substitute(code, "$(" + v.first + ")", v.second);
114  }
115 
116  // If we have a parent, apply their variable substitutions too
117  if(m_Parent) {
118  m_Parent->applyVars(code);
119  }
120  }
121 
122  //--------------------------------------------------------------------------
123  // Members
124  //--------------------------------------------------------------------------
125  std::map<std::string, std::string> m_VarSubstitutions;
126  std::map<std::string, std::pair<unsigned int, std::string>> m_FuncSubstitutions;
127  const Substitutions *m_Parent;
128 };
129 } // namespace CodeGenerator
Substitutions(const Substitutions *parent=nullptr)
Definition: substitutions.h:22
const std::string & getVarSubstitution(const std::string &source) const
Definition: substitutions.h:62
Helper class for generating code - automatically inserts brackets, indents etc.
Definition: backendBase.h:22
Substitutions(const std::vector< FunctionTemplate > &functions, const std::string &ftype)
Definition: substitutions.h:27
Definition: substitutions.h:19
void functionSubstitute(std::string &code, const std::string &funcName, unsigned int numParams, const std::string &replaceFuncTemplate)
This function substitutes function calls in the form:
Definition: codeGenUtils.cc:287
void addVarSubstitution(const std::string &source, const std::string &destionation, bool allowOverride=false)
Definition: substitutions.h:39
void apply(std::string &code) const
Definition: substitutions.h:76
void addFuncSubstitution(const std::string &source, unsigned int numArguments, const std::string &funcTemplate, bool allowOverride=false)
Definition: substitutions.h:47
bool hasVarSubstitution(const std::string &source) const
Definition: substitutions.h:57
const std::string operator[](const std::string &source) const
Definition: substitutions.h:87
void substitute(std::string &s, const std::string &trg, const std::string &rep)
Tool for substituting strings in the neuron code strings or other templates.
Definition: codeGenUtils.cc:233