Hi. I got a set of instructions to be used to run a VM function. Like this:

```
| i | instr |
|---+--------------+
| 0 | Const true; |
| 1 | Const false; |
| 2 | Goto 4; |
| 3 | Const true; |
| 4 | Goto 1 |
```

Where `Goto k`

signifies a jump to instruction at index `k`

.

I wrote this up as:

```
Inductive instr :=
| Const: bool -> instr
| Goto: nat -> instr.
Definition prog := list instr.
```

I wanted to get something like an epsilon-closure of an individual instruction. ie, the indices of non-Goto instructions that are reachable from a given instruction in a `prog`

.

So I naïvely tried

```
Fixpoint eclosure_aux (p:prog) (i:nat) (visited:list nat): list nat :=
let inds := seq 0 (length p) in
let aug := list_prod inds p in
match List.nth i aug (0, Goto 0) with
| (i,x) =>
match x with
| Const _ => [i]
| Goto k =>
if List.existsb (fun a => Nat.eqb a k) visited then [i]
else i :: (eclosure_aux p k (i::visited))
end
end.
Definition eclosure (p:prog) (i:nat): list nat := eclosure_aux p i [].
(*
Cannot guess decreasing argument of fix.
*)
```

I was hoping to get something like:

```
Example p1 := [
Const true; (* 0 *)
Const false; (* 1 *)
Goto 4; (* 2 *)
Const true; (* 3 *)
Goto 1 (* 4 *)
].
Compute eclosure p1 2 [].
(* [2; 4; 1] *)
```

The function `eclosure_aux`

can be made to terminate because of the `visited`

argument which can be used to avoid infinite loops.

But how can we convince the type checker?

Is there a way?

Complete example:

```
Require Import List.
Import ListNotations.
Inductive instr :=
| Const: bool -> instr
| Goto: nat -> instr.
Definition prog := list instr.
Example p1 := [
Const true; (* 0 *)
Const false; (* 1 *)
Goto 4; (* 2 *)
Const true; (* 3 *)
Goto 1 (* 4 *)
].
Fail Fixpoint eclosure_aux (p:prog) (i:nat) (visited:list nat): list nat :=
let inds := seq 0 (length p) in
let aug := list_prod inds p in
match List.nth i aug (0, Goto 0) with
| (i,x) =>
match x with
| Const _ => [i]
| Goto k =>
if List.existsb (fun a => Nat.eqb a k) visited then [i]
else i :: (eclosure_aux p k (i::visited))
end
end.
Fail Definition eclosure (p:prog) (i:nat): list nat := eclosure_aux p i [].
```

We can't just add a `fuel`

parameter, right? Since we can't tell in advance how long a goto-goto-goto-... chain would be (or could such info be baked into the type?)

a chain is at most `length p`

long so fuel should work AFAICT

Last updated: Oct 04 2023 at 19:01 UTC