on master help sign in
Change the canonicalization Env for new AST var info

Now that the AST tracks whether something is qualified or not, it makes sense to change the structure of the canonicalization Env a bit as well. The new one is focused on finding the good thing withers little extra mess in the way as possible. If there is an error, I will need to allocate a bunch of stuff so I can do a more elaborate analysis. It seems like a fine trade to pay more allocations for quality errors. The ms spent generating will be worth the minutes saved debugging. I think it made the code for setting up the environment (in Foreign and Local) a decent bit simpler. The code cut from Canonicalize.Module is a good guide to that. I had this two phase thing going for local declarations and it is not needed it turns out.

commita57d82912601e453bab49140e109a0af7edf0a7d authorEvan Czaplicki <evancz@users.noreply.github.com> dateWed 10 Jan 2018, 02:03 (9 years ago) parent450b5e7
4 files changed+488−579
src/Canonicalize/Environment.hs+107−52 src/Canonicalize/Environment/Foreign.hs+164−237 src/Canonicalize/Environment/Local.hs+210−238 src/Canonicalize/Module.hs+7−52
src/Canonicalize/Environment.hs+107−52
@@ -2,15 +2,17 @@
22{-# LANGUAGE OverloadedStrings #-}
33module Canonicalize.Environment
44 ( Env(..)
5− , VarHomes(..)
6− , UnqualifiedVarHome(..)
7− , ForeignVarHome(..)
5+ , Exposed
6+ , Qualified
7+ , Var(..)
8+ , ForeignVar(..)
89 , Type(..)
9− , Pattern(..)
10− , Homes(..)
10+ , Ctor(..)
1111 , addLocals
1212 , findType
13− , findPattern
13+ , findTypeQual
14+ , findCtor
15+ , findCtorQual
1416 , findBinop
1517 , Binop(..)
1618 )
@@ -23,7 +25,6 @@ import qualified Data.Map.Merge.Strict as Map
2325import qualified AST.Utils.Binop as Binop
2426import qualified AST.Canonical as Can
2527import qualified AST.Module.Name as ModuleName
26−import qualified Data.Bag as Bag
2728import qualified Data.Index as Index
2829import qualified Data.OneOrMore as OneOrMore
2930import qualified Elm.Name as N
@@ -47,39 +48,36 @@ type Result i w a =
4748data Env =
4849 Env
4950 { _home :: ModuleName.Canonical
50− , _vars :: Map.Map N.Name VarHomes
51− , _types :: Map.Map N.Name (Homes Type)
52− , _patterns :: Map.Map N.Name (Homes Pattern)
53− , _binops :: Map.Map N.Name (OneOrMore.OneOrMore Binop)
51+ , _vars :: Map.Map N.Name Var
52+ , _types :: Exposed Type
53+ , _ctors :: Exposed Ctor
54+ , _binops :: Exposed Binop
55+ , _q_vars :: Qualified ForeignVar
56+ , _q_types :: Qualified Type
57+ , _q_ctors :: Qualified Ctor
5458 }
5559
5660
57−data Homes a =
58− Homes
59− { _unqualified :: Bag.Bag a
60− , _qualified :: Map.Map N.Name (OneOrMore.OneOrMore a)
61− }
61+type Exposed a =
62+ Map.Map N.Name (OneOrMore.OneOrMore a)
6263
6364
65+type Qualified a =
66+ Map.Map N.Name (Map.Map N.Name (OneOrMore.OneOrMore a))
6467
65−-- VARIABLES
6668
6769
68−data VarHomes =
69− VarHomes
70− { _var_unqualified :: UnqualifiedVarHome
71− , _var_qualified :: Map.Map N.Name (OneOrMore.OneOrMore ForeignVarHome)
72− }
70+-- VARIABLES
7371
7472
75−data UnqualifiedVarHome
73+data Var
7674 = Local R.Region
7775 | TopLevel R.Region
78− | Foreign (Bag.Bag ForeignVarHome)
76+ | Foreign (OneOrMore.OneOrMore ForeignVar)
7977
8078
81−data ForeignVarHome =
82− ForeignVarHome ModuleName.Canonical Can.Annotation
79+data ForeignVar =
80+ ForeignVar ModuleName.Canonical Can.Annotation
8381
8482
8583
@@ -92,18 +90,18 @@ data Type
9290
9391
9492
95−-- PATTERNs
93+-- CTORS
9694
9795
98−data Pattern =
99− Pattern
100− { _p_home :: ModuleName.Canonical
101− , _p_type :: N.Name
102− , _p_vars :: [N.Name]
103− , _p_alts :: Can.CtorAlts
104− , _p_index :: Index.ZeroBased
105− , _p_args :: [Can.Type]
106− }
96+data Ctor
97+ = RecordCtor ModuleName.Canonical [N.Name] Can.Type
98+ | Ctor
99+ { _c_home :: ModuleName.Canonical
100+ , _c_type :: N.Name
101+ , _c_union :: Can.Union
102+ , _c_index :: Index.ZeroBased
103+ , _c_args :: [Can.Type]
104+ }
107105
108106
109107
@@ -126,7 +124,7 @@ data Binop =
126124
127125
128126addLocals :: Map.Map N.Name R.Region -> Env -> Result i w Env
129−addLocals names (Env home vars types patterns binops) =
127+addLocals names (Env home vars ts cs bs qvs qts qcs) =
130128 do newVars <-
131129 Map.mergeA
132130 (Map.mapMissing addLocalLeft)
@@ -134,19 +132,20 @@ addLocals names (Env home vars types patterns binops) =
134132 (Map.zipWithAMatched addLocalBoth)
135133 names
136134 vars
137− Result.ok $ Env home newVars types patterns binops
135+
136+ Result.ok (Env home newVars ts cs bs qvs qts qcs)
138137
139138
140−addLocalLeft :: N.Name -> R.Region -> VarHomes
139+addLocalLeft :: N.Name -> R.Region -> Var
141140addLocalLeft _ region =
142− VarHomes (Local region) Map.empty
141+ Local region
143142
144143
145−addLocalBoth :: N.Name -> R.Region -> VarHomes -> Result i w VarHomes
146−addLocalBoth name region (VarHomes unqualified qualified) =
147− case unqualified of
144+addLocalBoth :: N.Name -> R.Region -> Var -> Result i w Var
145+addLocalBoth name region var =
146+ case var of
148147 Foreign _ ->
149− Result.ok (VarHomes (Local region) qualified)
148+ Result.ok (Local region)
150149
151150 Local parentRegion ->
152151 Result.throw (Error.Shadowing name parentRegion region)
@@ -156,17 +155,73 @@ addLocalBoth name region (VarHomes unqualified qualified) =
156155
157156
158157
159−-- FIND TYPE and PATTERN
158+-- FIND TYPE
160159
161160
162−findType :: R.Region -> Env -> Maybe N.Name -> N.Name -> Result i w Type
163−findType region (Env _ _ types _ _) maybePrefix name =
164− error "TODO findType" region types maybePrefix name
161+findType :: R.Region -> Env -> N.Name -> Result i w Type
162+findType region (Env _ _ types _ _ _ _ _) name =
163+ case Map.lookup name types of
164+ Just (OneOrMore.One tipe) ->
165+ Result.ok tipe
166+
167+ Just _ ->
168+ error "TODO findType ambiguous unqualified"
165169
170+ Nothing ->
171+ error "TODO findType not found" region
172+
173+
174+findTypeQual :: R.Region -> Env -> N.Name -> N.Name -> Result i w Type
175+findTypeQual region (Env _ _ _ _ _ _ types _) prefix name =
176+ case Map.lookup prefix types of
177+ Just qualified ->
178+ case Map.lookup name qualified of
179+ Just (OneOrMore.One tipe) ->
180+ Result.ok tipe
181+
182+ Just more ->
183+ error "TODO findTypeQual ambiguous qualified" more
184+
185+ Nothing ->
186+ error "TODO findTypeQual no qualified"
187+
188+ Nothing ->
189+ error "TODO findTypeQual not found" region
166190
167−findPattern :: R.Region -> Env -> Maybe N.Name -> N.Name -> Result i w Pattern
168−findPattern region (Env _ _ _ patterns _) maybePrefix name =
169− error "TODO findPattern" region patterns maybePrefix name
191+
192+
193+-- FIND CTOR
194+
195+
196+findCtor :: R.Region -> Env -> N.Name -> Result i w Ctor
197+findCtor region (Env _ _ _ ctors _ _ _ _) name =
198+ case Map.lookup name ctors of
199+ Just (OneOrMore.One ctor) ->
200+ Result.ok ctor
201+
202+ Just _ ->
203+ error "TODO findCtor ambiguous unqualified"
204+
205+ Nothing ->
206+ error "TODO findCtor not found" region
207+
208+
209+findCtorQual :: R.Region -> Env -> N.Name -> N.Name -> Result i w Ctor
210+findCtorQual region (Env _ _ _ _ _ _ _ ctors) prefix name =
211+ case Map.lookup prefix ctors of
212+ Just qualified ->
213+ case Map.lookup name qualified of
214+ Just (OneOrMore.One pattern) ->
215+ Result.ok pattern
216+
217+ Just _ ->
218+ error "TODO findCtorQual ambiguous qualified"
219+
220+ Nothing ->
221+ error "TODO findCtorQual no qualified"
222+
223+ Nothing ->
224+ error "TODO findCtorQual not found" region
170225
171226
172227
@@ -174,7 +229,7 @@ findPattern region (Env _ _ _ patterns _) maybePrefix name =
174229
175230
176231findBinop :: R.Region -> Env -> N.Name -> Result i w Binop
177−findBinop region (Env _ _ _ _ binops) name =
232+findBinop region (Env _ _ _ _ binops _ _ _) name =
178233 case Map.lookup name binops of
179234 Just (OneOrMore.One binop) ->
180235 Result.ok binop
src/Canonicalize/Environment/Foreign.hs+164−237
@@ -6,15 +6,14 @@ module Canonicalize.Environment.Foreign
66 where
77
88
9+import Control.Monad (foldM)
910import qualified Data.Map.Strict as Map
10−import qualified Data.Set as Set
1111
1212import qualified AST.Canonical as Can
1313import qualified AST.Source as Src
1414import qualified AST.Module.Name as ModuleName
1515import qualified Canonicalize.Environment as Env
16−import qualified Data.Bag as Bag
17−import qualified Data.Index as Index
16+import qualified Data.List as List
1817import qualified Data.OneOrMore as OneOrMore
1918import qualified Elm.Interface as I
2019import qualified Elm.Name as N
@@ -34,214 +33,193 @@ type Result i w a =
3433
3534
3635
37−-- ENVIRONMENT
38−
39−
40−data Env =
41− Env
42− { _vars :: Map.Map N.Name (Env.Homes Env.ForeignVarHome)
43− , _types :: Map.Map N.Name (Env.Homes Env.Type)
44− , _patterns :: Map.Map N.Name (Env.Homes Env.Pattern)
45− , _binops :: Map.Map N.Name (OneOrMore.OneOrMore Env.Binop)
46− }
47−
48−
36+-- CREATE ENVIRONMENT
4937
50−-- MERGE
5138
39+type ImportDict =
40+ Map.Map N.Name ModuleName.Canonical
5241
53−merge :: Env -> Env -> Env
54−merge (Env v1 t1 p1 b1) (Env v2 t2 p2 b2) =
55− Env
56− (Map.unionWith mergeHomes v1 v2)
57− (Map.unionWith mergeHomes t1 t2)
58− (Map.unionWith mergeHomes p1 p2)
59− (Map.unionWith OneOrMore.more b1 b2)
6042
43+createInitialEnv :: ModuleName.Canonical -> ImportDict -> I.Interfaces -> [Src.Import] -> Result i w Env.Env
44+createInitialEnv home importDict interfaces sourceImports =
45+ do imports <- traverse (verifyImport importDict interfaces) sourceImports
46+ (State vs ts cs bs qvs qts qcs) <- foldM addImport emptyState imports
47+ Result.ok (Env.Env home (Map.map Env.Foreign vs) ts cs bs qvs qts qcs)
6148
62−mergeHomes :: Env.Homes a -> Env.Homes a -> Env.Homes a
63−mergeHomes (Env.Homes unqualified1 qualified1) (Env.Homes unqualified2 qualified2) =
64− Env.Homes
65− (Bag.append unqualified1 unqualified2)
66− (Map.unionWith OneOrMore.more qualified1 qualified2)
6749
6850
69−emptyEnv :: Env
70−emptyEnv =
71− Env Map.empty Map.empty Map.empty Map.empty
51+-- STATE
7252
7353
54+data State =
55+ State
56+ { _vars :: Env.Exposed Env.ForeignVar
57+ , _types :: Env.Exposed Env.Type
58+ , _ctors :: Env.Exposed Env.Ctor
59+ , _binops :: Env.Exposed Env.Binop
60+ , _q_vars :: Env.Qualified Env.ForeignVar
61+ , _q_types :: Env.Qualified Env.Type
62+ , _q_ctors :: Env.Qualified Env.Ctor
63+ }
7464
75−-- CREATE ENVIRONMENT
7665
66+emptyState :: State
67+emptyState =
68+ State Map.empty Map.empty Map.empty Map.empty Map.empty Map.empty Map.empty
7769
78−type ImportDict =
79− Map.Map N.Name ModuleName.Canonical
8070
8171
82−createInitialEnv :: ModuleName.Canonical -> ImportDict -> I.Interfaces -> [Src.Import] -> Result i w Env.Env
83−createInitialEnv home importDict interfaces sourceImports =
84− do imports <- traverse (verifyImport importDict interfaces) sourceImports
85− let (Env vars types patterns binops) = foldr merge emptyEnv (map importToEnv imports)
86− let toVarHome (Env.Homes u q) = Env.VarHomes (Env.Foreign u) q
87− return $ Env.Env home (Map.map toVarHome vars) types patterns binops
72+-- ADD IMPORTS
8873
8974
90−importToEnv :: Import -> Env
91−importToEnv (Import home (I.Interface types unions aliases binops) prefix exposing) =
75+addImport :: State -> Import -> Result i w State
76+addImport (State vs ts cs bs qvs qts qcs) (Import home (I.Interface defs unions aliases binops) prefix exposing) =
9277 let
93− patterns =
94− Map.fromList (concatMap (toPatterns home) (Map.toList unions))
78+ !rawTypeInfo =
79+ Map.union
80+ (Map.mapWithKey (unionToType home) unions)
81+ (Map.mapWithKey (aliasToType home) aliases)
82+
83+ !vars = Map.map (OneOrMore.one . Env.ForeignVar home) defs
84+ !types = Map.map (OneOrMore.one . fst) rawTypeInfo
85+ !ctors = Map.foldr (addExposed . snd) Map.empty rawTypeInfo
86+
87+ !qvs2 = addQualified prefix vars qvs
88+ !qts2 = addQualified prefix types qts
89+ !qcs2 = addQualified prefix ctors qcs
9590 in
9691 case exposing of
97− Open ->
98− Env
99− (Map.map (toOpenHomes home prefix toVarInfo) types)
100− (Map.unionWith mergeHomes
101− (Map.map (toOpenHomes home prefix toUnionInfo) unions)
102− (Map.map (toOpenHomes home prefix toAliasInfo) aliases)
103− )
104− (Map.map (toOpenHomes home prefix toPatternInfo) patterns)
105− (Map.mapWithKey (toBinopHomes home) binops)
106−
107− Explicit explicits ->
108− Env
109− (Map.mapWithKey (toExplicitHomes home prefix explicits toVarInfo toVarBag) types)
110− (Map.unionWith mergeHomes
111− (Map.mapWithKey (toExplicitHomes home prefix explicits toUnionInfo toUnionBag) unions)
112− (Map.mapWithKey (toExplicitHomes home prefix explicits toAliasInfo toAliasBag) aliases)
113− )
114− (Map.mapWithKey (toExplicitHomes home prefix explicits toPatternInfo toPatternBag) patterns)
115− (Map.mapWithKey (toBinopHomes home) binops)
116−
117−
118−toOpenHomes
119− :: ModuleName.Canonical
120− -> N.Name
121− -> (ModuleName.Canonical -> value -> info)
122− -> value
123− -> Env.Homes info
124−toOpenHomes home prefix toInfo value =
125− let info = toInfo home value in
126− Env.Homes
127− (Bag.one info)
128− (Map.singleton prefix (OneOrMore.one info))
129−
130−
131−toExplicitHomes
132− :: ModuleName.Canonical
133− -> N.Name
134− -> Map.Map N.Name Exposed
135− -> (ModuleName.Canonical -> value -> info)
136− -> (info -> Maybe Exposed -> Bag.Bag info)
137− -> N.Name
138− -> value
139− -> Env.Homes info
140−toExplicitHomes home prefix explicits toInfo toBag name value =
141− let info = toInfo home value in
142− Env.Homes
143− (toBag info (Map.lookup name explicits))
144− (Map.singleton prefix (OneOrMore.one info))
145−
146−
147−toBinopHomes :: ModuleName.Canonical -> N.Name -> I.Binop -> OneOrMore.OneOrMore Env.Binop
148−toBinopHomes home op (I.Binop name annotation associativity precedence) =
149− OneOrMore.one (Env.Binop op home name annotation associativity precedence)
150−
151−
152−
153−-- TO INFO
92+ Src.Open ->
93+ let
94+ !vs2 = addExposed vs vars
95+ !ts2 = addExposed ts types
96+ !cs2 = addExposed cs ctors
97+ !bs2 = addExposed bs (Map.mapWithKey (binopToBinop home) binops)
98+ in
99+ Result.ok (State vs2 ts2 cs2 bs2 qvs2 qts2 qcs2)
154100
101+ Src.Explicit exposedList ->
102+ foldM
103+ (addExposedValue home vars rawTypeInfo binops)
104+ (State vs ts cs bs qvs2 qts2 qcs2)
105+ exposedList
155106
156−{-# INLINE toVarInfo #-}
157−toVarInfo :: ModuleName.Canonical -> Can.Annotation -> Env.ForeignVarHome
158−toVarInfo =
159− Env.ForeignVarHome
160107
108+addExposed :: Env.Exposed a -> Env.Exposed a -> Env.Exposed a
109+addExposed =
110+ Map.unionWith OneOrMore.more
161111
162−toUnionInfo :: ModuleName.Canonical -> Can.Union -> Env.Type
163−toUnionInfo home (Can.Union args _) =
164− Env.Union (length args) home
165112
113+addQualified :: N.Name -> Env.Exposed a -> Env.Qualified a -> Env.Qualified a
114+addQualified prefix exposed qualified =
115+ Map.insertWith addExposed prefix exposed qualified
166116
167−toAliasInfo :: ModuleName.Canonical -> Can.Alias -> Env.Type
168−toAliasInfo home (Can.Alias args tipe _) =
169− Env.Alias (length args) home args tipe
170117
171118
172−toPatternInfo :: ModuleName.Canonical -> Env.Pattern -> Env.Pattern
173−toPatternInfo _ pattern =
174− pattern
119+-- CANONICAL DATA TO ENVIRONMENT DATA
175120
176121
177−toPatterns :: ModuleName.Canonical -> (N.Name, Can.Union) -> [(N.Name, Env.Pattern)]
178−toPatterns home (tipe, Can.Union vars ctors) =
122+unionToType :: ModuleName.Canonical -> N.Name -> Can.Union -> (Env.Type, Env.Exposed Env.Ctor)
123+unionToType home name union@(Can.Union vars ctors _ _) =
179124 let
180− alts =
181− Can.ctorsToAlts ctors
182−
183− fromCtor index (name, args) =
184− (name, Env.Pattern home tipe vars alts index args)
125+ addCtor dict (Can.Ctor ctor index _ args) =
126+ Map.insert ctor (OneOrMore.one (Env.Ctor home name union index args)) dict
185127 in
186− Index.indexedMap fromCtor ctors
187−
188−
189−
190−-- TO BAG
128+ ( Env.Union (length vars) home
129+ , List.foldl' addCtor Map.empty ctors
130+ )
191131
192132
193−toVarBag :: a -> Maybe Exposed -> Bag.Bag a
194−toVarBag info maybeExposed =
195− case maybeExposed of
196− Nothing ->
197− Bag.empty
133+aliasToType :: ModuleName.Canonical -> N.Name -> Can.Alias -> (Env.Type, Env.Exposed Env.Ctor)
134+aliasToType home name (Can.Alias vars tipe maybeRecordArgs) =
135+ (
136+ Env.Alias (length vars) home vars tipe
137+ ,
138+ case maybeRecordArgs of
139+ Nothing ->
140+ Map.empty
198141
199− Just exposed ->
200− case exposed of
201− Value ->
202− Bag.one info
142+ Just _ ->
143+ Map.singleton name (OneOrMore.one (Env.RecordCtor home vars tipe))
144+ )
203145
204− Type ->
205− Bag.empty
206146
207− Ctor Src.Private ->
208− Bag.empty
147+binopToBinop :: ModuleName.Canonical -> N.Name -> I.Binop -> OneOrMore.OneOrMore Env.Binop
148+binopToBinop home op (I.Binop name annotation associativity precedence) =
149+ OneOrMore.one (Env.Binop op home name annotation associativity precedence)
209150
210− Ctor Src.Public ->
211− Bag.one info
212151
213− Alias ->
214− Bag.one info
215152
153+-- ADD EXPOSED VALUE
216154
217−toUnionBag :: a -> Maybe Exposed -> Bag.Bag a
218−toUnionBag info maybeExposed =
219− case maybeExposed of
220− Just Type ->
221− Bag.one info
222155
223− _ ->
224− Bag.empty
156+addExposedValue
157+ :: ModuleName.Canonical
158+ -> Env.Exposed Env.ForeignVar
159+ -> Map.Map N.Name (Env.Type, Env.Exposed Env.Ctor)
160+ -> Map.Map N.Name I.Binop
161+ -> State
162+ -> A.Located Src.Exposed
163+ -> Result i w State
164+addExposedValue home vars types binops (State vs ts cs bs qvs qts qcs) (A.At region exposed) =
165+ case exposed of
166+ Src.Lower name ->
167+ case Map.lookup name vars of
168+ Just info ->
169+ Result.ok (State (Map.insert name info vs) ts cs bs qvs qts qcs)
225170
171+ Nothing ->
172+ throwExposingNotFound region name
226173
227−toAliasBag :: a -> Maybe Exposed -> Bag.Bag a
228−toAliasBag info maybeExposed =
229− case maybeExposed of
230− Just Alias ->
231− Bag.one info
174+ Src.Upper name privacy ->
175+ case privacy of
176+ Src.Private ->
177+ case Map.lookup name types of
178+ Just (tipe, ctors) ->
179+ case tipe of
180+ Env.Union _ _ ->
181+ let
182+ !ts2 = Map.insert name (OneOrMore.one tipe) ts
183+ in
184+ Result.ok (State vs ts2 cs bs qvs qts qcs)
185+
186+ Env.Alias _ _ _ _ ->
187+ let
188+ !ts2 = Map.insert name (OneOrMore.one tipe) ts
189+ !cs2 = addExposed cs ctors
190+ in
191+ Result.ok (State vs ts2 cs2 bs qvs qts qcs)
232192
233− _ ->
234− Bag.empty
193+ Nothing ->
194+ throwExposingNotFound region name
195+
196+ Src.Public ->
197+ case Map.lookup name types of
198+ Just (tipe, ctors) ->
199+ case tipe of
200+ Env.Union _ _ ->
201+ let
202+ !ts2 = Map.insert name (OneOrMore.one tipe) ts
203+ !cs2 = addExposed cs ctors
204+ in
205+ Result.ok (State vs ts2 cs2 bs qvs qts qcs)
206+
207+ Env.Alias _ _ _ _ ->
208+ Result.throw (Error.ImportOpenAlias region name)
235209
210+ Nothing ->
211+ throwExposingNotFound region name
236212
237−toPatternBag :: a -> Maybe Exposed -> Bag.Bag a
238−toPatternBag info maybeExposed =
239− case maybeExposed of
240− Just (Ctor Src.Public) ->
241− Bag.one info
213+ Src.Operator op ->
214+ case Map.lookup op binops of
215+ Just binop ->
216+ let
217+ !bs2 = Map.insert op (binopToBinop home op binop) bs
218+ in
219+ Result.ok (State vs ts cs bs2 qvs qts qcs)
242220
243− _ ->
244− Bag.empty
221+ Nothing ->
222+ throwExposingNotFound region op
245223
246224
247225
@@ -253,42 +231,23 @@ data Import =
253231 { _name :: ModuleName.Canonical
254232 , _interface :: I.Interface
255233 , _prefix :: N.Name
256− , _exposing :: Exposing
234+ , _exposing :: Src.Exposing
257235 }
258236
259237
260−data Exposing
261− = Open
262− | Explicit (Map.Map N.Name Exposed)
263−
264−
265−data Exposed
266− = Value
267− | Type
268− | Ctor Src.Privacy
269− | Alias
270−
271−
272238verifyImport :: ImportDict -> I.Interfaces -> Src.Import -> Result i w Import
273239verifyImport importDict interfaces (Src.Import (A.At region name) alias exposing) =
274240 case Map.lookup name importDict of
275− Nothing ->
276− throwImportNotFound region name (Map.elems importDict)
277−
278241 Just canonicalName ->
279242 case Map.lookup canonicalName interfaces of
243+ Just interface ->
244+ Result.ok (Import canonicalName interface (maybe name id alias) exposing)
245+
280246 Nothing ->
281247 throwImportNotFound region name (Map.keys interfaces)
282248
283− Just interface ->
284− Import canonicalName interface (maybe name id alias) <$>
285− case exposing of
286− Src.Open ->
287− Result.ok Open
288−
289− Src.Explicit exposedList ->
290− do pairLists <- traverse (verifyExposed name interface) exposedList
291− Result.ok (Explicit (Map.fromList (concat pairLists)))
249+ Nothing ->
250+ throwImportNotFound region name (Map.elems importDict)
292251
293252
294253throwImportNotFound :: R.Region -> N.Name -> [ModuleName.Canonical] -> Result i w a
@@ -298,58 +257,25 @@ throwImportNotFound region name knownModules =
298257 map ModuleName._module knownModules
299258
300259
301−verifyExposed :: N.Name -> I.Interface -> A.Located Src.Exposed -> Result i w [(N.Name, Exposed)]
302−verifyExposed moduleName interface@(I.Interface _ unions aliases _) (A.At region exposed) =
303− case exposed of
304− Src.Operator name ->
305− verifyValue moduleName region name interface
306−
307− Src.Lower name ->
308− verifyValue moduleName region name interface
260+throwExposingNotFound :: R.Region -> N.Name -> Result i w a
261+throwExposingNotFound region name =
262+ Result.throw (error "TODO throwExposingNotFound" region name)
309263
310− Src.Upper name privacy ->
311− case Map.lookup name unions of
312− Just (Can.Union _ ctors) ->
313− let repair (ctor, _) = (ctor, Ctor privacy) in
314− Result.ok $ (name, Type) : map repair ctors
315−
316− Nothing ->
317− case Map.lookup name aliases of
318− Just _ ->
319− verifyAlias region name privacy
320−
321− Nothing ->
322− throwExposingNotFound moduleName region name interface
323−
324−
325−verifyValue :: N.Name -> R.Region -> N.Name -> I.Interface -> Result i w [(N.Name, Exposed)]
326−verifyValue moduleName region name interface@(I.Interface types _ _ _) =
327− case Map.lookup name types of
328− Nothing ->
329− throwExposingNotFound moduleName region name interface
330−
331− Just _ ->
332− Result.ok [(name, Value)]
333−
334−
335−verifyAlias :: R.Region -> N.Name -> Src.Privacy -> Result i w [(N.Name, Exposed)]
336−verifyAlias region name privacy =
337− case privacy of
338− Src.Public ->
339− Result.throw (error "TODO cannot have (..) on type alias" region)
340−
341− Src.Private ->
342− Result.ok [(name, Alias)]
343−
344−
345−throwExposingNotFound :: N.Name -> R.Region -> N.Name -> I.Interface -> Result i w a
346−throwExposingNotFound moduleName region name (I.Interface types unions aliases _) =
264+{-
347265 let
348− toCtorPairs (tipe, Can.Union _ ctors) =
349− map (\(ctor, _) -> (ctor, tipe)) ctors
350−
351266 ctorDict =
352267 Map.fromList (concatMap toCtorPairs (Map.toList unions))
268+
269+ toCtorPairs (tipe, union) =
270+ case union of
271+ Can.Union _ _ ctors ->
272+ map (\(Can.Ctor ctor _ _) -> (ctor, tipe)) ctors
273+
274+ Can.Enum _ _ names ->
275+ map (\ctor -> (ctor, tipe)) names
276+
277+ Can.Box _ ctor _ ->
278+ [(ctor, tipe)]
353279 in
354280 case Map.lookup name ctorDict of
355281 Just tipe ->
@@ -359,3 +285,4 @@ throwExposingNotFound moduleName region name (I.Interface types unions aliases _
359285 Result.throw $ Error.ImportExposingNotFound region moduleName name $
360286 Help.nearbyNames N.toString name $ Set.toList $
361287 Set.unions [ Map.keysSet types, Map.keysSet unions, Map.keysSet aliases ]
288+-}
src/Canonicalize/Environment/Local.hs+210−238
@@ -1,331 +1,205 @@
11{-# OPTIONS_GHC -Wall #-}
22{-# LANGUAGE OverloadedStrings #-}
33module Canonicalize.Environment.Local
4− ( addVarsAndTypes
5− , addPatterns
4+ ( add
65 )
76 where
87
98
10−import Control.Applicative (liftA2)
119import Control.Monad (foldM)
1210import qualified Data.Graph as Graph
11+import qualified Data.List as List
1312import qualified Data.Map.Strict as Map
14−import qualified Data.Map.Merge.Strict as Map
1513
1614import qualified AST.Canonical as Can
1715import qualified AST.Source as Src
1816import qualified AST.Valid as Valid
17+import qualified AST.Module.Name as ModuleName
1918import qualified Canonicalize.Environment as Env
2019import qualified Canonicalize.Environment.Dups as Dups
2120import qualified Canonicalize.Type as Type
22−import qualified Data.Bag as Bag
2321import qualified Data.Index as Index
22+import qualified Data.OneOrMore as OneOrMore
2423import qualified Elm.Name as N
2524import qualified Reporting.Annotation as A
2625import qualified Reporting.Error.Canonicalize as Error
2726import qualified Reporting.Region as R
2827import qualified Reporting.Result as Result
29−import qualified Reporting.Warning as Warning
3028
3129
3230
3331-- RESULT
3432
3533
36−type Result i a =
37− Result.Result i [Warning.Warning] Error.Error a
34+type Result i w a =
35+ Result.Result i w Error.Error a
3836
3937
38+type Unions = Map.Map N.Name Can.Union
39+type Aliases = Map.Map N.Name Can.Alias
4040
41−-- ADD VARS, TYPES, AND OPS
42−--
43−-- We can add names for local definitions, unions, aliases, and operators.
44−-- These are basically just names. We CANNOT add patterns though. Those must
45−-- be added by `addPatterns` after some canonicalization has occurred.
46−--
47−-- This code checks for (1) duplicate names and (2) cycles in type aliases.
4841
49−
50−addVarsAndTypes :: Valid.Module -> Env.Env -> Result i Env.Env
51−addVarsAndTypes module_ env =
52− addVars module_ =<< addTypes module_ env
53−
54−
55−merge
56− :: (N.Name -> a -> homes)
57− -> (N.Name -> a -> homes -> homes)
58− -> Map.Map N.Name a
59− -> Map.Map N.Name homes
60− -> Map.Map N.Name homes
61−merge addLeft addBoth locals foreigns =
62− let addRight _ homes = homes in
63− Map.merge
64− (Map.mapMissing addLeft)
65− (Map.mapMissing addRight)
66− (Map.zipWithMatched addBoth)
67− locals
68− foreigns
69−
70−
71−
72−-- ADD PATTERNS
73−--
74−-- Local patterns are added to the environment later such that we can have
75−-- canonical union types. This way we can avoid looking up the types during
76−-- type constraint generation.
77−--
78−-- This function does not return a Result because Dups.detect is already called
79−-- in collectUpperVars. This will detect all local pattern clashes. We skip it
80−-- here to avoid a second version of the same error.
81−
82−
83−addPatterns :: Map.Map N.Name Can.Union -> Env.Env -> Env.Env
84−addPatterns unions (Env.Env home vars types patterns binops) =
85− let
86− localPatterns =
87− Map.fromList $ concatMap toPatterns (Map.toList unions)
88−
89− toPatterns (tipe, Can.Union tvars ctors) =
90− Index.indexedMap (ctorToPattern tipe tvars (Can.ctorsToAlts ctors)) ctors
91−
92− ctorToPattern tipe tvars alts index (name, args) =
93− ( name, Env.Pattern home tipe tvars alts index args )
94− in
95− let
96− newPatterns =
97− merge addLeft addBoth localPatterns patterns
98−
99− addLeft _ localPattern =
100− Env.Homes (Bag.one localPattern) Map.empty
101−
102− addBoth _ localPattern (Env.Homes _ qualified) =
103− Env.Homes (Bag.one localPattern) qualified
104− in
105− Env.Env home vars types newPatterns binops
42+add :: Valid.Module -> Env.Env -> Result i w (Env.Env, Unions, Aliases)
43+add module_ env =
44+ addCtors module_ =<< addVars module_ =<< addTypes module_ env
10645
10746
10847
10948-- ADD VARS
11049
11150
112−addVars :: Valid.Module -> Env.Env -> Result i Env.Env
113−addVars module_ (Env.Env home vars types patterns binops) =
114− do upperDict <- collectUpperVars module_
115− lowerDict <- collectLowerVars module_
116− let varDict = Map.union upperDict lowerDict
117− let newVars = addVarsHelp varDict vars
118− return $ Env.Env home newVars types patterns binops
51+addVars :: Valid.Module -> Env.Env -> Result i w Env.Env
52+addVars module_ (Env.Env home vs ts cs bs qvs qts qcs) =
53+ do topLevelVars <- collectVars module_
54+ let vs2 = Map.union topLevelVars vs
55+ -- Use union to overwrite foreign stuff.
56+ Result.ok $ Env.Env home vs2 ts cs bs qvs qts qcs
11957
12058
121−addVarsHelp :: Map.Map N.Name R.Region -> Map.Map N.Name Env.VarHomes -> Map.Map N.Name Env.VarHomes
122−addVarsHelp localVars vars =
59+collectVars :: Valid.Module -> Result i w (Map.Map N.Name Env.Var)
60+collectVars (Valid.Module _ _ _ _ _ decls _ _ _ effects) =
12361 let
124− addLeft _ region =
125− Env.VarHomes (Env.TopLevel region) Map.empty
126−
127− addBoth _ region (Env.VarHomes _ qualified) =
128− Env.VarHomes (Env.TopLevel region) qualified
62+ addDecl dict (A.At _ (Valid.Decl (A.At region name) _ _ _)) =
63+ Dups.insert name region (Env.TopLevel region) dict
12964 in
130− merge addLeft addBoth localVars vars
131−
132−
133−collectLowerVars :: Valid.Module -> Result i (Map.Map N.Name R.Region)
134−collectLowerVars (Valid.Module _ _ _ _ _ decls _ _ _ effects) =
135− let
136− addDecl (A.At _ (Valid.Decl (A.At region name) _ _ _)) dict =
137− Dups.insert name region region dict
65+ Dups.detect Error.DuplicateDecl $
66+ List.foldl' addDecl (toEffectDups effects) decls
13867
139− addPort (Valid.Port (A.At region name) _) dict =
140− Dups.insert name region region dict
14168
142− effectDict =
143− case effects of
144− Valid.NoEffects ->
145− Dups.none
69+toEffectDups :: Valid.Effects -> Dups.Dict Env.Var
70+toEffectDups effects =
71+ case effects of
72+ Valid.NoEffects ->
73+ Dups.none
14674
147− Valid.Ports ports ->
148− foldr addPort Dups.none ports
75+ Valid.Ports ports ->
76+ let
77+ addPort dict (Valid.Port (A.At region name) _) =
78+ Dups.insert name region (Env.TopLevel region) dict
79+ in
80+ List.foldl' addPort Dups.none ports
14981
150− Valid.Manager _ manager ->
151− case manager of
152− Valid.Cmd (A.At region _) ->
153− Dups.one "command" region region
82+ Valid.Manager _ manager ->
83+ case manager of
84+ Valid.Cmd (A.At region _) ->
85+ Dups.one "command" region (Env.TopLevel region)
15486
155− Valid.Sub (A.At region _) ->
156− Dups.one "subscription" region region
87+ Valid.Sub (A.At region _) ->
88+ Dups.one "subscription" region (Env.TopLevel region)
15789
158− Valid.Fx (A.At regionCmd _) (A.At regionSub _) ->
159− Dups.union
160− (Dups.one "command" regionCmd regionCmd)
161− (Dups.one "subscription" regionSub regionSub)
162− in
163− Dups.detect Error.DuplicateDecl $ foldr addDecl effectDict decls
164−
165−
166−collectUpperVars :: Valid.Module -> Result i (Map.Map N.Name R.Region)
167−collectUpperVars (Valid.Module _ _ _ _ _ _ unions aliases _ _) =
168− let
169− addUnion (Valid.Union _ _ ctors) dict =
170− foldr addCtor dict ctors
171−
172− addCtor (A.At region name, _args) dict =
173− Dups.insert name region region dict
174−
175− addAlias (Valid.Alias (A.At region name) _ (A.At _ tipe)) dict =
176− case tipe of
177− Src.TRecord _ Nothing ->
178− Dups.insert name region region dict
179−
180− _ ->
181− dict
182− in
183− Dups.detect Error.DuplicateCtor $
184− foldr addAlias (foldr addUnion Dups.none unions) aliases
90+ Valid.Fx (A.At regionCmd _) (A.At regionSub _) ->
91+ Dups.union
92+ (Dups.one "command" regionCmd (Env.TopLevel regionCmd))
93+ (Dups.one "subscription" regionSub (Env.TopLevel regionSub))
18594
18695
18796
18897-- ADD TYPES
18998
19099
191−addTypes :: Valid.Module -> Env.Env -> Result i Env.Env
192−addTypes (Valid.Module _ _ _ _ _ _ unions aliases _ _) env =
100+addTypes :: Valid.Module -> Env.Env -> Result i w Env.Env
101+addTypes (Valid.Module _ _ _ _ _ _ unions aliases _ _) (Env.Env home vs ts cs bs qvs qts qcs) =
193102 let
194− aliasToDict alias@(Valid.Alias (A.At region name) _ tipe) =
195− do args <- checkAliasFreeVars alias
196− return $ Dups.one name region (Left (Alias region name args tipe))
197−
198− unionToDict union@(Valid.Union (A.At region name) _ _) =
199− do arity <- checkUnionFreeVars union
200− return $ Dups.one name region (Right arity)
201−
202− combineDicts dicts1 dicts2 =
203− Dups.union (Dups.unions dicts1) (Dups.unions dicts2)
103+ addAliasDups dups (Valid.Alias (A.At region name) _ _) = Dups.insert name region () dups
104+ addUnionDups dups (Valid.Union (A.At region name) _ _) = Dups.insert name region () dups
105+ typeNameDups =
106+ List.foldl' addUnionDups (List.foldl' addAliasDups Dups.none aliases) unions
204107 in
205− do dict <-
206− liftA2 combineDicts
207− (traverse aliasToDict aliases)
208− (traverse unionToDict unions)
209− types <- Dups.detect Error.DuplicateType dict
210− let (aliasDict, unionDict) = Map.mapEither id types
211− addTypeAliases aliasDict (addUnionTypes unionDict env)
212−
108+ do _ <- Dups.detect Error.DuplicateType typeNameDups
109+ ts1 <- foldM (addUnion home) ts unions
110+ addAliases aliases (Env.Env home vs ts1 cs bs qvs qts qcs)
213111
214−addUnionTypes :: Map.Map N.Name Int -> Env.Env -> Env.Env
215−addUnionTypes unions (Env.Env home vars types patterns binops) =
216− let
217− addLeft _ arity =
218− Env.Homes (Bag.one (Env.Union arity home)) Map.empty
219112
220− addBoth _ arity (Env.Homes _ qualified) =
221− Env.Homes (Bag.one (Env.Union arity home)) qualified
222−
223− newTypes =
224− merge addLeft addBoth unions types
225− in
226− Env.Env home vars newTypes patterns binops
113+addUnion :: ModuleName.Canonical -> Env.Exposed Env.Type -> Valid.Union -> Result i w (Env.Exposed Env.Type)
114+addUnion home types union@(Valid.Union (A.At _ name) _ _) =
115+ do arity <- checkUnionFreeVars union
116+ let one = OneOrMore.one (Env.Union arity home)
117+ Result.ok $ Map.insertWith OneOrMore.more name one types
227118
228119
229120
230121-- ADD TYPE ALIASES
231122
232123
233−data Alias =
234− Alias
235− { _region :: R.Region
236− , _name :: N.Name
237− , _args :: [N.Name]
238− , _type :: Src.Type
239− }
240−
241−
242−addTypeAliases :: Map.Map N.Name Alias -> Env.Env -> Result i Env.Env
243−addTypeAliases aliases env =
244− do let nodes = map toNode (Map.elems aliases)
245− let sccs = Graph.stronglyConnComp nodes
246− foldM addTypeAlias env sccs
124+addAliases :: [Valid.Alias] -> Env.Env -> Result i w Env.Env
125+addAliases aliases env =
126+ let
127+ nodes = map toNode aliases
128+ sccs = Graph.stronglyConnComp nodes
129+ in
130+ foldM addAlias env sccs
247131
248132
249−addTypeAlias :: Env.Env -> Graph.SCC Alias -> Result i Env.Env
250−addTypeAlias env@(Env.Env home vars types patterns binops) scc =
133+addAlias :: Env.Env -> Graph.SCC Valid.Alias -> Result i w Env.Env
134+addAlias env@(Env.Env home vs ts cs bs qvs qts qcs) scc =
251135 case scc of
252− Graph.AcyclicSCC (Alias _ name args tipe) ->
253− do ctype <- Type.canonicalize env tipe
254− let info = Env.Alias (length args) home args ctype
255− let newTypes = Map.alter (addAliasInfo info) name types
256− return $ Env.Env home vars newTypes patterns binops
136+ Graph.AcyclicSCC alias@(Valid.Alias (A.At _ name) _ tipe) ->
137+ do args <- checkAliasFreeVars alias
138+ ctype <- Type.canonicalize env tipe
139+ let one = OneOrMore.one (Env.Alias (length args) home args ctype)
140+ let ts1 = Map.insertWith OneOrMore.more name one ts
141+ Result.ok $ Env.Env home vs ts1 cs bs qvs qts qcs
257142
258143 Graph.CyclicSCC [] ->
259144 Result.ok env
260145
261− Graph.CyclicSCC (Alias region name1 args tipe : others) ->
262− let toName (Alias _ name _ _) = name in
263− Result.throw (Error.RecursiveAlias region name1 args tipe (map toName others))
264−
265−
266−addAliasInfo :: a -> Maybe (Env.Homes a) -> Maybe (Env.Homes a)
267−addAliasInfo info maybeHomes =
268− Just $
269− case maybeHomes of
270− Nothing ->
271− Env.Homes (Bag.one info) Map.empty
272−
273− Just (Env.Homes _ qualified) ->
274− Env.Homes (Bag.one info) qualified
146+ Graph.CyclicSCC (alias@(Valid.Alias (A.At region name1) _ tipe) : others) ->
147+ do args <- checkAliasFreeVars alias
148+ let toName (Valid.Alias (A.At _ name) _ _) = name
149+ Result.throw (Error.RecursiveAlias region name1 args tipe (map toName others))
275150
276151
277152
278153-- DETECT TYPE ALIAS CYCLES
279154
280155
281−toNode :: Alias -> ( Alias, N.Name, [N.Name] )
282−toNode alias@(Alias _ name _ tipe) =
283− ( alias, name, Bag.toList (getEdges tipe) )
156+toNode :: Valid.Alias -> (Valid.Alias, N.Name, [N.Name])
157+toNode alias@(Valid.Alias (A.At _ name) _ tipe) =
158+ ( alias, name, getEdges [] tipe )
284159
285160
286−getEdges :: Src.Type -> Bag.Bag N.Name
287−getEdges (A.At _ tipe) =
161+getEdges :: [N.Name] -> Src.Type -> [N.Name]
162+getEdges edges (A.At _ tipe) =
288163 case tipe of
289164 Src.TLambda arg result ->
290− Bag.append (getEdges arg) (getEdges result)
165+ getEdges (getEdges edges arg) result
291166
292167 Src.TVar _ ->
293− Bag.empty
168+ edges
169+
170+ Src.TType _ name args ->
171+ List.foldl' getEdges (name:edges) args
294172
295− Src.TType _ Nothing name args ->
296− foldr Bag.append (Bag.one name) (map getEdges args)
173+ Src.TTypeQual _ _ _ args ->
174+ List.foldl' getEdges edges args
297175
298− Src.TType _ (Just _) _ args ->
299− foldr Bag.append Bag.empty (map getEdges args)
176+ Src.TRecord fields Nothing ->
177+ List.foldl' (\es (_,t) -> getEdges es t) edges fields
300178
301− Src.TRecord fields ext ->
302− foldr Bag.append
303− (maybe Bag.empty getEdges ext)
304− (map (getEdges . snd) fields)
179+ Src.TRecord fields (Just ext) ->
180+ List.foldl' (\es (_,t) -> getEdges es t) (getEdges edges ext) fields
305181
306182 Src.TUnit ->
307− Bag.empty
183+ edges
308184
309185 Src.TTuple a b cs ->
310− foldr Bag.append
311− (getEdges a)
312− (getEdges b : map getEdges cs)
186+ List.foldl' getEdges (getEdges (getEdges edges a) b) cs
313187
314188
315189
316190-- CHECK FREE VARIABLES
317191
318192
319−checkUnionFreeVars :: Valid.Union -> Result i Int
193+checkUnionFreeVars :: Valid.Union -> Result i w Int
320194checkUnionFreeVars (Valid.Union (A.At unionRegion name) args ctors) =
321195 let
322− addUnion (A.At region arg) dict =
196+ addArg (A.At region arg) dict =
323197 Dups.insert arg region region dict
324198
325199 addCtorFreeVars (_, tipes) freeVars =
326− foldr addFreeVars freeVars tipes
200+ List.foldl' addFreeVars freeVars tipes
327201 in
328− do boundVars <- Dups.detect (Error.DuplicateUnionArg name) (foldr addUnion Dups.none args)
202+ do boundVars <- Dups.detect (Error.DuplicateUnionArg name) (foldr addArg Dups.none args)
329203 let freeVars = foldr addCtorFreeVars Map.empty ctors
330204 case Map.toList (Map.difference freeVars boundVars) of
331205 [] ->
@@ -337,15 +211,14 @@ checkUnionFreeVars (Valid.Union (A.At unionRegion name) args ctors) =
337211 Error.TypeVarsUnboundInUnion unionRegion name (map A.toValue args) (map toLoc unbound)
338212
339213
340−
341−checkAliasFreeVars :: Valid.Alias -> Result i [N.Name]
214+checkAliasFreeVars :: Valid.Alias -> Result i w [N.Name]
342215checkAliasFreeVars (Valid.Alias (A.At aliasRegion name) args tipe) =
343216 let
344− addAlias (A.At region arg) dict =
217+ addArg (A.At region arg) dict =
345218 Dups.insert arg region region dict
346219 in
347− do boundVars <- Dups.detect (Error.DuplicateAliasArg name) (foldr addAlias Dups.none args)
348− let freeVars = addFreeVars tipe Map.empty
220+ do boundVars <- Dups.detect (Error.DuplicateAliasArg name) (foldr addArg Dups.none args)
221+ let freeVars = addFreeVars Map.empty tipe
349222 let overlap = Map.size (Map.intersection boundVars freeVars)
350223 if Map.size boundVars == overlap && Map.size freeVars == overlap
351224 then Result.ok (map A.toValue args)
@@ -358,26 +231,125 @@ checkAliasFreeVars (Valid.Alias (A.At aliasRegion name) args tipe) =
358231 (map toLoc (Map.toList (Map.difference freeVars boundVars)))
359232
360233
361−addFreeVars :: Src.Type -> Map.Map N.Name R.Region -> Map.Map N.Name R.Region
362−addFreeVars (A.At region tipe) freeVars =
234+addFreeVars :: Map.Map N.Name R.Region -> Src.Type -> Map.Map N.Name R.Region
235+addFreeVars freeVars (A.At region tipe) =
363236 case tipe of
364237 Src.TLambda arg result ->
365− addFreeVars arg (addFreeVars result freeVars)
238+ addFreeVars (addFreeVars freeVars arg) result
366239
367240 Src.TVar name ->
368241 Map.insert name region freeVars
369242
370− Src.TType _ _ _ args ->
371− foldr addFreeVars freeVars args
243+ Src.TType _ _ args ->
244+ List.foldl' addFreeVars freeVars args
245+
246+ Src.TTypeQual _ _ _ args ->
247+ List.foldl' addFreeVars freeVars args
372248
373249 Src.TRecord fields Nothing ->
374− foldr addFreeVars freeVars (map snd fields)
250+ List.foldl' (\fvs (_,t) -> addFreeVars fvs t) freeVars fields
375251
376252 Src.TRecord fields (Just ext) ->
377− foldr addFreeVars (addFreeVars ext freeVars) (map snd fields)
253+ List.foldl' (\fvs (_,t) -> addFreeVars fvs t) (addFreeVars freeVars ext) fields
378254
379255 Src.TUnit ->
380256 freeVars
381257
382258 Src.TTuple a b cs ->
383− foldr addFreeVars freeVars (a:b:cs)
259+ List.foldl' addFreeVars (addFreeVars (addFreeVars freeVars a) b) cs
260+
261+
262+
263+-- ADD CTORS
264+
265+
266+addCtors :: Valid.Module -> Env.Env -> Result i w (Env.Env, Unions, Aliases)
267+addCtors (Valid.Module _ _ _ _ _ _ unions aliases _ _) env@(Env.Env home vs ts cs bs qvs qts qcs) =
268+ do unionInfo <- traverse (canonicalizeUnion env) unions
269+ aliasInfo <- traverse (canonicalizeAlias env) aliases
270+
271+ ctors <-
272+ Dups.detect Error.DuplicateCtor $
273+ Dups.union
274+ (Dups.unions (map snd unionInfo))
275+ (Dups.unions (map snd aliasInfo))
276+
277+ let cs2 = Map.unionWith OneOrMore.more cs ctors
278+
279+ Result.ok
280+ ( Env.Env home vs ts cs2 bs qvs qts qcs
281+ , Map.fromList (map fst unionInfo)
282+ , Map.fromList (map fst aliasInfo)
283+ )
284+
285+
286+type CtorDups = Dups.Dict (OneOrMore.OneOrMore Env.Ctor)
287+
288+
289+
290+-- CANONICALIZE ALIAS
291+
292+
293+canonicalizeAlias :: Env.Env -> Valid.Alias -> Result i w ( (N.Name, Can.Alias), CtorDups )
294+canonicalizeAlias env@(Env.Env home _ _ _ _ _ _ _) (Valid.Alias (A.At region name) args tipe) =
295+ case tipe of
296+ A.At _ (Src.TRecord fields Nothing) ->
297+ do cfields <- traverse (traverse (Type.canonicalize env)) fields
298+ fieldDict <- Dups.checkFields cfields
299+
300+ let recordType = Can.TRecord fieldDict Nothing
301+ let ctorType = foldr (Can.TLambda . snd) recordType cfields
302+ let vars = map A.toValue args
303+ let alias = Can.Alias vars recordType (Just (map (A.toValue . fst) fields))
304+ let ctor = Env.RecordCtor home vars ctorType
305+
306+ Result.ok
307+ ( (name, alias)
308+ , Dups.one name region (OneOrMore.one ctor)
309+ )
310+
311+ _ ->
312+ do ctipe <- Type.canonicalize env tipe
313+ Result.ok
314+ ( (name, Can.Alias (map A.toValue args) ctipe Nothing)
315+ , Dups.none
316+ )
317+
318+
319+
320+-- CANONICALIZE UNION
321+
322+
323+canonicalizeUnion :: Env.Env -> Valid.Union -> Result i w ( (N.Name, Can.Union), CtorDups )
324+canonicalizeUnion env@(Env.Env home _ _ _ _ _ _ _) (Valid.Union (A.At _ name) avars ctors) =
325+ do cctors <- Index.indexedTraverse (canonicalizeCtor env) ctors
326+ let vars = map A.toValue avars
327+ let alts = map A.toValue cctors
328+ let union = Can.Union vars alts (length alts) (toOpts ctors)
329+ Result.ok
330+ ( (name, union)
331+ , Dups.unions $ map (toCtor home name union) cctors
332+ )
333+
334+
335+canonicalizeCtor :: Env.Env -> Index.ZeroBased -> (A.Located N.Name, [Src.Type]) -> Result i w (A.Located Can.Ctor)
336+canonicalizeCtor env index (A.At region ctor, tipes) =
337+ do ctipes <- traverse (Type.canonicalize env) tipes
338+ Result.ok $ A.At region $
339+ Can.Ctor ctor index (length ctipes) ctipes
340+
341+
342+toOpts :: [(A.Located N.Name, [Src.Type])] -> Can.CtorOpts
343+toOpts ctors =
344+ case ctors of
345+ [ (_,[_]) ] ->
346+ Can.Unbox
347+
348+ _ ->
349+ if all (null . snd) ctors then Can.Enum else Can.Normal
350+
351+
352+toCtor :: ModuleName.Canonical -> N.Name -> Can.Union -> A.Located Can.Ctor -> CtorDups
353+toCtor home typeName union (A.At region (Can.Ctor name index _ args)) =
354+ Dups.one name region $ OneOrMore.one $
355+ Env.Ctor home typeName union index args
src/Canonicalize/Module.hs+7−52
@@ -49,29 +49,19 @@ canonicalize
4949 -> I.Interfaces
5050 -> Valid.Module
5151 -> Result i [W.Warning] Can.Module
52−canonicalize pkg importDict interfaces module_@(Valid.Module name _ _ exports imports decls unions aliases binops effects) =
52+canonicalize pkg importDict interfaces module_@(Valid.Module name _ _ exports imports decls _ _ binops effects) =
5353 do let home = ModuleName.Canonical pkg name
54−
55− startEnv <- Local.addVarsAndTypes module_ =<<
56− Foreign.createInitialEnv home importDict interfaces imports
57−
58− (cunions, caliases) <-
59− (,)
60− <$> (Map.fromList <$> traverse (canonicalizeUnion startEnv) unions)
61− <*> (Map.fromList <$> traverse (canonicalizeAlias startEnv) aliases)
62−
63− let finalEnv = Local.addPatterns cunions startEnv
6454 let cbinops = Map.fromList (map canonicalizeBinop binops)
6555
66− (cdecls, ceffects) <-
67− (,)
68− <$> canonicalizeDecls finalEnv decls
69− <*> Effects.canonicalize finalEnv decls cunions effects
56+ (env, cunions, caliases) <-
57+ Local.add module_ =<<
58+ Foreign.createInitialEnv home importDict interfaces imports
7059
60+ cdecls <- canonicalizeDecls env decls
61+ ceffects <- Effects.canonicalize env decls cunions effects
7162 cexports <- canonicalizeExports decls cunions caliases cbinops ceffects exports
7263
73− let docs = toDocs module_
74− return $ Can.Module home docs cexports cdecls cunions caliases cbinops ceffects
64+ return $ Can.Module home (toDocs module_) cexports cdecls cunions caliases cbinops ceffects
7565
7666
7767
@@ -89,41 +79,6 @@ toDocs (Valid.Module _ docs comments _ _ _ _ _ _ _) =
8979
9080
9181
92−-- CANONICALIZE ALIAS
93−
94−
95−canonicalizeAlias :: Env.Env -> Valid.Alias -> Result i w ( N.Name, Can.Alias )
96−canonicalizeAlias env (Valid.Alias (A.At _ name) args tipe) =
97− do ctipe <- Type.canonicalize env tipe
98− return (name, Can.Alias (map A.toValue args) ctipe (toRecordCtorInfo tipe))
99−
100−
101−toRecordCtorInfo :: Src.Type -> Maybe [N.Name]
102−toRecordCtorInfo (A.At _ tipe) =
103− case tipe of
104− Src.TRecord fields Nothing ->
105− Just (map (A.toValue . fst) fields)
106−
107− _ ->
108− Nothing
109−
110−
111−
112−-- CANONICALIZE UNION
113−
114−
115−canonicalizeUnion :: Env.Env -> Valid.Union -> Result i w ( N.Name, Can.Union )
116−canonicalizeUnion env (Valid.Union (A.At _ name) args ctors) =
117− let
118− canonicalizeCtor (A.At _ ctor, tipes) =
119− do ctipes <- traverse (Type.canonicalize env) tipes
120− return (ctor, ctipes)
121− in
122− do cctors <- traverse canonicalizeCtor ctors
123− return ( name, Can.Union (map A.toValue args) cctors )
124−
125−
126−
12782-- CANONICALIZE BINOP
12883
12984