packages feed

djinn-ghc 0.0.1 → 0.0.2

raw patch · 2 files changed

+57/−18 lines, 2 filesdep +asyncdep +transformersdep ~djinn-libdep ~mtlPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: async, transformers

Dependency ranges changed: djinn-lib, mtl

API changes (from Hackage documentation)

+ Djinn.GHC: Max :: Int -> MaxSolutions
+ Djinn.GHC: newtype MaxSolutions
+ Djinn.GHC: type Environment = [(Name, Type)]
- Djinn.GHC: djinn :: GhcMonad m => Bool -> Type -> m [String]
+ Djinn.GHC: djinn :: GhcMonad m => Bool -> Maybe ModuleInfo -> Environment -> Type -> MaxSolutions -> Int -> m [String]

Files

djinn-ghc.cabal view
@@ -1,5 +1,5 @@ name:           djinn-ghc-version:        0.0.1+version:        0.0.2 synopsis:       Generate Haskell code from a type. Bridge from Djinn to GHC API. description:    Djinn uses an theorem prover for intuitionistic propositional logic                 to generate a Haskell expression when given a type.@@ -15,8 +15,10 @@ library   exposed-modules:  Djinn.GHC   build-depends:    base >= 4 && < 5,-                    mtl < 2.2,+                    mtl,                     ghc,                     containers,-                    djinn-lib == 0.0.1+                    transformers,+                    djinn-lib >= 0.0.1.1,+                    async   hs-source-dirs:   src
src/Djinn/GHC.hs view
@@ -1,12 +1,16 @@-{-# LANGUAGE PatternGuards #-}-module Djinn.GHC (djinn) where+{-# LANGUAGE PatternGuards, BangPatterns #-}+module Djinn.GHC (Environment, MaxSolutions(..), djinn) where +import Control.Concurrent+import Control.Concurrent.Async import Control.Monad (forM)+import Data.Maybe (isJust) import Data.Set (Set, insert, union, unions, empty, toList)  import qualified Djinn.HTypes as D import qualified Djinn.LJT as D +import MonadUtils import qualified DataCon as G import qualified GHC as G import qualified Name as G@@ -19,10 +23,12 @@  getConTs :: G.Type -> Set G.Name getConTs t | Just (_, i)  <- G.splitForAllTy_maybe t = getConTs i+getConTs t | Just (t1,t2) <- G.splitFunTy_maybe t    = getConTs t1 `union` getConTs t2 getConTs t | Just (c, ts) <- G.splitTyConApp_maybe t =    let args = unions $ map getConTs ts    in if G.isTupleTyCon c then args else insert (G.getName c) args getConTs t | Just (t1,t2) <- G.splitAppTy_maybe t    = getConTs t1 `union` getConTs t2+getConTs t | Just _       <- G.getTyVar_maybe t      = empty getConTs _                                           = empty  hType :: G.Type -> D.HType@@ -39,12 +45,12 @@ hType t | Just var <- G.getTyVar_maybe t          = D.HTVar (toHSymbol var) hType _                                           = error "Unimplemented" -environment :: G.GhcMonad m => G.Type -> m HEnvironment-environment = fmap concat . mapM environment1 . toList . getConTs+environment :: G.GhcMonad m => Maybe G.ModuleInfo -> G.Type -> m HEnvironment+environment minfo = fmap concat . mapM (environment1 minfo) . toList . getConTs -environment1 :: G.GhcMonad m => G.Name -> m HEnvironment-environment1 name = do-  thing <- G.lookupGlobalName name+environment1 :: G.GhcMonad m => Maybe G.ModuleInfo -> G.Name -> m HEnvironment+environment1 minfo name = do+  thing <- lookupNameEverywhere minfo name   case thing of     Just (G.ATyCon tycon) | G.isAlgTyCon tycon -> do       let tyconName = toHSymbol $ G.tyConName tycon@@ -53,7 +59,7 @@       dtypes <- forM datacons $ \dcon -> do         let dconN = toHSymbol $ G.dataConName dcon             (_,_,dconT,_) = G.dataConSig dcon-        dconE <- mapM environment dconT+        dconE <- mapM (environment minfo) dconT         return ((dconN, map hType dconT), dconE)       let dtypesT = map fst dtypes           dtypesE = concatMap snd dtypes@@ -65,20 +71,51 @@           varsH = map toHSymbol vars           htype = hType defn       -- Recursively obtain it for the environment of the type-      defnEnv <- environment defn+      defnEnv <- environment minfo defn       return $ (tyconName, (varsH, htype, NoExtraInfo)) : defnEnv     _ -> return [] +lookupNameEverywhere :: G.GhcMonad m => Maybe G.ModuleInfo -> G.Name -> m (Maybe G.TyThing)+lookupNameEverywhere (Just minfo) name = do+  thing <- G.modInfoLookupName minfo name+  if isJust thing then return thing else G.lookupGlobalName name+lookupNameEverywhere Nothing    name = G.lookupGlobalName name+ toHSymbol :: G.NamedThing a => a -> D.HSymbol toHSymbol = G.getOccString +toLJTSymbol :: G.NamedThing a => a -> D.Symbol+toLJTSymbol = D.Symbol . G.getOccString++-- |Bindings which are in scope at a specific point.+type Environment = [(G.Name, G.Type)]++-- |Obtain a maximum number of solutions.+newtype MaxSolutions = Max Int+ -- |Obtain the list of expressions which could fill -- something with the given type. -- The first flag specifies whether to return one -- or more solutions to the problem.-djinn :: G.GhcMonad m => Bool -> G.Type -> m [String]-djinn multi ty = do-  env <- environment ty-  let form = D.hTypeToFormula env (hType ty)-      prfs = D.prove multi [] form-  return $ map show prfs+djinn :: G.GhcMonad m => Bool -> Maybe G.ModuleInfo -> Environment -> G.Type -> MaxSolutions -> Int -> m [String]+djinn multi minfo env ty (Max mx) microsec = do+  tyEnv <- environment minfo ty+  let form = D.hTypeToFormula tyEnv (hType ty)+      envF = map (\(n,t) -> (toLJTSymbol n, D.hTypeToFormula tyEnv (hType t))) env+      prfs = D.prove multi envF form+      trms = map (D.hPrExpr . D.termToHExpr) prfs+  liftIO $ cropList trms microsec mx++cropList :: [a] -> Int -> Int -> IO [a]+cropList _   _  0 = return []+cropList lst ms n = withAsync (let !l = lst in return l) $ \a -> do+                      threadDelay ms+                      res <- poll a+                      case res of+                        Just r -> case r of+                          Right (x:xs) -> do ys <- cropList xs ms (n-1)+                                             return $ x : ys+                          _            -> return []+                        Nothing -> do cancel a+                                      return []+