g2-0.1.0.0: src/G2/Translation/PrimInject.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
-- | Primitive inejction into the environment
module G2.Translation.PrimInject
( primInject
, dataInject
, addPrimsToBase
, mergeProgs
, mergeProgTys
) where
import G2.Language.AST
import G2.Language.Naming
import G2.Language.Syntax
import G2.Language.Typing
import G2.Language.TypeEnv
import Data.List
import qualified Data.Text as T
primInject :: ASTContainer p Type => p -> p
primInject = modifyASTs primInjectT
primInjectT :: Type -> Type
primInjectT (TyCon (Name "TYPE" (Just "GHC.Prim") _ _) _) = TYPE
primInjectT (TyCon (Name "Int#" _ _ _) _) = TyLitInt
primInjectT (TyCon (Name "Word#" _ _ _) _) = TyLitInt
primInjectT (TyCon (Name "Float#" _ _ _) _) = TyLitFloat
primInjectT (TyCon (Name "Double#" _ _ _) _) = TyLitDouble
primInjectT (TyCon (Name "Char#" _ _ _) _) = TyLitChar
primInjectT t = t
dataInject :: Program -> [ProgramType] -> (Program, [ProgramType])
dataInject prog progTy =
let
dcNames = concatMap (\(_, dc) -> map conName (dataCon dc)) $ progTy
in
(modifyASTs (dataInject' dcNames) prog, progTy)
-- TODO: Polymorphic types?
dataInject' :: [(Name, [Type])] -> Expr -> Expr
dataInject' ns v@(Var (Id (Name n m _ _) t)) =
case find (\(Name n' m' _ _, _) -> n == n' && m == m') ns of
Just (n', _) -> Data (DataCon n' t)
Nothing -> v
dataInject' _ e = e
conName :: DataCon -> (Name, [Type])
conName (DataCon n t) = (n, anonArgumentTypes $ t)
primDefs :: [ProgramType] -> [(T.Text, Expr)]
primDefs pt = case boolName pt of
Just n -> primDefs' n
Nothing -> error "Bool type not found"
primDefs' :: Name -> [(T.Text, Expr)]
primDefs' b = [ ("==#", Prim Eq $ tyIntIntBool b)
, ("/=#", Prim Neq $ tyIntIntBool b)
, ("+#", Prim Plus tyIntIntInt)
, ("*#", Prim Mult tyIntIntInt)
, ("-#", Prim Minus tyIntIntInt)
, ("negateInt#", Prim Negate tyIntInt)
, ("<=#", Prim Le $ tyIntIntBool b)
, ("<#", Prim Lt $ tyIntIntBool b)
, (">#", Prim Gt $ tyIntIntBool b)
, (">=#", Prim Ge $ tyIntIntBool b)
, ("divInt#", Prim Quot tyIntIntInt)
, ("modInt#", Prim Mod tyIntIntInt)
, ("quotInt#", Prim Quot tyIntIntInt)
, ("remInt#", Prim Mod tyIntIntInt)
, ("==##", Prim Eq $ tyDoubleDoubleBool b)
, ("/=##", Prim Neq $ tyDoubleDoubleBool b)
, ("+##", Prim Plus tyDoubleDoubleDouble)
, ("*##", Prim Mult tyDoubleDoubleDouble)
, ("-##", Prim Minus tyDoubleDoubleDouble)
, ("negateDouble#", Prim Negate tyDoubleDouble)
, ("sqrtDouble#", Prim SqRt tyDoubleDoubleDouble)
, ("<=##", Prim Le $ tyDoubleDoubleBool b)
, ("<##", Prim Lt $ tyDoubleDoubleBool b)
, (">##", Prim Gt $ tyDoubleDoubleBool b)
, (">=##", Prim Ge $ tyDoubleDoubleBool b)
, ("plusFloat#", Prim Plus tyFloatFloatFloat)
, ("timesFloat#", Prim Mult tyFloatFloatFloat)
, ("minusFloat#", Prim Minus tyFloatFloatFloat)
, ("negateFloat#", Prim Negate tyFloatFloat)
, ("sqrtFloat#", Prim SqRt tyFloatFloatFloat)
, ("/##", Prim Div tyFloatFloatFloat)
, ("divideFloat#", Prim Div tyFloatFloatFloat)
, ("eqFloat#", Prim Eq $ tyFloatFloatBool b)
, ("neqFloat#", Prim Neq $ tyFloatFloatBool b)
, ("leFloat#", Prim Le $ tyFloatFloatBool b)
, ("ltFloat#", Prim Lt $ tyFloatFloatBool b)
, ("gtFloat#", Prim Gt $ tyFloatFloatBool b)
, ("geFloat#", Prim Ge $ tyFloatFloatBool b)
, ("quotInteger#", Prim Quot tyIntIntInt)
, ("eqChar#", Prim Eq $ tyCharCharBool b )
, ("neChar#", Prim Neq $ tyCharCharBool b )
, ("float2Int#", Prim ToInt (TyFun TyLitFloat TyLitInt))
, ("int2Float#", Prim IntToFloat (TyFun TyLitInt TyLitFloat))
, ("fromIntToFloat", Prim IntToFloat (TyFun TyLitInt TyLitFloat))
, ("double2Int#", Prim ToInt (TyFun TyLitDouble TyLitInt))
, ("int2Double#", Prim IntToDouble (TyFun TyLitInt TyLitDouble))
, ("fromIntToDouble", Prim IntToDouble (TyFun TyLitInt TyLitDouble))
, ("absentErr", Prim Error TyBottom)
, ("error", Prim Error TyBottom)
, ("errorWithoutStackTrace", Prim Error TyBottom)
, ("divZeroError", Prim Error TyBottom)
, ("patError", Prim Error TyBottom)
, ("succError", Prim Error TyBottom)
, ("toEnumError", Prim Error TyBottom)
, ("undefined", Prim Error TyBottom)]
tyIntInt :: Type
tyIntInt = TyFun TyLitInt TyLitInt
tyIntIntBool :: Name -> Type
tyIntIntBool n = TyFun TyLitInt $ TyFun TyLitInt (TyCon n TYPE)
tyIntIntInt :: Type
tyIntIntInt = TyFun TyLitInt $ TyFun TyLitInt TyLitInt
tyDoubleDouble :: Type
tyDoubleDouble = TyFun TyLitDouble TyLitDouble
tyDoubleDoubleBool :: Name -> Type
tyDoubleDoubleBool n = TyFun TyLitDouble $ TyFun TyLitDouble (TyCon n TYPE)
tyDoubleDoubleDouble :: Type
tyDoubleDoubleDouble = TyFun TyLitDouble $ TyFun TyLitDouble TyLitDouble
tyFloatFloat :: Type
tyFloatFloat = TyFun TyLitFloat TyLitFloat
tyFloatFloatBool :: Name -> Type
tyFloatFloatBool n = TyFun TyLitFloat $ TyFun TyLitFloat (TyCon n TYPE)
tyFloatFloatFloat :: Type
tyFloatFloatFloat = TyFun TyLitFloat $ TyFun TyLitFloat TyLitFloat
tyCharCharBool :: Name -> Type
tyCharCharBool n = TyFun TyLitChar $ TyFun TyLitChar (TyCon n TYPE)
boolName :: [ProgramType] -> Maybe Name
boolName = find ((==) "Bool" . nameOcc) . map fst
replaceFromPD :: [ProgramType] -> Id -> Expr -> (Id, Expr)
replaceFromPD pt i@(Id n _) e =
let
e' = fmap snd $ find ((==) (nameOcc n) . fst) (primDefs pt)
in
(i, maybe e id e')
addPrimsToBase :: [ProgramType] -> Program -> Program
addPrimsToBase pt prims = map (map (uncurry (replaceFromPD pt))) prims
mergeProgs :: Program -> Program -> Program
mergeProgs prog prims = prog ++ prims
-- The prog is used to change the names of types in the prog' and primTys
mergeProgTys :: [ProgramType] -> [ProgramType] -> [ProgramType]
mergeProgTys progTys primTys =
progTys ++ primTys