-- -- (c) Susumu Katayama -- {-# LANGUAGE MagicHash, TemplateHaskell #-} module MagicHaskeller.Execute(unsafeExecute, unDeBruijn, s, sprime, bprime, cprime, fix) where import System.IO.Unsafe(unsafeInterleaveIO) import MagicHaskeller.CoreLang import GHC.Exts(unsafeCoerce#) import Control.Concurrent(yield, ThreadId, throwTo) import Control.Monad(mplus) import MagicHaskeller.TyConLib import Data.Array((!)) import MagicHaskeller.MyDynamic import Language.Haskell.TH hiding (Type) import Data.Int unDeBruijn e = undeb 0 e undeb dep (Lambda e) = lambda (dep+1) (undeb (dep+1) e) undeb dep (X n) = X (dep-n) undeb dep (Y :$ e) = case undeb dep e of K :$ und -> und -- fix (\_ -> foo) = foo unde -> Y :$ unde undeb dep (e0 :$ e1) = undeb dep e0 :$ undeb dep e1 undeb dep (Fix e n is) = undeb dep $ foldl (:$) (Y :$ FunLambda (napply (fromIntegral n) Lambda e)) (map X is) undeb dep e = e -- well, B' is not so efficient. lambda :: Int8 -> CoreExpr -> CoreExpr lambda v e | v `isFreeIn` e = K :$ e lambda v (X n) = I lambda v (f :$ x :$ y) | v `isFreeIn` f = if v `isFreeIn` x then B' :$ f :$ x :$ (lambda v y) else if v `isFreeIn` y then C' :$ f :$ (lambda v x) :$ y else S' :$ f :$ (lambda v x) :$ (lambda v y) lambda v (x :$ y) | v `isFreeIn` x = B :$ x :$ lambda v y | v `isFreeIn` y = C :$ lambda v x :$ y | otherwise = S :$ lambda v x :$ lambda v y v `isFreeIn` (f :$ x) = v `isFreeIn` f && v `isFreeIn` x v `isFreeIn` (X n) = v /= n v `isFreeIn` _ = True -- checks if there is a free variable. usually used after unDeBruijn is applied and before tiExpression is applied. -- と思ったのだが,tiExpressionが内部でunDeBruijnを呼んでる. -- やっぱtiExpressionでfail使ってメッセージ運んだ方がよい? freeVar :: CoreExpr -> Maybe String freeVar (Lambda e) = freeVar e freeVar (e0 :$ e1) = freeVar e0 `mplus` freeVar e1 freeVar _ = Nothing -- Use haddock-2.2.2. Later (and much earlier) versions of haddock do not like quasi-quotes. See http://www.nabble.com/build-problems-on-Hackage-td21848164.html unsafeExecute :: VarLib -> CoreExpr -> Dynamic unsafeExecute vl e = exe (unDeBruijn e) where exe (e0 :$ e1) = dynAppErr "apply" (exe e0) (exe e1) exe (Primitive n) = fromPD (vl!n) exe (PrimCon n) = fromPD (vl!n) exe (Context (Dict pd)) = fromPD pd exe S = $(dynamic [|defaultTCL|] [| s :: (b->c->a) -> (b->c) -> b -> a |]) exe K = $(dynamic [|defaultTCL|] [| const :: a->b->a |]) exe I = $(dynamic [|defaultTCL|] [| id :: a->a |]) exe B = $(dynamic [|defaultTCL|] [| (.) :: (c->a) -> (b->c) -> b -> a |]) exe C = $(dynamic [|defaultTCL|] [| flip :: (b->c->a) -> c -> b -> a |]) exe S' = $(dynamic [|defaultTCL|] [| sprime :: (a->b->c)->(d->a)->(d->b)->d->c |]) exe B' = $(dynamic [|defaultTCL|] [| bprime :: (a->b->c)-> a ->(d->b)->d->c |]) exe C' = $(dynamic [|defaultTCL|] [| cprime :: (a->b->c)->(d->a)->b->d->c |]) exe Y = $(dynamic [|defaultTCL|] [| fix :: (a->a)->a |]) exe foo = error (show foo ++ " : unknown combinator") -- readType assumes the tcl is undefined, so it cannot be used when type constructors other than -> are used. s = \f g x -> f x (g x) sprime = \f g h x -> f (g x) (h x) bprime = \f g h x -> f g (h x) cprime = \f g h x -> f (g x) h fix f = let x = f x in x