(*---------------------------------------------------------------------------*
 * A HOL exploration of the Boyer-Moore small machine.                       *
 *---------------------------------------------------------------------------*)
app load ["bossLib"];

open bossLib; infix 8 by; infix &&;
open Num_conv;

Hol_datatype `state = MS of 'a # num       =>  (* pc *)
                            ('a # num)list =>  (* stk *)
                            'b list        =>  (* mem *)
                            bool           =>  (* halt *)
                            'c list            (* code *)`;

(*---------------------------------------------------------------------------*
 * Get the nth element from a list. Ignore error cases.                      *
 *---------------------------------------------------------------------------*)
Define `(nth 0 (CONS h t) = h) 
    /\  (nth (SUC n) (CONS h t) = nth n t)`;

val (nth_def, nth_induct) = (CONJUNCT1 it, CONJUNCT2 it);

(*---------------------------------------------------------------------------*
 * A totalized function for updating a list.                                 *
 *---------------------------------------------------------------------------*)
Define `(put 0 v [] = [v])
    /\  (put 0 v (CONS h t) = CONS v t)
    /\  (put (SUC n) v [] = CONS v (put n v []))
    /\  (put (SUC n) v (CONS h t) = CONS h (put n v t))`;

val (put_def, put_induct) = (CONJUNCT1 it, CONJUNCT2 it);

(*test*)REWRITE_CONV [put_def] (Term`put (SUC(SUC 0)) 77 [0;1;2;3;4]`);

(*---------------------------------------------------------------------------*
 * Getting something from an lookup list. (Fails to auto-define.)            *
 *---------------------------------------------------------------------------*)
Define `(assoc x (CONS (x1,y) rst) = (x=x1 => y | assoc x rst))`;


(*---------------------------------------------------------------------------*
 * Increment the program counter.                                            *
 *---------------------------------------------------------------------------*)

Define `inc (x,n) = (x, SUC n)`;

(*---------------------------------------------------------------------------*
 * Fetch the next instruction.                                               *
 *---------------------------------------------------------------------------*)
Define `fetch (x,n) code = nth n (assoc x code)`;

(*---------------------------------------------------------------------------*
 * The current instruction.                                                  *
 *---------------------------------------------------------------------------*)
Define `instr (MS p s m h c) = fetch p c`;

(*---------------------------------------------------------------------------*
 * Instructions.                                                             *
 *---------------------------------------------------------------------------*)

time 
Hol_datatype `instruction = Move  of num => num
                          | Movi  of num => num
                          | Add   of num => num
                          | Subi  of num => num
                          | Jump  of num
                          | Jumpz of num => num 
                          | Call  of num
                          | Ret`;

(* Won't define..... bugger! *)
Define 
`(EV(Move x y) (MS p s m h c) = MS(inc p) s (put x (nth y m) m) h c)          /\
 (EV(Movi x y) (MS p s m h c) = MS(inc p) s (put x y m) h c)                  /\
 (EV(Add  x y) (MS p s m h c) = MS(inc p) s (put x (nth x m+nth y m) m) h c)  /\
 (EV(Subi x y) (MS p s m h c) = MS(inc p) s (put x (nth x m - y) m) h c)      /\
 (EV(Jump x)   (MS (k,l) s m h c)  = MS (k,x) s m h c)                        /\
 (EV(Jumpz x y)(MS (k,l) s m h c) = MS(nth x m = 0 => (k,y) | inc p) s m h c) /\
 (EV(Call x) (MS p s m h c)        = MS (x,0) (CONS (inc p) s) m h c)         /\
 (EV Ret  (MS p [] m h c)          = MS p [] m T c)                           /\
 (EV Ret (MS p (CONS f r) m h c)   = MS f r m h c)`;

