-- -- (c) Susumu Katayama 2009 -- CoreLang.lhs extracted haskell-src-free stuff that can be used with Hat. (This looks like Bindging.hs....) \begin{code} {-# OPTIONS -cpp -fglasgow-exts -XExistentialQuantification #-} -- workaround Haddock invoked from Cabal unnecessarily chasing imports. (If cpp fails, haddock ignores the remaining part of the module.) #ifndef __GLASGOW_HASKELL__ -- x #hoge #endif module MagicHaskeller.CoreLang where import Language.Haskell.TH import Data.Array import Debug.Trace import MagicHaskeller.MyDynamic import Data.Char(chr,ord) #ifdef FORCE import Control.Parallel.Strategies #endif -- required to make sure expressions are ready, so we can measure the exact time consumed to execute the expressions before time out. import Data.Bits import Data.HashTable(hashInt, prime) infixl :$ data CoreExpr = S | K | I | B | C | S' | B' | C' | Lambda CoreExpr | X Int -- de Bruijn notation | Tuple Int | Primitive Int | CoreExpr :$ CoreExpr deriving (Read, Eq, Show, Ord) -- required to make sure expressions are ready, so we can measure the exact time consumed to execute the expressions before time out. #ifdef FORCE instance NFData CoreExpr where rnf (Lambda e) = rnf e rnf (X i) = rnf i rnf (Tuple i) = rnf i rnf (Primitive _) = () -- 最後のパターンにマッチするのでこれは要らなかったか. rnf (c :$ d) = rnf c `seq` rnf d rnf e = () #endif {- unused due to inefficiency ceToInteger (Lambda e) = ceToInteger e -- 型が変わっちゃうのでLambdaは無視できるはず.... といいつつ自信無.July 24, 2008のnotesを参照. ま,hashには使えるという程度のつもり. ceToInteger (f :$ e) = 3 * (ceToInteger f `interleave` ceToInteger e) ceToInteger (X n) = 3 * toInteger n + 1 ceToInteger (Primitive n) = 3 * toInteger n + 2 0 `interleave` 0 = 0 i `interleave` j = (j `interleave` (i `shiftR` 1)) * 2 + (i `mod` 2) -- IntegerでなくIntを使う場合,算術右シフトshiftRでなく論理右シフトを使う必要がある...のはいいけど,なぜライブラリに論理右シフトがない? logShiftR1 n = (n `clearBit` 0) `rotateR` 1 -} instance Enum CoreExpr where fromEnum (Lambda e) = fromIntegral prime * fromEnum e -- 型が変わっちゃうのでLambdaは無視できるはず.... といいつつ自信無.July 24, 2008のnotesを参照. ま,hashには使えるという程度のつもり. fromEnum (f :$ e) = fromEnum f #* fromEnum e fromEnum (X n) = n * 0xdeadbeef fromEnum (Primitive n) = (-1-n) * 0xdeadbeef m #* c = fromIntegral (hashInt m) + (c `mod` fromIntegral prime) newtype HValue = HV (forall a. a) instance Eq Dynamic where a == b = True instance Ord Dynamic where compare a b = EQ instance Read Dynamic where readsPrec _ str = [(error "Dynamics cannot be read.", str)] instance Ord Exp where compare (VarE n0) (VarE n1) = n0 `compare` n1 compare (VarE n0) _ = LT compare (ConE n0) (VarE n1) = GT compare (ConE n0) (ConE n1) = n0 `compare` n1 compare (ConE n0) _ = LT compare (AppE _ _) (VarE _) = GT compare (AppE _ _) (ConE _) = GT compare (AppE e0 f0) (AppE e1 f1) = case compare e0 e1 of EQ -> compare f0 f1 c -> c compare (AppE _ _) _ = LT compare a b = show a `compare` show b -- 超遅そう.... instance Read Exp where readsPrec _ str = [(error "ReadS Exp is not implemented yet", str)] type VarLib = Array Int (Exp,Dynamic) -- x 第1引数のplはArray Con Stringなんだけど,もう全部Primitiveを使うことになったので不要. -- exprToTHExp converts CoreLang.CoreExpr into Language.Haskell.TH.Exp exprToTHExp :: VarLib -> CoreExpr -> Exp exprToTHExp vl e = x2hsx (ord 'a'-1) e where x2hsx dep (Lambda e) = -- trace "Lambda" $ case x2hsx (dep+1) e of LamE pvars expr -> LamE (pvar:pvars) expr expr -> LamE [pvar] expr where pvar = VarP $ mkName [chr (dep+1)] x2hsx dep (X n) = VarE (mkName [chr (dep - n)]) -- X nはX 0, X 1, .... -- x2hsx _ (Qualified con) = VarE (mkName (pl ! con)) x2hsx _ (Primitive n) = fst (vl ! n) x2hsx dep (Primitive n :$ e0 :$ e1) = case fst (vl!n) of e@(VarE name) | head (nameBase name) `elem` "!@#$%&*+./<=>?\\^|-~" -> InfixE (Just $ x2hsx dep e0) e (Just $ x2hsx dep e1) e@(ConE name) | namestr == ":" -> case hsx1 of ListE hsxs -> ListE (hsx0 : hsxs) ConE n | nameBase n == "[]" -> ListE [hsx0] _ -> InfixE (Just hsx0) e (Just hsx1) | head namestr == ':' -> InfixE (Just hsx0) e (Just hsx1) where hsx0 = x2hsx dep e0 hsx1 = x2hsx dep e1 namestr = nameBase name e -> (e `AppE` x2hsx dep e0) `AppE` x2hsx dep e1 x2hsx dep (e0 :$ e1) = x2hsx dep e0 `AppE` x2hsx dep e1 x2hsx _ e = error ("exprToTHExp: converting" ++ show e) \end{code}