hobbes
a language, embedded compiler, and runtime for efficient dynamic expression evaluation, data storage and analysis
expr.H
Go to the documentation of this file.
1 #ifndef HOBBES_LANG_EXPR_HPP_INCLUDED
2 #define HOBBES_LANG_EXPR_HPP_INCLUDED
3 
4 #include <hobbes/lang/type.H>
5 #include <hobbes/util/ptr.H>
6 #include <hobbes/util/array.H>
8 #include <memory>
9 #include <iostream>
10 #include <string>
11 #include <vector>
12 
13 namespace hobbes {
14 
15 class Expr : public LexicallyAnnotated {
16 public:
17  virtual ~Expr();
18 
19  virtual void show(std::ostream&) const = 0;
20  virtual void showAnnotated(std::ostream&) const = 0;
21  virtual Expr* clone() const = 0;
22  virtual bool operator==(const Expr&) const = 0;
23 
24  // for use by type-inference, to explicitly annotate every term with its type
25  const QualTypePtr& type() const;
26  void type(const QualTypePtr& ty);
27 private:
29 
30  // improves performance of case-analysis over instances (to avoid 'dynamic_cast')
31 public:
32  int case_id() const;
33 protected:
34  Expr(int cid, const LexicalAnnotation&);
35 private:
36  int cid;
37 };
38 
39 // improves performance of case-analysis over MonoType instances (to avoid 'dynamic_cast')
40 template <typename Case>
41  class ExprCase : public Expr {
42  public:
45  virtual bool operator==(const Case&) const = 0;
46 
47  bool operator==(const Expr& rhs) const {
48  if (this == &rhs) {
49  return true;
50  } else if (const Case* trhs = is<Case>(&rhs)) {
51  return *this == *trhs;
52  } else {
53  return false;
54  }
55  }
56  };
57 
58 typedef std::shared_ptr<Expr> ExprPtr;
59 typedef std::vector<ExprPtr> Exprs;
60 
61 typedef std::pair<std::string, ExprPtr> Definition;
62 typedef std::vector<Definition> Definitions;
63 
64 std::string show(const Expr& e);
65 std::string show(const Expr* e);
66 std::string show(const ExprPtr& e);
67 std::string show(const Definition& d);
68 std::string showAnnotated(const Expr& e);
69 std::string showAnnotated(const Expr* e);
70 std::string showAnnotated(const ExprPtr& e);
71 std::string showAnnotated(const Definition& d);
72 
74 // primitive constants
76 
77 class Primitive : public Expr {
78 public:
79  virtual bool operator==(const Expr&) const = 0;
80  virtual bool operator< (const Primitive&) const = 0;
81  virtual MonoTypePtr primType() const = 0;
82 
83  // for efficient case dispatch
84  Primitive(int cid, const LexicalAnnotation&);
85 };
86 typedef std::shared_ptr<Primitive> PrimitivePtr;
87 
88 struct PrimPtrLT {
89  bool operator()(const PrimitivePtr&, const PrimitivePtr&) const;
90 };
91 typedef std::set<PrimitivePtr, PrimPtrLT> PrimitiveSet;
92 
93 template <typename Case>
94  class PrimitiveCase : public Primitive {
95  public:
98  virtual bool equiv(const Case&) const = 0;
99  virtual bool lt(const Case&) const = 0;
100 
101  bool operator<(const Primitive& rhs) const {
102  if (const Case* trhs = is<Case>(&rhs)) {
103  return lt(*trhs);
104  } else {
105  return case_id() < rhs.case_id();
106  }
107  }
108 
109  bool operator==(const Expr& rhs) const {
110  if (const Case* trhs = is<Case>(&rhs)) {
111  return this->equiv(*trhs);
112  } else {
113  return false;
114  }
115  }
116  };
117 
118 class Unit : public PrimitiveCase<Unit> {
119 public:
120  Unit(const LexicalAnnotation&);
121  Expr* clone() const;
122  void show(std::ostream& out) const;
123  void showAnnotated(std::ostream& out) const;
124  bool equiv(const Unit&) const;
125  bool lt(const Unit&) const;
126  MonoTypePtr primType() const;
127 
128  static const int type_case_id = 0;
129 };
130 
131 class Bool : public PrimitiveCase<Bool> {
132 public:
133  Bool(bool x, const LexicalAnnotation&);
134  bool value() const;
135  void value(bool);
136  Expr* clone() const;
137  void show(std::ostream& out) const;
138  void showAnnotated(std::ostream& out) const;
139  bool equiv(const Bool&) const;
140  bool lt(const Bool&) const;
141  MonoTypePtr primType() const;
142 
143  static const int type_case_id = 1;
144 private:
145  bool x;
146 };
147 
148 class Char : public PrimitiveCase<Char> {
149 public:
150  Char(char x, const LexicalAnnotation&);
151  char value() const;
152  void value(char);
153  Expr* clone() const;
154  void show(std::ostream& out) const;
155  void showAnnotated(std::ostream& out) const;
156  bool equiv(const Char&) const;
157  bool lt(const Char&) const;
158  MonoTypePtr primType() const;
159 
160  static const int type_case_id = 2;
161 private:
162  char x;
163 };
164 
165 // 8-bit int
166 class Byte : public PrimitiveCase<Byte> {
167 public:
168  Byte(unsigned char x, const LexicalAnnotation&);
169  unsigned char value() const;
170  void value(unsigned char);
171  Expr* clone() const;
172  void show(std::ostream& out) const;
173  void showAnnotated(std::ostream& out) const;
174  bool equiv(const Byte&) const;
175  bool lt(const Byte&) const;
176  MonoTypePtr primType() const;
177 
178  static const int type_case_id = 3;
179 private:
180  unsigned char x;
181 };
182 
183 // 16-bit int
184 class Short : public PrimitiveCase<Short> {
185 public:
186  Short(short x, const LexicalAnnotation&);
187  short value() const;
188  void value(short);
189  Expr* clone() const;
190  void show(std::ostream& out) const;
191  void showAnnotated(std::ostream& out) const;
192  bool equiv(const Short&) const;
193  bool lt(const Short&) const;
194  MonoTypePtr primType() const;
195 
196  static const int type_case_id = 4;
197 private:
198  short x;
199 };
200 
201 // 32-bit int
202 class Int : public PrimitiveCase<Int> {
203 public:
204  Int(int x, const LexicalAnnotation&);
205  int value() const;
206  void value(int);
207  Expr* clone() const;
208  void show(std::ostream& out) const;
209  void showAnnotated(std::ostream& out) const;
210  bool equiv(const Int&) const;
211  bool lt(const Int&) const;
212  MonoTypePtr primType() const;
213 
214  static const int type_case_id = 5;
215 private:
216  int x;
217 };
218 
219 // 64-bit int
220 class Long : public PrimitiveCase<Long> {
221 public:
222  Long(long x, const LexicalAnnotation&);
223  long value() const;
224  void value(long);
225  Expr* clone() const;
226  void show(std::ostream& out) const;
227  void showAnnotated(std::ostream& out) const;
228  bool equiv(const Long&) const;
229  bool lt(const Long&) const;
230  MonoTypePtr primType() const;
231 
232  static const int type_case_id = 6;
233 private:
234  long x;
235 };
236 
237 // 32-bit float
238 class Float : public PrimitiveCase<Float> {
239 public:
240  Float(float x, const LexicalAnnotation&);
241  float value() const;
242  void value(float);
243  Expr* clone() const;
244  void show(std::ostream& out) const;
245  void showAnnotated(std::ostream& out) const;
246  bool equiv(const Float&) const;
247  bool lt(const Float&) const;
248  MonoTypePtr primType() const;
249 
250  static const int type_case_id = 7;
251 private:
252  float x;
253 };
254 
255 // 64-bit float
256 class Double : public PrimitiveCase<Double> {
257 public:
258  Double(double x, const LexicalAnnotation&);
259  double value() const;
260  void value(double);
261  Expr* clone() const;
262  void show(std::ostream& out) const;
263  void showAnnotated(std::ostream& out) const;
264  bool equiv(const Double&) const;
265  bool lt(const Double&) const;
266  MonoTypePtr primType() const;
267 
268  static const int type_case_id = 8;
269 private:
270  double x;
271 };
272 
273 template <typename Case>
275  }
276 
278 // non-primitive terms
280 
281 // v (variable reference)
282 class Var : public ExprCase<Var> {
283 public:
284  Var(const std::string& id, const LexicalAnnotation&);
285  bool operator==(const Var&) const;
286 
287  const std::string& value() const;
288  void value(const std::string&);
289  Expr* clone() const;
290  void show(std::ostream& out) const;
291  void showAnnotated(std::ostream& out) const;
292 
293  static const int type_case_id = 9;
294 private:
295  std::string id;
296 };
297 
298 // local variable definition
299 class Let : public ExprCase<Let> {
300 public:
301  Let(const std::string& id, const ExprPtr& e, const ExprPtr& b, const LexicalAnnotation&);
302  bool operator==(const Let&) const;
303 
304  const std::string& var() const;
305  const ExprPtr& varExpr() const;
306  const ExprPtr& bodyExpr() const;
307 
308  void var(const std::string&);
309  void varExpr(const ExprPtr&);
310  void bodyExpr(const ExprPtr&);
311 
312  Expr* clone() const;
313  void show(std::ostream& out) const;
314  void showAnnotated(std::ostream& out) const;
315 
316  static const int type_case_id = 10;
317 private:
318  std::string id;
319  ExprPtr e;
320  ExprPtr b;
321 };
322 
323 // local mutually-recursive function definition
324 class LetRec : public ExprCase<LetRec> {
325 public:
326  typedef std::pair<std::string, ExprPtr> Binding;
327  typedef std::vector<Binding> Bindings;
328 
329  LetRec(const Bindings&, const ExprPtr&, const LexicalAnnotation&);
330  bool operator==(const LetRec&) const;
331 
332  const Bindings& bindings() const;
333  const ExprPtr& bodyExpr() const;
334  str::seq varNames() const;
335 
336  Bindings& bindings();
337  void bodyExpr(const ExprPtr&);
338 
339  Expr* clone() const;
340  void show(std::ostream&) const;
341  void showAnnotated(std::ostream&) const;
342 
343  static const int type_case_id = 11;
344 private:
345  Bindings bs;
346  ExprPtr e;
347 };
348 
349 // \x0...xn -> E (function introduction)
350 class Fn : public ExprCase<Fn> {
351 public:
352  typedef std::vector<std::string> VarNames;
353 
354  Fn(const VarNames& vs, const ExprPtr& e, const LexicalAnnotation&);
355  bool operator==(const Fn&) const;
356 
357  const VarNames& varNames() const;
358  const ExprPtr& body() const;
359 
360  VarNames& varNames();
361  void body(const ExprPtr&);
362 
363  Expr* clone() const;
364  void show(std::ostream& out) const;
365  void showAnnotated(std::ostream& out) const;
366 
367  static const int type_case_id = 12;
368 private:
369  VarNames vs;
370  ExprPtr e;
371 };
372 
373 // E(E0...EN) (function elimination)
374 class App : public ExprCase<App> {
375 public:
376  App(const ExprPtr& fn, const Exprs& args, const LexicalAnnotation&);
377  bool operator==(const App&) const;
378 
379  const ExprPtr& fn() const;
380  const Exprs& args() const;
381 
382  void fn(const ExprPtr&);
383  Exprs& args();
384 
385  Expr* clone() const;
386  void show(std::ostream& out) const;
387  void showAnnotated(std::ostream& out) const;
388 
389  static const int type_case_id = 13;
390 private:
391  ExprPtr fne;
392  Exprs argl;
393 };
394 
395 // E <- E (storage assignment)
396 class Assign : public ExprCase<Assign> {
397 public:
398  Assign(const ExprPtr& lhs, const ExprPtr& rhs, const LexicalAnnotation&);
399  bool operator==(const Assign&) const;
400 
401  const ExprPtr& left() const;
402  const ExprPtr& right() const;
403 
404  void left(const ExprPtr&);
405  void right(const ExprPtr&);
406 
407  Expr* clone() const;
408  void show(std::ostream& out) const;
409  void showAnnotated(std::ostream& out) const;
410 
411  static const int type_case_id = 14;
412 private:
413  ExprPtr lhs;
414  ExprPtr rhs;
415 };
416 
417 // [E0,...,EN] (fixed-length array introduction)
418 class MkArray : public ExprCase<MkArray> {
419 public:
420  MkArray(const Exprs& es, const LexicalAnnotation&);
421  bool operator==(const MkArray&) const;
422 
423  const Exprs& values() const;
424  Exprs& values();
425 
426  Expr* clone() const;
427  void show(std::ostream& out) const;
428  void showAnnotated(std::ostream& out) const;
429 
430  static const int type_case_id = 15;
431 private:
432  Exprs es;
433 };
434 
435 // |x=E| (variant introduction)
436 class MkVariant : public ExprCase<MkVariant> {
437 public:
438  MkVariant(const std::string& lbl, const ExprPtr& e, const LexicalAnnotation&);
439  bool operator==(const MkVariant&) const;
440 
441  const std::string& label() const;
442  const ExprPtr& value() const;
443 
444  void label(const std::string&);
445  void value(const ExprPtr&);
446 
447  Expr* clone() const;
448  void show(std::ostream& out) const;
449  void showAnnotated(std::ostream& out) const;
450 
451  static const int type_case_id = 16;
452 private:
453  std::string lbl;
454  ExprPtr e;
455 };
456 
457 // {f0=E0,...,fN=EN} (record introduction)
458 class MkRecord : public ExprCase<MkRecord> {
459 public:
460  typedef std::pair<std::string, ExprPtr> FieldDef;
461  typedef std::vector<FieldDef> FieldDefs;
462 
463  MkRecord(const FieldDefs& fs, const LexicalAnnotation&);
464  bool operator==(const MkRecord&) const;
465 
466  const FieldDefs& fields() const;
467  FieldDefs& fields();
468 
469  Expr* clone() const;
470  void show(std::ostream& out) const;
471  void showAnnotated(std::ostream& out) const;
472 
473  static const int type_case_id = 17;
474 private:
475  FieldDefs fs;
476 
477  bool isTuple() const;
478  void showRecord(std::ostream& out) const;
479  void showRecordAnnotated(std::ostream& out) const;
480  void showTuple(std::ostream& out) const;
481  void showTupleAnnotated(std::ostream& out) const;
482 };
483 
484 // E[i] (array index)
485 class AIndex : public ExprCase<AIndex> {
486 public:
487  AIndex(const ExprPtr&, const ExprPtr&, const LexicalAnnotation&);
488  bool operator==(const AIndex&) const;
489 
490  const ExprPtr& array() const;
491  const ExprPtr& index() const;
492 
493  void array(const ExprPtr&);
494  void index(const ExprPtr&);
495 
496  Expr* clone() const;
497  void show(std::ostream& out) const;
498  void showAnnotated(std::ostream& out) const;
499 
500  static const int type_case_id = 18;
501 private:
502  ExprPtr arr;
503  ExprPtr i;
504 };
505 
506 // case E of |c0:x0=>E0;...;cN:xN=>EN| (variant case analysis)
507 class Case : public ExprCase<Case> {
508 public:
509  struct Binding {
510  Binding() { }
511  Binding(const std::string& selector, const std::string& vname, const ExprPtr& exp) : selector(selector), vname(vname), exp(exp) { }
512 
513  std::string selector;
514  std::string vname;
515  ExprPtr exp;
516  };
517  typedef std::vector<Binding> Bindings;
518 
519  Case(const ExprPtr& v, const Bindings& bs, const LexicalAnnotation&);
520  Case(const ExprPtr& v, const Bindings& bs, const ExprPtr& def, const LexicalAnnotation&);
521  bool operator==(const Case&) const;
522 
523  const ExprPtr& variant() const;
524  const Bindings& bindings() const;
525  const ExprPtr& defaultExpr() const;
526 
527  void variant(const ExprPtr&);
528  Bindings& bindings();
529  void defaultExpr(const ExprPtr&);
530 
531  bool hasBinding(const std::string&) const;
532  void addBinding(const std::string& selector, const std::string& vname, const ExprPtr& exp);
533 
534  Expr* clone() const;
535  void show(std::ostream& out) const;
536  void showAnnotated(std::ostream& out) const;
537 
538  static const int type_case_id = 19;
539 private:
540  ExprPtr v;
541  Bindings bs;
542  ExprPtr def;
543 };
544 
545 // switch E of |c0=>E0;...;cN=>EN;default=>Ed|
546 class Switch : public ExprCase<Switch> {
547 public:
548  struct Binding {
549  Binding() { }
550  Binding(const PrimitivePtr& value, const ExprPtr& exp) : value(value), exp(exp) { }
551 
552  PrimitivePtr value;
553  ExprPtr exp;
554  };
555  typedef std::vector<Binding> Bindings;
556 
557  Switch(const ExprPtr& v, const Bindings& bs, const LexicalAnnotation&);
558  Switch(const ExprPtr& v, const Bindings& bs, const ExprPtr& def, const LexicalAnnotation&);
559  bool operator==(const Switch&) const;
560 
561  const ExprPtr& expr() const;
562  const Bindings& bindings() const;
563  const ExprPtr& defaultExpr() const;
564 
565  void expr(const ExprPtr&);
566  Bindings& bindings();
567  void defaultExpr(const ExprPtr&);
568 
569  Expr* clone() const;
570  void show(std::ostream&) const;
571  void showAnnotated(std::ostream& out) const;
572 
573  static const int type_case_id = 20;
574 private:
575  ExprPtr v;
576  Bindings bs;
577  ExprPtr def;
578 };
579 
580 // E.l (record projection)
581 class Proj : public ExprCase<Proj> {
582 public:
583  Proj(const ExprPtr& r, const std::string& fn, const LexicalAnnotation&);
584  bool operator==(const Proj&) const;
585 
586  const ExprPtr& record() const;
587  const std::string& field() const;
588 
589  void record(const ExprPtr&);
590  void field(const std::string&);
591 
592  Expr* clone() const;
593  void show(std::ostream& out) const;
594  void showAnnotated(std::ostream& out) const;
595 
596  static const int type_case_id = 21;
597 private:
598  ExprPtr r;
599  std::string fn;
600 };
601 
602 // E :: T (type casting/assumption)
603 class Assump : public ExprCase<Assump> {
604 public:
605  Assump(const ExprPtr& e, const QualTypePtr& t, const LexicalAnnotation&);
606  bool operator==(const Assump&) const;
607 
608  const ExprPtr& expr() const;
609  const QualTypePtr& ty() const;
610 
611  void expr(const ExprPtr&);
612  void ty(const QualTypePtr&);
613 
614  Expr* clone() const;
615  void show(std::ostream& out) const;
616  void showAnnotated(std::ostream& out) const;
617 
618  static const int type_case_id = 22;
619 private:
620  ExprPtr e;
622 };
623 
624 // pack E (existential type introduction)
625 class Pack : public ExprCase<Pack> {
626 public:
627  Pack(const ExprPtr& e, const LexicalAnnotation&);
628  bool operator==(const Pack&) const;
629 
630  const ExprPtr& expr() const;
631  void expr(const ExprPtr&);
632 
633  Expr* clone() const;
634  void show(std::ostream& out) const;
635  void showAnnotated(std::ostream& out) const;
636 
637  static const int type_case_id = 23;
638 private:
639  ExprPtr e;
640 };
641 
642 // unpack E in E (existential type elimination)
643 class Unpack : public ExprCase<Unpack> {
644 public:
645  Unpack(const std::string&, const ExprPtr&, const ExprPtr&, const LexicalAnnotation&);
646  bool operator==(const Unpack&) const;
647 
648  const std::string& varName() const;
649  const ExprPtr& package() const;
650  const ExprPtr& expr() const;
651 
652  void varName(const std::string&);
653  void package(const ExprPtr&);
654  void expr(const ExprPtr&);
655 
656  Expr* clone() const;
657  void show(std::ostream& out) const;
658  void showAnnotated(std::ostream& out) const;
659 
660  static const int type_case_id = 24;
661 private:
662  std::string vn;
663  ExprPtr pkg;
664  ExprPtr body;
665 };
666 
667 template <typename Case>
668  ExprCase<Case>::ExprCase(const LexicalAnnotation& la) : Expr(Case::type_case_id, la) {
669  }
670 
671 // expression utilities
672 inline ExprPtr constant(bool x, const LexicalAnnotation& la) {
673  ExprPtr r(new Bool(x, la));
674  r->type(qualtype(MonoTypePtr(Prim::make("bool"))));
675  return r;
676 }
677 
678 inline ExprPtr constant(uint8_t x, const LexicalAnnotation& la) {
679  ExprPtr r(new Byte(x, la));
680  r->type(qualtype(MonoTypePtr(Prim::make("byte"))));
681  return r;
682 }
683 
684 inline ExprPtr constant(int x, const LexicalAnnotation& la) {
685  ExprPtr r(new Int(x, la));
686  r->type(qualtype(MonoTypePtr(Prim::make("int"))));
687  return r;
688 }
689 
690 inline ExprPtr constant(long x, const LexicalAnnotation& la) {
691  ExprPtr r(new Long(x, la));
692  r->type(qualtype(MonoTypePtr(Prim::make("long"))));
693  return r;
694 }
695 
696 inline ExprPtr constant(size_t x, const LexicalAnnotation& la) {
697  ExprPtr r(new Long(x, la));
698  r->type(qualtype(MonoTypePtr(Prim::make("long"))));
699  return r;
700 }
701 
702 inline ExprPtr var(const std::string& vn, const LexicalAnnotation& la) {
703  return ExprPtr(new Var(vn, la));
704 }
705 
706 inline Exprs vars(const std::vector<std::string>& vns, const LexicalAnnotation& la) {
707  Exprs r;
708  for (const std::string& vn : vns) {
709  r.push_back(var(vn, la));
710  }
711  return r;
712 }
713 
714 inline ExprPtr var(const std::string& vn, const QualTypePtr& ty, const LexicalAnnotation& la) {
715  ExprPtr r(new Var(vn, la));
716  r->type(ty);
717  return r;
718 }
719 
720 inline ExprPtr var(const std::string& vn, const MonoTypePtr& ty, const LexicalAnnotation& la) {
721  return var(vn, qualtype(ty), la);
722 }
723 
724 inline ExprPtr let(const std::string& vn, const ExprPtr& e, const ExprPtr& b, const LexicalAnnotation& la) {
725  ExprPtr r(new Let(vn, e, b, la));
726  if (e->type() != QualTypePtr() && b->type() != QualTypePtr()) {
727  r->type(qualtype(mergeConstraints(e->type()->constraints(), b->type()->constraints()), b->type()->monoType()));
728  }
729  return r;
730 }
731 
732 inline ExprPtr let(const Definitions& bs, const ExprPtr& b, const LexicalAnnotation& la) {
733  ExprPtr r = b;
734  for (auto rb = bs.rbegin(); rb != bs.rend(); ++rb) {
735  r = let(rb->first, rb->second, r, la);
736  }
737  return r;
738 }
739 
740 inline ExprPtr let(const Exprs& es, const ExprPtr& b, const LexicalAnnotation& la) {
741  Definitions bs;
742  for (const auto& e : es) {
743  bs.push_back(Definition(freshName(), e));
744  }
745  return let(bs, b, la);
746 }
747 
748 inline ExprPtr mktunit(const LexicalAnnotation& la) {
749  ExprPtr r(new Unit(la));
750  r->type(qualtype(MonoTypePtr(Prim::make("unit"))));
751  return r;
752 }
753 
754 inline ExprPtr mkrecord(const MkRecord::FieldDefs& fds, const LexicalAnnotation& la) {
755  if (fds.size() == 0) {
756  return mktunit(la);
757  } else {
758  ExprPtr result(new MkRecord(fds, la));
759 
760  Constraints csts;
761  Record::Members ms;
762  for (MkRecord::FieldDefs::const_iterator fd = fds.begin(); fd != fds.end(); ++fd) {
763  if (fd->second->type() == QualTypePtr()) {
764  return result;
765  } else {
766  mergeConstraints(fd->second->type()->constraints(), &csts);
767  ms.push_back(Record::Member(fd->first, fd->second->type()->monoType()));
768  }
769  }
770 
771  result->type(qualtype(csts, MonoTypePtr(Record::make(ms))));
772  return result;
773  }
774 }
775 
776 // maybe generalize to make a tuple expr of any size
777 inline ExprPtr mktuple(const ExprPtr& e, const LexicalAnnotation& la) {
779  fs.push_back(MkRecord::FieldDef(".f0", e));
780  return mkrecord(fs, la);
781 }
782 
783 inline ExprPtr proj(const ExprPtr& rec, const Record* rty, const std::string& field, const LexicalAnnotation& la) {
784  ExprPtr p(new Proj(rec, field, la));
785  p->type(qualtype(rec->type()->constraints(), rty->member(field)));
786  return p;
787 }
788 
789 inline ExprPtr proj(const ExprPtr& rec, const std::string& field, const LexicalAnnotation& la) {
790  if (rec->type() != QualTypePtr()) {
791  if (const Record* rty = is<Record>(rec->type()->monoType())) {
792  return proj(rec, rty, field, la);
793  } else {
794  throw annotated_error(*rec, "Expected record type in projection");
795  }
796  }
797  return ExprPtr(new Proj(rec, field, la));
798 }
799 
800 inline ExprPtr proj(const ExprPtr& rec, const str::seq& fields, const LexicalAnnotation& la) {
801  ExprPtr r = rec;
802  for (const auto& f : fields) {
803  r = proj(r, f, la);
804  }
805  return r;
806 }
807 
809  return Case::Bindings();
810 }
811 
812 template <typename ... Cases>
813  Case::Bindings caseOfBindings(const char* ctor, const char* vname, const ExprPtr& e, Cases... cs) {
814  Case::Bindings hbs;
815  hbs.push_back(Case::Binding(ctor, vname, e));
816  Case::Bindings tbs = caseOfBindings(cs...);
817  hbs.insert(hbs.end(), tbs.begin(), tbs.end());
818  return hbs;
819  }
820 
821 template <typename ... Cases>
822  ExprPtr caseOf(const ExprPtr& e, Cases... cs) {
823  return ExprPtr(new Case(e, caseOfBindings(cs...), e->la()));
824  }
825 
826 inline Constraints liftConstraints(const Exprs& es) {
827  Constraints r;
828  for (Exprs::const_iterator e = es.begin(); e != es.end(); ++e) {
829  QualTypePtr qt = (*e)->type();
830  if (qt != QualTypePtr()) {
831  append(&r, qt->constraints());
832  }
833  }
834  return r;
835 }
836 
837 inline ExprPtr fn(const str::seq& vns, const ExprPtr& b, const LexicalAnnotation& la) {
838  return ExprPtr(new Fn(vns, b, la));
839 }
840 
841 inline ExprPtr fn(const std::string& vn, const ExprPtr& b, const LexicalAnnotation& la) {
842  return fn(str::strings(vn), b, la);
843 }
844 
845 inline ExprPtr fncall(const ExprPtr& f, const Exprs& args, const LexicalAnnotation& la) {
846  ExprPtr r(new App(f, args, la));
847  if (f->type() != QualTypePtr()) {
848  r->type(qualtype(liftConstraints(cons(f, args)), fnresult(f->type()->monoType())));
849  }
850  return r;
851 }
852 
853 inline ExprPtr fncall(const ExprPtr& f, const ExprPtr& a, const LexicalAnnotation& la) {
854  return fncall(f, list(a), la);
855 }
856 
857 inline ExprPtr closcall(const ExprPtr& c, const Exprs& args, const LexicalAnnotation& la) {
858  QualTypePtr qt = c->type();
859  std::string cn = freshName();
860 
861  if (qt == QualTypePtr()) {
862  return ExprPtr(new Unpack(cn, c, fncall(proj(var(cn, la), ".f0", la), cons(proj(var(cn, la), ".f1", la), args), la), la));
863  }
864 
865  const Exists* ety = is<Exists>(qt->monoType());
866  if (!ety) {
867  throw annotated_error(*c, "Expected existential type in closure application");
868  }
869 
870  ExprPtr cv = var(cn, unpackedType(ety), la);
871  ExprPtr r = fncall(proj(cv, ".f0", la), cons(proj(cv, ".f1", la), args), la);
872  ExprPtr up = ExprPtr(new Unpack(cn, c, r, la));
873 
874  up->type(r->type());
875  return up;
876 }
877 
878 // op :: (a0..aN) -> r => \(a0..aN).op(a0..aN)
879 inline ExprPtr etaLift(const std::string& opname, const MonoTypePtr& oty, const LexicalAnnotation& la) {
880  Func* fty = is<Func>(oty);
881  if (!fty) { throw annotated_error(la, "Internal compiler error while eta-expanding primitive op: " + opname); }
882 
883  ExprPtr op = var(opname, oty, la);
884 
885  const MonoTypes& atys = fty->parameters();
886  Exprs args;
887  Fn::VarNames vns;
888  int i = 0;
889 
890  for (const auto& a : atys) {
891  std::string vname = canonicalName(i);
892  args.push_back(var(vname, a, la));
893  vns.push_back(vname);
894  ++i;
895  }
896 
897  ExprPtr ret = fn(vns, fncall(op, args, la), la);
898  ret->type(qualtype(oty));
899  return ret;
900 }
901 
902 inline Expr* mkarray(const std::vector<unsigned char>& v, const LexicalAnnotation& la) {
903  MonoTypePtr bty = primty("byte");
904  QualTypePtr ety = qualtype(bty);
905  QualTypePtr aty = qualtype(arrayty(bty));
906 
907  Exprs cs;
908  for (size_t b = 0; b < v.size(); ++b) {
909  ExprPtr be(new Byte(v[b], la));
910  be->type(ety);
911  cs.push_back(be);
912  }
913 
914  ExprPtr marr(new MkArray(cs, la));
915  marr->type(aty);
916 
917  Expr* result = new Assump(marr, aty, la);
918  result->type(aty);
919 
920  return result;
921 }
922 
923 inline Expr* mkarray(const std::string& v, const LexicalAnnotation& la) {
924  MonoTypePtr cty = primty("char");
925  QualTypePtr ety = qualtype(cty);
926  QualTypePtr aty = qualtype(arrayty(cty));
927 
928  Exprs cs;
929  for (size_t c = 0; c < v.size(); ++c) {
930  ExprPtr ce(new Char(v[c], la));
931  ce->type(ety);
932  cs.push_back(ce);
933  }
934 
935  ExprPtr marr(new MkArray(cs, la));
936  marr->type(aty);
937 
938  Expr* result = new Assump(marr, aty, la);
939  result->type(aty);
940 
941  return result;
942 }
943 
944 inline ExprPtr switchE(const ExprPtr& e, const Switch::Bindings& bs, const ExprPtr& def, const LexicalAnnotation& la) {
945  if (bs.size() == 0) {
946  return def;
947  } else {
948  return ExprPtr(new Switch(e, bs, def, la));
949  }
950 }
951 
952 inline ExprPtr assume(const ExprPtr& e, const QualTypePtr& t, const LexicalAnnotation& la) {
953  if (const Assump* ae = is<Assump>(e)) {
954  if (*ae->ty() == *t) {
955  return e;
956  }
957  }
958 
959  QualTypePtr ety = e->type();
960  if (ety) {
961  ExprPtr r(new Assump(e, t, la));
962  r->type(qualtype(mergeConstraints(ety->constraints(), t->constraints()), ety->monoType()));
963  return r;
964  } else {
965  return ExprPtr(new Assump(e, t, la));
966  }
967 }
968 
969 inline ExprPtr assume(const ExprPtr& e, const MonoTypePtr& t, const LexicalAnnotation& la) {
970  return assume(e, qualtype(t), la);
971 }
972 
973 // justE :: expr:a -> |1=expr|::()+a
974 inline ExprPtr justE(const ExprPtr& e, const LexicalAnnotation& la) {
975  if (e->type()) {
976  ExprPtr r(new MkVariant(".f1", e, la));
977  r->type(qualtype(e->type()->constraints(), sumtype(primty("unit"), e->type()->monoType())));
978  return assume(r, r->type(), la);
979  } else {
981  return assume(ExprPtr(new MkVariant(".f1", assume(e, t, la), la)), sumtype(primty("unit"), t), la);
982  }
983 }
984 
985 // nothingE :: () -> |0=()|
986 inline ExprPtr nothingE(const LexicalAnnotation& la) {
987  return ExprPtr(new MkVariant(".f0", mktunit(la), la));
988 }
989 
990 inline ExprPtr nothingE(const MonoTypePtr& jt, const LexicalAnnotation& la) {
991  ExprPtr r(new MkVariant(".f0", mktunit(la), la));
992  r->type(qualtype(maybety(jt)));
993  return r;
994 }
995 
996 inline ExprPtr assign(const ExprPtr& lhs, const ExprPtr& rhs, const LexicalAnnotation& la) {
997  ExprPtr r(new Assign(lhs, rhs, la));
998  if (lhs->type() && rhs->type()) {
999  r->type(qualtype(mergeConstraints(lhs->type()->constraints(), rhs->type()->constraints()), primty("unit")));
1000  }
1001  return r;
1002 }
1003 
1004 inline Exprs exprs(const MkRecord::FieldDefs& ms) {
1005  Exprs r;
1006  for (MkRecord::FieldDefs::const_iterator m = ms.begin(); m != ms.end(); ++m) {
1007  r.push_back(m->second);
1008  }
1009  return r;
1010 }
1011 
1012 inline Exprs exprs(const Case::Bindings& bs) {
1013  Exprs r;
1014  for (Case::Bindings::const_iterator b = bs.begin(); b != bs.end(); ++b) {
1015  r.push_back(b->exp);
1016  }
1017  return r;
1018 }
1019 
1020 // replaces instances of a given variable name with the specified expression
1021 // (NOTE: this does nothing to prevent variable capture, other than respecting shadowing)
1022 // (ie: the free variables of the substituted expression should be disjoint with program variables)
1023 typedef std::map<std::string, ExprPtr> VarMapping;
1024 ExprPtr substitute(const VarMapping& vm, const ExprPtr& e, bool* mapped = 0);
1025 
1026 // apply a type substitution across an expression
1027 ExprPtr substitute(const MonoTypeSubst& s, const ExprPtr& e);
1028 
1029 // safely consume constants
1030 // (if the set of constants is extended but functions on constants aren't extended, it will be a compile-error)
1031 template <typename T>
1032  struct switchConst {
1033  virtual T with(const Unit* v) const = 0;
1034  virtual T with(const Bool* v) const = 0;
1035  virtual T with(const Char* v) const = 0;
1036  virtual T with(const Byte* v) const = 0;
1037  virtual T with(const Short* v) const = 0;
1038  virtual T with(const Int* v) const = 0;
1039  virtual T with(const Long* v) const = 0;
1040  virtual T with(const Float* v) const = 0;
1041  virtual T with(const Double* v) const = 0;
1042  };
1043 
1044 template <typename T>
1045  T switchOf(const PrimitivePtr& p, const switchConst<T>& f) {
1046  switch (p->case_id()) {
1047  case Unit::type_case_id:
1048  return f.with((Unit*)(p.get()));
1049  case Bool::type_case_id:
1050  return f.with((Bool*)(p.get()));
1051  case Char::type_case_id:
1052  return f.with((Char*)(p.get()));
1053  case Byte::type_case_id:
1054  return f.with((Byte*)(p.get()));
1055  case Short::type_case_id:
1056  return f.with((Short*)(p.get()));
1057  case Int::type_case_id:
1058  return f.with((Int*)(p.get()));
1059  case Long::type_case_id:
1060  return f.with((Long*)(p.get()));
1061  case Float::type_case_id:
1062  return f.with((Float*)(p.get()));
1063  case Double::type_case_id:
1064  return f.with((Double*)(p.get()));
1065  default:
1066  throw annotated_error(*p, "Internal error, cannot switch on unknown constant: " + show(p));
1067  }
1068  }
1069 
1070 // safely consume expressions
1071 // (if the expression type is extended but functions on expressions aren't extended, it will be a compile-error)
1072 template <typename T>
1073  struct switchExpr {
1074  virtual T with(const Unit* v) const = 0;
1075  virtual T with(const Bool* v) const = 0;
1076  virtual T with(const Char* v) const = 0;
1077  virtual T with(const Byte* v) const = 0;
1078  virtual T with(const Short* v) const = 0;
1079  virtual T with(const Int* v) const = 0;
1080  virtual T with(const Long* v) const = 0;
1081  virtual T with(const Float* v) const = 0;
1082  virtual T with(const Double* v) const = 0;
1083  virtual T with(const Var* v) const = 0;
1084  virtual T with(const Let* v) const = 0;
1085  virtual T with(const LetRec* v) const = 0;
1086  virtual T with(const Fn* v) const = 0;
1087  virtual T with(const App* v) const = 0;
1088  virtual T with(const Assign* v) const = 0;
1089  virtual T with(const MkArray* v) const = 0;
1090  virtual T with(const MkVariant* v) const = 0;
1091  virtual T with(const MkRecord* v) const = 0;
1092  virtual T with(const AIndex* v) const = 0;
1093  virtual T with(const Case* v) const = 0;
1094  virtual T with(const Switch* v) const = 0;
1095  virtual T with(const Proj* v) const = 0;
1096  virtual T with(const Assump* v) const = 0;
1097  virtual T with(const Pack* v) const = 0;
1098  virtual T with(const Unpack* v) const = 0;
1099  };
1100 
1101 template <typename T>
1102  struct switchExprC : public switchExpr<T> {
1103  virtual T withConst(const Expr* v) const = 0;
1104  virtual T with (const Var* v) const = 0;
1105  virtual T with (const Let* v) const = 0;
1106  virtual T with (const LetRec* v) const = 0;
1107  virtual T with (const Fn* v) const = 0;
1108  virtual T with (const App* v) const = 0;
1109  virtual T with (const Assign* v) const = 0;
1110  virtual T with (const MkArray* v) const = 0;
1111  virtual T with (const MkVariant* v) const = 0;
1112  virtual T with (const MkRecord* v) const = 0;
1113  virtual T with (const AIndex* v) const = 0;
1114  virtual T with (const Case* v) const = 0;
1115  virtual T with (const Switch* v) const = 0;
1116  virtual T with (const Proj* v) const = 0;
1117  virtual T with (const Assump* v) const = 0;
1118  virtual T with (const Pack* v) const = 0;
1119  virtual T with (const Unpack* v) const = 0;
1120 
1121  // implement just the constant 'with' terms to collapse them
1122  T with(const Unit* v) const { return withConst(v); }
1123  T with(const Bool* v) const { return withConst(v); }
1124  T with(const Char* v) const { return withConst(v); }
1125  T with(const Byte* v) const { return withConst(v); }
1126  T with(const Short* v) const { return withConst(v); }
1127  T with(const Int* v) const { return withConst(v); }
1128  T with(const Long* v) const { return withConst(v); }
1129  T with(const Float* v) const { return withConst(v); }
1130  T with(const Double* v) const { return withConst(v); }
1131  };
1132 
1133 bool isConst(const ExprPtr&);
1134 
1135 template <typename T>
1136  struct switchExprM {
1137  virtual T with(Unit* v) = 0;
1138  virtual T with(Bool* v) = 0;
1139  virtual T with(Char* v) = 0;
1140  virtual T with(Byte* v) = 0;
1141  virtual T with(Short* v) = 0;
1142  virtual T with(Int* v) = 0;
1143  virtual T with(Long* v) = 0;
1144  virtual T with(Float* v) = 0;
1145  virtual T with(Double* v) = 0;
1146  virtual T with(Var* v) = 0;
1147  virtual T with(Let* v) = 0;
1148  virtual T with(LetRec* v) = 0;
1149  virtual T with(Fn* v) = 0;
1150  virtual T with(App* v) = 0;
1151  virtual T with(Assign* v) = 0;
1152  virtual T with(MkArray* v) = 0;
1153  virtual T with(MkVariant* v) = 0;
1154  virtual T with(MkRecord* v) = 0;
1155  virtual T with(AIndex* v) = 0;
1156  virtual T with(Case* v) = 0;
1157  virtual T with(Switch* v) = 0;
1158  virtual T with(Proj* v) = 0;
1159  virtual T with(Assump* v) = 0;
1160  virtual T with(Pack* v) = 0;
1161  virtual T with(Unpack* v) = 0;
1162  };
1163 
1164 
1165 template <typename T, typename F>
1166  T switchOfF(const Expr& e, F f) {
1167  switch (e.case_id()) {
1168  case Unit::type_case_id:
1169  return f.with((Unit*)&e);
1170  case Bool::type_case_id:
1171  return f.with((Bool*)&e);
1172  case Char::type_case_id:
1173  return f.with((Char*)&e);
1174  case Byte::type_case_id:
1175  return f.with((Byte*)&e);
1176  case Short::type_case_id:
1177  return f.with((Short*)&e);
1178  case Int::type_case_id:
1179  return f.with((Int*)&e);
1180  case Long::type_case_id:
1181  return f.with((Long*)&e);
1182  case Float::type_case_id:
1183  return f.with((Float*)&e);
1184  case Double::type_case_id:
1185  return f.with((Double*)&e);
1186  case Var::type_case_id:
1187  return f.with((Var*)&e);
1188  case Let::type_case_id:
1189  return f.with((Let*)&e);
1190  case LetRec::type_case_id:
1191  return f.with((LetRec*)&e);
1192  case Fn::type_case_id:
1193  return f.with((Fn*)&e);
1194  case App::type_case_id:
1195  return f.with((App*)&e);
1196  case Assign::type_case_id:
1197  return f.with((Assign*)&e);
1198  case MkArray::type_case_id:
1199  return f.with((MkArray*)&e);
1200  case MkVariant::type_case_id:
1201  return f.with((MkVariant*)&e);
1202  case MkRecord::type_case_id:
1203  return f.with((MkRecord*)&e);
1204  case AIndex::type_case_id:
1205  return f.with((AIndex*)&e);
1206  case Case::type_case_id:
1207  return f.with((Case*)&e);
1208  case Switch::type_case_id:
1209  return f.with((Switch*)&e);
1210  case Proj::type_case_id:
1211  return f.with((Proj*)&e);
1212  case Assump::type_case_id:
1213  return f.with((Assump*)&e);
1214  case Pack::type_case_id:
1215  return f.with((Pack*)&e);
1216  case Unpack::type_case_id:
1217  return f.with((Unpack*)&e);
1218  default:
1219  throw annotated_error(e, "Internal error, cannot switch on unknown expression: " + show(e));
1220  }
1221  }
1222 
1223 template <typename T>
1224  T switchOf(const Expr& e, const switchExpr<T>& f) {
1225  return switchOfF< T, const switchExpr<T>& >(e, f);
1226  }
1227 
1228 template <typename T>
1229  T switchOf(const ExprPtr& e, const switchExpr<T>& f) {
1230  return switchOfF< T, const switchExpr<T>& >(*e, f);
1231  }
1232 
1233 template <typename T>
1234  T switchOf(const ExprPtr& e, const switchExprM<T>& f) {
1235  return switchOfF< T, switchExprM<T>& >(*e, const_cast<switchExprM<T>&>(f));
1236  }
1237 
1238 template <typename T>
1239  std::vector<T> switchOf(const Exprs& es, const switchExpr<T>& f) {
1240  std::vector<T> result;
1241  for (Exprs::const_iterator e = es.begin(); e != es.end(); ++e) {
1242  result.push_back(switchOf(*e, f));
1243  }
1244  return result;
1245  }
1246 
1247 template <typename T>
1248  std::vector<T> switchOf(const Exprs& es, const switchExprM<T>& f) {
1249  std::vector<T> result;
1250  for (Exprs::const_iterator e = es.begin(); e != es.end(); ++e) {
1251  result.push_back(switchOf(*e, const_cast<switchExprM<T>&>(f)));
1252  }
1253  return result;
1254  }
1255 
1256 template <typename K, typename T>
1257  std::vector< std::pair<K, T> > switchOf(const std::vector< std::pair<K, ExprPtr> >& kes, const switchExpr<T>& f) {
1258  typedef std::pair<K, T> KT;
1259  typedef std::vector<KT> KTS;
1260  KTS kts;
1261  for (typename std::vector< std::pair<K, ExprPtr> >::const_iterator ke = kes.begin(); ke != kes.end(); ++ke) {
1262  kts.push_back(KT(ke->first, switchOf(ke->second, f)));
1263  }
1264  return kts;
1265  }
1266 
1267 template <typename K, typename T>
1268  std::vector< std::pair<K, T> > switchOf(const std::vector< std::pair<K, ExprPtr> >& kes, const switchExprM<T>& f) {
1269  typedef std::pair<K, T> KT;
1270  typedef std::vector<KT> KTS;
1271  KTS kts;
1272  for (typename std::vector< std::pair<K, ExprPtr> >::const_iterator ke = kes.begin(); ke != kes.end(); ++ke) {
1273  kts.push_back(KT(ke->first, switchOf(ke->second, const_cast<switchExprM<T>&>(f))));
1274  }
1275  return kts;
1276  }
1277 
1278 // simplify type-directed expression transforms (e.g.: unqualification)
1279 // as a function or an in-place mutation
1280 //
1281 struct switchExprTyFn : public switchExprC<ExprPtr> {
1282  // whatever type transform is being done (default is the identity transform)
1283  virtual QualTypePtr withTy(const QualTypePtr& qt) const;
1284 
1285  // e :: withTy(qty) -- wrapped in a shared pointer
1286  virtual ExprPtr wrapWithTy(const QualTypePtr& qty, Expr* e) const;
1287 
1288  // allocate a fresh expression, updating types as we go
1289  ExprPtr withConst(const Expr* v) const;
1290  ExprPtr with (const Var* v) const;
1291  ExprPtr with (const Let* v) const;
1292  ExprPtr with (const LetRec* v) const;
1293  ExprPtr with (const Fn* v) const;
1294  ExprPtr with (const App* v) const;
1295  ExprPtr with (const Assign* v) const;
1296  ExprPtr with (const MkArray* v) const;
1297  ExprPtr with (const MkVariant* v) const;
1298  ExprPtr with (const MkRecord* v) const;
1299  ExprPtr with (const AIndex* v) const;
1300  ExprPtr with (const Case* v) const;
1301  ExprPtr with (const Switch* v) const;
1302  ExprPtr with (const Proj* v) const;
1303  ExprPtr with (const Assump* v) const;
1304  ExprPtr with (const Pack* v) const;
1305  ExprPtr with (const Unpack* v) const;
1306 };
1307 
1308 struct switchExprTyFnM : public switchExprM<UnitV> {
1309  // whatever type transform is being done (default is the identity transform)
1310  virtual QualTypePtr withTy(const QualTypePtr& qt) const;
1311 
1312  UnitV with(Unit* v);
1313  UnitV with(Bool* v);
1314  UnitV with(Char* v);
1315  UnitV with(Byte* v);
1316  UnitV with(Short* v);
1317  UnitV with(Int* v);
1318  UnitV with(Long* v);
1319  UnitV with(Float* v);
1320  UnitV with(Double* v);
1321  UnitV with(Var* v);
1322  UnitV with(Let* v);
1323  UnitV with(LetRec* v);
1324  UnitV with(Fn* v);
1325  UnitV with(App* v);
1326  UnitV with(Assign* v);
1327  UnitV with(MkArray* v);
1328  UnitV with(MkVariant* v);
1329  UnitV with(MkRecord* v);
1330  UnitV with(AIndex* v);
1331  UnitV with(Case* v);
1332  UnitV with(Switch* v);
1333  UnitV with(Proj* v);
1334  UnitV with(Assump* v);
1335  UnitV with(Pack* v);
1336  UnitV with(Unpack* v);
1337 private:
1338  UnitV updateTy(Expr* e);
1339 };
1340 
1343 
1344 // require that a mono-type can be extracted from an expression
1345 const MonoTypePtr& requireMonotype(const ExprPtr&);
1346 MonoTypes requireMonotype(const Exprs&);
1347 
1348 // add explicit type assumption terms where we have annotations
1349 ExprPtr liftTypesAsAssumptions(const ExprPtr& e);
1350 
1351 // strip type assumptions from terms (these aren't necessary when we're dealing with mono-typed expressions)
1352 ExprPtr stripExplicitAssumptions(const ExprPtr&);
1353 const ExprPtr& stripAssumpHead(const ExprPtr&);
1354 
1355 // find the free variables in a term
1356 typedef std::set<std::string> VarSet;
1357 
1358 VarSet freeVars(const ExprPtr&);
1359 VarSet freeVars(const Expr&);
1360 
1361 // find the type variables used in a term
1362 NameSet tvarNames(const ExprPtr&);
1363 
1364 // simplify introducing array comprehensions (these should just be syntax sugar for core terms anyway)
1366  ComprehensionDef(const std::string& varname, const ExprPtr& ex);
1367  ComprehensionDef(const ExprPtr& ex);
1368 
1369  bool isfilter;
1370  std::string varname;
1371  ExprPtr ex;
1372 };
1373 
1374 typedef std::vector<ComprehensionDef> ComprehensionDefs;
1375 
1376 ExprPtr desugarComprehension(const ExprPtr& ex, const ComprehensionDefs& cdefs, const LexicalAnnotation& la);
1377 
1378 // generate a format expression from a format string
1379 ExprPtr mkFormatExpr(const std::string& fmt, const LexicalAnnotation&);
1380 
1381 // generate constants for some common types
1382 PrimitivePtr mkTimespanPrim(const str::seq&, const LexicalAnnotation&);
1383 ExprPtr mkTimespanExpr(const str::seq&, const LexicalAnnotation&);
1384 
1385 PrimitivePtr mkTimePrim(const std::string&, const LexicalAnnotation&);
1386 ExprPtr mkTimeExpr(const std::string&, const LexicalAnnotation&);
1387 
1388 ExprPtr mkDateTimeExpr(const std::string&, const LexicalAnnotation&);
1389 PrimitivePtr mkDateTimePrim(const std::string&, const LexicalAnnotation&);
1390 
1391 // support a binary codec for expressions
1392 void encode(const PrimitivePtr&, std::ostream&);
1393 void decode(PrimitivePtr*, std::istream&);
1394 
1395 void encode(const ExprPtr&, std::ostream&);
1396 void decode(ExprPtr*, std::istream&);
1397 
1398 void encode(const ExprPtr&, std::vector<uint8_t>*);
1399 void decode(const std::vector<uint8_t>&, ExprPtr*);
1400 
1401 // determine whether or not an expression is fully annotated everywhere with a singular type
1402 bool hasSingularType(const ExprPtr&);
1403 
1404 // determine the tgen size of types across an expression
1405 int tgenSize(const ExprPtr&);
1406 
1407 }
1408 
1409 #endif
ExprPtr mkrecord(const MkRecord::FieldDefs &fds, const LexicalAnnotation &la)
Definition: expr.H:754
T with(const Unit *v) const
Definition: expr.H:1122
PrimitivePtr value
Definition: expr.H:552
ExprPtr v
Definition: expr.H:540
int case_id() const
Definition: expr.C:41
std::string varname
Definition: expr.H:1370
virtual bool operator==(const Expr &) const =0
Definition: expr.H:148
Definition: expr.H:131
Definition: expr.H:374
ExprPtr closcall(const ExprPtr &c, const Exprs &args, const LexicalAnnotation &la)
Definition: expr.H:857
ExprPtr mktuple(const ExprPtr &e, const LexicalAnnotation &la)
Definition: expr.H:777
ExprPtr e
Definition: expr.H:620
std::string vn
Definition: expr.H:662
Definition: expr.H:184
std::string vname
Definition: expr.H:514
QualTypePtr annotatedType
Definition: expr.H:28
MonoTypePtr arrayty(const MonoTypePtr &ty, size_t n)
Definition: type.H:1155
ExprPtr switchE(const ExprPtr &e, const Switch::Bindings &bs, const ExprPtr &def, const LexicalAnnotation &la)
Definition: expr.H:944
static void addBinding(imagefile *f, const std::string &vname, const MonoTypePtr &type, size_t offset)
Definition: file.C:497
Definition: expr.H:485
ExprPtr fncall(const ExprPtr &f, const ExprPtr &a, const LexicalAnnotation &la)
Definition: expr.H:853
std::pair< std::string, ExprPtr > Definition
Definition: expr.H:61
Definition: expr.H:118
ExprPtr field(MDFA *dfa, const std::string &vn, const std::string &fn)
Definition: dfa.C:183
Definition: expr.H:282
Definition: expr.H:643
float x
Definition: expr.H:252
ExprPtr def
Definition: expr.H:542
std::string fn
Definition: expr.H:599
ExprPtr proj(const ExprPtr &rec, const str::seq &fields, const LexicalAnnotation &la)
Definition: expr.H:800
ExprPtr caseOf(const ExprPtr &e, Cases... cs)
Definition: expr.H:822
Definition: expr.H:77
Definition: terminal.H:71
PrimitiveCase(const LexicalAnnotation &)
Definition: expr.H:274
std::set< TVName > NameSet
Definition: type.H:142
Bindings bs
Definition: expr.H:345
const LexicalAnnotation & la() const
Definition: lannotation.C:98
ExprPtr b
Definition: expr.H:320
ExprPtr e
Definition: expr.H:346
T with(const Byte *v) const
Definition: expr.H:1125
ExprPtr def
Definition: expr.H:577
T with(const Bool *v) const
Definition: expr.H:1123
ExprPtr e
Definition: expr.H:319
ExprPtr varName(MDFA *dfa, const std::string &vn)
Definition: dfa.C:129
PrimitivePtr mkTimePrim(const std::string &, const LexicalAnnotation &)
Definition: expr.C:1457
MonoTypePtr primty(const char *x)
Definition: type.H:1008
ExprPtr fne
Definition: expr.H:391
Definition: expr.H:256
ExprPtr assume(const ExprPtr &e, const MonoTypePtr &t, const LexicalAnnotation &la)
Definition: expr.H:969
long x
Definition: expr.H:234
Binding()
Definition: expr.H:510
ExprCase< Case > Base
Definition: expr.H:43
void encode(const ExprPtr &, std::vector< uint8_t > *)
Definition: expr.C:1933
ExprPtr exp
Definition: expr.H:553
T * make(const Args &... args)
Definition: hobbes.H:60
Exprs argl
Definition: expr.H:392
ExprPtr etaLift(const std::string &opname, const MonoTypePtr &oty, const LexicalAnnotation &la)
Definition: expr.H:879
Definition: expr.H:507
ExprPtr liftTypesAsAssumptions(const ExprPtr &e)
Definition: expr.C:1247
std::pair< std::string, ExprPtr > Binding
Definition: expr.H:326
QualTypePtr qualtype(const Constraints &cs, const MonoTypePtr &p)
Definition: type.H:1016
Constraints liftConstraints(const Exprs &es)
Definition: expr.H:826
bool operator==(const PatternRow &, const PatternRow &)
Definition: pattern.C:270
const QualTypePtr & type() const
Definition: expr.C:39
Expr(int cid, const LexicalAnnotation &)
Definition: expr.C:37
Definition: boot.H:7
Definition: type.H:425
NameSet tvarNames(const ExprPtr &)
Definition: expr.C:1383
ExprPtr var(const std::string &vn, const MonoTypePtr &ty, const LexicalAnnotation &la)
Definition: expr.H:720
Definition: type.H:423
Definition: expr.H:548
std::vector< ExprPtr > Exprs
Definition: expr.H:59
PrimitivePtr mkDateTimePrim(const std::string &, const LexicalAnnotation &)
Definition: expr.C:1464
Definition: expr.H:88
Definition: expr.H:458
TVName canonicalName(int v)
Definition: type.C:2032
virtual T with(const Unit *v) const =0
bool isConst(const ExprPtr &)
Definition: expr.C:1009
ExprPtr mkFormatExpr(const std::string &fmt, const LexicalAnnotation &)
Definition: expr.C:1442
Exprs es
Definition: expr.H:432
MonoTypes parameters() const
Definition: type.C:1397
ExprPtr desugarComprehension(const ExprPtr &ex, const ComprehensionDefs &cdefs, const LexicalAnnotation &la)
Definition: expr.C:1429
FieldDefs fs
Definition: expr.H:475
ExprPtr e
Definition: expr.H:370
Definition: expr.H:625
ExprPtr ex
Definition: expr.H:1371
void append(std::vector< T > *xs, const std::vector< T > &ys)
Definition: array.H:292
QualTypePtr t
Definition: expr.H:621
std::string id
Definition: expr.H:295
bool operator==(const Expr &rhs) const
Definition: expr.H:109
virtual Expr * clone() const =0
std::shared_ptr< Primitive > PrimitivePtr
Definition: expr.H:86
int index(const std::vector< T > &xs, T x)
Definition: array.H:63
Definition: expr.H:350
Definition: expr.H:41
MonoType::ptr MonoTypePtr
Definition: type.H:71
ExprPtr e
Definition: expr.H:639
MonoTypePtr maybety(const MonoTypePtr &t)
Definition: type.H:1087
Definition: expr.H:166
ExprPtr assign(const ExprPtr &lhs, const ExprPtr &rhs, const LexicalAnnotation &la)
Definition: expr.H:996
std::map< std::string, ExprPtr > VarMapping
Definition: expr.H:1023
Case::Bindings caseOfBindings(const char *ctor, const char *vname, const ExprPtr &e, Cases... cs)
Definition: expr.H:813
std::vector< Binding > Bindings
Definition: expr.H:555
VarSet freeVars(const Expr &)
Definition: expr.C:1327
std::vector< ComprehensionDef > ComprehensionDefs
Definition: expr.H:1374
ExprPtr mkTimeExpr(const std::string &, const LexicalAnnotation &)
Definition: expr.C:1460
ExprPtr pkg
Definition: expr.H:663
Exprs exprs(const Case::Bindings &bs)
Definition: expr.H:1012
Definition: expr.H:299
Definition: expr.H:1281
PrimitivePtr mkTimespanPrim(const str::seq &, const LexicalAnnotation &)
Definition: expr.C:1450
str::seq varNames(unsigned int n)
Definition: pattern.C:527
std::string lbl
Definition: expr.H:453
T with(const Int *v) const
Definition: expr.H:1127
double x
Definition: expr.H:270
const ExprPtr & stripAssumpHead(const ExprPtr &)
Definition: expr.C:1261
MonoTypePtr fnresult(const MonoTypePtr &fty)
Definition: type.H:1233
Definition: expr.H:581
Binding(const std::string &selector, const std::string &vname, const ExprPtr &exp)
Definition: expr.H:511
std::string id
Definition: expr.H:318
std::vector< T > cons(T h, std::vector< T > t)
Definition: array.H:286
ExprPtr substitute(const MonoTypeSubst &s, const ExprPtr &e)
Definition: expr.C:985
Definition: expr.H:546
PrimitiveCase< Case > Base
Definition: expr.H:96
Bindings bs
Definition: expr.H:541
std::vector< ConstraintPtr > Constraints
Definition: type.H:35
bool operator==(const Expr &rhs) const
Definition: expr.H:47
unsigned char x
Definition: expr.H:180
ExprPtr lhs
Definition: expr.H:413
Definition: expr.H:603
int tgenSize(const ExprPtr &)
Definition: expr.C:2152
Definition: expr.H:1365
Definition: expr.H:1102
int x
Definition: expr.H:216
Definition: expr.H:324
Expr * mkarray(const std::string &v, const LexicalAnnotation &la)
Definition: expr.H:923
std::shared_ptr< Expr > ExprPtr
Definition: expr.H:58
ExprPtr nothingE(const MonoTypePtr &jt, const LexicalAnnotation &la)
Definition: expr.H:990
Definition: expr.H:238
ExprPtr stripExplicitAssumptions(const ExprPtr &)
Definition: expr.C:1257
ExprPtr justE(const ExprPtr &e, const LexicalAnnotation &la)
Definition: expr.H:974
ExprPtr body
Definition: expr.H:664
std::vector< T > list()
Definition: array.H:25
Definition: expr.H:418
T with(const Long *v) const
Definition: expr.H:1128
Definition: lannotation.H:36
short x
Definition: expr.H:198
Definition: tylift.H:81
size_t r(const reader::MetaData &md, size_t o, T *t)
Definition: storage.H:1730
bool hasSingularType(const ExprPtr &)
Definition: expr.C:2047
Definition: lannotation.H:60
Definition: lannotation.H:22
Definition: expr.H:436
std::vector< std::string > seq
Definition: str.H:19
MonoTypePtr freshTypeVar()
Definition: type.C:1612
Binding(const PrimitivePtr &value, const ExprPtr &exp)
Definition: expr.H:550
void decode(const std::vector< uint8_t > &, ExprPtr *)
Definition: expr.C:1938
ExprPtr mktunit(const LexicalAnnotation &la)
Definition: expr.H:748
virtual ~Expr()
Definition: expr.C:38
Definition: expr.H:1073
Definition: expr.H:202
ExprPtr mkTimespanExpr(const str::seq &, const LexicalAnnotation &)
Definition: expr.C:1453
#define out
Definition: netio.H:19
Definition: type.H:513
std::vector< FieldDef > FieldDefs
Definition: expr.H:461
std::vector< Definition > Definitions
Definition: expr.H:62
Definition: expr.H:94
std::set< PrimitivePtr, PrimPtrLT > PrimitiveSet
Definition: expr.H:91
Definition: terminal.H:71
const MonoTypePtr & member(const std::string &mn) const
Definition: type.C:1316
ExprPtr e
Definition: expr.H:454
Definition: variant.H:103
MonoTypePtr clone(const MonoTypePtr &)
Definition: type.C:1530
ExprPtr let(const Exprs &es, const ExprPtr &b, const LexicalAnnotation &la)
Definition: expr.H:740
ExprPtr constant(size_t x, const LexicalAnnotation &la)
Definition: expr.H:696
uint32_t result
Definition: regex.C:376
VarNames vs
Definition: expr.H:369
Bindings bs
Definition: expr.H:576
std::vector< Member > Members
Definition: type.H:435
Definition: expr.H:1308
std::set< std::string > VarSet
Definition: expr.H:1356
MonoTypePtr unpackedType(const Exists *e)
Definition: type.C:2274
ExprPtr i
Definition: expr.H:503
std::pair< std::string, ExprPtr > FieldDef
Definition: expr.H:460
bool isfilter
Definition: expr.H:1369
std::string showAnnotated(const Definition &d)
Definition: expr.C:858
MonoTypePtr sumtype(const MonoTypePtr &t0, const MonoTypePtr &t1)
Definition: type.H:1080
T with(const Short *v) const
Definition: expr.H:1126
Definition: tylift.H:310
std::vector< V > values(const std::map< K, V > &m)
Definition: array.H:218
std::vector< std::string > strings
Definition: data.H:69
T with(const Float *v) const
Definition: expr.H:1129
Definition: expr.H:15
ExprPtr r
Definition: expr.H:598
char x
Definition: expr.H:162
Definition: expr.H:1136
std::vector< MonoTypePtr > MonoTypes
Definition: type.H:72
T switchOfF(const Expr &e, F f)
Definition: expr.H:1166
ExprPtr v
Definition: expr.H:575
Definition: type.H:491
std::shared_ptr< QualType > QualTypePtr
Definition: type.H:28
MonoTypes requireMonotype(const Exprs &)
Definition: expr.C:1239
Definition: expr.H:1032
std::vector< Binding > Bindings
Definition: expr.H:327
T with(const Char *v) const
Definition: expr.H:1124
ExprPtr fn(const std::string &vn, const ExprPtr &b, const LexicalAnnotation &la)
Definition: expr.H:841
LexicalAnnotation m(const YYLTYPE &p)
Definition: hexpr.parse.C:127
std::vector< std::string > VarNames
Definition: expr.H:352
Case::Bindings switchOf(const Case::Bindings &bs, const switchExpr< ExprPtr > &f)
Definition: expr.C:1023
std::map< TVName, MonoTypePtr > MonoTypeSubst
Definition: type.H:143
Definition: expr.H:396
Binding()
Definition: expr.H:549
Definition: expr.H:509
ExprPtr rhs
Definition: expr.H:414
ExprPtr arr
Definition: expr.H:502
std::string show(const Definition &d)
Definition: expr.C:27
Definition: jitcc.H:21
Definition: expr.H:220
bool x
Definition: expr.H:145
bool operator<(const Primitive &rhs) const
Definition: expr.H:101
virtual void showAnnotated(std::ostream &) const =0
std::string selector
Definition: expr.H:513
ExprPtr mkDateTimeExpr(const std::string &, const LexicalAnnotation &)
Definition: expr.C:1467
Exprs vars(const std::vector< std::string > &vns, const LexicalAnnotation &la)
Definition: expr.H:706
virtual void show(std::ostream &) const =0
unsigned char UnitV
Definition: array.H:17
int cid
Definition: expr.H:36
TVName freshName()
Definition: type.C:1600
std::vector< Binding > Bindings
Definition: expr.H:517
Constraints mergeConstraints(const Constraints &lhs, const Constraints &rhs)
Definition: type.C:1581
T with(const Double *v) const
Definition: expr.H:1130
ExprPtr exp
Definition: expr.H:515