@ -676,7 +711,7 @@ That is, `(jmp, t0)` is a valid instruction at `pc`. Then, using

Coq's `inversion` tactic, we ask: how is this possible? There is

only one inference rule that gives us such a conclusion, and it is named `valid_inst_jmp`

in our Coq code. Since we have a proof that our `jmp` is valid,

it must mean that this rule was used. Furthermore, sicne this

it must mean that this rule was used. Furthermore, since this

rule requires that `valid_jump_t` evaluates to `Some f'`, we know

that this must be the case here! Coq now has adds the following

two lines to our proof state:

@ -820,7 +855,7 @@ are fairly trivial:

{{<codelines"Coq""aoc-2020/day8.v"237240>}}

We basically connect the dots between the premises (in a form like `done`)

and the corresponding inference rule (`run_noswap_done`). The more

and the corresponding inference rule (`run_noswap_ok`). The more

interesting case is when we can take a step.

{{<codelines"Coq""aoc-2020/day8.v"241253>}}

@ -864,10 +899,43 @@ this proof will __return to us the final program counter and accumulator!__

This is precisely what we'd need to solve part 1.

But wait, almost? What's missing? We're missing a few implementation details:

* We've not provided a concrete impelmentation of integers.

* We've not provided a concrete impelmentation of integers. The simplest

thing to do here would be to use [`Coq.ZArith.BinInt`](https://coq.inria.fr/library/Coq.ZArith.BinInt.html),

for which there is a module [`Z_as_Int`](https://coq.inria.fr/library/Coq.ZArith.Int.html#Z_as_Int)

that provides `t` and friends.

* We assumed (reasonably, I would say) that it's possible to convert a natural

number to an integer.

number to an integer. If we're using the aforementioned `BinInt` module,

we can use [`Z.of_nat`](https://coq.inria.fr/library/Coq.ZArith.BinIntDef.html#Z.of_nat).

* We also assumed (still reasonably) that we can try convert an integer

back to a finite natural number, failing if it's too small or too large.

{{<todo>}}Finish up{{</todo>}}

There's no built-in function for this, but `Z`, for one, distinguishes

between the "positive", "zero", and "negative" cases, and we have

`Pos.to_nat` for the positive case.

Well, I seem to have covered all the implementation details. Why not just

go ahead and solve the problem? I tried, and ran into two issues:

* Although this is "given", we assumed that our input program will be

valid. For us to use the result of our Coq proof, we need to provide it

a constructive proof that our program is valid. Creating this proof is tedious

in theory, and quite difficult in practice: I've run into a

strange issue trying to pattern match on finite naturals.

* Even supposing we _do_ have a proof of validity, I'm not certain

if it's possible to actually extract an answer from it. It seems

that Coq distinguishes between proofs (things of type `Prop`) and

values (things of type `Set`). things of types `Prop` are supposed

to be _erased_. This means that when you convert Coq code,

to, say, Haskell, you will see no trace of any `Prop`s in that generated

code. Unfortunately, this also means we

[can't use our proofs to construct values](https://stackoverflow.com/questions/27322979/why-coq-doesnt-allow-inversion-destruct-etc-when-the-goal-is-a-type),

even though our proof objects do indeed contain them.

So, we "theoretically" have a solution to part 1, down to the algorithm

used to compute it and a proof that our algorithm works. In "reality", though, we

can't actually use this solution to procure an answer. Like we did with day 1, we'll have

to settle for only a proof.

Let's wrap up for this post. It would be more interesting to devise and

formally verify an algorithm for part 2, but this post has already gotten

quite long and contains a lot of information. Perhaps I will revisit this