Spicy
unit.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <iostream>
6 #include <list>
7 #include <map>
8 #include <memory>
9 #include <set>
10 #include <string>
11 #include <tuple>
12 #include <utility>
13 #include <vector>
14 
15 #include <hilti/rt/filesystem.h>
16 #include <hilti/rt/json-fwd.h>
17 #include <hilti/rt/types/reference.h>
18 
19 #include <hilti/ast/ctor.h>
20 #include <hilti/ast/expression.h>
21 #include <hilti/ast/module.h>
22 #include <hilti/ast/operator.h>
23 #include <hilti/ast/statement.h>
24 #include <hilti/ast/type.h>
25 #include <hilti/ast/types/function.h>
26 #include <hilti/base/result.h>
27 #include <hilti/compiler/context.h>
28 #include <hilti/compiler/detail/cxx/elements.h>
29 #include <hilti/compiler/detail/cxx/formatter.h>
30 
31 namespace hilti {
32 namespace detail {
33 
34 namespace cxx {
35 
36 class Linker;
37 
38 namespace linker {
39 
41 
48 struct Join {
51  std::list<cxx::declaration::Type>
53  int64_t priority =
54  0;
55  bool declare_only = false;
57  bool operator<(const Join& other) const {
58  return std::make_tuple(id, priority, callee.id) < std::make_tuple(other.id, other.priority, other.callee.id);
59  }
60 };
61 
62 extern void to_json(nlohmann::json& j, const Join& x); // NOLINT
63 extern void from_json(const nlohmann::json& j, Join& x); // NOLINT
64 
65 } // namespace linker
66 
68 class Unit {
69 public:
70  Unit(std::shared_ptr<Context> context);
71 
72  void setModule(const hilti::Module& m);
73  cxx::ID moduleID() const { return _module_id; }
74 
75  void setUsesGlobals() { _uses_globals = true; }
76 
77  void add(const declaration::IncludeFile& i, const Meta& m = Meta());
78  void add(const declaration::Global& g, const Meta& m = Meta());
79  void add(const declaration::Constant& c, const Meta& m = Meta());
80  void add(const declaration::Type& t, const Meta& m = Meta());
81  void add(const declaration::Function& f, const Meta& m = Meta());
82  void add(const Function& f, const Meta& m = Meta());
83  void add(const std::string& stmt, const Meta& m = Meta()); // add generic top-level item
84  void add(const linker::Join& f);
85 
86  // Prioritize type with given ID to be written out so that others
87  // depending on it will have it available.
88  void prioritizeType(const cxx::ID& id) {
89  if ( std::find(_types_in_order.begin(), _types_in_order.end(), id) == _types_in_order.end() )
90  _types_in_order.push_back(id);
91  }
92 
93  bool hasDeclarationFor(const cxx::ID& id);
94  std::optional<cxx::declaration::Type> lookupType(const cxx::ID& id) const;
95 
96  void addComment(const std::string& comment);
97  void addInitialization(cxx::Block block) { _init_module.appendFromBlock(std::move(block)); }
98  void addPreInitialization(cxx::Block block) { _preinit_module.appendFromBlock(std::move(block)); }
99 
100  Result<Nothing> finalize();
101 
102  Result<Nothing> print(std::ostream& out) const; // only after finalize
103  Result<Nothing> createPrototypes(std::ostream& out); // only after finalize
104  void importDeclarations(const Unit& other); // only after finalize
105  Result<linker::MetaData> linkerMetaData() const; // only after finalize
106  cxx::ID cxxNamespace() const;
107 
108  std::shared_ptr<Context> context() const { return _context; }
109 
110  static std::pair<bool, std::optional<linker::MetaData>> readLinkerMetaData(std::istream& input);
111 
112 protected:
113  friend class Linker;
114  Unit(std::shared_ptr<Context> context, cxx::ID module_id);
115  Unit(std::shared_ptr<Context> context, cxx::ID module_id, const std::string& cxx_code);
116 
117 private:
118  void _generateCode(Formatter& f, bool prototypes_only);
119  void _addHeader(Formatter& f);
120  void _addModuleInitFunction();
121 
122  std::shared_ptr<Context> _context;
123 
124  cxx::ID _module_id;
125  hilti::rt::filesystem::path _module_path;
126  bool _no_linker_meta_data = false;
127  bool _uses_globals = false;
128 
129  std::optional<std::string> _cxx_code;
130 
131  std::vector<std::string> _comments;
132  std::set<declaration::IncludeFile> _includes;
133  std::map<ID, declaration::Type> _types;
134  std::vector<ID> _types_in_order;
135  std::map<ID, declaration::Type> _types_forward;
136  std::map<ID, declaration::Global> _globals;
137  std::map<ID, declaration::Constant> _constants;
138  std::map<ID, declaration::Constant> _constants_forward;
139  std::multimap<ID, declaration::Function> _function_declarations;
140  std::multimap<ID, Function> _function_implementations;
141  std::vector<std::string> _statements;
142  std::set<linker::Join> _linker_joins; // set to keep sorted.
143  std::set<std::string> _namespaces; // set to keep sorted.
144  std::set<ID> _ids;
145 
146  cxx::Block _init_module;
147  cxx::Block _preinit_module;
148  cxx::Block _init_globals;
149 };
150 
151 } // namespace cxx
152 } // namespace detail
153 } // namespace hilti
Definition: formatter.h:16
Definition: elements.h:177
std::list< cxx::declaration::Type > aux_types
Definition: unit.h:52
Definition: elements.h:109
Definition: unit.h:68
Definition: meta.h:18
cxx::ID id
Definition: unit.h:49
cxx::declaration::Function callee
Definition: unit.h:50
Definition: reference.h:47
Definition: linker.h:28
Definition: elements.h:66
Definition: module.h:20
bool declare_only
Definition: unit.h:55
Definition: elements.h:253
Definition: elements.h:142
int64_t priority
Definition: unit.h:53
Definition: result.h:67