module CSPM.Evaluator.PatBind where
import Control.Monad
import CSPM.DataStructures.Names
import CSPM.DataStructures.Syntax
import CSPM.Evaluator.Monad
import CSPM.Evaluator.Values
import CSPM.Evaluator.ValueSet
import Util.Annotated
import Util.Exception
class Bindable a where
bind :: a -> Value -> EvaluationMonad (Bool, [(Name, Value)])
instance Bindable a => Bindable (Annotated b a) where
bind (An _ _ a) v = bind a v
instance Bindable Pat where
bind (PCompList ps Nothing _) (VList xs) | length ps == length xs =
bindAll ps xs
bind (PCompList starts (Just (middle, ends)) _) (VList xs) =
if not (atLeastLength (length starts + length ends) xs) then
return (False, [])
else do
(b1, nvs1) <- bindAll starts xsStart
(b2, nvs2) <- bindAll ends xsEnd
(b3, nvs3) <- bind middle (VList xsMiddle)
return (b1 && b2 && b3, nvs1++nvs2++nvs3)
where
atLeastLength 0 _ = True
atLeastLength _ [] = False
atLeastLength n (x:xs) = atLeastLength (n1) xs
(xsStart, rest) = splitAt (length starts) xs
(xsMiddle, xsEnd) =
if length ends == 0 then (rest, [])
else splitAt (length rest length ends) rest
bind (PCompDot ps _) (VDot vs) = do
(b1, nvs1) <- bindAll psInit vsInit
(b2, nvs2) <- bind pLast (VDot vsLast)
return (b1 && b2, nvs1++nvs2)
where
(psInit, pLast) = initLast ps
(vsInit, vsLast) = splitAt (length psInit) vs
initLast :: [a] -> ([a], a)
initLast [a] = ([],a)
initLast (a:as) = let (bs,b) = initLast as in (a:bs,b)
bind (PDoublePattern p1 p2) v = do
(m1, b1) <- bind p1 v
(m2, b2) <- bind p2 v
return $ (m1 && m2, b1++b2)
bind (PLit (Int i1)) (VInt i2) | i1 == i2 = return (True, [])
bind (PLit (Bool b1)) (VBool b2) | b1 == b2 = return (True, [])
bind (PSet [p]) (VSet s) =
case singletonValue s of
Just v -> bind p v
Nothing -> return (False, [])
bind (PTuple ps) (VTuple vs) = do
bindAll ps vs
bind (PVar n) v = return (True, [(n, v)])
bind PWildCard v = return (True, [])
bind _ _ = return (False, [])
bindAll :: Bindable a => [a] -> [Value]
-> EvaluationMonad (Bool, [(Name, Value)])
bindAll ps xs = do
rs <- zipWithM bind ps xs
return (and (map fst rs), concat (map snd rs))