on 542c763 help sign in
elk/src/AST/Module.hs
243 lines 4.8 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module AST.Module
4 ( Header(..), defaultHeader, Module(..)
6 , Source, SourceInfo(..), SourceTag(..), SourceSettings, emptySettings
7 , Valid, ValidInfo(..)
8 , Canonical, Optimized, Info(..)
10 , UserImport, DefaultImport, ImportMethod(..)
12 , Types
13 , Aliases
14 , Unions, UnionInfo, CanonicalUnion
16 , Interfaces, Interface(..), toInterface, privatize
17 )
18 where
20import Data.Binary
21import qualified Data.Map as Map
22import Data.Text (Text)
24import qualified AST.Declaration as Decl
25import qualified AST.Effects as Effects
26import qualified AST.Expression.Canonical as Canonical
27import qualified AST.Expression.Optimized as Optimized
28import qualified AST.Module.Name as Name
29import qualified AST.Type as Type
30import qualified AST.Variable as Var
31import qualified Docs.AST as Docs
32import qualified Reporting.Annotation as A
33import qualified Reporting.Region as R
37-- HEADERS FOR PARSING
40{-| Basic info needed to identify modules and determine dependencies. -}
41data Header imports =
42 Header
43 { _tag :: SourceTag
44 , _name :: Name.Raw
45 , _exports :: Var.Listing (A.Located Var.Value)
46 , _settings :: SourceSettings
47 , _docs :: A.Located (Maybe Text)
48 , _imports :: imports
49 }
52instance Show (Header a) where
53 show header =
54 show (_name header)
57defaultHeader :: R.Position -> R.Position -> imports -> Header imports
58defaultHeader start end imports_ =
59 Header Normal "Main" Var.openListing emptySettings (A.at start end Nothing) imports_
63-- MODULES
66data Module phase =
67 Module
68 { name :: Name.Canonical
69 , path :: FilePath
70 , info :: phase
71 }
74type Source =
75 Module SourceInfo
78data SourceInfo =
79 Source
80 { srcTag :: SourceTag
81 , srcSettings :: SourceSettings
82 , srcDocs :: A.Located (Maybe Text)
83 , srcExports :: Var.Listing (A.Located Var.Value)
84 , srcImports :: [UserImport]
85 , srcDecls :: [Decl.Source]
86 }
89data SourceTag
90 = Normal
91 | Effect R.Region
92 | Port R.Region
95type SourceSettings =
96 A.Located [(A.Located Text, A.Located Text)]
99emptySettings :: SourceSettings
100emptySettings =
101 A.A (error "region of empty settings should not be needed") []
104type Valid =
105 Module ValidInfo
108data ValidInfo =
109 Valid
110 { validDocs :: A.Located (Maybe Text)
111 , validExports :: Var.Listing (A.Located Var.Value)
112 , validImports :: ([DefaultImport], [UserImport])
113 , validDecls :: Decl.Valid
114 , validEffects :: Effects.Raw
115 }
118type Canonical =
119 Module (Info Canonical.Expr)
122type Optimized =
123 Module (Info [Optimized.Def])
127-- IMPORTS
130type UserImport = A.Located (Name.Raw, ImportMethod)
133type DefaultImport = (Name.Raw, ImportMethod)
136data ImportMethod =
137 ImportMethod
138 { alias :: Maybe Text
139 , exposedVars :: !(Var.Listing Var.Value)
140 }
144-- LATE PHASE MODULE INFORMATION
147data Info program =
148 Info
149 { docs :: A.Located (Maybe Docs.Centralized)
150 , exports :: [Var.Value]
151 , imports :: [Name.Raw]
152 , program :: program
153 , types :: Types
154 , fixities :: [Decl.Infix]
155 , aliases :: Aliases
156 , unions :: Unions
157 , effects :: Effects.Canonical
158 }
161type Types =
162 Map.Map Text Type.Canonical
165type Aliases =
166 Map.Map Text ([Text], Type.Canonical)
169type Unions =
170 Map.Map Text (UnionInfo Text)
173type UnionInfo v =
174 ( [Text], [(v, [Type.Canonical])] )
177type CanonicalUnion =
178 ( Var.Canonical, UnionInfo Var.Canonical )
182-- INTERFACES
185type Interfaces =
186 Map.Map Name.Canonical Interface
189{-| Key facts about a module, used when reading info from .elmi files. -}
190data Interface =
191 Interface
192 { iExports :: [Var.Value]
193 , iImports :: [Name.Raw] -- TODO perhaps use this to crawl faster
194 , iTypes :: Types
195 , iUnions :: Unions
196 , iAliases :: Aliases
197 , iFixities :: [Decl.Infix]
198 }
201toInterface :: Optimized -> Interface
202toInterface modul =
203 let
204 myInfo =
205 info modul
206 in
207 Interface
208 { iExports = exports myInfo
209 , iImports = imports myInfo
210 , iTypes = types myInfo
211 , iUnions = unions myInfo
212 , iAliases = aliases myInfo
213 , iFixities = fixities myInfo
214 }
217privatize :: Interface -> Maybe Interface
218privatize (Interface _ _ _ myUnions myAliases _) =
219 if Map.null myUnions && Map.null myAliases then
220 Nothing
222 else
223 Just $ Interface
224 { iExports = []
225 , iImports = []
226 , iTypes = Map.empty
227 , iUnions = myUnions
228 , iAliases = myAliases
229 , iFixities = []
230 }
233instance Binary Interface where
234 get =
235 Interface <$> get <*> get <*> get <*> get <*> get <*> get
237 put modul =
238 do put (iExports modul)
239 put (iImports modul)
240 put (iTypes modul)
241 put (iUnions modul)
242 put (iAliases modul)
243 put (iFixities modul)