Spicy
unit.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <unistd.h>
6 
7 #include <functional>
8 #include <memory>
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include <hilti/rt/filesystem.h>
14 
15 #include <hilti/ast/id.h>
16 #include <hilti/ast/module.h>
17 #include <hilti/base/logger.h>
18 #include <hilti/base/result.h>
19 #include <hilti/base/util.h>
20 #include <hilti/compiler/context.h>
21 #include <hilti/compiler/detail/cxx/unit.h>
22 #include <hilti/compiler/jit.h>
23 
24 namespace hilti {
25 
26 struct Plugin;
27 
28 namespace linker {
37 using MetaData = detail::cxx::linker::MetaData;
38 } // namespace linker
39 
47 class Unit {
48 public:
50  ~Unit();
51 
53  NodeRef moduleRef() const { return _module ? NodeRef(*_module) : NodeRef(); }
54 
59  Node& module() {
60  assert(_module);
61  return *_module;
62  }
63 
68  const auto& cacheIndex() { return _index; }
69 
71  const auto& id() const { return _index.id; }
72 
74  const auto& path() const { return _index.path; }
75 
82  const auto& extension() const { return _extension; }
83 
92  void setExtension(const hilti::rt::filesystem::path& ext) { _extension = ext; }
93 
94  enum ASTState { Modified, NotModified };
95 
97  void resetAST();
98 
105  Result<Nothing> buildASTScopes(const Plugin& plugin);
106 
114  Result<ASTState> resolveAST(const Plugin& plugin);
115 
122  bool validateASTPre(const Plugin& plugin);
123 
130  bool validateASTPost(const Plugin& plugin);
131 
138  Result<Nothing> transformAST(const Plugin& plugin);
139 
145  Result<Nothing> codegen();
146 
155  Result<Nothing> print(std::ostream& out) const;
156 
165  Result<Nothing> createPrototypes(std::ostream& out);
166 
173  Result<CxxCode> cxxCode() const;
174 
176  const auto& dependencies() { return _dependencies; }
177 
179  void clearDependencies() { _dependencies.clear(); };
180 
187  bool addDependency(std::shared_ptr<Unit> unit);
188 
195  if ( _cxx_unit )
196  return _cxx_unit->linkerMetaData();
197 
198  return result::Error("no C++ code compiled");
199  }
200 
206  bool isCompiledHILTI() const { return _module.has_value(); }
207 
213  bool requiresCompilation();
214 
219  void setRequiresCompilation() { _requires_compilation = true; }
220 
224  bool isResolved() { return _resolved; }
225 
232  void setResolved(bool resolved) { _resolved = resolved; }
233 
235  std::shared_ptr<Context> context() const { return _context.lock(); }
236 
238  const Options& options() const { return context()->options(); }
239 
253  static Result<std::shared_ptr<Unit>> fromSource(const std::shared_ptr<Context>& context,
254  const hilti::rt::filesystem::path& path,
255  std::optional<hilti::rt::filesystem::path> ast_extension = {});
256 
270  static std::shared_ptr<Unit> fromModule(const std::shared_ptr<Context>& context, hilti::Module module,
271  hilti::rt::filesystem::path extension);
272 
288  static Result<std::shared_ptr<Unit>> fromImport(const std::shared_ptr<Context>& context, const ID& id,
289  const hilti::rt::filesystem::path& parse_extension,
290  const hilti::rt::filesystem::path& ast_extension,
291  std::optional<ID> scope,
292  std::vector<hilti::rt::filesystem::path> search_dirs);
293 
303  static Result<std::shared_ptr<Unit>> fromCache(const std::shared_ptr<Context>& context, const hilti::ID& id,
304  const hilti::rt::filesystem::path& extension);
305 
314  static Result<std::shared_ptr<Unit>> fromCache(const std::shared_ptr<Context>& context,
315  const hilti::rt::filesystem::path& path);
316 
325  static Result<std::shared_ptr<Unit>> fromCXX(std::shared_ptr<Context> context, detail::cxx::Unit cxx,
326  const hilti::rt::filesystem::path& path = "");
327 
338  static Result<std::shared_ptr<Unit>> link(const std::shared_ptr<Context>& context,
339  const std::vector<linker::MetaData>& mds);
340 
357  static std::pair<bool, std::optional<linker::MetaData>> readLinkerMetaData(
358  std::istream& input, const hilti::rt::filesystem::path& path = "<input stream>");
359 
360 private:
361  // Private constructor initializing the unit's meta data. Use the public
362  // `from*()` factory functions instead to instantiate a unit.
363  Unit(std::shared_ptr<Context> context, ID id, hilti::rt::filesystem::path path,
364  hilti::rt::filesystem::path extension, Node&& module)
365  : _index(id, util::normalizePath(path)),
366  _extension(extension),
367  _module(std::move(module)),
368  _context(std::move(context)) {}
369 
370  Unit(std::shared_ptr<Context> context, ID id, hilti::rt::filesystem::path path,
371  hilti::rt::filesystem::path extension, std::optional<detail::cxx::Unit> cxx_unit = {})
372  : _index(id, util::normalizePath(path)),
373  _extension(extension),
374  _context(std::move(context)),
375  _cxx_unit(std::move(cxx_unit)) {}
376 
377  // Backend for the public import() methods.
378  Result<context::CacheIndex> _import(const hilti::rt::filesystem::path& path, std::optional<ID> expected_name);
379 
380  // Reports any errors recorded in the AST to stderr.
381  //
382  // @returns false if there were errors, true if the AST is all good
383  bool _collectErrors();
384 
385  // Recursively destroys the module's AST.
386  void _destroyModule();
387 
388  // Parses a source file with the appropriate plugin.
389  static Result<hilti::Module> _parse(const std::shared_ptr<Context>& context,
390  const hilti::rt::filesystem::path& path);
391 
392  context::CacheIndex _index; // index for the context's module cache
393  hilti::rt::filesystem::path _extension; // AST extension, which may differ from source file
394  std::optional<Node> _module; // root node for AST (always a `Module`), if available
395  std::vector<std::weak_ptr<Unit>> _dependencies; // recorded dependencies
396  std::weak_ptr<Context> _context; // global context
397  std::optional<detail::cxx::Unit> _cxx_unit; // compiled C++ code for this unit, once available
398  bool _resolved = false; // state of resolving the AST
399  bool _requires_compilation = false; // mark explicitly as requiring compilation to C++
400 };
401 
402 } // namespace hilti
Definition: context.h:106
void setExtension(const hilti::rt::filesystem::path &ext)
Definition: unit.h:92
Definition: result.h:18
Definition: context.h:33
const Options & options() const
Definition: unit.h:238
bool isCompiledHILTI() const
Definition: unit.h:206
bool isResolved()
Definition: unit.h:224
const auto & id() const
Definition: unit.h:71
Node & module()
Definition: unit.h:59
void setRequiresCompilation()
Definition: unit.h:219
NodeRef moduleRef() const
Definition: unit.h:53
Definition: unit.h:68
const auto & path() const
Definition: unit.h:74
Result< linker::MetaData > linkerMetaData() const
Definition: unit.h:194
Definition: plugin.h:52
const auto & dependencies()
Definition: unit.h:176
const auto & cacheIndex()
Definition: unit.h:68
std::shared_ptr< Context > context() const
Definition: unit.h:235
Definition: unit.h:47
Definition: module.h:21
Definition: node.h:113
Definition: node-ref.h:44
void clearDependencies()
Definition: unit.h:179
const auto & extension() const
Definition: unit.h:82
Definition: id.h:18
Definition: result.h:67
void setResolved(bool resolved)
Definition: unit.h:232