OpenVDB  12.1.0
Compiler.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: Apache-2.0
3 
4 /// @file compiler/Compiler.h
5 ///
6 /// @authors Nick Avramoussis, Francisco Gochez, Richard Jones
7 ///
8 /// @brief The OpenVDB AX Compiler class provides methods to generate
9 /// AX executables from a provided AX AST (or directly from a given
10 /// string). The class object exists to cache various structures,
11 /// primarily LLVM constructs, which benefit from existing across
12 /// additional compilation runs.
13 ///
14 
15 #ifndef OPENVDB_AX_COMPILER_HAS_BEEN_INCLUDED
16 #define OPENVDB_AX_COMPILER_HAS_BEEN_INCLUDED
17 
18 #include "CompilerOptions.h"
19 #include "CustomData.h"
20 #include "Logger.h"
21 
22 #include "openvdb_ax/ax.h" // backward compat support for initialize()
23 #include "openvdb_ax/ast/Parse.h"
24 
25 #include <openvdb/version.h>
26 #include <openvdb/util/Assert.h>
27 
28 #include <memory>
29 #include <sstream>
30 
31 
32 namespace openvdb {
34 namespace OPENVDB_VERSION_NAME {
35 
36 namespace ax {
37 
38 namespace codegen {
39 // forward
40 class FunctionRegistry;
41 }
42 
43 /// @brief The compiler class. This holds a set of compiler options and
44 /// constructs executable objects (e.g. PointExecutable or VolumeExecutable)
45 /// from a syntax tree or snippet of code.
46 /// @note Compilers cannot be copied and it is _unsafe_ to call compile()
47 /// methods concurrently on instances of the same compiler (due to access
48 /// into the function registry currently not being thread safe). It is safe
49 /// to create new instances of a Compiler to compile programs concurrently.
51 {
52 public:
53  using Ptr = std::shared_ptr<Compiler>;
54  using UniquePtr = std::unique_ptr<Compiler>;
55 
56  /// @brief Construct a compiler object with given settings
57  /// @param options CompilerOptions object with various settings
58  Compiler(const CompilerOptions& options = CompilerOptions());
59  ~Compiler();
60 
61  Compiler(const Compiler&) = delete;
62  Compiler& operator=(const Compiler&) = delete;
63  Compiler(Compiler&&);
64  Compiler& operator=(Compiler&&);
65 
66  /// @brief Static method for creating Compiler objects
67  static UniquePtr create(const CompilerOptions& options = CompilerOptions());
68 
69  /// @brief Compile a given AST into an executable object of the given type.
70  /// @param syntaxTree An abstract syntax tree to compile
71  /// @param logger Logger for errors and warnings during compilation, this
72  /// should be linked to an ast::Tree and populated with AST node + line
73  /// number mappings for this Tree, e.g. during ast::parse(). This Tree can
74  /// be different from the syntaxTree argument.
75  /// @param data Optional external/custom data which is to be referenced by
76  /// the executable object. It allows one to reference data held elsewhere,
77  /// such as inside of a DCC, from inside the AX code
78  /// @note If the logger has not been populated with AST node and line
79  /// mappings, all messages will appear without valid line and column
80  /// numbers.
81  template <typename ExecutableT>
82  typename ExecutableT::Ptr
83  compile(const ast::Tree& syntaxTree,
84  Logger& logger,
85  const CustomData::Ptr data = CustomData::Ptr());
86 
87  /// @brief Compile a given snippet of AX code into an executable object of
88  /// the given type.
89  /// @param code A string of AX code
90  /// @param logger Logger for errors and warnings during compilation, will be
91  /// cleared of existing data
92  /// @param data Optional external/custom data which is to be referenced by
93  /// the executable object. It allows one to reference data held elsewhere,
94  /// such as inside of a DCC, from inside the AX code
95  /// @note If compilation is unsuccessful, will return nullptr. Logger can
96  /// then be queried for errors.
97  template <typename ExecutableT>
98  typename ExecutableT::Ptr
99  compile(const std::string& code,
100  Logger& logger,
101  const CustomData::Ptr data = CustomData::Ptr())
102  {
103  logger.clear();
104  const ast::Tree::ConstPtr syntaxTree = ast::parse(code.c_str(), logger);
105  if (syntaxTree) return compile<ExecutableT>(*syntaxTree, logger, data);
106  else return nullptr;
107  }
108 
109  /// @brief Compile a given snippet of AX code into an executable object of
110  /// the given type.
111  /// @param code A string of AX code
112  /// @param data Optional external/custom data which is to be referenced by
113  /// the executable object. It allows one to reference data held elsewhere,
114  /// such as inside of a DCC, from inside the AX code
115  /// @note Parser errors are handled separately from compiler errors.
116  /// Each are collected and produce runtime errors.
117  template <typename ExecutableT>
118  typename ExecutableT::Ptr
119  compile(const std::string& code,
120  const CustomData::Ptr data = CustomData::Ptr())
121  {
122  std::vector<std::string> errors;
123  openvdb::ax::Logger logger(
124  [&errors] (const std::string& error) {
125  errors.emplace_back(error + "\n");
126  },
127  [] (const std::string&) {} // ignore warnings
128  );
129  const ast::Tree::ConstPtr syntaxTree = ast::parse(code.c_str(), logger);
130  if (!errors.empty()) {
131  std::ostringstream os;
132  for (const auto& e : errors) os << e << "\n";
133  OPENVDB_THROW(AXSyntaxError, os.str());
134  }
135  OPENVDB_ASSERT(syntaxTree);
136  typename ExecutableT::Ptr exe = this->compile<ExecutableT>(*syntaxTree, logger, data);
137  if (!errors.empty()) {
138  std::ostringstream os;
139  for (const auto& e : errors) os << e << "\n";
140  OPENVDB_THROW(AXCompilerError, os.str());
141  }
142  OPENVDB_ASSERT(exe);
143  return exe;
144  }
145 
146  /// @brief Compile a given AST into an executable object of the given type.
147  /// @param syntaxTree An abstract syntax tree to compile
148  /// @param data Optional external/custom data which is to be referenced by
149  /// the executable object. It allows one to reference data held elsewhere,
150  /// such as inside of a DCC, from inside the AX code
151  /// @note Any errors encountered are collected into a single runtime error
152  template <typename ExecutableT>
153  typename ExecutableT::Ptr
154  compile(const ast::Tree& syntaxTree,
155  const CustomData::Ptr data = CustomData::Ptr())
156  {
157  std::vector<std::string> errors;
158  openvdb::ax::Logger logger(
159  [&errors] (const std::string& error) {
160  errors.emplace_back(error + "\n");
161  },
162  [] (const std::string&) {} // ignore warnings
163  );
164  auto exe = compile<ExecutableT>(syntaxTree, logger, data);
165  if (!errors.empty()) {
166  std::ostringstream os;
167  for (const auto& e : errors) os << e << "\n";
168  OPENVDB_THROW(AXCompilerError, os.str());
169  }
170  OPENVDB_ASSERT(exe);
171  return exe;
172  }
173 
174  /// @brief Sets the compiler's function registry object.
175  /// @param functionRegistry A unique pointer to a FunctionRegistry object.
176  /// The compiler will take ownership of the registry that was passed in.
177  /// @todo Perhaps allow one to register individual functions into this
178  /// class rather than the entire registry at once, and/or allow one to
179  /// extract a pointer to the registry and update it manually.
180  void setFunctionRegistry(std::unique_ptr<codegen::FunctionRegistry>&& functionRegistry);
181 
182  ///////////////////////////////////////////////////////////////////////////
183 
184 private:
185  template <typename ExeT, typename GenT>
186  typename ExeT::Ptr
187  compile(const ast::Tree& tree,
188  const std::string& moduleName,
189  const std::vector<std::string>& functions,
190  CustomData::Ptr data,
191  Logger& logger);
192 
193 private:
194  CompilerOptions mCompilerOptions;
195  std::unique_ptr<codegen::FunctionRegistry> mFunctionRegistry;
196 };
197 
198 
199 } // namespace ax
200 } // namespace OPENVDB_VERSION_NAME
201 } // namespace openvdb
202 
203 #endif // OPENVDB_AX_COMPILER_HAS_BEEN_INCLUDED
204 
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
#define OPENVDB_AX_API
Definition: Platform.h:312
A Tree is the highest concrete (non-abstract) node in the entire AX AST hierarchy. It represents an entire conversion of a valid AX string.
Definition: AST.h:562
Parsing methods for creating abstract syntax trees out of AX code.
Single header include which provides methods for initializing AX and running a full AX pipeline (pars...
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
std::unique_ptr< Compiler > UniquePtr
Definition: Compiler.h:54
ExecutableT::Ptr compile(const std::string &code, const CustomData::Ptr data=CustomData::Ptr())
Compile a given snippet of AX code into an executable object of the given type.
Definition: Compiler.h:119
Definition: Exceptions.h:13
OpenVDB AX Compiler Options.
std::shared_ptr< CustomData > Ptr
Definition: CustomData.h:37
ExecutableT::Ptr compile(const std::string &code, Logger &logger, const CustomData::Ptr data=CustomData::Ptr())
Compile a given snippet of AX code into an executable object of the given type.
Definition: Compiler.h:99
Definition: Exceptions.h:39
The compiler class. This holds a set of compiler options and constructs executable objects (e...
Definition: Compiler.h:50
Logging system to collect errors and warnings throughout the different stages of parsing and compilat...
Definition: Exceptions.h:37
Logger for collecting errors and warnings that occur during AX compilation.
Definition: Logger.h:57
void clear()
Clear the tree-code mapping and reset the number of errors/warnings.
Settings which control how a Compiler class object behaves.
Definition: CompilerOptions.h:47
Access to the CustomData class which can provide custom user user data to the OpenVDB AX Compiler...
std::shared_ptr< Compiler > Ptr
Definition: Compiler.h:53
ExecutableT::Ptr compile(const ast::Tree &syntaxTree, const CustomData::Ptr data=CustomData::Ptr())
Compile a given AST into an executable object of the given type.
Definition: Compiler.h:154
OPENVDB_AX_API openvdb::ax::ast::Tree::ConstPtr parse(const char *code, ax::Logger &logger)
Construct an abstract syntax tree from a code snippet.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
std::shared_ptr< const Tree > ConstPtr
Definition: AST.h:565
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218