module MagicHaskeller.TICE where
import MagicHaskeller.CoreLang
import MagicHaskeller.Types
import MagicHaskeller.TyConLib
import MagicHaskeller.Execute(unsafeExecute, unDeBruijn, s, sprime, bprime, cprime, fix)
import MagicHaskeller.PriorSubsts
import qualified MagicHaskeller.PolyDynamic as PD
import MagicHaskeller.MyDynamic(unsafeFromDyn)
import MagicHaskeller.ReadTHType(thTypeToType)
import Data.Array.IArray
import Control.Monad(MonadPlus)
import Language.Haskell.TH(pprint)
import Debug.Trace
type TI = PriorSubsts Maybe
ceToDynamic :: TyConLib -> VarLib -> CoreExpr -> PD.Dynamic
ceToDynamic tcl vl ce = case tiCE tcl vl ce of
Nothing -> error ("ceToDynamic: " ++ pprint (exprToTHExp' False vl ce) ++ " type mismatch.")
Just ty -> PD.unsafeToDyn tcl ty (unsafeFromDyn $ unsafeExecute vl ce) $ exprToTHExp vl ce
tiCE :: (Functor m, MonadPlus m) => TyConLib -> VarLib -> CoreExpr -> m Type
tiCE tcl vl ce = do t <- runPS (tiEx tcl vl (unDeBruijn ce) >>= applyPS)
return $ normalize t
tiEx tcl vl ex = tie ex
where
tie (e :$ f) = do
te <- tie e
tf <- tie f
tv <- newTVar
let t = TV tv
(if runPS (unify (tf :-> t) te) == Nothing then trace ("unifying " ++ show (tf :-> t) ++ " and " ++ show te) else id)
unify (tf :-> t) te
t' <- applyPS t
return t'
tie prim = freshInst (PD.dynType $ exe prim)
exe :: CoreExpr -> PD.Dynamic
exe (Primitive n) = vl!n
exe (PrimCon n) = vl!n
exe (Context (Dict pd)) = pd
exe S = $(PD.dynamic [|defaultTCL|] [| s :: (b->c->a) -> (b->c) -> b -> a |])
exe K = $(PD.dynamic [|defaultTCL|] [| const :: a->b->a |])
exe I = $(PD.dynamic [|defaultTCL|] [| id :: a->a |])
exe B = $(PD.dynamic [|defaultTCL|] [| (.) :: (c->a) -> (b->c) -> b -> a |])
exe C = $(PD.dynamic [|defaultTCL|] [| flip :: (b->c->a) -> c -> b -> a |])
exe S' = $(PD.dynamic [|defaultTCL|] [| sprime :: (a->b->c)->(d->a)->(d->b)->d->c |])
exe B' = $(PD.dynamic [|defaultTCL|] [| bprime :: (a->b->c)-> a ->(d->b)->d->c |])
exe C' = $(PD.dynamic [|defaultTCL|] [| cprime :: (a->b->c)->(d->a)->b->d->c |])
exe Y = $(PD.dynamic [|defaultTCL|] [| fix :: (a->a)->a |])
exe foo = error ("TICE.tiEx: " ++ show foo ++ " : unknown combinator")