yapb-0.1.0: app/polyrpc/cs/CSExpr.hs
{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
module CSExpr where
import qualified Data.Set as Set
import Location
import Prim
import Literal
import CSType
import qualified Expr as SE
import Text.JSON.Generic
data Expr =
ValExpr Value
| Let [BindingDecl] Expr
| Case Value Type [Alternative] -- including pi_i (V)
| App Value Type Value
| TypeApp Value Type [Type]
| LocApp Value Type [Location]
| Prim PrimOp [Location] [Type] [Value]
deriving (Show, Typeable, Data)
data Value =
Var String
| Lit Literal
| Tuple [Value]
| Constr String [Location] [Type] [Value] [Type]
| Closure [Value] [Type] CodeName [String] -- [] or [rec_f] for now, [rec_f1, ...,, rec_fk] in future
| UnitM Value
| BindM [BindingDecl] Expr
| Req Value Type Value
| Call Value Type Value
| GenApp Location Value Type Value
-- Runtime values
| Addr Integer
deriving (Show, Typeable, Data)
data BindingDecl =
Binding String Type Expr
deriving (Show, Typeable, Data)
data DataTypeDecl =
DataType String [String] [TypeConDecl]
-- For aeson
-- deriving (Show, Generic)
deriving (Show, Typeable, Data)
data TopLevelDecl =
BindingTopLevel BindingDecl
| DataTypeTopLevel DataTypeDecl
| LibDeclTopLevel String Type
-- For aeson
-- deriving (Show, Generic)
deriving (Show, Typeable, Data)
data TypeConDecl =
TypeCon String [Type]
-- For aeson
-- deriving (Show, Generic)
deriving (Show, Typeable, Data)
data Alternative =
Alternative String [String] Expr
| TupleAlternative [String] Expr
deriving (Show, Typeable, Data)
data Code =
Code [String] [String] [String] OpenCode -- [loc]. [alpha]. [x]. OpenCode
deriving (Show, Typeable, Data)
data OpenCode =
CodeAbs [(String, Type)] Expr
| CodeTypeAbs [String] Expr
| CodeLocAbs [String] Expr
deriving (Show, Typeable, Data)
data CodeName =
CodeName String [Location] [Type]
deriving (Show, Typeable, Data)
--
-- [(Name, Location Vars, Type Vars)]
type TypeInfo = [(String, [String], [String])]
-- [(ConName, (ConArgTypes, DTName, LocationVars, TypeVars))]
type ConTypeInfo = [(String, ([Type], String, [String], [String]))]
type BindingTypeInfo = [(String, Type)]
-- [ (DTName, LocationVars, TypeVars, [(ConName, ArgTypes)]) ]
type DataTypeInfo = [(String, ([String], [String], [(String,[Type])]))]
type LibInfo = [(String, Type)]
data GlobalTypeInfo = GlobalTypeInfo
{ _typeInfo :: TypeInfo
, _conTypeInfo :: ConTypeInfo
, _dataTypeInfo :: DataTypeInfo
, _libInfo :: LibInfo } -- library types
deriving (Show, Typeable, Data)
data Env = Env
{ _locVarEnv :: [String]
, _typeVarEnv :: [String]
, _varEnv :: BindingTypeInfo }
initEnv = Env { _locVarEnv=[], _typeVarEnv=[], _varEnv=[] }
--
data FunctionStore = FunctionStore
{ _clientstore :: [(String, (CodeType, Code))]
, _serverstore :: [(String, (CodeType, Code))]
, _new :: Int
}
deriving (Show, Typeable, Data)
addClientFun :: FunctionStore -> String -> CodeType -> Code -> FunctionStore
addClientFun fnstore name ty code =
fnstore {_clientstore = _clientstore fnstore ++ [(name,(ty,code))] }
addServerFun :: FunctionStore -> String -> CodeType -> Code -> FunctionStore
addServerFun fnstore name ty code =
fnstore {_serverstore = (_serverstore fnstore) ++ [(name,(ty,code))] }
addFun :: Location -> FunctionStore -> String -> CodeType -> Code -> FunctionStore
addFun loc funstore name ty@(CodeType [] [] fvtys (FunType _ funloc _)) code =
if isClient funloc then addClientFun funstore name ty code
else if isServer funloc then addServerFun funstore name ty code
else addServerFun (addClientFun funstore name ty code) name ty code
addFun loc funstore name ty@(CodeType [] [] fvtys somety) code =
addServerFun (addClientFun funstore name ty code) name ty code
addFun loc funstore name ty@(CodeType locvars tyvars fvtys somety) code =
addServerFun (addClientFun funstore name ty code) name ty code
newName :: FunctionStore -> (String, FunctionStore)
newName fnstore = let n = _new fnstore in ("f" ++ show n, fnstore{_new =n+1})
newVar :: FunctionStore -> (String, FunctionStore)
newVar fnstore = let n = _new fnstore in ("x" ++ show n, fnstore{_new =n+1})
newVars :: Int -> FunctionStore -> ([String], FunctionStore)
newVars 0 funStore = ([], funStore)
newVars n funStore =
let (x, funStore1) = newVar funStore
(xs, funStore2) = newVars (n-1) funStore1
in (x:xs, funStore2)
initFunctionStore = FunctionStore
{ _clientstore=[]
, _serverstore=[]
, _new = 1
}
--
--
primOpTypes :: [(PrimOp, ([String], [String], [Type], Type))] -- (locvars, tyvars, argtys, retty)
primOpTypes =
[ (NotPrimOp, (["l"], [], [bool_type], bool_type))
, (OrPrimOp, (["l"], [], [bool_type, bool_type], bool_type))
, (AndPrimOp, (["l"], [], [bool_type, bool_type], bool_type))
, (EqPrimOp, (["l"], [], [bool_type, bool_type], bool_type))
, (NeqPrimOp, (["l"], [], [bool_type, bool_type], bool_type))
, (LtPrimOp, (["l"], [], [int_type, int_type], bool_type))
, (LePrimOp, (["l"], [], [int_type, int_type], bool_type))
, (GtPrimOp, (["l"], [], [int_type, int_type], bool_type))
, (GePrimOp, (["l"], [], [int_type, int_type], bool_type))
, (AddPrimOp, (["l"], [], [int_type, int_type], int_type))
, (SubPrimOp, (["l"], [], [int_type, int_type], int_type))
, (MulPrimOp, (["l"], [], [int_type, int_type], int_type))
, (DivPrimOp, (["l"], [], [int_type, int_type], int_type))
, (NegPrimOp, (["l"], [], [int_type], int_type))
, (PrimReadOp, (["l"], [], [unit_type], string_type))
, (PrimPrintOp, (["l"], [], [string_type], unit_type))
, (PrimIntToStringOp, (["l"], [], [int_type], string_type))
, (PrimConcatOp, (["l"], [], [string_type,string_type], string_type))
, (PrimRefCreateOp,
let l1 = "l1" in
let a = "a" in
let tyvar_a = TypeVarType a in
let locvar_l1 = LocVar l1 in
([l1], [a], [tyvar_a], ConType refType [locvar_l1] [tyvar_a]))
, (PrimRefReadOp,
let l1 = "l1" in
let a = "a" in
let tyvar_a = TypeVarType a in
let locvar_l1 = LocVar l1 in
([l1], [a], [ConType refType [locvar_l1] [tyvar_a]], tyvar_a))
, (PrimRefWriteOp,
let l1 = "l1" in
let a = "a" in
let tyvar_a = TypeVarType a in
let locvar_l1 = LocVar l1 in
([l1], [a], [ConType refType [locvar_l1] [tyvar_a], tyvar_a], unit_type))
]
lookupPrimOpType primop =
[ (locvars,tyvars,tys,ty)
| (primop1,(locvars, tyvars, tys,ty)) <- primOpTypes, primop==primop1]
lookupConstr :: GlobalTypeInfo -> String -> [([Type], String, [String], [String])]
lookupConstr gti x = [z | (con, z) <- _conTypeInfo gti, x==con]
-----------------
-- free variables
-----------------
fvOpenCode :: OpenCode -> Set.Set String
fvOpenCode (CodeAbs xTys expr) = fvExpr expr `Set.difference` Set.fromList (map fst xTys)
fvOpenCode (CodeTypeAbs tyvars expr) = fvExpr expr
fvOpenCode (CodeLocAbs locvars expr) = fvExpr expr
fvExpr :: Expr -> Set.Set String
fvExpr (ValExpr val) = fvValue val
fvExpr (Let bindingDcl expr) = Set.empty
fvExpr (Case val _ alts) = fvValue val `Set.union` Set.unions (map fvAlt alts)
fvExpr (App left _ right) = fvValue left `Set.union` fvValue right
fvExpr (TypeApp left _ _) = fvValue left
fvExpr (LocApp left _ _) = fvValue left
fvExpr (Prim primop locs tys vs) = Set.unions (map fvValue vs)
fvAlt :: Alternative -> Set.Set String
fvAlt (Alternative cname xs expr) = fvExpr expr `Set.difference` Set.fromList xs
fvAlt (TupleAlternative xs expr) = fvExpr expr `Set.difference` Set.fromList xs
fvValue :: Value -> Set.Set String
fvValue (Var x) = Set.singleton x
fvValue (Lit lit) = Set.empty
fvValue (Tuple vs) = Set.unions (map fvValue vs)
fvValue (Constr cname _ _ vs _) = Set.unions (map fvValue vs)
fvValue (Closure vs _ codename _) = Set.unions (map fvValue vs)
fvValue (UnitM v) = fvValue v
fvValue (BindM bindingDecls expr) =
(Set.unions (map (\(Binding _ _ expr) -> fvExpr expr) bindingDecls) `Set.union` fvExpr expr)
`Set.difference` (Set.fromList (map (\(Binding x _ _) -> x) bindingDecls))
fvValue (Req left _ right) = fvValue left `Set.union` fvValue right
fvValue (Call left _ right) = fvValue left `Set.union` fvValue right
fvValue (GenApp _ left _ right) = fvValue left `Set.union` fvValue right
--
singleBindM (BindM [] expr) = expr
singleBindM (BindM (bind:binds) expr) =
ValExpr $ BindM [bind] (singleBindM (BindM binds expr))