packages feed

pec-0.2.2: Pec/IUtil.hs

{-# OPTIONS -Wall #-}

-- The pec embedded compiler
-- Copyright 2011-2012, Brett Letner

module Pec.IUtil where

import Control.Concurrent
import Data.Char
import Data.Generics.Uniplate.Data
import Data.List
import Data.Maybe
import Grm.Prims
import Language.Pir.Abs
import System.IO.Unsafe

gTyDecls :: MVar [(Type,TyDecl)]
gTyDecls = unsafePerformIO $ newMVar []

fvsIDefine :: Define -> [TVar]
fvsIDefine x@(Define _ _ _ ds) =
  (nub $ filter f $ universeBi ds) \\ bvsIDefine x
  where
    f v@(TVar a _) = not (a `elem` builtins || isBinOp v || isFldOp a)

isFldOp :: String -> Bool
isFldOp = has_suffix "_fld"

bvsIDefine :: Define -> [TVar]
bvsIDefine x@(Define _ _ cs _) = nub (cs ++ lvsIDefine x)

lvsIDefine :: Define -> [TVar]
lvsIDefine (Define _ _ _ ds) = nub [ v | LetS v _ <- universeBi ds ]

builtins :: [String]
builtins = ["mk", "tagv", "idx", "un", "printf"]

isTypeEquiv :: Type -> Type -> Bool
isTypeEquiv a b = case (a,b) of
  (Type "Char_" [], Type "W_" [Type "Cnt8" []]) -> True
  (Type "W_" [Type "Cnt8" []], Type "Char_" []) -> True
  _ -> False

tyVoid :: Type
tyVoid = Type "Void_" []
  
vtvar :: TVar -> String
vtvar (TVar a _) = a

ttvar :: TVar -> Type
ttvar (TVar _ b) = b

ttlit :: TLit -> Type
ttlit (TLit _ b) = b

tatom :: Atom -> Type
tatom x = case x of
  LitA a -> ttlit a
  VarA a -> ttvar a

isBinOp :: TVar -> Bool
isBinOp = isJust . lookupBinOp

cBinOp :: TVar -> String
cBinOp = fromJust . lookupBinOp

lookupBinOp :: TVar -> Maybe String
lookupBinOp v = lookup (vtvar v)
  [ ("add","+")
  , ("sub","-")
  , ("mul","*")
  , ("div","/")
  , ("rem","%")
  , ("gt",">")
  , ("gte",">=")
  , ("lt","<")
  , ("lte","<=")
  , ("eq","==")
  , ("ne","!=")
  , ("shl","<<")
  , ("shr",">>")
  , ("band","&")
  , ("bor","|")
  , ("bxor","^")
  , ("bnot","~")
  , ("and","&&")
  , ("or","||")
  ]

nCnt :: [Type] -> Number
nCnt [t@(Type cs [])] | isCnt t = filter isDigit cs
nCnt _ = error "nCnt"

isCnt :: Type -> Bool
isCnt (Type ('C':'n':'t':cs) []) = not (null cs) && all isDigit cs
isCnt _ = False

has_suffix :: Eq a => [a] -> [a] -> Bool
has_suffix a b = drop (length b - length a) b == a

drop_suffix :: [a] -> [a] -> [a]
drop_suffix a b = take (length b - length a) b

promote :: Number -> Number
promote s
  | x <= 8 = "8"
  | x <= 16 = "16"
  | x <= 32 = "32"
  | x <= 64 = "64"
  | x <= 128 = "128"
  | otherwise = error $ "too many bits required to represent number:" ++ show x
  where
    x = readNumber s :: Integer
    
strip_underscore :: String -> String
strip_underscore "" = ""
strip_underscore s
  | last s == '_' = case reverse $ dropWhile ((==) '_') $ reverse s of
      [] -> "_"
      s1 -> s1
  | otherwise = s

isSigned :: Type -> Bool
isSigned x = case x of
  Type "I_" [_] -> True
  _ -> False

isUnsigned :: Type -> Bool
isUnsigned x = case x of
  Type "W_" [_] -> True
  _ -> False

isFloating :: Type -> Bool
isFloating x = case x of
  Type "Double_" [] -> True
  Type "Float_" [] -> True
  _ -> False

inlineAtoms :: Define -> Define
inlineAtoms x = transformBi h $ rewriteBi g $ rewriteBi f x
  where
    tbl = [ (a,b) | LetS a (AtomE b) <- universeBi x ]
    f (VarA v) = lookup v tbl
    f _ = Nothing
    g v = case lookup v tbl of
      Just (VarA v1) -> Just v1
      _ -> Nothing
    h (LetS _ AtomE{}) = NoOpS
    h s = s

tyEnums :: TyDecl -> [(String,Integer)]
tyEnums x = zip (sort ss) [ 0 .. ]
  where
  ss = [ a | EnumC a <- universeBi x ] ++ [ a | ConC a _ <- universeBi x ]

tyFields :: TyDecl -> [(String,Integer)]
tyFields x = zip [ a ++ "fld" | FieldT a _ <- universeBi x ] [ 0 .. ]