g2-0.2.0.0: src/G2/Execution/NormalForms.hs
module G2.Execution.NormalForms where
import G2.Language
import qualified G2.Language.Stack as S
import qualified G2.Language.ExprEnv as E
import G2.Language.Typing
import qualified Data.HashSet as HS
-- A Var counts as being in EVF if it's symbolic or if it's unmapped.
isSWHNF :: State t -> Bool
isSWHNF (State { expr_env = h, curr_expr = CurrExpr _ e }) =
let e' = modifyASTs stripTicks e
t = typeOf e'
in case e' of
Var _ -> (isPrimType t || not (concretizable t)) && isExprValueForm h e'
_ -> isExprValueForm h e'
stripTicks :: Expr -> Expr
stripTicks (Tick _ e) = e
stripTicks e = e
-- used by EquivADT and Tactics
concretizable :: Type -> Bool
concretizable (TyVar _) = False
concretizable (TyForAll _ _) = False
concretizable (TyFun _ _) = False
concretizable t@(TyApp _ _) =
concretizable $ last $ unTyApp t
concretizable TYPE = False
concretizable TyUnknown = False
concretizable _ = True
-- | If something is in "value form", then it is essentially ready to be
-- returned and popped off the heap. This will be the SSTG equivalent of having
-- Return vs Evaluate for the ExecCode of the `State`.
--
-- So in this context, the following are considered NOT-value forms:
-- `Var`, only if a lookup still available in the expression environment.
-- `App`, which involves pushing the RHS onto the `Stack`, if the center is not a Prim or DataCon
-- `Let`, which involves binding the binds into the eenv
-- `Case`, which involves pattern decomposition and stuff.
isExprValueForm :: E.ExprEnv -> Expr -> Bool
isExprValueForm eenv (Var var) =
E.lookup (idName var) eenv == Nothing || E.isSymbolic (idName var) eenv
isExprValueForm eenv (App f a) = case unApp (App f a) of
(Prim _ _:xs) -> all (isExprValueForm eenv) xs
(Data _:_) -> True
((Var _):_) -> False
_ -> False
isExprValueForm _ (Let _ _) = False
isExprValueForm _ (Case _ _ _ _) = False
isExprValueForm eenv (Cast e (t :~ _)) = not (hasFuncType t) && isExprValueForm eenv e
isExprValueForm _ (Tick _ _) = False
isExprValueForm _ (NonDet _) = False
isExprValueForm _ (SymGen _ _) = False
isExprValueForm _ (Assume _ _ _) = False
isExprValueForm _ (Assert _ _ _) = False
isExprValueForm _ _ = True
-- | Is the execution state in a value form of some sort? This would entail:
-- * The `Stack` is empty.
-- * The `ExecCode` is in a `Return` form.
-- * We have no path conds to reduce
isExecValueForm :: State t -> Bool
isExecValueForm state | Nothing <- S.pop (exec_stack state)
, CurrExpr Return _ <- curr_expr state
, non_red_path_conds state == [] = True
| otherwise = False
isExecValueFormDisNonRedPC :: State t -> Bool
isExecValueFormDisNonRedPC s = isExecValueForm $ s {non_red_path_conds = []}
normalForm :: E.ExprEnv -> Expr -> Bool
normalForm = normalForm' HS.empty
normalForm' :: HS.HashSet Name -> E.ExprEnv -> Expr -> Bool
normalForm' looked eenv (Var (Id n _))
| n `HS.member` looked = True
| Just e <- E.lookup n eenv = normalForm' (HS.insert n looked) eenv e
| otherwise = E.isSymbolic n eenv
normalForm' looked eenv (App f a) = case unApp (App f a) of
(Prim _ _:xs) -> all (normalForm' looked eenv) xs
(Data _:xs) -> all (normalForm' looked eenv) xs
((Var _):_) -> False
_ -> False
normalForm' _ _ (Let _ _) = False
normalForm' _ _ (Case _ _ _ _) = False
normalForm' looked eenv (Cast e (t :~ _)) = not (hasFuncType t) && normalForm' looked eenv e
normalForm' _ _ (Tick _ _) = False
normalForm' _ _ (NonDet _) = False
normalForm' _ _ (SymGen _ _) = False
normalForm' _ _ (Assume _ _ _) = False
normalForm' _ _ (Assert _ _ _) = False
normalForm' _ _ _ = True