{-# LANGUAGE DeriveDataTypeable, KindSignatures, PolyKinds,
             TypeFamilies, TypeFamilyDependencies, UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-simplifiable-class-constraints #-}

-- | ISO Modula-2 Finally Tagless Abstract Syntax Tree definitions

module Language.Modula2.ISO.Abstract (Modula2(..)) where

import Data.Data (Data, Typeable)
import qualified Data.Kind as K (Type)
import Data.List.NonEmpty
import Data.Text (Text)

import qualified Language.Modula2.Abstract as Report
import Language.Modula2.Abstract hiding (Modula2)

-- | The additional finally-tagless associated types and methods relevant to the ISO Modula-2 language.
class Report.Modula2 l => Modula2 l where
   type AddressedIdent l = (d :: K.Type -> (K.Type -> K.Type) -> (K.Type -> K.Type) -> K.Type) | d -> l
   type Item l = (i :: K.Type -> (K.Type -> K.Type) -> (K.Type -> K.Type) -> K.Type) | i -> l

   -- Declaration
   emptyVariant :: Variant l l' f' f
   addressedVariableDeclaration :: NonEmpty (f (AddressedIdent l' l' f' f')) -> f (Type l' l' f' f')
                                -> Declaration l l' f' f
   forwardProcedureDeclaration :: f (ProcedureHeading l' l' f' f') -> Declaration l l' f' f
   exceptionHandlingBlock :: [f (Declaration l' l' f' f')] -> Maybe (f (StatementSequence l' l' f' f'))
                          -> Maybe (f (StatementSequence l' l' f' f')) -> Maybe (f (StatementSequence l' l' f' f'))
                          -> Block l l' f' f
   addressedIdent :: Ident -> f (ConstExpression l' l' f' f') -> AddressedIdent l l' f' f
   unaddressedIdent :: Ident -> AddressedIdent l l' f' f

   -- Type
   packedSetType :: f (Type l' l' f' f') -> Type l l' f' f

   -- Statement
   retryStatement :: Statement l l' f' f

    -- Expression
   array :: Maybe (QualIdent l') -> [f (Item l' l' f' f')] -> Expression l l' f' f
   record :: Maybe (QualIdent l') -> [f (Expression l' l' f' f')] -> Expression l l' f' f
   remainder :: f (Expression l' l' f' f') -> f (Expression l' l' f' f') -> Expression l l' f' f

   -- Compound expression
   single :: f (Expression l' l' f' f') -> Item l l' f' f
   repeated :: f (Expression l' l' f' f') -> f (ConstExpression l' l' f' f') -> Item l l' f' f

instance Wirthy l => Modula2 (WirthySubsetOf l) where
   type AddressedIdent (WirthySubsetOf l) = Maybe3 (AddressedIdent l)
   type Item (WirthySubsetOf l) = Maybe3 (Item l)
   emptyVariant :: forall l' (f' :: * -> *) (f :: * -> *).
Variant (WirthySubsetOf l) l' f' f
emptyVariant = Maybe3 (Variant l) l' f' f
Variant (WirthySubsetOf l) l' f' f
forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   addressedVariableDeclaration :: forall (f :: * -> *) l' (f' :: * -> *).
NonEmpty (f (AddressedIdent l' l' f' f'))
-> f (Type l' l' f' f') -> Declaration (WirthySubsetOf l) l' f' f
addressedVariableDeclaration = (f (Type l' l' f' f') -> Declaration (WirthySubsetOf l) l' f' f)
-> NonEmpty (f (AddressedIdent l' l' f' f'))
-> f (Type l' l' f' f')
-> Declaration (WirthySubsetOf l) l' f' f
forall a b. a -> b -> a
const ((f (Type l' l' f' f') -> Declaration (WirthySubsetOf l) l' f' f)
 -> NonEmpty (f (AddressedIdent l' l' f' f'))
 -> f (Type l' l' f' f')
 -> Declaration (WirthySubsetOf l) l' f' f)
-> (f (Type l' l' f' f') -> Declaration (WirthySubsetOf l) l' f' f)
-> NonEmpty (f (AddressedIdent l' l' f' f'))
-> f (Type l' l' f' f')
-> Declaration (WirthySubsetOf l) l' f' f
forall a b. (a -> b) -> a -> b
$ Maybe3 (Declaration l) l' f' f
-> f (Type l' l' f' f') -> Maybe3 (Declaration l) l' f' f
forall a b. a -> b -> a
const Maybe3 (Declaration l) l' f' f
forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   forwardProcedureDeclaration :: forall (f :: * -> *) l' (f' :: * -> *).
f (ProcedureHeading l' l' f' f')
-> Declaration (WirthySubsetOf l) l' f' f
forwardProcedureDeclaration = Maybe3 (Declaration l) l' f' f
-> f (ProcedureHeading l' l' f' f')
-> Maybe3 (Declaration l) l' f' f
forall a b. a -> b -> a
const Maybe3 (Declaration l) l' f' f
forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   exceptionHandlingBlock :: forall (f :: * -> *) l' (f' :: * -> *).
[f (Declaration l' l' f' f')]
-> Maybe (f (StatementSequence l' l' f' f'))
-> Maybe (f (StatementSequence l' l' f' f'))
-> Maybe (f (StatementSequence l' l' f' f'))
-> Block (WirthySubsetOf l) l' f' f
exceptionHandlingBlock = (Maybe (f (StatementSequence l' l' f' f'))
 -> Maybe (f (StatementSequence l' l' f' f'))
 -> Maybe (f (StatementSequence l' l' f' f'))
 -> Block (WirthySubsetOf l) l' f' f)
-> [f (Declaration l' l' f' f')]
-> Maybe (f (StatementSequence l' l' f' f'))
-> Maybe (f (StatementSequence l' l' f' f'))
-> Maybe (f (StatementSequence l' l' f' f'))
-> Block (WirthySubsetOf l) l' f' f
forall a b. a -> b -> a
const ((Maybe (f (StatementSequence l' l' f' f'))
  -> Maybe (f (StatementSequence l' l' f' f'))
  -> Maybe (f (StatementSequence l' l' f' f'))
  -> Block (WirthySubsetOf l) l' f' f)
 -> [f (Declaration l' l' f' f')]
 -> Maybe (f (StatementSequence l' l' f' f'))
 -> Maybe (f (StatementSequence l' l' f' f'))
 -> Maybe (f (StatementSequence l' l' f' f'))
 -> Block (WirthySubsetOf l) l' f' f)
-> (Maybe (f (StatementSequence l' l' f' f'))
    -> Maybe (f (StatementSequence l' l' f' f'))
    -> Maybe (f (StatementSequence l' l' f' f'))
    -> Block (WirthySubsetOf l) l' f' f)
-> [f (Declaration l' l' f' f')]
-> Maybe (f (StatementSequence l' l' f' f'))
-> Maybe (f (StatementSequence l' l' f' f'))
-> Maybe (f (StatementSequence l' l' f' f'))
-> Block (WirthySubsetOf l) l' f' f
forall a b. (a -> b) -> a -> b
$ (Maybe (f (StatementSequence l' l' f' f'))
 -> Maybe (f (StatementSequence l' l' f' f'))
 -> Block (WirthySubsetOf l) l' f' f)
-> Maybe (f (StatementSequence l' l' f' f'))
-> Maybe (f (StatementSequence l' l' f' f'))
-> Maybe (f (StatementSequence l' l' f' f'))
-> Block (WirthySubsetOf l) l' f' f
forall a b. a -> b -> a
const ((Maybe (f (StatementSequence l' l' f' f'))
  -> Maybe (f (StatementSequence l' l' f' f'))
  -> Block (WirthySubsetOf l) l' f' f)
 -> Maybe (f (StatementSequence l' l' f' f'))
 -> Maybe (f (StatementSequence l' l' f' f'))
 -> Maybe (f (StatementSequence l' l' f' f'))
 -> Block (WirthySubsetOf l) l' f' f)
-> (Maybe (f (StatementSequence l' l' f' f'))
    -> Maybe (f (StatementSequence l' l' f' f'))
    -> Block (WirthySubsetOf l) l' f' f)
-> Maybe (f (StatementSequence l' l' f' f'))
-> Maybe (f (StatementSequence l' l' f' f'))
-> Maybe (f (StatementSequence l' l' f' f'))
-> Block (WirthySubsetOf l) l' f' f
forall a b. (a -> b) -> a -> b
$ (Maybe (f (StatementSequence l' l' f' f'))
 -> Block (WirthySubsetOf l) l' f' f)
-> Maybe (f (StatementSequence l' l' f' f'))
-> Maybe (f (StatementSequence l' l' f' f'))
-> Block (WirthySubsetOf l) l' f' f
forall a b. a -> b -> a
const ((Maybe (f (StatementSequence l' l' f' f'))
  -> Block (WirthySubsetOf l) l' f' f)
 -> Maybe (f (StatementSequence l' l' f' f'))
 -> Maybe (f (StatementSequence l' l' f' f'))
 -> Block (WirthySubsetOf l) l' f' f)
-> (Maybe (f (StatementSequence l' l' f' f'))
    -> Block (WirthySubsetOf l) l' f' f)
-> Maybe (f (StatementSequence l' l' f' f'))
-> Maybe (f (StatementSequence l' l' f' f'))
-> Block (WirthySubsetOf l) l' f' f
forall a b. (a -> b) -> a -> b
$ Maybe3 (Block l) l' f' f
-> Maybe (f (StatementSequence l' l' f' f'))
-> Maybe3 (Block l) l' f' f
forall a b. a -> b -> a
const Maybe3 (Block l) l' f' f
forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   addressedIdent :: forall (f :: * -> *) l' (f' :: * -> *).
Ident
-> f (ConstExpression l' l' f' f')
-> AddressedIdent (WirthySubsetOf l) l' f' f
addressedIdent = (f (ConstExpression l' l' f' f')
 -> AddressedIdent (WirthySubsetOf l) l' f' f)
-> Ident
-> f (ConstExpression l' l' f' f')
-> AddressedIdent (WirthySubsetOf l) l' f' f
forall a b. a -> b -> a
const ((f (ConstExpression l' l' f' f')
  -> AddressedIdent (WirthySubsetOf l) l' f' f)
 -> Ident
 -> f (ConstExpression l' l' f' f')
 -> AddressedIdent (WirthySubsetOf l) l' f' f)
-> (f (ConstExpression l' l' f' f')
    -> AddressedIdent (WirthySubsetOf l) l' f' f)
-> Ident
-> f (ConstExpression l' l' f' f')
-> AddressedIdent (WirthySubsetOf l) l' f' f
forall a b. (a -> b) -> a -> b
$ Maybe3 (AddressedIdent l) l' f' f
-> f (ConstExpression l' l' f' f')
-> Maybe3 (AddressedIdent l) l' f' f
forall a b. a -> b -> a
const Maybe3 (AddressedIdent l) l' f' f
forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   unaddressedIdent :: forall l' (f' :: * -> *) (f :: * -> *).
Ident -> AddressedIdent (WirthySubsetOf l) l' f' f
unaddressedIdent = Maybe3 (AddressedIdent l) l' f' f
-> Ident -> Maybe3 (AddressedIdent l) l' f' f
forall a b. a -> b -> a
const Maybe3 (AddressedIdent l) l' f' f
forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3

   -- Type
   packedSetType :: forall (f :: * -> *) l' (f' :: * -> *).
f (Type l' l' f' f') -> Type (WirthySubsetOf l) l' f' f
packedSetType = Maybe3 (Type l) l' f' f
-> f (Type l' l' f' f') -> Maybe3 (Type l) l' f' f
forall a b. a -> b -> a
const Maybe3 (Type l) l' f' f
forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3

   -- Statement
   retryStatement :: forall l' (f' :: * -> *) (f :: * -> *).
Statement (WirthySubsetOf l) l' f' f
retryStatement = Maybe3 (Statement l) l' f' f
Statement (WirthySubsetOf l) l' f' f
forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3

    -- Expression
   array :: forall l' (f :: * -> *) (f' :: * -> *).
Maybe (QualIdent l')
-> [f (Item l' l' f' f')] -> Expression (WirthySubsetOf l) l' f' f
array = ([f (Item l' l' f' f')] -> Expression (WirthySubsetOf l) l' f' f)
-> Maybe (QualIdent l')
-> [f (Item l' l' f' f')]
-> Expression (WirthySubsetOf l) l' f' f
forall a b. a -> b -> a
const (([f (Item l' l' f' f')] -> Expression (WirthySubsetOf l) l' f' f)
 -> Maybe (QualIdent l')
 -> [f (Item l' l' f' f')]
 -> Expression (WirthySubsetOf l) l' f' f)
-> ([f (Item l' l' f' f')]
    -> Expression (WirthySubsetOf l) l' f' f)
-> Maybe (QualIdent l')
-> [f (Item l' l' f' f')]
-> Expression (WirthySubsetOf l) l' f' f
forall a b. (a -> b) -> a -> b
$ Maybe3 (Expression l) l' f' f
-> [f (Item l' l' f' f')] -> Maybe3 (Expression l) l' f' f
forall a b. a -> b -> a
const Maybe3 (Expression l) l' f' f
forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   record :: forall l' (f :: * -> *) (f' :: * -> *).
Maybe (QualIdent l')
-> [f (Expression l' l' f' f')]
-> Expression (WirthySubsetOf l) l' f' f
record = ([f (Expression l' l' f' f')]
 -> Expression (WirthySubsetOf l) l' f' f)
-> Maybe (QualIdent l')
-> [f (Expression l' l' f' f')]
-> Expression (WirthySubsetOf l) l' f' f
forall a b. a -> b -> a
const (([f (Expression l' l' f' f')]
  -> Expression (WirthySubsetOf l) l' f' f)
 -> Maybe (QualIdent l')
 -> [f (Expression l' l' f' f')]
 -> Expression (WirthySubsetOf l) l' f' f)
-> ([f (Expression l' l' f' f')]
    -> Expression (WirthySubsetOf l) l' f' f)
-> Maybe (QualIdent l')
-> [f (Expression l' l' f' f')]
-> Expression (WirthySubsetOf l) l' f' f
forall a b. (a -> b) -> a -> b
$ Maybe3 (Expression l) l' f' f
-> [f (Expression l' l' f' f')] -> Maybe3 (Expression l) l' f' f
forall a b. a -> b -> a
const Maybe3 (Expression l) l' f' f
forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   remainder :: forall (f :: * -> *) l' (f' :: * -> *).
f (Expression l' l' f' f')
-> f (Expression l' l' f' f')
-> Expression (WirthySubsetOf l) l' f' f
remainder = (f (Expression l' l' f' f')
 -> Expression (WirthySubsetOf l) l' f' f)
-> f (Expression l' l' f' f')
-> f (Expression l' l' f' f')
-> Expression (WirthySubsetOf l) l' f' f
forall a b. a -> b -> a
const ((f (Expression l' l' f' f')
  -> Expression (WirthySubsetOf l) l' f' f)
 -> f (Expression l' l' f' f')
 -> f (Expression l' l' f' f')
 -> Expression (WirthySubsetOf l) l' f' f)
-> (f (Expression l' l' f' f')
    -> Expression (WirthySubsetOf l) l' f' f)
-> f (Expression l' l' f' f')
-> f (Expression l' l' f' f')
-> Expression (WirthySubsetOf l) l' f' f
forall a b. (a -> b) -> a -> b
$ Maybe3 (Expression l) l' f' f
-> f (Expression l' l' f' f') -> Maybe3 (Expression l) l' f' f
forall a b. a -> b -> a
const Maybe3 (Expression l) l' f' f
forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3

   -- Compound expression
   single :: forall (f :: * -> *) l' (f' :: * -> *).
f (Expression l' l' f' f') -> Item (WirthySubsetOf l) l' f' f
single = Maybe3 (Item l) l' f' f
-> f (Expression l' l' f' f') -> Maybe3 (Item l) l' f' f
forall a b. a -> b -> a
const Maybe3 (Item l) l' f' f
forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   repeated :: forall (f :: * -> *) l' (f' :: * -> *).
f (Expression l' l' f' f')
-> f (Expression l' l' f' f') -> Item (WirthySubsetOf l) l' f' f
repeated = (f (ConstExpression l' l' f' f')
 -> Item (WirthySubsetOf l) l' f' f)
-> f (ConstExpression l' l' f' f')
-> f (ConstExpression l' l' f' f')
-> Item (WirthySubsetOf l) l' f' f
forall a b. a -> b -> a
const ((f (ConstExpression l' l' f' f')
  -> Item (WirthySubsetOf l) l' f' f)
 -> f (ConstExpression l' l' f' f')
 -> f (ConstExpression l' l' f' f')
 -> Item (WirthySubsetOf l) l' f' f)
-> (f (ConstExpression l' l' f' f')
    -> Item (WirthySubsetOf l) l' f' f)
-> f (ConstExpression l' l' f' f')
-> f (ConstExpression l' l' f' f')
-> Item (WirthySubsetOf l) l' f' f
forall a b. (a -> b) -> a -> b
$ Maybe3 (Item l) l' f' f
-> f (ConstExpression l' l' f' f') -> Maybe3 (Item l) l' f' f
forall a b. a -> b -> a
const Maybe3 (Item l) l' f' f
forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3