{-# LANGUAGE OverloadedStrings #-} module SMR.Prim.Op.Bool where import SMR.Core.Exp import SMR.Prim.Op.Base import Data.Text (Text) -- | Primitive evaluators for boolean operators. primOpsBool :: [PrimEval s Prim w] primOpsBool = [ primOpBool1 "not" "boolean negation" (\b -> not b) , primOpBool2 "and" "boolean and" (&&) , primOpBool2 "or" "boolean or" (||) , primOpIf ] -- | Construct an evaluator for 1-arity bool operator. primOpBool1 :: Name -> Text -> (Bool -> Bool) -> PrimEval s Prim w primOpBool1 name desc fn = PrimEval (PrimOp name) desc [PVal] fn' where fn' _world as0 | Just (b1, []) <- takeArgBool as0 = return $ Just $ makeXBool (fn b1) fn' _world _ = return $ Nothing -- | Construct an evaluator for 2-arity bool operator. primOpBool2 :: Name -> Text -> (Bool -> Bool -> Bool) -> PrimEval s Prim w primOpBool2 name desc fn = PrimEval (PrimOp name) desc [PVal, PVal] fn' where fn' _world as0 | Just (b1, as1) <- takeArgBool as0 , Just (b2, []) <- takeArgBool as1 = return $ Just $ makeXBool (fn b1 b2) fn' _world _ = return $ Nothing -- | Primitive evaluator for the #if operator. -- Only the scrutinee is demanded, while the branches are not. primOpIf :: PrimEval s Prim w primOpIf = PrimEval (PrimOp "if") "boolean if-then-else operator" [PVal, PExp, PExp] fn' where fn' _world as0 | Just (b1, as1) <- takeArgBool as0 , Just (x1, as2) <- takeArgExp as1 , Just (x2, []) <- takeArgExp as2 = return $ Just $ if b1 then x1 else x2 fn' _world _ = return $ Nothing