Idris2/libs/papers/Language/IntrinsicTyping/STLCR.idr
2022-11-02 12:58:13 +00:00

68 lines
2.4 KiB
Idris

||| The content of this module is based on the MSc Thesis
||| Coinductive Formalization of SECD Machine in Agda
||| by Adam Krupička
module Language.IntrinsicTyping.STLCR
import Data.List.Elem
import Language.IntrinsicTyping.SECD
%default total
public export
data STLCR : List (Ty, Ty) -> List Ty -> Ty -> Type where
Var : Elem ty g -> STLCR r g ty
Lam : STLCR ((a, b) :: r) (a :: g) b -> STLCR r g (TyFun a b)
App : {a : _} -> STLCR r g (TyFun a b) -> STLCR r g a -> STLCR r g b
Rec : Elem (a,b) r -> STLCR r g (TyFun a b)
If : STLCR r g TyBool -> (t, f : STLCR r g a) -> STLCR r g a
Eqb : {a : _} -> STLCR r g a -> STLCR r g a -> STLCR r g TyBool
Lit : Const ty -> STLCR r g ty
Add, Sub, Mul : (m, n : STLCR r g TyInt) -> STLCR r g TyInt
public export
fromInteger : Integer -> STLCR r g TyInt
fromInteger n = Lit (AnInt (cast n))
factorial : STLCR [] [] (TyFun TyInt TyInt)
factorial
= Lam $ If (Eqb (Var Here) 0)
1
(Mul (Var Here) (App (Rec Here) (Sub (Var Here) 1)))
public export
compile : {ty : _} -> STLCR r g ty -> MkState s g r `Steps` MkState (ty :: s) g r
public export
compileT : {b : _} -> STLCR ((a, b) :: r) (a :: g) b ->
MkState [] (a :: g) ((a, b) :: r) `Steps` MkState [b] (a :: g) ((a, b) :: r)
public export
compileAcc : {ty : _} -> init `Stepz` MkState s g r -> STLCR r g ty -> init `Stepz` MkState (ty :: s) g r
compileAcc acc (Var v) = acc :< LDA v
compileAcc acc (Lam b) = acc :< LDF (compileT b)
compileAcc acc (App f t) = compileAcc (compileAcc acc f) t :< APP
compileAcc acc (Rec v) = acc :< LDR v
compileAcc acc (If b t f) = compileAcc acc b :< BCH (compile t) (compile f)
compileAcc acc (Eqb x y) = compileAcc (compileAcc acc y) x :< EQB
compileAcc acc (Lit c) = acc :< LDC c
compileAcc acc (Add m n) = compileAcc (compileAcc acc n) m :< ADD
compileAcc acc (Sub m n) = compileAcc (compileAcc acc n) m :< SUB
compileAcc acc (Mul m n) = compileAcc (compileAcc acc n) m :< MUL
compile t = compileAcc [<] t <>> []
compileT (Lam b) = [LDF (compileT b)]
compileT (App f t) = compileAcc (compileAcc [<] f) t <>> [TAP]
compileT (If b t f) = compileAcc [<] b <>> [BCH (compileT t) (compileT f)]
compileT (Lit c) = [LDC c]
compileT t = compileAcc [<] t <>> [RTN]
testPLS : compile (Lam (Lam (Add (Var (There Here)) (Var Here))))
=== [LDF [LDF [LDA Here, LDA (There Here), ADD, RTN]]]
testPLS = Refl
testFAC : run (compile (App STLCR.factorial 5)) 12 === Just 120
testFAC = Refl