mulang-3.6.0: src/Language/Mulang/Generator.hs
module Language.Mulang.Generator (
boundDeclarations,
declarations,
declarationsOf,
declaredIdentifiers,
mainDeclaredIdentifiers,
equationBodies,
expressions,
referencedIdentifiers,
identifierReferences,
transitiveReferencedIdentifiers,
Generator,
Expression(..)) where
import Language.Mulang.Ast
import Language.Mulang.Identifier
import Data.Maybe (mapMaybe)
import Data.List (nub)
type Generator a = Expression -> [a]
-- | Returns all the declarations their identifiers -
-- | classes, methods, functions, records, local and global variables, and so on
-- |
-- | For example, in 'f x = g x where x = y', it returns '(f, f x = ...)' and '(x, x = y)'
declarations :: Generator (Identifier, Expression)
declarations (Sequence es) = concatMap declarations es
declarations e@(Attribute n _) = [(n, e)]
declarations e@(Class n _ b) = (n, e) : declarations b
declarations e@(Clause n _ es) = (n, e) : concatMap declarations es
declarations e@(Enumeration n _) = [(n, e)]
declarations e@(Interface n _ b) = (n, e) : declarations b
declarations e@(EntryPoint n b) = (n, e) : declarations b
declarations e@(Subroutine n b) = (n, e) : concatMap declarations (equationExpressions b)
declarations e@(Object n b) = (n, e) : declarations b
declarations e@(Clause n _ _) = [(n, e)]
declarations e@(Record n) = [(n, e)]
declarations e@(TypeAlias n) = [(n, e)]
declarations e@(TypeSignature n _ _)= [(n, e)]
declarations e@(Variable n _) = [(n, e)]
declarations _ = []
-- | Returns all declarations bound to the given identifier predicate
-- |
boundDeclarations :: IdentifierPredicate -> Generator Expression
boundDeclarations f = map snd . filter (f.fst) . declarations
-- | Returns the given expression and all its subexpressions
-- For example: in 'f x = x + 1', it returns 'f x = x + 1', 'x + 1', 'x' and '1'
expressions :: Generator Expression
expressions expr = expr : concatMap expressions (subExpressions expr)
where
subExpressions :: Generator Expression
subExpressions (Assignment _ e) = [e]
subExpressions (Attribute _ v) = [v]
subExpressions (Call op args) = op:args
subExpressions (Class _ _ v) = [v]
subExpressions (Clause _ _ es) = es
subExpressions (Comprehension a _) = [a] --TODO
subExpressions (EntryPoint _ e) = [e]
subExpressions (Forall e1 e2) = [e1, e2]
subExpressions (If a b c) = [a, b, c]
subExpressions (Interface _ _ v) = [v]
subExpressions (Lambda _ a) = [a]
subExpressions (Match e1 equations) = e1:equationExpressions equations
subExpressions (MuList as) = as
subExpressions (MuObject es) = [es]
subExpressions (MuTuple as) = as
subExpressions (New _ es) = es
subExpressions (Not e) = [e]
subExpressions (Object _ v) = [v]
subExpressions (Repeat e1 e2) = [e1, e2]
subExpressions (Return v) = [v]
subExpressions (Sequence es) = es
subExpressions (Subroutine _ es) = equationExpressions es
subExpressions (Switch e1 list _) = e1 : concatMap (\(x,y) -> [x,y]) list
subExpressions (Try t cs f) = t : map snd cs ++ [f]
subExpressions (Variable _ v) = [v]
subExpressions (While e1 e2) = [e1, e2]
subExpressions _ = []
-- | Returns all the referenced identifiers
-- For example, in 'f (x + 1)', it returns 'f' and 'x'
referencedIdentifiers :: Generator Identifier
referencedIdentifiers = nub . identifierReferences
identifierReferences :: Generator Identifier
identifierReferences = mapMaybe extractReference . expressions
-- | Returns all the identifiers transitively referenced by the given one
-- |
transitiveReferencedIdentifiers :: Identifier -> Generator Identifier
transitiveReferencedIdentifiers identifier code = expand (concatMap referencedIdentifiers . (`declarationsOf` code)) identifier
where
expand :: Eq a => (a-> [a]) -> a -> [a]
expand f x = expand' [] f [x]
expand' _ _ [] = []
expand' ps f (x:xs) | elem x ps = expand' ps f xs
| otherwise = [x] ++ expand' (x:ps) f (xs ++ f x)
-- | Returns all the declared identifiers
-- For example, in 'f x = g x where x = y', it returns 'f' and 'x'
declaredIdentifiers :: Generator Identifier
declaredIdentifiers = map fst . declarations
mainDeclaredIdentifiers :: Generator Identifier
mainDeclaredIdentifiers (Sequence _) = []
mainDeclaredIdentifiers expression = take 1 . declaredIdentifiers $ expression
-- | Returns all the body equations of functions, procedures and methods
equationBodies :: Generator EquationBody
equationBodies = concatMap (bodiesOf . snd) . declarations
where
bodiesOf :: Generator EquationBody
bodiesOf (Subroutine _ equations) = equationBodies equations
bodiesOf _ = []
equationBodies = map (\(Equation _ body) -> body)
declarationsOf :: Identifier -> Generator Expression
declarationsOf b = boundDeclarations (named b)
extractReference :: Expression -> Maybe Identifier
extractReference (Reference n) = Just n
extractReference (Exist n _) = Just n
extractReference (New n _) = Just n
extractReference (Implement n) = Just n
extractReference (Include n) = Just n
extractReference _ = Nothing
equationExpressions = concatMap (\(Equation _ body) -> bodyExpressions body)
where
bodyExpressions (UnguardedBody e) = [e]
bodyExpressions (GuardedBody b) = b >>= \(es1, es2) -> [es1, es2]