{-# LANGUAGE CPP #-}
#if __GLASGOW_HASKELL__ == 708
{-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-}
#endif
module Data.Express.Core
(
Expr (..)
, value
, val
, ($$)
, var
, evaluate
, eval
, evl
, typ
, etyp
, mtyp
, toDynamic
, isValue
, isApp
, isVar
, isConst
, isIllTyped
, isWellTyped
, isFun
, hasVar
, isGround
, compareComplexity
, compareLexicographically
, compareQuickly
, arity
, size
, depth
, height
, subexprs
, values
, vars
, consts
, nubSubexprs
, nubValues
, nubVars
, nubConsts
, unfoldApp
, showExpr
, showOpExpr
, showPrecExpr
)
where
import Data.Dynamic
import Data.Express.Utils
import Data.Express.Utils.Typeable
data Expr = Value String Dynamic
| Expr :$ Expr
#if __GLASGOW_HASKELL__ == 708
deriving instance Typeable Expr
#endif
value :: Typeable a => String -> a -> Expr
value :: forall a. Typeable a => String -> a -> Expr
value String
s a
x = String -> Dynamic -> Expr
Value String
s (forall a. Typeable a => a -> Dynamic
toDyn a
x)
val :: (Typeable a, Show a) => a -> Expr
val :: forall a. (Typeable a, Show a) => a -> Expr
val a
x = forall a. Typeable a => String -> a -> Expr
value (forall a. Show a => a -> String
show a
x) a
x
($$) :: Expr -> Expr -> Maybe Expr
Expr
e1 $$ :: Expr -> Expr -> Maybe Expr
$$ Expr
e2 | Expr -> Bool
isIllTyped Expr
e = forall a. Maybe a
Nothing
| Bool
otherwise = forall a. a -> Maybe a
Just Expr
e
where
e :: Expr
e = Expr
e1 Expr -> Expr -> Expr
:$ Expr
e2
var :: Typeable a => String -> a -> Expr
var :: forall a. Typeable a => String -> a -> Expr
var String
s a
a = forall a. Typeable a => String -> a -> Expr
value (Char
'_'forall a. a -> [a] -> [a]
:String
s) (forall a. HasCallStack => a
undefined forall a. a -> a -> a
`asTypeOf` a
a)
typ :: Expr -> TypeRep
typ :: Expr -> TypeRep
typ = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall {a} {a} {a}. (Show a, Show a) => (a, a) -> a
err forall a. a -> a
id forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> Either (TypeRep, TypeRep) TypeRep
etyp
where
err :: (a, a) -> a
err (a
t1, a
t2) = forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ String
"type mismatch, cannot apply `"
forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
t1 forall a. [a] -> [a] -> [a]
++ String
"' to `" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
t2 forall a. [a] -> [a] -> [a]
++ String
"'"
etyp :: Expr -> Either (TypeRep, TypeRep) TypeRep
etyp :: Expr -> Either (TypeRep, TypeRep) TypeRep
etyp (Value String
_ Dynamic
d) = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ Dynamic -> TypeRep
dynTypeRep Dynamic
d
etyp (Expr
e1 :$ Expr
e2) = case (Expr -> Either (TypeRep, TypeRep) TypeRep
etyp Expr
e1, Expr -> Either (TypeRep, TypeRep) TypeRep
etyp Expr
e2) of
(Right TypeRep
t1, Right TypeRep
t2) -> case TypeRep
t1 TypeRep -> TypeRep -> Maybe TypeRep
`funResultTy` TypeRep
t2 of
Maybe TypeRep
Nothing -> forall a b. a -> Either a b
Left (TypeRep
t1,TypeRep
t2)
Just TypeRep
t -> forall a b. b -> Either a b
Right TypeRep
t
(Left (TypeRep, TypeRep)
e, Either (TypeRep, TypeRep) TypeRep
_) -> forall a b. a -> Either a b
Left (TypeRep, TypeRep)
e
(Either (TypeRep, TypeRep) TypeRep
_, Left (TypeRep, TypeRep)
e) -> forall a b. a -> Either a b
Left (TypeRep, TypeRep)
e
mtyp :: Expr -> Maybe TypeRep
mtyp :: Expr -> Maybe TypeRep
mtyp = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a b. a -> b -> a
const forall a. Maybe a
Nothing) forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> Either (TypeRep, TypeRep) TypeRep
etyp
isIllTyped :: Expr -> Bool
isIllTyped :: Expr -> Bool
isIllTyped = forall a. Maybe a -> Bool
isNothing forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> Maybe TypeRep
mtyp
isWellTyped :: Expr -> Bool
isWellTyped :: Expr -> Bool
isWellTyped = forall a. Maybe a -> Bool
isJust forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> Maybe TypeRep
mtyp
isFun :: Expr -> Bool
isFun :: Expr -> Bool
isFun = TypeRep -> Bool
isFunTy forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> TypeRep
typ
evaluate :: Typeable a => Expr -> Maybe a
evaluate :: forall a. Typeable a => Expr -> Maybe a
evaluate Expr
e = Expr -> Maybe Dynamic
toDynamic Expr
e forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a. Typeable a => Dynamic -> Maybe a
fromDynamic
eval :: Typeable a => a -> Expr -> a
eval :: forall a. Typeable a => a -> Expr -> a
eval a
x Expr
e = forall a. a -> Maybe a -> a
fromMaybe a
x (forall a. Typeable a => Expr -> Maybe a
evaluate Expr
e)
evl :: Typeable a => Expr -> a
evl :: forall a. Typeable a => Expr -> a
evl Expr
e = a
r
where
r :: a
r = forall a. Typeable a => a -> Expr -> a
eval a
err Expr
e
err :: a
err = forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ String
"evl: cannot evaluate Expr `" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Expr
e forall a. [a] -> [a] -> [a]
++ String
"' at the " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show (forall a. Typeable a => a -> TypeRep
typeOf a
r) forall a. [a] -> [a] -> [a]
++ String
" type"
toDynamic :: Expr -> Maybe Dynamic
toDynamic :: Expr -> Maybe Dynamic
toDynamic (Value String
_ Dynamic
x) = forall a. a -> Maybe a
Just Dynamic
x
toDynamic (Expr
e1 :$ Expr
e2) = do Dynamic
v1 <- Expr -> Maybe Dynamic
toDynamic Expr
e1
Dynamic
v2 <- Expr -> Maybe Dynamic
toDynamic Expr
e2
Dynamic -> Dynamic -> Maybe Dynamic
dynApply Dynamic
v1 Dynamic
v2
instance Show Expr where
showsPrec :: Int -> Expr -> ShowS
showsPrec Int
d Expr
e = Bool -> ShowS -> ShowS
showParen (Int
d forall a. Ord a => a -> a -> Bool
> Int
10)
forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" :: "
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> ShowS
showsTypeExpr Expr
e
showsTypeExpr :: Expr -> String -> String
showsTypeExpr :: Expr -> ShowS
showsTypeExpr Expr
e = case Expr -> Either (TypeRep, TypeRep) TypeRep
etyp Expr
e of
Left (TypeRep
t1,TypeRep
t2) -> String -> ShowS
showString String
"ill-typed # "
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> ShowS
shows TypeRep
t1
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" $ "
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> ShowS
shows TypeRep
t2
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" #"
Right TypeRep
t -> forall a. Show a => a -> ShowS
shows TypeRep
t
showsPrecExpr :: Int -> Expr -> String -> String
showsPrecExpr :: Int -> Expr -> ShowS
showsPrecExpr Int
d (Value String
"_" Dynamic
_) = String -> ShowS
showString String
"_"
showsPrecExpr Int
d (Value (Char
'_':String
s) Dynamic
_)
| String -> Bool
isInfixedPrefix String
s = String -> ShowS
showString forall a b. (a -> b) -> a -> b
$ ShowS
toPrefix String
s
| Bool
otherwise = Bool -> ShowS -> ShowS
showParen (String -> Bool
isInfix String
s) forall a b. (a -> b) -> a -> b
$ String -> ShowS
showString String
s
showsPrecExpr Int
d (Value String
s Dynamic
_) | String -> Bool
isInfixedPrefix String
s = String -> ShowS
showString forall a b. (a -> b) -> a -> b
$ ShowS
toPrefix String
s
showsPrecExpr Int
d (Value String
s Dynamic
_) | String -> Bool
isNegativeLiteral String
s = Bool -> ShowS -> ShowS
showParen (Int
d forall a. Ord a => a -> a -> Bool
> Int
0) forall a b. (a -> b) -> a -> b
$ String -> ShowS
showString String
s
showsPrecExpr Int
d (Value String
s Dynamic
_) = Bool -> ShowS -> ShowS
showParen Bool
sp forall a b. (a -> b) -> a -> b
$ String -> ShowS
showString String
s
where sp :: Bool
sp = if String -> Bool
atomic String
s then String -> Bool
isInfix String
s else forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True (Int
d forall a. Ord a => a -> a -> Bool
>) forall a b. (a -> b) -> a -> b
$ String -> Maybe Int
outernmostPrec String
s
showsPrecExpr Int
d (Value String
":" Dynamic
_ :$ Expr
e1 :$ Expr
e2)
| Expr -> Bool
isConst Expr
e1 Bool -> Bool -> Bool
&& Expr -> Maybe TypeRep
mtyp Expr
e1 forall a. Eq a => a -> a -> Bool
== forall a. a -> Maybe a
Just (forall a. Typeable a => a -> TypeRep
typeOf (forall a. HasCallStack => a
undefined :: Char)) =
case Expr -> ShowS
showsTailExpr Expr
e2 String
"" of
Char
'\"':String
cs -> String -> ShowS
showString (String
"\"" forall a. [a] -> [a] -> [a]
++ (forall a. [a] -> [a]
init forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
tail) (Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
e1 String
"") forall a. [a] -> [a] -> [a]
++ String
cs)
String
cs -> Bool -> ShowS -> ShowS
showParen (Int
d forall a. Ord a => a -> a -> Bool
> String -> Int
prec String
":")
forall a b. (a -> b) -> a -> b
$ String -> Expr -> ShowS
showsOpExpr String
":" Expr
e1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
":" forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
cs
showsPrecExpr Int
d (Value String
":" Dynamic
_ :$ Expr
e1 :$ Expr
e2) =
case Expr -> ShowS
showsTailExpr Expr
e2 String
"" of
String
"[]" -> String -> ShowS
showString String
"[" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
e1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"]"
Char
'[':String
cs -> String -> ShowS
showString String
"[" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
e1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"," forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
cs
String
cs -> Bool -> ShowS -> ShowS
showParen (Int
d forall a. Ord a => a -> a -> Bool
> String -> Int
prec String
":")
forall a b. (a -> b) -> a -> b
$ String -> Expr -> ShowS
showsOpExpr String
":" Expr
e1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
":" forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
cs
showsPrecExpr Int
d Expr
ee | Expr -> Bool
isTuple Expr
ee = Bool -> ShowS -> ShowS
showParen Bool
True
forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 (\ShowS
s1 ShowS
s2 -> ShowS
s1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"," forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
s2)
(Int -> Expr -> ShowS
showsPrecExpr Int
0 forall a b. (a -> b) -> [a] -> [b]
`map` Expr -> [Expr]
unfoldTuple Expr
ee)
showsPrecExpr Int
d (Value String
"if" Dynamic
_ :$ Expr
ep :$ Expr
ex :$ Expr
ey) =
Bool -> ShowS -> ShowS
showParen (Int
d forall a. Ord a => a -> a -> Bool
>= Int
0) forall a b. (a -> b) -> a -> b
$ String -> ShowS
showString String
"if " forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ep
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" then " forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ex
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" else " forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ey
showsPrecExpr Int
d (Value String
"case" Dynamic
_ :$ Expr
ep :$ Expr
ex :$ Expr
ey) | Expr -> TypeRep
typ Expr
ep forall a. Eq a => a -> a -> Bool
== TypeRep
boolTy =
Bool -> ShowS -> ShowS
showParen (Int
d forall a. Ord a => a -> a -> Bool
>= Int
0) forall a b. (a -> b) -> a -> b
$ String -> ShowS
showString String
"case " forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ep
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" of False -> " forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ex
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"; True -> " forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ey
showsPrecExpr Int
d (Value String
"case" Dynamic
_ :$ Expr
eo :$ Expr
ex :$ Expr
ey :$ Expr
ez) | Expr -> TypeRep
typ Expr
eo forall a. Eq a => a -> a -> Bool
== TypeRep
orderingTy =
Bool -> ShowS -> ShowS
showParen (Int
d forall a. Ord a => a -> a -> Bool
>= Int
0) forall a b. (a -> b) -> a -> b
$ String -> ShowS
showString String
"case " forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
eo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" of LT -> " forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ex
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"; EQ -> " forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"; GT -> " forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ez
showsPrecExpr Int
d (Value String
",.." Dynamic
_ :$ Expr
ex :$ Expr
ey :$ Expr
ez) =
String -> ShowS
showString String
"[" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ex
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (if Expr -> Bool
dotdot Expr
ex Bool -> Bool -> Bool
&& Expr -> Bool
dotdot Expr
ey Bool -> Bool -> Bool
&& Expr -> Bool
dotdot Expr
ez then String
"," else String
", ")
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (if Expr -> Bool
dotdot Expr
ex Bool -> Bool -> Bool
&& Expr -> Bool
dotdot Expr
ey Bool -> Bool -> Bool
&& Expr -> Bool
dotdot Expr
ez then String
".." else String
" .. ")
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ez
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"]"
showsPrecExpr Int
d (Value String
",.." Dynamic
_ :$ Expr
ex :$ Expr
ey) =
String -> ShowS
showString String
"[" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ex
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (if Expr -> Bool
dotdot Expr
ex Bool -> Bool -> Bool
&& Expr -> Bool
dotdot Expr
ey then String
"," else String
", ")
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (if Expr -> Bool
dotdot Expr
ex Bool -> Bool -> Bool
&& Expr -> Bool
dotdot Expr
ey then String
"..]" else String
" ..]")
showsPrecExpr Int
d (Value String
".." Dynamic
_ :$ Expr
ex :$ Expr
ey) =
String -> ShowS
showString String
"[" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ex
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (if Expr -> Bool
dotdot Expr
ex Bool -> Bool -> Bool
&& Expr -> Bool
dotdot Expr
ey then String
".." else String
" .. ")
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"]"
showsPrecExpr Int
d (Value String
".." Dynamic
_ :$ Expr
ex) =
String -> ShowS
showString String
"[" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
ex forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (if Expr -> Bool
dotdot Expr
ex then String
"..]" else String
" ..]")
showsPrecExpr Int
d (Value String
f' Dynamic
_ :$ Expr
e1 :$ Expr
e2)
| String -> Bool
isInfix String
f = Bool -> ShowS -> ShowS
showParen (Int
d forall a. Ord a => a -> a -> Bool
> String -> Int
prec String
f)
forall a b. (a -> b) -> a -> b
$ String -> Expr -> ShowS
showsOpExpr String
f Expr
e1
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" " forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" "
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Expr -> ShowS
showsOpExpr String
f Expr
e2
| Bool
otherwise = Bool -> ShowS -> ShowS
showParen (Int
d forall a. Ord a => a -> a -> Bool
> String -> Int
prec String
" ")
forall a b. (a -> b) -> a -> b
$ String -> ShowS
showString String
f
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" " forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Expr -> ShowS
showsOpExpr String
" " Expr
e1
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" " forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Expr -> ShowS
showsOpExpr String
" " Expr
e2
where
f :: String
f = case String
f' of String
"_" -> String
"_"
(Char
'_':String
f) -> String
f
String
f -> String
f
showsPrecExpr Int
d (Value String
f' Dynamic
_ :$ Expr
e1)
| String -> Bool
isInfix String
f = Bool -> ShowS -> ShowS
showParen Bool
True forall a b. (a -> b) -> a -> b
$ String -> Expr -> ShowS
showsOpExpr String
f Expr
e1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" " forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
f
where
f :: String
f = case String
f' of String
"_" -> String
"_"
(Char
'_':String
f) -> String
f
String
f -> String
f
showsPrecExpr Int
d (Expr
e1 :$ Expr
e2) = Bool -> ShowS -> ShowS
showParen (Int
d forall a. Ord a => a -> a -> Bool
> String -> Int
prec String
" ")
forall a b. (a -> b) -> a -> b
$ Int -> Expr -> ShowS
showsPrecExpr (String -> Int
prec String
" ") Expr
e1
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" "
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr (String -> Int
prec String
" " forall a. Num a => a -> a -> a
+ Int
1) Expr
e2
dotdot :: Expr -> Bool
dotdot :: Expr -> Bool
dotdot (Value (Char
c:String
_) Dynamic
_) = Char -> Bool
isNumber Char
c Bool -> Bool -> Bool
|| Char -> Bool
isLower Char
c Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'_' Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'\''
dotdot Expr
_ = Bool
False
showsTailExpr :: Expr -> String -> String
showsTailExpr :: Expr -> ShowS
showsTailExpr (Value String
":" Dynamic
_ :$ Expr
e1 :$ Expr
e2)
| Expr -> Bool
isConst Expr
e1 Bool -> Bool -> Bool
&& Expr -> Maybe TypeRep
mtyp Expr
e1 forall a. Eq a => a -> a -> Bool
== forall a. a -> Maybe a
Just (forall a. Typeable a => a -> TypeRep
typeOf (forall a. HasCallStack => a
undefined :: Char)) =
case Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
e2 String
"" of
Char
'\"':String
cs -> String -> ShowS
showString (String
"\"" forall a. [a] -> [a] -> [a]
++ (forall a. [a] -> [a]
init forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
tail) (Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
e1 String
"") forall a. [a] -> [a] -> [a]
++ String
cs)
String
cs -> String -> Expr -> ShowS
showsOpExpr String
":" Expr
e1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
":" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> ShowS
showsTailExpr Expr
e2
showsTailExpr (Value String
":" Dynamic
_ :$ Expr
e1 :$ Expr
e2) =
case Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
e2 String
"" of
String
"[]" -> String -> ShowS
showString String
"[" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
e1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"]"
Char
'[':String
cs -> String -> ShowS
showString String
"[" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Expr -> ShowS
showsPrecExpr Int
0 Expr
e1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"," forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
cs
String
cs -> String -> Expr -> ShowS
showsOpExpr String
":" Expr
e1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
":" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> ShowS
showsTailExpr Expr
e2
showsTailExpr Expr
e = String -> Expr -> ShowS
showsOpExpr String
":" Expr
e
showsOpExpr :: String -> Expr -> String -> String
showsOpExpr :: String -> Expr -> ShowS
showsOpExpr String
op = Int -> Expr -> ShowS
showsPrecExpr (String -> Int
prec String
op forall a. Num a => a -> a -> a
+ Int
1)
showOpExpr :: String -> Expr -> String
showOpExpr :: String -> Expr -> String
showOpExpr String
op = Int -> Expr -> String
showPrecExpr (String -> Int
prec String
op forall a. Num a => a -> a -> a
+ Int
1)
showPrecExpr :: Int -> Expr -> String
showPrecExpr :: Int -> Expr -> String
showPrecExpr Int
n Expr
e = Int -> Expr -> ShowS
showsPrecExpr Int
n Expr
e String
""
showExpr :: Expr -> String
showExpr :: Expr -> String
showExpr = Int -> Expr -> String
showPrecExpr (-Int
1)
instance Eq Expr where
Value String
s1 Dynamic
d1 == :: Expr -> Expr -> Bool
== Value String
s2 Dynamic
d2 = String
s1 forall a. Eq a => a -> a -> Bool
== String
s2 Bool -> Bool -> Bool
&& Dynamic -> TypeRep
dynTypeRep Dynamic
d1 forall a. Eq a => a -> a -> Bool
== Dynamic -> TypeRep
dynTypeRep Dynamic
d2
(Expr
ef1 :$ Expr
ex1) == (Expr
ef2 :$ Expr
ex2) = Expr
ef1 forall a. Eq a => a -> a -> Bool
== Expr
ef2 Bool -> Bool -> Bool
&& Expr
ex1 forall a. Eq a => a -> a -> Bool
== Expr
ex2
Expr
_ == Expr
_ = Bool
False
instance Ord Expr where
compare :: Expr -> Expr -> Ordering
compare = Expr -> Expr -> Ordering
compareComplexity forall a. Semigroup a => a -> a -> a
<> Expr -> Expr -> Ordering
compareLexicographically
compareComplexity :: Expr -> Expr -> Ordering
compareComplexity :: Expr -> Expr -> Ordering
compareComplexity = (forall a. Ord a => a -> a -> Ordering
compare forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` forall (t :: * -> *) a. Foldable t => t a -> Int
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> [Expr]
values)
forall a. Semigroup a => a -> a -> a
<> (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Ord a => a -> a -> Ordering
compare forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` forall (t :: * -> *) a. Foldable t => t a -> Int
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> [Expr]
nubVars)
forall a. Semigroup a => a -> a -> a
<> (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Ord a => a -> a -> Ordering
compare forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` forall (t :: * -> *) a. Foldable t => t a -> Int
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> [Expr]
vars)
forall a. Semigroup a => a -> a -> a
<> (forall a. Ord a => a -> a -> Ordering
compare forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` forall (t :: * -> *) a. Foldable t => t a -> Int
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> [Expr]
nubConsts)
compareLexicographically :: Expr -> Expr -> Ordering
compareLexicographically :: Expr -> Expr -> Ordering
compareLexicographically = Expr -> Expr -> Ordering
cmp
where
(Expr
f :$ Expr
x) cmp :: Expr -> Expr -> Ordering
`cmp` (Expr
g :$ Expr
y) = Expr
f Expr -> Expr -> Ordering
`cmp` Expr
g forall a. Semigroup a => a -> a -> a
<> Expr
x Expr -> Expr -> Ordering
`cmp` Expr
y
(Expr
_ :$ Expr
_) `cmp` Expr
_ = Ordering
GT
Expr
_ `cmp` (Expr
_ :$ Expr
_) = Ordering
LT
e1 :: Expr
e1@(Value String
s1 Dynamic
_) `cmp` e2 :: Expr
e2@(Value String
s2 Dynamic
_) = Expr -> Bool
isConst Expr
e1 forall a. Ord a => a -> a -> Ordering
`compare` Expr -> Bool
isConst Expr
e2
forall a. Semigroup a => a -> a -> a
<> Expr -> TypeRep
typ Expr
e1 TypeRep -> TypeRep -> Ordering
`compareTy` Expr -> TypeRep
typ Expr
e2
forall a. Semigroup a => a -> a -> a
<> String
s1 String -> String -> Ordering
`cmpbool` String
s2
forall a. Semigroup a => a -> a -> a
<> forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s1 forall a. Ord a => a -> a -> Ordering
`compare` forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s2
forall a. Semigroup a => a -> a -> a
<> String
s1 forall a. Ord a => a -> a -> Ordering
`compare` String
s2
String
"False" cmpbool :: String -> String -> Ordering
`cmpbool` String
"True" = Ordering
LT
String
"True" `cmpbool` String
"False" = Ordering
GT
String
_ `cmpbool` String
_ = Ordering
EQ
compareQuickly :: Expr -> Expr -> Ordering
compareQuickly :: Expr -> Expr -> Ordering
compareQuickly = Expr -> Expr -> Ordering
cmp
where
(Expr
f :$ Expr
x) cmp :: Expr -> Expr -> Ordering
`cmp` (Expr
g :$ Expr
y) = Expr
f Expr -> Expr -> Ordering
`cmp` Expr
g forall a. Semigroup a => a -> a -> a
<> Expr
x Expr -> Expr -> Ordering
`cmp` Expr
y
(Expr
_ :$ Expr
_) `cmp` Expr
_ = Ordering
GT
Expr
_ `cmp` (Expr
_ :$ Expr
_) = Ordering
LT
x :: Expr
x@(Value String
n1 Dynamic
_) `cmp` y :: Expr
y@(Value String
n2 Dynamic
_) = Expr -> TypeRep
typ Expr
x TypeRep -> TypeRep -> Ordering
`compareTy` Expr -> TypeRep
typ Expr
y
forall a. Semigroup a => a -> a -> a
<> String
n1 forall a. Ord a => a -> a -> Ordering
`compare` String
n2
unfoldApp :: Expr -> [Expr]
unfoldApp :: Expr -> [Expr]
unfoldApp Expr
e = Expr -> [Expr] -> [Expr]
u Expr
e []
where
u :: Expr -> [Expr] -> [Expr]
u (Expr
ef :$ Expr
ex) = Expr -> [Expr] -> [Expr]
u Expr
ef forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Expr
exforall a. a -> [a] -> [a]
:)
u Expr
ex = (Expr
exforall a. a -> [a] -> [a]
:)
unfoldTuple :: Expr -> [Expr]
unfoldTuple :: Expr -> [Expr]
unfoldTuple = [Expr] -> [Expr]
u forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> [Expr]
unfoldApp
where
u :: [Expr] -> [Expr]
u (Value String
cs Dynamic
_:[Expr]
es) | Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Expr]
es) Bool -> Bool -> Bool
&& String
cs forall a. Eq a => a -> a -> Bool
== forall a. Int -> a -> [a]
replicate (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Expr]
es forall a. Num a => a -> a -> a
- Int
1) Char
',' = [Expr]
es
u [Expr]
_ = []
isTuple :: Expr -> Bool
isTuple :: Expr -> Bool
isTuple = Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> [Expr]
unfoldTuple
hasVar :: Expr -> Bool
hasVar :: Expr -> Bool
hasVar (Expr
e1 :$ Expr
e2) = Expr -> Bool
hasVar Expr
e1 Bool -> Bool -> Bool
|| Expr -> Bool
hasVar Expr
e2
hasVar Expr
e = Expr -> Bool
isVar Expr
e
isGround :: Expr -> Bool
isGround :: Expr -> Bool
isGround = Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> Bool
hasVar
isConst :: Expr -> Bool
isConst :: Expr -> Bool
isConst (Value (Char
'_':String
_) Dynamic
_) = Bool
False
isConst (Value String
_ Dynamic
_) = Bool
True
isConst Expr
_ = Bool
False
isVar :: Expr -> Bool
isVar :: Expr -> Bool
isVar (Value (Char
'_':String
_) Dynamic
_) = Bool
True
isVar Expr
_ = Bool
False
isValue :: Expr -> Bool
isValue :: Expr -> Bool
isValue (Value String
_ Dynamic
_) = Bool
True
isValue Expr
_ = Bool
False
isApp :: Expr -> Bool
isApp :: Expr -> Bool
isApp (Expr
_ :$ Expr
_) = Bool
True
isApp Expr
_ = Bool
False
subexprs :: Expr -> [Expr]
subexprs :: Expr -> [Expr]
subexprs Expr
e = Expr -> [Expr] -> [Expr]
s Expr
e []
where
s :: Expr -> [Expr] -> [Expr]
s :: Expr -> [Expr] -> [Expr]
s e :: Expr
e@(Expr
e1 :$ Expr
e2) = (Expr
eforall a. a -> [a] -> [a]
:) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> [Expr] -> [Expr]
s Expr
e1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> [Expr] -> [Expr]
s Expr
e2
s Expr
e = (Expr
eforall a. a -> [a] -> [a]
:)
nubSubexprs :: Expr -> [Expr]
nubSubexprs :: Expr -> [Expr]
nubSubexprs = Expr -> [Expr]
s
where
s :: Expr -> [Expr]
s e :: Expr
e@(Expr
e1 :$ Expr
e2) = [Expr
e] forall a. Ord a => [a] -> [a] -> [a]
+++ Expr -> [Expr]
s Expr
e1 forall a. Ord a => [a] -> [a] -> [a]
+++ Expr -> [Expr]
s Expr
e2
s Expr
e = [Expr
e]
values :: Expr -> [Expr]
values :: Expr -> [Expr]
values Expr
e = Expr -> [Expr] -> [Expr]
v Expr
e []
where
v :: Expr -> [Expr] -> [Expr]
v :: Expr -> [Expr] -> [Expr]
v (Expr
e1 :$ Expr
e2) = Expr -> [Expr] -> [Expr]
v Expr
e1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> [Expr] -> [Expr]
v Expr
e2
v Expr
e = (Expr
eforall a. a -> [a] -> [a]
:)
nubValues :: Expr -> [Expr]
nubValues :: Expr -> [Expr]
nubValues = Expr -> [Expr]
v
where
v :: Expr -> [Expr]
v (Expr
e1 :$ Expr
e2) = Expr -> [Expr]
v Expr
e1 forall a. Ord a => [a] -> [a] -> [a]
+++ Expr -> [Expr]
v Expr
e2
v Expr
e = [Expr
e]
consts :: Expr -> [Expr]
consts :: Expr -> [Expr]
consts = forall a. (a -> Bool) -> [a] -> [a]
filter Expr -> Bool
isConst forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> [Expr]
values
nubConsts :: Expr -> [Expr]
nubConsts :: Expr -> [Expr]
nubConsts = Expr -> [Expr]
c
where
c :: Expr -> [Expr]
c (Expr
e1 :$ Expr
e2) = Expr -> [Expr]
c Expr
e1 forall a. Ord a => [a] -> [a] -> [a]
+++ Expr -> [Expr]
c Expr
e2
c Expr
e = [Expr
e | Expr -> Bool
isConst Expr
e]
vars :: Expr -> [Expr]
vars :: Expr -> [Expr]
vars = forall a. (a -> Bool) -> [a] -> [a]
filter Expr -> Bool
isVar forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> [Expr]
values
nubVars :: Expr -> [Expr]
nubVars :: Expr -> [Expr]
nubVars = Expr -> [Expr]
v
where
v :: Expr -> [Expr]
v (Expr
e1 :$ Expr
e2) = Expr -> [Expr]
v Expr
e1 forall a. Ord a => [a] -> [a] -> [a]
+++ Expr -> [Expr]
v Expr
e2
v Expr
e = [Expr
e | Expr -> Bool
isVar Expr
e]
arity :: Expr -> Int
arity :: Expr -> Int
arity = TypeRep -> Int
tyArity forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> TypeRep
typ
size :: Expr -> Int
size :: Expr -> Int
size = forall (t :: * -> *) a. Foldable t => t a -> Int
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> [Expr]
values
depth :: Expr -> Int
depth :: Expr -> Int
depth e :: Expr
e@(Expr
_:$Expr
_) = Int
1 forall a. Num a => a -> a -> a
+ forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (forall a b. (a -> b) -> [a] -> [b]
map Expr -> Int
depth forall a b. (a -> b) -> a -> b
$ Expr -> [Expr]
unfoldApp Expr
e)
depth Expr
_ = Int
1
height :: Expr -> Int
height :: Expr -> Int
height (Expr
e1 :$ Expr
e2) = Int
1 forall a. Num a => a -> a -> a
+ Expr -> Int
height Expr
e1 forall a. Ord a => a -> a -> a
`max` Expr -> Int
height Expr
e2
height Expr
_ = Int
1