cnc-spec-compiler-0.2.0.0: Intel/Cnc/Spec/Passes/TypeDef.hs
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
-- This module contains the simple spec transformation pass that desugars type synonyms (TypeDefs)
-- Certainly this is a candidate for Scrap-your-boilerplate generic programming.
module Intel.Cnc.Spec.Passes.TypeDef where
import Intel.Cnc.Spec.Util
import StringTable.Atom
import qualified StringTable.AtomMap as AM
import Intel.Cnc.Spec.AST
import Test.HUnit
--import Debug.Trace
desugarTypeDefs :: [PStatement dec] -> [PStatement dec]
desugarTypeDefs input =
mapTypes desugarTy everything_else
where
synonyms = AM.fromList$ map (\ (TypeDef _ nm ty) -> (nm,ty)) $
filter isdef input
everything_else = filter (not . isdef) input
isdef (TypeDef _ _ _) = True
isdef _ = False
desugarTy ty =
case ty of
TInt -> TInt
TFloat -> TFloat
TDouble -> TDouble
TSym atom -> case AM.lookup atom synonyms of
Nothing -> TSym atom
Just ty -> ty -- Easy, no constructor application
TPtr ty -> TPtr $ desugarTy ty
TRef ty -> TRef $ desugarTy ty
TDense ty -> TDense $ desugarTy ty
TConst ty -> TConst $ desugarTy ty
TTuple ls -> TTuple $ map desugarTy ls
----------------------------------------------------------------------------------------------------
-- Everything below this line is total boilerplate just to traverse the data-types.
----------------------------------------------------------------------------------------------------
-- Process all the types, SYB eligible.
class MapTypes a where
mapTypes :: (Type -> Type) -> a -> a
instance MapTypes (PStatement dec) where
mapTypes fn stmnt = case stmnt of
DeclareTags s nm mty -> DeclareTags s nm $ fmap fn mty
DeclareItems s nm Nothing -> stmnt
DeclareItems s nm (Just (ty1,ty2)) -> DeclareItems s nm $ Just (fn ty1, fn ty2)
DeclareReductions s nm op exp Nothing -> DeclareReductions s nm op (mapTypes fn exp) Nothing
DeclareReductions s nm op exp (Just (ty1,ty2)) -> DeclareReductions s nm op (mapTypes fn exp) (Just (fn ty1, fn ty2))
DeclareSteps _ _ -> stmnt
Function -> stmnt
DeclareExtern -> stmnt
Chain insts links -> Chain (mapTypes fn insts) (mapTypes fn links)
Constraints s inst els -> Constraints s (mapTypes fn inst) (mapTypes fn els)
TypeDef _ _ _ -> error "serious internal implementation error"
instance MapTypes (CollectionInstance dec) where
mapTypes fn inst = case inst of
InstName dec str -> inst
InstStepOrTags dec str els -> InstStepOrTags dec str $ mapTypes fn els
InstTagCol dec str els -> InstTagCol dec str $ mapTypes fn els
InstItemCol dec str els -> InstItemCol dec str $ mapTypes fn els
InstStepCol dec str els -> InstStepCol dec str $ mapTypes fn els
instance MapTypes (RelLink dec) where
mapTypes fn lnk = case lnk of
ProduceLink dec insts -> ProduceLink dec $ mapTypes fn insts
PrescribeLink dec insts -> PrescribeLink dec $ mapTypes fn insts
RevProduceLink dec insts -> RevProduceLink dec $ mapTypes fn insts
-- Expressions don't YET have any type info but we do a meaningless traversal here
-- just so we will catch future expressions added...
instance MapTypes (Exp dec) where
mapTypes fn e = case e of
Lit _ _ -> e
Var _ _ -> e
App s rat rands -> App s (mapTypes fn rat) (mapTypes fn rands)
If s a b c -> If s (mapTypes fn a) (mapTypes fn b) (mapTypes fn c)
instance MapTypes a => MapTypes [a] where
mapTypes fn = map (mapTypes fn)
instance (MapTypes a, MapTypes b) => MapTypes (a,b) where
mapTypes fn (a,b) = (mapTypes fn a, mapTypes fn b)
----------------------------------------------------------------------------------------------------
mty = Just (TSym (toAtom "triple"), TPtr (TPtr (TSym (toAtom "double"))))
-- This will, oddly, compile but only hit the second part of the tuple!
strange = fmap (fmap (const TInt)) mty
strange2 = fmap (fmap (+1)) (Just (0,0))
-- Oh it must depend on compiler parameters, in a fresh GHCI this DOES NOT work:
-- Does some module I imported define this instance?? Ouch, non-local effect in this module?
strange3 = fmap (+1) (0,0)
test_desugarTypeDefs =
testSet "TypeDef"
[testCase "" "basic desugarTypeDefs test"$ result ~=? desugarTypeDefs input]
where
pair = toAtom "pair"
triple = toAtom "triple"
int = toAtom "int"
double = toAtom "double"
lkji = toAtom "Lkji"
control_S2 = toAtom "control_S2"
control_S3 = toAtom "control_S3"
result = [DeclareItems () lkji (Just (TTuple [TSym int,TSym int,TSym int],TPtr (TPtr (TSym double)))),
DeclareTags () control_S2 (Just (TTuple [TSym int,TSym int])),
DeclareTags () control_S3 (Just (TTuple [TSym int,TSym int,TSym int]))]
input = [TypeDef () pair (TTuple [TSym int, TSym int]),
TypeDef () triple (TTuple [TSym int,TSym int,TSym int]),
DeclareItems () lkji (Just (TSym triple, TPtr (TPtr (TSym double)))),
DeclareTags () control_S2 (Just (TSym pair)),
DeclareTags () control_S3 (Just (TSym triple))]