{-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -- | Expression for 'Bool's. module Language.LOL.Symantic.Expr.Bool where import Data.Proxy (Proxy(..)) import Prelude hiding (and, not, or) import Language.LOL.Symantic.AST import Language.LOL.Symantic.Type import Language.LOL.Symantic.Expr.Common import Language.LOL.Symantic.Expr.Lambda import Language.LOL.Symantic.Repr.Dup import Language.LOL.Symantic.Trans.Common -- * Class 'Sym_Bool' -- | Symantic. class Sym_Bool repr where bool :: Bool -> repr Bool not :: repr Bool -> repr Bool and :: repr Bool -> repr Bool -> repr Bool or :: repr Bool -> repr Bool -> repr Bool xor :: repr Bool -> repr Bool -> repr Bool xor x y = (x `or` y) `and` not (x `and` y) default bool :: Trans t repr => Bool -> t repr Bool default not :: Trans t repr => t repr Bool -> t repr Bool default and :: Trans t repr => t repr Bool -> t repr Bool -> t repr Bool default or :: Trans t repr => t repr Bool -> t repr Bool -> t repr Bool bool = trans_lift . bool not = trans_map1 not and = trans_map2 and or = trans_map2 or instance -- Sym_Bool Dup ( Sym_Bool r1 , Sym_Bool r2 ) => Sym_Bool (Dup r1 r2) where bool x = bool x `Dup` bool x not (x1 `Dup` x2) = not x1 `Dup` not x2 and (x1 `Dup` x2) (y1 `Dup` y2) = and x1 y1 `Dup` and x2 y2 or (x1 `Dup` x2) (y1 `Dup` y2) = or x1 y1 `Dup` or x2 y2 xor (x1 `Dup` x2) (y1 `Dup` y2) = xor x1 y1 `Dup` xor x2 y2 -- * Type 'Expr_Bool' -- | Expression. data Expr_Bool (root:: *) type instance Root_of_Expr (Expr_Bool root) = root type instance Type_of_Expr (Expr_Bool root) = Type_Bool type instance Sym_of_Expr (Expr_Bool root) repr = Sym_Bool repr type instance Error_of_Expr ast (Expr_Bool root) = Error_Expr_Bool ast instance -- Expr_from AST Expr_Bool ( Type_from AST (Type_Root_of_Expr root) , Expr_from AST root , Type_Root_Lift Type_Bool (Type_Root_of_Expr root) , Error_Type_Lift (Error_Type_Fun AST) (Error_of_Type AST (Type_Root_of_Expr root)) , Error_Expr_Lift (Error_Expr_Lambda (Error_of_Type AST (Type_Root_of_Expr root)) ( Type_Root_of_Expr root) AST) (Error_of_Expr AST root) , Error_Expr_Lift (Error_Expr AST) (Error_of_Expr AST root) , Type_Unlift Type_Bool (Type_of_Expr root) , Root_of_Expr root ~ root , Implicit_HBool (Is_Last_Expr (Expr_Bool root) root) ) => Expr_from AST (Expr_Bool root) where expr_from _px_ex ctx ast k = case ast of AST "bool" asts -> case asts of [AST ast_bool []] -> case read_safe ast_bool of Left err -> Left $ error_expr_lift $ Error_Expr_Read err ast Right (i::Bool) -> k type_bool $ Forall_Repr_with_Context $ const $ bool i _ -> Left $ error_lambda_lift $ Error_Expr_Fun_Wrong_number_of_arguments 3 ast AST "not" asts -> unary_from asts not AST "and" asts -> binary_from asts and AST "or" asts -> binary_from asts or AST "xor" asts -> binary_from asts xor -- _ -> Left $ error_expr_lift $ Error_Expr_Unsupported_here ast _ -> Left $ case hbool :: HBool (Is_Last_Expr (Expr_Bool root) root) of HTrue -> error_expr_lift $ Error_Expr_Unsupported ast HFalse -> error_expr_lift $ Error_Expr_Unsupported_here ast where unary_from asts (op::forall repr. Sym_Bool repr => repr Bool -> repr Bool) = case asts of [ast_x] -> expr_from (Proxy::Proxy root) ctx ast_x $ \(ty_x::Type_Root_of_Expr root h_x) (Forall_Repr_with_Context x) -> case type_unlift $ unType_Root ty_x of Just (Type_Bool::Type_Bool (Type_Root_of_Expr root) h_x) -> k ty_x $ Forall_Repr_with_Context (op . x) _ -> Left $ error_lambda_lift $ Error_Expr_Fun_Argument_mismatch (Exists_Type type_bool) (Exists_Type ty_x) ast _ -> Left $ error_lambda_lift $ Error_Expr_Fun_Wrong_number_of_arguments 1 ast binary_from asts (op::forall repr. Sym_Bool repr => repr Bool -> repr Bool -> repr Bool) = case asts of [ast_x, ast_y] -> expr_from (Proxy::Proxy root) ctx ast_x $ \(ty_x::Type_Root_of_Expr root h_x) (Forall_Repr_with_Context x) -> expr_from (Proxy::Proxy root) ctx ast_y $ \(ty_y::Type_Root_of_Expr root h_y) (Forall_Repr_with_Context y) -> case type_unlift $ unType_Root ty_x of Just (Type_Bool::Type_Bool (Type_Root_of_Expr root) h_x) -> case type_unlift $ unType_Root ty_y of Just (Type_Bool::Type_Bool (Type_Root_of_Expr root) h_y) -> k ty_x $ Forall_Repr_with_Context $ \c -> x c `op` y c Nothing -> Left $ error_lambda_lift $ Error_Expr_Fun_Argument_mismatch (Exists_Type type_bool) (Exists_Type ty_y) ast Nothing -> Left $ error_lambda_lift $ Error_Expr_Fun_Argument_mismatch (Exists_Type type_bool) (Exists_Type ty_x) ast _ -> Left $ error_lambda_lift $ Error_Expr_Fun_Wrong_number_of_arguments 2 ast error_lambda_lift :: Error_Expr_Lambda (Error_of_Type AST (Type_Root_of_Expr root)) (Type_Root_of_Expr root) AST -> Error_of_Expr AST root error_lambda_lift = error_expr_lift -- ** Type 'Expr_Lambda_Bool' -- | Convenient alias. type Expr_Lambda_Bool lam = Expr_Root (Expr_Cons (Expr_Lambda lam) Expr_Bool) expr_lambda_bool_from :: forall lam ast. Expr_from ast (Expr_Lambda_Bool lam) => Proxy lam -> ast -> Either (Error_of_Expr ast (Expr_Lambda_Bool lam)) (Exists_Type_and_Repr (Type_Root_of_Expr (Expr_Lambda_Bool lam)) (Forall_Repr (Expr_Lambda_Bool lam))) expr_lambda_bool_from _px_lam ast = expr_from (Proxy::Proxy (Expr_Lambda_Bool lam)) Context_Empty ast $ \ty (Forall_Repr_with_Context repr) -> Right $ Exists_Type_and_Repr ty $ Forall_Repr $ repr Context_Empty -- * Type 'Error_Expr_Bool' data Error_Expr_Bool ast = Error_Expr_Bool deriving (Eq, Show)