packages feed

language-oberon-0.2.1: src/Language/Oberon/AST.hs

{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses, UndecidableInstances,
             StandaloneDeriving, TemplateHaskell #-}
{-# OPTIONS_GHC -Wno-simplifiable-class-constraints #-}

-- | Oberon Abstract Syntax Tree definitions

module Language.Oberon.AST where

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

import Transformation.Deep (Product)
import qualified Transformation.Deep.TH
import qualified Rank2.TH

data Module f' f = Module Ident [Import] ([f (Declaration f' f')]) (Maybe (f (StatementSequence f' f'))) Ident

deriving instance (Typeable f, Typeable f',
                   Data (f (Declaration f' f')), Data (f (StatementSequence f' f'))) => Data (Module f' f)
deriving instance (Show (f (Declaration f' f')), Show (f (StatementSequence f' f'))) => Show (Module f' f)

type Ident = Text

type Import = (Maybe Ident, Ident)

data Declaration f' f = ConstantDeclaration IdentDef (f (ConstExpression f' f'))
                      | TypeDeclaration IdentDef (f (Type f' f'))
                      | VariableDeclaration IdentList (f (Type f' f'))
                      | ProcedureDeclaration (ProcedureHeading f' f) (ProcedureBody f' f) Ident
                      | ForwardDeclaration IdentDef (Maybe (f (FormalParameters f' f')))

deriving instance (Typeable f, Typeable f',
                   Data (f (Type f' f')), Data (f (ConstExpression f' f')), Data (f (FormalParameters f' f')),
                   Data (ProcedureHeading f' f), Data (ProcedureBody f' f)) => Data (Declaration f' f)
deriving instance (Show (f (Type f' f')), Show (f (ConstExpression f' f')), Show (f (FormalParameters f' f')),
                   Show (ProcedureHeading f' f), Show (ProcedureBody f' f)) => Show (Declaration f' f)

data IdentDef = IdentDef Ident AccessMode
   deriving (Data, Eq, Ord, Show)

data AccessMode = Exported | ReadOnly | PrivateOnly
   deriving (Data, Eq, Ord, Show)

type ConstExpression = Expression

data Expression f' f = Relation RelOp (f (Expression f' f')) (f (Expression f' f'))
                     | Positive (f (Expression f' f'))
                     | Negative (f (Expression f' f'))
                     | Add (f (Expression f' f')) (f (Expression f' f'))
                     | Subtract (f (Expression f' f')) (f (Expression f' f'))
                     | Or (f (Expression f' f')) (f (Expression f' f'))
                     | Multiply (f (Expression f' f')) (f (Expression f' f'))
                     | Divide (f (Expression f' f')) (f (Expression f' f'))
                     | IntegerDivide (f (Expression f' f')) (f (Expression f' f'))
                     | Modulo (f (Expression f' f')) (f (Expression f' f'))
                     | And (f (Expression f' f')) (f (Expression f' f'))
                     | Integer Text
                     | Real Text
                     | CharConstant Char
                     | CharCode Int
                     | String Text
                     | Nil 
                     | Set [f (Element f' f')]
                     | Read (f (Designator f' f'))
                     | FunctionCall (f (Designator f' f')) [f (Expression f' f')]
                     | Not (f (Expression f' f'))

deriving instance (Typeable f, Typeable f', Data (f (Designator f' f')),
                   Data (f (Element f' f')), Data (f (Expression f' f'))) => Data (Expression f' f)
deriving instance (Show (f (Designator f' f')),
                   Show (f (Element f' f')), Show (f (Expression f' f'))) => Show (Expression f' f)

data RelOp = Equal | Unequal | Less | LessOrEqual | Greater | GreaterOrEqual | In | Is
   deriving (Data, Show)

data Element f' f = Element (f (Expression f' f'))
                  | Range (f (Expression f' f')) (f (Expression f' f'))

deriving instance (Typeable f, Typeable f', Data (f (Expression f' f'))) => Data (Element f' f)
deriving instance Show (f (Expression f' f')) => Show (Element f' f)

data Designator f' f = Variable QualIdent
                     | Field (f (Designator f' f')) Ident 
                     | Index (f (Designator f' f')) (NonEmpty (f (Expression f' f')))
                     | TypeGuard (f (Designator f' f')) QualIdent 
                     | Dereference (f (Designator f' f'))

deriving instance (Typeable f, Typeable f', Data (f (Designator f' f')), Data (f (Expression f' f'))) =>
                  Data (Designator f' f)
deriving instance (Show (f (Designator f' f')), Show (f (Expression f' f'))) => Show (Designator f' f)

data Type f' f = TypeReference QualIdent 
               | ArrayType [f (ConstExpression f' f')] (f (Type f' f'))
               | RecordType (Maybe BaseType) (NonEmpty (f (FieldList f' f')))
               | PointerType (f (Type f' f'))
               | ProcedureType (Maybe (f (FormalParameters f' f')))

deriving instance (Typeable f, Typeable f', Data (f (Type f' f')), Data (f (ConstExpression f' f')),
                   Data (f (FormalParameters f' f')), Data (f (FieldList f' f'))) => Data (Type f' f)
deriving instance (Show (f (Type f' f')), Show (f (ConstExpression f' f')),
                   Show (f (FormalParameters f' f')), Show (f (FieldList f' f'))) => Show (Type f' f)

data QualIdent = QualIdent Ident Ident 
               | NonQualIdent Ident
   deriving (Data, Eq, Ord, Show)

type BaseType  = QualIdent

data FieldList f' f = FieldList IdentList (f (Type f' f'))
                    | EmptyFieldList

deriving instance (Typeable f, Typeable f', Data (f (Type f' f')), Data (f (Expression f' f'))) => Data (FieldList f' f)
deriving instance (Show (f (Type f' f')), Show (f (Expression f' f'))) => Show (FieldList f' f)

type IdentList = NonEmpty IdentDef

data ProcedureHeading f' f = 
   ProcedureHeading (Maybe (Bool, Ident, Ident)) Bool IdentDef (Maybe (f (FormalParameters f' f')))
data FormalParameters f' f = FormalParameters [f (FPSection f' f')] (Maybe QualIdent)

data FPSection f' f = FPSection Bool (NonEmpty Ident) (f (Type f' f'))

deriving instance (Typeable f, Typeable f', Data (f (FormalParameters f' f'))) => Data (ProcedureHeading f' f)
deriving instance (Show (f (FormalParameters f' f'))) => Show (ProcedureHeading f' f)

deriving instance (Typeable f, Typeable f', Data (f (FPSection f' f')),  Data (f (Expression f' f'))) =>
                  Data (FormalParameters f' f)
deriving instance (Show (f (FPSection f' f')), Show (f (Expression f' f'))) => Show (FormalParameters f' f)

deriving instance (Typeable f, Typeable f', Data (f (Type f' f')),  Data (f (Expression f' f'))) =>
                  Data (FPSection f' f)
deriving instance (Show (f (Type f' f')), Show (f (Expression f' f'))) => Show (FPSection f' f)

data ProcedureBody f' f =  ProcedureBody [f (Declaration f' f')] (Maybe (f (StatementSequence f' f')))

deriving instance (Typeable f, Typeable f', Data (f (Declaration f' f')), Data (f (Designator f' f')),
                   Data (f (Expression f' f')), Data (f (StatementSequence f' f'))) =>
                  Data (ProcedureBody f' f)
deriving instance (Show (f (Declaration f' f')), Show (f (Designator f' f')),
                   Show (f (Expression f' f')), Show (f (StatementSequence f' f'))) => Show (ProcedureBody f' f)

newtype StatementSequence f' f = StatementSequence (NonEmpty (f (Statement f' f')))

deriving instance (Typeable f, Typeable f', Data (f (Statement f' f'))) => Data (StatementSequence f' f)
deriving instance Show (f (Statement f' f')) => Show (StatementSequence f' f)

data Statement f' f = EmptyStatement
                    | Assignment (f (Designator f' f')) (f (Expression f' f'))
                    | ProcedureCall (f (Designator f' f')) (Maybe [f (Expression f' f')])
                    | If (NonEmpty (f (Product Expression StatementSequence f' f')))
                         (Maybe (f (StatementSequence f' f')))
                    | CaseStatement (f (Expression f' f')) 
                                    (NonEmpty (f (Case f' f'))) 
                                    (Maybe (f (StatementSequence f' f')))
                    | While (f (Expression f' f')) (f (StatementSequence f' f'))
                    | Repeat (f (StatementSequence f' f')) (f (Expression f' f'))
                    | For Ident (f (Expression f' f')) (f (Expression f' f')) 
                          (Maybe (f (Expression f' f'))) (f (StatementSequence f' f'))  -- Oberon2
                    | Loop (f (StatementSequence f' f'))
                    | With (NonEmpty (f (WithAlternative f' f'))) (Maybe (f (StatementSequence f' f')))
                    | Exit 
                    | Return (Maybe (f (Expression f' f')))

deriving instance (Typeable f, Typeable f', Data (f (Designator f' f')), Data (f (Expression f' f')),
                   Data (f (Product Expression StatementSequence f' f')),
                   Data (f (Case f' f')), Data (f (WithAlternative f' f')),
                   Data (f (Statement f' f')), Data (f (StatementSequence f' f'))) => Data (Statement f' f)
deriving instance (Show (f (Designator f' f')), Show (f (Expression f' f')),
                   Show (f (Product Expression StatementSequence f' f')),
                   Show (f (Case f' f')), Show (f (WithAlternative f' f')),
                   Show (f (Statement f' f')), Show (f (StatementSequence f' f'))) => Show (Statement f' f)

data WithAlternative f' f = WithAlternative QualIdent QualIdent (f (StatementSequence f' f'))

data Case f' f = Case (NonEmpty (f (CaseLabels f' f'))) (f (StatementSequence f' f'))
               | EmptyCase

data CaseLabels f' f = SingleLabel (f (ConstExpression f' f'))
                     | LabelRange (f (ConstExpression f' f')) (f (ConstExpression f' f'))

deriving instance (Typeable f, Typeable f', Data (f (Designator f' f')), Data (f (StatementSequence f' f'))) =>
                  Data (WithAlternative f' f)
deriving instance (Show (f (StatementSequence f' f'))) => Show (WithAlternative f' f)

deriving instance (Typeable f, Typeable f', Data (f (CaseLabels f' f')), Data (f (StatementSequence f' f'))) =>
                  Data (Case f' f)
deriving instance (Show (f (CaseLabels f' f')), Show (f (StatementSequence f' f'))) => Show (Case f' f)

deriving instance (Typeable f, Typeable f', Data (f (ConstExpression f' f'))) => Data (CaseLabels f' f)
deriving instance Show (f (ConstExpression f' f')) => Show (CaseLabels f' f)

$(mconcat <$> mapM Transformation.Deep.TH.deriveAll
  [''Module, ''Declaration, ''Type, ''Expression,
   ''Element, ''Designator, ''FieldList,
   ''ProcedureHeading, ''FormalParameters, ''FPSection, ''ProcedureBody,
   ''Statement, ''StatementSequence, ''WithAlternative, ''Case, ''CaseLabels])