elm/compiler/Transform/Declaration.hs

64 lines
2.3 KiB
Haskell
Raw Normal View History

{-# OPTIONS_GHC -Wall #-}
module Transform.Declaration where
import Control.Applicative ((<$>))
import qualified SourceSyntax.Pattern as P
import SourceSyntax.Expression as E
import SourceSyntax.Declaration as D
import qualified Transform.Expression as Expr
import qualified Transform.Definition as Def
combineAnnotations :: [ParseDeclaration] -> Either String [Declaration]
combineAnnotations = go
where
msg x = "Syntax Error: The type annotation for '" ++ x ++
"' must be directly above its definition."
exprCombineAnnotations = Expr.crawlLet Def.combineAnnotations
go decls =
case decls of
-- simple cases, pass them through with no changes
[] -> return []
Datatype name tvars ctors : rest ->
(:) (Datatype name tvars ctors) <$> go rest
TypeAlias name tvars alias : rest ->
(:) (TypeAlias name tvars alias) <$> go rest
Fixity assoc prec op : rest ->
(:) (Fixity assoc prec op) <$> go rest
-- combine definitions
D.Definition def : defRest ->
case def of
Def pat expr ->
do expr' <- exprCombineAnnotations expr
let def' = E.Definition pat expr' Nothing
(:) (D.Definition def') <$> go defRest
TypeAnnotation name tipe ->
case defRest of
D.Definition (Def pat@(P.PVar name') expr) : rest | name == name' ->
do expr' <- exprCombineAnnotations expr
let def' = E.Definition pat expr' (Just tipe)
(:) (D.Definition def') <$> go rest
_ -> Left (msg name)
-- combine ports
Port port : portRest ->
case port of
2014-01-13 18:24:17 +00:00
PPDef name _ -> Left (msg name)
PPAnnotation name tipe ->
case portRest of
2014-01-13 18:24:17 +00:00
Port (PPDef name' expr) : rest | name == name' ->
do expr' <- exprCombineAnnotations expr
(:) (Port (Out name expr' tipe)) <$> go rest
2014-01-13 18:24:17 +00:00
_ -> (:) (Port (In name tipe)) <$> go portRest