@@ -2,8 +2,14 @@
22module Elm.Interface
33 ( Interfaces
44 , Interface(..)
5+ , Union
6+ , Alias
57 , Binop(..)
68 , fromModule
9+ , toPublicUnion
10+ , toPublicAlias
11+ , toUnionInternals
12+ , toAliasInternals
713 )
814 where
915
@@ -12,6 +18,7 @@ import Control.Monad (liftM4)
1218import Data.Binary
1319import Data.Map ((!))
1420import qualified Data.Map as Map
21+import qualified Data.Map.Merge.Strict as Map
1522
1623import qualified AST.Canonical as Can
1724import qualified AST.Module.Name as ModuleName
@@ -35,12 +42,23 @@ type Interfaces =
3542data Interface =
3643 Interface
3744 { _types :: Map.Map N.Name Can.Annotation
38− , _unions :: Map.Map N.Name Can.Union
39− , _aliases :: Map.Map N.Name Can.Alias
45+ , _unions :: Map.Map N.Name Union
46+ , _aliases :: Map.Map N.Name Alias
4047 , _binops :: Map.Map N.Name Binop
4148 }
4249
4350
51+data Union
52+ = OpenUnion Can.Union
53+ | ClosedUnion Can.Union
54+ | PrivateUnion Can.Union
55+
56+
57+data Alias
58+ = PublicAlias Can.Alias
59+ | PrivateAlias Can.Alias
60+
61+
4462data Binop =
4563 Binop
4664 { _op_name :: N.Name
@@ -57,39 +75,104 @@ data Binop =
5775fromModule :: Map.Map N.Name Can.Annotation -> Can.Module -> Interface
5876fromModule types (Can.Module _ _ exports _ unions aliases binops _) =
5977 Interface
60− { _types = privatize exports const types
61− , _unions = privatize exports toUnion unions
62− , _aliases = privatize exports const aliases
63− , _binops = privatize exports const (Map.map (toOp types) binops)
78+ { _types = privatize exports types
79+ , _unions = privatizeUnions exports unions
80+ , _aliases = privatizeAliases exports aliases
81+ , _binops = privatize exports (Map.map (toOp types) binops)
6482 }
6583
6684
67−privatize :: Can.Exports -> (a -> A.Located Can.Export -> a) -> Map.Map N.Name a -> Map.Map N.Name a
68−privatize exports func dict =
85+privatize :: Can.Exports -> Map.Map N.Name a -> Map.Map N.Name a
86+privatize exports dict =
6987 case exports of
7088 Can.ExportEverything _ ->
7189 dict
7290
7391 Can.Export explicitExports ->
74− Map.intersectionWith func dict explicitExports
92+ Map.intersection dict explicitExports
7593
7694
77−toUnion :: Can.Union -> A.Located Can.Export -> Can.Union
78−toUnion union@(Can.Union vars _ _ opts) (A.At _ export) =
79− case export of
80− Can.ExportUnionOpen ->
81− union
95+toOp :: Map.Map N.Name Can.Annotation -> Can.Binop -> Binop
96+toOp types (Can.Binop_ associativity precedence name) =
97+ Binop name (types ! name) associativity precedence
8298
83− Can.ExportUnionClosed ->
84− Can.Union vars [] 0 opts
8599
86− _ ->
87− error "Compiler bug. Should not run into non-union exports here."
100+privatizeUnions :: Can.Exports -> Map.Map N.Name Can.Union -> Map.Map N.Name Union
101+privatizeUnions exports unions =
102+ case exports of
103+ Can.ExportEverything _ ->
104+ Map.map OpenUnion unions
88105
106+ Can.Export explicitExports ->
107+ Map.merge onLeft onRight onBoth explicitExports unions
108+ where
109+ onLeft = Map.dropMissing
110+ onRight = Map.mapMissing (\_ u -> PrivateUnion u)
111+ onBoth = Map.zipWithMatched $ \_ e u ->
112+ case A.toValue e of
113+ Can.ExportUnionOpen -> OpenUnion u
114+ Can.ExportUnionClosed -> ClosedUnion u
115+ _ -> error "impossible exports discovered in privatizeUnions"
116+
117+
118+privatizeAliases :: Can.Exports -> Map.Map N.Name Can.Alias -> Map.Map N.Name Alias
119+privatizeAliases exports aliases =
120+ case exports of
121+ Can.ExportEverything _ ->
122+ Map.map PublicAlias aliases
89123
90−toOp :: Map.Map N.Name Can.Annotation -> Can.Binop -> Binop
91−toOp types (Can.Binop_ associativity precedence name) =
92− Binop name (types ! name) associativity precedence
124+ Can.Export explicitExports ->
125+ Map.merge onLeft onRight onBoth explicitExports aliases
126+ where
127+ onLeft = Map.dropMissing
128+ onRight = Map.mapMissing (\_ a -> PrivateAlias a)
129+ onBoth = Map.zipWithMatched (\_ _ a -> PublicAlias a)
130+
131+
132+
133+-- PUBLICIZE
134+
135+
136+toPublicUnion :: Union -> Maybe Can.Union
137+toPublicUnion iUnion =
138+ case iUnion of
139+ OpenUnion union ->
140+ Just union
141+
142+ ClosedUnion (Can.Union vars _ _ opts) ->
143+ Just (Can.Union vars [] 0 opts)
144+
145+ PrivateUnion _ ->
146+ Nothing
147+
148+
149+toPublicAlias :: Alias -> Maybe Can.Alias
150+toPublicAlias iAlias =
151+ case iAlias of
152+ PublicAlias alias ->
153+ Just alias
154+
155+ PrivateAlias _ ->
156+ Nothing
157+
158+
159+
160+-- INTERNALS
161+
162+
163+toUnionInternals :: Union -> Can.Union
164+toUnionInternals iUnion =
165+ case iUnion of
166+ OpenUnion union -> union
167+ ClosedUnion union -> union
168+ PrivateUnion union -> union
169+
170+
171+toAliasInternals :: Alias -> Can.Alias
172+toAliasInternals iAlias =
173+ case iAlias of
174+ PublicAlias alias -> alias
175+ PrivateAlias alias -> alias
93176
94177
95178
@@ -104,6 +187,36 @@ instance Binary Interface where
104187 put a >> put b >> put c >> put d
105188
106189
190+instance Binary Union where
191+ put union =
192+ case union of
193+ OpenUnion u -> putWord8 0 >> put u
194+ ClosedUnion u -> putWord8 1 >> put u
195+ PrivateUnion u -> putWord8 2 >> put u
196+
197+ get =
198+ do n <- getWord8
199+ case n of
200+ 0 -> OpenUnion <$> get
201+ 1 -> ClosedUnion <$> get
202+ 2 -> PrivateUnion <$> get
203+ _ -> error "binary encoding of Union was corrupted"
204+
205+
206+instance Binary Alias where
207+ put union =
208+ case union of
209+ PublicAlias a -> putWord8 0 >> put a
210+ PrivateAlias a -> putWord8 1 >> put a
211+
212+ get =
213+ do n <- getWord8
214+ case n of
215+ 0 -> PublicAlias <$> get
216+ 1 -> PrivateAlias <$> get
217+ _ -> error "binary encoding of Alias was corrupted"
218+
219+
107220instance Binary Binop where
108221 get =
109222 liftM4 Binop get get get get