language-Modula2-0.1.2: src/Language/Modula2/ISO/AST.hs
{-# LANGUAGE DataKinds, DeriveDataTypeable, FlexibleContexts, FlexibleInstances, GADTs, KindSignatures, InstanceSigs,
MultiParamTypeClasses, UndecidableInstances,
ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TypeFamilies #-}
{-# OPTIONS_GHC -Wno-simplifiable-class-constraints #-}
-- | ISO Modula-2 Abstract Syntax Tree definitions
module Language.Modula2.ISO.AST where
import Control.Applicative (ZipList(ZipList, getZipList))
import Control.Monad (forM, mapM)
import Data.Coerce (coerce)
import Data.Data (Data, Typeable)
import Data.List.NonEmpty
import Data.Text (Text)
import qualified Transformation.Shallow.TH
import qualified Transformation.Deep.TH
import qualified Rank2 as Rank2
import qualified Rank2.TH
import qualified Language.Modula2.Abstract as Abstract
import qualified Language.Modula2.ISO.Abstract as ISO.Abstract
import qualified Language.Modula2.AST as Report
import Language.Modula2.Abstract (Ident)
import Language.Modula2.AST hiding (Language, Block(..), Declaration(..), Expression(..), Statement(..),
Type(..), Variant(..))
-- | Data type representing the Modula-2 language, as specified by the ISO standard.
data Language = Language deriving (Data, Typeable)
instance Abstract.Wirthy Language where
type Module Language = Module Language
type Declaration Language = Declaration True Language
type Type Language = Type Language
type Statement Language = Statement Language
type Expression Language = Expression Language
type Designator Language = Designator Language
type Value Language = Value Language
type Import Language = Import Language
type FieldList Language = FieldList Language
type ProcedureHeading Language = ProcedureHeading Language
type FormalParameters Language = FormalParameters Language
type FPSection Language = FPSection Language
type Block Language = Block Language
type StatementSequence Language = StatementSequence Language
type Case Language = Case Language
type CaseLabels Language = CaseLabels Language
type ConditionalBranch Language = ConditionalBranch Language
type Element Language = Element Language
type IdentDef Language = Ident
type QualIdent Language = QualIdent Language
-- Declaration
constantDeclaration = ConstantDeclaration
typeDeclaration = TypeDeclaration
variableDeclaration = VariableDeclaration
procedureDeclaration = ProcedureDeclaration
formalParameters = FormalParameters . ZipList
fpSection = FPSection
block = Block . ZipList
fieldList = FieldList
-- Type
pointerType = PointerType
procedureType = ProcedureType
typeReference = TypeReference
-- Statement
assignment = Assignment
caseStatement scrutinee cases = CaseStatement scrutinee (ZipList cases)
emptyStatement = EmptyStatement
exitStatement = Exit
ifStatement (branch :| branches) = If branch (ZipList branches)
loopStatement = Loop
procedureCall proc args = ProcedureCall proc (ZipList <$> args)
repeatStatement = Repeat
returnStatement = Return
whileStatement = While
conditionalBranch = ConditionalBranch
caseAlternative (c :| cs) = Case c (ZipList cs)
labelRange = LabelRange
singleLabel = SingleLabel
statementSequence = StatementSequence . ZipList
-- Expression
add = Add
subtract = Subtract
and = And
or = Or
divide = Divide
integerDivide = IntegerDivide
literal = Literal
modulo = Modulo
multiply = Multiply
functionCall fun args = FunctionCall fun (ZipList args)
negative = Negative
positive = Positive
not = Not
read = Read
relation = Relation
element = Element
range = Range
-- Value
builtin = Builtin
integer = Integer
nil = Nil
real = Real
string = String
charCode = CharCode
false = Boolean False
true = Boolean True
-- Designator
variable = Variable
field = Field
index array (index :| indexes) = Index array index (ZipList indexes)
dereference = Dereference
-- Identifier
identDef = id
nonQualIdent = QualIdent []
instance Abstract.CoWirthy Language where
type TargetClass Language = ISO.Abstract.Modula2
coDeclaration (ConstantDeclaration name value) = Abstract.constantDeclaration name value
coDeclaration (TypeDeclaration name ty) = Abstract.typeDeclaration name ty
coDeclaration (VariableDeclaration name ty) = Abstract.variableDeclaration name ty
coDeclaration (ProcedureDeclaration heading body) = Abstract.procedureDeclaration heading body
coDeclaration (AddressedVariableDeclaration var vars tp) =
ISO.Abstract.addressedVariableDeclaration (var :| getZipList vars) tp
coDeclaration (ForwardProcedureDeclaration heading) = ISO.Abstract.forwardProcedureDeclaration heading
coDeclaration (ModuleDeclaration name priority imports exports body) =
Abstract.moduleDeclaration name priority imports exports body
coType (ArrayType dimensions itemType) = Abstract.arrayType (getZipList dimensions) itemType
coType (EnumerationType names) = Abstract.enumeration names
coType (PackedSetType base) = ISO.Abstract.packedSetType base
coType (PointerType destination) = Abstract.pointerType destination
coType (ProcedureType params) = Abstract.procedureType params
coType (RecordType fields) = Abstract.recordType (getZipList fields)
coType (SetType itemType) = Abstract.setType itemType
coType (SubrangeType base low high) = Abstract.subRange base low high
coType (TypeReference q) = Abstract.typeReference q
coStatement EmptyStatement = Abstract.emptyStatement
coStatement (Assignment destination expression) = Abstract.assignment destination expression
coStatement (ProcedureCall procedure parameters) = Abstract.procedureCall procedure $ getZipList <$> parameters
coStatement (If branch elsifs fallback) = Abstract.ifStatement (branch :| getZipList elsifs) fallback
coStatement (CaseStatement scrutinee cases fallback) =
Abstract.caseStatement scrutinee (getZipList cases) fallback
coStatement (While condition body) = Abstract.whileStatement condition body
coStatement (Repeat body condition) = Abstract.repeatStatement body condition
coStatement (Loop body) = Abstract.loopStatement body
coStatement (With designator body) = Abstract.withStatement designator body
coStatement Exit = Abstract.exitStatement
coStatement (Return result) = Abstract.returnStatement result
coStatement (For index from to by body) = Abstract.forStatement index from to by body
coStatement RetryStatement = ISO.Abstract.retryStatement
coExpression (Relation op left right) = Abstract.relation op left right
coExpression (Positive e) = Abstract.positive e
coExpression (Negative e) = Abstract.negative e
coExpression (Add left right) = Abstract.add left right
coExpression (Subtract left right) = Abstract.subtract left right
coExpression (Or left right) = Abstract.or left right
coExpression (Multiply left right) = Abstract.multiply left right
coExpression (Divide left right) = Abstract.divide left right
coExpression (IntegerDivide left right) = Abstract.integerDivide left right
coExpression (Modulo left right) = Abstract.modulo left right
coExpression (And left right) = Abstract.and left right
coExpression (Literal value) = Abstract.literal value
coExpression (Read var) = Abstract.read var
coExpression (FunctionCall function parameters) = Abstract.functionCall function $ getZipList parameters
coExpression (Not e) = Abstract.not e
coExpression (Set itemType elements) = Abstract.set itemType (getZipList elements)
coExpression (Remainder left right) = ISO.Abstract.remainder left right
coExpression (Array itemType items) = ISO.Abstract.array itemType items
coExpression (Record tp fields) = ISO.Abstract.record tp fields
coValue Nil = Abstract.nil
coValue (Boolean False) = Abstract.false
coValue (Boolean True) = Abstract.true
coValue (Builtin name) = Abstract.builtin name
coValue (Integer n) = Abstract.integer n
coValue (Real r) = Abstract.real r
coValue (String s) = Abstract.string s
coValue (CharCode c) = Abstract.charCode c
coDesignator (Variable q) = Abstract.variable q
coDesignator (Field record name) = Abstract.field record name
coDesignator (Index array index indexes) = Abstract.index array (index :| getZipList indexes)
coDesignator (Dereference pointer) = Abstract.dereference pointer
instance Abstract.Nameable Language where
getProcedureName (ProcedureHeading name _) = name
getIdentDefName = id
getNonQualIdentName (QualIdent [] name) = Just name
getNonQualIdentName _ = Nothing
instance Abstract.Modula2 Language where
type Export Language = Export Language
type Definition Language = Declaration False Language
type Variant Language = Variant Language
-- Module
definitionModule name imports exports definitions = DefinitionModule name imports exports (ZipList definitions)
implementationModule = ImplementationModule
programModule = ProgramModule
moduleExport = Export
moduleImport = Import
-- Definition
constantDefinition = ConstantDeclaration
typeDefinition = \name-> maybe (OpaqueTypeDeclaration name) (TypeDeclaration name)
variableDefinition = VariableDeclaration
procedureDefinition = ProcedureDefinition
-- Declaration
moduleDeclaration = ModuleDeclaration
-- Type
arrayType = ArrayType . ZipList
recordType = RecordType . ZipList
procedureHeading = ProcedureHeading
caseFieldList n t (variant :| variants) fallback = CaseFieldList n t variant (ZipList variants) (ZipList fallback)
variant (case1 :| cases) fields = Variant case1 (ZipList cases) (ZipList fields)
forStatement = For
withStatement = With
enumeration = EnumerationType
subRange = SubrangeType
setType = SetType
-- Expression
set memberType members = Set memberType (ZipList members)
qualIdent = QualIdent
instance ISO.Abstract.Modula2 Language where
type AddressedIdent Language = AddressedIdent Language
type Item Language = Item Language
-- Declaration
emptyVariant = EmptyVariant
addressedVariableDeclaration (var :| vars) = AddressedVariableDeclaration var (ZipList vars)
forwardProcedureDeclaration = ForwardProcedureDeclaration
exceptionHandlingBlock = ExceptionHandlingBlock . ZipList
addressedIdent = AddressedIdent
unaddressedIdent = UnaddressedIdent
-- Type
packedSetType = PackedSetType
-- Statement
retryStatement = RetryStatement
-- Expression
array = Array
record = Record
remainder = Remainder
-- Compound expression
single = Single
repeated = Repeated
data Declaration (full :: Bool) λ l (f' :: * -> *) (f :: * -> *) where
ConstantDeclaration :: Abstract.IdentDef l -> f (Abstract.ConstExpression l l f' f') -> Declaration x λ l f' f
TypeDeclaration :: Abstract.IdentDef l -> f (Abstract.Type l l f' f') -> Declaration x λ l f' f
OpaqueTypeDeclaration :: Abstract.IdentDef l -> Declaration False λ l f' f
VariableDeclaration :: Abstract.IdentList l -> f (Abstract.Type l l f' f') -> Declaration x λ l f' f
AddressedVariableDeclaration :: f (ISO.Abstract.AddressedIdent l l f' f')
-> ZipList (f (ISO.Abstract.AddressedIdent l l f' f'))
-> f (Abstract.Type l l f' f')
-> Declaration True λ l f' f
ProcedureDeclaration :: f (Abstract.ProcedureHeading l l f' f') -> f (Abstract.Block l l f' f')
-> Declaration True λ l f' f
ProcedureDefinition :: f (Abstract.ProcedureHeading l l f' f') -> Declaration False λ l f' f
ForwardProcedureDeclaration :: f (Abstract.ProcedureHeading l l f' f') -> Declaration True λ l f' f
ModuleDeclaration :: Ident -> Maybe (f (Abstract.Priority l l f' f')) -> [Abstract.Import l]
-> Maybe (Abstract.Export l) -> f (Abstract.Block l l f' f') -> Declaration True λ l f' f
deriving instance (Show (Abstract.Export l), Show (Abstract.Import l), Show (f (ISO.Abstract.AddressedIdent l l f' f')),
Show (f (Abstract.Type l l f' f')), Show (f (Abstract.ConstExpression l l f' f')),
Show (f (Abstract.FormalParameters l l f' f')), Show (f (Abstract.ProcedureHeading l l f' f')),
Show (f (Abstract.Block l l f' f')), Show (f (Abstract.Block l l f' f')),
Show (Abstract.IdentDef l)) => Show (Declaration x λ l f' f)
data AddressedIdent λ l f' f = AddressedIdent Ident (f (Abstract.ConstExpression l l f' f'))
| UnaddressedIdent Ident
deriving instance (Typeable λ, Typeable l, Typeable f, Typeable f',
Data (f (Abstract.ConstExpression l l f' f'))) => Data (AddressedIdent λ l f' f)
deriving instance (Show (f (Abstract.ConstExpression l l f' f'))) => Show (AddressedIdent λ l f' f)
data Type λ l f' f = TypeReference (Abstract.QualIdent l)
| ArrayType (ZipList (f (Abstract.Type l l f' f'))) (f (Abstract.Type l l f' f'))
| EnumerationType (Abstract.IdentList l)
| SubrangeType (Maybe (Abstract.QualIdent l))
(f (Abstract.ConstExpression l l f' f')) (f (Abstract.ConstExpression l l f' f'))
| SetType (f (Abstract.Type l l f' f'))
| PackedSetType (f (Abstract.Type l l f' f'))
| RecordType (ZipList (f (Abstract.FieldList l l f' f')))
| PointerType (f (Abstract.Type l l f' f'))
| ProcedureType (Maybe (f (Abstract.FormalParameters l l f' f')))
deriving instance (Typeable λ, Typeable l, Typeable f, Typeable f',
Data (Abstract.QualIdent l), Data (Abstract.IdentList l),
Data (f (Abstract.Type l l f' f')), Data (f (Abstract.ConstExpression l l f' f')),
Data (f (Abstract.FormalParameters l l f' f')), Data (f (Abstract.FieldList l l f' f'))) =>
Data (Type λ l f' f)
deriving instance (Show (Abstract.QualIdent l), Show (Abstract.IdentList l), Show (f (Abstract.Type l l f' f')),
Show (f (Abstract.ConstExpression l l f' f')), Show (f (Abstract.FormalParameters l l f' f')),
Show (f (Abstract.FieldList l l f' f'))) =>
Show (Type λ l f' f)
data Expression λ l f' f = Relation RelOp (f (Abstract.Expression l l f' f')) (f (Abstract.Expression l l f' f'))
| Positive (f (Abstract.Expression l l f' f'))
| Negative (f (Abstract.Expression l l f' f'))
| Add (f (Abstract.Expression l l f' f')) (f (Abstract.Expression l l f' f'))
| Subtract (f (Abstract.Expression l l f' f')) (f (Abstract.Expression l l f' f'))
| Or (f (Abstract.Expression l l f' f')) (f (Abstract.Expression l l f' f'))
| Multiply (f (Abstract.Expression l l f' f')) (f (Abstract.Expression l l f' f'))
| Divide (f (Abstract.Expression l l f' f')) (f (Abstract.Expression l l f' f'))
| IntegerDivide (f (Abstract.Expression l l f' f')) (f (Abstract.Expression l l f' f'))
| Modulo (f (Abstract.Expression l l f' f')) (f (Abstract.Expression l l f' f'))
| Remainder (f (Abstract.Expression l l f' f')) (f (Abstract.Expression l l f' f'))
| And (f (Abstract.Expression l l f' f')) (f (Abstract.Expression l l f' f'))
| Array (Maybe (Abstract.QualIdent l)) [f (ISO.Abstract.Item l l f' f')]
| Record (Maybe (Abstract.QualIdent l)) [f (Abstract.Expression l l f' f')]
| Set (Maybe (Abstract.QualIdent l)) (ZipList (f (Abstract.Element l l f' f')))
| Read (f (Abstract.Designator l l f' f'))
| FunctionCall (f (Abstract.Designator l l f' f')) (ZipList (f (Abstract.Expression l l f' f')))
| Not (f (Abstract.Expression l l f' f'))
| Literal (f (Abstract.Value l l f' f'))
data Item λ l f' f = Single (f (Abstract.Expression l l f' f'))
| Repeated (f (Abstract.Expression l l f' f')) (f (Abstract.ConstExpression l l f' f'))
deriving instance (Typeable λ, Typeable l, Typeable f, Typeable f', Data (Abstract.QualIdent l),
Data (f (Abstract.Designator l l f' f')), Data (f (Abstract.Element l l f' f')),
Data (f (ISO.Abstract.Item l l f' f')), Data (f (Abstract.Value l l f' f')),
Data (f (Abstract.Expression l l f' f'))) =>
Data (Expression λ l f' f)
deriving instance (Show (Abstract.QualIdent l), Show (f (Abstract.Designator l l f' f')),
Show (f (Abstract.Element l l f' f')), Show (f (ISO.Abstract.Item l l f' f')),
Show (f (Abstract.Value l l f' f')), Show (f (Abstract.Expression l l f' f'))) => Show (Expression λ l f' f)
deriving instance (Eq (Abstract.QualIdent l), Eq (f (Abstract.Designator l l f' f')),
Eq (f (Abstract.Element l l f' f')), Eq (f (ISO.Abstract.Item l l f' f')),
Eq (f (Abstract.Value l l f' f')), Eq (f (Abstract.Expression l l f' f'))) => Eq (Expression λ l f' f)
deriving instance (Typeable λ, Typeable l, Typeable f, Typeable f', Data (f (Abstract.Expression l l f' f')),
Data (f (Abstract.Expression l l f' f'))) =>
Data (Item λ l f' f)
deriving instance (Show (f (Abstract.Expression l l f' f'))) => Show (Item λ l f' f)
deriving instance (Eq (f (Abstract.Expression l l f' f'))) => Eq (Item λ l f' f)
data Variant λ l f' f =
Variant (f (Abstract.CaseLabels l l f' f')) (ZipList (f (Abstract.CaseLabels l l f' f')))
(ZipList (f (Abstract.FieldList l l f' f')))
| EmptyVariant
deriving instance (Typeable λ, Typeable l, Typeable f, Typeable f', Data (f (Abstract.CaseLabels l l f' f')),
Data (f (Abstract.FieldList l l f' f'))) => Data (Variant λ l f' f)
deriving instance (Show (f (Abstract.CaseLabels l l f' f')), Show (f (Abstract.FieldList l l f' f')))
=> Show (Variant λ l f' f)
data Block λ l f' f = Block (ZipList (f (Abstract.Declaration l l f' f'))) (Maybe (f (Abstract.StatementSequence l l f' f')))
| ExceptionHandlingBlock (ZipList (f (Abstract.Declaration l l f' f')))
(Maybe (f (Abstract.StatementSequence l l f' f')))
(Maybe (f (Abstract.StatementSequence l l f' f')))
(Maybe (f (Abstract.StatementSequence l l f' f')))
deriving instance (Typeable λ, Typeable l, Typeable f, Typeable f', Data (f (Abstract.Declaration l l f' f')),
Data (f (Abstract.Designator l l f' f')), Data (f (Abstract.Expression l l f' f')),
Data (f (Abstract.StatementSequence l l f' f'))) =>
Data (Block λ l f' f)
deriving instance (Show (f (Abstract.Declaration l l f' f')), Show (f (Abstract.Designator l l f' f')),
Show (f (Abstract.Expression l l f' f')), Show (f (Abstract.StatementSequence l l f' f'))) =>
Show (Block λ l f' f)
data Statement λ l f' f = EmptyStatement
| Assignment (f (Abstract.Designator l l f' f')) (f (Abstract.Expression l l f' f'))
| ProcedureCall (f (Abstract.Designator l l f' f')) (Maybe (ZipList (f (Abstract.Expression l l f' f'))))
| If (f (Abstract.ConditionalBranch l l f' f'))
(ZipList (f (Abstract.ConditionalBranch l l f' f')))
(Maybe (f (Abstract.StatementSequence l l f' f')))
| CaseStatement (f (Abstract.Expression l l f' f'))
(ZipList (f (Abstract.Case l l f' f')))
(Maybe (f (Abstract.StatementSequence l l f' f')))
| While (f (Abstract.Expression l l f' f')) (f (Abstract.StatementSequence l l f' f'))
| Repeat (f (Abstract.StatementSequence l l f' f')) (f (Abstract.Expression l l f' f'))
| For Ident (f (Abstract.Expression l l f' f')) (f (Abstract.Expression l l f' f'))
(Maybe (f (Abstract.Expression l l f' f'))) (f (Abstract.StatementSequence l l f' f'))
| Loop (f (Abstract.StatementSequence l l f' f'))
| With (f (Abstract.Designator l l f' f')) (f (Abstract.StatementSequence l l f' f'))
| Exit
| Return (Maybe (f (Abstract.Expression l l f' f')))
| RetryStatement
deriving instance (Typeable λ, Typeable l, Typeable f, Typeable f',
Data (f (Abstract.Designator l l f' f')), Data (f (Abstract.Expression l l f' f')),
Data (f (Abstract.Case l l f' f')), Data (f (Abstract.ConditionalBranch l l f' f')),
Data (f (Abstract.StatementSequence l l f' f'))) => Data (Statement λ l f' f)
deriving instance (Show (f (Abstract.Designator l l f' f')), Show (f (Abstract.Expression l l f' f')),
Show (f (Abstract.Case l l f' f')), Show (f (Abstract.ConditionalBranch l l f' f')),
Show (f (Abstract.StatementSequence l l f' f'))) => Show (Statement λ l f' f)
$(concat <$>
(forM [Rank2.TH.deriveFunctor, Rank2.TH.deriveFoldable, Rank2.TH.deriveTraversable,
Transformation.Shallow.TH.deriveAll, Transformation.Deep.TH.deriveAll] $
\derive-> mconcat <$> mapM derive
[''AddressedIdent, ''Block, ''Declaration, ''Expression, ''Item, ''Statement, ''Type, ''Variant]))
$(mconcat <$> mapM Rank2.TH.unsafeDeriveApply
[''AddressedIdent, ''Block, ''Declaration, ''Type, ''Statement, ''Expression, ''Item, ''Variant])