{-# LANGUAGE DeriveAnyClass, DeriveGeneric, DeriveDataTypeable #-}
module Language.Floorplan.Semantics where
import Data.Maybe (fromJust)
import Language.Floorplan.Core.Syntax
data Tree =
T Tree Tree
| N String Tree
| B0 | B1
deriving (Eq, Ord, Show)
leaves (T t1 t2) = leaves t1 + leaves t2
leaves (N _ t) = leaves t
leaves B0 = 0
leaves B1 = 1
addStep s xs = map (\(r,d) -> (r, s : d)) xs
g p0 p1 p2 p3 = let
g' a m theta ((:+) e1 e2) =
let params = \r1 -> (a + leaves r1, m - leaves r1, theta, e2)
in
[ (T r1 r2, ("Plus: i = 0.." ++ show m ++ ", Pause (g " ++ show (params r1) ++ ")") : deriv1
++ ["Resume (g " ++ show (params r1) ++ ")" ++ ", leaves r1 = " ++ show (leaves r1)] ++ deriv2)
| (r1, deriv1) <- concat [ addStep ("Plus_r1: Choose i=" ++ show i) $ g a i theta e1 | i <- [0..m]]
, (r2, deriv2) <- addStep ("Plus_r2: leaves(" ++ show e1 ++ ")=" ++ show (leaves r1)) $ g (a + leaves r1) (m - leaves r1) theta e2
]
g' a m theta ((:||) e1 e2) = let
r1 = addStep ("Or_e1") (g a m theta e1)
r2 = addStep ("Or_e2") (g a m theta e2)
in r1 ++ r2
g' a m theta (Prim n)
| m == n = [(foldl T B0 (take n $ repeat B1), ["Prim: Evaluate " ++ show n ++ "-leaf tree"])]
| otherwise = []
g' a m theta (Con n e)
| m == n = addStep ("Con: " ++ show n) (g a m theta e)
| m /= n = []
g' a m theta ((:@) e aln)
| a `mod` aln == 0 = g a m theta e
| otherwise = []
g' a m theta ((:::) l e) =
[ (N l r, ("HasType: " ++ l) : deriv)
| (r, deriv) <- g a m theta e
]
g' a m theta (Exists f e) = concat
[ addStep ("Exists: Choose " ++ f ++ "=" ++ show i)
$ g a m ((f, i) : theta) e | i <- [0 .. m] ]
g' a m theta ((:#) f e)
| (Just m) == lookup f theta && m == 0 = [(T B0 B0, ["Pound: m = 0"])]
| (Just 0) == lookup f theta = []
| otherwise = let
params = \r1 -> (a + leaves r1, m - leaves r1, (f, (fromJust $ lookup f theta) - 1) : theta, (:#) f e)
in case lookup f theta of
Nothing -> error "Nothing"
Just thetaF -> [ (T r1 r2, ("Pound: theta(" ++ f ++ ")=" ++ show thetaF ++ ", Pause (g " ++ show (params r1)) : deriv1
++ ["Resume (g " ++ show (params r1) ++ ")"] ++ deriv2)
| (r1, deriv1) <- concat [addStep ("Pound_r1: Choose i=" ++ show i) $ g a i theta e | i <- [0..m]]
, (r2, deriv2) <- addStep ("Pound_r2: leaves(" ++ show e ++ ")=" ++ show (leaves r1)) $
g (a + leaves r1) (m - leaves r1) ((f, (fromJust $ lookup f theta) - 1) : theta) ((:#) f e)
]
addLabel (r, d:ds) = (r, (d ++ "[[g " ++ show (p0, p1, p2, p3) ++ "]] ") : ds)
in map addLabel (g' p0 p1 p2 p3)