1{-# OPTIONS_GHC -Wall #-}
2module Transform.Declaration (combineAnnotations, toExpr) where
4import Control.Applicative ((<$>))
6import qualified AST.Annotation as A
7import qualified AST.Declaration as D
8import qualified AST.Expression.General as E
9import qualified AST.Expression.Source as Source
10import qualified AST.Expression.Valid as Valid
11import qualified AST.Expression.Canonical as Canonical
12import qualified AST.Module as Module
13import qualified AST.Pattern as P
14import qualified AST.Type as T
15import qualified AST.Variable as Var
17import qualified Transform.Expression as Expr
18import qualified Transform.Definition as Def
21combineAnnotations :: [D.SourceDecl] -> Either String [D.ValidDecl]
25 errorMessage kind name =
26 "Syntax Error: The type annotation for " ++ kind ++ " '" ++
27 name ++ "' must be directly above its definition."
29 exprCombineAnnotations =
30 Expr.crawlLet Def.combineAnnotations
34 -- simple cases, pass them through with no changes
38 D.Datatype name tvars ctors : rest ->
39 (:) (D.Datatype name tvars ctors) <$> go rest
41 D.TypeAlias name tvars alias : rest ->
42 (:) (D.TypeAlias name tvars alias) <$> go rest
44 D.Fixity assoc prec op : rest ->
45 (:) (D.Fixity assoc prec op) <$> go rest
47 -- combine definitions
48 D.Definition def : defRest ->
50 Source.Definition pat expr ->
51 do expr' <- exprCombineAnnotations expr
52 let def' = Valid.Definition pat expr' Nothing
53 (:) (D.Definition def') <$> go defRest
55 Source.TypeAnnotation name tipe ->
57 D.Definition (Source.Definition pat@(P.Var name') expr) : rest
59 do expr' <- exprCombineAnnotations expr
60 let def' = Valid.Definition pat expr' (Just tipe)
61 (:) (D.Definition def') <$> go rest
63 _ -> Left (errorMessage "value" name)
67 D.PortAnnotation name tipe ->
69 D.Port (D.PortDefinition name' expr) : restRest
71 do expr' <- exprCombineAnnotations expr
72 let port' = D.Out name expr' tipe
73 (:) (D.Port port') <$> go restRest
76 (:) (D.Port (D.In name tipe)) <$> go rest
78 D.PortDefinition name _ ->
79 Left (errorMessage "port" name)
82toExpr :: Module.Name -> [D.CanonicalDecl] -> [Canonical.Def]
84 concatMap (toDefs moduleName)
87toDefs :: Module.Name -> D.CanonicalDecl -> [Canonical.Def]
88toDefs moduleName decl =
89 let typeVar = Var.Canonical (Var.Module moduleName) in
94 D.Datatype name tvars constructors ->
95 concatMap toDefs' constructors
97 toDefs' (ctor, tipes) =
98 let vars = take (length tipes) arguments
99 tbody = T.App (T.Type (typeVar name)) (map T.Var tvars)
100 body = A.none . E.Data ctor $ map (A.none . E.localVar) vars
102 [ definition ctor (buildFunction body vars) (foldr T.Lambda tbody tipes) ]
104 D.TypeAlias name tvars tipe@(T.Record fields ext) ->
105 [ definition name (buildFunction record vars) (foldr T.Lambda result args) ]
108 T.Aliased (typeVar name) (zip tvars (map T.Var tvars)) (T.Holey tipe)
111 map snd fields ++ maybe [] (:[]) ext
113 var = A.none . E.localVar
114 vars = take (length args) arguments
116 efields = zip (map fst fields) (map var vars)
119 Nothing -> A.none $ E.Record efields
121 foldl (\r (f,v) -> A.none $ E.Insert r f v) (var $ last vars) efields
123 -- Type aliases must be added to an extended equality dictionary,
124 -- but they do not require any basic constraints.
128 D.Port (D.CanonicalPort impl) ->
129 let body = A.none (E.Port impl)
133 [ definition name body (T.portType tipe) ]
135 E.Out name _expr tipe ->
136 [ definition name body (T.portType tipe) ]
138 E.Task name _expr tipe ->
139 [ definition name body (T.portType tipe) ]
141 -- no constraints are needed for fixity declarations
148 map (:[]) ['a'..'z'] ++ map (\n -> "_" ++ show (n :: Int)) [1..]
151buildFunction :: Canonical.Expr -> [String] -> Canonical.Expr
152buildFunction body@(A.A s _) vars =
153 foldr (\p e -> A.A s (E.Lambda p e)) body (map P.Var vars)
156definition :: String -> Canonical.Expr -> T.CanonicalType -> Canonical.Def
157definition name expr tipe =
158 Canonical.Definition (P.Var name) expr (Just tipe)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list