packages feed

language-Modula2-0.1: src/Language/Modula2/Abstract.hs

{-# 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 = const $ const $ const $ const nothing3
   implementationModule = const $ const $ const $ const nothing3
   programModule = const $ const $ const $ const nothing3

   moduleExport = const $ const Nothing
   moduleImport = const $ const Nothing

   -- Definition
   constantDefinition = const $ const nothing3
   typeDefinition = const $ const nothing3
   variableDefinition = const $ const nothing3
   procedureDefinition = const nothing3

   -- Declaration
   moduleDeclaration = const $ const $ const $ const $ const nothing3

   procedureHeading = const $ const nothing3
   caseFieldList = const $ const $ const $ const nothing3
   variant = const $ const nothing3

   -- Type
   enumeration = const nothing3
   subRange = const $ const $ const nothing3
   arrayType = const $ const nothing3
   setType = const nothing3
   recordType = const nothing3

   -- Statement
   withStatement = const $ const nothing3
   forStatement = const $ const $ const $ const $ const nothing3

   -- Expression
   set = const $ const nothing3
   qualIdent = const $ const Nothing