{-# LANGUAGE ScopedTypeVariables #-}
module Language.Floorplan.Core.Syntax where
import Data.Maybe (maybeToList)
import Language.Floorplan.Syntax (LayerID, FormalID, FlagID, FieldID, SizeArith(..))
type Nat = Int
type Align = Int
type ExistsID = String
type NameID = String
data Exp a
= Prim Nat
| Con Nat (Exp a)
| (:@) (Exp a) Align
| (:+) (Exp a) (Exp a)
| (:||) (Exp a) (Exp a)
| (:::) NameID (Exp a)
| Exists ExistsID (Exp a)
| (:#) ExistsID (Exp a)
| Attr a (Exp a)
deriving (Eq, Ord, Show)
data Attribute ty
= Contains NameID
| BaseType ty
deriving (Eq, Ord, Show)
data BaseType
= EnumBT [FlagID]
| BitsBT [(NameID, Int)]
| PtrBT NameID
| SizeBT SizeArith
deriving (Eq, Ord, Show)
type BaseExp = Exp (Attribute BaseType)
accum :: (Exp a -> Maybe b) -> Exp a -> [b]
accum fn e@(Prim{}) = maybeToList (fn e)
accum fn e1@(Con _ e2) = maybeToList (fn e1) ++ accum fn e2
accum fn e1@(e2 :@ _) = maybeToList (fn e1) ++ accum fn e2
accum fn e1@(e2 :+ e3) = maybeToList (fn e1) ++ accum fn e2 ++ accum fn e3
accum fn e1@(e2 :|| e3) = maybeToList (fn e1) ++ accum fn e2 ++ accum fn e3
accum fn e1@(_ ::: e2) = maybeToList (fn e1) ++ accum fn e2
accum fn e1@(Exists _ e2) = maybeToList (fn e1) ++ accum fn e2
accum fn e1@(_ :# e2) = maybeToList (fn e1) ++ accum fn e2
accum fn e1@(Attr _ e2) = maybeToList (fn e1) ++ accum fn e2
callSub :: (Exp a -> [b]) -> Exp a -> [b]
callSub fn (Prim{}) = []
callSub fn (Con _ e) = fn e
callSub fn (e :@ _) = fn e
callSub fn (e1 :+ e2) = fn e1 ++ fn e2
callSub fn (e1 :|| e2) = fn e1 ++ fn e2
callSub fn (_ ::: e) = fn e
callSub fn (Exists _ e) = fn e
callSub fn (_ :# e) = fn e
callSub fn (Attr _ e) = fn e
plus :: Maybe Int -> Maybe Int -> Maybe Int
plus a b = do
a' <- a
b' <- b
return $ a' + b'
expSize :: Exp a -> Maybe Int
expSize (Prim n) = return n
expSize (Con n _) = return n
expSize (e :@ _) = expSize e
expSize (e1 :+ e2) = expSize e1 `plus` expSize e2
expSize (e1 :|| e2) =
let s1 = expSize e1
s2 = expSize e2
in if s1 == s2 then s1 else Nothing
expSize (_ ::: e) = expSize e
expSize (Exists _ e) = expSize e
expSize (_ :# _) = Nothing
expSize (Attr _ e) = expSize e
l2r :: forall a b. (Maybe Nat -> Exp a -> Maybe b) -> Exp a -> [b]
l2r fn e' = let
mTL :: Maybe Nat -> Exp a -> [b]
mTL i = maybeToList . fn i
lr :: Maybe Nat -> Exp a -> [b]
lr i e@(Prim{}) = mTL i e
lr i e1@(Con _ e2) = mTL i e1 ++ lr i e2
lr i e1@(e2 :@ _) = mTL i e1 ++ lr i e2
lr i e1@(e2 :+ e3) = mTL i e1 ++ (lr i e2 ++ lr (i `plus` expSize e2) e3)
lr i e1@(e2 :|| e3) = mTL i e1 ++ (lr i e2 ++ lr i e3)
lr i e1@(_ ::: e2) = mTL i e1 ++ lr i e2
lr i e1@(Exists _ e2) = mTL i e1 ++ lr i e2
lr i e1@(_ :# e2) = mTL i e1 ++ lr Nothing e2
lr i e1@(Attr _ e2) = mTL i e1 ++ lr i e2
in lr (Just 0) e'