The idea is to match the precedence used in regular programming
languages, where `x = y || x = z` is parsed as `(x = y) || (x = z)`.
This commit also adds `!x` as notation for `bnot x`
All theorems are proved without using the tactic framework.
Thus, we can define `fin/uint32/uint64` types and their operations
before we define the tactic framework.
With the current elaboration scheme, out_params and coercions do not mix well,
as evidenced by the following example by @digama:
```
variables {α : Type*} [group α]
def gpow : α → ℤ → α := sorry
instance group.has_pow : has_pow α ℤ := ⟨gpow⟩
example (a : α) : a ^ 0 = 1 := sorry -- failed to synth ⊢ has_pow α ℕ
example (a : α) : a ^ (0:ℕ) = 1 := sorry -- ok, coerces
example (a : α) : a ^ (0:ℤ) = 1 := sorry -- ok
```
The issue is that
* we first try to solve `has_pow ?α ?β`, which is postponed
* then infer `?α = nat` from `a`
* then at some point call `elaborator::synthesize()` and default `β` to `nat`
* then try to solve `has_pow nat nat`, which fails at `int =?= nat`
The previous `decidable_bex` was using a nasty hack.
First, it was relying on a bug in the local_context object that was
fixed at commit 6060b75e6. Note that, the type class resolution
will be even more restrictive after we implement the fix described at a75b0d8ee.
Second, it was built using tactics that are meant for constructing
proof irrelevant code (e.g., `simp`).
@kha I've added
iterator.extract : iterator -> iterator -> option string
It returns `none` if the iterators are "incompatible".
If this function is inconvenient to use, we can change it and return the
empty string in these cases.
Given iterators `it1` and `it2`, if they are sharing the same string
object in memory, then the cost is O(pos(it2) - pos(it1)).
If not, we have an extra O(N) step where we check whether the strings
being iterated by it1 and it2 are equal (`N` is the size of the strings).
In most applications, I believe the iterators will share the string
object.
I didn't test the code much. BTW, I found an unrelated bug at
vm_string.cpp. So, I'm not very confident this code is rock solid.