1 {-# LANGUAGE AllowAmbiguousTypes #-}
2 {-# LANGUAGE DataKinds #-}
4 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
5 {-# LANGUAGE RecordWildCards #-}
6 {-# LANGUAGE UndecidableInstances #-}
7 {-# LANGUAGE UndecidableSuperClasses #-}
8 {-# OPTIONS_GHC -fno-warn-orphans #-}
9 module Hcompta.LCC.Read
10 ( module Hcompta.LCC.Read
11 , module Hcompta.LCC.Read.Compta
12 , module Hcompta.LCC.Read.Megaparsec
15 import Control.Applicative (Applicative(..), (<*))
16 import Control.Monad (Monad(..))
17 import Data.Char (Char)
18 import Data.Either (Either(..))
20 import Data.Function (($), (.))
21 import Data.Functor (Functor(..), (<$>))
22 import Data.Map.Strict (Map)
23 import Data.Maybe (Maybe(..))
24 import Data.Monoid (Monoid(..))
25 import Data.Semigroup (Semigroup(..))
26 import Data.Text (Text)
27 import Data.Typeable (Typeable, eqT)
28 import System.FilePath (FilePath)
29 import System.IO (IO, hPrint, stderr)
30 import Text.Show (Show(..))
31 import Prelude (error)
32 import qualified Data.ByteString as BS
33 import qualified Data.Map.Strict as Map
34 import qualified Data.Strict as S
35 import qualified Data.Text.Encoding as Enc
36 import qualified System.FilePath as FilePath
37 import qualified Text.Megaparsec as P
39 import Language.Symantic.Grammar
40 import qualified Language.Symantic as Sym
41 import Language.Symantic.Lib ()
43 import Hcompta.LCC.Journal
44 import Hcompta.LCC.Compta
45 import Hcompta.LCC.Posting
46 import Hcompta.LCC.Transaction
48 -- import Hcompta.LCC.Sym.Compta ()
50 import Hcompta.LCC.Read.Compta
51 import Hcompta.LCC.Read.Megaparsec
52 import qualified Hcompta.LCC.Lib.Strict as S
53 import qualified Hcompta as H
55 -- import qualified Control.Monad.Classes as MC
58 forall ss src e m j a.
61 Sym.ModulesTyInj ss =>
62 Sym.ModulesInj src ss =>
63 m ~ S.StateT (Context_Read src) (S.StateT (Context_Sym src ss) IO) =>
64 e ~ P.ParseError Char P.Dec =>
67 (Transaction -> j -> j) ->
68 CF (P.ParsecT P.Dec Text m) a ->
70 IO ((Either e a, Context_Read src), Context_Sym src ss)
71 read consTxn g fp inp =
72 S.runState context_sym $
73 S.runState (context_read consTxn) $
74 P.runParserT (unCF $ g <* eoi) (FilePath.normalise fp) inp
76 readFile :: FilePath -> (FilePath -> Text -> IO a) -> IO a
78 content <- Enc.decodeUtf8 <$> BS.readFile fp
82 newtype ComptaG src ss a = ComptaG (forall j. P.ParsecT P.Dec Text (S.StateT (Context_Read src j) (S.StateT (Context_Sym src ss) IO)) a)
83 instance Functor (ComptaG src ss) where
84 fmap f (ComptaG m) = ComptaG (fmap f m)
85 instance Applicative (ComptaG src ss) where
86 pure a = ComptaG (pure a)
87 ComptaG f <*> ComptaG a = ComptaG (f <*> a)
88 instance Monad (ComptaG src ss) where
90 ComptaG m >>= f = ComptaG (m >>= \a -> case f a of ComptaG b -> b)
95 g ~ P.ParsecT P.Dec Text (S.StateT (Context_Read src) (S.StateT (Context_Sym src ss) IO)) =>
98 SourceInj (Sym.AST_Type src) src =>
99 SourceInj (Sym.KindK src) src =>
100 SourceInj (Sym.TypeVT src) src =>
102 Sym.Gram_Term_Atoms src ss g =>
103 Sym.ImportTypes ss =>
104 Sym.ModulesTyInj ss =>
105 Sym.ModulesInj src ss =>
109 (Transaction -> j -> j) ->
110 IO (( Either (P.ParseError Char P.Dec)
111 (S.Either [At src (Error_Compta src)] CanonFile)
113 , Context_Sym src ss )
114 readJournal path consTxn = readFile path $ read consTxn $ g_compta @ss
122 (Transaction -> j -> j) ->
124 IO (Either (Error_Read src) (Compta src ss j, [At src Warning_Compta]))
125 readCompta consTxn path = do
126 ((r, Context_Read{context_read_journals=(compta_journals::Journals j'), ..}), Context_Sym{..}) <-
127 readFile path (read @(Sym.Proxy (Compta src ss) ': ss) @src consTxn $ g_compta @(Sym.Proxy (Compta src ss) ': ss) @src)
129 Left err -> Left $ Error_Read_Syntax err
130 Right r' | Just (Sym.Refl :: j Sym.:~: j') <- eqT ->
132 S.Left err -> Left $ Error_Read_Semantic err
133 S.Right _r'' -> Right $ (,context_read_warnings) Compta
135 , compta_chart = context_read_chart
136 , compta_style_amounts = context_read_style_amounts
137 , compta_modules = context_sym_modules
138 , compta_terms = context_sym_terms
141 consTransactions :: Transaction -> Map Date [Transaction] -> Map Date [Transaction]
142 consTransactions t = Map.insertWith (<>) (transaction_date t) [t]
144 type ComptaT src ss =
146 (S.StateT (Context_Read src)
147 (S.StateT (Context_Sym src (Sym.Proxy (Compta src ss) ': ss))
150 type Comptable src ss =
153 , SourceInj (Sym.AST_Type src) src
154 , SourceInj (Sym.KindK src) src
155 , SourceInj (Sym.TypeVT src) src
156 , Gram_Source src (ComptaT src ss)
157 , Sym.Gram_Term_Atoms src (Sym.Proxy (Compta src ss) ': ss) (ComptaT src ss)
158 -- , Sym.Gram_Term_AtomsFor src (Sym.Proxy (Compta src ss) : ss) (ComptaT src ss j) (Compta src ss)
159 -- , Sym.Gram_Term_AtomsR src (Sym.Proxy (Compta src ss) : ss) ss (ComptaT src ss j)
160 -- (P.ParsecT P.Dec Text (S.StateT (Context_Read src j) (S.StateT (Context_Sym src (Sym.Proxy (Compta src ss) : ss)) IO))) (Compta src ss)
161 , Sym.ImportTypes (Sym.Proxy (Compta src ss) ': ss)
162 , Sym.ModulesTyInj (Sym.Proxy (Compta src ss) ': ss)
163 , Sym.ModulesInj src (Sym.Proxy (Compta src ss) ': ss)
168 instance Comptable src ss =>
169 FromFile (Compta src ss (Map Date [Transaction])) where
170 fromFile (PathFile p) =
171 readCompta consTransactions p >>= \case
172 Left err -> error $ show err
173 Right (a, warns) -> do
177 -- * Type 'Error_Read'
179 = Error_Read_Syntax (P.ParseError Char P.Dec)
180 | Error_Read_Semantic [At src (Error_Compta src)]
185 :: (Consable c j, Monoid j)
188 -> ExceptT [R.Error Error_Read] IO (Journal j)
192 (Right <$> Text.IO.readFile path) $
193 \ko -> return $ Left $
194 [R.Error_Custom (R.initialPos path) $
195 Error_Read_reading_file path ko])
196 >>= liftIO . R.runParserTWithError
197 (read_journal path) ctx path
199 Left ko -> throwE $ ko
200 Right ok -> ExceptT $ return $ Right ok