module MagicHaskeller.Analytical.Syntax where
import Control.Monad
import Data.List(nub)
import qualified MagicHaskeller.Types as T
import Data.Word
import MagicHaskeller.CoreLang(Var)
data IOPair a = IOP { numUniIDs :: Int
, inputs :: [Expr a]
, output :: Expr a}
deriving (Show,Eq)
instance Functor IOPair where
fmap f iop = iop{inputs = map (fmap f) $ inputs iop, output = fmap f $ output iop}
type TBS = [Bool]
data Expr a = E {ann :: a, iD :: Int}
| U {ann :: a, iD :: Int}
| C {ann :: a, sz :: Int, ctor :: T.Typed Constr, fields :: [Expr a]}
deriving (Show)
instance Eq (Expr a) where
E{iD=i} == E{iD=j} = i==j
U{iD=i} == U{iD=j} = i==j
C{ctor=c,fields=fs} == C{ctor=d,fields=gs} = T.typee c == T.typee d && fs == gs
_ == _ = False
instance Functor Expr where
fmap f (E a i) = E (f a) i
fmap f (U a i) = U (f a) i
fmap f c = c{ann = f (ann c), fields = map (fmap f) $ fields c}
type Constr = Var
normalizeMkIOP :: [Expr a] -> Expr a -> IOPair a
normalizeMkIOP ins out = let varIDs = nub $ concatMap vr (out : ins)
tup = zip varIDs [0..]
in mapIOP (mapU (\tv -> case lookup tv tup of Just n -> n)) IOP{numUniIDs = length varIDs, inputs = ins, output = out}
vr (U _ i) = [i]
vr (C{fields=es}) = concatMap vr es
mapU f (U a i) = U a $ f i
mapU f e@(C{fields=xs}) = e{fields=map (mapU f) xs}
maybeCtor :: Expr a -> Maybe (T.Typed Constr)
maybeCtor (C{ctor=c}) = Just c
maybeCtor _ = Nothing
hasExistential (E{}) = True
hasExistential (U{}) = False
hasExistential (C{fields=es}) = any hasExistential es
visibles tbs ins = [ i | (True,i) <- zip tbs ins ]
type Subst a = [(Int, Expr a)]
unify (C _ _ i xs) (C _ _ j ys) | T.typee i == T.typee j = unifyList xs ys
| otherwise = mzero
unify e f | e==f = return []
unify (E _ i) e = bind i e
unify e (E _ i) = bind i e
unify _ _ = mzero
unifyList [] [] = return []
unifyList (x:xs) (y:ys) = do s1 <- unify x y
s2 <- unifyList (map (apply s1) xs) (map (apply s1) ys)
return $ s2 `plusSubst` s1
unifyList _ _ = error "Partial application to a constructor."
bind i e | i `occursIn` e = mzero
| otherwise = return [(i,e)]
apply subst v@(E _ i) = maybe v id $ lookup i subst
apply subst v@(U _ _) = v
apply subst (C a _ i xs) = cap a i (map (apply subst) xs)
i `occursIn` (E _ j) = i==j
i `occursIn` (U _ _) = False
i `occursIn` (C _ _ _ xs) = any (i `occursIn`) xs
plusSubst :: Subst a -> Subst a -> Subst a
s0 `plusSubst` s1 = [(u, apply s0 t) | (u,t) <- s1] ++ s0
emptySubst = []
fresh f e@(E{}) = e
fresh f (U a i) = E a $ f i
fresh f (C a s c xs) = C a s c (map (fresh f) xs)
apfresh s e@(E{}) = e
apfresh s (U a i) = maybe (E a i) id $ lookup i s
apfresh s (C a _sz c xs) = cap a c (map (apfresh s) xs)
mapE f e@(U{}) = e
mapE f (E a i) = E a $ f i
mapE f e@(C{fields=xs}) = e{fields=map (mapE f) xs}
applyIOPs s iops = map (applyIOP s) iops
applyIOP s iop = mapIOP (apply s) iop
mapIOP f (IOP bvs ins out) = IOP bvs (map f ins) (f out)
mapTypee f (x T.::: t) = f x T.::: t
newtype TermStat = TS {unTS :: [Bool]} deriving Show
initTS :: TermStat
initTS = TS $ replicate (length termCrit) True
updateTS :: [Expr a] -> [Expr a] -> TermStat -> TermStat
updateTS bkis is (TS bs) = TS $ zipWith (&&) bs [ bkis < is | (<) <- termCrit ]
evalTS :: TermStat -> Bool
evalTS (TS bs) = or bs
termCrit :: [[Expr a]->[Expr a]->Bool]
termCrit = [aWise]
fullyLex, revFullyLex, aWise, revAWise, linear :: [Expr a]->[Expr a]->Bool
fullyLex = lessRevListsLex cmpExprs
revFullyLex= lessListsLex cmpExprs
aWise = lessRevListsLex cmpExprSzs
revAWise = lessListsLex cmpExprSzs
linear ls rs = sum (map size ls) < sum (map size rs)
revArgs :: ([Expr a]->[Expr a]->Bool) -> [Expr a]->[Expr a]->Bool
revArgs cmp ls rs = cmp (reverse ls) (reverse rs)
lessRevListsLex cmp = revArgs (lessListsLex cmp)
lessListsLex cmp [] _ = False
lessListsLex cmp (e0:es0) (e1:es1) = case cmp e0 e1 of LT -> True
EQ -> lessListsLex cmp es0 es1
GT -> False
cmpExprss [] [] = EQ
cmpExprss [] _ = LT
cmpExprss _ [] = GT
cmpExprss (e0:es0) (e1:es1) = case cmpExprs e0 e1 of EQ -> cmpExprss es0 es1
c -> c
cmpExprs (C _ _ _ fs) (C _ _ _ gs) = cmpExprss fs gs
cmpExprs _ (C _ _ _ _) = LT
cmpExprs (C _ _ _ _) _ = GT
cmpExprs _ _ = EQ
cmpExprSzs e0 e1 = compare (size e0) (size e1)
size (C _ sz _ fs) = sz
size _ = 1
cap a con fs = C a (1 + sum (map size fs)) con fs