{- -----------------------------------------------------------------------------
Copyright 2020 Kevin P. Barry

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
----------------------------------------------------------------------------- -}

-- Author: Kevin P. Barry [ta0kira@gmail.com]

{-# LANGUAGE Safe #-}

module Parser.SourceFile (
  parseInternalSource,
  parsePublicSource,
  parseTestSource,
) where

import Text.Parsec
import Text.Parsec.String

import Base.CompileError
import Parser.Common
import Parser.DefinedCategory
import Parser.IntegrationTest ()
import Parser.Pragma
import Parser.TypeCategory ()
import Types.DefinedCategory
import Types.IntegrationTest
import Types.Pragma
import Types.TypeCategory


parseInternalSource :: CompileErrorM m =>
  (FilePath,String) -> m ([Pragma SourcePos],[AnyCategory SourcePos],[DefinedCategory SourcePos])
parseInternalSource :: (FilePath, FilePath)
-> m ([Pragma SourcePos], [AnyCategory SourcePos],
      [DefinedCategory SourcePos])
parseInternalSource (FilePath
f,FilePath
s) = Either
  ParseError
  ([Pragma SourcePos], [AnyCategory SourcePos],
   [DefinedCategory SourcePos])
-> m ([Pragma SourcePos], [AnyCategory SourcePos],
      [DefinedCategory SourcePos])
forall (m :: * -> *) a a.
(CompileErrorM m, Show a) =>
Either a a -> m a
unwrap Either
  ParseError
  ([Pragma SourcePos], [AnyCategory SourcePos],
   [DefinedCategory SourcePos])
parsed where
  parsed :: Either
  ParseError
  ([Pragma SourcePos], [AnyCategory SourcePos],
   [DefinedCategory SourcePos])
parsed = Parsec
  FilePath
  ()
  ([Pragma SourcePos], [AnyCategory SourcePos],
   [DefinedCategory SourcePos])
-> FilePath
-> FilePath
-> Either
     ParseError
     ([Pragma SourcePos], [AnyCategory SourcePos],
      [DefinedCategory SourcePos])
forall s t a.
Stream s Identity t =>
Parsec s () a -> FilePath -> s -> Either ParseError a
parse (ParsecT FilePath () Identity ()
-> ParsecT FilePath () Identity ()
-> Parsec
     FilePath
     ()
     ([Pragma SourcePos], [AnyCategory SourcePos],
      [DefinedCategory SourcePos])
-> Parsec
     FilePath
     ()
     ([Pragma SourcePos], [AnyCategory SourcePos],
      [DefinedCategory SourcePos])
forall s (m :: * -> *) t u open close a.
Stream s m t =>
ParsecT s u m open
-> ParsecT s u m close -> ParsecT s u m a -> ParsecT s u m a
between ParsecT FilePath () Identity ()
optionalSpace ParsecT FilePath () Identity ()
endOfDoc Parsec
  FilePath
  ()
  ([Pragma SourcePos], [AnyCategory SourcePos],
   [DefinedCategory SourcePos])
withPragmas) FilePath
f FilePath
s
  unwrap :: Either a a -> m a
unwrap (Left a
e)  = FilePath -> m a
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (a -> FilePath
forall a. Show a => a -> FilePath
show a
e)
  unwrap (Right a
t) = a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
t
  withPragmas :: Parsec
  FilePath
  ()
  ([Pragma SourcePos], [AnyCategory SourcePos],
   [DefinedCategory SourcePos])
withPragmas = do
    [Pragma SourcePos]
pragmas <- [Parser (Pragma SourcePos)] -> Parser [Pragma SourcePos]
forall a. [Parser a] -> Parser [a]
parsePragmas [Parser (Pragma SourcePos)]
internalSourcePragmas
    ParsecT FilePath () Identity ()
optionalSpace
    ([AnyCategory SourcePos]
cs,[DefinedCategory SourcePos]
ds) <- Parser ([AnyCategory SourcePos], [DefinedCategory SourcePos])
parseAnySource
    ([Pragma SourcePos], [AnyCategory SourcePos],
 [DefinedCategory SourcePos])
-> Parsec
     FilePath
     ()
     ([Pragma SourcePos], [AnyCategory SourcePos],
      [DefinedCategory SourcePos])
forall (m :: * -> *) a. Monad m => a -> m a
return ([Pragma SourcePos]
pragmas,[AnyCategory SourcePos]
cs,[DefinedCategory SourcePos]
ds)

parsePublicSource :: CompileErrorM m => (FilePath,String) -> m ([Pragma SourcePos],[AnyCategory SourcePos])
parsePublicSource :: (FilePath, FilePath)
-> m ([Pragma SourcePos], [AnyCategory SourcePos])
parsePublicSource (FilePath
f,FilePath
s) = Either ParseError ([Pragma SourcePos], [AnyCategory SourcePos])
-> m ([Pragma SourcePos], [AnyCategory SourcePos])
forall (m :: * -> *) a a.
(CompileErrorM m, Show a) =>
Either a a -> m a
unwrap Either ParseError ([Pragma SourcePos], [AnyCategory SourcePos])
parsed where
  parsed :: Either ParseError ([Pragma SourcePos], [AnyCategory SourcePos])
parsed = Parsec FilePath () ([Pragma SourcePos], [AnyCategory SourcePos])
-> FilePath
-> FilePath
-> Either ParseError ([Pragma SourcePos], [AnyCategory SourcePos])
forall s t a.
Stream s Identity t =>
Parsec s () a -> FilePath -> s -> Either ParseError a
parse (ParsecT FilePath () Identity ()
-> ParsecT FilePath () Identity ()
-> Parsec FilePath () ([Pragma SourcePos], [AnyCategory SourcePos])
-> Parsec FilePath () ([Pragma SourcePos], [AnyCategory SourcePos])
forall s (m :: * -> *) t u open close a.
Stream s m t =>
ParsecT s u m open
-> ParsecT s u m close -> ParsecT s u m a -> ParsecT s u m a
between ParsecT FilePath () Identity ()
optionalSpace ParsecT FilePath () Identity ()
endOfDoc Parsec FilePath () ([Pragma SourcePos], [AnyCategory SourcePos])
withPragmas) FilePath
f FilePath
s
  unwrap :: Either a a -> m a
unwrap (Left a
e)  = FilePath -> m a
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (a -> FilePath
forall a. Show a => a -> FilePath
show a
e)
  unwrap (Right a
t) = a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
t
  withPragmas :: Parsec FilePath () ([Pragma SourcePos], [AnyCategory SourcePos])
withPragmas = do
    [Pragma SourcePos]
pragmas <- [Parser (Pragma SourcePos)] -> Parser [Pragma SourcePos]
forall a. [Parser a] -> Parser [a]
parsePragmas [Parser (Pragma SourcePos)]
publicSourcePragmas
    ParsecT FilePath () Identity ()
optionalSpace
    [AnyCategory SourcePos]
cs <- ParsecT FilePath () Identity (AnyCategory SourcePos)
-> ParsecT FilePath () Identity ()
-> ParsecT FilePath () Identity [AnyCategory SourcePos]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
sepBy ParsecT FilePath () Identity (AnyCategory SourcePos)
forall a. ParseFromSource a => Parser a
sourceParser ParsecT FilePath () Identity ()
optionalSpace
    ([Pragma SourcePos], [AnyCategory SourcePos])
-> Parsec FilePath () ([Pragma SourcePos], [AnyCategory SourcePos])
forall (m :: * -> *) a. Monad m => a -> m a
return ([Pragma SourcePos]
pragmas,[AnyCategory SourcePos]
cs)

parseTestSource :: CompileErrorM m => (FilePath,String) -> m ([Pragma SourcePos],[IntegrationTest SourcePos])
parseTestSource :: (FilePath, FilePath)
-> m ([Pragma SourcePos], [IntegrationTest SourcePos])
parseTestSource (FilePath
f,FilePath
s) = Either ParseError ([Pragma SourcePos], [IntegrationTest SourcePos])
-> m ([Pragma SourcePos], [IntegrationTest SourcePos])
forall (m :: * -> *) a a.
(CompileErrorM m, Show a) =>
Either a a -> m a
unwrap Either ParseError ([Pragma SourcePos], [IntegrationTest SourcePos])
parsed where
  parsed :: Either ParseError ([Pragma SourcePos], [IntegrationTest SourcePos])
parsed = Parsec
  FilePath () ([Pragma SourcePos], [IntegrationTest SourcePos])
-> FilePath
-> FilePath
-> Either
     ParseError ([Pragma SourcePos], [IntegrationTest SourcePos])
forall s t a.
Stream s Identity t =>
Parsec s () a -> FilePath -> s -> Either ParseError a
parse (ParsecT FilePath () Identity ()
-> ParsecT FilePath () Identity ()
-> Parsec
     FilePath () ([Pragma SourcePos], [IntegrationTest SourcePos])
-> Parsec
     FilePath () ([Pragma SourcePos], [IntegrationTest SourcePos])
forall s (m :: * -> *) t u open close a.
Stream s m t =>
ParsecT s u m open
-> ParsecT s u m close -> ParsecT s u m a -> ParsecT s u m a
between ParsecT FilePath () Identity ()
optionalSpace ParsecT FilePath () Identity ()
endOfDoc Parsec
  FilePath () ([Pragma SourcePos], [IntegrationTest SourcePos])
withPragmas) FilePath
f FilePath
s
  unwrap :: Either a a -> m a
unwrap (Left a
e)  = FilePath -> m a
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (a -> FilePath
forall a. Show a => a -> FilePath
show a
e)
  unwrap (Right a
t) = a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
t
  withPragmas :: Parsec
  FilePath () ([Pragma SourcePos], [IntegrationTest SourcePos])
withPragmas = do
    [Pragma SourcePos]
pragmas <- [Parser (Pragma SourcePos)] -> Parser [Pragma SourcePos]
forall a. [Parser a] -> Parser [a]
parsePragmas [Parser (Pragma SourcePos)]
testSourcePragmas
    ParsecT FilePath () Identity ()
optionalSpace
    [IntegrationTest SourcePos]
ts <- ParsecT FilePath () Identity (IntegrationTest SourcePos)
-> ParsecT FilePath () Identity ()
-> ParsecT FilePath () Identity [IntegrationTest SourcePos]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
sepBy ParsecT FilePath () Identity (IntegrationTest SourcePos)
forall a. ParseFromSource a => Parser a
sourceParser ParsecT FilePath () Identity ()
optionalSpace
    ([Pragma SourcePos], [IntegrationTest SourcePos])
-> Parsec
     FilePath () ([Pragma SourcePos], [IntegrationTest SourcePos])
forall (m :: * -> *) a. Monad m => a -> m a
return ([Pragma SourcePos]
pragmas,[IntegrationTest SourcePos]
ts)

publicSourcePragmas :: [Parser (Pragma SourcePos)]
publicSourcePragmas :: [Parser (Pragma SourcePos)]
publicSourcePragmas = [Parser (Pragma SourcePos)
pragmaModuleOnly,Parser (Pragma SourcePos)
pragmaTestsOnly]

internalSourcePragmas :: [Parser (Pragma SourcePos)]
internalSourcePragmas :: [Parser (Pragma SourcePos)]
internalSourcePragmas = [Parser (Pragma SourcePos)
pragmaTestsOnly]

testSourcePragmas :: [Parser (Pragma SourcePos)]
testSourcePragmas :: [Parser (Pragma SourcePos)]
testSourcePragmas = []