+/** Check whether the expression matches a given pattern. For every wildcard
+ * object in the pattern, an expression of the form "wildcard == matching_expression"
+ * is added to repl_lst. */
+bool basic::match(const ex & pattern, lst & repl_lst) const
+{
+/*
+ Sweet sweet shapes, sweet sweet shapes,
+ That's the key thing, right right.
+ Feed feed face, feed feed shapes,
+ But who is the king tonight?
+ Who is the king tonight?
+ Pattern is the thing, the key thing-a-ling,
+ But who is the king of Pattern?
+ But who is the king, the king thing-a-ling,
+ Who is the king of Pattern?
+ Bog is the king, the king thing-a-ling,
+ Bog is the king of Pattern.
+ Ba bu-bu-bu-bu bu-bu-bu-bu-bu-bu bu-bu
+ Bog is the king of Pattern.
+*/
+
+ if (is_exactly_a<wildcard>(pattern)) {
+
+ // Wildcard matches anything, but check whether we already have found
+ // a match for that wildcard first (if so, it the earlier match must
+ // be the same expression)
+ for (lst::const_iterator it = repl_lst.begin(); it != repl_lst.end(); ++it) {
+ if (it->op(0).is_equal(pattern))
+ return is_equal(ex_to<basic>(it->op(1)));
+ }
+ repl_lst.append(pattern == *this);
+ return true;
+
+ } else {
+
+ // Expression must be of the same type as the pattern
+ if (tinfo() != ex_to<basic>(pattern).tinfo())
+ return false;
+
+ // Number of subexpressions must match
+ if (nops() != pattern.nops())
+ return false;
+
+ // No subexpressions? Then just compare the objects (there can't be
+ // wildcards in the pattern)
+ if (nops() == 0)
+ return is_equal_same_type(ex_to<basic>(pattern));
+
+ // Check whether attributes that are not subexpressions match
+ if (!match_same_type(ex_to<basic>(pattern)))
+ return false;
+
+ // Otherwise the subexpressions must match one-to-one
+ for (size_t i=0; i<nops(); i++)
+ if (!op(i).match(pattern.op(i), repl_lst))
+ return false;
+
+ // Looks similar enough, match found
+ return true;
+ }
+}
+
+/** Helper function for subs(). Does not recurse into subexpressions. */
+ex basic::subs_one_level(const exmap & m, unsigned options) const
+{
+ exmap::const_iterator it;
+
+ if (options & subs_options::no_pattern) {
+ it = m.find(*this);
+ if (it != m.end())
+ return it->second;
+ } else {
+ for (it = m.begin(); it != m.end(); ++it) {
+ lst repl_lst;
+ if (match(ex_to<basic>(it->first), repl_lst))
+ return it->second.subs(repl_lst, options | subs_options::no_pattern); // avoid infinite recursion when re-substituting the wildcards
+ }
+ }
+
+ return *this;
+}
+