Theory RegisterMachineSpecification

section ‹Register Machines›

subsection ‹Register Machine Specification›
theory RegisterMachineSpecification
  imports Main
begin

subsubsection ‹Basic Datatype Definitions›

text ‹The following specification of register machines is inspired by cite"mech_turing" (see 
      cite"mech_turing_afp" for the corresponding AFP article).›

(* Type synonyms for registers (= register indices) the "tape" (sim. to a
 * Turing machine) that contains a list of register values.
 *)
type_synonym register = nat
type_synonym tape = "register list"

(* The register machine understands "instructions" that operate on state(-id)s
 * and modify register(-id)s. The machine stops at the HALT instruction.
 *)
type_synonym state = nat
datatype instruction =
  isadd: Add (modifies : register) (goes_to : state) |
  issub: Sub (modifies : register) (goes_to : state) (goes_to_alt : state) |
  ishalt: Halt
where
  "modifies Halt = 0" |
  "goes_to_alt (Add _ next) = next"

(* A program, then, just becomes a list of these instructions *)
type_synonym program = "instruction list"

(* A configuration of the (runtime of) a machine encodes information about the
 * instruction and the state of the registers (i.e., the tape). We describe it
 * here as a tuple.
 *)
type_synonym configuration = "(state * tape)"

subsubsection ‹Essential Functions to operate the Register Machine›

(* Given a tape of register values and some instruction(s) the register
 * machine first reads the value of the register from the tape (by convention
 * assume that the value "read" by the HALT state is zero). The machine then,
 * fetches the next instruction from the program, and finally updates the
 * tape to reflect changes by the last instruction.
 *)

definition read :: "tape  program  state  nat"
  where "read t p s = t ! (modifies (p!s))"

definition fetch :: "state  program  nat  state" where
  "fetch s p v = (if issub (p!s)  v = 0 then goes_to_alt (p!s)
                       else if ishalt (p!s) then s
                       else goes_to (p!s))"

definition update :: "tape  instruction  tape" where
  "update t i = (if ishalt i then t
                    else if isadd i then list_update t (modifies i) (t!(modifies i) + 1)
                    else list_update t (modifies i) (if t!(modifies i) = 0 then 0 else (t!(modifies i)) - 1) )"

definition step :: "configuration  program  configuration"
  where
    "(step ic p) = (let nexts = fetch (fst ic) p (read (snd ic) p (fst ic));
                        nextt = update (snd ic) (p!(fst ic))
                        in (nexts, nextt))"

fun steps :: "configuration  program  nat  configuration"
  where
    steps_zero: "(steps c p 0) = c"
  | steps_suc:  "(steps c p (Suc n)) = (step (steps c p n) p)"


subsubsection ‹Validity Checks and Assumptions›

(* check bound for each type of instruction *)
(* take a m representing the upper bound for state number *)
fun instruction_state_check :: "nat  instruction  bool"
  where isc_halt: "instruction_state_check _ Halt = True"
  |     isc_add: "instruction_state_check m (Add _ ns) = (ns < m)"
  |     isc_sub: "instruction_state_check m (Sub _ ns1 ns2) = ((ns1 < m) & (ns2 < m))"

fun instruction_register_check :: "nat  instruction  bool"
  where "instruction_register_check _ Halt = True"
  |     "instruction_register_check n (Add reg _) = (reg < n)"
  |     "instruction_register_check n (Sub reg _ _) = (reg < n)"

(* passes function via currying into list_all *)
fun program_state_check :: "program  bool"
  where "program_state_check p = list_all (instruction_state_check (length p)) p"

fun program_register_check :: "program  nat  bool"
  where "program_register_check p n = list_all (instruction_register_check n) p"

fun tape_check_initial :: "tape  nat  bool"
  where "tape_check_initial t a = (t  []  t!0 = a  (l>0. t ! l = 0))"

fun program_includes_halt :: "program  bool"
  where "program_includes_halt p = (length p > 1  ishalt (p ! (length p -1))  (k<length p-1. ¬ ishalt (p!k)))"

text ‹Is Valid and Terminates›

definition is_valid
  where "is_valid c p = (program_includes_halt p  program_state_check p
                             (program_register_check p (length (snd c))))"

definition is_valid_initial
  where "is_valid_initial c p a = ((is_valid c p)
                                 (tape_check_initial (snd c) a)
                                 (fst c = 0))"

definition correct_halt
  where "correct_halt c p q = (ishalt (p ! (fst (steps c p q)))  ― ‹halting›
                             (l<(length (snd c)). snd (steps c p q) ! l = 0))"

definition terminates :: "configuration  program  nat  bool"
  where "terminates c p q = ((q>0)
                           (correct_halt c p q)
                           (x<q. ¬ ishalt (p ! (fst (steps c p x)))))"

definition initial_config :: "nat  nat  configuration" where
  "initial_config n a = (0, (a # replicate n 0))"

end