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 where
11 import Control.Applicative (Applicative(..), (<*))
12 import Control.Monad (Monad(..))
13 import Data.Char (Char)
14 import Data.Either (Either(..))
16 import Data.Function (($), (.))
17 import Data.Functor (Functor(..), (<$>))
18 import Data.Map.Strict (Map)
19 import Data.Maybe (Maybe(..))
20 import Data.Monoid (Monoid(..))
21 import Data.Semigroup (Semigroup(..))
22 import Data.Text (Text)
23 import Data.Typeable (Typeable, eqT)
24 import System.FilePath (FilePath)
25 import System.IO (IO, hPrint, stderr)
26 import Text.Show (Show(..))
27 import Prelude (error)
28 import qualified Data.ByteString as BS
29 import qualified Data.Map.Strict as Map
30 import qualified Data.Strict as S
31 import qualified Data.Text.Encoding as Enc
32 import qualified System.FilePath as FilePath
33 import qualified Text.Megaparsec as P
35 import Language.Symantic.Grammar
36 import qualified Language.Symantic as Sym
37 import Language.Symantic.Lib ()
39 import Hcompta.LCC.Journal
40 import Hcompta.LCC.Compta
41 import Hcompta.LCC.Posting
42 import Hcompta.LCC.Transaction
44 -- import Hcompta.LCC.Sym.Compta ()
46 import Hcompta.LCC.Grammar
47 import Hcompta.LCC.Megaparsec ()
48 import qualified Hcompta.LCC.Lib.Strict as S
49 import qualified Hcompta as H
51 -- import qualified Control.Monad.Classes as MC
54 forall ss src e m j a.
57 Sym.ModulesTyInj ss =>
58 Sym.ModulesInj src ss =>
59 m ~ S.StateT (Context_Read src) (S.StateT (Context_Sym src ss) IO) =>
60 e ~ P.ParseError Char P.Dec =>
63 (Transaction -> j -> j) ->
64 CF (P.ParsecT P.Dec Text m) a ->
66 IO ((Either e a, Context_Read src), Context_Sym src ss)
67 read consTxn g fp inp =
68 S.runState context_sym $
69 S.runState (context_read consTxn) $
70 P.runParserT (unCF $ g <* eoi) (FilePath.normalise fp) inp
72 readFile :: FilePath -> (FilePath -> Text -> IO a) -> IO a
74 content <- Enc.decodeUtf8 <$> BS.readFile fp
78 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)
79 instance Functor (ComptaG src ss) where
80 fmap f (ComptaG m) = ComptaG (fmap f m)
81 instance Applicative (ComptaG src ss) where
82 pure a = ComptaG (pure a)
83 ComptaG f <*> ComptaG a = ComptaG (f <*> a)
84 instance Monad (ComptaG src ss) where
86 ComptaG m >>= f = ComptaG (m >>= \a -> case f a of ComptaG b -> b)
91 g ~ P.ParsecT P.Dec Text (S.StateT (Context_Read src) (S.StateT (Context_Sym src ss) IO)) =>
94 SourceInj (Sym.AST_Type src) src =>
95 SourceInj (Sym.KindK src) src =>
96 SourceInj (Sym.TypeVT src) src =>
98 Sym.Gram_Term_Atoms src ss g =>
100 Sym.ModulesTyInj ss =>
101 Sym.ModulesInj src ss =>
105 (Transaction -> j -> j) ->
106 IO (( Either (P.ParseError Char P.Dec)
107 (S.Either [At src (Error_Compta src)] CanonFile)
109 , Context_Sym src ss )
110 readJournal path consTxn = readFile path $ read consTxn $ g_compta @ss
118 (Transaction -> j -> j) ->
120 IO (Either (Error_Read src) (Compta src ss j, [At src Warning_Compta]))
121 readCompta consTxn path = do
122 ((r, Context_Read{context_read_journals=(compta_journals::Journals j'), ..}), Context_Sym{..}) <-
123 readFile path (read @(Sym.Proxy (Compta src ss) ': ss) @src consTxn $ g_compta @(Sym.Proxy (Compta src ss) ': ss) @src)
125 Left err -> Left $ Error_Read_Syntax err
126 Right r' | Just (Sym.Refl :: j Sym.:~: j') <- eqT ->
128 S.Left err -> Left $ Error_Read_Semantic err
129 S.Right _r'' -> Right $ (,context_read_warnings) Compta
131 , compta_chart = context_read_chart
132 , compta_style_amounts = context_read_style_amounts
133 , compta_modules = context_sym_modules
134 , compta_terms = context_sym_terms
137 consTransactions :: Transaction -> Map Date [Transaction] -> Map Date [Transaction]
138 consTransactions t = Map.insertWith (<>) (transaction_date t) [t]
140 type ComptaT src ss =
142 (S.StateT (Context_Read src)
143 (S.StateT (Context_Sym src (Sym.Proxy (Compta src ss) ': ss))
146 type Comptable src ss =
149 , SourceInj (Sym.AST_Type src) src
150 , SourceInj (Sym.KindK src) src
151 , SourceInj (Sym.TypeVT src) src
152 , Gram_Source src (ComptaT src ss)
153 , Sym.Gram_Term_Atoms src (Sym.Proxy (Compta src ss) ': ss) (ComptaT src ss)
154 -- , Sym.Gram_Term_AtomsFor src (Sym.Proxy (Compta src ss) : ss) (ComptaT src ss j) (Compta src ss)
155 -- , Sym.Gram_Term_AtomsR src (Sym.Proxy (Compta src ss) : ss) ss (ComptaT src ss j)
156 -- (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)
157 , Sym.ImportTypes (Sym.Proxy (Compta src ss) ': ss)
158 , Sym.ModulesTyInj (Sym.Proxy (Compta src ss) ': ss)
159 , Sym.ModulesInj src (Sym.Proxy (Compta src ss) ': ss)
164 instance Comptable src ss =>
165 FromFile (Compta src ss (Map Date [Transaction])) where
166 fromFile (PathFile p) =
167 readCompta consTransactions p >>= \case
168 Left err -> error $ show err
169 Right (a, warns) -> do
173 -- * Type 'Error_Read'
175 = Error_Read_Syntax (P.ParseError Char P.Dec)
176 | Error_Read_Semantic [At src (Error_Compta src)]
181 :: (Consable c j, Monoid j)
184 -> ExceptT [R.Error Error_Read] IO (Journal j)
188 (Right <$> Text.IO.readFile path) $
189 \ko -> return $ Left $
190 [R.Error_Custom (R.initialPos path) $
191 Error_Read_reading_file path ko])
192 >>= liftIO . R.runParserTWithError
193 (read_journal path) ctx path
195 Left ko -> throwE $ ko
196 Right ok -> ExceptT $ return $ Right ok