module Lambda.VirtualMachine where
open import Coinduction
open import Data.Fin
open import Data.Function
open import Data.List
open import Data.Nat
open import Data.Star
open import Data.Star.Properties
open import Data.Vec using (Vec; []; _∷_; lookup)
open import Relation.Binary.PropositionalEquality
open import Lambda.Closure as C hiding (Env; Value)
open import Lambda.Syntax hiding (Value)
mutual
data Instr (n : ℕ) : Set where
Var : (x : Fin n) → Instr n
Con : (i : ℕ) → Instr n
Clos : (c : Code (suc n)) → Instr n
App : Instr n
Ret : Instr n
Code : ℕ → Set
Code n = List (Instr n)
open Closure Code public
data StackElement : Set where
val : (v : Value) → StackElement
ret : ∀ {n} (c : Code n) (ρ : Env n) → StackElement
Stack : Set
Stack = List StackElement
data State : Set where
⟨_,_,_⟩ : ∀ {n} (c : Code n) (s : Stack) (ρ : Env n) → State
infix 4 _⟶_
data _⟶_ : State → State → Set where
Var : ∀ {n} {x : Fin n} {c s ρ} →
⟨ Var x ∷ c , s , ρ ⟩ ⟶ ⟨ c , val (lookup x ρ) ∷ s , ρ ⟩
Con : ∀ {n i} {c : Code n} {s ρ} →
⟨ Con i ∷ c , s , ρ ⟩ ⟶ ⟨ c , val (con i) ∷ s , ρ ⟩
Clos : ∀ {n} {c : Code n} {c′ s ρ} →
⟨ Clos c′ ∷ c , s , ρ ⟩ ⟶ ⟨ c , val (ƛ c′ ρ) ∷ s , ρ ⟩
App : ∀ {n} {c : Code n} {v n′} {c′ : Code (suc n′)} {ρ′ s ρ} →
⟨ App ∷ c , val v ∷ val (ƛ c′ ρ′) ∷ s , ρ ⟩ ⟶ ⟨ c′ , ret c ρ ∷ s , v ∷ ρ′ ⟩
Ret : ∀ {n} {c : Code n} {v n′} {c′ : Code n′} {ρ′ s ρ} →
⟨ Ret ∷ c , val v ∷ ret c′ ρ′ ∷ s , ρ ⟩ ⟶ ⟨ c′ , val v ∷ s , ρ′ ⟩
infix 4 _⟶⋆_
_⟶⋆_ : State → State → Set
_⟶⋆_ = Star _⟶_
open StarReasoning _⟶_ public
infixr 5 _◅_
infix 4 _⟶∞ _⟶∞′
data _⟶∞ : State → Set where
_◅_ : ∀ {s₁ s₂} (s₁⟶s₂ : s₁ ⟶ s₂) (s₂⟶∞ : ∞ (s₂ ⟶∞)) → s₁ ⟶∞
infixr 2 _⟶⟨_⟩′_ _⟶⋆⟨_⟩′_
infix 2 _⟶∞⟨_⟩
data _⟶∞′ : State → Set where
_⟶⟨_⟩′_ : ∀ s₁ {s₂} (s₁⟶s₂ : s₁ ⟶ s₂) (s₂⟶∞ : ∞ (s₂ ⟶∞′)) → s₁ ⟶∞′
_⟶⋆⟨_⟩′_ : ∀ s₁ {s₂} (s₁⟶⋆s₂ : s₁ ⟶⋆ s₂) (s₂⟶∞ : s₂ ⟶∞′) → s₁ ⟶∞′
_⟶∞⟨_⟩ : ∀ s (s⟶∞ : s ⟶∞′) → s ⟶∞′
∞′→∞ : ∀ {s} → s ⟶∞′ → s ⟶∞
∞′→∞ (s₁ ⟶⟨ s₁⟶s₂ ⟩′ s₂⟶∞) = s₁⟶s₂ ◅ ♯ (∞′→∞ (♭ s₂⟶∞))
∞′→∞ (s ⟶⋆⟨ ε ⟩′ s⟶∞) = ∞′→∞ s⟶∞
∞′→∞ (s₁ ⟶⋆⟨ s₁⟶s₂ ◅ s₂⟶⋆s₃ ⟩′ s₃⟶∞) = s₁⟶s₂ ◅ ♯ (∞′→∞ (_ ⟶⋆⟨ s₂⟶⋆s₃ ⟩′ s₃⟶∞))
∞′→∞ (s ⟶∞⟨ s⟶∞ ⟩) = ∞′→∞ s⟶∞
⟦_⟧ : ∀ {n} → Tm n → Code n → Code n
⟦ con i ⟧ c = Con i ∷ c
⟦ var x ⟧ c = Var x ∷ c
⟦ ƛ t ⟧ c = Clos (⟦ t ⟧ [ Ret ]) ∷ c
⟦ t₁ · t₂ ⟧ c = ⟦ t₁ ⟧ (⟦ t₂ ⟧ (App ∷ c))
mutual
⟦_⟧ρ : ∀ {n} → C.Env n → Env n
⟦ [] ⟧ρ = []
⟦ v ∷ ρ ⟧ρ = ⟦ v ⟧v ∷ ⟦ ρ ⟧ρ
⟦_⟧v : C.Value → Value
⟦ con i ⟧v = con i
⟦ ƛ t ρ ⟧v = ƛ (⟦ t ⟧ [ Ret ]) ⟦ ρ ⟧ρ
lookup-hom : ∀ {n} (x : Fin n) ρ → lookup x ⟦ ρ ⟧ρ ≡ ⟦ lookup x ρ ⟧v
lookup-hom zero (v ∷ ρ) = refl
lookup-hom (suc x) (v ∷ ρ) = lookup-hom x ρ
correct⇓′ : ∀ {n} {ρ : C.Env n} {c s v t} →
ρ ⊢ t ⇒ val v →
⟨ ⟦ t ⟧ c , s , ⟦ ρ ⟧ρ ⟩ ⟶⋆ ⟨ c , val ⟦ v ⟧v ∷ s , ⟦ ρ ⟧ρ ⟩
correct⇓′ {ρ = ρ} {c} {s} (var {x}) = begin
⟨ Var x ∷ c , s , ⟦ ρ ⟧ρ ⟩ ⟶⟨ Var ⟩
⟨ c , val (lookup x ⟦ ρ ⟧ρ) ∷ s , ⟦ ρ ⟧ρ ⟩ ≡⟨ cong (λ v → ⟨ c , val v ∷ s , ⟦ ρ ⟧ρ ⟩)
(lookup-hom x ρ) ⟩
⟨ c , val ⟦ lookup x ρ ⟧v ∷ s , ⟦ ρ ⟧ρ ⟩ ∎
correct⇓′ {ρ = ρ} {c} {s} (con {i}) = begin
⟨ Con i ∷ c , s , ⟦ ρ ⟧ρ ⟩ ⟶⟨ Con ⟩
⟨ c , val (con i) ∷ s , ⟦ ρ ⟧ρ ⟩ ∎
correct⇓′ {ρ = ρ} {c} {s} (ƛ {t}) = begin
⟨ Clos (⟦ t ⟧ [ Ret ]) ∷ c , s , ⟦ ρ ⟧ρ ⟩ ⟶⟨ Clos ⟩
⟨ c , val ⟦ ƛ t ρ ⟧v ∷ s , ⟦ ρ ⟧ρ ⟩ ∎
correct⇓′ {ρ = ρ} {c} {s} {v′} (app {t₁} {t₂} {t = t} {ρ′} {v} t₁⇓ t₂⇓ t₁t₂⇓) = begin
⟨ ⟦ t₁ ⟧ (⟦ t₂ ⟧ (App ∷ c)) , s , ⟦ ρ ⟧ρ ⟩ ⟶⋆⟨ correct⇓′ t₁⇓ ⟩
⟨ ⟦ t₂ ⟧ (App ∷ c) , val ⟦ ƛ t ρ′ ⟧v ∷ s , ⟦ ρ ⟧ρ ⟩ ⟶⋆⟨ correct⇓′ t₂⇓ ⟩
⟨ App ∷ c , val ⟦ v ⟧v ∷ val ⟦ ƛ t ρ′ ⟧v ∷ s , ⟦ ρ ⟧ρ ⟩ ⟶⟨ App ⟩
⟨ ⟦ t ⟧ [ Ret ] , ret c ⟦ ρ ⟧ρ ∷ s , ⟦ v ⟧v ∷ ⟦ ρ′ ⟧ρ ⟩ ⟶⋆⟨ correct⇓′ t₁t₂⇓ ⟩
⟨ [ Ret ] , val ⟦ v′ ⟧v ∷ ret c ⟦ ρ ⟧ρ ∷ s , ⟦ v ⟧v ∷ ⟦ ρ′ ⟧ρ ⟩ ⟶⟨ Ret ⟩
⟨ c , val ⟦ v′ ⟧v ∷ s , ⟦ ρ ⟧ρ ⟩ ∎
correct⇑′ : ∀ {n} {ρ : C.Env n} {c s t} →
ρ ⊢ t ⇒ ⊥ → ⟨ ⟦ t ⟧ c , s , ⟦ ρ ⟧ρ ⟩ ⟶∞′
correct⇑′ {ρ = ρ} {c} {s} (app {t₁} {t₂} {t = t} {ρ′} {v} t₁⇓ t₂⇓ t₁t₂⇑) =
⟨ ⟦ t₁ ⟧ (⟦ t₂ ⟧ (App ∷ c)) , s , ⟦ ρ ⟧ρ ⟩ ⟶⋆⟨ correct⇓′ t₁⇓ ⟩′
⟨ ⟦ t₂ ⟧ (App ∷ c) , val ⟦ ƛ t ρ′ ⟧v ∷ s , ⟦ ρ ⟧ρ ⟩ ⟶⋆⟨ correct⇓′ t₂⇓ ⟩′
⟨ App ∷ c , val ⟦ v ⟧v ∷ val ⟦ ƛ t ρ′ ⟧v ∷ s , ⟦ ρ ⟧ρ ⟩ ⟶⟨ App ⟩′ ♯
(⟨ ⟦ t ⟧ [ Ret ] , ret c ⟦ ρ ⟧ρ ∷ s , ⟦ v ⟧v ∷ ⟦ ρ′ ⟧ρ ⟩ ⟶∞⟨ correct⇑′ (♭ t₁t₂⇑) ⟩)
correct⇑′ {ρ = ρ} {c} {s} (·ˡ {t₁} {t₂} t₁⇑) =
⟨ ⟦ t₁ ⟧ (⟦ t₂ ⟧ (App ∷ c)) , s , ⟦ ρ ⟧ρ ⟩ ⟶∞⟨ correct⇑′ (♭ t₁⇑) ⟩
correct⇑′ {ρ = ρ} {c} {s} (·ʳ {t₁} {t₂} {v} t₁⇓ t₂⇑) =
⟨ ⟦ t₁ ⟧ (⟦ t₂ ⟧ (App ∷ c)) , s , ⟦ ρ ⟧ρ ⟩ ⟶⋆⟨ correct⇓′ t₁⇓ ⟩′
⟨ ⟦ t₂ ⟧ (App ∷ c) , val ⟦ v ⟧v ∷ s , ⟦ ρ ⟧ρ ⟩ ⟶∞⟨ correct⇑′ (♭ t₂⇑) ⟩
correct⇓ : ∀ {t v} →
[] ⊢ t ⇒ val v →
⟨ ⟦ t ⟧ [] , [] , [] ⟩ ⟶⋆ ⟨ [] , [ val ⟦ v ⟧v ] , [] ⟩
correct⇓ = correct⇓′
correct⇑ : ∀ {t} → [] ⊢ t ⇒ ⊥ → ⟨ ⟦ t ⟧ [] , [] , [] ⟩ ⟶∞
correct⇑ = ∞′→∞ ∘ correct⇑′