{- -----------------------------------------------------------------------------
Copyright 2019-2021 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 FlexibleInstances #-}

module Parser.DefinedCategory (
) where

import Prelude hiding (pi)

import Base.CompilerError
import Parser.Common
import Parser.Pragma (autoPragma)
import Parser.Procedure ()
import Parser.TextParser hiding (hidden)
import Parser.TypeCategory
import Parser.TypeInstance ()
import Types.DefinedCategory
import Types.Procedure
import Types.TypeCategory
import Types.TypeInstance


instance ParseFromSource (DefinedCategory SourceContext) where
  sourceParser :: TextParser (DefinedCategory SourceContext)
sourceParser = String
-> TextParser (DefinedCategory SourceContext)
-> TextParser (DefinedCategory SourceContext)
forall a. String -> TextParser a -> TextParser a
labeled String
"defined concrete category" (TextParser (DefinedCategory SourceContext)
 -> TextParser (DefinedCategory SourceContext))
-> TextParser (DefinedCategory SourceContext)
-> TextParser (DefinedCategory SourceContext)
forall a b. (a -> b) -> a -> b
$ do
    SourceContext
c <- TextParser SourceContext
getSourceContext
    TextParser ()
kwDefine
    CategoryName
n <- TextParser CategoryName
forall a. ParseFromSource a => TextParser a
sourceParser
    TextParser () -> TextParser ()
forall a. TextParser a -> TextParser a
sepAfter (String -> TextParser ()
string_ String
"{")
    [PragmaDefined SourceContext]
pragmas <- ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
-> TextParser ()
-> ParsecT
     CompilerMessage String Identity [PragmaDefined SourceContext]
forall (m :: * -> *) a sep. MonadPlus m => m a -> m sep -> m [a]
sepBy ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
singlePragma TextParser ()
optionalSpace
    ([ValueRefine SourceContext]
ds,[ValueDefine SourceContext]
rs) <- ParsecT
  CompilerMessage
  String
  Identity
  ([ValueRefine SourceContext], [ValueDefine SourceContext])
parseRefinesDefines
    ([DefinedMember SourceContext]
ms,[ExecutableProcedure SourceContext]
ps,[ScopedFunction SourceContext]
fs) <- CategoryName
-> TextParser
     ([DefinedMember SourceContext],
      [ExecutableProcedure SourceContext],
      [ScopedFunction SourceContext])
parseMemberProcedureFunction CategoryName
n
    TextParser () -> TextParser ()
forall a. TextParser a -> TextParser a
sepAfter (String -> TextParser ()
string_ String
"}")
    DefinedCategory SourceContext
-> TextParser (DefinedCategory SourceContext)
forall a. a -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (DefinedCategory SourceContext
 -> TextParser (DefinedCategory SourceContext))
-> DefinedCategory SourceContext
-> TextParser (DefinedCategory SourceContext)
forall a b. (a -> b) -> a -> b
$ [SourceContext]
-> CategoryName
-> [PragmaDefined SourceContext]
-> [ValueRefine SourceContext]
-> [ValueDefine SourceContext]
-> [DefinedMember SourceContext]
-> [ExecutableProcedure SourceContext]
-> [ScopedFunction SourceContext]
-> DefinedCategory SourceContext
forall c.
[c]
-> CategoryName
-> [PragmaDefined c]
-> [ValueRefine c]
-> [ValueDefine c]
-> [DefinedMember c]
-> [ExecutableProcedure c]
-> [ScopedFunction c]
-> DefinedCategory c
DefinedCategory [SourceContext
c] CategoryName
n [PragmaDefined SourceContext]
pragmas [ValueRefine SourceContext]
ds [ValueDefine SourceContext]
rs [DefinedMember SourceContext]
ms [ExecutableProcedure SourceContext]
ps [ScopedFunction SourceContext]
fs
    where
      parseRefinesDefines :: ParsecT
  CompilerMessage
  String
  Identity
  ([ValueRefine SourceContext], [ValueDefine SourceContext])
parseRefinesDefines = ([([ValueRefine SourceContext], [ValueDefine SourceContext])]
 -> ([ValueRefine SourceContext], [ValueDefine SourceContext]))
-> ParsecT
     CompilerMessage
     String
     Identity
     [([ValueRefine SourceContext], [ValueDefine SourceContext])]
-> ParsecT
     CompilerMessage
     String
     Identity
     ([ValueRefine SourceContext], [ValueDefine SourceContext])
forall a b.
(a -> b)
-> ParsecT CompilerMessage String Identity a
-> ParsecT CompilerMessage String Identity b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [([ValueRefine SourceContext], [ValueDefine SourceContext])]
-> ([ValueRefine SourceContext], [ValueDefine SourceContext])
forall (f :: * -> *) a b.
(Foldable f, Monoid a, Monoid b) =>
f (a, b) -> (a, b)
merge2 (ParsecT
   CompilerMessage
   String
   Identity
   [([ValueRefine SourceContext], [ValueDefine SourceContext])]
 -> ParsecT
      CompilerMessage
      String
      Identity
      ([ValueRefine SourceContext], [ValueDefine SourceContext]))
-> ParsecT
     CompilerMessage
     String
     Identity
     [([ValueRefine SourceContext], [ValueDefine SourceContext])]
-> ParsecT
     CompilerMessage
     String
     Identity
     ([ValueRefine SourceContext], [ValueDefine SourceContext])
forall a b. (a -> b) -> a -> b
$ ParsecT
  CompilerMessage
  String
  Identity
  ([ValueRefine SourceContext], [ValueDefine SourceContext])
-> TextParser ()
-> ParsecT
     CompilerMessage
     String
     Identity
     [([ValueRefine SourceContext], [ValueDefine SourceContext])]
forall (m :: * -> *) a sep. MonadPlus m => m a -> m sep -> m [a]
sepBy ParsecT
  CompilerMessage
  String
  Identity
  ([ValueRefine SourceContext], [ValueDefine SourceContext])
refineOrDefine TextParser ()
optionalSpace
      singlePragma :: ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
singlePragma = ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
readOnly ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall a.
ParsecT CompilerMessage String Identity a
-> ParsecT CompilerMessage String Identity a
-> ParsecT CompilerMessage String Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
readOnlyExcept ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall a.
ParsecT CompilerMessage String Identity a
-> ParsecT CompilerMessage String Identity a
-> ParsecT CompilerMessage String Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
hidden ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall a.
ParsecT CompilerMessage String Identity a
-> ParsecT CompilerMessage String Identity a
-> ParsecT CompilerMessage String Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
flatCleanup
      flatCleanup :: ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
flatCleanup = String
-> Either
     (SourceContext -> PragmaDefined SourceContext)
     (SourceContext
      -> ParsecT
           CompilerMessage String Identity (PragmaDefined SourceContext))
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall a.
String
-> Either (SourceContext -> a) (SourceContext -> TextParser a)
-> TextParser a
autoPragma String
"FlatCleanup" (Either
   (SourceContext -> PragmaDefined SourceContext)
   (SourceContext
    -> ParsecT
         CompilerMessage String Identity (PragmaDefined SourceContext))
 -> ParsecT
      CompilerMessage String Identity (PragmaDefined SourceContext))
-> Either
     (SourceContext -> PragmaDefined SourceContext)
     (SourceContext
      -> ParsecT
           CompilerMessage String Identity (PragmaDefined SourceContext))
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall a b. (a -> b) -> a -> b
$ (SourceContext
 -> ParsecT
      CompilerMessage String Identity (PragmaDefined SourceContext))
-> Either
     (SourceContext -> PragmaDefined SourceContext)
     (SourceContext
      -> ParsecT
           CompilerMessage String Identity (PragmaDefined SourceContext))
forall a b. b -> Either a b
Right SourceContext
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall {c}.
c -> ParsecT CompilerMessage String Identity (PragmaDefined c)
parseAt where
        parseAt :: c -> ParsecT CompilerMessage String Identity (PragmaDefined c)
parseAt c
c = do
          VariableName
v <- String -> TextParser VariableName -> TextParser VariableName
forall a. String -> TextParser a -> TextParser a
labeled String
"variable name" TextParser VariableName
forall a. ParseFromSource a => TextParser a
sourceParser
          PragmaDefined c
-> ParsecT CompilerMessage String Identity (PragmaDefined c)
forall a. a -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (PragmaDefined c
 -> ParsecT CompilerMessage String Identity (PragmaDefined c))
-> PragmaDefined c
-> ParsecT CompilerMessage String Identity (PragmaDefined c)
forall a b. (a -> b) -> a -> b
$ [c] -> VariableName -> PragmaDefined c
forall c. [c] -> VariableName -> PragmaDefined c
FlatCleanup [c
c] VariableName
v
      readOnly :: ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
readOnly = String
-> Either
     (SourceContext -> PragmaDefined SourceContext)
     (SourceContext
      -> ParsecT
           CompilerMessage String Identity (PragmaDefined SourceContext))
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall a.
String
-> Either (SourceContext -> a) (SourceContext -> TextParser a)
-> TextParser a
autoPragma String
"ReadOnly" (Either
   (SourceContext -> PragmaDefined SourceContext)
   (SourceContext
    -> ParsecT
         CompilerMessage String Identity (PragmaDefined SourceContext))
 -> ParsecT
      CompilerMessage String Identity (PragmaDefined SourceContext))
-> Either
     (SourceContext -> PragmaDefined SourceContext)
     (SourceContext
      -> ParsecT
           CompilerMessage String Identity (PragmaDefined SourceContext))
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall a b. (a -> b) -> a -> b
$ (SourceContext
 -> ParsecT
      CompilerMessage String Identity (PragmaDefined SourceContext))
-> Either
     (SourceContext -> PragmaDefined SourceContext)
     (SourceContext
      -> ParsecT
           CompilerMessage String Identity (PragmaDefined SourceContext))
forall a b. b -> Either a b
Right SourceContext
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall {c}.
c -> ParsecT CompilerMessage String Identity (PragmaDefined c)
parseAt where
        parseAt :: c -> ParsecT CompilerMessage String Identity (PragmaDefined c)
parseAt c
c = do
          [VariableName]
vs <- String -> TextParser [VariableName] -> TextParser [VariableName]
forall a. String -> TextParser a -> TextParser a
labeled String
"variable names" (TextParser [VariableName] -> TextParser [VariableName])
-> TextParser [VariableName] -> TextParser [VariableName]
forall a b. (a -> b) -> a -> b
$ TextParser VariableName
-> ParsecT CompilerMessage String Identity (Tokens String)
-> TextParser [VariableName]
forall (m :: * -> *) a sep. MonadPlus m => m a -> m sep -> m [a]
sepBy TextParser VariableName
forall a. ParseFromSource a => TextParser a
sourceParser (ParsecT CompilerMessage String Identity (Tokens String)
-> ParsecT CompilerMessage String Identity (Tokens String)
forall a. TextParser a -> TextParser a
sepAfter (ParsecT CompilerMessage String Identity (Tokens String)
 -> ParsecT CompilerMessage String Identity (Tokens String))
-> ParsecT CompilerMessage String Identity (Tokens String)
-> ParsecT CompilerMessage String Identity (Tokens String)
forall a b. (a -> b) -> a -> b
$ Tokens String
-> ParsecT CompilerMessage String Identity (Tokens String)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string String
Tokens String
",")
          PragmaDefined c
-> ParsecT CompilerMessage String Identity (PragmaDefined c)
forall a. a -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (PragmaDefined c
 -> ParsecT CompilerMessage String Identity (PragmaDefined c))
-> PragmaDefined c
-> ParsecT CompilerMessage String Identity (PragmaDefined c)
forall a b. (a -> b) -> a -> b
$ [c] -> [VariableName] -> PragmaDefined c
forall c. [c] -> [VariableName] -> PragmaDefined c
MembersReadOnly [c
c] [VariableName]
vs
      readOnlyExcept :: ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
readOnlyExcept = String
-> Either
     (SourceContext -> PragmaDefined SourceContext)
     (SourceContext
      -> ParsecT
           CompilerMessage String Identity (PragmaDefined SourceContext))
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall a.
String
-> Either (SourceContext -> a) (SourceContext -> TextParser a)
-> TextParser a
autoPragma String
"ReadOnlyExcept" (Either
   (SourceContext -> PragmaDefined SourceContext)
   (SourceContext
    -> ParsecT
         CompilerMessage String Identity (PragmaDefined SourceContext))
 -> ParsecT
      CompilerMessage String Identity (PragmaDefined SourceContext))
-> Either
     (SourceContext -> PragmaDefined SourceContext)
     (SourceContext
      -> ParsecT
           CompilerMessage String Identity (PragmaDefined SourceContext))
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall a b. (a -> b) -> a -> b
$ (SourceContext
 -> ParsecT
      CompilerMessage String Identity (PragmaDefined SourceContext))
-> Either
     (SourceContext -> PragmaDefined SourceContext)
     (SourceContext
      -> ParsecT
           CompilerMessage String Identity (PragmaDefined SourceContext))
forall a b. b -> Either a b
Right SourceContext
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall {c}.
c -> ParsecT CompilerMessage String Identity (PragmaDefined c)
parseAt where
        parseAt :: c -> ParsecT CompilerMessage String Identity (PragmaDefined c)
parseAt c
c = do
          [VariableName]
vs <- String -> TextParser [VariableName] -> TextParser [VariableName]
forall a. String -> TextParser a -> TextParser a
labeled String
"variable names" (TextParser [VariableName] -> TextParser [VariableName])
-> TextParser [VariableName] -> TextParser [VariableName]
forall a b. (a -> b) -> a -> b
$ TextParser VariableName
-> ParsecT CompilerMessage String Identity (Tokens String)
-> TextParser [VariableName]
forall (m :: * -> *) a sep. MonadPlus m => m a -> m sep -> m [a]
sepBy TextParser VariableName
forall a. ParseFromSource a => TextParser a
sourceParser (ParsecT CompilerMessage String Identity (Tokens String)
-> ParsecT CompilerMessage String Identity (Tokens String)
forall a. TextParser a -> TextParser a
sepAfter (ParsecT CompilerMessage String Identity (Tokens String)
 -> ParsecT CompilerMessage String Identity (Tokens String))
-> ParsecT CompilerMessage String Identity (Tokens String)
-> ParsecT CompilerMessage String Identity (Tokens String)
forall a b. (a -> b) -> a -> b
$ Tokens String
-> ParsecT CompilerMessage String Identity (Tokens String)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string String
Tokens String
",")
          PragmaDefined c
-> ParsecT CompilerMessage String Identity (PragmaDefined c)
forall a. a -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (PragmaDefined c
 -> ParsecT CompilerMessage String Identity (PragmaDefined c))
-> PragmaDefined c
-> ParsecT CompilerMessage String Identity (PragmaDefined c)
forall a b. (a -> b) -> a -> b
$ [c] -> [VariableName] -> PragmaDefined c
forall c. [c] -> [VariableName] -> PragmaDefined c
MembersReadOnlyExcept [c
c] [VariableName]
vs
      hidden :: ParsecT
  CompilerMessage String Identity (PragmaDefined SourceContext)
hidden = String
-> Either
     (SourceContext -> PragmaDefined SourceContext)
     (SourceContext
      -> ParsecT
           CompilerMessage String Identity (PragmaDefined SourceContext))
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall a.
String
-> Either (SourceContext -> a) (SourceContext -> TextParser a)
-> TextParser a
autoPragma String
"Hidden" (Either
   (SourceContext -> PragmaDefined SourceContext)
   (SourceContext
    -> ParsecT
         CompilerMessage String Identity (PragmaDefined SourceContext))
 -> ParsecT
      CompilerMessage String Identity (PragmaDefined SourceContext))
-> Either
     (SourceContext -> PragmaDefined SourceContext)
     (SourceContext
      -> ParsecT
           CompilerMessage String Identity (PragmaDefined SourceContext))
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall a b. (a -> b) -> a -> b
$ (SourceContext
 -> ParsecT
      CompilerMessage String Identity (PragmaDefined SourceContext))
-> Either
     (SourceContext -> PragmaDefined SourceContext)
     (SourceContext
      -> ParsecT
           CompilerMessage String Identity (PragmaDefined SourceContext))
forall a b. b -> Either a b
Right SourceContext
-> ParsecT
     CompilerMessage String Identity (PragmaDefined SourceContext)
forall {c}.
c -> ParsecT CompilerMessage String Identity (PragmaDefined c)
parseAt where
        parseAt :: c -> ParsecT CompilerMessage String Identity (PragmaDefined c)
parseAt c
c = do
          [VariableName]
vs <- String -> TextParser [VariableName] -> TextParser [VariableName]
forall a. String -> TextParser a -> TextParser a
labeled String
"variable names" (TextParser [VariableName] -> TextParser [VariableName])
-> TextParser [VariableName] -> TextParser [VariableName]
forall a b. (a -> b) -> a -> b
$ TextParser VariableName
-> ParsecT CompilerMessage String Identity (Tokens String)
-> TextParser [VariableName]
forall (m :: * -> *) a sep. MonadPlus m => m a -> m sep -> m [a]
sepBy TextParser VariableName
forall a. ParseFromSource a => TextParser a
sourceParser (ParsecT CompilerMessage String Identity (Tokens String)
-> ParsecT CompilerMessage String Identity (Tokens String)
forall a. TextParser a -> TextParser a
sepAfter (ParsecT CompilerMessage String Identity (Tokens String)
 -> ParsecT CompilerMessage String Identity (Tokens String))
-> ParsecT CompilerMessage String Identity (Tokens String)
-> ParsecT CompilerMessage String Identity (Tokens String)
forall a b. (a -> b) -> a -> b
$ Tokens String
-> ParsecT CompilerMessage String Identity (Tokens String)
forall e s (m :: * -> *).
MonadParsec e s m =>
Tokens s -> m (Tokens s)
string String
Tokens String
",")
          PragmaDefined c
-> ParsecT CompilerMessage String Identity (PragmaDefined c)
forall a. a -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (PragmaDefined c
 -> ParsecT CompilerMessage String Identity (PragmaDefined c))
-> PragmaDefined c
-> ParsecT CompilerMessage String Identity (PragmaDefined c)
forall a b. (a -> b) -> a -> b
$ [c] -> [VariableName] -> PragmaDefined c
forall c. [c] -> [VariableName] -> PragmaDefined c
MembersHidden [c
c] [VariableName]
vs
      refineOrDefine :: ParsecT
  CompilerMessage
  String
  Identity
  ([ValueRefine SourceContext], [ValueDefine SourceContext])
refineOrDefine = String
-> ParsecT
     CompilerMessage
     String
     Identity
     ([ValueRefine SourceContext], [ValueDefine SourceContext])
-> ParsecT
     CompilerMessage
     String
     Identity
     ([ValueRefine SourceContext], [ValueDefine SourceContext])
forall a. String -> TextParser a -> TextParser a
labeled String
"refine or define" (ParsecT
   CompilerMessage
   String
   Identity
   ([ValueRefine SourceContext], [ValueDefine SourceContext])
 -> ParsecT
      CompilerMessage
      String
      Identity
      ([ValueRefine SourceContext], [ValueDefine SourceContext]))
-> ParsecT
     CompilerMessage
     String
     Identity
     ([ValueRefine SourceContext], [ValueDefine SourceContext])
-> ParsecT
     CompilerMessage
     String
     Identity
     ([ValueRefine SourceContext], [ValueDefine SourceContext])
forall a b. (a -> b) -> a -> b
$ ParsecT CompilerMessage String Identity (ValueRefine SourceContext)
-> ParsecT
     CompilerMessage
     String
     Identity
     ([ValueRefine SourceContext], [ValueDefine SourceContext])
forall (m :: * -> *) a b.
(Functor m, Monad m) =>
m a -> m ([a], [b])
put12 ParsecT CompilerMessage String Identity (ValueRefine SourceContext)
singleRefine ParsecT
  CompilerMessage
  String
  Identity
  ([ValueRefine SourceContext], [ValueDefine SourceContext])
-> ParsecT
     CompilerMessage
     String
     Identity
     ([ValueRefine SourceContext], [ValueDefine SourceContext])
-> ParsecT
     CompilerMessage
     String
     Identity
     ([ValueRefine SourceContext], [ValueDefine SourceContext])
forall a.
ParsecT CompilerMessage String Identity a
-> ParsecT CompilerMessage String Identity a
-> ParsecT CompilerMessage String Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ParsecT CompilerMessage String Identity (ValueDefine SourceContext)
-> ParsecT
     CompilerMessage
     String
     Identity
     ([ValueRefine SourceContext], [ValueDefine SourceContext])
forall (m :: * -> *) b a.
(Functor m, Monad m) =>
m b -> m ([a], [b])
put22 ParsecT CompilerMessage String Identity (ValueDefine SourceContext)
singleDefine

instance ParseFromSource (DefinedMember SourceContext) where
  sourceParser :: TextParser (DefinedMember SourceContext)
sourceParser = String
-> TextParser (DefinedMember SourceContext)
-> TextParser (DefinedMember SourceContext)
forall a. String -> TextParser a -> TextParser a
labeled String
"defined member" (TextParser (DefinedMember SourceContext)
 -> TextParser (DefinedMember SourceContext))
-> TextParser (DefinedMember SourceContext)
-> TextParser (DefinedMember SourceContext)
forall a b. (a -> b) -> a -> b
$ do
    SourceContext
c <- TextParser SourceContext
getSourceContext
    (SymbolScope
s,ValueType
t) <- ParsecT CompilerMessage String Identity (SymbolScope, ValueType)
-> ParsecT CompilerMessage String Identity (SymbolScope, ValueType)
forall a. TextParser a -> TextParser a
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try ParsecT CompilerMessage String Identity (SymbolScope, ValueType)
parseType
    VariableName
n <- TextParser VariableName
forall a. ParseFromSource a => TextParser a
sourceParser
    Maybe (Expression SourceContext)
e <- if SymbolScope
s SymbolScope -> SymbolScope -> Bool
forall a. Eq a => a -> a -> Bool
== SymbolScope
ValueScope
            then Maybe (Expression SourceContext)
-> TextParser (Maybe (Expression SourceContext))
forall a. a -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Expression SourceContext)
forall a. Maybe a
Nothing
            else TextParser (Maybe (Expression SourceContext))
parseInit
    DefinedMember SourceContext
-> TextParser (DefinedMember SourceContext)
forall a. a -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (DefinedMember SourceContext
 -> TextParser (DefinedMember SourceContext))
-> DefinedMember SourceContext
-> TextParser (DefinedMember SourceContext)
forall a b. (a -> b) -> a -> b
$ [SourceContext]
-> SymbolScope
-> ValueType
-> VariableName
-> Maybe (Expression SourceContext)
-> DefinedMember SourceContext
forall c.
[c]
-> SymbolScope
-> ValueType
-> VariableName
-> Maybe (Expression c)
-> DefinedMember c
DefinedMember [SourceContext
c] SymbolScope
s ValueType
t VariableName
n Maybe (Expression SourceContext)
e
    where
      parseInit :: TextParser (Maybe (Expression SourceContext))
parseInit = String
-> TextParser (Maybe (Expression SourceContext))
-> TextParser (Maybe (Expression SourceContext))
forall a. String -> TextParser a -> TextParser a
labeled String
"member initializer" (TextParser (Maybe (Expression SourceContext))
 -> TextParser (Maybe (Expression SourceContext)))
-> TextParser (Maybe (Expression SourceContext))
-> TextParser (Maybe (Expression SourceContext))
forall a b. (a -> b) -> a -> b
$ do
        TextParser ()
assignOperator
        Expression SourceContext
e <- TextParser (Expression SourceContext)
forall a. ParseFromSource a => TextParser a
sourceParser
        Maybe (Expression SourceContext)
-> TextParser (Maybe (Expression SourceContext))
forall a. a -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Expression SourceContext)
 -> TextParser (Maybe (Expression SourceContext)))
-> Maybe (Expression SourceContext)
-> TextParser (Maybe (Expression SourceContext))
forall a b. (a -> b) -> a -> b
$ Expression SourceContext -> Maybe (Expression SourceContext)
forall a. a -> Maybe a
Just Expression SourceContext
e
      parseType :: ParsecT CompilerMessage String Identity (SymbolScope, ValueType)
parseType = do
        SymbolScope
s <- TextParser SymbolScope
parseScope
        ValueType
t <- TextParser ValueType
forall a. ParseFromSource a => TextParser a
sourceParser
        (SymbolScope, ValueType)
-> ParsecT CompilerMessage String Identity (SymbolScope, ValueType)
forall a. a -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (SymbolScope
s,ValueType
t)

parseMemberProcedureFunction ::
  CategoryName -> TextParser ([DefinedMember SourceContext],
                             [ExecutableProcedure SourceContext],
                             [ScopedFunction SourceContext])
parseMemberProcedureFunction :: CategoryName
-> TextParser
     ([DefinedMember SourceContext],
      [ExecutableProcedure SourceContext],
      [ScopedFunction SourceContext])
parseMemberProcedureFunction CategoryName
n = do
  ([DefinedMember SourceContext]
ms,[ExecutableProcedure SourceContext]
ps,[(ScopedFunction SourceContext, ExecutableProcedure SourceContext)]
fs) <- TextParser (DefinedMember SourceContext)
-> TextParser (ExecutableProcedure SourceContext)
-> TextParser
     (ScopedFunction SourceContext, ExecutableProcedure SourceContext)
-> TextParser
     ([DefinedMember SourceContext],
      [ExecutableProcedure SourceContext],
      [(ScopedFunction SourceContext,
        ExecutableProcedure SourceContext)])
forall a b c.
TextParser a
-> TextParser b -> TextParser c -> TextParser ([a], [b], [c])
parseAny3 (TextParser (DefinedMember SourceContext)
forall {a}. TextParser a
catchUnscopedType TextParser (DefinedMember SourceContext)
-> TextParser (DefinedMember SourceContext)
-> TextParser (DefinedMember SourceContext)
forall a.
ParsecT CompilerMessage String Identity a
-> ParsecT CompilerMessage String Identity a
-> ParsecT CompilerMessage String Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> TextParser (DefinedMember SourceContext)
forall a. ParseFromSource a => TextParser a
sourceParser) TextParser (ExecutableProcedure SourceContext)
forall a. ParseFromSource a => TextParser a
sourceParser TextParser
  (ScopedFunction SourceContext, ExecutableProcedure SourceContext)
singleFunction
  let ps2 :: [ExecutableProcedure SourceContext]
ps2 = [ExecutableProcedure SourceContext]
ps [ExecutableProcedure SourceContext]
-> [ExecutableProcedure SourceContext]
-> [ExecutableProcedure SourceContext]
forall a. [a] -> [a] -> [a]
++ ((ScopedFunction SourceContext, ExecutableProcedure SourceContext)
 -> ExecutableProcedure SourceContext)
-> [(ScopedFunction SourceContext,
     ExecutableProcedure SourceContext)]
-> [ExecutableProcedure SourceContext]
forall a b. (a -> b) -> [a] -> [b]
map (ScopedFunction SourceContext, ExecutableProcedure SourceContext)
-> ExecutableProcedure SourceContext
forall a b. (a, b) -> b
snd [(ScopedFunction SourceContext, ExecutableProcedure SourceContext)]
fs
  let fs2 :: [ScopedFunction SourceContext]
fs2 = ((ScopedFunction SourceContext, ExecutableProcedure SourceContext)
 -> ScopedFunction SourceContext)
-> [(ScopedFunction SourceContext,
     ExecutableProcedure SourceContext)]
-> [ScopedFunction SourceContext]
forall a b. (a -> b) -> [a] -> [b]
map (ScopedFunction SourceContext, ExecutableProcedure SourceContext)
-> ScopedFunction SourceContext
forall a b. (a, b) -> a
fst [(ScopedFunction SourceContext, ExecutableProcedure SourceContext)]
fs
  ([DefinedMember SourceContext],
 [ExecutableProcedure SourceContext],
 [ScopedFunction SourceContext])
-> TextParser
     ([DefinedMember SourceContext],
      [ExecutableProcedure SourceContext],
      [ScopedFunction SourceContext])
forall a. a -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ([DefinedMember SourceContext]
ms,[ExecutableProcedure SourceContext]
ps2,[ScopedFunction SourceContext]
fs2) where
    singleFunction :: TextParser
  (ScopedFunction SourceContext, ExecutableProcedure SourceContext)
singleFunction = String
-> TextParser
     (ScopedFunction SourceContext, ExecutableProcedure SourceContext)
-> TextParser
     (ScopedFunction SourceContext, ExecutableProcedure SourceContext)
forall a. String -> TextParser a -> TextParser a
labeled String
"function" (TextParser
   (ScopedFunction SourceContext, ExecutableProcedure SourceContext)
 -> TextParser
      (ScopedFunction SourceContext, ExecutableProcedure SourceContext))
-> TextParser
     (ScopedFunction SourceContext, ExecutableProcedure SourceContext)
-> TextParser
     (ScopedFunction SourceContext, ExecutableProcedure SourceContext)
forall a b. (a -> b) -> a -> b
$ do
      ScopedFunction SourceContext
f <- TextParser SymbolScope
-> TextParser CategoryName
-> TextParser (ScopedFunction SourceContext)
parseScopedFunction TextParser SymbolScope
parseScope (CategoryName -> TextParser CategoryName
forall a. a -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return CategoryName
n)
      TextParser () -> TextParser ()
forall a. TextParser a -> TextParser a
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
lookAhead (TextParser () -> TextParser ()
forall a. TextParser a -> TextParser a
sepAfter (TextParser () -> TextParser ()) -> TextParser () -> TextParser ()
forall a b. (a -> b) -> a -> b
$ String -> TextParser ()
string_ (String -> TextParser ()) -> String -> TextParser ()
forall a b. (a -> b) -> a -> b
$ FunctionName -> String
forall a. Show a => a -> String
show (ScopedFunction SourceContext -> FunctionName
forall c. ScopedFunction c -> FunctionName
sfName ScopedFunction SourceContext
f)) TextParser () -> TextParser () -> TextParser ()
forall a.
ParsecT CompilerMessage String Identity a
-> ParsecT CompilerMessage String Identity a
-> ParsecT CompilerMessage String Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
        (String -> TextParser ()
forall a. String -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM (String -> TextParser ()) -> String -> TextParser ()
forall a b. (a -> b) -> a -> b
$ String
"expected definition of function " String -> String -> String
forall a. [a] -> [a] -> [a]
++ FunctionName -> String
forall a. Show a => a -> String
show (ScopedFunction SourceContext -> FunctionName
forall c. ScopedFunction c -> FunctionName
sfName ScopedFunction SourceContext
f))
      ExecutableProcedure SourceContext
p <- String
-> TextParser (ExecutableProcedure SourceContext)
-> TextParser (ExecutableProcedure SourceContext)
forall a. String -> TextParser a -> TextParser a
labeled (String
"definition of function " String -> String -> String
forall a. [a] -> [a] -> [a]
++ FunctionName -> String
forall a. Show a => a -> String
show (ScopedFunction SourceContext -> FunctionName
forall c. ScopedFunction c -> FunctionName
sfName ScopedFunction SourceContext
f)) (TextParser (ExecutableProcedure SourceContext)
 -> TextParser (ExecutableProcedure SourceContext))
-> TextParser (ExecutableProcedure SourceContext)
-> TextParser (ExecutableProcedure SourceContext)
forall a b. (a -> b) -> a -> b
$ TextParser (ExecutableProcedure SourceContext)
forall a. ParseFromSource a => TextParser a
sourceParser
      (ScopedFunction SourceContext, ExecutableProcedure SourceContext)
-> TextParser
     (ScopedFunction SourceContext, ExecutableProcedure SourceContext)
forall a. a -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (ScopedFunction SourceContext
f,ExecutableProcedure SourceContext
p)
    catchUnscopedType :: TextParser a
catchUnscopedType = String -> TextParser a -> TextParser a
forall a. String -> TextParser a -> TextParser a
labeled String
"" (TextParser a -> TextParser a) -> TextParser a -> TextParser a
forall a b. (a -> b) -> a -> b
$ do
      ValueType
_ <- TextParser ValueType -> TextParser ValueType
forall a. TextParser a -> TextParser a
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try TextParser ValueType
forall a. ParseFromSource a => TextParser a
sourceParser :: TextParser ValueType
      String -> TextParser a
forall a. String -> ParsecT CompilerMessage String Identity a
forall (m :: * -> *) a. ErrorContextM m => String -> m a
compilerErrorM String
"members must have an explicit @value or @category scope"