------------------------------------------------------------------------
-- A virtual machine for the language
------------------------------------------------------------------------

-- To avoid having to deal with labels/jumps this virtual machine is
-- non-standard in several ways:
--
-- • Instructions can contain instruction sequences.
-- • Instructions can contain uncompiled expressions.
-- • The virtual machine invokes the compiler.

module VirtualMachine where

open import Syntax
open import Infinite

open import Data.List
open import Data.Nat
open import Data.Star
open import Data.Product
open import Relation.Unary hiding (U)

------------------------------------------------------------------------
-- Virtual machine

mutual

  -- A virtual machine code snippet is a list of instructions.

  data Inst : Set where
    push   : (n : )  Inst
    throw  : Inst
    loop   : (x : Expr partial)  Inst
    add    : Inst
    pop    : Inst
    mark   : (ops : Code)  Inst
    unmark : Inst
    set    : (i : Status)  Inst
    reset  : Inst

  Code : Set
  Code = List Inst

-- The virtual machine operates on a stack of items.

data Item : Set where
  nat : (n : )  Item
  han : (ops : Code)  Item
  int : (i : Status)  Item

Stack : Set
Stack = List Item

-- The virtual machine's transition relation.

data State : Set where
  ⟨_,_,_⟩ : (ops : Code) (i : Status) (s : Stack)  State
  ⟪_,_⟫   :              (i : Status) (s : Stack)  State

mutual

  data _⟶_ : State  State  Set where
    push      :  {n ops i s}      push n     ops , i , s                    ops , i  , nat n  s 
    add       :  {ops i m n s}    add        ops , i , nat n  nat m  s    ops , i  , nat (m + n)  s 
    pop       :  {ops i n s}      pop        ops , i , nat n  s            ops , i  , s 
    mark      :  {ops' ops i s}   mark ops'  ops , i , s                    ops , i  , han ops'  s 
    unmark    :  {ops i x c s}    unmark     ops , i , x  han c  s        ops , i  , x  s 
    set       :  {i' ops i s}     set i'     ops , i , s                    ops , i' , int i  s 
    reset     :  {ops i x i' s}   reset      ops , i , x  int i'  s       ops , i' , x  s 
    loop      :  {x ops i s}      loop x     ops , i , s                    comp x (pop  loop x  ops) , i , s 
    throw     :  {ops i s}        throw      ops , i , s                    i , s 

    interrupt :  {op ops s}       op         ops , U , s                    U , s 

    nat       :  {i n s}          i , nat n    s                            i  , s 
    int       :  {i i' s}         i , int i'   s                            i' , s 
    han       :  {i ops s}        i , han ops  s                            ops , B , int i  s 

  -- Compiler from the high-level language to the virtual machine
  -- language.

  comp :  {t}  Expr t  Code  Code
  comp  nat n    ops = push n  ops
  comp  throw    ops = throw  ops
  comp (loop x)    ops = loop x  ops
  comp (x  y)     ops = comp x (comp y (add  ops))
  comp (x >> y)    ops = comp x (pop  comp y ops)
  comp (x catch y) ops = mark (comp y (reset  ops))  comp x (unmark  ops)
  comp (block x)   ops = set B  comp x (reset  ops)
  comp (unblock x) ops = set U  comp x (reset  ops)

infix 4 _⟶⋆_

-- Reflexive transitive closure.

_⟶⋆_ : State  State  Set
_⟶⋆_ = Star _⟶_

-- "Infinite closure".

_⟶∞ : State  Set
_⟶∞ = Infinite _⟶_

-- Starting states for the virtual machine.

start :  {t}  Expr t  Status  State
start e i =  comp e [] , i , [] 

-- Final states.

_↛ : State  Set
s₁  =  λ s₂  s₁  s₂