I'm trying to define a simple stack-based language in Coq. For now, the instruction set contains push
which pushes a nat
, and an instruction pop
which pops one. The idea is that programs are dependently typed; Prog 2
is a program which leaves two elements on the stack after execution.
This is implemented by this simple program:
Require Import Coq.Vectors.VectorDef.
Inductive Prog : nat -> Type :=
| push : forall n : nat, nat -> Prog n -> Prog (S n)
| pop : forall n : nat, Prog (S n) -> Prog n.
Fixpoint eval (n : nat) (p : Prog n) : t nat n :=
match p with
| push _ n p => cons _ n _ (eval _ p)
| pop _ p => match eval _ p with
| cons _ _ _ stack => stack
end
end.
I now want to add an instruction pop'
which pops an element of the stack but can only be applied when there are at least two elements on the stack.
Inductive Prog : nat -> Type :=
| push : forall n : nat, nat -> Prog n -> Prog (S n)
| pop' : forall n : nat, Prog (S (S n)) -> Prog (S n).
When using the same Fixpoint
as above (changing pop
to pop'
) I get the error
The term "stack" has type "t nat n0" while it is expected to have type "t nat (S k)".
So I thought I could do this with Program
. So I use:
Require Import Coq.Program.Tactics Coq.Logic.JMeq.
Program Fixpoint eval (n : nat) (p : Prog n) : t nat n :=
match p with
| push _ n p => cons _ n _ (eval _ p)
| pop' k p => match eval _ p with
| cons _ l _ stack => stack
| nil _ => _
end
end.
However, for some reason this generates weird obligations, which I don't think can be solved. The first (of two) obligations left after automatic attempts is:
k : nat
p0 : Prog (S k)
p : Prog (S (S k))
Heq_p : JMeq (pop' k p) p0
l, n0 : nat
stack : t nat n0
h : nat
t : t nat n0
Heq_anonymous0 : JMeq (cons nat l n0 stack) (cons nat h n0 t)
______________________________________(1/1)
n0 = S k
I don't see a way to link the k
, which is the type argument for Prog
, and the n0
, which is the type argument for the vector type t
.
Why does this Program
yield this weird obligation, and how can I write the evaluation function circumventing this issue?