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

-- | Finally Tagless Abstract Syntax Tree definitions for the programming language Modula-2

module Language.Modula2.Abstract (Ident, IdentList, BaseType, ConstExpression, Priority,
                                  Wirthy(..), CoWirthy(..), Nameable(..), Modula2(..),
                                  RelOp(..), WirthySubsetOf(..), Maybe3(..), just3, maybe3, nothing3) where

import Data.Data (Data, Typeable)
import Data.List.NonEmpty
import Data.Text (Text)

import Language.Oberon.Abstract

-- | Module priority
type Priority l = ConstExpression l

-- | The finally-tagless associated types and methods relevant to the Modula-2 language. Every non-leaf node type has
-- four type variables:
--
-- * type variable @l@ represents the language of the constructs built by the methods,
-- * @l'@ is the language of the child node constructs,
-- * @f'@ wraps all descendant nodes, except
-- * @f@ wraps all direct children of the node.
class Wirthy l => Modula2 l where
   type Export l = x | x -> l
   type Definition l = (d :: * -> (* -> *) -> (* -> *) -> *) | d -> l
   type Variant l = (v :: * -> (* -> *) -> (* -> *) -> *) | v -> l

   -- Module
   definitionModule :: Ident -> [Import l'] -> Maybe (Export l') -> [f (Definition l' l' f' f')] -> Module l l' f' f
   implementationModule,
      programModule :: Ident -> Maybe (f (Priority l' l' f' f')) -> [Import l'] -> f (Block l' l' f' f')
                    -> Module l l' f' f

   moduleExport :: Bool -> NonEmpty Ident -> Export l
   moduleImport :: Maybe Ident -> NonEmpty Ident -> Import l

   -- Definition
   constantDefinition :: IdentDef l' -> f (ConstExpression l' l' f' f') -> Definition l l' f' f
   typeDefinition :: IdentDef l' -> Maybe (f (Type l' l' f' f')) -> Definition l l' f' f
   variableDefinition :: IdentList l' -> f (Type l' l' f' f') -> Definition l l' f' f
   procedureDefinition :: f (ProcedureHeading l' l' f' f') -> Definition l l' f' f

   -- Declaration
   moduleDeclaration :: Ident -> Maybe (f (Priority l' l' f' f'))
                     -> [Import l'] -> Maybe (Export l') -> f (Block l' l' f' f') -> Declaration l l' f' f

   procedureHeading :: Ident -> Maybe (f (FormalParameters l' l' f' f')) -> ProcedureHeading l l' f' f
   caseFieldList :: Maybe Ident -> QualIdent l' -> NonEmpty (f (Variant l' l' f' f')) -> [f (FieldList l' l' f' f')]
                 -> FieldList l l' f' f
   variant :: NonEmpty (f (CaseLabels l' l' f' f')) -> [f (FieldList l' l' f' f')] -> Variant l l' f' f

   -- Type
   enumeration :: IdentList l' -> Type l l' f' f
   subRange :: Maybe (QualIdent l') -> f (ConstExpression l' l' f' f') -> f (ConstExpression l' l' f' f')
            -> Type l l' f' f
   arrayType :: [f (Type l' l' f' f')] -> f (Type l' l' f' f') -> Type l l' f' f
   setType :: f (Type l' l' f' f') -> Type l l' f' f
   recordType :: [f (FieldList l' l' f' f')] -> Type l l' f' f

   -- Statement
   withStatement :: f (Designator l' l' f' f') -> f (StatementSequence l' l' f' f') -> Statement l l' f' f
   forStatement :: Ident -> f (Expression l' l' f' f') -> f (Expression l' l' f' f')
                -> Maybe (f (Expression l' l' f' f')) -> f (StatementSequence l' l' f' f')
                -> Statement l l' f' f

   -- Expression
   set :: Maybe (QualIdent l') -> [f (Element l' l' f' f')] -> Expression l l' f' f
   qualIdent :: [Ident] -> Ident -> QualIdent l

instance Wirthy l => Modula2 (WirthySubsetOf l) where
   type Export (WirthySubsetOf l) = Maybe (Export l)
   type Definition (WirthySubsetOf l) = Maybe3 (Definition l)
   type Variant (WirthySubsetOf l) = Maybe3 (Variant l)
   definitionModule :: forall l' (f :: * -> *) (f' :: * -> *).
Ident
-> [Import l']
-> Maybe (Export l')
-> [f (Definition l' l' f' f')]
-> Module (WirthySubsetOf l) l' f' f
definitionModule = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   implementationModule :: forall (f :: * -> *) l' (f' :: * -> *).
Ident
-> Maybe (f (Priority l' l' f' f'))
-> [Import l']
-> f (Block l' l' f' f')
-> Module (WirthySubsetOf l) l' f' f
implementationModule = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   programModule :: forall (f :: * -> *) l' (f' :: * -> *).
Ident
-> Maybe (f (Priority l' l' f' f'))
-> [Import l']
-> f (Block l' l' f' f')
-> Module (WirthySubsetOf l) l' f' f
programModule = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3

   moduleExport :: Bool -> NonEmpty Ident -> Export (WirthySubsetOf l)
moduleExport = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a. Maybe a
Nothing
   moduleImport :: Maybe Ident -> NonEmpty Ident -> Import (WirthySubsetOf l)
moduleImport = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a. Maybe a
Nothing

   -- Definition
   constantDefinition :: forall l' (f :: * -> *) (f' :: * -> *).
IdentDef l'
-> f (ConstExpression l' l' f' f')
-> Definition (WirthySubsetOf l) l' f' f
constantDefinition = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   typeDefinition :: forall l' (f :: * -> *) (f' :: * -> *).
IdentDef l'
-> Maybe (f (Type l' l' f' f'))
-> Definition (WirthySubsetOf l) l' f' f
typeDefinition = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   variableDefinition :: forall l' (f :: * -> *) (f' :: * -> *).
IdentList l'
-> f (Type l' l' f' f') -> Definition (WirthySubsetOf l) l' f' f
variableDefinition = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   procedureDefinition :: forall (f :: * -> *) l' (f' :: * -> *).
f (ProcedureHeading l' l' f' f')
-> Definition (WirthySubsetOf l) l' f' f
procedureDefinition = forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3

   -- Declaration
   moduleDeclaration :: forall (f :: * -> *) l' (f' :: * -> *).
Ident
-> Maybe (f (Priority l' l' f' f'))
-> [Import l']
-> Maybe (Export l')
-> f (Block l' l' f' f')
-> Declaration (WirthySubsetOf l) l' f' f
moduleDeclaration = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3

   procedureHeading :: forall (f :: * -> *) l' (f' :: * -> *).
Ident
-> Maybe (f (FormalParameters l' l' f' f'))
-> ProcedureHeading (WirthySubsetOf l) l' f' f
procedureHeading = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   caseFieldList :: forall l' (f :: * -> *) (f' :: * -> *).
Maybe Ident
-> QualIdent l'
-> NonEmpty (f (Variant l' l' f' f'))
-> [f (FieldList l' l' f' f')]
-> FieldList (WirthySubsetOf l) l' f' f
caseFieldList = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   variant :: forall (f :: * -> *) l' (f' :: * -> *).
NonEmpty (f (CaseLabels l' l' f' f'))
-> [f (FieldList l' l' f' f')]
-> Variant (WirthySubsetOf l) l' f' f
variant = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3

   -- Type
   enumeration :: forall l' (f' :: * -> *) (f :: * -> *).
IdentList l' -> Type (WirthySubsetOf l) l' f' f
enumeration = forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   subRange :: forall l' (f :: * -> *) (f' :: * -> *).
Maybe (QualIdent l')
-> f (ConstExpression l' l' f' f')
-> f (ConstExpression l' l' f' f')
-> Type (WirthySubsetOf l) l' f' f
subRange = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   arrayType :: forall (f :: * -> *) l' (f' :: * -> *).
[f (Type l' l' f' f')]
-> f (Type l' l' f' f') -> Type (WirthySubsetOf l) l' f' f
arrayType = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   setType :: forall (f :: * -> *) l' (f' :: * -> *).
f (Type l' l' f' f') -> Type (WirthySubsetOf l) l' f' f
setType = forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   recordType :: forall (f :: * -> *) l' (f' :: * -> *).
[f (FieldList l' l' f' f')] -> Type (WirthySubsetOf l) l' f' f
recordType = forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3

   -- Statement
   withStatement :: forall (f :: * -> *) l' (f' :: * -> *).
f (Designator l' l' f' f')
-> f (StatementSequence l' l' f' f')
-> Statement (WirthySubsetOf l) l' f' f
withStatement = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   forStatement :: forall (f :: * -> *) l' (f' :: * -> *).
Ident
-> f (Expression l' l' f' f')
-> f (Expression l' l' f' f')
-> Maybe (f (Expression l' l' f' f'))
-> f (StatementSequence l' l' f' f')
-> Statement (WirthySubsetOf l) l' f' f
forStatement = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3

   -- Expression
   set :: forall l' (f :: * -> *) (f' :: * -> *).
Maybe (QualIdent l')
-> [f (Element l' l' f' f')]
-> Expression (WirthySubsetOf l) l' f' f
set = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall {k1} {k2} {k3} {f :: k1 -> k2 -> k3 -> *} {a :: k1}
       {b :: k2} {c :: k3}.
Maybe3 f a b c
nothing3
   qualIdent :: [Ident] -> Ident -> QualIdent (WirthySubsetOf l)
qualIdent = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const forall a. Maybe a
Nothing