on befb3df help sign in
elk/src/AST/Module.hs
245 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 [(Text, Optimized.Decl)])
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 (Module _ myInfo) =
209 Interface
210 { iExports = exports myInfo
211 , iImports = imports myInfo
212 , iTypes = types myInfo
213 , iUnions = unions myInfo
214 , iAliases = aliases myInfo
215 , iFixities = fixities myInfo
216 }
219privatize :: Interface -> Maybe Interface
220privatize (Interface _ _ _ myUnions myAliases _) =
221 if Map.null myUnions && Map.null myAliases then
222 Nothing
224 else
225 Just $ Interface
226 { iExports = Exposing.nothing
227 , iImports = []
228 , iTypes = Map.empty
229 , iUnions = myUnions
230 , iAliases = myAliases
231 , iFixities = []
232 }
235instance Binary Interface where
236 get =
237 Interface <$> get <*> get <*> get <*> get <*> get <*> get
239 put modul =
240 do put (iExports modul)
241 put (iImports modul)
242 put (iTypes modul)
243 put (iUnions modul)
244 put (iAliases modul)
245 put (iFixities modul)