{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ViewPatterns #-}

-- |
-- Module      :   Grisette.IR.SymPrim.Data.Prim.Helpers
-- Copyright   :   (c) Sirui Lu 2021-2023
-- License     :   BSD-3-Clause (see the LICENSE file)
--
-- Maintainer  :   siruilu@cs.washington.edu
-- Stability   :   Experimental
-- Portability :   GHC only
module Grisette.IR.SymPrim.Data.Prim.Helpers
  ( pattern UnaryTermPatt,
    pattern BinaryTermPatt,
    pattern TernaryTermPatt,
    pattern UnsafeUnaryTermPatt,
    pattern UnsafeBinaryTermPatt,
    pattern Unsafe1t21BinaryTermPatt,
    pattern Unsafe1u2t32TernaryTermPatt,
  )
where

import Data.Typeable
import Grisette.IR.SymPrim.Data.Prim.InternedTerm.Term
import Grisette.IR.SymPrim.Data.Prim.InternedTerm.TermUtils
import Unsafe.Coerce

unsafeUnaryTermView :: forall a b tag. (Typeable tag) => Term a -> Maybe (tag, Term b)
unsafeUnaryTermView :: forall a b tag. Typeable tag => Term a -> Maybe (tag, Term b)
unsafeUnaryTermView (UnaryTerm Id
_ (tag
tag :: tagt) Term arg
t1) =
  case forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast tag
tag of
    Just tag
t -> forall a. a -> Maybe a
Just (tag
t, forall a b. a -> b
unsafeCoerce Term arg
t1)
    Maybe tag
Nothing -> forall a. Maybe a
Nothing
-- (,) <$> cast tag <*> castTerm t1
unsafeUnaryTermView Term a
_ = forall a. Maybe a
Nothing

pattern UnsafeUnaryTermPatt :: forall a b tag. (Typeable tag) => tag -> Term b -> Term a
pattern $mUnsafeUnaryTermPatt :: forall {r} {a} {b} {tag}.
Typeable tag =>
Term a -> (tag -> Term b -> r) -> ((# #) -> r) -> r
UnsafeUnaryTermPatt tag t <- (unsafeUnaryTermView @a @b @tag -> Just (tag, t))

unaryTermView :: forall a b tag. (Typeable tag, Typeable b) => Term a -> Maybe (tag, Term b)
unaryTermView :: forall a b tag.
(Typeable tag, Typeable b) =>
Term a -> Maybe (tag, Term b)
unaryTermView (UnaryTerm Id
_ (tag
tag :: tagt) Term arg
t1) =
  (,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast tag
tag forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a b. Typeable b => Term a -> Maybe (Term b)
castTerm Term arg
t1
unaryTermView Term a
_ = forall a. Maybe a
Nothing

pattern UnaryTermPatt :: forall a b tag. (Typeable tag, Typeable b) => tag -> Term b -> Term a
pattern $mUnaryTermPatt :: forall {r} {a} {b} {tag}.
(Typeable tag, Typeable b) =>
Term a -> (tag -> Term b -> r) -> ((# #) -> r) -> r
UnaryTermPatt tag t <- (unaryTermView @a @b @tag -> Just (tag, t))

unsafeBinaryTermView :: forall a b c tag. (Typeable tag) => Term a -> Maybe (tag, Term b, Term c)
unsafeBinaryTermView :: forall a b c tag.
Typeable tag =>
Term a -> Maybe (tag, Term b, Term c)
unsafeBinaryTermView (BinaryTerm Id
_ (tag
tag :: tagt) Term arg1
t1 Term arg2
t2) =
  case forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast tag
tag of
    Just tag
t -> forall a. a -> Maybe a
Just (tag
t, forall a b. a -> b
unsafeCoerce Term arg1
t1, forall a b. a -> b
unsafeCoerce Term arg2
t2)
    Maybe tag
Nothing -> forall a. Maybe a
Nothing
-- (,) <$> cast tag <*> castTerm t1
unsafeBinaryTermView Term a
_ = forall a. Maybe a
Nothing

pattern UnsafeBinaryTermPatt :: forall a b c tag. (Typeable tag) => tag -> Term b -> Term c -> Term a
pattern $mUnsafeBinaryTermPatt :: forall {r} {a} {b} {c} {tag}.
Typeable tag =>
Term a -> (tag -> Term b -> Term c -> r) -> ((# #) -> r) -> r
UnsafeBinaryTermPatt tag t1 t2 <- (unsafeBinaryTermView @a @b @c @tag -> Just (tag, t1, t2))

unsafe1t21BinaryTermView :: forall a b tag. (Typeable tag, Typeable b) => Term a -> Maybe (tag, Term b, Term b)
unsafe1t21BinaryTermView :: forall a b tag.
(Typeable tag, Typeable b) =>
Term a -> Maybe (tag, Term b, Term b)
unsafe1t21BinaryTermView (BinaryTerm Id
_ (tag
tag :: tagt) Term arg1
t1 Term arg2
t2) =
  case (forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast tag
tag, forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast Term arg1
t1) of
    (Just tag
tg, Just Term b
t1') -> forall a. a -> Maybe a
Just (tag
tg, Term b
t1', forall a b. a -> b
unsafeCoerce Term arg2
t2)
    (Maybe tag, Maybe (Term b))
_ -> forall a. Maybe a
Nothing
-- (,) <$> cast tag <*> castTerm t1
unsafe1t21BinaryTermView Term a
_ = forall a. Maybe a
Nothing

pattern Unsafe1t21BinaryTermPatt :: forall a b tag. (Typeable tag, Typeable b) => tag -> Term b -> Term b -> Term a
pattern $mUnsafe1t21BinaryTermPatt :: forall {r} {a} {b} {tag}.
(Typeable tag, Typeable b) =>
Term a -> (tag -> Term b -> Term b -> r) -> ((# #) -> r) -> r
Unsafe1t21BinaryTermPatt tag t1 t2 <- (unsafe1t21BinaryTermView @a @b @tag -> Just (tag, t1, t2))

binaryTermView :: forall a b c tag. (Typeable tag, Typeable b, Typeable c) => Term a -> Maybe (tag, Term b, Term c)
binaryTermView :: forall a b c tag.
(Typeable tag, Typeable b, Typeable c) =>
Term a -> Maybe (tag, Term b, Term c)
binaryTermView (BinaryTerm Id
_ (tag
tag :: tagt) Term arg1
t1 Term arg2
t2) =
  (,,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast tag
tag forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a b. Typeable b => Term a -> Maybe (Term b)
castTerm Term arg1
t1 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a b. Typeable b => Term a -> Maybe (Term b)
castTerm Term arg2
t2
binaryTermView Term a
_ = forall a. Maybe a
Nothing

pattern BinaryTermPatt :: forall a b c tag. (Typeable tag, Typeable b, Typeable c) => tag -> Term b -> Term c -> Term a
pattern $mBinaryTermPatt :: forall {r} {a} {b} {c} {tag}.
(Typeable tag, Typeable b, Typeable c) =>
Term a -> (tag -> Term b -> Term c -> r) -> ((# #) -> r) -> r
BinaryTermPatt tag l r <- (binaryTermView @a @b @c @tag -> Just (tag, l, r))

unsafe1u2t32TernaryTermView ::
  forall a b c tag.
  (Typeable tag, Typeable c) =>
  Term a ->
  Maybe (tag, Term b, Term c, Term c)
unsafe1u2t32TernaryTermView :: forall a b c tag.
(Typeable tag, Typeable c) =>
Term a -> Maybe (tag, Term b, Term c, Term c)
unsafe1u2t32TernaryTermView (TernaryTerm Id
_ (tag
tag :: tagt) Term arg1
t1 Term arg2
t2 Term arg3
t3) =
  case (forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast tag
tag, forall a b. Typeable b => Term a -> Maybe (Term b)
castTerm Term arg2
t2) of
    (Just tag
tg, Just Term c
t2') -> forall a. a -> Maybe a
Just (tag
tg, forall a b. a -> b
unsafeCoerce Term arg1
t1, Term c
t2', forall a b. a -> b
unsafeCoerce Term arg3
t3)
    (Maybe tag, Maybe (Term c))
_ -> forall a. Maybe a
Nothing
unsafe1u2t32TernaryTermView Term a
_ = forall a. Maybe a
Nothing

pattern Unsafe1u2t32TernaryTermPatt ::
  forall a b c tag.
  (Typeable tag, Typeable c) =>
  tag ->
  Term b ->
  Term c ->
  Term c ->
  Term a
pattern $mUnsafe1u2t32TernaryTermPatt :: forall {r} {a} {b} {c} {tag}.
(Typeable tag, Typeable c) =>
Term a
-> (tag -> Term b -> Term c -> Term c -> r) -> ((# #) -> r) -> r
Unsafe1u2t32TernaryTermPatt tag a b c <-
  (unsafe1u2t32TernaryTermView @a @b @c @tag -> Just (tag, a, b, c))

ternaryTermView ::
  forall a b c d tag.
  (Typeable tag, Typeable b, Typeable c, Typeable d) =>
  Term a ->
  Maybe (tag, Term b, Term c, Term d)
ternaryTermView :: forall a b c d tag.
(Typeable tag, Typeable b, Typeable c, Typeable d) =>
Term a -> Maybe (tag, Term b, Term c, Term d)
ternaryTermView (TernaryTerm Id
_ (tag
tag :: tagt) Term arg1
t1 Term arg2
t2 Term arg3
t3) =
  (,,,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast tag
tag forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a b. Typeable b => Term a -> Maybe (Term b)
castTerm Term arg1
t1 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a b. Typeable b => Term a -> Maybe (Term b)
castTerm Term arg2
t2 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a b. Typeable b => Term a -> Maybe (Term b)
castTerm Term arg3
t3
ternaryTermView Term a
_ = forall a. Maybe a
Nothing

pattern TernaryTermPatt ::
  forall a b c d tag.
  (Typeable tag, Typeable b, Typeable c, Typeable d) =>
  tag ->
  Term b ->
  Term c ->
  Term d ->
  Term a
pattern $mTernaryTermPatt :: forall {r} {a} {b} {c} {d} {tag}.
(Typeable tag, Typeable b, Typeable c, Typeable d) =>
Term a
-> (tag -> Term b -> Term c -> Term d -> r) -> ((# #) -> r) -> r
TernaryTermPatt tag a b c <- (ternaryTermView @a @b @c @d @tag -> Just (tag, a, b, c))