{-# LANGUAGE GADTs, RankNTypes, TypeOperators, FlexibleInstances #-} module Walk where import Test.QuickCheck import Data.List import Control.Monad import Control.Applicative import Induction.Structural import Trace import EnvTypes import Env import Util construct :: VarMap -> Hyp -> Gen [Repr'] construct vm (hyps,tms) = mapM (construct1 hyps vm) tms construct1 :: [(String,Ty')] -> VarMap -> Tm -> Gen Repr' construct1 hyps vm tm = case tm of Var s -> case lookup s vm of Just u -> return u Nothing -> case lookup s hyps of Just t -> arbFromType' t -- ^ if this is missing, generate a new one with arbitrary!! Nothing -> error $ show s ++ " missing!" ++ show vm ++ "," ++ show hyps Con s tms -> mkCon s <$> mapM (construct1 hyps vm) tms Fun{} -> error "exponentials not supported" -- | We can only pick 1-2 hyps, otherwise we get crazy exponential behaviour pickHyps :: [a] -> Gen [a] pickHyps [] = return [] pickHyps hs = do let n = length hs - 1 i <- choose (0,n) i' <- choose (0,n) two <- arbitrary return $ if two && i /= i' then [hs !! i,hs !! i'] else [hs !! i] -- TODO: Can this be reorganized so we get an efficient unrolling? makeTracer :: [Repr'] -> [Oblig] -> Gen (Trace [Repr']) makeTracer args parts = go parts where go p = case p of Obligation _ hyps conc:is | length args == length conc -> case zipWithM match args conc of Nothing -> go is Just vms -> halfSize $ \ _ -> do -- Throw away some hypotheses hyps' <- pickHyps hyps argss' <- mapM (construct (concat vms)) hyps' forks <- mapM (`makeTracer` parts) argss' return (Fork args forks) | otherwise -> mk_error $ "Unequal lengths (conc=" ++ intercalate "," (map (render . linTerm style) conc) ++ ")" _ -> mk_error "No case" where mk_error msg = error $ "makeTracer " ++ show args ++ " : " ++ msg ++ "!" ++ "\nDetails: args = (" ++ intercalate " , " (map showRepr' args) ++ ")" ++ "\nCheck Env.match and EnvTypes.==?, or case is missing from schema:" ++ "\n" ++ showOblig parts