on 821268b help sign in
elk/src/AST/Module.hs
249 lines 4.8 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module AST.Module
4 ( Header(..), HeaderDecl(..), defaultHeaderDecl
5 , Module(..)
7 , Source, SourceInfo(..), SourceTag(..), SourceSettings, emptySettings
8 , Valid, ValidInfo(..)
9 , Canonical, Optimized, Info(..)
11 , UserImport, DefaultImport, ImportMethod(..)
13 , Types
14 , Aliases
15 , Unions, UnionInfo, CanonicalUnion
17 , Interfaces, Interface(..), toInterface, privatize
18 )
19 where
21import Data.Binary
22import qualified Data.Map as Map
23import Data.Text (Text)
25import qualified AST.Declaration as Decl
26import qualified AST.Effects as Effects
27import qualified AST.Exposing as Exposing
28import qualified AST.Expression.Canonical as Canonical
29import qualified AST.Expression.Optimized as Optimized
30import qualified AST.Module.Name as Name
31import qualified AST.Type as Type
32import qualified AST.Variable as Var
33import qualified Docs.AST as Docs
34import qualified Reporting.Annotation as A
35import qualified Reporting.Region as R
39-- HEADERS FOR PARSING
42{-| Basic info needed to identify modules and determine dependencies. -}
43data Header imports =
44 Header
45 { _decl :: Maybe HeaderDecl
46 , _imports :: imports
47 }
50data HeaderDecl =
51 HeaderDecl
52 { _tag :: SourceTag
53 , _name :: Name.Raw
54 , _exports :: Exposing.Raw
55 , _settings :: SourceSettings
56 , _docs :: A.Located (Maybe Text)
57 }
60defaultHeaderDecl :: HeaderDecl
61defaultHeaderDecl =
62 let
63 zero = R.Position 1 1
64 noDocs = A.at zero zero Nothing
65 in
66 HeaderDecl Normal "Main" Exposing.Open emptySettings noDocs
70-- MODULES
73data Module phase =
74 Module
75 { name :: Name.Canonical
76 , info :: phase
77 }
80type Source =
81 Module SourceInfo
84data SourceInfo =
85 Source
86 { srcTag :: SourceTag
87 , srcSettings :: SourceSettings
88 , srcDocs :: A.Located (Maybe Text)
89 , srcExports :: Exposing.Raw
90 , srcImports :: [UserImport]
91 , srcDecls :: [Decl.Source]
92 }
95data SourceTag
96 = Normal
97 | Effect R.Region
98 | Port R.Region
101type SourceSettings =
102 A.Located [(A.Located Text, A.Located Text)]
105emptySettings :: SourceSettings
106emptySettings =
107 A.A (error "region of empty settings should not be needed") []
110type Valid =
111 Module ValidInfo
114data ValidInfo =
115 Valid
116 { validDocs :: A.Located (Maybe Text)
117 , validExports :: Exposing.Raw
118 , validImports :: ([DefaultImport], [UserImport])
119 , validDecls :: Decl.Valid
120 , validEffects :: Effects.Raw
121 }
124type Canonical =
125 Module (Info Canonical.Expr)
128type Optimized =
129 Module (Info [Optimized.Def])
133-- IMPORTS
136type UserImport = A.Located (Name.Raw, ImportMethod)
139type DefaultImport = (Name.Raw, ImportMethod)
142data ImportMethod =
143 ImportMethod
144 { alias :: Maybe Text
145 , exposedVars :: !Exposing.Raw
146 }
150-- LATE PHASE MODULE INFORMATION
153data Info program =
154 Info
155 { docs :: A.Located (Maybe Docs.Centralized)
156 , exports :: Exposing.Canonical
157 , imports :: [Name.Raw]
158 , program :: program
159 , types :: Types
160 , fixities :: [Decl.Infix]
161 , aliases :: Aliases
162 , unions :: Unions
163 , effects :: Effects.Canonical
164 }
167type Types =
168 Map.Map Text Type.Canonical
171type Aliases =
172 Map.Map Text ([Text], Type.Canonical)
175type Unions =
176 Map.Map Text (UnionInfo Text)
179type UnionInfo v =
180 ( [Text], [(v, [Type.Canonical])] )
183type CanonicalUnion =
184 ( Var.Canonical, UnionInfo Var.Canonical )
188-- INTERFACES
191type Interfaces =
192 Map.Map Name.Canonical Interface
195{-| Key facts about a module, used when reading info from .elmi files. -}
196data Interface =
197 Interface
198 { iExports :: Exposing.Canonical
199 , iImports :: [Name.Raw] -- TODO perhaps use this to crawl faster
200 , iTypes :: Types
201 , iUnions :: Unions
202 , iAliases :: Aliases
203 , iFixities :: [Decl.Infix]
204 }
207toInterface :: Optimized -> Interface
208toInterface modul =
209 let
210 myInfo =
211 info modul
212 in
213 Interface
214 { iExports = exports myInfo
215 , iImports = imports myInfo
216 , iTypes = types myInfo
217 , iUnions = unions myInfo
218 , iAliases = aliases myInfo
219 , iFixities = fixities myInfo
220 }
223privatize :: Interface -> Maybe Interface
224privatize (Interface _ _ _ myUnions myAliases _) =
225 if Map.null myUnions && Map.null myAliases then
226 Nothing
228 else
229 Just $ Interface
230 { iExports = Exposing.nothing
231 , iImports = []
232 , iTypes = Map.empty
233 , iUnions = myUnions
234 , iAliases = myAliases
235 , iFixities = []
236 }
239instance Binary Interface where
240 get =
241 Interface <$> get <*> get <*> get <*> get <*> get <*> get
243 put modul =
244 do put (iExports modul)
245 put (iImports modul)
246 put (iTypes modul)
247 put (iUnions modul)
248 put (iAliases modul)
249 put (iFixities modul)