User Guide
visitor_utils.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2023 Blue Brain Project, EPFL.
3  * See the top-level LICENSE file for details.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #pragma once
9 
10 /**
11  * \file
12  * \brief Utility functions for visitors implementation
13  */
14 
15 #include <map>
16 #include <set>
17 #include <string>
18 #include <unordered_set>
19 
20 #include <ast/ast_decl.hpp>
21 #include <utils/common_utils.hpp>
22 
23 namespace nmodl {
24 namespace visitor {
25 
27 
28 /**
29  * \brief Return the "original_string" with a random suffix if "original_string" exists in "vars"
30  *
31  * Return a std::string in the form "original_string"_"random_string", where
32  * random_string is a string defined in the nmodl::utils::SingletonRandomString
33  * for the original_string. Vars is a const ref to std::set<std::string> which
34  * holds the names that need to be checked for uniqueness. Choose if the
35  * "random_string" will include numbers using "use_num"
36  *
37  * \param vars a const ref to std::set<std::string> which holds the names of the variables we should
38  * check for uniqueness. Normally this is a vector of all the variables defined in the
39  * mod file.
40  * \param original_string the original string to be suffixed with a random string
41  * \param use_num a UseNumbersInString enum value to choose if the random string will include
42  * numbers
43  * \return std::string the new string with the proper suffix if needed
44  */
45 std::string suffix_random_string(
46  const std::set<std::string>& vars,
47  const std::string& original_string,
49 
50 /// Return new name variable by appending `_suffix_COUNT` where `COUNT` is
51 /// number of times the given variable is already used.
52 std::string get_new_name(const std::string& name,
53  const std::string& suffix,
54  std::map<std::string, int>& variables);
55 
56 
57 /// Return pointer to local statement in the given block, otherwise nullptr
58 std::shared_ptr<ast::LocalListStatement> get_local_list_statement(const ast::StatementBlock& node);
59 
60 
61 /// Add empty local statement to given block if already doesn't exist
62 void add_local_statement(ast::StatementBlock& node);
63 
64 
65 /// Add new local variable to the block
66 ast::LocalVar* add_local_variable(ast::StatementBlock& node, const std::string& varname);
67 ast::LocalVar* add_local_variable(ast::StatementBlock& node, ast::Identifier* varname);
68 ast::LocalVar* add_local_variable(ast::StatementBlock& node, const std::string& varname, int dim);
69 
70 
71 /// Create ast statement node from given code in string format
72 std::shared_ptr<ast::Statement> create_statement(const std::string& code_statement);
73 
74 /// Same as for create_statement but for vectors of strings
75 std::vector<std::shared_ptr<ast::Statement>> create_statements(
76  const std::vector<std::string>::const_iterator& code_statements_beg,
77  const std::vector<std::string>::const_iterator& code_statements_end);
78 
79 
80 /// Create ast statement block node from given code in string format
81 std::shared_ptr<ast::StatementBlock> create_statement_block(
82  const std::vector<std::string>& code_statements);
83 
84 
85 /// Return set of strings with the names of all global variables
86 std::set<std::string> get_global_vars(const ast::Program& node);
87 
88 
89 /// Checks whether block contains a call to a particular function
90 bool calls_function(const ast::Ast& node, const std::string& name);
91 
92 } // namespace visitor
93 
94 /// traverse \a node recursively and collect nodes of given \a types
95 std::vector<std::shared_ptr<const ast::Ast>> collect_nodes(
96  const ast::Ast& node,
97  const std::vector<ast::AstNodeType>& types = {});
98 
99 /// traverse \a node recursively and collect nodes of given \a types
100 std::vector<std::shared_ptr<ast::Ast>> collect_nodes(
101  ast::Ast& node,
102  const std::vector<ast::AstNodeType>& types = {});
103 
104 /// Whether or not a solver of type name exists in the AST
105 bool solver_exists(const ast::Ast& node, const std::string& name);
106 
107 /// Whether a node of type `ast_type` exists as a subnode of `node`.
108 bool node_exists(const ast::Ast& node, ast::AstNodeType ast_type);
109 
110 /// Given AST node, return the NMODL string representation
111 std::string to_nmodl(const ast::Ast& node, const std::set<ast::AstNodeType>& exclude_types = {});
112 
113 /// Given a shared pointer to an AST node, return the NMODL string representation
114 template <typename T>
115 typename std::enable_if<std::is_base_of<ast::Ast, T>::value, std::string>::type to_nmodl(
116  const std::shared_ptr<T>& node,
117  const std::set<ast::AstNodeType>& exclude_types = {}) {
118  return to_nmodl(*node, exclude_types);
119 }
120 
121 /// Given AST node, return the JSON string representation
122 std::string to_json(const ast::Ast& node,
123  bool compact = false,
124  bool expand = false,
125  bool add_nmodl = false);
126 
127 /// The `result.first` of `statement_dependencies`.
128 std::string statement_dependencies_key(const std::shared_ptr<ast::Expression>& lhs);
129 
130 /// If \p lhs and \p rhs combined represent an assignment (we assume to have an "=" in between them)
131 /// we extract the variables on which the assigned variable depends on. We provide the input with
132 /// lhs and rhs because there are a few nodes that have this similar structure but slightly
133 /// different naming (binaryExpression, diff_eq_expression, linExpression)
134 std::pair<std::string, std::unordered_set<std::string>> statement_dependencies(
135  const std::shared_ptr<ast::Expression>& lhs,
136  const std::shared_ptr<ast::Expression>& rhs);
137 
138 /// Given a Indexed node, return the name with index
139 std::string get_indexed_name(const ast::IndexedName& node);
140 
141 /// Given a VarName node, return the full var name including index
142 std::string get_full_var_name(const ast::VarName& node);
143 
144 /// Is given name a one of the function for RANDOM construct
145 bool is_random_construct_function(const std::string& name);
146 
147 /// Is given name `nrn_pointing`.
148 bool is_nrn_pointing(const std::string& name);
149 
150 } // namespace nmodl
nmodl::get_indexed_name
std::string get_indexed_name(const ast::IndexedName &node)
Given a Indexed node, return the name with index.
Definition: visitor_utils.cpp:282
nmodl::to_nmodl
std::string to_nmodl(const ast::Ast &node, const std::set< ast::AstNodeType > &exclude_types)
Given AST node, return the NMODL string representation.
Definition: visitor_utils.cpp:234
nmodl::visitor::create_statements
std::vector< std::shared_ptr< Statement > > create_statements(const std::vector< std::string >::const_iterator &code_statements_beg, const std::vector< std::string >::const_iterator &code_statements_end)
Same as for create_statement but for vectors of strings.
Definition: visitor_utils.cpp:137
nmodl::visitor::calls_function
bool calls_function(const ast::Ast &node, const std::string &name)
Checks whether block contains a call to a particular function.
Definition: visitor_utils.cpp:194
ast_decl.hpp
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.
nmodl::visitor::get_local_list_statement
std::shared_ptr< ast::LocalListStatement > get_local_list_statement(const StatementBlock &node)
Return pointer to local statement in the given block, otherwise nullptr.
Definition: visitor_utils.cpp:74
nmodl
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
nmodl::to_json
std::string to_json(const ast::Ast &node, bool compact, bool expand, bool add_nmodl)
Given AST node, return the JSON string representation.
Definition: visitor_utils.cpp:242
nmodl::is_random_construct_function
bool is_random_construct_function(const std::string &name)
Is given name a one of the function for RANDOM construct.
Definition: visitor_utils.cpp:297
nmodl::statement_dependencies
std::pair< std::string, std::unordered_set< std::string > > statement_dependencies(const std::shared_ptr< ast::Expression > &lhs, const std::shared_ptr< ast::Expression > &rhs)
If lhs and rhs combined represent an assignment (we assume to have an "=" in between them) we extract...
Definition: visitor_utils.cpp:262
nmodl::ast::AstNodeType
AstNodeType
Enum type for every AST node type.
Definition: ast_decl.hpp:166
nmodl::solver_exists
bool solver_exists(const ast::Ast &node, const std::string &name)
Whether or not a solver of type name exists in the AST.
Definition: visitor_utils.cpp:224
nmodl::utils::UseNumbersInString
UseNumbersInString
Enum to wrap bool variable to select if random string should have numbers or not.
Definition: common_utils.hpp:51
nmodl::utils::WithNumbers
@ WithNumbers
Definition: common_utils.hpp:51
nmodl::statement_dependencies_key
std::string statement_dependencies_key(const std::shared_ptr< ast::Expression > &lhs)
The result.first of statement_dependencies.
Definition: visitor_utils.cpp:253
nmodl::is_nrn_pointing
bool is_nrn_pointing(const std::string &name)
Is given name nrn_pointing.
Definition: visitor_utils.cpp:301
nmodl::node_exists
bool node_exists(const ast::Ast &node, ast::AstNodeType ast_type)
Whether a node of type ast_type exists as a subnode of node.
Definition: visitor_utils.cpp:219
nmodl::get_full_var_name
std::string get_full_var_name(const ast::VarName &node)
Given a VarName node, return the full var name including index.
Definition: visitor_utils.cpp:286
nmodl::visitor::create_statement
std::shared_ptr< Statement > create_statement(const std::string &code_statement)
Convert given code statement (in string format) to corresponding ast node.
Definition: visitor_utils.cpp:127
nmodl::collect_nodes
std::vector< std::shared_ptr< const ast::Ast > > collect_nodes(const ast::Ast &node, const std::vector< ast::AstNodeType > &types)
traverse node recursively and collect nodes of given types
Definition: visitor_utils.cpp:206
nmodl::visitor::add_local_statement
void add_local_statement(StatementBlock &node)
Add empty local statement to given block if already doesn't exist.
Definition: visitor_utils.cpp:84
nmodl::visitor::get_new_name
std::string get_new_name(const std::string &name, const std::string &suffix, std::map< std::string, int > &variables)
Return new name variable by appending _suffix_COUNT where COUNT is number of times the given variable...
Definition: visitor_utils.cpp:62
nmodl::visitor::create_statement_block
std::shared_ptr< StatementBlock > create_statement_block(const std::vector< std::string > &code_statements)
Convert given code statement (in string format) to corresponding ast node.
Definition: visitor_utils.cpp:156
nmodl::visitor::add_local_variable
LocalVar * add_local_variable(StatementBlock &node, Identifier *varname)
Definition: visitor_utils.cpp:93
nmodl::visitor::suffix_random_string
std::string suffix_random_string(const std::set< std::string > &vars, const std::string &original_string, const UseNumbersInString use_num)
Return the "original_string" with a random suffix if "original_string" exists in "vars".
Definition: visitor_utils.cpp:33
common_utils.hpp
Common utility functions for file/dir manipulation.
nmodl::visitor::get_global_vars
std::set< std::string > get_global_vars(const Program &node)
Return set of strings with the names of all global variables.
Definition: visitor_utils.cpp:171