packages feed

salak 0.3.3.1 → 0.3.3.2

raw patch · 12 files changed

+385/−415 lines, 12 filesdep +dlistPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: dlist

API changes (from Hackage documentation)

- Salak: askSalak :: MonadSalak m => m SourcePack
- Salak: instance GHC.Base.Monad m => Salak.Internal.Prop.FromProp m Salak.FileConfig
- Salak.Internal: askSalak :: MonadSalak m => m SourcePack
- Salak.Internal: instance GHC.Base.Monad m => Salak.Internal.Prop.MonadSalak (Salak.Internal.RunSalakT m)
- Salak.Trie: alterF :: (Functor f, Eq v) => (Maybe v -> f (Maybe v)) -> Keys -> Trie v -> f (Trie v)
+ Salak: askSourcePack :: MonadSalak m => m SourcePack
+ Salak: instance Salak.Internal.Prop.FromProp m Salak.FileConfig
+ Salak.Internal: askSourcePack :: MonadSalak m => m SourcePack
+ Salak.Internal: fromKeys :: [Key] -> Keys
+ Salak.Internal: instance Control.Monad.IO.Class.MonadIO m => Salak.Internal.Prop.MonadSalak (Salak.Internal.RunSalakT m)
+ Salak.Trie: subTrie :: Key -> Trie v -> Trie v
+ Salak.Trie: subTries :: Keys -> Trie v -> Trie v
- Salak: class Monad m => FromProp m a
+ Salak: class FromProp m a
- Salak: fromProp :: (FromProp m a, Generic a, GFromProp m (Rep a)) => Prop m a
+ Salak: fromProp :: (FromProp m a, Generic a, GFromProp m (Rep a), Monad m) => Prop m a
- Salak.Internal: Keys :: [Key] -> Keys
+ Salak.Internal: Keys :: DList Key -> Keys
- Salak.Internal: SourcePack :: !Source -> ![Key] -> !MVar QFunc -> !MVar LFunc -> !IO ReloadResult -> SourcePack
+ Salak.Internal: SourcePack :: !Source -> !Keys -> !MVar QFunc -> !MVar LFunc -> !IO ReloadResult -> SourcePack
- Salak.Internal: [pref] :: SourcePack -> ![Key]
+ Salak.Internal: [pref] :: SourcePack -> !Keys
- Salak.Internal: [unKeys] :: Keys -> [Key]
+ Salak.Internal: [unKeys] :: Keys -> DList Key
- Salak.Internal: simpleKeys :: Text -> [Key]
+ Salak.Internal: simpleKeys :: Text -> Keys

Files

README.md view
@@ -72,7 +72,7 @@   , ext  :: Int   } deriving (Eq, Show) -instance Monad m => FromProp m Config where+instance FromProp m Config where   fromProp = Config     <$> "user" ? pattern "[a-z]{5,16}"     <*> "pwd"@@ -90,7 +90,7 @@ λ> import Data.Default λ> import Data.Text(Text) λ> data Config = Config { name :: Text, dir  :: Maybe Text, ext  :: Int} deriving (Eq, Show)-λ> instance Monad m => FromProp m Config where fromProp = Config <$> "user" <*> "dir" <*> "ext" .?= 1+λ> instance FromProp m Config where fromProp = Config <$> "user" <*> "dir" <*> "ext" .?= 1 λ> runSalak def (require "") :: IO Config Config {name = "daniel", dir = Nothing, ext = 1} ```
salak.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.12 name: salak-version: 0.3.3.1+version: 0.3.3.2 license: MIT license-file: LICENSE copyright: 2019 Daniel YU@@ -26,7 +26,9 @@         Salak.Internal.Prop         Salak.Internal.Writable     default-language: Haskell2010-    default-extensions: RecordWildCards TupleSections+    default-extensions: RecordWildCards TupleSections OverloadedStrings+                        ScopedTypeVariables FlexibleInstances MultiParamTypeClasses+                        DeriveGeneric     ghc-options: -Wall -fno-warn-orphans -fno-warn-missing-signatures     build-depends:         attoparsec >=0.13.2.2 && <0.14,@@ -35,6 +37,7 @@         containers >=0.6.0.1 && <0.7,         data-default >=0.7.1.1 && <0.8,         directory >=1.3.3.0 && <1.4,+        dlist >=0.8.0.7 && <0.9,         exceptions >=0.10.2 && <0.11,         filepath >=1.4.2.1 && <1.5,         hashable >=1.2.7.0 && <1.3,@@ -50,8 +53,12 @@ test-suite spec     type: exitcode-stdio-1.0     main-is: Spec.hs+    build-tool-depends: hspec-discover:hspec-discover -any     hs-source-dirs: test src     other-modules:+        Salak.Internal.KeySpec+        Salak.Internal.PropSpec+        Salak.Internal.SourceSpec         Salak         Salak.Internal         Salak.Internal.Key@@ -62,7 +69,9 @@         Salak.Trie         Paths_salak     default-language: Haskell2010-    default-extensions: RecordWildCards TupleSections+    default-extensions: RecordWildCards TupleSections OverloadedStrings+                        ScopedTypeVariables FlexibleInstances MultiParamTypeClasses+                        DeriveGeneric     ghc-options: -Wall -fno-warn-orphans -fno-warn-missing-signatures     build-depends:         QuickCheck >=2.13.2 && <2.14,@@ -72,6 +81,7 @@         containers >=0.6.0.1 && <0.7,         data-default >=0.7.1.1 && <0.8,         directory >=1.3.3.0 && <1.4,+        dlist >=0.8.0.7 && <0.9,         exceptions >=0.10.2 && <0.11,         filepath >=1.4.2.1 && <1.5,         hashable >=1.2.7.0 && <1.3,
src/Salak.hs view
@@ -108,7 +108,7 @@   , configDir :: Maybe FilePath   } -instance Monad m => FromProp m FileConfig where+instance FromProp m FileConfig where   fromProp = FileConfig     <$> "name" .?= Nothing     <*> "dir"  .?= Nothing@@ -210,7 +210,7 @@ -- >>> import Data.Default -- >>> import Data.Text(Text) -- >>> data Config = Config { name :: Text, dir  :: Maybe Text, ext  :: Int} deriving (Eq, Show)--- >>> instance Monad m => FromProp m Config where fromProp = Config <$> "user" <*> "dir" <*> "ext" .?= 1+-- >>> instance FromProp m Config where fromProp = Config <$> "user" <*> "dir" <*> "ext" .?= 1 -- >>> runSalak def (require "") :: IO Config -- Config {name = "daniel", dir = Nothing, ext = 1} --
src/Salak/Internal.hs view
@@ -42,6 +42,7 @@   , Keys(..)   , Key(..)   , simpleKeys+  , fromKeys   , ToKeys(..)   , setVal   , Val(..)@@ -100,7 +101,7 @@ liftNT a = MS.get >>= liftIO . runLoad a  instance MonadIO m => MonadSalak (LoadSalakT m) where-  askSalak = MS.get >>= toSourcePack+  askSourcePack = MS.get >>= toSourcePack   setLogF f = do     UpdateSource{..} <- MS.get     liftIO $ void $ swapMVar lfunc f@@ -125,9 +126,10 @@ runRun :: Monad m => RunSalakT m a -> SourcePack -> m a runRun (RunSalakT ma) = runReaderT ma -instance Monad m => MonadSalak (RunSalakT m) where-  askSalak = RunSalakT ask +instance MonadIO m => MonadSalak (RunSalakT m) where+  askSourcePack = ask+ instance (MonadThrow m, IU.MonadUnliftIO m) => IU.MonadUnliftIO (RunSalakT m) where   askUnliftIO = do     ut <- ask@@ -172,7 +174,7 @@   runLoad (lm >> MS.get) (UpdateSource r 0 HM.empty l q u) >>= toSourcePack  toSourcePack :: MonadIO m => UpdateSource -> m SourcePack-toSourcePack UpdateSource{..} = liftIO (readMVar ref) >>= \s -> return $ SourcePack s [] qfunc lfunc go+toSourcePack UpdateSource{..} = liftIO (readMVar ref) >>= \s -> return $ SourcePack s mempty qfunc lfunc go   where     go = do       t        <- readMVar ref
src/Salak/Internal/Key.hs view
@@ -1,9 +1,14 @@+{-# LANGUAGE CPP               #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} module Salak.Internal.Key(     Key(..)   , Keys(..)+  , mempty   , simpleKeys+  , singletonKey+  , fromKeys+  , toKeyList   , ToKeys(..)   , isNum   , isStr@@ -11,11 +16,14 @@  import           Control.Applicative  ((<|>)) import           Data.Attoparsec.Text-import           Data.Coerce          (coerce)+import qualified Data.DList           as D import           Data.Hashable import           Data.List            (intercalate) import           Data.Text            (Text) import qualified Data.Text            as T+#if __GLASGOW_HASKELL__ < 804+import           Data.Semigroup+#endif  data Key   = KT !Text@@ -28,10 +36,29 @@   compare (KI _) _      = LT   compare _      _      = GT -newtype Keys = Keys { unKeys :: [Key] } deriving Eq+newtype Keys = Keys { unKeys :: D.DList Key } deriving Eq +emptyKey :: Keys+emptyKey = Keys D.empty++singletonKey :: Key -> Keys+singletonKey k = fromKeys [k]++fromKeys :: [Key] -> Keys+fromKeys = Keys . D.fromList++toKeyList :: Keys -> [Key]+toKeyList = D.toList . unKeys++instance Semigroup Keys where+  (Keys a) <> (Keys b) = Keys $ a <> b++instance Monoid Keys where+  mempty = emptyKey+  mappend = (<>)+ instance Show Keys where-  show ks = toKey (coerce ks)+  show = toKey . D.toList . unKeys     where       toKey = intercalate "." . go       go (a@(KT _):cs) = let (b,c) = break isStr cs in (show a ++ concat (show <$> b)) : go c@@ -56,8 +83,8 @@   show (KT x) = T.unpack x   show (KI i) = "[" ++ show i ++ "]" -simpleKeys :: Text -> [Key]-simpleKeys as = fmap KT $ filter (not.T.null) $ T.splitOn "." as+simpleKeys :: Text -> Keys+simpleKeys = fromKeys . fmap KT . filter (not.T.null) . T.splitOn "."  exprs :: Parser [Key] exprs = concat <$> ( (expr <|> return []) `sepBy` char '.')@@ -91,7 +118,7 @@   toKeys = Right  instance ToKeys Text where-  toKeys = fmap Keys . selectors+  toKeys = fmap fromKeys . selectors     where       selectors = go . parse exprs . flip T.snoc '\n'       go (Done i r) = if i /= "\n" then Left $ "uncomplete parse" ++ T.unpack i else Right r
src/Salak/Internal/Prop.hs view
@@ -17,6 +17,7 @@ import           Control.Monad import           Control.Monad.Catch import           Control.Monad.Except+import           Control.Monad.Fail import           Control.Monad.Identity  (Identity (..)) import           Control.Monad.Reader import qualified Data.ByteString         as B@@ -26,7 +27,7 @@ import           Data.Hashable           (Hashable) import qualified Data.HashMap.Strict     as HM import           Data.Int-import           Data.List               (sortBy)+import           Data.List               (sort) import qualified Data.Map.Strict         as M import           Data.Maybe import           Data.Menshen@@ -47,44 +48,26 @@ import           Salak.Internal.Val import qualified Salak.Trie              as TR import           Text.Read               (readMaybe)--class Monad m => FromProp m a where-  fromProp :: Prop m a-  default fromProp :: (Generic a, GFromProp m (Rep a)) => Prop m a-  fromProp = fmap to gFromProp--newtype Prop m a-  = Prop { unProp :: ReaderT SourcePack (ExceptT SomeException m) a }-  deriving (Functor, Applicative, Monad, MonadReader SourcePack, MonadIO)--instance MonadTrans Prop where-  lift = Prop . lift . lift--instance Monad m => A.Alternative (Prop m) where-  empty = notFound-  a <|> b = do-    v <- try a-    case v of-      Right x                   -> return x-      Left (_ :: SomeException) -> b+import           Unsafe.Coerce           (unsafeCoerce)  -- | Core type class of salak, which provide function to parse properties. class Monad m => MonadSalak m where-  -- | Monad has the ability to get a `SourcePack` instance.-  askSalak :: m SourcePack +  -- | Monad has the ability to get a SourcePack instance.+  askSourcePack :: m SourcePack+   -- | Get reload action which used for reload profiles   askReload :: m (IO ReloadResult)-  askReload = reload <$> askSalak+  askReload = reload <$> askSourcePack    setLogF :: MonadIO m => (String -> IO ()) -> m ()   setLogF f = do-    SourcePack{..} <- askSalak+    SourcePack{..} <- askSourcePack     liftIO $ void $ swapMVar lref f    logSalak :: MonadIO m => String -> m ()   logSalak msg = do-    SourcePack{..} <- askSalak+    SourcePack{..} <- askSourcePack     liftIO $ do       f <- readMVar lref       f msg@@ -99,55 +82,98 @@   -- `require` supports parse `IO` values, which actually wrap a 'MVar' variable and can be reseted by reloading configurations.   -- Normal value will not be affected by reloading configurations.   require :: (MonadThrow m, FromProp m a) => Text -> m a-  require ks = do-    sp@SourcePack{..} <- askSalak-    case search ks source of-      Left  e     -> throwM $ SalakException (unpack ks) (toException $ PropException e)-      Right (k,t) -> do-        v <- runProp2 sp { source = t, pref = pref ++ unKeys k} fromProp-        case v of-          Left  e -> case fromException e of-            Just (SalakException a b) -> throwM $ SalakException a  b-            Just pe                   -> throwM $ SalakException (unpack ks) (toException pe)-            _                         -> throwM $ SalakException (unpack ks) e-          Right x -> return x+  require ks = askSourcePack >>= \s -> runProp s $ do+    case toKeys ks of+      Left  e -> failKey (unpack ks) (PropException e)+      Right k -> withKeys k fromProp -instance {-# OVERLAPPABLE #-} (m ~ t m', Monad m', Monad m, MonadTrans t, MonadSalak m') => MonadSalak m where-  askSalak = lift askSalak+-- | Property parser, used to parse property from `Value`+newtype Prop m a+  = Prop { unProp :: ReaderT SourcePack (ExceptT SomeException m) a }+  deriving (Functor, Applicative, Monad, MonadReader SourcePack, MonadIO) -instance Monad m => MonadSalak (Prop m) where-  askSalak = Prop ask+runProp :: MonadThrow m => SourcePack -> Prop m a -> m a+runProp sp (Prop p) = do+  v <- runExceptT (runReaderT p sp)+  case v of+    Left  e -> throwM e+    Right x -> return x +withProp :: (SourcePack -> SourcePack) -> Prop m a -> Prop m a+withProp = unsafeCoerce withReaderT++withKey :: Key -> Prop m a -> Prop m a+withKey = withKeys . singletonKey++withKeys :: Keys -> Prop m a -> Prop m a+withKeys key = withProp+  $ \SourcePack{..} ->+     SourcePack{pref = pref <> key, source = TR.subTries key source, ..}++data SalakException+  = PropException String -- ^ Parse failed+  | NullException        -- ^ Not found+  | SalakException String SomeException+  deriving Show++instance Exception SalakException+++failKey :: Monad m => String -> SalakException -> Prop m a+failKey ks e = do+  SourcePack{..} <- ask+  throwM+    $ SalakException (go (show pref) ks)+    $ toException e+  where+    go "" a = a+    go a "" = a+    go a  b = a <> "." <> b++-- | Automatic convert literal string into an instance of `Prop` @m@ @a@.+instance (Monad m, FromProp m a) => IsString (Prop m a) where+  fromString ks = do+    case toKeys ks of+      Left  e -> failKey ks (PropException e)+      Right k -> withKeys k fromProp+++instance MonadTrans Prop where+  lift = Prop . lift . lift++instance Monad m => A.Alternative (Prop m) where+  empty = failKey "" NullException++  a <|> b = do+    v <- try a+    case v of+      Right x                   -> return x+      Left (_ :: SomeException) -> b++instance Monad m => MonadError SomeException (Prop m) where+  throwError = Prop . lift . throwError . toException+  catchError (Prop ma) me = Prop $ do+    c <- ask+    lift $ catchError (runReaderT ma c) (\e -> runReaderT (unProp $ me e) c)+ instance Monad m => MonadThrow (Prop m) where-  throwM = Prop . lift . throwError . toException+  throwM = throwError . toException  instance Monad m => MonadCatch (Prop m) where-  catch (Prop a) f = do-    sp <- ask-    v  <- lift $ runExceptT (runReaderT a sp)-    case v of-      Left  e -> case fromException e of-        Just ee -> f ee-        _       -> throwM e-      Right x -> return x+  catch ma me = catchError ma (\e -> maybe (throwM e) me $ fromException e) -runProp2 :: Monad m => SourcePack -> Prop m a -> m (Either SomeException a)-runProp2 sp (Prop p) = runExceptT (runReaderT p sp)+instance Monad m => MonadFail (Prop m) where+  fail = failKey "" . PropException -runProp1 :: MonadThrow m => SourcePack -> Prop m a -> m a-runProp1 sp p = do-  v <- runProp2 sp p-  case v of-    Left  e -> throwM e-    Right x -> return x -runProp :: Monad m => SourcePack -> Prop m a -> Prop m a-runProp sp p = do-  v <- lift $ runProp2 sp p-  case v of-    Left  e -> throwM e-    Right x -> return x+-- | Type class used to parse properties.+class FromProp m a where +  -- | Parse properties from `Value`.+  fromProp :: Monad m => Prop m a+  default fromProp :: (Generic a, GFromProp m (Rep a), Monad m) => Prop m a+  fromProp = fmap to gFromProp+ instance FromProp m a => FromProp m (Maybe a) where   fromProp = do     v <- try fromProp@@ -162,7 +188,6 @@  instance FromProp m a => FromProp m (Either String a) where   fromProp = do-    SourcePack{..} <- ask     v <- try fromProp     return $ case v of       Left  e -> Left $ show (e :: SomeException)@@ -170,19 +195,15 @@  instance {-# OVERLAPPABLE #-} FromProp m a => FromProp m [a] where   fromProp = do-    sp@SourcePack{..} <- askSalak-    foldM (go sp) [] $ sortBy g2 $ filter (isNum.fst) $ HM.toList $ TR.getMap source-    where-      go s vs (k,t) = (:vs) <$> runProp s { pref = pref s ++ [k], source = t} fromProp-      g2 (a,_) (b,_) = compare b a+    SourcePack{..} <- ask+    sequence $ (`withKey` fromProp) <$> sort (filter isNum $ HM.keys $ TR.getMap source)  instance {-# OVERLAPPABLE #-} (IsString s, FromProp m a) => FromProp m [(s, a)] where   fromProp = do-    sp@SourcePack{..} <- askSalak-    foldM (go sp) [] $ sortBy g2 $ filter (isStr.fst) $ HM.toList $ TR.getMap source+    SourcePack{..} <- ask+    sequence $ go <$> sort (filter isStr $ HM.keys $ TR.getMap source)     where-      go s vs (k,t) = (:vs) . (fromString $ show $ Keys [k],) <$> runProp s { pref = pref s ++ [k], source = t} fromProp-      g2 (a,_) (b,_) = compare b a+      go k = (fromString $ show $ singletonKey k,) <$> withKey k fromProp  instance (Eq s, Hashable s, IsString s, FromProp m a) => FromProp m (HM.HashMap s a) where   fromProp = HM.fromList <$> fromProp@@ -201,8 +222,7 @@ buildIO sp a = liftIO $ do   aref <- newMVar a   modifyMVar_ (qref sp) $ \f -> return $ \s ->-    let b = runProp1 sp {source = search2 s (pref sp), pref = pref sp} fromProp-    in case b of+    case runProp sp {source = s} $ withKeys (pref sp) fromProp of       Left  e -> Left $ show e       Right v -> do         vb <- v@@ -210,34 +230,7 @@         return (swapMVar aref (fromMaybe a vb) >> io)   return (readMVar aref) -data SalakException-  = PropException String -- ^ Parse failed-  | NullException        -- ^ Not found-  | SalakException String SomeException-  deriving Show -instance Exception SalakException---- | Automatic convert literal string into an instance of `Prop` @m@ @a@.-instance FromProp m a => IsString (Prop m a) where-  fromString ks = do-    sp@SourcePack{..} <- askSalak-    case search ks source of-      Left  e     -> throwM $ SalakException-        (if null pref then ks else show (Keys pref) ++ "." ++ ks)-        (toException $ PropException e)-      Right (k,t) -> runProp sp { source = t, pref = pref ++ unKeys k} fromProp--notFound :: Monad m => Prop m a-notFound = do-  SourcePack{..} <- askSalak-  throwM $ SalakException (show (Keys pref)) $ toException NullException--err :: Monad m => String -> Prop m a-err e = do-  SourcePack{..} <- askSalak-  throwM $ PropException $ show (Keys pref) ++ ":" ++ e- -- | Prop operators. -- -- Suppose we have the following definition:@@ -276,24 +269,24 @@ -- | Support for setting default `IO` value. instance (MonadIO m, FromProp (Either SomeException) a) => PropOp (Prop m) (IO a) where   (.?=) ma a = do-    sp <- askSalak+    sp <- ask     v  <- try ma     case v of       Left  (_ :: SomeException) -> liftIO a >>= buildIO sp       Right o                    -> return o  instance Monad m => HasValid (Prop m) where-  invalid = err . toI18n+  invalid = Control.Monad.Fail.fail . toI18n  -- | Parse primitive value from `Value` readPrimitive :: Monad m => (Value -> Either String a) -> Prop m a readPrimitive f = do-  SourcePack{..} <- askSalak+  SourcePack{..} <- ask   vx <- g $ TR.getPrimitive source >>= getVal   case f <$> vx of-    Just (Left e)  -> err e+    Just (Left e)  -> Control.Monad.Fail.fail e     Just (Right a) -> return a-    _              -> notFound+    _              -> A.empty   where     g = return @@ -305,29 +298,27 @@     go _ x      = Left $ fst (typeOfV x) ++ " cannot convert to enum"  -class Monad m => GFromProp m f where-  gFromProp :: Prop m (f a)+class GFromProp m f where+  gFromProp :: Monad m => Prop m (f a) -instance {-# OVERLAPPABLE #-} (Monad m, Constructor c, GFromProp m a) => GFromProp m (M1 C c a) where+instance {-# OVERLAPPABLE #-} (Constructor c, GFromProp m a) => GFromProp m (M1 C c a) where     gFromProp       | conIsRecord m = fmap M1 gFromProp       | otherwise     = fmap M1 $ gEnum $ T.pack (conName m)       where m = undefined :: t c a x -gEnum :: (Monad m, GFromProp m f) => Text -> Prop m (f a)+gEnum :: (GFromProp m f, Monad m) => Text -> Prop m (f a) gEnum va = do   o <- gFromProp   readEnum $ \x -> if x==va then Right o else Left "enum invalid"  instance {-# OVERLAPPABLE #-} (Selector s, GFromProp m a) => GFromProp m(M1 S s a) where-  gFromProp = Prop $ do-    let k = KT $ T.pack $ selName (undefined :: t s a p)-    withReaderT (\s -> s { pref = pref s ++ [k], source = search1 (source s) k }) $ unProp $ M1 <$> gFromProp+  gFromProp = withKey (KT $ T.pack $ selName (undefined :: t s a p)) $ M1 <$> gFromProp  instance {-# OVERLAPPABLE #-} GFromProp m a => GFromProp m (M1 D i a) where   gFromProp = M1 <$> gFromProp -instance {-# OVERLAPPABLE #-} (FromProp m a) => GFromProp m (K1 i a) where+instance {-# OVERLAPPABLE #-} FromProp m a => GFromProp m (K1 i a) where     gFromProp = fmap K1 fromProp  instance Monad m => GFromProp m U1 where@@ -336,62 +327,62 @@ instance {-# OVERLAPPABLE #-} (GFromProp m a, GFromProp m b) => GFromProp m (a:*:b) where   gFromProp = (:*:) <$> gFromProp <*> gFromProp -instance {-# OVERLAPPABLE #-} (Monad m, GFromProp m a, GFromProp m b) => GFromProp m (a:+:b) where+instance {-# OVERLAPPABLE #-} (GFromProp m a, GFromProp m b) => GFromProp m (a:+:b) where   gFromProp = fmap L1 gFromProp A.<|> fmap R1 gFromProp -instance (Monad m, FromProp m a) => FromProp m (Identity a) where+instance FromProp m a => FromProp m (Identity a) where   fromProp = Identity <$> fromProp -instance (Monad m, FromProp m a, FromProp m b) => FromProp m (a,b) where+instance (FromProp m a, FromProp m b) => FromProp m (a,b) where   fromProp = (,) <$> fromProp <*> fromProp -instance (Monad m, FromProp m a, FromProp m b, FromProp m c) => FromProp m(a,b,c) where+instance (FromProp m a, FromProp m b, FromProp m c) => FromProp m(a,b,c) where   fromProp = (,,) <$> fromProp <*> fromProp <*> fromProp -instance (Monad m, FromProp m a, FromProp m b, FromProp m c, FromProp m d) => FromProp m(a,b,c,d) where+instance (FromProp m a, FromProp m b, FromProp m c, FromProp m d) => FromProp m(a,b,c,d) where   fromProp = (,,,) <$> fromProp <*> fromProp <*> fromProp <*> fromProp -instance (Monad m, FromProp m a, FromProp m b, FromProp m c, FromProp m d, FromProp m e) => FromProp m(a,b,c,d,e) where+instance (FromProp m a, FromProp m b, FromProp m c, FromProp m d, FromProp m e) => FromProp m(a,b,c,d,e) where   fromProp = (,,,,) <$> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp -instance (Monad m, FromProp m a, FromProp m b, FromProp m c, FromProp m d, FromProp m e, FromProp m f) => FromProp m(a,b,c,d,e,f) where+instance (FromProp m a, FromProp m b, FromProp m c, FromProp m d, FromProp m e, FromProp m f) => FromProp m(a,b,c,d,e,f) where   fromProp = (,,,,,) <$> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp -instance (Monad m, FromProp m a, FromProp m b, FromProp m c, FromProp m d, FromProp m e, FromProp m f, FromProp m g) => FromProp m(a,b,c,d,e,f,g) where+instance (FromProp m a, FromProp m b, FromProp m c, FromProp m d, FromProp m e, FromProp m f, FromProp m g) => FromProp m(a,b,c,d,e,f,g) where   fromProp = (,,,,,,) <$> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp -instance (Monad m, FromProp m a, FromProp m b, FromProp m c, FromProp m d, FromProp m e, FromProp m f, FromProp m g, FromProp m h) => FromProp m(a,b,c,d,e,f,g,h) where+instance (FromProp m a, FromProp m b, FromProp m c, FromProp m d, FromProp m e, FromProp m f, FromProp m g, FromProp m h) => FromProp m(a,b,c,d,e,f,g,h) where   fromProp = (,,,,,,,) <$> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp -instance (Monad m, FromProp m a, FromProp m b, FromProp m c, FromProp m d, FromProp m e, FromProp m f, FromProp m g, FromProp m h, FromProp m i) => FromProp m(a,b,c,d,e,f,g,h,i) where+instance (FromProp m a, FromProp m b, FromProp m c, FromProp m d, FromProp m e, FromProp m f, FromProp m g, FromProp m h, FromProp m i) => FromProp m(a,b,c,d,e,f,g,h,i) where   fromProp = (,,,,,,,,) <$> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp <*> fromProp  -instance (Monad m, FromProp m a) => FromProp m (Min a) where+instance FromProp m a => FromProp m (Min a) where   fromProp = Min <$> fromProp -instance (Monad m, FromProp m a) => FromProp m (Max a) where+instance FromProp m a => FromProp m (Max a) where   fromProp = Max <$> fromProp -instance (Monad m, FromProp m a) => FromProp m (First a) where+instance FromProp m a => FromProp m (First a) where   fromProp = First <$> fromProp -instance (Monad m, FromProp m a) => FromProp m (Last a) where+instance FromProp m a => FromProp m (Last a) where   fromProp = Last <$> fromProp -instance (Monad m, FromProp m a) => FromProp m (Dual a) where+instance FromProp m a => FromProp m (Dual a) where   fromProp = Dual <$> fromProp -instance (Monad m, FromProp m a) => FromProp m (Sum a) where+instance FromProp m a => FromProp m (Sum a) where   fromProp = Sum <$> fromProp -instance (Monad m, FromProp m a) => FromProp m (Product a) where+instance FromProp m a => FromProp m (Product a) where   fromProp = Product <$> fromProp -instance (Monad m, FromProp m a) => FromProp m (Option a) where+instance FromProp m a => FromProp m (Option a) where   fromProp = Option <$> fromProp -instance Monad m => FromProp m Bool where+instance FromProp m Bool where   fromProp = readPrimitive go     where       go (VB x) = Right x@@ -403,25 +394,25 @@         _       -> Left "string convert bool failed"       go x      = Left $ getType x ++ " cannot be bool" -instance Monad m => FromProp m Text where+instance FromProp m Text where   fromProp = readPrimitive go     where       go (VT x) = Right x       go x      = Right $ T.pack $ snd $ typeOfV x -instance Monad m => FromProp m TL.Text where+instance FromProp m TL.Text where   fromProp = TL.fromStrict <$> fromProp -instance Monad m => FromProp m B.ByteString where+instance FromProp m B.ByteString where   fromProp = TB.encodeUtf8 <$> fromProp -instance Monad m => FromProp m BL.ByteString where+instance FromProp m BL.ByteString where   fromProp = TBL.encodeUtf8 <$> fromProp -instance Monad m => FromProp m String where+instance FromProp m String where   fromProp = T.unpack <$> fromProp -instance Monad m => FromProp m Scientific where+instance FromProp m Scientific where   fromProp = readPrimitive go     where       go (VT x) = case readMaybe $ T.unpack x of@@ -430,49 +421,49 @@       go (VI x) = Right x       go x      = Left $ getType x ++ " cannot be number" -instance Monad m => FromProp m Float where+instance FromProp m Float where   fromProp = toRealFloat <$> fromProp -instance Monad m => FromProp m Double where+instance FromProp m Double where   fromProp = toRealFloat <$> fromProp -instance Monad m => FromProp m Integer where+instance FromProp m Integer where   fromProp = toInteger <$> (fromProp :: Prop m Int) -instance Monad m => FromProp m Int where+instance FromProp m Int where   fromProp = fromProp >>= toNum -instance Monad m => FromProp m Int8 where+instance FromProp m Int8 where   fromProp = fromProp >>= toNum -instance Monad m => FromProp m Int16 where+instance FromProp m Int16 where   fromProp = fromProp >>= toNum -instance Monad m => FromProp m Int32 where+instance FromProp m Int32 where   fromProp = fromProp >>= toNum -instance Monad m => FromProp m Int64 where+instance FromProp m Int64 where   fromProp = fromProp >>= toNum -instance Monad m => FromProp m Word where+instance FromProp m Word where   fromProp = fromProp >>= toNum -instance Monad m => FromProp m Word8 where+instance FromProp m Word8 where   fromProp = fromProp >>= toNum -instance Monad m => FromProp m Word16 where+instance FromProp m Word16 where   fromProp = fromProp >>= toNum -instance Monad m => FromProp m Word32 where+instance FromProp m Word32 where   fromProp = fromProp >>= toNum -instance Monad m => FromProp m Word64 where+instance FromProp m Word64 where   fromProp = fromProp >>= toNum -instance Monad m => FromProp m NominalDiffTime where+instance FromProp m NominalDiffTime where   fromProp = fromInteger <$> fromProp -instance Monad m => FromProp m DiffTime where+instance FromProp m DiffTime where   fromProp = fromInteger <$> fromProp  instance (HasResolution a, Monad m) => FromProp m (Fixed a) where@@ -481,40 +472,40 @@ toNum :: (Monad m, Integral i, Bounded i) => Scientific -> Prop m i toNum s = case toBoundedInteger s of   Just v -> return v-  _      -> err "scientific number doesn't fit in the target representation"+  _      -> Control.Monad.Fail.fail "scientific number doesn't fit in the target representation" -instance Monad m => FromProp m CBool where+instance FromProp m CBool where   fromProp = do     b <- fromProp     return $ if b then 1 else 0 -instance Monad m => FromProp m CShort where+instance FromProp m CShort where   fromProp = CShort <$> fromProp -instance Monad m => FromProp m CUShort where+instance FromProp m CUShort where   fromProp = CUShort <$> fromProp -instance Monad m => FromProp m CInt where+instance FromProp m CInt where   fromProp = CInt <$> fromProp -instance Monad m => FromProp m CUInt where+instance FromProp m CUInt where   fromProp = CUInt <$> fromProp -instance Monad m => FromProp m CLong where+instance FromProp m CLong where   fromProp = CLong <$> fromProp -instance Monad m => FromProp m CULong where+instance FromProp m CULong where   fromProp = CULong <$> fromProp -instance Monad m => FromProp m CLLong where+instance FromProp m CLLong where   fromProp = CLLong <$> fromProp -instance Monad m => FromProp m CULLong where+instance FromProp m CULLong where   fromProp = CULLong <$> fromProp -instance Monad m => FromProp m CFloat where+instance FromProp m CFloat where   fromProp = CFloat <$> fromProp -instance Monad m => FromProp m CDouble where+instance FromProp m CDouble where   fromProp = CDouble <$> fromProp 
src/Salak/Internal/Source.hs view
@@ -7,7 +7,6 @@ import           Data.HashMap.Strict     (HashMap) import qualified Data.HashMap.Strict     as HM import qualified Data.Heap               as H-import           Data.Maybe import           Salak.Internal.Key import           Salak.Internal.Val import qualified Salak.Trie              as T@@ -27,7 +26,7 @@  data SourcePack = SourcePack   { source :: !Source-  , pref   :: ![Key]+  , pref   :: !Keys   , qref   :: !(MVar QFunc)   , lref   :: !(MVar LFunc)   , reload :: !(IO ReloadResult)@@ -61,23 +60,12 @@ gen i = foldr go T.empty   where     go (k,v) x = case toKeys k of-      Left  e  -> T.alter (g3 e) (Keys []) x+      Left  e  -> T.alter (g3 e) mempty x       Right k' -> T.alter (g2 $ Val i $ toVal v) k' x     g2 v (Just (a,Vals c)) = Just (a, Vals $ H.insert v c)     g2 v _                 = Just ([], Vals $ H.singleton v)     g3 e (Just (a,c)) = Just (e:a,c)     g3 e _            = Just ([e], Vals H.empty)--search :: (ToKeys k) => k -> Source -> Either String (Keys, Source)-search k t = fmap (go . unKeys) (toKeys k)-  where-    go ks = (Keys ks, foldl search1 t ks)--search2 :: Source -> [Key] -> Source-search2 = foldl search1--search1 :: Source -> Key -> Source-search1 m key = fromMaybe T.empty $ HM.lookup key $ T.getMap m  fmt :: ModType -> Int -> String -> String -> String fmt m i s n = concat ['#' : show i, ' ' : show m, ' ' : s ,  ' ' : n]
src/Salak/Trie.hs view
@@ -21,13 +21,15 @@   , Salak.Trie.null   , member   , lookup+  , subTrie+  , subTries   , insert   , modify   , modifyF   , modify'   , update   , alter-  , alterF+  -- , alterF   -- * Lists   , Salak.Trie.toList   , fromList@@ -41,13 +43,14 @@ import           Control.Applicative (pure, (<*>)) import           Control.Monad       (Monad (..)) import           Data.Bool+import qualified Data.DList          as D import           Data.Eq import           Data.Foldable       (Foldable (..)) import           Data.Function import           Data.Functor import           Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HM-import           Data.List           (concat, intercalate, map, reverse, (++))+import           Data.List           (concat, intercalate, map, (++)) import           Data.Maybe import           Data.Traversable import           Data.Tuple          (uncurry)@@ -97,15 +100,16 @@ member :: Eq v => Keys -> Trie v -> Bool member k t = isJust (lookup k t) +subTrie :: Key -> Trie v -> Trie v+subTrie key = fromMaybe empty . HM.lookup key . getMap++subTries :: Keys -> Trie v -> Trie v+subTries ks v = foldl (flip subTrie) v (toKeyList ks)+ -- | /O(log (n+m))/. Return the primitive value to which the specified key is mapped, -- or Nothing if this trie contains no mapping for the key. lookup :: Eq v => Keys -> Trie v -> Maybe v-lookup (Keys keys) = go keys-  where-    go []     (Trie v _) = v-    go (k:ks) (Trie _ m) = case HM.lookup k m of-      Just t -> go ks t-      _      -> Nothing+lookup keys = getPrimitive . subTries keys  -- | /O(log n)/. Associate the specified value with the specified key in this trie. -- If this trie previously contained a mapping for the key, the old value is replaced.@@ -120,7 +124,7 @@  -- | /O(log (n+m))/. The expression (`modify'` ks f trie) modifies the sub trie at ks. modify' :: Eq v => Keys -> (Trie v -> Trie v) -> Trie v -> Trie v-modify' (Keys ks) f = foldr modify f ks+modify' ks f = foldr modify f (toKeyList ks)  -- | /O(log m)/. The expression (`modifyF` k f trie) modifies the sub trie at k. modifyF :: (Monad m, Eq v) => Key -> (Trie v -> m (Trie v)) -> Trie v -> m (Trie v)@@ -131,33 +135,29 @@  -- | /O(1)/. The expression (update f trie) updates the primitive value in the trie. update :: Eq v => (Maybe v -> Maybe v) -> Trie v -> Trie v-update f = alter f (Keys [])+update f = alter f mempty  -- | /O(n)/. The expression (update f ks trie) updates the primitive value of sub trie at ks. alter :: Eq v => (Maybe v -> Maybe v) -> Keys -> Trie v -> Trie v-alter f (Keys keys) = go keys-  where-    go []     (Trie v m) = Trie (f v) m-    go (k:ks) (Trie v m) = Trie v $ HM.alter (g2 ks) k m-    g2 ks t = let t1 = go ks (fromMaybe empty t) in if t1 == empty then Nothing else Just t1+alter f keys = modify' keys (\(Trie a b) -> Trie (f a) b)  -- | /O(n)/. The expression (update f ks trie) updates the primitive value of sub trie at ks.-alterF :: (Functor f, Eq v) => (Maybe v -> f(Maybe v)) -> Keys -> Trie v -> f (Trie v)-alterF f (Keys keys) = go keys-  where-    go []     (Trie v m) = (`Trie` m) <$> f v-    go (k:ks) (Trie v m) = Trie v <$> HM.alterF (g2 ks) k m-    g2 ks t = g3 <$> go ks (fromMaybe empty t)-    g3 t = if t == empty then Nothing else Just t+-- alterF :: (Functor f, Eq v) => (Maybe v -> f(Maybe v)) -> Keys -> Trie v -> f (Trie v)+-- alterF f keys = modifyF+  -- where+  --   go D.Nil         (Trie v m) = (`Trie` m) <$> f v+  --   go (D.Cons k ks) (Trie v m) = Trie v <$> HM.alterF (g2 ks) k m+  --   g2 ks t = g3 <$> go ks (fromMaybe empty t)+  --   g3 t = if t == empty then Nothing else Just t  -- | /O(n*m)/. Return a list of this tries's elements. The list is produced lazily. toList :: Trie v -> [(Keys, v)]-toList = go []+toList = go D.empty   where-    go p (Trie (Just v) m) = (Keys $ reverse p, v) : g2 p m+    go p (Trie (Just v) m) = (Keys p, v) : g2 p m     go p (Trie _        m) = g2 p m     g2 p m = concat $ g3 p <$> HM.toList m-    g3 p (k,t) = go (k:p) t+    g3 p (k,t) = go (D.cons k p) t  -- | /O(n*m*log n)/. Construct a trie with the supplied mappings. -- If the list contains duplicate mappings, the later mappings take precedence.
+ test/Salak/Internal/KeySpec.hs view
@@ -0,0 +1,37 @@+module Salak.Internal.KeySpec where++import           Data.List          (intercalate)+import           Data.Text          (Text, pack, unpack)+import           Salak.Internal.Key+import           Test.Hspec+import           Test.QuickCheck++newtype SKey = SKey { unKey :: Text } deriving Show++instance Arbitrary SKey where+  arbitrary = do+    key <- choose (1,20)+    vs  <- vectorOf key $ do+      k <- choose (1,20)+      v <- vectorOf k $ choose ('a','z')+      b <- choose (0,10) :: Gen Int+      if b > 0 then return v else do+        x <- choose (0,10) :: Gen Int+        return (v ++ "[" ++ show x ++ "]")+    return (SKey $ pack $ intercalate "." vs)+++spec :: SpecWith ()+spec = do+  context "selectors" $ do+    it "normal" $ do+      toKeys (""         :: Text) `shouldBe` Right mempty+      toKeys ("."        :: Text) `shouldBe` Right mempty+      toKeys (".."       :: Text) `shouldBe` Right mempty+      toKeys ("xx"       :: Text) `shouldBe` Right (fromKeys $ [KT "xx"])+      toKeys ("xx[0]"    :: Text) `shouldBe` Right (fromKeys $ [KT "xx", KI 0])+      toKeys ("xx.yy"    :: Text) `shouldBe` Right (fromKeys $ [KT "xx", KT "yy"])+      toKeys ("xx[0][1]" :: Text) `shouldBe` Right (fromKeys $ [KT "xx", KI 0, KI 1])+      show (fromKeys $ KT "x" : (KI <$> [0..9])) `shouldBe` "x[0][1][2][3][4][5][6][7][8][9]"+    it "QuickCheck" $ do+      quickCheck $ \s -> let s' = unKey s in (show <$> toKeys s') `shouldBe` Right (unpack s')
+ test/Salak/Internal/PropSpec.hs view
@@ -0,0 +1,37 @@+module Salak.Internal.PropSpec where++import           Control.Concurrent.MVar+import           Data.Int+import           Salak.Internal+import           Salak.Internal.Source+import           Salak.Internal.Val+import qualified Salak.Trie              as T+import           Test.Hspec+-- import           Test.QuickCheck++newSource :: Value -> Source+newSource v = T.singleton $ modVals (Val 0 v) emptyVals++newSourcePack :: Value -> IO SourcePack+newSourcePack v = do+  let source = newSource v+      pref   = mempty+      reload = return $ ReloadResult False []+  qref <- newMVar $ \_ -> Right (return ())+  lref <- newMVar $ \_ -> return ()+  return SourcePack{..}++spec :: SpecWith ()+spec = do+  context "VT" $ do+    it "text" $ do+      sp <- newSourcePack (VT "128")+      let run :: forall m a. Monad m => RunSalakT m a -> m a+          run = (`runRun` sp)+      vInt   :: Int   <- run $ require ""+      vInt32 :: Int32 <- run $ require ""+      -- vInt8  :: Int8  <- run $ require ""+      128 `shouldBe` vInt+      128 `shouldBe` vInt32+      -- print vInt8+
+ test/Salak/Internal/SourceSpec.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE NoOverloadedLists #-}+module Salak.Internal.SourceSpec where++import           Control.Monad.Writer+import           Data.Text             (Text, unpack)+import           GHC.Generics+import           Salak+import           Salak.Internal+import           Salak.Internal.Source+import qualified Salak.Trie            as T+import           System.Random         (randomIO)+import           Test.Hspec+import           Test.QuickCheck+++data Config = Config+  { level :: IO Int+  , world :: Maybe Bool+  }++instance MonadIO m => FromProp m Config where+  fromProp = Config <$> "level" .?= (return 1) <*> "world"++data Hello = Hello+  { hello :: IO Int+  } deriving Generic++instance MonadIO m => FromProp m Hello++loadRandom :: (MonadThrow m, MonadIO m) => Text -> LoadSalakT m ()+loadRandom key = loadList True (unpack key) go+  where+    go = do+      a :: Int <- randomIO+      return [(key, a)]++spec :: SpecWith ()+spec = do+  context "source" $ do+    it "normal - 2" $ do+      let (_,b,c) = extract T.empty $ gen 0 ([("hello", "world")] :: [(Text, Text)])+      length c `shouldBe` 0+      length (T.toList b) `shouldBe` 1+    it "normal - 2" $ do+      let (_,b,c) = extract T.empty $ gen 0 ([("hello.value", "world")] :: [(Text, Text)])+      length c `shouldBe` 0+      length (T.toList b) `shouldBe` 1+  context "Reload test" $ do+    it "reload" $ do+      loadAndRunSalak (loadRandom "hello") $ do+        Hello{..}  <- require ""+        Config{..} <- require ""+        x  <- liftIO hello+        liftIO $ print x+        liftIO $ print world+        q1 <- liftIO level+        r  <- askReload+        lift $ quickCheck $ \(_ :: Int) -> do+          ReloadResult{..} <- liftIO r+          when hasError $ print msgs+          hasError `shouldBe` False+          msgs     `shouldBe` ["hello:Mod"]+          y  <- hello+          x  `shouldNotBe` y+          q2 <- level+          q1 `shouldBe` q2
test/Spec.hs view
@@ -1,190 +1,2 @@-{-# LANGUAGE DataKinds             #-}-{-# LANGUAGE DeriveGeneric         #-}-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE RecordWildCards       #-}-{-# LANGUAGE ScopedTypeVariables   #-}--module Main where--import           Control.Monad.Writer-import           Data.List             (intercalate)-import           Data.Text             (Text, pack, unpack)-import           GHC.Generics-import           Salak-import           Salak.Internal-import           Salak.Internal.Source-import qualified Salak.Trie            as T-import           System.Random         (randomIO)-import           Test.Hspec-import           Test.QuickCheck--main :: IO ()-main = hspec spec--spec :: Spec-spec = do-  describe "Salak.Types" specProperty--newtype SKey = SKey { unKey :: Text } deriving Show--instance Arbitrary SKey where-  arbitrary = do-    key <- choose (1,20)-    vs  <- vectorOf key $ do-      k <- choose (1,20)-      v <- vectorOf k $ choose ('a','z')-      b <- choose (0,10) :: Gen Int-      if b > 0 then return v else do-        x <- choose (0,10) :: Gen Int-        return (v ++ "[" ++ show x ++ "]")-    return (SKey $ pack $ intercalate "." vs)--data Hello = Hello-  { hello :: IO Int-  } deriving Generic--instance MonadIO m => FromProp m Hello--data Config = Config-  { level :: IO Int-  , world :: Maybe Bool-  }--instance MonadIO m => FromProp m Config where-  fromProp = Config <$> "level" .?= (return 1) <*> "world"--loadRandom :: (MonadThrow m, MonadIO m) => Text -> LoadSalakT m ()-loadRandom key = loadList True (unpack key) go-  where-    go = do-      a :: Int <- randomIO-      return [(key, a)]--specProperty :: SpecWith ()-specProperty = do-  context "selectors" $ do-    it "normal" $ do-      toKeys (""         :: Text) `shouldBe` Right (Keys $ [])-      toKeys ("."        :: Text) `shouldBe` Right (Keys $ [])-      toKeys (".."       :: Text) `shouldBe` Right (Keys $ [])-      toKeys ("xx"       :: Text) `shouldBe` Right (Keys $ [KT "xx"])-      toKeys ("xx[0]"    :: Text) `shouldBe` Right (Keys $ [KT "xx", KI 0])-      toKeys ("xx.yy"    :: Text) `shouldBe` Right (Keys $ [KT "xx", KT "yy"])-      toKeys ("xx[0][1]" :: Text) `shouldBe` Right (Keys $ [KT "xx", KI 0, KI 1])-      show (Keys $ KT "x" : (KI <$> [0..9])) `shouldBe` "x[0][1][2][3][4][5][6][7][8][9]"-    it "QuickCheck" $ do-      quickCheck $ \s -> let s' = unKey s in (show <$> toKeys s') `shouldBe` Right (unpack s')-  -- context "value" $ do-  --   it "basic" $ do-  --     newVT "xxxx"       0 `shouldBe` VT 0 "xxxx"-  --     newVT "{x.y}"      0 `shouldBe` VT 0 "{x.y}"-  --     newVT "${x*}"      0 `shouldBe` VT 0 "${x*}"-      -- newVT "${x}"       0 `shouldBe` VRef 0 [RRef [KT "x"]]-      -- newVT "${x.y}"     0 `shouldBe` VRef 0 [RRef [KT "x", KT "y"]]-      -- newVT "${x${y}}"   0 `shouldBe` VT 0 "${x${y}}"-      -- newVT "a${x}b"     0 `shouldBe` VRef 0 [RVal "a", RRef [KT "x"], RVal "b"]-      -- newVT "a${x}b${"   0 `shouldBe` VRef 0 [RVal "a", RRef [KT "x"], RVal "b${"]-      -- newVT "a${x}b${c}" 0 `shouldBe` VRef 0 [RVal "a", RRef [KT "x"], RVal "b", RRef [KT "c"]]-  context "source" $ do-    it "normal - 2" $ do-      let (a,b,c) = extract T.empty $ gen 0 ([("hello", "world")] :: [(Text, Text)])-      length c `shouldBe` 0-      length (T.toList b) `shouldBe` 1-  --   it "normal - 3" $ do-  --     let (s2,e2) = runWriter $ insert "1"     (VT 0 "world") emptySource-  --     sizeSource s2       `shouldBe` 1-  --     length e2           `shouldBe` 0-  --   it "normal - 4" $ do-  --     let (s3,e3) = runWriter $ insert "a.b"   (VT 0 "world") emptySource-  --     print s3-  --     sizeSource s3       `shouldBe` 1-  --     length e3           `shouldBe` 0-  -- context "source - merge" $ do-  --   let s  = fst $ runWriter $ insert "hello" (VT 0 "world") emptySource-  --       so = fst $ runWriter $ insert "hello" (VT 1 "yyyyy") emptySource-  --       s1 = fst $ runWriter $ insert "hello" (VT 0 "xxxxx") emptySource-  --   it "merge - del" $ do-  --     let (s2,e2) = runWriter $ replace 0 emptySource s-  --     s2 `shouldBe` emptySource-  --     e2 `shouldBe` ["#0 Del hello"]-  --     let (s3,e3) = runWriter $ replace 1 emptySource s-  --     s3 `shouldBe` s-  --     e3 `shouldBe` []-  --   it "merge - mod" $ do-  --     let (s3,e3) = runWriter $ replace 0 s1 s-  --     e3 `shouldBe` ["#0 Mod hello"]-  --     s3 `shouldBe` s1-  --     let (s2,e2) = runWriter $ replace 1 s1 s-  --     e2 `shouldBe` []-  --     s2 `shouldBe` s-  --     let (_,e4) = runWriter $ replace 1 so s-  --     e4 `shouldBe` ["#1 Add hello"]-  --   it "merge - add" $ do-  --     let (s4,e4) = runWriter $ replace 0 s emptySource-  --     e4 `shouldBe` ["#0 Add hello"]-  --     s4 `shouldBe` s-  --     let (s2,e2) = runWriter $ replace 1 s emptySource-  --     s2 `shouldBe` emptySource-  --     e2 `shouldBe` []-  --     let (s3,e3) = runWriter $ replace 1 so emptySource-  --     e3 `shouldBe` ["#1 Add hello"]-  --     s3 `shouldBe` so-  --   it "merge - unchange" $ do-  --     let (s5,e5) = runWriter $ replace 0 s s-  --     e5 `shouldBe` []-  --     s5 `shouldBe` s-  -- context "Generic" $ do-  --   it "conf" $ do-  --     sp <- runLoadT Nothing $ loadOnceMock-  --       [ ("name", "Daniel")-  --       , ("age", "18")-  --       , ("male", "yes")-  --       ]-  --     errs sp `shouldBe` []-  --     let a = search "" sp :: Either String Conf-  --     print a-  --     isRight a `shouldBe` True-  --   it "placeholder" $ do-  --     let xs = [ ("name", "daniel")-  --              , ("user", "${name}")-  --              , ("a","${b}")-  --              , ("b","${a}")-  --              , ("x", "${y}")-  --              , ("y", "${z}")-  --              , ("z", "Hey! you")-  --              ]-  --     loadAndRunSalak (loadOnceMock xs) $ do-  --       a <- require "name"-  --       b <- require "user"-  --       x <- require "x"-  --       z <- require "z"-  --       lift $ do-  --         a `shouldBe` (b :: Text)-  --         x `shouldBe` (z :: Text)-  --     let x = loadAndRunSalak (loadOnceMock xs) (require "a") :: IO Text-  --     x `shouldThrow` anyErrorCall-  context "Reload test" $ do-    it "reload" $ do-      loadAndRunSalak (loadRandom "hello") $ do-        Hello{..}  <- require ""-        Config{..} <- require ""-        x  <- liftIO hello-        liftIO $ print x-        liftIO $ print world-        q1 <- liftIO level-        r  <- askReload-        lift $ quickCheck $ \(_ :: Int) -> do-          ReloadResult{..} <- liftIO r-          when hasError $ print msgs-          hasError `shouldBe` False-          msgs     `shouldBe` ["hello:Mod"]-          y  <- hello-          x  `shouldNotBe` y-          q2 <- level-          q1 `shouldBe` q2---+-- file test/Spec.hs+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}