@kha I have added support for opaque constants to the old C++ frontend,
and made sure the new frontend can still parse `library/init/core.lean`.
The kernel should enforce that opaque constants are really opaque, and
the following example should fail
```
constant x : nat := 0
theorem foo : x = 0 := rfl
```
If it doesn't, it is a bug.
Here are some remaining issues:
1- `environment.mk_empty` is currently an axiom because we cannot create
an inhabitant of an opaque type. A possible solution is to use
`option environment` instead of `environment`.
2- There is no support for opaque constants in the new
frontend. However, I modified it to handle axioms, and fixed the literal
values with decl_cmd_kind. I tried to mark some of my changes with
comments, but it is probably much easier for you to just check the
commit change list.
3- I did not add any support for automatically constructing `e`
at `constant x : t := e`. I think we can do this later
after we replace the old frontend with the new one. BTW, it took only a
few minutes to provide the inhabitants manually.
Remark: `vm_timeit` was for the Lean 3 `timeit` primitive which is
different from the Lean 4 one. It has a different arity, and was
producing an assertion violation at emit_bytecode.cpp
@kha I found yet another bug in the specializer code :(
The bug is related to the previous bug fix where we try avoid
duplication of work by lambda abstracting let-variables.
We knew this could introduce type errors, but I thought it would only
happen in very complicated programs that make a heavy use of dependent
types. Actually, this is not the case. I just found an instance when
I was playing with the new parser.
`fix.lean` and `fix_1.lean` are very similar, but fix.lean is almost
twice as fast. Reason: `fix.lean` uses `fix_2` instead of `fix_1` and
avoid the creation of many closures. Here are runtime numbers on my
machine.
```
time ./fix_1.lean.out 23
352321527
real 0m0.729s
user 0m0.724s
sys 0m0.000s
```
```
~/projects/lean4/tests/playground (master +)$ time ./fix.lean.out 23
352321527
real 0m0.396s
user 0m0.388s
sys 0m0.004s
```
TODO: modify the compiler to replace `fix_core_n f a_1 ... a_m`
with `fix_core_m f a_1 ... a_m` whenever `n < m`.
This feature is quite useful for writing reusable/generic code. For
example, we cannot write an efficient `rec_t` without it because we
don't know the arity of `m A` when we write `rec_t`.