SilverSight/coq/AVMIsa/avm.v
allaun 069e54d8e9 fix(coq): migrate all files to Rocq 9.0 imports (ZCompat, no ZArith)
All 5 Coq files now use:
  From Corelib Require Import BinNums PosDef NatDef IntDef.
  Require Import SilverSight.coq.ZCompat.

instead of Require Import ZArith Lia.

Build: 5 Coq files, 0 errors
2026-07-01 23:21:29 -05:00

148 lines
5.1 KiB
Coq

(* AVM ISA v1 — Coq Formalization (Rocq 9.0) *)
From Corelib Require Import BinNums PosDef NatDef IntDef Init.Datatypes.
Require Import SilverSight.coq.ZCompat.
Local Open Scope Z_scope.
Module AVM.
Fixpoint pow2_positive (n : nat) : positive :=
match n with O => xH | S m => xO (pow2_positive m) end.
Definition q16_scale : Z := Zpos (pow2_positive 16).
Inductive AvmTy : Set := Q0_16 | Q16_16 | Bool.
Inductive AvmVal : Set := Vq0 (x : Z) | Vq16 (x : Z) | Vbool (b : bool).
Inductive Prim : Set :=
AddQ16 | SubQ16 | MulQ16 | DivQ16 | LtQ16 | EqQ16 | And | Or | Not.
Inductive Instr : Set :=
Push_q16 (x : Z) | Push_bool (b : bool) | Pop | Dup | Swap
| Load (i : nat) | Store (i : nat) | Jump (t : nat) | Jump_if (t : nat)
| Prim_op (p : Prim) | Halt.
Record State : Set := mkState {
pc : nat; stack : list AvmVal; locals : list (option AvmVal); halted : bool
}.
Definition empty_state : State := mkState O nil nil false.
Definition q16_mul (a b : Z) : Z := Z.div (Z.mul a b) q16_scale.
Definition q16_div (a b : Z) : Z :=
if Z.eqb b Z0 then q16_scale else Z.div (Z.mul a q16_scale) b.
Infix "::" := cons (at level 60, right associativity).
Infix "++" := app (at level 60, right associativity).
Fixpoint nth_error {A} (l : list A) (n : nat) : option A :=
match l with
| nil => None
| x :: xs => match n with O => Some x | S n' => nth_error xs n' end
end.
Definition get_local (s : State) (i : nat) : option AvmVal :=
match nth_error s.(locals) i with
| Some (Some v) => Some v | _ => None
end.
Definition exec_prim (p : Prim) (a b : option AvmVal) : option AvmVal :=
match p, a, b with
| AddQ16, Some (Vq16 x), Some (Vq16 y) => Some (Vq16 (Z.add x y))
| SubQ16, Some (Vq16 x), Some (Vq16 y) => Some (Vq16 (Z.sub x y))
| MulQ16, Some (Vq16 x), Some (Vq16 y) => Some (Vq16 (q16_mul x y))
| DivQ16, Some (Vq16 x), Some (Vq16 y) => Some (Vq16 (q16_div x y))
| LtQ16, Some (Vq16 x), Some (Vq16 y) => Some (Vbool (Z.ltb x y))
| EqQ16, Some (Vq16 x), Some (Vq16 y) => Some (Vbool (Z.eqb x y))
| And, Some (Vbool x), Some (Vbool y) => Some (Vbool (x && y))
| Or, Some (Vbool x), Some (Vbool y) => Some (Vbool (x || y))
| Not, Some (Vbool x), None => Some (Vbool (negb x))
| _, _, _ => None
end.
Fixpoint firstn {A} (n : nat) (l : list A) : list A :=
match n with O => nil | S m => match l with nil => nil | x :: xs => x :: firstn m xs end end.
Fixpoint skipn {A} (n : nat) (l : list A) : list A :=
match n with O => l | S m => match l with nil => nil | _ :: xs => skipn m xs end end.
Definition step (s : State) (prog : list Instr) : option State :=
if s.(halted) then None else
match nth_error prog s.(pc) with
| None => Some (mkState s.(pc) s.(stack) s.(locals) true)
| Some instr =>
let new_pc := S s.(pc) in
let push v := Some (mkState new_pc (v :: s.(stack)) s.(locals) false) in
match instr with
| Push_q16 x => push (Vq16 x)
| Push_bool x => push (Vbool x)
| Pop =>
match s.(stack) with
| _ :: rest => Some (mkState new_pc rest s.(locals) false)
| nil => None
end
| Dup =>
match s.(stack) with
| v :: _ => push v | nil => None
end
| Swap =>
match s.(stack) with
| a :: b :: rest => Some (mkState new_pc (b :: a :: rest) s.(locals) false)
| _ => None
end
| Load i =>
match get_local s i with
| Some v => push v | None => None
end
| Store i =>
match s.(stack) with
| v :: rest =>
Some (mkState new_pc rest
(firstn i s.(locals) ++ Some v :: skipn (S i) s.(locals)) false)
| nil => None
end
| Jump t => Some (mkState t s.(stack) s.(locals) false)
| Jump_if t =>
match s.(stack) with
| Vbool true :: rest => Some (mkState t rest s.(locals) false)
| Vbool false :: rest => Some (mkState new_pc rest s.(locals) false)
| _ :: _ => None | nil => None
end
| Prim_op p =>
(match p with
| Not =>
match s.(stack) with
| a :: rest =>
match exec_prim p (Some a) None with
| Some v => Some (mkState new_pc (v :: rest) s.(locals) false)
| None => None
end
| nil => None
end
| _ =>
match s.(stack) with
| a :: b :: rest =>
match exec_prim p (Some a) (Some b) with
| Some v => Some (mkState new_pc (v :: rest) s.(locals) false)
| None => None
end
| _ => None
end
end)
| Halt => Some (mkState s.(pc) s.(stack) s.(locals) true)
end
end.
Fixpoint run (s : State) (prog : list Instr) (fuel : nat) {struct fuel} : option State :=
match fuel with
| O => Some s
| S k =>
if s.(halted) then Some s else
match step s prog with
| None => None | Some s' => run s' prog k
end
end.
Lemma step_halted (s : State) (prog : list Instr) (h : s.(halted) = true) :
step s prog = None.
Proof. unfold step; rewrite h; reflexivity. Qed.
End AVM.