aboutsummaryrefslogtreecommitdiff
path: root/tiny/src/Circuit.hs
blob: d64e8c17b02ab58da954c5ace3b85f846ea65199 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
module Circuit () where

import RIO

import Data.Kind


data Nat = Zero | Succ Nat | Plus Nat Nat

data Env :: Nat -> Type -> Type where
    Leaf :: Env Zero a
    Cons :: a -> Env n a -> Env (Succ n) a
    Node :: Env l a -> Env r a -> Env (Plus l r) a

data Circuit :: Nat -> Type -> Type where
    Con :: Int -> Circuit Zero t
    Var :: t -> Circuit Zero t
    Add :: Circuit m t -> Circuit n t -> Circuit (Plus m n) t
    Let :: Circuit m t -> (t -> Circuit n t) -> Circuit (Plus m n) t
    Fix :: (t -> Circuit n t) -> Circuit n t
    Reg :: Circuit n t -> Circuit (Succ n) t

eval :: (Circuit n Int, Env n Int) -> Int
eval (Con i    ,        _) = i
eval (Var x    ,        _) = x
eval (Add e1 e2, Node l r) = eval (e1, l) + eval (e2, r)
eval (Let e1 e2, Node l r) = eval (e2 (eval (e1, l)), r)
eval (Fix e    ,      env) = fix (\x -> eval (e x, env))
eval (Reg _    , Cons v _) = v

step :: (Circuit n Int, Env n Int) -> Env n Int
step (Con i    ,        _)  = Leaf
step (Var x    ,        _)  = Leaf
step (Add e1 e2, Node l r)  = Node (step (e1, l)) (step (e2, r))
step (Let e1 e2, Node l r)  = Node (step (e1, l)) (step (e2 (eval (e1, l)), r))
step (Fix e    ,      env)  = step (fix (\e' -> e (eval (e', env))), env)
step (Reg e    , Cons _ vs) = Cons (eval (e, vs)) (step (e, vs))

acc i = Fix (\x -> Reg (Add (Var x) (Var i)))
fib = Fix (\x -> Reg (acc x))
pipe = Reg (Reg (Reg (Reg (Reg (Reg (Con 6))))))