{-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -- | Expression for 'Int'. module Language.LOL.Symantic.Expr.Int where import Data.Proxy (Proxy(..)) import Data.Type.Equality ((:~:)(Refl)) 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_Int' -- | Symantic. class Sym_Int repr where int :: Int -> repr Int neg :: repr Int -> repr Int add :: repr Int -> repr Int -> repr Int default int :: Trans t repr => Int -> t repr Int default neg :: Trans t repr => t repr Int -> t repr Int default add :: Trans t repr => t repr Int -> t repr Int -> t repr Int int = trans_lift . int neg = trans_map1 neg add = trans_map2 add instance -- Sym_Int Dup ( Sym_Int r1 , Sym_Int r2 ) => Sym_Int (Dup r1 r2) where int x = int x `Dup` int x neg (x1 `Dup` x2) = neg x1 `Dup` neg x2 add (x1 `Dup` x2) (y1 `Dup` y2) = add x1 y1 `Dup` add x2 y2 -- * Type 'Expr_Int' -- | Expression. data Expr_Int (root:: *) type instance Root_of_Expr (Expr_Int root) = root type instance Type_of_Expr (Expr_Int root) = Type_Int type instance Sym_of_Expr (Expr_Int root) repr = Sym_Int repr type instance Error_of_Expr ast (Expr_Int root) = () instance -- Expr_from AST Expr_Int ( Type_from AST (Type_Root_of_Expr root) , Expr_from AST root , Type_Root_Lift Type_Int (Type_Root_of_Expr root) , Error_Expr_Lift (Error_Expr (Error_of_Type AST (Type_Root_of_Expr root)) ( Type_Root_of_Expr root) AST) (Error_of_Expr AST root) , Type_Unlift Type_Int (Type_of_Expr root) , Root_of_Expr root ~ root , Implicit_HBool (Is_Last_Expr (Expr_Int root) root) ) => Expr_from AST (Expr_Int root) where expr_from px_ex ctx ast k = case ast of AST "int" asts -> case asts of [AST ast_int []] -> case read_safe ast_int of Left err -> Left $ error_expr px_ex $ Error_Expr_Read err ast Right (i::Int) -> k type_int $ Forall_Repr_with_Context $ const $ int i _ -> Left $ error_expr px_ex $ Error_Expr_Wrong_number_of_arguments ast 1 AST "neg" asts -> unary_from asts neg AST "add" asts -> binary_from asts add _ -> Left $ error_expr_unsupported px_ex ast where unary_from asts (op::forall repr. Sym_Int repr => repr Int -> repr Int) = case asts of [ast_x] -> expr_from (Proxy::Proxy root) ctx ast_x $ \ty_x (Forall_Repr_with_Context x) -> when_type_eq px_ex ast type_int ty_x $ \Refl -> k ty_x $ Forall_Repr_with_Context (op . x) _ -> Left $ error_expr px_ex $ Error_Expr_Wrong_number_of_arguments ast 1 binary_from asts (op::forall repr. Sym_Int repr => repr Int -> repr Int -> repr Int) = case asts of [ast_x, ast_y] -> expr_from (Proxy::Proxy root) ctx ast_x $ \ty_x (Forall_Repr_with_Context x) -> expr_from (Proxy::Proxy root) ctx ast_y $ \ty_y (Forall_Repr_with_Context y) -> when_type_eq px_ex ast type_int ty_x $ \Refl -> when_type_eq px_ex ast type_int ty_y $ \Refl -> k ty_x $ Forall_Repr_with_Context $ \c -> x c `op` y c _ -> Left $ error_expr px_ex $ Error_Expr_Wrong_number_of_arguments ast 2 -- ** Type 'Expr_Lambda_Int' -- | Convenient alias. type Expr_Lambda_Int lam = Expr_Root (Expr_Alt (Expr_Lambda lam) Expr_Int) -- | Convenient alias around 'expr_from'. expr_lambda_int_from :: forall lam ast. Expr_from ast (Expr_Lambda_Int lam) => Proxy lam -> ast -> Either (Error_of_Expr ast (Expr_Lambda_Int lam)) (Exists_Type_and_Repr (Type_Root_of_Expr (Expr_Lambda_Int lam)) (Forall_Repr (Expr_Lambda_Int lam))) expr_lambda_int_from _px_lam ast = expr_from (Proxy::Proxy (Expr_Lambda_Int lam)) Context_Empty ast $ \ty (Forall_Repr_with_Context repr) -> Right $ Exists_Type_and_Repr ty $ Forall_Repr $ repr Context_Empty