hobbes
a language, embedded compiler, and runtime for efficient dynamic expression evaluation, data storage and analysis
pattern.H
Go to the documentation of this file.
1 /*
2  * pattern : defines a high-level pattern matching expression
3  */
4 
5 #ifndef HOBBES_LANG_PAT_PATTERN_HPP_INCLUDED
6 #define HOBBES_LANG_PAT_PATTERN_HPP_INCLUDED
7 
8 #include <hobbes/lang/expr.H>
10 #include <hobbes/util/hash.H>
12 
13 namespace hobbes {
14 
15 typedef std::vector<size_t> Idxs;
16 
17 // the main signature for this module -- convert a pattern match expression to a primitive compilable expression
18 class Pattern;
19 typedef std::shared_ptr<Pattern> PatternPtr;
20 typedef std::vector<PatternPtr> Patterns;
21 
22 struct PatternRow {
23  inline PatternRow() { }
24  inline PatternRow(const Patterns& ps, const ExprPtr& r) : patterns(ps), result(r) { }
25  inline PatternRow(const Patterns& ps, const ExprPtr& g, const ExprPtr& r) : patterns(ps), guard(g), result(r) { }
26 
27  Patterns patterns; // match conditions for this row
28  ExprPtr guard; // a required condition for a match (may be null if there is no guard)
29  ExprPtr result; // the expression to be evaluated when the given pattern conditions are met
30 };
31 typedef std::vector<PatternRow> PatternRows;
32 typedef std::shared_ptr<std::vector<std::pair<size_t, PatternRow>>> UnreachableMatchRowsPtr;
33 
34 // support quick hashing of pattern tables
35 bool operator==(const PatternRow&, const PatternRow&);
36 size_t hash(const PatternRow&);
37 
38 // sneak the whole compiler through a back door to see how bindings are set up and maybe to do low-level compilation for special cases of pattern matches
39 class cc;
40 
41 // evaluate the expression for the first pattern row matching the input
42 ExprPtr compileMatch(cc*, const Exprs&, const PatternRows&, const LexicalAnnotation&);
43 
44 // produce an expression to test whether an expression matches a single pattern
45 ExprPtr compileMatchTest(cc*, const ExprPtr&, const PatternPtr&, const LexicalAnnotation&);
46 
47 // a general representation of patterns to match
48 class Pattern : public LexicallyAnnotated {
49 public:
50  virtual void show(std::ostream&) const = 0;
51  virtual bool operator==(const Pattern&) const = 0;
52 
53  // allow explicit naming of stages of a pattern (for internal use only)
54  const std::string& name() const;
55  void name(const std::string&);
56 private:
57  std::string pname;
58 protected:
59  virtual void assignSubNames(const std::string&) = 0;
60 
61  // improves performance of case-analysis over instances (to avoid 'dynamic_cast')
62 public:
63  int case_id() const;
64 protected:
65  Pattern(int cid, const LexicalAnnotation&);
66 private:
67  int cid;
68 };
69 
70 template <typename Case>
71  class PatternCase : public Pattern {
72  public:
75  };
76 
77 std::string show(const PatternPtr& p);
78 std::string show(const Patterns& ps);
79 std::string show(const PatternRow& pr);
80 
81 // literal patterns
82 // contain a "proxy value" for internal equality/ordering checks: ((), false, 0xde, 'c', 1, 3L, 2.3, ...)
83 // contain a "residual expression value" for generating code
84 // (this distinction allows us to use aliased constants like exchanges, timespans, etc in match expressions)
85 class MatchLiteral : public PatternCase<MatchLiteral> {
86 public:
87  MatchLiteral(const PrimitivePtr& proxy, const LexicalAnnotation&);
88  MatchLiteral(const PrimitivePtr& proxy, const ExprPtr& value, const LexicalAnnotation&);
89 
90  const ExprPtr& expression() const;
91  const PrimitivePtr& equivConstant() const;
92 
93  void show(std::ostream&) const;
94  bool operator==(const Pattern&) const;
95 
96  static const int type_case_id = 0;
97 private:
100 
101  void assignSubNames(const std::string&);
102 };
103 
104 // match any value, maybe bind it to a variable name
105 class MatchAny : public PatternCase<MatchAny> {
106 public:
107  MatchAny(const std::string& vn, const LexicalAnnotation&);
108 
109  const std::string& value() const;
110 
111  void show(std::ostream&) const;
112  bool operator==(const Pattern&) const;
113 
114  static const int type_case_id = 1;
115 private:
116  std::string vn;
117 
118  void assignSubNames(const std::string&);
119 };
120 
121 // match an array of patterns
122 class MatchArray : public PatternCase<MatchArray> {
123 public:
124  MatchArray(const Patterns& ps, const LexicalAnnotation&); // default indexes = [0,ps.size())
125 
126  const PatternPtr& pattern(size_t i) const;
127  const Idxs& indexes() const;
128  size_t size() const; // alias for indexes().size()
129 
130  // allow external permutation of array match sequence
131  void indexes(const Idxs&);
132 
133  void show(std::ostream&) const;
134  bool operator==(const Pattern&) const;
135 
136  static const int type_case_id = 2;
137 private:
138  Patterns ps;
139  Idxs idxs;
140 
141  void assignSubNames(const std::string&);
142 };
143 
144 // match a regular expression
145 class MatchRegex : public PatternCase<MatchRegex> {
146 public:
147  MatchRegex(const RegexPtr&, const LexicalAnnotation&);
148  MatchRegex(const std::string&, const LexicalAnnotation&);
149 
150  std::string text() const;
151  const RegexPtr& value() const;
152 
153  static PatternPtr toRegex(const MatchArray&);
154 
155  void show(std::ostream&) const;
156  bool operator==(const Pattern&) const;
157  static const int type_case_id = 3;
158 private:
160 
161  void assignSubNames(const std::string&);
162 };
163 
164 // match a record of patterns
165 class MatchRecord : public PatternCase<MatchRecord> {
166 public:
167  typedef std::pair<std::string, PatternPtr> Field;
168  typedef std::vector<Field> Fields;
169 
170  MatchRecord(const Fields& fs, const LexicalAnnotation&); // default indexes = [0,fs.size())
171 
172  const Field& pattern(size_t i) const;
173  const Idxs& indexes() const;
174  size_t size() const; // alias for indexes().size()
175 
176  const Fields& fields() const;
177  void fields(const Fields&);
178 
179  void show(std::ostream&) const;
180  bool operator==(const Pattern&) const;
181 
182  static const int type_case_id = 4;
183 private:
184  Fields fs;
185  Idxs is;
186 
187  void assignSubNames(const std::string&);
188 
189  static void show(std::ostream&, const Field& f);
190 };
191 
192 // match a variant constructor
193 class MatchVariant : public PatternCase<MatchVariant> {
194 public:
195  MatchVariant(const std::string& lbl, const PatternPtr& p, const LexicalAnnotation&);
196 
197  const std::string& label() const;
198  const PatternPtr& value() const;
199 
200  void show(std::ostream&) const;
201  bool operator==(const Pattern&) const;
202 
203  static const int type_case_id = 5;
204 private:
205  std::string lbl;
206  PatternPtr p;
207 
208  void assignSubNames(const std::string&);
209 };
210 
211 template <typename Case>
213  }
214 
215 // destruction-side for high-level pattern representations
216 template <typename T>
217  struct switchPattern {
218  virtual T with(const MatchLiteral*) const = 0;
219  virtual T with(const MatchAny*) const = 0;
220  virtual T with(const MatchArray*) const = 0;
221  virtual T with(const MatchRegex*) const = 0;
222  virtual T with(const MatchRecord*) const = 0;
223  virtual T with(const MatchVariant*) const = 0;
224  };
225 
226 template <typename T>
227  T switchOf(const PatternPtr& p, const switchPattern<T>& f) {
228  switch (p->case_id()) {
229  case MatchLiteral::type_case_id:
230  return f.with((const MatchLiteral*)p.get());
231  case MatchAny::type_case_id:
232  return f.with((const MatchAny*)p.get());
233  case MatchArray::type_case_id:
234  return f.with((const MatchArray*)p.get());
235  case MatchRegex::type_case_id:
236  return f.with((const MatchRegex*)p.get());
237  case MatchRecord::type_case_id:
238  return f.with((const MatchRecord*)p.get());
239  case MatchVariant::type_case_id:
240  return f.with((const MatchVariant*)p.get());
241  default:
242  throw annotated_error(*p, "Internal error, cannot switch on unknown high-level pattern: " + show(p));
243  }
244  }
245 
246 template <typename T>
247  std::vector<T> switchOf(const Patterns& ps, const switchPattern<T>& f) {
248  std::vector<T> r;
249  for (Patterns::const_iterator p = ps.begin(); p != ps.end(); ++p) {
250  r.push_back(switchOf(*p, f));
251  }
252  return r;
253  }
254 
255 // construction utilities
256 inline MatchArray* mkpatarray(const std::vector<unsigned char>& bs, const LexicalAnnotation& la) {
257  Patterns ps;
258  for (std::vector<unsigned char>::const_iterator b = bs.begin(); b != bs.end(); ++b) {
259  ps.push_back(PatternPtr(new MatchLiteral(PrimitivePtr(new Byte(*b, la)), la)));
260  }
261  return new MatchArray(ps, la);
262 }
263 
264 inline MatchArray* mkpatarray(const std::string& cs, const LexicalAnnotation& la) {
265  Patterns ps;
266  for (std::string::const_iterator c = cs.begin(); c != cs.end(); ++c) {
267  ps.push_back(PatternPtr(new MatchLiteral(PrimitivePtr(new Char(*c, la)), la)));
268  }
269  return new MatchArray(ps, la);
270 }
271 
272 // is it possible for a pattern to be refuted?
273 bool refutable(const PatternPtr&);
274 
275 // is a pattern a match on unit?
276 bool isUnitPat(const PatternPtr&);
277 
278 }
279 
280 // make sure that pattern rows can be used as keys in hash maps
281 namespace std {
282 template <>
283  struct hash< hobbes::PatternRow > {
284  inline size_t operator()(const hobbes::PatternRow& x) const {
285  return hobbes::hash(x);
286  }
287  };
288 }
289 
290 #endif
PatternRow(const Patterns &ps, const ExprPtr &r)
Definition: pattern.H:24
std::pair< std::string, PatternPtr > Field
Definition: pattern.H:167
std::vector< T > switchOf(const Patterns &ps, const switchPattern< T > &f)
Definition: pattern.H:247
Definition: pattern.H:48
Definition: expr.H:148
Definition: pattern.H:122
Definition: pattern.H:165
int cid
Definition: pattern.H:67
std::shared_ptr< Regex > RegexPtr
Definition: regex.H:40
ExprPtr result
Definition: pattern.H:29
std::shared_ptr< std::vector< std::pair< size_t, PatternRow > > > UnreachableMatchRowsPtr
Definition: pattern.H:32
Definition: pattern.H:22
std::string show(const PatternRow &pr)
Definition: pattern.C:309
Definition: pattern.H:281
Definition: expr.H:507
bool operator==(const PatternRow &, const PatternRow &)
Definition: pattern.C:270
Definition: boot.H:7
std::vector< ExprPtr > Exprs
Definition: expr.H:59
std::string lbl
Definition: pattern.H:205
std::string pname
Definition: pattern.H:57
Patterns patterns
Definition: pattern.H:27
size_t hash(const PatternRow &)
Definition: pattern.C:283
Patterns ps
Definition: pattern.H:138
ExprPtr guard
Definition: pattern.H:28
std::shared_ptr< Primitive > PrimitivePtr
Definition: expr.H:86
Definition: pattern.H:105
ExprPtr compileMatchTest(cc *, const ExprPtr &, const PatternPtr &, const LexicalAnnotation &)
Definition: pattern.C:631
Definition: pattern.H:145
Definition: expr.H:166
MatchArray * mkpatarray(const std::string &cs, const LexicalAnnotation &la)
Definition: pattern.H:264
virtual T with(const MatchLiteral *) const =0
PatternCase< Case > Base
Definition: pattern.H:73
bool refutable(const PatternPtr &)
Definition: pattern.C:658
std::string show(const Expr &e)
Definition: expr.C:19
ExprPtr compileMatch(cc *, const Exprs &, const PatternRows &, const LexicalAnnotation &)
Definition: pattern.C:617
RegexPtr regex
Definition: pattern.H:159
std::shared_ptr< Expr > ExprPtr
Definition: expr.H:58
PatternRow(const Patterns &ps, const ExprPtr &g, const ExprPtr &r)
Definition: pattern.H:25
Definition: lannotation.H:36
size_t r(const reader::MetaData &md, size_t o, T *t)
Definition: storage.H:1730
PrimitivePtr p
Definition: pattern.H:98
size_t operator()(const hobbes::PatternRow &x) const
Definition: pattern.H:284
Definition: cc.H:64
Definition: lannotation.H:60
Definition: lannotation.H:22
std::string vn
Definition: pattern.H:116
PatternRow()
Definition: pattern.H:23
ExprPtr e
Definition: pattern.H:99
uint32_t result
Definition: regex.C:376
std::vector< PatternPtr > Patterns
Definition: pattern.H:20
Definition: pattern.H:71
Idxs is
Definition: pattern.H:185
Definition: tylift.H:310
std::vector< Field > Fields
Definition: pattern.H:168
std::vector< size_t > Idxs
Definition: pattern.H:15
Fields fs
Definition: pattern.H:184
PatternPtr p
Definition: pattern.H:206
Idxs idxs
Definition: pattern.H:139
bool isUnitPat(const PatternPtr &)
Definition: pattern.C:662
Definition: pattern.H:85
std::vector< PatternRow > PatternRows
Definition: pattern.H:31
Definition: pattern.H:217
std::shared_ptr< Pattern > PatternPtr
Definition: pattern.H:18
PatternCase(const LexicalAnnotation &)
Definition: pattern.H:212
Definition: pattern.H:193