FAUST compiler  0.9.9.6b8
patternmatcher.cpp
Go to the documentation of this file.
1 
2 /* compiler/patternmatcher/patternmatcher.cpp: implementation of the Faust
3  rewriting engine */
4 
5 #include "tlib.hh"
6 #include "list.hh"
7 #include "boxes.hh"
8 #include "ppbox.hh"
9 #include "eval.hh"
10 #include "patternmatcher.hh"
11 
12 using namespace std;
13 #include <vector>
14 #include <list>
15 #include <set>
16 #include <utility>
17 
18 /* Uncomment for debugging output. */
19 //#define DEBUG
20 
21 /* Additional Tree deconstruction operations. */
22 
23 /* Check for cons (nonempty list) nodes. */
24 
25 static inline bool isCons(Tree x, Tree& h, Tree& t)
26 {
27  if (isList(x)) {
28  h = hd(x); t = tl(x);
29  return true;
30  } else
31  return false;
32 }
33 
34 /* Deconstruct a (BDA) op pattern (YO). */
35 
36 static inline bool isBoxPatternOp(Tree box, Node& n, Tree& t1, Tree& t2)
37 {
38  if ( isBoxPar(box, t1, t2) ||
39  isBoxSeq(box, t1, t2) ||
40  isBoxSplit(box, t1, t2) ||
41  isBoxMerge(box, t1, t2) ||
42  isBoxHGroup(box, t1, t2) ||
43  isBoxVGroup(box, t1, t2) ||
44  isBoxTGroup(box, t1, t2) ||
45  isBoxRec(box, t1, t2) )
46  {
47  n = box->node();
48  return true;
49  } else {
50  return false;
51  }
52 }
53 
54 /* TA data structures. */
55 
56 /* subterm paths */
57 
58 typedef vector<int> Path;
59 
60 /* Subterm at given path in given term tree. */
61 
62 static Tree subtree(Tree X, int i, const Path& p)
63 {
64  int n = (int)p.size();
65  Node op(0);
66  Tree x0, x1;
67  if (i < n && isBoxPatternOp(X, op, x0, x1))
68  return subtree((p[i]==0)?x0:x1, i+1, p);
69  else
70  return X;
71 }
72 
73 /* rule markers */
74 
75 struct Rule {
76  int r; // rule number
77  Tree id; // matched variable (NULL if none)
78  Path p; // subterm path indicating where variable value is found
79 
80  Rule(int _r, Tree _id) : r(_r), id(_id), p(Path()) {}
81  Rule(int _r, Tree _id, const Path& _p) : r(_r), id(_id), p(_p) {}
82  Rule(const Rule& rule) : r(rule.r), id(rule.id), p(rule.p) {}
83 
84  Rule& operator = (const Rule& rule)
85  { r = rule.r; id = rule.id; p = rule.p; return *this; }
86 
87  bool operator == (const Rule& rule) const
88  { return r == rule.r; }
89  bool operator < (const Rule& rule) const
90  { return r < rule.r; }
91 
92 #ifdef DEBUG
93  ostream& print(ostream& fout) const;
94 #endif
95 };
96 
97 struct State;
98 
99 /* transitions */
100 
101 struct Trans {
102  Tree x; // symbol or constant (NULL for variable)
103  Node n; // operator symbol (if arity>0)
104  int arity; // symbol arity
105  State *state; // successor state
106 
107  Trans(Tree _x);
108  Trans(const Node& _n, int _arity);
109  Trans(const Trans& trans);
110  ~Trans();
111 
112  Trans& operator = (const Trans& trans);
113 
114  bool is_var_trans() const { return arity == 0 && x == NULL; }
115  bool is_cst_trans(Tree &_x) const { _x = x; return arity == 0 && x != NULL; }
116  bool is_op_trans(Node &_n) const { _n = n; return arity > 0; }
117 
118  bool operator == (const Trans& trans) const
119  { return arity == trans.arity && x == trans.x && n == trans.n; }
120  bool operator < (const Trans& trans) const
121  { return (arity < trans.arity) ? 1 :
122  (arity > trans.arity) ? 0 :
123  (arity == 0) ? (x < trans.x) :
124  (n.getSym() < trans.n.getSym()); }
125 
126 #ifdef DEBUG
127  ostream& print(ostream& fout) const;
128 #endif
129 };
130 
131 /* states */
132 
133 struct State {
134  int s; // state number
135  bool match_num; // whether state has a transition on a numeric constant
136  list<Rule> rules; // rule markers
137  list<Trans> trans; // transitions (1st transition is on variable if available)
138  State() :
139  s(0), match_num(false), rules(list<Rule>()), trans(list<Trans>()) {}
140  State(const State& state) :
141  s(state.s), match_num(state.match_num),
142  rules(state.rules), trans(state.trans) {}
143 
144  State& operator = (const State& state)
145  { s = state.s; match_num = state.match_num;
146  rules = state.rules; trans = state.trans;
147  return *this;
148  }
149 
150 #ifdef DEBUG
151  ostream& print(ostream& fout) const;
152 #endif
153 };
154 
155 // these need to come here so that the storage size of struct State is known
156 
158  x(_x), n(0), arity(0), state(new State)
159 {
160 }
161 
162 Trans::Trans(const Node& _n, int _arity) :
163  x(NULL), n(_n), arity(_arity), state(new State)
164 {
165 }
166 
167 Trans::Trans(const Trans& trans) :
168  x(trans.x), n(trans.n), arity(trans.arity)
169 {
170  state = new State(*trans.state);
171 }
172 
174 {
175  delete state;
176 }
177 
179 {
180  x = trans.x; n = trans.n; arity = trans.arity;
181  state = new State(*trans.state);
182  return *this;
183 }
184 
185 /* the automaton */
186 
187 struct Automaton {
188  vector<State*> state;
189  vector<Tree> rhs;
190 
191  Automaton() : state(vector<State*>()), rhs(vector<Tree>()), s(0) {}
192 
193  // number of rules
194  int n_rules() { return (int)rhs.size(); }
195  // markers of rules still active in state s
196  const list<Rule>& rules(int s) { return state[s]->rules; }
197  // transitions in state s
198  const list<Trans>& trans(int s) { return state[s]->trans; }
199  // is s a final state?
200  bool final(int s) { return trans(s).empty(); }
201 
202  // assign state numbers and build the state table
203  int s;
204  void build(State *st);
205 
206 #ifdef DEBUG
207  ostream& print(ostream& fout) const;
208 #endif
209 };
210 
212 {
213  state.push_back(st);
214  st->s = s++;
215  list<Trans>::const_iterator t;
216  for (t = st->trans.begin(); t != st->trans.end(); t++) {
217  Tree x;
218  double f;
219  int i;
220  if (t->is_cst_trans(x) &&
221  (isBoxInt(x, &i) || isBoxReal(x, &f)))
222  st->match_num = true;
223  build(t->state);
224  }
225 }
226 
227 /* Debugging output. */
228 
229 #ifdef DEBUG
230 inline ostream& operator << (ostream& s, const Rule& x)
231 { return x.print(s); }
232 inline ostream& operator << (ostream& s, const Trans& x)
233 { return x.print(s); }
234 inline ostream& operator << (ostream& s, const State& x)
235 { return x.print(s); }
236 inline ostream& operator << (ostream& s, const Automaton& x)
237 { return x.print(s); }
238 
239 ostream& Rule::print(ostream& fout) const
240 {
241  if (id != NULL)
242  fout << "#" << r << "(" << *id << ")";
243  else
244  fout << "#" << r;
245  return fout;
246 }
247 
248 ostream& Trans::print(ostream& fout) const
249 {
250  if (arity > 0)
251  fout << "\top " << n << ": state " << state->s << endl;
252  else if (x == NULL)
253  fout << "\tvar _: state " << state->s << endl;
254  else
255  fout << "\tcst " << *x << ": state " << state->s << endl;
256  return fout;
257 }
258 
259 ostream& State::print(ostream& fout) const
260 {
261  fout << "state " << s << ":";
262  list<Rule>::const_iterator r;
263  for (r = rules.begin(); r != rules.end(); r++)
264  fout << " " << *r;
265  fout << endl;
266  list<Trans>::const_iterator t;
267  for (t = trans.begin(); t != trans.end(); t++)
268  fout << *t;
269  return fout;
270 }
271 
272 ostream& Automaton::print(ostream& fout) const
273 {
274  int i, n = rhs.size();
275  for (i = 0; i < n; i++)
276  fout << "rule #" << i << ": " << *rhs[i] << endl;
277  n = state.size();
278  for (i = 0; i < n; i++)
279  fout << *state[i];
280  return fout;
281 }
282 #endif
283 
284 /* Construction algorithm for the pattern matching automaton.
285  *
286  * We employ the incremental technique described in Graef: Left-To-Right Tree
287  * Pattern Matching, Proc. RTA 1991, Springer 1991 (LNCS 488) to construct a
288  * tree automaton (TA) for the given patterns. The basic outline of the
289  * technique is as follows. Initially, the automaton is empty. From each
290  * pattern we produce a trie (considering the pattern as a string of variable
291  * and function symbols and constants). This trie is then merged with the TA
292  * obtained so far. The latter process is similar to merging two deterministic
293  * finite automata, but it also takes into account the variables (see the
294  * merge_state() routine below).
295  */
296 
297 /* Construct a trie from a term tree. Takes the "start" and returns the "end"
298  state of the (sub-)trie. */
299 
300 static State *make_state(State *state, int r, Tree x, Path& p)
301 {
302  Tree id, x0, x1;
303  Node op(0);
304  if (isBoxPatternVar(x, id)) {
305  /* variable */
306  Rule rule(r, id, p);
307  state->rules.push_back(rule);
308  Trans trans(NULL);
309  state->trans.push_back(trans);
310  return state->trans.begin()->state;
311  } else if (isBoxPatternOp(x, op, x0, x1)) {
312  /* composite pattern */
313  Rule rule(r, NULL);
314  state->rules.push_back(rule);
315  Trans trans(op, 2);
316  state->trans.push_back(trans);
317  State *next = state->trans.begin()->state;
318  p.push_back(0);
319  next = make_state(next, r, x0, p);
320  p.pop_back();
321  p.push_back(1);
322  next = make_state(next, r, x1, p);
323  p.pop_back();
324  return next;
325  } else {
326  /* constant */
327  Rule rule(r, NULL);
328  state->rules.push_back(rule);
329  Trans trans(x);
330  state->trans.push_back(trans);
331  return state->trans.begin()->state;
332  }
333 }
334 
335 /* Take a copy of a state and prefix it with n variable transitions. */
336 
337 static State *make_var_state(int n, State *state)
338 {
339  if (n <= 0)
340  return new State(*state);
341  list<Rule>rules = state->rules;
342  list<Rule>::iterator r;
343  for (r = rules.begin(); r != rules.end(); r++) {
344  r->id = NULL; r->p = Path();
345  }
346  State *prefix = new State, *current = prefix;
347  while (n-- > 0) {
348  current->rules = rules;
349  Trans trans(NULL);
350  current->trans.push_back(trans);
351  current = current->trans.begin()->state;
352  }
353  *current = *state;
354  return prefix;
355 }
356 
357 /* Merge two tree automata. Merges the tree automaton rooted at state2 into
358  the automaton rooted at state1. We assume that state2 is in "trie" form,
359  i.e., each state has at most one transition, which is always guaranteed
360  here and simplifies the algorithm. */
361 
362 static void merge_state(State *state1, State *state2);
363 
364 static void inline merge_rules(list<Rule>& rules1, list<Rule>& rules2)
365 {
366  list<Rule> cprules2 = rules2;
367  rules1.merge(cprules2);
368 }
369 
370 static void merge_trans_var(list<Trans>& trans, State *state)
371 {
372  if (!trans.begin()->is_var_trans()) {
373  /* If we don't have a variable transition in this state yet then create a
374  new one. */
375  Trans tr(NULL);
376  trans.push_front(tr);
377  }
378  list<Trans>::const_iterator t;
379  Tree x;
380  Node op(0);
381  for (t = trans.begin(); t != trans.end(); t++) {
382  if (t->is_var_trans())
383  merge_state(t->state, state);
384  else if (t->is_cst_trans(x)) {
385  /* add the completion of the given state for a constant */
386  merge_state(t->state, state);
387  } else if (t->is_op_trans(op)) {
388  /* add the completion of the given state for an arity>0 op */
389  State *state1 = make_var_state(t->arity, state);
390  merge_state(t->state, state1);
391  delete state1;
392  }
393  }
394 }
395 
396 static void merge_trans_cst(list<Trans>& trans, Tree x, State *state)
397 {
398  list<Trans>::iterator t0 = trans.begin(), t1 = t0, t;
399  Tree x1;
400  if (t0->is_var_trans()) t1++;
401  for (t = t1; t != trans.end(); t++) {
402  if (t->is_cst_trans(x1)) {
403  if (x == x1) {
404  merge_state(t->state, state);
405  return;
406  } else if (x < x1)
407  break;
408  }
409  }
410  /* no matching transition has been found; add a new one */
411  Trans tr(x);
412  trans.insert(t, tr); t--;
413  State *state1 = t->state;
414  *state1 = *state;
415  if (t1 != t0) {
416  /* if we have a variable transition in the current state, we also need to
417  merge its completion for the current symbol/constant */
418  merge_state(state1, t0->state);
419  }
420 }
421 
422 static void merge_trans_op(list<Trans>& trans, const Node& op,
423  int arity, State *state)
424 {
425  /* analogous to merge_trans_cst above, but handles the arity>0 case */
426  list<Trans>::iterator t0 = trans.begin(), t1 = t0, t;
427  Node op1(0);
428  if (t0->is_var_trans()) t1++;
429  for (t = t1; t != trans.end(); t++) {
430  if (t->is_op_trans(op1)) {
431  if (op == op1) {
432  merge_state(t->state, state);
433  return;
434  } else if (op.getSym() < op1.getSym())
435  break;
436  }
437  }
438  Trans tr(op, arity);
439  trans.insert(t, tr); t--;
440  State *state1 = t->state;
441  *state1 = *state;
442  if (t1 != t0) {
443  State *state2 = make_var_state(arity, t0->state);
444  merge_state(state1, state2);
445  delete state2;
446  }
447 }
448 
449 static void merge_trans(list<Trans>& trans1, list<Trans>& trans2)
450 {
451  Tree x;
452  Node op(0);
453  if (trans2.empty())
454  ;
455  else if (trans1.empty()) {
456  list<Trans> cptrans2 = trans2;
457  /* append a copy of trans2 to trans1 */
458  trans1.splice(trans1.end(), cptrans2);
459  } else if (trans2.begin()->is_var_trans())
460  /* merge a variable transition */
461  merge_trans_var(trans1, trans2.begin()->state);
462  else if (trans2.begin()->is_cst_trans(x))
463  /* merge a constant transition */
464  merge_trans_cst(trans1, x, trans2.begin()->state);
465  else if (trans2.begin()->is_op_trans(op))
466  /* merge a BDA op transition */
467  merge_trans_op(trans1, op, trans2.begin()->arity, trans2.begin()->state);
468 }
469 
470 static void merge_state(State *state1, State *state2)
471 {
472  merge_rules(state1->rules, state2->rules);
473  merge_trans(state1->trans, state2->trans);
474 }
475 
476 /* Take the rules of a BoxCase expression and return a pointer to the
477  corresponding TA automaton (interface operation). */
478 
480 /* Tree R encodes the rules of a case box expressions as a Tree object, as
481  follows:
482 
483  Rules ::= cons Rule (cons Rule ... nil)
484  Rule ::= cons Lhs Rhs
485  Lhs ::= cons Pattern (cons Pattern ... nil)
486  Pattern ::= Tree (parameter pattern)
487  Rhs ::= Tree
488 
489  NOTE: The lists of rules and patterns are actually delivered in reverse
490  order by the parser, so we have to reverse them on the fly. */
491 {
492  Automaton *A = new Automaton;
493  int n = len(R), r = n;
494  State *start = new State;
495  Tree rule, rest;
496  vector<Tree> rules(n, (Tree)NULL);
497  vector< vector<Tree> > testpats(n);
498  while (isCons(R, rule, rest)) {
499  rules[--r] = rule;
500  R = rest;
501  }
502  for (r = 0; r < n; r++) {
503  Tree lhs, rhs;
504  if (isCons(rules[r], lhs, rhs)) {
505  Tree pat, rest;
506  int m = len(lhs), i = m;
507  vector<Tree> pats(len(lhs), (Tree)NULL);
508  State *state0 = new State, *state = state0;
509  A->rhs.push_back(rhs);
510  while (isCons(lhs, pat, rest)) {
511  pats[--i] = pat;
512  lhs = rest;
513  }
514  testpats[r] = pats;
515  for (i = 0; i < m; i++) {
516  Path p;
517  state = make_state(state, r, pats[i], p);
518  }
519  Rule rule(r, NULL);
520  state->rules.push_back(rule);
521  merge_state(start, state0);
522  delete state0;
523  }
524  }
525  A->build(start);
526  /* Check for shadowed rules. Note that because of potential nonlinearities
527  it is *not* enough to just check the rule lists of final states and
528  determine whether they have multiple matched rules. */
529  for (r = 0; r < n; r++) {
530  int s = 0, m = (int)testpats[r].size();
531  Tree C;
532  vector<Tree> E(n, nil);
533  /* try to match the lhs of rule #r */
534  for (int i = 0; i < m; i++) {
535  s = apply_pattern_matcher(A, s, testpats[r][i], C, E);
536  if (s < 0) break;
537  }
538  if (A->final(s)) {
539  list<Rule>::const_iterator ru;
540  for (ru = A->rules(s).begin(); ru != A->rules(s).end(); ru++)
541  if (!isBoxError(E[ru->r]))
542  if (ru->r < r) {
543  /* Lhs of rule #r matched a higher-priority rule, so rule #r may
544  be shadowed. */
545  Tree lhs1, rhs1, lhs2, rhs2;
546  if (isCons(rules[ru->r], lhs1, rhs1) && isCons(rules[r], lhs2, rhs2)) {
547  cerr << "WARNING : shadowed pattern-matching rule: "
548  << boxpp(reverse(lhs2)) << " => " << boxpp(rhs2) << ";"
549  << " previous rule was: "
550  << boxpp(reverse(lhs1)) << " => " << boxpp(rhs1) << ";"
551  << endl;
552  } else {
553  cerr << "INTERNAL ERROR : " << __FILE__ << ":" << __LINE__ << endl;
554  exit(1);
555  }
556  } else if (ru->r >= r)
557  break;
558  }
559  }
560 #ifdef DEBUG
561  cerr << "automaton " << A << endl << *A << "end automaton" << endl;
562 #endif
563  return A;
564 }
565 
566 /* Helper type to represent variable substitutions which are recorded during
567  matching. Each variable is associated with the path pointing at the subterm
568  of the argument where the substitution of the matched variable is to be
569  found. */
570 
571 struct Assoc {
574  Assoc(Tree _id, const Path& _p) : id(_id), p(_p) {}
575 };
576 typedef list<Assoc> Subst;
577 
578 /* add all substitutions for a given state */
579 
580 static void add_subst(vector<Subst>& subst, Automaton *A, int s)
581 {
582  list<Rule> rules = A->rules(s);
583  list<Rule>::const_iterator r;
584  for (r = rules.begin(); r != rules.end(); r++)
585  if (r->id != NULL)
586  subst[r->r].push_back(Assoc(r->id, r->p));
587 }
588 
589 /* Process a given term tree X starting from state s, modify variable
590  substitutions accordingly. Returns the resulting state, or -1 if no
591  match. This does all the grunt work of matching. */
592 
594  vector<Subst>& subst)
595 {
596  /* FIXME: rewrite this non-recursively? */
597  if (s >= 0) {
598  list<Trans>::const_iterator t;
599  if (A->state[s]->match_num)
600  /* simplify possible numeric argument on the fly */
601  X = simplifyPattern(X);
602  /* first check for applicable non-variable transitions */
603  for (t = A->trans(s).begin(); t != A->trans(s).end(); t++) {
604  Tree x;
605  Node op(0), op1(0);
606  if (t->is_var_trans())
607  continue;
608  else if (t->is_cst_trans(x)) {
609  if (X==x) {
610  /* transition on constant */
611 #ifdef DEBUG
612  cerr << "state " << s << ", " << *x << ": goto state " << t->state->s << endl;
613 #endif
614  add_subst(subst, A, s);
615  s = t->state->s;
616  return s;
617  }
618  } else if (t->is_op_trans(op)) {
619  Tree x0, x1;
620  if (isBoxPatternOp(X, op1, x0, x1) && op == op1) {
621  /* transition on operation symbol */
622 #ifdef DEBUG
623  cerr << "state " << s << ", " << op << ": goto state " << t->state->s << endl;
624 #endif
625  add_subst(subst, A, s);
626  s = t->state->s;
627  if (s >= 0)
628  s = apply_pattern_matcher_internal(A, s, x0, subst);
629  if (s >= 0)
630  s = apply_pattern_matcher_internal(A, s, x1, subst);
631  return s;
632  }
633  }
634  }
635  /* check for variable transition (is always first in the list of
636  transitions) */
637  t = A->trans(s).begin();
638  if (t->is_var_trans()) {
639 #ifdef DEBUG
640  cerr << "state " << s << ", _: goto state " << t->state->s << endl;
641 #endif
642  add_subst(subst, A, s);
643  s = t->state->s;
644  } else {
645 #ifdef DEBUG
646  cerr << "state " << s << ", *** match failed ***" << endl;
647 #endif
648  s = -1;
649  }
650  }
651  return s;
652 }
653 
654 /* Apply the pattern matcher to a single argument, starting from a given state
655  (interface operation). Returns the resulting state, modifies the variable
656  bindings E accordingly, and sets C to the resulting closure if a final
657  state is reached. Result will be -1 to indicate a matching failure, and C
658  will be set to nil if no final state has been reached yet. */
659 
660 int apply_pattern_matcher(Automaton *A, // automaton
661  int s, // start state
662  Tree X, // arg to be matched
663  Tree& C, // output closure (if any)
664  vector<Tree>& E) // modified output environments
665 {
666  int n = A->n_rules();
667  vector<Subst> subst(n, Subst());
668  /* perform matching, record variable substitutions */
669 #ifdef DEBUG
670  cerr << "automaton " << A << ", state " << s << ", start match on arg: " << *X << endl;
671 #endif
672  s = apply_pattern_matcher_internal(A, s, X, subst);
673  C = nil;
674  if (s < 0)
675  /* failed match */
676  return s;
677  /* process variable substitutions */
678  list<Rule>::const_iterator r;
679  for (r = A->rules(s).begin(); r != A->rules(s).end(); r++) {
680  // all rules still active in state s
681  if (!isBoxError(E[r->r])) { // and still viable
682  Subst::const_iterator assoc;
683  for (assoc = subst[r->r].begin(); assoc != subst[r->r].end(); assoc++) {
684  Tree Z, Z1 = subtree(X, 0, assoc->p);
685  if (searchIdDef(assoc->id, Z, E[r->r])) {
686  if (Z != Z1) {
687  /* failed nonlinearity, add to the set of nonviable rules */
688 #ifdef DEBUG
689  cerr << "state " << s << ", rule #" << r->r << ": " <<
690  *assoc->id << " := " << *Z1 << " *** failed *** old value: " <<
691  *Z << endl;
692 #endif
693  E[r->r] = boxError();
694  }
695  } else {
696  /* bind a variable for the current rule */
697 #ifdef DEBUG
698  cerr << "state " << s << ", rule #" << r->r << ": " <<
699  *assoc->id << " := " << *Z1 << endl;
700 #endif
701  E[r->r] = pushValueDef(assoc->id, Z1, E[r->r]);
702  }
703  }
704  }
705  }
706  if (A->final(s)) {
707  /* if in a final state then return the right-hand side together with the
708  corresponding variable environment */
709  for (r = A->rules(s).begin(); r != A->rules(s).end(); r++) // all rules matched in state s
710  if (!isBoxError(E[r->r])) { // and still viable
711  /* return the rhs of the matched rule */
712  C = closure(A->rhs[r->r], nil, nil, E[r->r]);
713 #ifdef DEBUG
714  cerr << "state " << s << ", complete match yields rhs #" << r->r <<
715  ": " << *A->rhs[r->r] << endl;
716 #endif
717  return s;
718  }
719  /* if none of the rules were matched then declare a failed match */
720 #ifdef DEBUG
721  cerr << "state " << s << ", *** match failed ***" << endl;
722 #endif
723  return -1;
724  }
725 #ifdef DEBUG
726  cerr << "state " << s << ", successful incomplete match" << endl;
727 #endif
728  return s;
729 }
static void merge_trans_var(list< Trans > &trans, State *state)
State * state
Sym getSym() const
Definition: node.hh:106
static State * make_var_state(int n, State *state)
static bool isBoxPatternOp(Tree box, Node &n, Tree &t1, Tree &t2)
bool isBoxSeq(Tree t, Tree &x, Tree &y)
Definition: boxes.cpp:136
Tree reverse(Tree l)
Definition: list.cpp:240
bool isBoxInt(Tree t)
Definition: boxes.cpp:78
Class Node = (type x (int + double + Sym + void*))
Definition: node.hh:75
Rule(int _r, Tree _id)
Tree pushValueDef(Tree id, Tree def, Tree lenv)
Push a new layer and add a single definition.
Definition: environment.cpp:94
static void merge_trans(list< Trans > &trans1, list< Trans > &trans2)
bool isBoxSplit(Tree t, Tree &x, Tree &y)
Definition: boxes.cpp:148
static Tree subtree(Tree X, int i, const Path &p)
static State * make_state(State *state, int r, Tree x, Path &p)
bool searchIdDef(Tree id, Tree &def, Tree lenv)
Search the environment (until first barrier) for the definition of a symbol ID and return it...
A CTree = (Node x [CTree]) is a Node associated with a list of subtrees called branches.
Definition: tree.hh:109
static void add_subst(vector< Subst > &subst, Automaton *A, int s)
bool match_num
State(const State &state)
Assoc(Tree _id, const Path &_p)
Tree hd(Tree l)
Definition: list.hh:133
const Node & node() const
return the content of the tree
Definition: tree.hh:143
bool isBoxHGroup(Tree s)
Definition: boxes.cpp:437
list< Rule > rules
bool is_op_trans(Node &_n) const
bool final(int s)
list< Assoc > Subst
interval operator<(const interval &, const interval &)
Definition: interval.hh:171
bool isBoxRec(Tree t, Tree &x, Tree &y)
Definition: boxes.cpp:144
Interface of the block diagram evaluator.
vector< Tree > rhs
static void merge_trans_op(list< Trans > &trans, const Node &op, int arity, State *state)
static bool isCons(Tree x, Tree &h, Tree &t)
Tree simplifyPattern(Tree value)
Simplify a block-diagram pattern by computing its numerical sub-expressions.
Definition: eval.cpp:617
Trans & operator=(const Trans &trans)
bool isBoxTGroup(Tree s)
Definition: boxes.cpp:449
const list< Trans > & trans(int s)
bool isBoxReal(Tree t)
Definition: boxes.cpp:79
string subst(const string &model, const vector< string > &args)
Text substitution.
Definition: Text.cpp:47
vector< State * > state
bool isList(Tree l)
Definition: list.hh:138
bool isBoxPar(Tree t, Tree &x, Tree &y)
Definition: boxes.cpp:140
static void merge_trans_cst(list< Trans > &trans, Tree x, State *state)
static int apply_pattern_matcher_internal(Automaton *A, int s, Tree X, vector< Subst > &subst)
ostream & operator<<(ostream &file, const boxpp &bpp)
Definition: ppbox.hh:69
Tree boxError()
Definition: boxes.cpp:244
bool isBoxVGroup(Tree s)
Definition: boxes.cpp:443
vector< int > Path
Tree closure(Tree abstr, Tree genv, Tree vis, Tree lenv)
Definition: boxes.cpp:234
void build(State *st)
Definition: ppbox.hh:58
Rule(int _r, Tree _id, const Path &_p)
Tree nil
Definition: list.cpp:116
bool isBoxPatternVar(Tree s, Tree &id)
Definition: boxes.cpp:622
interval operator==(const interval &, const interval &)
Definition: interval.hh:191
const list< Rule > & rules(int s)
static void merge_state(State *state1, State *state2)
bool is_var_trans() const
bool isBoxError(Tree t)
Definition: boxes.cpp:249
bool isBoxMerge(Tree t, Tree &x, Tree &y)
Definition: boxes.cpp:152
static void merge_rules(list< Rule > &rules1, list< Rule > &rules2)
Trans(Tree _x)
Rule(const Rule &rule)
list< Trans > trans
int apply_pattern_matcher(Automaton *A, int s, Tree X, Tree &C, vector< Tree > &E)
int len(Tree l)
Definition: list.cpp:198
Automaton * make_pattern_matcher(Tree R)
Tree tl(Tree l)
Definition: list.hh:134
bool is_cst_trans(Tree &_x) const
void print(Tree t, FILE *out)
Definition: list.cpp:154