private boolean matches(final Expr expr1, final Expr expr2) {
		final LinkedList leaves = new LinkedList();

		expr1.visit(new TreeVisitor() {
			public void visitStoreExpr(final StoreExpr expr) {
				expr.target().visit(this);
			}

			public void visitConstantExpr(final ConstantExpr expr) {
				leaves.add(expr);
			}

			public void visitVarExpr(final VarExpr expr) {
				leaves.add(expr);
			}
		});

		final Bool match = new Bool();
		match.value = true;

		expr2.visit(new TreeVisitor() {
			public void visitExpr(final Expr expr) {
				if (match.value) {
					expr.visitChildren(this);
				}
			}

			public void visitStoreExpr(final StoreExpr expr) {
				if (match.value) {
					expr.target().visit(this);
				}
			}

			public void visitConstantExpr(final ConstantExpr expr) {
				visitLeaf(expr);
			}

			public void visitVarExpr(final VarExpr expr) {
				visitLeaf(expr);
			}

			public void visitLeaf(final Expr expr) {
				if (leaves.isEmpty()) {
					match.value = false;
					return;
				}

				final Expr leaf = (Expr) leaves.removeFirst();

				if ((leaf == null)
						|| (expr.valueNumber() != leaf.valueNumber())) {
					match.value = false;
				}
			}
		});

		return match.value;
	}