{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}

module DataFrame.Internal.Expression where

import Control.DeepSeq (NFData (..))
import Data.String
import qualified Data.Text as T
import Data.Type.Equality (TestEquality (testEquality), type (:~:) (Refl))
import qualified Data.Vector.Generic as VG
import DataFrame.Internal.Column
import Type.Reflection (Typeable, typeOf, typeRep)

data UnaryOp a b = MkUnaryOp
    { forall a b. UnaryOp a b -> a -> b
unaryFn :: a -> b
    , forall a b. UnaryOp a b -> Text
unaryName :: T.Text
    , forall a b. UnaryOp a b -> Maybe Text
unarySymbol :: Maybe T.Text
    }

data BinaryOp a b c = MkBinaryOp
    { forall a b c. BinaryOp a b c -> a -> b -> c
binaryFn :: a -> b -> c
    , forall a b c. BinaryOp a b c -> Text
binaryName :: T.Text
    , forall a b c. BinaryOp a b c -> Maybe Text
binarySymbol :: Maybe T.Text
    , forall a b c. BinaryOp a b c -> Bool
binaryCommutative :: Bool
    , forall a b c. BinaryOp a b c -> Int
binaryPrecedence :: Int
    }

data MeanAcc = MeanAcc {-# UNPACK #-} !Double {-# UNPACK #-} !Int
    deriving (Int -> MeanAcc -> ShowS
[MeanAcc] -> ShowS
MeanAcc -> String
(Int -> MeanAcc -> ShowS)
-> (MeanAcc -> String) -> ([MeanAcc] -> ShowS) -> Show MeanAcc
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MeanAcc -> ShowS
showsPrec :: Int -> MeanAcc -> ShowS
$cshow :: MeanAcc -> String
show :: MeanAcc -> String
$cshowList :: [MeanAcc] -> ShowS
showList :: [MeanAcc] -> ShowS
Show, MeanAcc -> MeanAcc -> Bool
(MeanAcc -> MeanAcc -> Bool)
-> (MeanAcc -> MeanAcc -> Bool) -> Eq MeanAcc
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MeanAcc -> MeanAcc -> Bool
== :: MeanAcc -> MeanAcc -> Bool
$c/= :: MeanAcc -> MeanAcc -> Bool
/= :: MeanAcc -> MeanAcc -> Bool
Eq, Eq MeanAcc
Eq MeanAcc =>
(MeanAcc -> MeanAcc -> Ordering)
-> (MeanAcc -> MeanAcc -> Bool)
-> (MeanAcc -> MeanAcc -> Bool)
-> (MeanAcc -> MeanAcc -> Bool)
-> (MeanAcc -> MeanAcc -> Bool)
-> (MeanAcc -> MeanAcc -> MeanAcc)
-> (MeanAcc -> MeanAcc -> MeanAcc)
-> Ord MeanAcc
MeanAcc -> MeanAcc -> Bool
MeanAcc -> MeanAcc -> Ordering
MeanAcc -> MeanAcc -> MeanAcc
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: MeanAcc -> MeanAcc -> Ordering
compare :: MeanAcc -> MeanAcc -> Ordering
$c< :: MeanAcc -> MeanAcc -> Bool
< :: MeanAcc -> MeanAcc -> Bool
$c<= :: MeanAcc -> MeanAcc -> Bool
<= :: MeanAcc -> MeanAcc -> Bool
$c> :: MeanAcc -> MeanAcc -> Bool
> :: MeanAcc -> MeanAcc -> Bool
$c>= :: MeanAcc -> MeanAcc -> Bool
>= :: MeanAcc -> MeanAcc -> Bool
$cmax :: MeanAcc -> MeanAcc -> MeanAcc
max :: MeanAcc -> MeanAcc -> MeanAcc
$cmin :: MeanAcc -> MeanAcc -> MeanAcc
min :: MeanAcc -> MeanAcc -> MeanAcc
Ord, ReadPrec [MeanAcc]
ReadPrec MeanAcc
Int -> ReadS MeanAcc
ReadS [MeanAcc]
(Int -> ReadS MeanAcc)
-> ReadS [MeanAcc]
-> ReadPrec MeanAcc
-> ReadPrec [MeanAcc]
-> Read MeanAcc
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS MeanAcc
readsPrec :: Int -> ReadS MeanAcc
$creadList :: ReadS [MeanAcc]
readList :: ReadS [MeanAcc]
$creadPrec :: ReadPrec MeanAcc
readPrec :: ReadPrec MeanAcc
$creadListPrec :: ReadPrec [MeanAcc]
readListPrec :: ReadPrec [MeanAcc]
Read)

instance NFData MeanAcc where
    rnf :: MeanAcc -> ()
rnf (MeanAcc Double
_ Int
_) = ()

data AggStrategy a b where
    CollectAgg ::
        (VG.Vector v b, Typeable v) => T.Text -> (v b -> a) -> AggStrategy a b
    FoldAgg :: T.Text -> Maybe a -> (a -> b -> a) -> AggStrategy a b
    MergeAgg ::
        (Columnable acc) =>
        T.Text ->
        acc ->
        (acc -> b -> acc) ->
        (acc -> acc -> acc) ->
        (acc -> a) ->
        AggStrategy a b

data Expr a where
    Col :: (Columnable a) => T.Text -> Expr a
    Lit :: (Columnable a) => a -> Expr a
    Unary ::
        (Columnable a, Columnable b) => UnaryOp b a -> Expr b -> Expr a
    Binary ::
        (Columnable c, Columnable b, Columnable a) =>
        BinaryOp c b a -> Expr c -> Expr b -> Expr a
    If :: (Columnable a) => Expr Bool -> Expr a -> Expr a -> Expr a
    Agg :: (Columnable a, Columnable b) => AggStrategy a b -> Expr b -> Expr a

data UExpr where
    UExpr :: (Columnable a) => Expr a -> UExpr

instance Show UExpr where
    show :: UExpr -> String
    show :: UExpr -> String
show (UExpr Expr a
expr) = Expr a -> String
forall a. Show a => a -> String
show Expr a
expr

type NamedExpr = (T.Text, UExpr)

instance (Num a, Columnable a) => Num (Expr a) where
    (+) :: Expr a -> Expr a -> Expr a
    + :: Expr a -> Expr a -> Expr a
(+) =
        BinaryOp a a a -> Expr a -> Expr a -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
BinaryOp b b a -> Expr b -> Expr b -> Expr a
Binary
            ( MkBinaryOp
                { binaryFn :: a -> a -> a
binaryFn = a -> a -> a
forall a. Num a => a -> a -> a
(+)
                , binaryName :: Text
binaryName = Text
"add"
                , binarySymbol :: Maybe Text
binarySymbol = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"+"
                , binaryCommutative :: Bool
binaryCommutative = Bool
True
                , binaryPrecedence :: Int
binaryPrecedence = Int
6
                }
            )

    (-) :: Expr a -> Expr a -> Expr a
    (-) =
        BinaryOp a a a -> Expr a -> Expr a -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
BinaryOp b b a -> Expr b -> Expr b -> Expr a
Binary
            ( MkBinaryOp
                { binaryFn :: a -> a -> a
binaryFn = (-)
                , binaryName :: Text
binaryName = Text
"sub"
                , binarySymbol :: Maybe Text
binarySymbol = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"-"
                , binaryCommutative :: Bool
binaryCommutative = Bool
False
                , binaryPrecedence :: Int
binaryPrecedence = Int
6
                }
            )

    (*) :: Expr a -> Expr a -> Expr a
    * :: Expr a -> Expr a -> Expr a
(*) =
        BinaryOp a a a -> Expr a -> Expr a -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
BinaryOp b b a -> Expr b -> Expr b -> Expr a
Binary
            ( MkBinaryOp
                { binaryFn :: a -> a -> a
binaryFn = a -> a -> a
forall a. Num a => a -> a -> a
(*)
                , binaryName :: Text
binaryName = Text
"mult"
                , binarySymbol :: Maybe Text
binarySymbol = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"*"
                , binaryCommutative :: Bool
binaryCommutative = Bool
True
                , binaryPrecedence :: Int
binaryPrecedence = Int
7
                }
            )

    fromInteger :: Integer -> Expr a
    fromInteger :: Integer -> Expr a
fromInteger = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit (a -> Expr a) -> (Integer -> a) -> Integer -> Expr a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> a
forall a. Num a => Integer -> a
fromInteger

    negate :: Expr a -> Expr a
    negate :: Expr a -> Expr a
negate =
        UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary
            (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Num a => a -> a
negate, unaryName :: Text
unaryName = Text
"negate", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})

    abs :: (Num a) => Expr a -> Expr a
    abs :: Num a => Expr a -> Expr a
abs = UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Num a => a -> a
abs, unaryName :: Text
unaryName = Text
"abs", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})

    signum :: (Num a) => Expr a -> Expr a
    signum :: Num a => Expr a -> Expr a
signum =
        UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary
            (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Num a => a -> a
signum, unaryName :: Text
unaryName = Text
"signum", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})

add :: (Num a, Columnable a) => Expr a -> Expr a -> Expr a
add :: forall a. (Num a, Columnable a) => Expr a -> Expr a -> Expr a
add = Expr a -> Expr a -> Expr a
forall a. Num a => a -> a -> a
(+)

sub :: (Num a, Columnable a) => Expr a -> Expr a -> Expr a
sub :: forall a. (Num a, Columnable a) => Expr a -> Expr a -> Expr a
sub = (-)

mult :: (Num a, Columnable a) => Expr a -> Expr a -> Expr a
mult :: forall a. (Num a, Columnable a) => Expr a -> Expr a -> Expr a
mult = Expr a -> Expr a -> Expr a
forall a. Num a => a -> a -> a
(*)

instance (Fractional a, Columnable a) => Fractional (Expr a) where
    fromRational :: (Fractional a, Columnable a) => Rational -> Expr a
    fromRational :: (Fractional a, Columnable a) => Rational -> Expr a
fromRational = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit (a -> Expr a) -> (Rational -> a) -> Rational -> Expr a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> a
forall a. Fractional a => Rational -> a
fromRational

    (/) :: (Fractional a, Columnable a) => Expr a -> Expr a -> Expr a
    / :: (Fractional a, Columnable a) => Expr a -> Expr a -> Expr a
(/) =
        BinaryOp a a a -> Expr a -> Expr a -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
BinaryOp b b a -> Expr b -> Expr b -> Expr a
Binary
            ( MkBinaryOp
                { binaryFn :: a -> a -> a
binaryFn = a -> a -> a
forall a. Fractional a => a -> a -> a
(/)
                , binaryName :: Text
binaryName = Text
"divide"
                , binarySymbol :: Maybe Text
binarySymbol = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"/"
                , binaryCommutative :: Bool
binaryCommutative = Bool
False
                , binaryPrecedence :: Int
binaryPrecedence = Int
7
                }
            )

divide :: (Fractional a, Columnable a) => Expr a -> Expr a -> Expr a
divide :: forall a.
(Fractional a, Columnable a) =>
Expr a -> Expr a -> Expr a
divide = Expr a -> Expr a -> Expr a
forall a. Fractional a => a -> a -> a
(/)

instance (IsString a, Columnable a) => IsString (Expr a) where
    fromString :: String -> Expr a
    fromString :: String -> Expr a
fromString String
s = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit (String -> a
forall a. IsString a => String -> a
fromString String
s)

instance (Floating a, Columnable a) => Floating (Expr a) where
    pi :: (Floating a, Columnable a) => Expr a
    pi :: (Floating a, Columnable a) => Expr a
pi = a -> Expr a
forall a. Columnable a => a -> Expr a
Lit a
forall a. Floating a => a
pi
    exp :: (Floating a, Columnable a) => Expr a -> Expr a
    exp :: (Floating a, Columnable a) => Expr a -> Expr a
exp = UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
exp, unaryName :: Text
unaryName = Text
"exp", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})
    sqrt :: (Floating a, Columnable a) => Expr a -> Expr a
    sqrt :: (Floating a, Columnable a) => Expr a -> Expr a
sqrt =
        UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
sqrt, unaryName :: Text
unaryName = Text
"sqrt", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})
    (**) :: (Floating a, Columnable a) => Expr a -> Expr a -> Expr a
    ** :: (Floating a, Columnable a) => Expr a -> Expr a -> Expr a
(**) =
        BinaryOp a a a -> Expr a -> Expr a -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
BinaryOp b b a -> Expr b -> Expr b -> Expr a
Binary
            ( MkBinaryOp
                { binaryFn :: a -> a -> a
binaryFn = a -> a -> a
forall a. Floating a => a -> a -> a
(**)
                , binaryName :: Text
binaryName = Text
"exponentiate"
                , binarySymbol :: Maybe Text
binarySymbol = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"**"
                , binaryCommutative :: Bool
binaryCommutative = Bool
False
                , binaryPrecedence :: Int
binaryPrecedence = Int
8
                }
            )
    log :: (Floating a, Columnable a) => Expr a -> Expr a
    log :: (Floating a, Columnable a) => Expr a -> Expr a
log = UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
log, unaryName :: Text
unaryName = Text
"log", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})
    logBase :: (Floating a, Columnable a) => Expr a -> Expr a -> Expr a
    logBase :: (Floating a, Columnable a) => Expr a -> Expr a -> Expr a
logBase =
        BinaryOp a a a -> Expr a -> Expr a -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
BinaryOp b b a -> Expr b -> Expr b -> Expr a
Binary
            ( MkBinaryOp
                { binaryFn :: a -> a -> a
binaryFn = a -> a -> a
forall a. Floating a => a -> a -> a
logBase
                , binaryName :: Text
binaryName = Text
"logBase"
                , binarySymbol :: Maybe Text
binarySymbol = Maybe Text
forall a. Maybe a
Nothing
                , binaryCommutative :: Bool
binaryCommutative = Bool
False
                , binaryPrecedence :: Int
binaryPrecedence = Int
1
                }
            )
    sin :: (Floating a, Columnable a) => Expr a -> Expr a
    sin :: (Floating a, Columnable a) => Expr a -> Expr a
sin = UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
sin, unaryName :: Text
unaryName = Text
"sin", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})
    cos :: (Floating a, Columnable a) => Expr a -> Expr a
    cos :: (Floating a, Columnable a) => Expr a -> Expr a
cos = UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
cos, unaryName :: Text
unaryName = Text
"cos", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})
    tan :: (Floating a, Columnable a) => Expr a -> Expr a
    tan :: (Floating a, Columnable a) => Expr a -> Expr a
tan = UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
tan, unaryName :: Text
unaryName = Text
"tan", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})
    asin :: (Floating a, Columnable a) => Expr a -> Expr a
    asin :: (Floating a, Columnable a) => Expr a -> Expr a
asin =
        UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
asin, unaryName :: Text
unaryName = Text
"asin", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})
    acos :: (Floating a, Columnable a) => Expr a -> Expr a
    acos :: (Floating a, Columnable a) => Expr a -> Expr a
acos =
        UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
acos, unaryName :: Text
unaryName = Text
"acos", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})
    atan :: (Floating a, Columnable a) => Expr a -> Expr a
    atan :: (Floating a, Columnable a) => Expr a -> Expr a
atan =
        UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
atan, unaryName :: Text
unaryName = Text
"atan", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})
    sinh :: (Floating a, Columnable a) => Expr a -> Expr a
    sinh :: (Floating a, Columnable a) => Expr a -> Expr a
sinh =
        UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
sinh, unaryName :: Text
unaryName = Text
"sinh", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})
    cosh :: (Floating a, Columnable a) => Expr a -> Expr a
    cosh :: (Floating a, Columnable a) => Expr a -> Expr a
cosh =
        UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
cosh, unaryName :: Text
unaryName = Text
"cosh", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})
    asinh :: (Floating a, Columnable a) => Expr a -> Expr a
    asinh :: (Floating a, Columnable a) => Expr a -> Expr a
asinh =
        UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary
            (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
asinh, unaryName :: Text
unaryName = Text
"asinh", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})
    acosh :: (Floating a, Columnable a) => Expr a -> Expr a
    acosh :: (Floating a, Columnable a) => Expr a -> Expr a
acosh =
        UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary
            (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
acosh, unaryName :: Text
unaryName = Text
"acosh", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})
    atanh :: (Floating a, Columnable a) => Expr a -> Expr a
    atanh :: (Floating a, Columnable a) => Expr a -> Expr a
atanh =
        UnaryOp a a -> Expr a -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary
            (MkUnaryOp{unaryFn :: a -> a
unaryFn = a -> a
forall a. Floating a => a -> a
atanh, unaryName :: Text
unaryName = Text
"atanh", unarySymbol :: Maybe Text
unarySymbol = Maybe Text
forall a. Maybe a
Nothing})

instance (Show a) => Show (Expr a) where
    show :: forall a. (Show a) => Expr a -> String
    show :: forall a. Show a => Expr a -> String
show (Col Text
name) = String
"(col @" String -> ShowS
forall a. [a] -> [a] -> [a]
++ TypeRep a -> String
forall a. Show a => a -> String
show (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
forall a. Show a => a -> String
show Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (Lit a
value) = String
"(lit (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
value String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"))"
    show (If Expr Bool
cond Expr a
l Expr a
r) = String
"(ifThenElse " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr Bool -> String
forall a. Show a => a -> String
show Expr Bool
cond String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr a -> String
forall a. Show a => a -> String
show Expr a
l String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr a -> String
forall a. Show a => a -> String
show Expr a
r String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (Unary UnaryOp b a
op Expr b
value) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack (UnaryOp b a -> Text
forall a b. UnaryOp a b -> Text
unaryName UnaryOp b a
op) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Show a => a -> String
show Expr b
value String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (Binary BinaryOp c b a
op Expr c
a Expr b
b) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack (BinaryOp c b a -> Text
forall a b c. BinaryOp a b c -> Text
binaryName BinaryOp c b a
op) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr c -> String
forall a. Show a => a -> String
show Expr c
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Show a => a -> String
show Expr b
b String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (Agg (CollectAgg Text
op v b -> a
_) Expr b
expr) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
op String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Show a => a -> String
show Expr b
expr String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (Agg (FoldAgg Text
op Maybe a
_ a -> b -> a
_) Expr b
expr) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
op String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Show a => a -> String
show Expr b
expr String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
    show (Agg (MergeAgg Text
op acc
_ acc -> b -> acc
_ acc -> acc -> acc
_ acc -> a
_) Expr b
expr) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
op String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Show a => a -> String
show Expr b
expr String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"

normalize :: (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize :: forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr a
expr = case Expr a
expr of
    Col Text
name -> Text -> Expr a
forall a. Columnable a => Text -> Expr a
Col Text
name
    Lit a
val -> a -> Expr a
forall a. Columnable a => a -> Expr a
Lit a
val
    If Expr Bool
cond Expr a
th Expr a
el -> Expr Bool -> Expr a -> Expr a -> Expr a
forall a. Columnable a => Expr Bool -> Expr a -> Expr a -> Expr a
If (Expr Bool -> Expr Bool
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr Bool
cond) (Expr a -> Expr a
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr a
th) (Expr a -> Expr a
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr a
el)
    Unary UnaryOp b a
op Expr b
e -> UnaryOp b a -> Expr b -> Expr a
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary UnaryOp b a
op (Expr b -> Expr b
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr b
e)
    Binary BinaryOp c b a
op Expr c
e1 Expr b
e2
        | BinaryOp c b a -> Bool
forall a b c. BinaryOp a b c -> Bool
binaryCommutative BinaryOp c b a
op ->
            let n1 :: Expr c
n1 = Expr c -> Expr c
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr c
e1
                n2 :: Expr b
n2 = Expr b -> Expr b
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr b
e2
             in case TypeRep (Expr c) -> TypeRep (Expr b) -> Maybe (Expr c :~: Expr b)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (Expr c -> TypeRep (Expr c)
forall a. Typeable a => a -> TypeRep a
typeOf Expr c
n1) (Expr b -> TypeRep (Expr b)
forall a. Typeable a => a -> TypeRep a
typeOf Expr b
n2) of
                    Maybe (Expr c :~: Expr b)
Nothing -> Expr a
expr
                    Just Expr c :~: Expr b
Refl ->
                        if Expr c -> Expr c -> Ordering
forall a. Expr a -> Expr a -> Ordering
compareExpr Expr c
n1 Expr c
Expr b
n2 Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
GT
                            then BinaryOp c b a -> Expr c -> Expr b -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
BinaryOp b b a -> Expr b -> Expr b -> Expr a
Binary BinaryOp c b a
op Expr c
Expr b
n2 Expr c
Expr b
n1 -- Swap to canonical order
                            else BinaryOp c b a -> Expr c -> Expr b -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
BinaryOp b b a -> Expr b -> Expr b -> Expr a
Binary BinaryOp c b a
op Expr c
n1 Expr b
n2
        | Bool
otherwise -> BinaryOp c b a -> Expr c -> Expr b -> Expr a
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
BinaryOp b b a -> Expr b -> Expr b -> Expr a
Binary BinaryOp c b a
op (Expr c -> Expr c
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr c
e1) (Expr b -> Expr b
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr b
e2)
    Agg AggStrategy a b
strat Expr b
e -> AggStrategy a b -> Expr b -> Expr a
forall a b.
(Columnable a, Columnable b) =>
AggStrategy a b -> Expr b -> Expr a
Agg AggStrategy a b
strat (Expr b -> Expr b
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr b
e)

-- Compare expressions for ordering (used in normalization)
compareExpr :: Expr a -> Expr a -> Ordering
compareExpr :: forall a. Expr a -> Expr a -> Ordering
compareExpr Expr a
e1 Expr a
e2 = String -> String -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Expr a -> String
forall a. Expr a -> String
exprKey Expr a
e1) (Expr a -> String
forall a. Expr a -> String
exprKey Expr a
e2)
  where
    exprKey :: Expr a -> String
    exprKey :: forall a. Expr a -> String
exprKey (Col Text
name) = String
"0:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name
    exprKey (Lit a
val) = String
"1:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
val
    exprKey (If Expr Bool
c Expr a
t Expr a
e) = String
"2:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr Bool -> String
forall a. Expr a -> String
exprKey Expr Bool
c String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr a -> String
forall a. Expr a -> String
exprKey Expr a
t String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr a -> String
forall a. Expr a -> String
exprKey Expr a
e
    exprKey (Unary UnaryOp b a
op Expr b
e) = String
"3:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack (UnaryOp b a -> Text
forall a b. UnaryOp a b -> Text
unaryName UnaryOp b a
op) String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Expr a -> String
exprKey Expr b
e
    exprKey (Binary BinaryOp c b a
op Expr c
e1 Expr b
e2) = String
"4:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack (BinaryOp c b a -> Text
forall a b c. BinaryOp a b c -> Text
binaryName BinaryOp c b a
op) String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr c -> String
forall a. Expr a -> String
exprKey Expr c
e1 String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Expr a -> String
exprKey Expr b
e2
    exprKey (Agg (CollectAgg Text
name v b -> a
_) Expr b
e) = String
"5:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Expr a -> String
exprKey Expr b
e
    exprKey (Agg (FoldAgg Text
name Maybe a
_ a -> b -> a
_) Expr b
e) = String
"5:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Expr a -> String
exprKey Expr b
e
    exprKey (Agg (MergeAgg Text
name acc
_ acc -> b -> acc
_ acc -> acc -> acc
_ acc -> a
_) Expr b
e) = String
"5:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr b -> String
forall a. Expr a -> String
exprKey Expr b
e

instance (Eq a, Columnable a) => Eq (Expr a) where
    == :: Expr a -> Expr a -> Bool
(==) Expr a
l Expr a
r = Expr a -> Expr a -> Bool
eqNormalized (Expr a -> Expr a
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr a
l) (Expr a -> Expr a
forall a. (Eq a, Ord a, Show a, Typeable a) => Expr a -> Expr a
normalize Expr a
r)
      where
        exprEq :: (Columnable b, Columnable c) => Expr b -> Expr c -> Bool
        exprEq :: forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
exprEq Expr b
e1 Expr c
e2 = case TypeRep (Expr b) -> TypeRep (Expr c) -> Maybe (Expr b :~: Expr c)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (Expr b -> TypeRep (Expr b)
forall a. Typeable a => a -> TypeRep a
typeOf Expr b
e1) (Expr c -> TypeRep (Expr c)
forall a. Typeable a => a -> TypeRep a
typeOf Expr c
e2) of
            Just Expr b :~: Expr c
Refl -> Expr b
e1 Expr b -> Expr b -> Bool
forall a. Eq a => a -> a -> Bool
== Expr b
Expr c
e2
            Maybe (Expr b :~: Expr c)
Nothing -> Bool
False
        eqNormalized :: Expr a -> Expr a -> Bool
        eqNormalized :: Expr a -> Expr a -> Bool
eqNormalized (Col Text
n1) (Col Text
n2) = Text
n1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
n2
        eqNormalized (Lit a
v1) (Lit a
v2) = a
v1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
v2
        eqNormalized (If Expr Bool
c1 Expr a
t1 Expr a
e1) (If Expr Bool
c2 Expr a
t2 Expr a
e2) =
            Expr Bool
c1 Expr Bool -> Expr Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Expr Bool
c2 Bool -> Bool -> Bool
&& Expr a
t1 Expr a -> Expr a -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr a
t2 Bool -> Bool -> Bool
&& Expr a
e1 Expr a -> Expr a -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr a
e2
        eqNormalized (Unary UnaryOp b a
op1 Expr b
e1) (Unary UnaryOp b a
op2 Expr b
e2) = UnaryOp b a -> Text
forall a b. UnaryOp a b -> Text
unaryName UnaryOp b a
op1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== UnaryOp b a -> Text
forall a b. UnaryOp a b -> Text
unaryName UnaryOp b a
op2 Bool -> Bool -> Bool
&& Expr b
e1 Expr b -> Expr b -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr b
e2
        eqNormalized (Binary BinaryOp c b a
op1 Expr c
e1a Expr b
e1b) (Binary BinaryOp c b a
op2 Expr c
e2a Expr b
e2b) = BinaryOp c b a -> Text
forall a b c. BinaryOp a b c -> Text
binaryName BinaryOp c b a
op1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== BinaryOp c b a -> Text
forall a b c. BinaryOp a b c -> Text
binaryName BinaryOp c b a
op2 Bool -> Bool -> Bool
&& Expr c
e1a Expr c -> Expr c -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr c
e2a Bool -> Bool -> Bool
&& Expr b
e1b Expr b -> Expr b -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr b
e2b
        eqNormalized (Agg (CollectAgg Text
n1 v b -> a
_) Expr b
e1) (Agg (CollectAgg Text
n2 v b -> a
_) Expr b
e2) =
            Text
n1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
n2 Bool -> Bool -> Bool
&& Expr b
e1 Expr b -> Expr b -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr b
e2
        eqNormalized (Agg (FoldAgg Text
n1 Maybe a
_ a -> b -> a
_) Expr b
e1) (Agg (FoldAgg Text
n2 Maybe a
_ a -> b -> a
_) Expr b
e2) =
            Text
n1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
n2 Bool -> Bool -> Bool
&& Expr b
e1 Expr b -> Expr b -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr b
e2
        eqNormalized (Agg (MergeAgg Text
n1 acc
_ acc -> b -> acc
_ acc -> acc -> acc
_ acc -> a
_) Expr b
e1) (Agg (MergeAgg Text
n2 acc
_ acc -> b -> acc
_ acc -> acc -> acc
_ acc -> a
_) Expr b
e2) =
            Text
n1 Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
n2 Bool -> Bool -> Bool
&& Expr b
e1 Expr b -> Expr b -> Bool
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Bool
`exprEq` Expr b
e2
        eqNormalized Expr a
_ Expr a
_ = Bool
False

instance (Ord a, Columnable a) => Ord (Expr a) where
    compare :: Expr a -> Expr a -> Ordering
    compare :: Expr a -> Expr a -> Ordering
compare Expr a
e1 Expr a
e2 = case (Expr a
e1, Expr a
e2) of
        (Col Text
n1, Col Text
n2) -> Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
n1 Text
n2
        (Lit a
v1, Lit a
v2) -> a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
v1 a
v2
        (If Expr Bool
c1 Expr a
t1 Expr a
e1', If Expr Bool
c2 Expr a
t2 Expr a
e2') ->
            Expr Bool -> Expr Bool -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Expr Bool
c1 Expr Bool
c2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr a -> Expr a -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr a
t1 Expr a
t2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr a -> Expr a -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr a
e1' Expr a
e2'
        (Unary UnaryOp b a
op1 Expr b
e1', Unary UnaryOp b a
op2 Expr b
e2') -> Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (UnaryOp b a -> Text
forall a b. UnaryOp a b -> Text
unaryName UnaryOp b a
op1) (UnaryOp b a -> Text
forall a b. UnaryOp a b -> Text
unaryName UnaryOp b a
op2) Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr b -> Expr b -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr b
e1' Expr b
e2'
        (Binary BinaryOp c b a
op1 Expr c
a1 Expr b
b1, Binary BinaryOp c b a
op2 Expr c
a2 Expr b
b2) ->
            Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (BinaryOp c b a -> Text
forall a b c. BinaryOp a b c -> Text
binaryName BinaryOp c b a
op1) (BinaryOp c b a -> Text
forall a b c. BinaryOp a b c -> Text
binaryName BinaryOp c b a
op2) Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr c -> Expr c -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr c
a1 Expr c
a2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr b -> Expr b -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr b
b1 Expr b
b2
        (Agg (CollectAgg Text
n1 v b -> a
_) Expr b
e1', Agg (CollectAgg Text
n2 v b -> a
_) Expr b
e2') -> Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
n1 Text
n2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr b -> Expr b -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr b
e1' Expr b
e2'
        (Agg (FoldAgg Text
n1 Maybe a
_ a -> b -> a
_) Expr b
e1', Agg (FoldAgg Text
n2 Maybe a
_ a -> b -> a
_) Expr b
e2') -> Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
n1 Text
n2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr b -> Expr b -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr b
e1' Expr b
e2'
        (Agg (MergeAgg Text
n1 acc
_ acc -> b -> acc
_ acc -> acc -> acc
_ acc -> a
_) Expr b
e1', Agg (MergeAgg Text
n2 acc
_ acc -> b -> acc
_ acc -> acc -> acc
_ acc -> a
_) Expr b
e2') -> Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
n1 Text
n2 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Expr b -> Expr b -> Ordering
forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr b
e1' Expr b
e2'
        -- Different constructors - compare by priority
        (Col Text
_, Expr a
_) -> Ordering
LT
        (Expr a
_, Col Text
_) -> Ordering
GT
        (Lit a
_, Expr a
_) -> Ordering
LT
        (Expr a
_, Lit a
_) -> Ordering
GT
        (Unary{}, Expr a
_) -> Ordering
LT
        (Expr a
_, Unary{}) -> Ordering
GT
        (Binary{}, Expr a
_) -> Ordering
LT
        (Expr a
_, Binary{}) -> Ordering
GT
        (If{}, Expr a
_) -> Ordering
LT
        (Expr a
_, If{}) -> Ordering
GT
        (Agg{}, Expr a
_) -> Ordering
LT

exprComp :: (Columnable b, Columnable c) => Expr b -> Expr c -> Ordering
exprComp :: forall b c.
(Columnable b, Columnable c) =>
Expr b -> Expr c -> Ordering
exprComp Expr b
e1 Expr c
e2 = case TypeRep (Expr b) -> TypeRep (Expr c) -> Maybe (Expr b :~: Expr c)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (Expr b -> TypeRep (Expr b)
forall a. Typeable a => a -> TypeRep a
typeOf Expr b
e1) (Expr c -> TypeRep (Expr c)
forall a. Typeable a => a -> TypeRep a
typeOf Expr c
e2) of
    Just Expr b :~: Expr c
Refl -> Expr b
e1 Expr b -> Expr b -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` Expr b
Expr c
e2
    Maybe (Expr b :~: Expr c)
Nothing -> Ordering
LT

replaceExpr ::
    forall a b c.
    (Columnable a, Columnable b, Columnable c) =>
    Expr a -> Expr b -> Expr c -> Expr c
replaceExpr :: forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr c
expr = case TypeRep b -> TypeRep c -> Maybe (b :~: c)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @b) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @c) of
    Just b :~: c
Refl -> case TypeRep a -> TypeRep c -> Maybe (a :~: c)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @c) of
        Just a :~: c
Refl -> if Expr b
old Expr b -> Expr b -> Bool
forall a. Eq a => a -> a -> Bool
== Expr b
Expr c
expr then Expr a
Expr c
new else Expr c
replace'
        Maybe (a :~: c)
Nothing -> Expr c
expr
    Maybe (b :~: c)
Nothing -> Expr c
replace'
  where
    replace' :: Expr c
replace' = case Expr c
expr of
        (Col Text
_) -> Expr c
expr
        (Lit c
_) -> Expr c
expr
        (If Expr Bool
cond Expr c
l Expr c
r) ->
            Expr Bool -> Expr c -> Expr c -> Expr c
forall a. Columnable a => Expr Bool -> Expr a -> Expr a -> Expr a
If (Expr a -> Expr b -> Expr Bool -> Expr Bool
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr Bool
cond) (Expr a -> Expr b -> Expr c -> Expr c
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr c
l) (Expr a -> Expr b -> Expr c -> Expr c
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr c
r)
        (Unary UnaryOp b c
op Expr b
value) -> UnaryOp b c -> Expr b -> Expr c
forall a b.
(Columnable a, Columnable b) =>
UnaryOp b a -> Expr b -> Expr a
Unary UnaryOp b c
op (Expr a -> Expr b -> Expr b -> Expr b
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr b
value)
        (Binary BinaryOp c b c
op Expr c
l Expr b
r) -> BinaryOp c b c -> Expr c -> Expr b -> Expr c
forall b b a.
(Columnable b, Columnable b, Columnable a) =>
BinaryOp b b a -> Expr b -> Expr b -> Expr a
Binary BinaryOp c b c
op (Expr a -> Expr b -> Expr c -> Expr c
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr c
l) (Expr a -> Expr b -> Expr b -> Expr b
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr b
r)
        (Agg AggStrategy c b
op Expr b
expr) -> AggStrategy c b -> Expr b -> Expr c
forall a b.
(Columnable a, Columnable b) =>
AggStrategy a b -> Expr b -> Expr a
Agg AggStrategy c b
op (Expr a -> Expr b -> Expr b -> Expr b
forall a b c.
(Columnable a, Columnable b, Columnable c) =>
Expr a -> Expr b -> Expr c -> Expr c
replaceExpr Expr a
new Expr b
old Expr b
expr)

eSize :: Expr a -> Int
eSize :: forall a. Expr a -> Int
eSize (Col Text
_) = Int
1
eSize (Lit a
_) = Int
1
eSize (If Expr Bool
c Expr a
l Expr a
r) = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Expr Bool -> Int
forall a. Expr a -> Int
eSize Expr Bool
c Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Expr a -> Int
forall a. Expr a -> Int
eSize Expr a
l Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Expr a -> Int
forall a. Expr a -> Int
eSize Expr a
r
eSize (Unary UnaryOp b a
_ Expr b
e) = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Expr b -> Int
forall a. Expr a -> Int
eSize Expr b
e
eSize (Binary BinaryOp c b a
_ Expr c
l Expr b
r) = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Expr c -> Int
forall a. Expr a -> Int
eSize Expr c
l Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Expr b -> Int
forall a. Expr a -> Int
eSize Expr b
r
eSize (Agg AggStrategy a b
strategy Expr b
expr) = Expr b -> Int
forall a. Expr a -> Int
eSize Expr b
expr Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1

getColumns :: Expr a -> [T.Text]
getColumns :: forall a. Expr a -> [Text]
getColumns (Col Text
cName) = [Text
cName]
getColumns expr :: Expr a
expr@(Lit a
_) = []
getColumns (If Expr Bool
cond Expr a
l Expr a
r) = Expr Bool -> [Text]
forall a. Expr a -> [Text]
getColumns Expr Bool
cond [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> Expr a -> [Text]
forall a. Expr a -> [Text]
getColumns Expr a
l [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> Expr a -> [Text]
forall a. Expr a -> [Text]
getColumns Expr a
r
getColumns (Unary UnaryOp b a
op Expr b
value) = Expr b -> [Text]
forall a. Expr a -> [Text]
getColumns Expr b
value
getColumns (Binary BinaryOp c b a
op Expr c
l Expr b
r) = Expr c -> [Text]
forall a. Expr a -> [Text]
getColumns Expr c
l [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> Expr b -> [Text]
forall a. Expr a -> [Text]
getColumns Expr b
r
getColumns (Agg AggStrategy a b
strategy Expr b
expr) = Expr b -> [Text]
forall a. Expr a -> [Text]
getColumns Expr b
expr

prettyPrint :: Expr a -> String
prettyPrint :: forall a. Expr a -> String
prettyPrint = Int -> Int -> Expr a -> String
forall a. Int -> Int -> Expr a -> String
go Int
0 Int
0
  where
    indent :: Int -> String
    indent :: Int -> String
indent Int
n = Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
2) Char
' '

    go :: Int -> Int -> Expr a -> String
    go :: forall a. Int -> Int -> Expr a -> String
go Int
depth Int
prec Expr a
expr = case Expr a
expr of
        Col Text
name -> Text -> String
T.unpack Text
name
        Lit a
value -> a -> String
forall a. Show a => a -> String
show a
value
        If Expr Bool
cond Expr a
t Expr a
e ->
            let inner :: String
inner =
                    String
"if "
                        String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Int -> Expr Bool -> String
forall a. Int -> Int -> Expr a -> String
go (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int
0 Expr Bool
cond
                        String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\n"
                        String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
indent (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
                        String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"then "
                        String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Int -> Expr a -> String
forall a. Int -> Int -> Expr a -> String
go (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int
0 Expr a
t
                        String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\n"
                        String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
indent (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
                        String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"else "
                        String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Int -> Expr a -> String
forall a. Int -> Int -> Expr a -> String
go (Int
depth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int
0 Expr a
e
             in if Int
prec Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 then String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
inner String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")" else String
inner
        Unary UnaryOp b a
op Expr b
arg -> case UnaryOp b a -> Maybe Text
forall a b. UnaryOp a b -> Maybe Text
unarySymbol UnaryOp b a
op of
            Maybe Text
Nothing -> Text -> String
T.unpack (UnaryOp b a -> Text
forall a b. UnaryOp a b -> Text
unaryName UnaryOp b a
op) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Int -> Expr b -> String
forall a. Int -> Int -> Expr a -> String
go Int
depth Int
0 Expr b
arg String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
            Just Text
sym -> Text -> String
T.unpack Text
sym String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Int -> Expr b -> String
forall a. Int -> Int -> Expr a -> String
go Int
depth Int
0 Expr b
arg String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
        Binary BinaryOp c b a
op Expr c
l Expr b
r ->
            let p :: Int
p = BinaryOp c b a -> Int
forall a b c. BinaryOp a b c -> Int
binaryPrecedence BinaryOp c b a
op
                inner :: String
inner = case BinaryOp c b a -> Maybe Text
forall a b c. BinaryOp a b c -> Maybe Text
binarySymbol BinaryOp c b a
op of
                    Just Text
name -> Int -> Int -> Expr c -> String
forall a. Int -> Int -> Expr a -> String
go Int
depth Int
p Expr c
l String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Int -> Expr b -> String
forall a. Int -> Int -> Expr a -> String
go Int
depth Int
p Expr b
r
                    Maybe Text
Nothing ->
                        Text -> String
T.unpack (BinaryOp c b a -> Text
forall a b c. BinaryOp a b c -> Text
binaryName BinaryOp c b a
op) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Int -> Expr c -> String
forall a. Int -> Int -> Expr a -> String
go Int
depth Int
p Expr c
l String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
", " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Int -> Expr b -> String
forall a. Int -> Int -> Expr a -> String
go Int
depth Int
p Expr b
r String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
             in if Int
prec Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
p then String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
inner String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")" else String
inner
        Agg (CollectAgg Text
op v b -> a
_) Expr b
arg -> Text -> String
T.unpack Text
op String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Int -> Expr b -> String
forall a. Int -> Int -> Expr a -> String
go Int
depth Int
0 Expr b
arg String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
        Agg (FoldAgg Text
op Maybe a
_ a -> b -> a
_) Expr b
arg -> Text -> String
T.unpack Text
op String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Int -> Expr b -> String
forall a. Int -> Int -> Expr a -> String
go Int
depth Int
0 Expr b
arg String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
        Agg (MergeAgg Text
op acc
_ acc -> b -> acc
_ acc -> acc -> acc
_ acc -> a
_) Expr b
arg -> Text -> String
T.unpack Text
op String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Int -> Expr b -> String
forall a. Int -> Int -> Expr a -> String
go Int
depth Int
0 Expr b
arg String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"