on master help sign in
Get a decent chunk of expression canonicalization compiling

Some highlights include: - The “definition sorting” moves into expression canonicalization. - Cyclic values are not permitted in lets, but cyclic functions are okay. - Checks for duplicate record fields are forced by the new AST. - Local variable shadowing is not allowed. You can shadow foreign stuff that got in through exposing (..) though. In 0.18 we would allow cyclic values if the cycle included a lambda. So if it went through a function or anonymous function, it was permitted because it MAY actually work. Those sorts of cycles will be permitted at the top-level though, and the hope is that this is a reasonable compromise between allowing folks to express everything they need and avoiding confusing mistakes. It also means that cyclic values can never be allocated dynamically, which will allow some future GC to not worry about cyclic data.

commitbfb8eca2a73343c4400276460fcb99190123dc87 authorEvan Czaplicki <evancz@users.noreply.github.com> dateMon 30 Oct 2017, 22:28 (9 years ago) parentc62990e
9 files changed+651−394
src/Canonicalize/Environment.hs+16−1 src/Canonicalize/Environment/Dups.hs+4−4 src/Canonicalize/Environment/Foreign.hs+18−9 src/Canonicalize/Environment/Internals.hs+49−10 src/Canonicalize/Environment/Local.hs+23−14 src/Canonicalize/Expression.hs+295 src/Canonicalize/Pattern.hs+221 src/Canonicalize/Sort.hs−346 src/Canonicalize/Type.hs+25−10
src/Canonicalize/Environment.hs+16−1
@@ -4,6 +4,7 @@ module Canonicalize.Environment
44 ( Env.Result
55 , Env.Env
66 , create
7+ , Env.addLocals
78 , Env.findVar
89 , Env.findType
910 , Env.findPattern
@@ -23,14 +24,28 @@ import qualified Canonicalize.Environment.Internals as Env
2324import qualified Canonicalize.Environment.Local as Local
2425import qualified Elm.Interface as I
2526import qualified Elm.Package as Package
27+import qualified Reporting.Error.Canonicalize as Error
28+import qualified Reporting.Result as Result
29+import qualified Reporting.Warning as Warning
2630
2731
2832
33+-- RESULT
34+
35+
36+type Result a =
37+ Result.Result () Warning.Warning Error.Error a
38+
39+
40+
41+-- CREATE
42+
43+
2944type ImportDict =
3045 Map.Map ModuleName.Raw ModuleName.Canonical
3146
3247
33−create :: Package.Name -> ImportDict -> I.Interfaces -> Valid.Module -> Env.Result Env.Env
48+create :: Package.Name -> ImportDict -> I.Interfaces -> Valid.Module -> Result Env.Env
3449create pkg importDict interfaces module_@(Valid.Module name _ _ _ imports _ _ _ _ _) =
3550 let home = ModuleName.Canonical pkg name in
3651 Local.addDeclarations module_ =<<
src/Canonicalize/Environment/Dups.hs+4−4
@@ -1,7 +1,7 @@
11{-# OPTIONS_GHC -Wall #-}
22{-# LANGUAGE OverloadedStrings #-}
33module Canonicalize.Environment.Dups
4− ( Info
4+ ( Info(Info)
55 , info
66 , detect
77 , checkFields
@@ -45,12 +45,12 @@ type ToError c =
4545 N.Name -> c -> c -> Error.Error
4646
4747
48−detect :: ToError c -> [(N.Name, [Info c v])] -> Result (Map.Map N.Name v)
48+detect :: ToError c -> [(N.Name, [Info c v])] -> Result () (Map.Map N.Name v)
4949detect toError pairs =
5050 Map.traverseWithKey (detectHelp toError) $ Map.fromListWith (++) pairs
5151
5252
53−detectHelp :: ToError c -> N.Name -> [Info c v] -> Result v
53+detectHelp :: ToError c -> N.Name -> [Info c v] -> Result () v
5454detectHelp toError name values =
5555 case values of
5656 [Info _ _ value] ->
@@ -67,7 +67,7 @@ detectHelp toError name values =
6767-- CHECK FIELDS
6868
6969
70−checkFields :: [(A.Located N.Name, a)] -> Result (Map.Map N.Name a)
70+checkFields :: [(A.Located N.Name, a)] -> Result () (Map.Map N.Name a)
7171checkFields fields =
7272 let
7373 toInfo (A.A region name, value) =
src/Canonicalize/Environment/Foreign.hs+18−9
@@ -12,9 +12,9 @@ import qualified Data.Set as Set
1212import qualified AST.Expression.Canonical as Can
1313import qualified AST.Expression.Source as Src
1414import qualified AST.Module.Name as ModuleName
15−import qualified Canonicalize.Bag as Bag
1615import qualified Canonicalize.Environment.Internals as Env
17−import qualified Canonicalize.OneOrMore as OneOrMore
16+import qualified Data.Bag as Bag
17+import qualified Data.OneOrMore as OneOrMore
1818import qualified Elm.Interface as I
1919import qualified Elm.Name as N
2020import qualified Reporting.Annotation as A
@@ -22,6 +22,15 @@ import qualified Reporting.Error.Canonicalize as Error
2222import qualified Reporting.Helpers as Help (nearbyNames)
2323import qualified Reporting.Region as R
2424import qualified Reporting.Result as Result
25+import qualified Reporting.Warning as Warning
26+
27+
28+
29+-- RESULT
30+
31+
32+type Result a =
33+ Result.Result () Warning.Warning Error.Error a
2534
2635
2736
@@ -70,7 +79,7 @@ type ImportDict =
7079 Map.Map ModuleName.Raw ModuleName.Canonical
7180
7281
73−createInitialEnv :: ModuleName.Canonical -> ImportDict -> I.Interfaces -> [Src.Import] -> Env.Result Env.Env
82+createInitialEnv :: ModuleName.Canonical -> ImportDict -> I.Interfaces -> [Src.Import] -> Result Env.Env
7483createInitialEnv home importDict interfaces sourceImports =
7584 do imports <- traverse (verifyImport importDict interfaces) sourceImports
7685 let (Env vars types patterns binops) = foldr merge emptyEnv (map importToEnv imports)
@@ -238,7 +247,7 @@ data Exposed
238247 | Alias
239248
240249
241−verifyImport :: ImportDict -> I.Interfaces -> Src.Import -> Env.Result Import
250+verifyImport :: ImportDict -> I.Interfaces -> Src.Import -> Result Import
242251verifyImport importDict interfaces (Src.Import (A.A region name) alias exposing) =
243252 case Map.lookup name importDict of
244253 Nothing ->
@@ -260,14 +269,14 @@ verifyImport importDict interfaces (Src.Import (A.A region name) alias exposing)
260269 Result.ok (Explicit (Map.fromList (concat pairLists)))
261270
262271
263−throwImportNotFound :: R.Region -> ModuleName.Raw -> [ModuleName.Canonical] -> Env.Result a
272+throwImportNotFound :: R.Region -> ModuleName.Raw -> [ModuleName.Canonical] -> Result a
264273throwImportNotFound region name knownModules =
265274 Result.throw region $ Error.ImportNotFound name $
266275 Help.nearbyNames ModuleName.toString name $
267276 map ModuleName._module knownModules
268277
269278
270−verifyExposed :: ModuleName.Raw -> I.Interface -> A.Located Src.Exposed -> Env.Result [(N.Name, Exposed)]
279+verifyExposed :: ModuleName.Raw -> I.Interface -> A.Located Src.Exposed -> Result [(N.Name, Exposed)]
271280verifyExposed moduleName interface@(I.Interface _ _ unions aliases _) (A.A region exposed) =
272281 case exposed of
273282 Src.Operator name ->
@@ -291,7 +300,7 @@ verifyExposed moduleName interface@(I.Interface _ _ unions aliases _) (A.A regio
291300 throwExposingNotFound moduleName region name interface
292301
293302
294−verifyValue :: ModuleName.Raw -> R.Region -> N.Name -> I.Interface -> Env.Result [(N.Name, Exposed)]
303+verifyValue :: ModuleName.Raw -> R.Region -> N.Name -> I.Interface -> Result [(N.Name, Exposed)]
295304verifyValue moduleName region name interface@(I.Interface _ types _ _ _) =
296305 case Map.lookup name types of
297306 Nothing ->
@@ -301,7 +310,7 @@ verifyValue moduleName region name interface@(I.Interface _ types _ _ _) =
301310 Result.ok [(name, Value)]
302311
303312
304−verifyAlias :: R.Region -> N.Name -> Src.Privacy -> Env.Result [(N.Name, Exposed)]
313+verifyAlias :: R.Region -> N.Name -> Src.Privacy -> Result [(N.Name, Exposed)]
305314verifyAlias region name privacy =
306315 case privacy of
307316 Src.Public ->
@@ -311,7 +320,7 @@ verifyAlias region name privacy =
311320 Result.ok [(name, Alias)]
312321
313322
314−throwExposingNotFound :: ModuleName.Raw -> R.Region -> N.Name -> I.Interface -> Env.Result a
323+throwExposingNotFound :: ModuleName.Raw -> R.Region -> N.Name -> I.Interface -> Result a
315324throwExposingNotFound moduleName region name (I.Interface _ types unions aliases _) =
316325 let
317326 toCtorPairs (tipe, Can.Union _ ctors) =
src/Canonicalize/Environment/Internals.hs+49−10
@@ -7,6 +7,7 @@ module Canonicalize.Environment.Internals
77 , UnqualifiedVarHome(..)
88 , Type(..)
99 , Homes(..)
10+ , addLocals
1011 , findVar
1112 , findType
1213 , findPattern
@@ -17,14 +18,17 @@ module Canonicalize.Environment.Internals
1718
1819
1920import qualified Data.Map.Strict as Map
21+import qualified Data.Map.Merge.Strict as Map
22+import qualified Data.Set as Set
2023
2124import qualified AST.Binop as Binop
2225import qualified AST.Expression.Canonical as Can
2326import qualified AST.Module.Name as ModuleName
2427import qualified AST.Type as Type
25−import qualified Canonicalize.Bag as Bag
26−import qualified Canonicalize.OneOrMore as OneOrMore
28+import qualified Data.Bag as Bag
29+import qualified Data.OneOrMore as OneOrMore
2730import qualified Elm.Name as N
31+import qualified Reporting.Annotation as A
2832import qualified Reporting.Error.Canonicalize as Error
2933import qualified Reporting.Region as R
3034import qualified Reporting.Result as Result
@@ -35,8 +39,8 @@ import qualified Reporting.Warning as Warning
3539-- RESULT HELPERS
3640
3741
38−type Result a =
39− Result.Result () Warning.Warning Error.Error a
42+type Result i a =
43+ Result.Result i Warning.Warning Error.Error a
4044
4145
4246
@@ -88,10 +92,45 @@ data Binop =
8892
8993
9094
95+-- ADD LOCALS
96+
97+
98+addLocals :: Map.Map N.Name (A.Located a) -> Env -> Result () Env
99+addLocals names (Env home vars types patterns binops) =
100+ do newVars <-
101+ Map.mergeA
102+ (Map.mapMissing (\_ _ -> localVarHomes))
103+ (Map.mapMissing (\_ homes -> homes))
104+ (Map.zipWithAMatched addLocalBoth)
105+ names
106+ vars
107+ Result.ok $ Env home newVars types patterns binops
108+
109+
110+{-# NOINLINE localVarHomes #-}
111+localVarHomes :: VarHomes
112+localVarHomes =
113+ VarHomes Local Map.empty
114+
115+
116+addLocalBoth :: N.Name -> A.Located a -> VarHomes -> Result () VarHomes
117+addLocalBoth name (A.A region _) (VarHomes unqualified qualified) =
118+ case unqualified of
119+ Foreign _ ->
120+ Result.ok (VarHomes Local qualified)
121+
122+ Local ->
123+ Result.throw region (Error.Shadowing name)
124+
125+ TopLevel ->
126+ Result.throw region (Error.Shadowing name)
127+
128+
129+
91130-- FIND VAR
92131
93132
94−findVar :: R.Region -> Env -> Maybe N.Name -> N.Name -> Result Can.Expr_
133+findVar :: R.Region -> Env -> Maybe N.Name -> N.Name -> Result (Set.Set N.Name) Can.Expr_
95134findVar region (Env home vars _ _ _) maybePrefix name =
96135 case Map.lookup name vars of
97136 Nothing ->
@@ -102,10 +141,10 @@ findVar region (Env home vars _ _ _) maybePrefix name =
102141 Nothing ->
103142 case unqualified of
104143 Local ->
105− Result.ok (Can.VarLocal name)
144+ Result.accumulate (Set.singleton name) (Can.VarLocal name)
106145
107146 TopLevel ->
108− Result.ok (Can.VarTopLevel home name)
147+ Result.accumulate (Set.singleton name) (Can.VarTopLevel home name)
109148
110149 Foreign bag ->
111150 case bag of
@@ -134,12 +173,12 @@ findVar region (Env home vars _ _ _) maybePrefix name =
134173-- FIND TYPE and PATTERN
135174
136175
137−findType :: R.Region -> Env -> Maybe N.Name -> N.Name -> Int -> Result Type
176+findType :: (Monoid i) => R.Region -> Env -> Maybe N.Name -> N.Name -> Int -> Result i Type
138177findType region (Env _ _ types _ _) maybePrefix name arity =
139178 error "TODO findType" region types maybePrefix name arity
140179
141180
142−findPattern :: R.Region -> Env -> Maybe N.Name -> N.Name -> Int -> Result ModuleName.Canonical
181+findPattern :: (Monoid i) => R.Region -> Env -> Maybe N.Name -> N.Name -> Int -> Result i ModuleName.Canonical
143182findPattern region (Env _ _ _ patterns _) maybePrefix name arity =
144183 error "TODO findPattern" region patterns maybePrefix name arity
145184
@@ -148,7 +187,7 @@ findPattern region (Env _ _ _ patterns _) maybePrefix name arity =
148187-- FIND BINOP
149188
150189
151−findBinop :: R.Region -> Env -> N.Name -> Result Binop
190+findBinop :: R.Region -> Env -> N.Name -> Result (Set.Set N.Name) Binop
152191findBinop region (Env _ _ _ _ binops) name =
153192 case Map.lookup name binops of
154193 Just (OneOrMore.One binop) ->
src/Canonicalize/Environment/Local.hs+23−14
@@ -14,23 +14,32 @@ import qualified Data.Map.Merge.Strict as Map
1414
1515import qualified AST.Expression.Valid as Valid
1616import qualified AST.Type as Type
17−import qualified Canonicalize.Bag as Bag
1817import qualified Canonicalize.Environment.Dups as Dups
1918import qualified Canonicalize.Environment.Internals as Env
20−import qualified Canonicalize.OneOrMore as OneOrMore
2119import qualified Canonicalize.Type as Type
20+import qualified Data.Bag as Bag
21+import qualified Data.OneOrMore as OneOrMore
2222import qualified Elm.Name as N
2323import qualified Reporting.Annotation as A
2424import qualified Reporting.Error.Canonicalize as Error
2525import qualified Reporting.Region as R
2626import qualified Reporting.Result as Result
27+import qualified Reporting.Warning as Warning
28+
29+
30+
31+-- RESULT
32+
33+
34+type Result a =
35+ Result.Result () Warning.Warning Error.Error a
2736
2837
2938
3039-- ADD DECLARATIONS
3140
3241
33−addDeclarations :: Valid.Module -> Env.Env -> Env.Result Env.Env
42+addDeclarations :: Valid.Module -> Env.Env -> Result Env.Env
3443addDeclarations module_ env =
3544 addVars module_
3645 =<< addTypes module_
@@ -89,7 +98,7 @@ addPatterns (Valid.Module _ _ _ _ _ _ unions _ _ _) (Env.Env home vars types pat
8998-- ADD BINOPS
9099
91100
92−addBinops :: Valid.Module -> Env.Env -> Env.Result Env.Env
101+addBinops :: Valid.Module -> Env.Env -> Result Env.Env
93102addBinops (Valid.Module _ _ _ _ _ _ _ _ ops _) (Env.Env home vars types patterns binops) =
94103 let
95104 toInfo (Valid.Binop (A.A region op) assoc prec name) =
@@ -107,7 +116,7 @@ addBinops (Valid.Module _ _ _ _ _ _ _ _ ops _) (Env.Env home vars types patterns
107116-- ADD VARS
108117
109118
110−addVars :: Valid.Module -> Env.Env -> Env.Result Env.Env
119+addVars :: Valid.Module -> Env.Env -> Result Env.Env
111120addVars module_ (Env.Env home vars types patterns binops) =
112121 do upperDict <- collectUpperVars module_
113122 lowerDict <- collectLowerVars module_
@@ -131,7 +140,7 @@ addVarsHelp localVars vars =
131140 merge addLeft addBoth localVars vars
132141
133142
134−collectLowerVars :: Valid.Module -> Env.Result (Map.Map N.Name ())
143+collectLowerVars :: Valid.Module -> Result (Map.Map N.Name ())
135144collectLowerVars (Valid.Module _ _ _ _ _ decls _ _ _ effects) =
136145 let
137146 declToInfo (Valid.Decl (A.A region name) _ _ _) =
@@ -166,7 +175,7 @@ collectLowerVars (Valid.Module _ _ _ _ _ decls _ _ _ effects) =
166175 effectInfo ++ map declToInfo decls
167176
168177
169−collectUpperVars :: Valid.Module -> Env.Result (Map.Map N.Name ())
178+collectUpperVars :: Valid.Module -> Result (Map.Map N.Name ())
170179collectUpperVars (Valid.Module _ _ _ _ _ _ unions aliases _ _) =
171180 let
172181 unionToInfos (Valid.Union (A.A _ name) _ ctors) =
@@ -191,7 +200,7 @@ collectUpperVars (Valid.Module _ _ _ _ _ _ unions aliases _ _) =
191200-- ADD TYPES
192201
193202
194−addTypes :: Valid.Module -> Env.Env -> Env.Result Env.Env
203+addTypes :: Valid.Module -> Env.Env -> Result Env.Env
195204addTypes (Valid.Module _ _ _ _ _ _ unions aliases _ _) env =
196205 let
197206 aliasToInfo alias@(Valid.Alias (A.A region name) _ tipe) =
@@ -246,18 +255,18 @@ data Alias =
246255 }
247256
248257
249−addTypeAliases :: Map.Map N.Name Alias -> Env.Env -> Env.Result Env.Env
258+addTypeAliases :: Map.Map N.Name Alias -> Env.Env -> Result Env.Env
250259addTypeAliases aliases env =
251260 do let nodes = map toNode (Map.elems aliases)
252261 let sccs = Graph.stronglyConnComp nodes
253262 foldM addTypeAlias env sccs
254263
255264
256−addTypeAlias :: Env.Env -> Graph.SCC Alias -> Env.Result Env.Env
265+addTypeAlias :: Env.Env -> Graph.SCC Alias -> Result Env.Env
257266addTypeAlias env@(Env.Env home vars types patterns binops) scc =
258267 case scc of
259268 Graph.AcyclicSCC (Alias _ name args tipe) ->
260− do ctype <- Type.canonicalize env tipe
269+ do (A.A _ ctype) <- Type.canonicalize env tipe
261270 let info = (Env.Alias home args ctype, length args)
262271 let newTypes = Map.alter (addAliasInfo info) name types
263272 return $ Env.Env home vars newTypes patterns binops
@@ -267,7 +276,7 @@ addTypeAlias env@(Env.Env home vars types patterns binops) scc =
267276
268277 Graph.CyclicSCC (Alias region name1 args tipe : others) ->
269278 let toName (Alias _ name _ _) = name in
270− Result.throw region (Error.AliasRecursion name1 args tipe (map toName others))
279+ Result.throw region (Error.RecursiveAlias name1 args tipe (map toName others))
271280
272281
273282addAliasInfo :: a -> Maybe (Env.Homes a) -> Maybe (Env.Homes a)
@@ -319,7 +328,7 @@ getEdges (A.A _ tipe) =
319328-- CHECK FREE VARIABLES
320329
321330
322−checkUnionFreeVars :: Valid.Union -> Env.Result Int
331+checkUnionFreeVars :: Valid.Union -> Result Int
323332checkUnionFreeVars (Valid.Union (A.A unionRegion name) args ctors) =
324333 let
325334 toInfo (A.A region arg) =
@@ -344,7 +353,7 @@ checkUnionFreeVars (Valid.Union (A.A unionRegion name) args ctors) =
344353
345354
346355
347−checkAliasFreeVars :: Valid.Alias -> Env.Result [N.Name]
356+checkAliasFreeVars :: Valid.Alias -> Result [N.Name]
348357checkAliasFreeVars (Valid.Alias (A.A aliasRegion name) args tipe) =
349358 let
350359 toInfo (A.A region arg) =
src/Canonicalize/Expression.hsnew file+295
@@ -0,0 +1,295 @@
1+{-# OPTIONS_GHC -Wall #-}
2+module Canonicalize.Expression
3+ ( canonicalize
4+ )
5+ where
6+
7+
8+import Control.Applicative (liftA2)
9+import qualified Data.Graph as Graph
10+import qualified Data.Map.Strict as Map
11+import qualified Data.Set as Set
12+
13+import qualified AST.Expression.Canonical as Can
14+import qualified AST.Expression.Valid as Valid
15+import qualified Canonicalize.Environment as Env
16+import qualified Canonicalize.Environment.Dups as Dups
17+import qualified Canonicalize.Pattern as Pattern
18+import qualified Canonicalize.Type as Type
19+import qualified Elm.Name as N
20+import qualified Reporting.Annotation as A
21+import qualified Reporting.Error.Canonicalize as Error
22+import qualified Reporting.Region as R
23+import qualified Reporting.Result as Result
24+import qualified Reporting.Warning as Warning
25+
26+
27+
28+-- RESULTS
29+
30+
31+type Result i a =
32+ Result.Result i Warning.Warning Error.Error a
33+
34+
35+type FreeLocals =
36+ Set.Set N.Name
37+
38+
39+
40+-- EXPRESSIONS
41+
42+
43+canonicalize :: Env.Env -> Valid.Expr -> Result FreeLocals Can.Expr
44+canonicalize env (A.A region expression) =
45+ A.A region <$>
46+ case expression of
47+ Valid.Literal lit ->
48+ Result.ok (Can.Literal lit)
49+
50+ Valid.Var maybePrefix name ->
51+ Env.findVar region env maybePrefix name
52+
53+ Valid.List exprs ->
54+ Can.List <$> traverse (canonicalize env) exprs
55+
56+ Valid.Op name ->
57+ do (Env.Binop home func _ _) <- Env.findBinop region env name
58+ return (Can.VarOperator name home func)
59+
60+ Valid.Negate expr ->
61+ Can.Negate <$> canonicalize env expr
62+
63+ Valid.Binops ops final ->
64+ error "TODO"
65+
66+ Valid.Lambda args body ->
67+ addLocals $
68+ do cargs@(Can.Args _ destructors) <- Pattern.canonicalizeArgs env args
69+ newEnv <- Env.addLocals destructors env
70+ removeLocals destructors $
71+ Can.Lambda cargs <$> canonicalize newEnv body
72+
73+ Valid.Call func args ->
74+ Can.Call
75+ <$> canonicalize env func
76+ <*> traverse (canonicalize env) args
77+
78+ Valid.If branches finally ->
79+ Can.If
80+ <$> traverse (canonicalizeBranch env) branches
81+ <*> canonicalize env finally
82+
83+ Valid.Let defs expr ->
84+ A.drop <$> canonicalizeLet region env defs expr
85+
86+ Valid.Case expr cases ->
87+ error "TODO"
88+
89+ Valid.Accessor field ->
90+ Result.ok $ Can.Accessor field
91+
92+ Valid.Access record field ->
93+ Can.Access
94+ <$> canonicalize env record
95+ <*> Result.ok field
96+
97+ Valid.Update (A.A reg name) fields ->
98+ do fieldDict <- Result.untracked $ Dups.checkFields fields
99+ name_ <- Env.findVar reg env Nothing name
100+ Can.Update (A.A reg name_)
101+ <$> traverse (canonicalize env) fieldDict
102+
103+ Valid.Record fields ->
104+ do fieldDict <- Result.untracked $ Dups.checkFields fields
105+ Can.Record <$> traverse (canonicalize env) fieldDict
106+
107+ Valid.Unit ->
108+ Result.ok Can.Unit
109+
110+ Valid.Tuple a b cs ->
111+ Can.Tuple
112+ <$> canonicalize env a
113+ <*> canonicalize env b
114+ <*> canonicalizeTupleExtras region env cs
115+
116+ Valid.GLShader uid src tipe ->
117+ Result.ok (Can.GLShader uid src tipe)
118+
119+
120+
121+-- CANONICALIZE TUPLE EXTRAS
122+
123+
124+canonicalizeTupleExtras :: R.Region -> Env.Env -> [Valid.Expr] -> Result FreeLocals (Maybe Can.Expr)
125+canonicalizeTupleExtras region env extras =
126+ case extras of
127+ [] ->
128+ Result.ok Nothing
129+
130+ [three] ->
131+ Just <$> canonicalize env three
132+
133+ _ : others ->
134+ let (A.A r1 _, A.A r2 _) = (head others, last others) in
135+ Result.throw region (Error.TupleLargerThanThree (R.merge r1 r2))
136+
137+
138+
139+-- CANONICALIZE IF BRANCH
140+
141+
142+canonicalizeBranch :: Env.Env -> (Valid.Expr, Valid.Expr) -> Result FreeLocals (Can.Expr, Can.Expr)
143+canonicalizeBranch env (condition, branch) =
144+ liftA2 (,) (canonicalize env condition) (canonicalize env branch)
145+
146+
147+
148+-- CANONICALIZE LET
149+
150+
151+canonicalizeLet :: R.Region -> Env.Env -> [Valid.Def] -> Valid.Expr -> Result FreeLocals Can.Expr
152+canonicalizeLet region env defs body =
153+ addLocals $
154+ do (bindings, boundNames) <- Pattern.canonicalizeBindings env defs
155+ newEnv <- Env.addLocals boundNames env
156+ let defKeys = Map.map A.drop boundNames
157+ nodes <- Result.untracked $ traverse (bindingToNode defKeys newEnv) bindings
158+ removeLocals defKeys $
159+ do cbody <- canonicalize env body
160+ detectCycles region (Graph.stronglyConnComp nodes) cbody
161+
162+
163+addLocals :: Result () (expr, FreeLocals) -> Result FreeLocals expr
164+addLocals (Result.Result () warnings answer) =
165+ case answer of
166+ Result.Ok (value, freeLocals) ->
167+ Result.Result freeLocals warnings (Result.Ok value)
168+
169+ Result.Err err ->
170+ Result.Result Set.empty warnings (Result.Err err)
171+
172+
173+removeLocals :: Map.Map N.Name a -> Result FreeLocals expr -> Result () (expr, FreeLocals)
174+removeLocals boundNames (Result.Result freeLocals warnings answer) =
175+ Result.Result () warnings $
176+ case answer of
177+ Result.Ok value ->
178+ Result.Ok
179+ ( value
180+ , Set.difference freeLocals (Map.keysSet boundNames)
181+ )
182+
183+ Result.Err err ->
184+ Result.Err err
185+
186+
187+
188+-- BUILD BINDINGS GRAPH
189+
190+
191+data Binding
192+ = Define R.Region Can.Def
193+ | Destruct R.Region Can.Match Can.Expr
194+
195+
196+data Node = Node Binding FreeLocals
197+
198+
199+bindingToNode :: Map.Map N.Name Int -> Env.Env -> Pattern.Binding -> Result () (Node, Int, [Int])
200+bindingToNode defKeys env binding =
201+ case binding of
202+ Pattern.Define region index name args body maybeType ->
203+ do cargs@(Can.Args _ destructors) <- Pattern.canonicalizeArgs env args
204+ ctype <- traverse (Type.canonicalize env) maybeType
205+ newEnv <- Env.addLocals destructors env
206+ toNode defKeys destructors index $
207+ do cbody <- canonicalize newEnv body
208+ return (Define region (Can.Def name cargs cbody ctype))
209+
210+ Pattern.Destruct region index match body ->
211+ toNode defKeys Map.empty index $
212+ Destruct region match <$> canonicalize env body
213+
214+
215+toNode :: Map.Map N.Name Int -> Map.Map N.Name a -> Int -> Result FreeLocals Binding -> Result () (Node, Int, [Int])
216+toNode defKeys args index (Result.Result freeLocals warnings answer) =
217+ Result.Result () warnings $
218+ case answer of
219+ Result.Err err ->
220+ Result.Err err
221+
222+ Result.Ok binding ->
223+ let
224+ actuallyFreeLocals = Set.difference freeLocals (Map.keysSet args)
225+ locallyDefinedLocals = Map.restrictKeys defKeys freeLocals
226+ in
227+ Result.Ok
228+ ( Node binding actuallyFreeLocals
229+ , index
230+ , Map.elems locallyDefinedLocals
231+ )
232+
233+
234+
235+-- DETECT CYCLES
236+
237+
238+detectCycles :: R.Region -> [Graph.SCC Node] -> Can.Expr -> Result FreeLocals Can.Expr
239+detectCycles region sccs body =
240+ case sccs of
241+ [] ->
242+ Result.ok body
243+
244+ scc : subSccs ->
245+ A.A region <$>
246+ case scc of
247+ Graph.AcyclicSCC (Node binding freeLocals) ->
248+ case binding of
249+ Define _ def ->
250+ Result.accumulate freeLocals (Can.Let def)
251+ <*> detectCycles region subSccs body
252+
253+ Destruct _ match expr ->
254+ Result.accumulate freeLocals (Can.LetDestruct match expr)
255+ <*> detectCycles region subSccs body
256+
257+ Graph.CyclicSCC nodes ->
258+ case unzip <$> traverse requireDefine nodes of
259+ Nothing ->
260+ Result.throw region (Error.RecursiveValue (map toCycleNodes nodes))
261+
262+ Just (defs, freeLocals) ->
263+ Result.accumulate (Set.unions freeLocals) (Can.LetRec defs)
264+ <*> detectCycles region subSccs body
265+
266+
267+
268+requireDefine :: Node -> Maybe (Can.Def, FreeLocals)
269+requireDefine (Node binding freeLocals) =
270+ case binding of
271+ Define _ def@(Can.Def _ (Can.Args args _) _ _) ->
272+ case args of
273+ [] ->
274+ Nothing
275+
276+ _ ->
277+ Just (def, freeLocals)
278+
279+ Destruct _ _ _ ->
280+ Nothing
281+
282+
283+toCycleNodes :: Node -> Error.CycleNode
284+toCycleNodes (Node binding _) =
285+ case binding of
286+ Define _ (Can.Def name (Can.Args args _) _ _) ->
287+ case args of
288+ [] ->
289+ Error.CycleValue name
290+
291+ _ ->
292+ Error.CycleFunc name
293+
294+ Destruct _ (Can.Match pattern _) _ ->
295+ Error.CyclePattern pattern
src/Canonicalize/Pattern.hsnew file+221
@@ -0,0 +1,221 @@
1+{-# OPTIONS_GHC -Wall #-}
2+module Canonicalize.Pattern
3+ ( canonicalizeArgs
4+ , canonicalizeMatch
5+ , canonicalizeBindings
6+ , Binding(..)
7+ )
8+ where
9+
10+
11+import Control.Monad (zipWithM)
12+import qualified Data.Map.Strict as Map
13+
14+import qualified AST.Expression.Canonical as Can
15+import qualified AST.Expression.Source as Src
16+import qualified AST.Expression.Valid as Valid
17+import qualified AST.Type as Type
18+import qualified Canonicalize.Environment as Env
19+import qualified Canonicalize.Environment.Dups as Dups
20+import qualified Data.Bag as Bag
21+import qualified Elm.Name as N
22+import qualified Reporting.Annotation as A
23+import qualified Reporting.Error.Canonicalize as Error
24+import qualified Reporting.Region as R
25+import qualified Reporting.Result as Result
26+import qualified Reporting.Warning as Warning
27+
28+
29+
30+-- RESULTS
31+
32+
33+type Result i =
34+ Result.Result i Warning.Warning Error.Error
35+
36+
37+
38+-- CANONICALIZE ARGS
39+
40+
41+canonicalizeArgs :: Env.Env -> [Src.Pattern] -> Result () Can.Args
42+canonicalizeArgs env patterns =
43+ case zipWithM (canonicalizeArg env) patterns [ 0 .. length patterns ] of
44+ Result.Result bag warnings (Result.Ok args) ->
45+ do let toError name () () = Error.DuplicateArg name
46+ destructors <- Dups.detect toError (Bag.toList bag)
47+ Result.Result () warnings $ Result.Ok $
48+ Can.Args args destructors
49+
50+ Result.Result _ warnings (Result.Err err) ->
51+ Result.Result () warnings (Result.Err err)
52+
53+
54+canonicalizeArg :: Env.Env -> Src.Pattern -> Int -> Result Bag Can.Arg
55+canonicalizeArg env pattern index =
56+ Can.Arg index <$> canonicalize env (Can.DRoot index) pattern
57+
58+
59+
60+-- CANONICALIZE MATCH
61+
62+
63+canonicalizeMatch :: Env.Env -> Src.Pattern -> Result () Can.Match
64+canonicalizeMatch env pattern =
65+ case canonicalize env (Can.DRoot 0) pattern of
66+ Result.Result bag warnings (Result.Ok cpattern) ->
67+ do let toError name () () = Error.DuplicateArg name
68+ destructors <- Dups.detect toError (Bag.toList bag)
69+ Result.Result () warnings $ Result.Ok $
70+ Can.Match cpattern destructors
71+
72+ Result.Result _ warnings (Result.Err err) ->
73+ Result.Result () warnings (Result.Err err)
74+
75+
76+
77+-- CANONICALIZE BINDINGS
78+
79+
80+data Binding
81+ = Define R.Region Int (A.Located N.Name) [Src.Pattern] Valid.Expr (Maybe Type.Raw)
82+ | Destruct R.Region Int Can.Match Valid.Expr
83+
84+
85+canonicalizeBindings :: Env.Env -> [Valid.Def] -> Result () ( [Binding], Map.Map N.Name (A.Located Int) )
86+canonicalizeBindings env defs =
87+ case zipWithM (canonicalizeBinding env) defs [ 0 .. length defs ] of
88+ Result.Result bag warnings (Result.Ok cdefs) ->
89+ do let toError name () () = Error.DuplicateBindingName name
90+ nodes <- Dups.detect toError (Bag.toList bag)
91+ Result.Result () warnings (Result.Ok (cdefs, nodes))
92+
93+ Result.Result _ warnings (Result.Err err) ->
94+ Result.Result () warnings (Result.Err err)
95+
96+
97+type KeyBag =
98+ Bag.Bag ( N.Name, [Dups.Info () (A.Located Int)] )
99+
100+
101+canonicalizeBinding :: Env.Env -> Valid.Def -> Int -> Result KeyBag Binding
102+canonicalizeBinding env def index =
103+ case def of
104+ Valid.Define region aname@(A.A reg name) args body maybeType ->
105+ let info = Dups.info name reg () (A.A region index) in
106+ Result.accumulate (Bag.one info) $
107+ Define region index aname args body maybeType
108+
109+ Valid.Destruct region pattern body ->
110+ case canonicalize env (Can.DRoot 0) pattern of
111+ Result.Result bag warnings (Result.Ok cpattern) ->
112+ do let toError name () () = Error.DuplicateBindingName name
113+ destructors <- Result.untracked (Dups.detect toError (Bag.toList bag))
114+ Result.Result (toKeyBag index bag) warnings $ Result.Ok $
115+ Destruct region index (Can.Match cpattern destructors) body
116+
117+ Result.Result bag warnings (Result.Err err) ->
118+ Result.Result (toKeyBag index bag) warnings (Result.Err err)
119+
120+
121+toKeyBag :: Int -> Bag -> KeyBag
122+toKeyBag index bag =
123+ let
124+ redoInfo (Dups.Info region () _) =
125+ Dups.Info region () (A.A region index)
126+
127+ replaceWithIndex ( name, infos ) =
128+ ( name, map redoInfo infos )
129+ in
130+ Bag.map replaceWithIndex bag
131+
132+
133+
134+-- CANONICALIZE
135+
136+
137+type Bag =
138+ Bag.Bag (N.Name, [Dups.Info () (A.Located Can.Destructor)])
139+
140+
141+canonicalize :: Env.Env -> Can.Destructor -> Src.Pattern -> Result Bag Can.Pattern
142+canonicalize env destructor (A.A region pattern) =
143+ A.A region <$>
144+ case pattern of
145+ Src.PAnything ->
146+ Result.ok Can.PAnything
147+
148+ Src.PVar name ->
149+ Result.accumulate
150+ (Bag.one (Dups.info name region () (A.A region destructor)))
151+ (Can.PVar name)
152+
153+ Src.PRecord fields ->
154+ let
155+ fieldToInfo (A.A reg name) =
156+ Dups.info name reg () (A.A reg (Can.DField name destructor))
157+ in
158+ Result.accumulate
159+ (Bag.fromList fieldToInfo fields)
160+ (Can.PRecord (map A.drop fields))
161+
162+ Src.PUnit ->
163+ Result.ok Can.PUnit
164+
165+ Src.PTuple a b cs ->
166+ Can.PTuple
167+ <$> canonicalize env (Can.DIndex 0 destructor) a
168+ <*> canonicalize env (Can.DIndex 1 destructor) b
169+ <*> canonicalizeTuple region env destructor cs
170+
171+ Src.PCtor nameRegion maybePrefix name patterns ->
172+ let
173+ ctorArg ptrn index =
174+ canonicalize env (Can.DIndex index destructor) ptrn
175+ in
176+ Can.PCtor
177+ <$> Env.findPattern nameRegion env maybePrefix name (length patterns)
178+ <*> pure name
179+ <*> zipWithM ctorArg patterns [ 0 .. length patterns ]
180+
181+ Src.PList patterns ->
182+ Can.PList <$> canonicalizeList env destructor patterns
183+
184+ Src.PCons first rest ->
185+ Can.PCons
186+ <$> canonicalize env (Can.DIndex 0 destructor) first
187+ <*> canonicalize env (Can.DIndex 1 destructor) rest
188+
189+ Src.PAlias ptrn (A.A reg name) ->
190+ do cpattern <- canonicalize env destructor ptrn
191+ let info = Dups.info name reg () (A.A reg destructor)
192+ Result.accumulate (Bag.one info) (Can.PAlias cpattern name)
193+
194+ Src.PLiteral lit ->
195+ Result.ok (Can.PLiteral lit)
196+
197+
198+canonicalizeTuple :: R.Region -> Env.Env -> Can.Destructor -> [Src.Pattern] -> Result Bag (Maybe Can.Pattern)
199+canonicalizeTuple tupleRegion env destructor extras =
200+ case extras of
201+ [] ->
202+ Result.ok Nothing
203+
204+ [three] ->
205+ Just <$> canonicalize env (Can.DIndex 2 destructor) three
206+
207+ _ : others ->
208+ let (A.A r1 _, A.A r2 _) = (head others, last others) in
209+ Result.throw tupleRegion (Error.TupleLargerThanThree (R.merge r1 r2))
210+
211+
212+canonicalizeList :: Env.Env -> Can.Destructor -> [Src.Pattern] -> Result Bag [Can.Pattern]
213+canonicalizeList env destructor list =
214+ case list of
215+ [] ->
216+ Result.ok []
217+
218+ pattern : otherPatterns ->
219+ (:)
220+ <$> canonicalize env (Can.DIndex 0 destructor) pattern
221+ <*> canonicalizeList env (Can.DIndex 1 destructor) otherPatterns
src/Canonicalize/Sort.hsdeleted−346
@@ -1,346 +0,0 @@
1−{-# OPTIONS_GHC -Wall #-}
2−module Canonicalize.Sort (definitions) where
3−
4−import qualified Data.Foldable as F
5−import qualified Data.Graph as Graph
6−import qualified Data.Map as Map
7−import qualified Data.Maybe as Maybe
8−import qualified Data.Set as Set
9−import Data.Text (Text)
10−
11−import qualified AST.Expression.Canonical as C
12−import qualified AST.Pattern as P
13−import qualified AST.Variable as V
14−import qualified Reporting.Annotation as A
15−import qualified Reporting.Error.Canonicalize as E
16−import qualified Reporting.Result as R
17−
18−
19−
20−-- SORT DEFINITIONS
21−
22−
23−definitions :: (Monoid i) => C.Expr -> R.Result i w E.Error C.Expr
24−definitions expression =
25− let
26− (R.Result _ warnings answer) =
27− reorder expression
28− in
29− R.Result mempty warnings answer
30−
31−
32−data LocalVars =
33− LocalVars
34− { _immediate :: Set.Set Text
35− , _delayed :: Set.Set Text
36− , _tags :: Set.Set Text
37− }
38−
39−
40−instance Monoid LocalVars where
41− mempty =
42− LocalVars Set.empty Set.empty Set.empty
43−
44− mappend (LocalVars i1 d1 t1) (LocalVars i2 d2 t2) =
45− LocalVars (Set.union i1 i2) (Set.union d1 d2) (Set.union t1 t2)
46−
47−
48−addTag :: Text -> a -> R.Result LocalVars w e a
49−addTag name value =
50− R.accumulate (LocalVars Set.empty Set.empty (Set.singleton name)) value
51−
52−
53−addImmediate :: V.Canonical -> a -> R.Result LocalVars w e a
54−addImmediate (V.Canonical home name) value =
55− case home of
56− V.Local ->
57− R.accumulate (LocalVars (Set.singleton name) Set.empty Set.empty) value
58−
59− V.TopLevel _ ->
60− R.accumulate (LocalVars (Set.singleton name) Set.empty Set.empty) value
61−
62− V.BuiltIn ->
63− return value
64−
65− V.Module _ ->
66− return value
67−
68−
69−capture :: P.Canonical -> R.Result LocalVars w e a -> R.Result LocalVars w e a
70−capture pattern result =
71− captureVars (P.boundVarSet pattern) result
72−
73−
74−captureVars :: Set.Set Text -> R.Result LocalVars w e a -> R.Result LocalVars w e a
75−captureVars bound (R.Result (LocalVars immediate delayed tags) warnings result) =
76− let
77− localVars =
78− LocalVars (Set.difference immediate bound) (Set.difference delayed bound) tags
79− in
80− R.Result localVars warnings result
81−
82−
83−delay :: R.Result LocalVars w e a -> R.Result LocalVars w e a
84−delay (R.Result (LocalVars immediate delayed tags) warnings result) =
85− R.Result (LocalVars Set.empty (Set.union immediate delayed) tags) warnings result
86−
87−
88−
89−-- REORDER EXPRESSIONS
90−
91−
92−reorder :: C.Expr -> R.Result LocalVars w E.Error C.Expr
93−reorder (A.A region expression) =
94− A.A region <$>
95− case expression of
96− C.Var var ->
97− addImmediate var expression
98−
99− C.Lambda pattern body ->
100− delay $
101− bindingReorder C.Lambda (pattern, body)
102−
103− C.Binop op leftExpr rightExpr ->
104− do binop <- C.Binop op <$> reorder leftExpr <*> reorder rightExpr
105− addImmediate op binop
106−
107− C.Case expr cases ->
108− C.Case <$> reorder expr <*> traverse (bindingReorder (,)) cases
109−
110− C.Ctor ctor@(V.Canonical _ name) exprs ->
111− addTag name =<< (C.Ctor ctor <$> traverse reorder exprs)
112−
113− -- Just pipe the reorder though
114− C.Literal _ ->
115− return expression
116−
117− C.List es ->
118− C.List <$> traverse reorder es
119−
120− C.App func arg ->
121− C.App <$> reorder func <*> reorder arg
122−
123− C.If branches finally ->
124− C.If
125− <$> traverse (\(cond,branch) -> (,) <$> reorder cond <*> reorder branch) branches
126− <*> reorder finally
127−
128− C.Access record field ->
129− C.Access
130− <$> reorder record
131− <*> return field
132−
133− C.Update record fields ->
134− C.Update
135− <$> reorder record
136− <*> traverse (traverse reorder) fields
137−
138− C.Record fields ->
139− C.Record
140− <$> traverse (traverse reorder) fields
141−
142− C.Cmd _ _ ->
143− return expression
144−
145− C.Sub _ _ ->
146− return expression
147−
148− C.OutgoingPort _ _ ->
149− return expression
150−
151− C.IncomingPort _ _ ->
152− return expression
153−
154− C.Program _ _ ->
155− error "DANGER - Program AST nodes should not be in def sorting."
156−
157− C.SaveEnv _ _ ->
158− return expression
159−
160− C.GLShader _ _ _ ->
161− return expression
162−
163− -- Actually do some reordering
164− C.Let defs body ->
165− case reorderDefs defs of
166− R.Result () warnings (R.Err errors) ->
167− R.Result mempty warnings (R.Err errors)
168−
169− R.Result () warnings (R.Ok (boundVars, defGroups, defLocals)) ->
170− captureVars boundVars $
171− do _ <- R.Result mempty warnings (R.Ok ())
172− newBody <- reorder body
173− R.accumulate defLocals $ A.drop $
174− foldr (\defGroup expr -> A.A region (C.Let defGroup expr)) newBody defGroups
175−
176−
177−
178−-- BINDINGS
179−
180−
181−bindingReorder
182− :: (P.Canonical -> C.Expr -> a)
183− -> (P.Canonical, C.Expr)
184− -> R.Result LocalVars w E.Error a
185−bindingReorder func (pattern, expr) =
186− do answer <- func pattern <$> capture pattern (reorder expr)
187− addPatternTags pattern answer
188−
189−
190−
191−-- FREE CONSTRUCTORS
192−
193−
194−addPatternTags :: P.Canonical -> a -> R.Result LocalVars w e a
195−addPatternTags pattern value =
196− R.accumulate (LocalVars Set.empty Set.empty (getPatternTags pattern)) value
197−
198−
199−getPatternTags :: P.Canonical -> Set.Set Text
200−getPatternTags (A.A _ pattern) =
201− case pattern of
202− P.Var _ ->
203− Set.empty
204−
205− P.Alias _ subPattern ->
206− getPatternTags subPattern
207−
208− P.Record _ ->
209− Set.empty
210−
211− P.Anything ->
212− Set.empty
213−
214− P.Literal _ ->
215− Set.empty
216−
217− P.Ctor (V.Canonical home name) patterns ->
218− let
219− freeCtors =
220− Set.unions (map getPatternTags patterns)
221− in
222− case home of
223− V.Local ->
224− Set.insert name freeCtors
225−
226− V.TopLevel _ ->
227− Set.insert name freeCtors
228−
229− V.BuiltIn ->
230− freeCtors
231−
232− V.Module _ ->
233− freeCtors
234−
235−
236−
237−-- REORDER DEFINITIONS
238−
239−
240−reorderDefs
241− :: [C.Def]
242− -> R.Result () w E.Error (Set.Set Text, [[C.Def]], LocalVars)
243−reorderDefs defs =
244− do rawNodes <- sequenceA $ zipWith toRawNode [0..] defs
245− let boundVarDict = toBoundVarDict rawNodes
246− _ <- detectLoops boundVarDict rawNodes
247− return $ groupDefs boundVarDict rawNodes
248−
249−
250−toRawNode :: Int -> C.Def -> R.Result () w E.Error (C.Def, Int, LocalVars)
251−toRawNode index (C.Def region pattern body maybeType) =
252− let
253− (R.Result localVars warnings answer) =
254− addPatternTags pattern =<< reorder body
255−
256− toRawNodeHelp newBody =
257− ( C.Def region pattern newBody maybeType, index, localVars )
258− in
259− toRawNodeHelp <$> R.Result () warnings answer
260−
261−
262−toBoundVarDict :: [(C.Def, Int, a)] -> Map.Map Text Int
263−toBoundVarDict defAndDeps =
264− Map.fromList (concatMap toBoundVarDictHelp defAndDeps)
265−
266−
267−toBoundVarDictHelp :: (C.Def, Int, a) -> [(Text, Int)]
268−toBoundVarDictHelp (C.Def _ pattern _ _, key, _) =
269− map (\(A.A _ name) -> (name, key)) (P.boundVars pattern)
270−
271−
272−
273−-- BUILD GRAPHS
274−
275−
276−toNode
277− :: (deps -> [Text])
278− -> Map.Map Text Int
279− -> (C.Def, Int, deps)
280− -> (C.Def, Int, [Int])
281−toNode toVars boundVarDict (def, index, deps) =
282− let
283− localDeps =
284− Maybe.mapMaybe (\var -> Map.lookup var boundVarDict) (toVars deps)
285− in
286− ( def, index, localDeps )
287−
288−
289−immediateOnly :: LocalVars -> [Text]
290−immediateOnly (LocalVars immediate _ _) =
291− Set.toList immediate
292−
293−
294−allVars :: LocalVars -> [Text]
295−allVars (LocalVars immediate delayed tags) =
296− Set.toList immediate ++ Set.toList delayed ++ Set.toList tags
297−
298−
299−
300−-- DETECT LOOPS
301−
302−
303−detectLoops
304− :: Map.Map Text Int
305− -> [(C.Def, Int, LocalVars)]
306− -> R.Result () w E.Error ()
307−detectLoops boundVarDict rawNodes =
308− F.traverse_ detectLoopsHelp $
309− Graph.stronglyConnComp $
310− map (toNode immediateOnly boundVarDict) rawNodes
311−
312−
313−detectLoopsHelp :: Graph.SCC C.Def -> R.Result () w E.Error ()
314−detectLoopsHelp scc =
315− case scc of
316− Graph.AcyclicSCC _ ->
317− R.ok ()
318−
319− Graph.CyclicSCC defs ->
320− case defs of
321− [] ->
322− R.ok ()
323−
324− def@(C.Def region (A.A nameRegion _) _ _) : rest ->
325− R.throw region $ E.BadRecursion nameRegion def rest
326−
327−
328−
329−-- GROUP DEFINITIONS
330−
331−
332−groupDefs
333− :: Map.Map Text Int
334− -> [(C.Def, Int, LocalVars)]
335− -> ( Set.Set Text, [[C.Def]], LocalVars )
336−groupDefs boundVarDict rawNodes =
337− let
338− allLocalVars =
339− mconcat (map (\(_, _, localVars) -> localVars) rawNodes)
340−
341− defGroups =
342− map Graph.flattenSCC $
343− Graph.stronglyConnComp $
344− map (toNode allVars boundVarDict) rawNodes
345− in
346− ( Map.keysSet boundVarDict, defGroups, allLocalVars )
src/Canonicalize/Type.hs+25−10
@@ -12,22 +12,37 @@ import qualified AST.Type as Type
1212import qualified Canonicalize.Environment.Dups as Dups
1313import qualified Canonicalize.Environment.Internals as Env
1414import qualified Reporting.Annotation as A
15+import qualified Reporting.Error.Canonicalize as Error
1516import qualified Reporting.Result as Result
17+import qualified Reporting.Warning as Warning
18+
19+
20+
21+-- RESULT
22+
23+
24+type Result i a =
25+ Result.Result i Warning.Warning Error.Error a
1626
1727
1828
1929-- CANONICALIZE TYPES
2030
2131
22−canonicalize :: Env.Env -> Type.Raw -> Env.Result Type.Canonical
23−canonicalize env (A.A _ tipe) =
32+canonicalize :: Env.Env -> Type.Raw -> Result () (A.Located Type.Canonical)
33+canonicalize env tipe@(A.A region _) =
34+ A.A region <$> canonicalizeHelp env tipe
35+
36+
37+canonicalizeHelp :: Env.Env -> Type.Raw -> Result () Type.Canonical
38+canonicalizeHelp env (A.A _ tipe) =
2439 case tipe of
2540 Type.RVar x ->
2641 Result.ok (Type.Var x)
2742
2843 Type.RType region maybePrefix name args ->
2944 do info <- Env.findType region env maybePrefix name (length args)
30− cargs <- traverse (canonicalize env) args
45+ cargs <- traverse (canonicalizeHelp env) args
3146 return $
3247 case info of
3348 Env.Alias home argNames aliasedType ->
@@ -38,20 +53,20 @@ canonicalize env (A.A _ tipe) =
3853
3954 Type.RLambda a b ->
4055 Type.Lambda
41− <$> canonicalize env a
42− <*> canonicalize env b
56+ <$> canonicalizeHelp env a
57+ <*> canonicalizeHelp env b
4358
4459 Type.RRecord fields ext ->
4560 do fieldDict <- Dups.checkFields fields
4661 Type.Record
47− <$> Map.traverseWithKey (\_ t -> canonicalize env t) fieldDict
48− <*> traverse (canonicalize env) ext
62+ <$> Map.traverseWithKey (\_ t -> canonicalizeHelp env t) fieldDict
63+ <*> traverse (canonicalizeHelp env) ext
4964
5065 Type.RUnit ->
5166 Result.ok Type.Unit
5267
5368 Type.RTuple a b cs ->
5469 Type.Tuple
55− <$> canonicalize env a
56− <*> canonicalize env b
57− <*> traverse (canonicalize env) cs
70+ <$> canonicalizeHelp env a
71+ <*> canonicalizeHelp env b
72+ <*> traverse (canonicalizeHelp env) cs