hobbes
a language, embedded compiler, and runtime for efficient dynamic expression evaluation, data storage and analysis
cc.H
Go to the documentation of this file.
1 
2 #ifndef HOBBES_EVAL_CC_HPP_INCLUDED
3 #define HOBBES_EVAL_CC_HPP_INCLUDED
4 
5 #include <hobbes/lang/expr.H>
6 #include <hobbes/lang/type.H>
7 #include <hobbes/lang/tylift.H>
8 #include <hobbes/lang/typeinf.H>
11 #include <hobbes/lang/typepreds.H>
12 #include <hobbes/read/parser.H>
13 #include <hobbes/eval/jitcc.H>
14 
15 #include <hobbes/util/func.H>
16 #include <hobbes/util/llvm.H>
17 #include <hobbes/util/str.H>
18 
19 #include <string>
20 #include <map>
21 #include <vector>
22 #include <stdexcept>
23 #include <iostream>
24 #include <unordered_map>
25 
26 namespace hobbes {
27 
28 typedef std::map<std::string, PolyTypePtr> TypeAliasMap;
29 typedef std::map<std::string, MonoTypePtr> MonoTypeAliasMap;
30 
31 // parameter parsing for the 'compileFn' family of functions
32 typedef std::function<ExprPtr(const std::string&)> ExprParser;
33 
34 template <typename ... NamesAndExpr>
35  struct PArgl {
36  };
37 template <>
38  struct PArgl<ExprPtr> {
39  static str::seq names(const ExprPtr&) { return str::seq(); }
40  static ExprPtr expr(const ExprParser&, const ExprPtr& e) { return e; }
41  };
42 template <>
43  struct PArgl<std::string> {
44  static str::seq names(const std::string&) { return str::seq(); }
45  static ExprPtr expr(const ExprParser& p, const std::string& e) { return p(e); }
46  };
47 template <>
48  struct PArgl<const char*> {
49  static str::seq names(const char*) { return str::seq(); }
50  static ExprPtr expr(const ExprParser& p, const char* e) { return p(std::string(e)); }
51  };
52 template <typename ... NamesAndExpr>
53  struct PArgl<const char*, NamesAndExpr...> {
54  static str::seq names(const char* x, const NamesAndExpr& ... args) { str::seq r = PArgl<NamesAndExpr...>::names(args...); r.insert(r.begin(), std::string(x)); return r; }
55  static ExprPtr expr(const ExprParser& p, const char*, const NamesAndExpr& ... args) { return PArgl<NamesAndExpr...>::expr(p, args...); }
56  };
57 template <typename ... NamesAndExpr>
58  struct PArgl<std::string, NamesAndExpr...> {
59  static str::seq names(const std::string& x, const NamesAndExpr& ... args) { str::seq r = PArgl<NamesAndExpr...>::names(args...); r.insert(r.begin(), x); return r; }
60  static ExprPtr expr(const ExprParser& p, const std::string&, const NamesAndExpr& ... args) { return PArgl<NamesAndExpr...>::expr(p, args...); }
61  };
62 
63 // the main compiler
64 class cc : public typedb {
65 public:
66  cc();
67  virtual ~cc();
68 
69  // parse expressions
70  typedef ModulePtr (*readModuleFileFn)(cc*, const std::string&);
71  ModulePtr readModuleFile(const std::string&);
72  void setReadModuleFileFn(readModuleFileFn);
73 
74  typedef ModulePtr (*readModuleFn)(cc*, const std::string&);
75  ModulePtr readModule(const std::string&);
76  void setReadModuleFn(readModuleFn);
77 
78  typedef std::pair<std::string, ExprPtr> (*readExprDefnFn)(cc*, const std::string&);
79  std::pair<std::string, ExprPtr> readExprDefn(const std::string&);
80  void setReadExprDefnFn(readExprDefnFn);
81 
82  typedef ExprPtr (*readExprFn)(cc*, const std::string&);
83  ExprPtr readExpr(const std::string&);
84  void setReadExprFn(readExprFn);
85 private:
86  readModuleFileFn readModuleFileF;
87  readModuleFn readModuleF;
88  readExprDefnFn readExprDefnF;
89  readExprFn readExprF;
90 public:
91  // type-safe compilation to C++ function pointers
92  template <typename RFn, typename ... NamesAndExpr>
93  typename func<RFn>::type compileFn(NamesAndExpr ... args) {
94  static_assert(func<RFn>::arity == sizeof...(NamesAndExpr)-1, "Formal parameter list and expected function type arity mismatch");
95  return reinterpret_cast<typename func<RFn>::type>(
96  unsafeCompileFn(
97  lift<RFn>::type(*this),
99  PArgl<NamesAndExpr...>::expr([&](const std::string& x){return this->readExpr(x);}, args...)
100  )
101  );
102  }
103 
104  // perform type-checking, explicit type annotation, and type class resolution
105  ExprPtr unsweetenExpression(const TEnvPtr& te, const ExprPtr& e);
106  ExprPtr unsweetenExpression(const TEnvPtr& te, const std::string& vname, const ExprPtr& e);
107  ExprPtr unsweetenExpression(const ExprPtr& e);
108  ExprPtr unsweetenExpression(const std::string& vname, const ExprPtr& e);
109  ExprPtr normalize(const ExprPtr& e); // unalias + unsweeten
110 
111  // access the LLVM resources
112  llvm::IRBuilder<>* builder() const;
113  llvm::Module* module() const;
114 
115  // dump the contents of the active type environment (useful for debugging)
116  void dumpTypeEnv() const;
117  void dumpTypeEnv(str::seq* syms, str::seq* types) const;
118  std::string showTypeEnv() const;
119 
120  const TEnvPtr& typeEnv() const;
121 
122  // forward-declare a variable binding
123  void forwardDeclare(const std::string& vname, const QualTypePtr& qt);
124 
125  // is a variable merely forward-declared, or does it have a definition?
126  bool hasValueBinding(const std::string& vname);
127 
128  // process and define a set of residual definitions produced by type unqualification
131  void drainUnqualifyDefs(const Definitions& ds);
132 
133  // compile an expression and associate it with a name
134  void define(const std::string& vname, const ExprPtr& e);
135  void define(const std::string& vname, const std::string& expr);
136 
137  // shorthand for class instance definitions for classes with 0 or 1 members
138  void overload(const std::string&, const MonoTypes&);
139  void overload(const std::string&, const MonoTypes&, const ExprPtr&);
140  void overload(const std::string&, const MonoTypes&, const std::string&);
141 
142  // add a type class instance to a known class (wrap up recursive unsweetening/def-draining)
143  void addInstance(const TClassPtr&, const TCInstancePtr&);
144 
145  // dump the contents of the generated module (useful for debugging)
146  void dumpModule();
147 
148  // get the x86 machine code for an expression (useful for debugging)
149  typedef std::vector<unsigned char> bytes;
150  bytes machineCodeForExpr(const std::string& expr);
151 
152  // keep track of C++ classes so that we can perform upcasts where necessary
153  template <typename T>
154  void addObj() {
155  this->objs->add<T>();
156  }
157 
158  // convenience method for lifting C++ types
159  template <typename T>
161  return generalize(lift<T>::type(*this));
162  }
163 
164  template <typename T>
166  return lift<T>::type(*this);
167  }
168 
169  // bind a C++ value (be sure it stays in scope!)
170  void bind(const PolyTypePtr& tn, const std::string& vn, void* x);
171 
172  template <typename T>
173  void bind(const std::string& vn, T* x) {
174  bind(generalize(liftValue<T*>::type(*this, x)), vn, reinterpret_cast<void*>(x));
175  }
176 
177  template <typename T, int N>
178  void bindArr(const std::string& vn, T x[N]) {
179  bind(polytype(qualtype(arrayty(lift<T>::type(*this), N))), vn, reinterpret_cast<void*>(x));
180  }
181 
182  // simplify binding user functions
183  template <typename R, typename ... Args>
184  void bind(const std::string& fn, R (*pfn)(Args...)) {
185  bindExternFunction(fn, lift<R(Args...)>::type(*this), (void*)pfn);
186  }
187 private:
188  typedef std::pair<str::seq, MonoTypePtr> TTyDef;
189  typedef std::unordered_map<std::string, TTyDef> TTyDefs;
190  TTyDefs ttyDefs;
191 public:
192  // allow the definition of transparent type aliases
193  // ("transparent" in the sense that all other aspects of compilation see the fully expanded type)
194  void defineTypeAlias(const std::string& name, const str::seq& argNames, const MonoTypePtr& ty);
195  bool isTypeAliasName(const std::string& name) const;
196  MonoTypePtr replaceTypeAliases(const MonoTypePtr& ty) const;
197 
198  // typedb interface
199  PolyTypePtr opaquePtrPolyType(const std::type_info& ti, unsigned int sz, bool inStruct);
200  MonoTypePtr opaquePtrMonoType(const std::type_info& ti, unsigned int sz, bool inStruct);
201 
202  PolyTypePtr generalize(const MonoTypePtr& mt) const;
203 
204  MonoTypePtr defineNamedType(const std::string& name, const str::seq& argNames, const MonoTypePtr& ty);
205  bool isTypeName(const std::string&) const;
206  MonoTypePtr namedTypeRepresentation(const std::string&) const;
207 
208  // an 'unsafe' compilation method
209  // (the compiled function will conform to the input type description, but this type structure will not be available to C++)
210  void* unsafeCompileFn(const MonoTypePtr& retTy, const str::seq& names, const MonoTypes& argTys, const ExprPtr& exp);
211  void* unsafeCompileFn(const MonoTypePtr& fnTy, const str::seq& names, const ExprPtr& exp);
212  void* unsafeCompileFn(const MonoTypePtr& fnTy, const str::seq& names, const std::string& exp);
213  void releaseMachineCode(void*);
214 
215  // compile/optimization options
216  void enableModuleInlining(bool f);
217  bool enableModuleInlining() const;
218  void buildInterpretedMatches(bool f);
219  bool buildInterpretedMatches() const;
220  void requireMatchReachability(bool f);
221  bool requireMatchReachability() const;
222  void alwaysLowerPrimMatchTables(bool);
223  bool alwaysLowerPrimMatchTables() const;
224 
225  // allow caller to gather a vector of unreachable rows arising from match compilation
227 
228  // allow low-level functions to be added
229  void bindLLFunc(const std::string&, op*);
230 
231  // bind external functions
232  void bindExternFunction(const std::string& fname, const MonoTypePtr& fty, void* fn);
233 
234  // have we already loaded the standard prelude?
235  // (this is a bit of a hack to avoid some automatic translations that assume prelude functions _within_ the prelude)
236  bool preludeLoaded() const;
237 private:
238  // the JIT engine that compiles our monotyped expressions
240 
241  // optimization options
246 
247  // the bound root type-def environment
249  TypeAliasMap typeAliases;
250 
251  PolyTypePtr lookupVarType(const std::string& vname) const;
252 
253  // global variables
254  void definePolyValue(const std::string& vname, const ExprPtr& unsweetExp);
255 
256  // the bound root function environment
257  bool booted;
258 
259  // track C++ object relationships
261 private:
262  // disable copying
263  cc(const cc&);
264  void operator=(const cc&);
265 };
266 
267 #define LIFTCTY(cc, e) (cc).liftMonoType<decltype(e)>()
268 
269 template <typename T>
270  struct rccF {
271  static T compile(cc* c, const str::seq& vns, const std::string& expr) {
272  throw std::runtime_error("Internal error, unsupported compilation target type");
273  }
274  };
275 
276 template <typename R, typename ... Args>
277  struct rccF<R(*)(Args...)> {
278  typedef R (*cbF)(Args...);
279  static cbF compile(cc* c, const str::seq& vns, const std::string& expr) {
280  return (cbF)c->unsafeCompileFn(lift<cbF>::type(*c), vns, expr);
281  }
282  };
283 
284 template <typename T>
285  T compileTo(cc* c, const str::seq& vns, const std::string& expr) {
286  return rccF<T>::compile(c, vns, expr);
287  }
288 
289 }
290 
291 // support binding to C++ class member functions
292 #define memberfn(e) &hobbes::mfnThunk< decltype(e), decltype(e), e >::fn
293 
294 #endif
std::shared_ptr< PolyType > PolyTypePtr
Definition: type.H:23
Types types(const Constants &cs)
Definition: llvm.H:357
Definition: tylift.H:115
std::shared_ptr< TCInstance > TCInstancePtr
Definition: class.H:24
static str::seq names(const char *x, const NamesAndExpr &... args)
Definition: cc.H:54
PolyTypePtr generalize(const QualTypePtr &qt)
Definition: type.C:2016
Definition: jitcc.H:33
TEnvPtr tenv
Definition: cc.H:248
Definition: func.H:8
readModuleFileFn readModuleFileF
Definition: cc.H:86
MonoTypePtr arrayty(const MonoTypePtr &ty, size_t n)
Definition: type.H:1155
static ExprPtr expr(const ExprParser &p, const std::string &, const NamesAndExpr &... args)
Definition: cc.H:60
static ExprPtr expr(const ExprParser &p, const char *e)
Definition: cc.H:50
std::map< std::string, MonoTypePtr > MonoTypeAliasMap
Definition: cc.H:29
std::shared_ptr< std::vector< std::pair< size_t, PatternRow > > > UnreachableMatchRowsPtr
Definition: pattern.H:32
std::unordered_map< std::string, TTyDef > TTyDefs
Definition: cc.H:189
Definition: tylift.H:22
UnreachableMatchRowsPtr unreachableMatchRowsPtr
Definition: cc.H:226
void bind(const std::string &vn, T *x)
Definition: cc.H:173
Definition: pattern.H:281
static str::seq names(const std::string &x, const NamesAndExpr &... args)
Definition: cc.H:59
jitcc jit
Definition: cc.H:239
static str::seq names(const ExprPtr &)
Definition: cc.H:39
PolyTypePtr liftType()
Definition: cc.H:160
void bind(const std::string &fn, R(*pfn)(Args...))
Definition: cc.H:184
QualTypePtr qualtype(const Constraints &cs, const MonoTypePtr &p)
Definition: type.H:1016
Definition: boot.H:7
static str::seq names(const char *)
Definition: cc.H:49
static ExprPtr expr(const ExprParser &, const ExprPtr &e)
Definition: cc.H:40
ObjsPtr objs
Definition: cc.H:260
bool booted
Definition: cc.H:257
bool checkMatchReachability
Definition: cc.H:244
MonoType::ptr MonoTypePtr
Definition: type.H:71
TTyDefs ttyDefs
Definition: cc.H:190
Definition: cc.H:270
bool genInterpretedMatch
Definition: cc.H:243
void bindArr(const std::string &vn, T x[N])
Definition: cc.H:178
readExprDefnFn readExprDefnF
Definition: cc.H:88
std::map< std::string, PolyTypePtr > TypeAliasMap
Definition: cc.H:28
readModuleFn readModuleF
Definition: cc.H:87
bool drainingDefs
Definition: cc.H:129
Definition: cc.H:35
static ExprPtr expr(const ExprParser &p, const char *, const NamesAndExpr &... args)
Definition: cc.H:55
std::shared_ptr< Expr > ExprPtr
Definition: expr.H:58
LetRec::Bindings drainDefs
Definition: cc.H:130
size_t r(const reader::MetaData &md, size_t o, T *t)
Definition: storage.H:1730
Definition: cc.H:64
MonoTypePtr liftMonoType()
Definition: cc.H:165
std::shared_ptr< Module > ModulePtr
Definition: module.H:171
std::shared_ptr< TEnv > TEnvPtr
Definition: type.H:80
func< RFn >::type compileFn(NamesAndExpr ... args)
Definition: cc.H:93
std::vector< std::string > seq
Definition: str.H:19
bool runModInlinePass
Definition: cc.H:242
bool lowerPrimMatchTables
Definition: cc.H:245
static str::seq names(const std::string &)
Definition: cc.H:44
ExprPtr fn(const str::seq &vns, const ExprPtr &b, const LexicalAnnotation &la)
Definition: expr.H:837
static ExprPtr expr(const ExprParser &p, const std::string &e)
Definition: cc.H:45
std::vector< Definition > Definitions
Definition: expr.H:62
std::vector< unsigned char > bytes
Definition: cc.H:149
PolyTypePtr polytype(int tvs, const QualTypePtr &qt)
Definition: type.H:1036
void addObj()
Definition: cc.H:154
std::shared_ptr< TClass > TClassPtr
Definition: class.H:102
static MonoTypePtr type(typedb &tenv)
Definition: tylift.H:136
std::map< std::string, llvm::Value * > Args
Definition: dfa.C:1276
std::vector< MonoTypePtr > MonoTypes
Definition: type.H:72
std::shared_ptr< QualType > QualTypePtr
Definition: type.H:28
std::vector< Binding > Bindings
Definition: expr.H:327
Definition: tylift.H:452
std::shared_ptr< Objs > ObjsPtr
Definition: obj.H:93
std::function< ExprPtr(const std::string &)> ExprParser
Definition: cc.H:32
static T compile(cc *c, const str::seq &vns, const std::string &expr)
Definition: cc.H:271
readExprFn readExprF
Definition: cc.H:89
std::pair< str::seq, MonoTypePtr > TTyDef
Definition: cc.H:188
void * unsafeCompileFn(const MonoTypePtr &retTy, const str::seq &names, const MonoTypes &argTys, const ExprPtr &exp)
Definition: cc.C:558
T compileTo(cc *c, const str::seq &vns, const std::string &expr)
Definition: cc.H:285
Definition: jitcc.H:21
TypeAliasMap typeAliases
Definition: cc.H:249
static cbF compile(cc *c, const str::seq &vns, const std::string &expr)
Definition: cc.H:279