1{-# OPTIONS_GHC -Wall #-}
2module Canonicalize.Pattern
11import Control.Monad (zipWithM)
12import qualified Data.Map.Strict as Map
14import qualified AST.Canonical as Can
15import qualified AST.Source as Src
16import qualified AST.Valid as Valid
17import qualified Canonicalize.Environment as Env
18import qualified Canonicalize.Environment.Dups as Dups
19import qualified Data.Bag as Bag
20import qualified Data.Index as Index
21import qualified Elm.Name as N
22import qualified Reporting.Annotation as A
23import qualified Reporting.Error.Canonicalize as Error
24import qualified Reporting.Region as R
25import qualified Reporting.Result as Result
26import qualified Reporting.Warning as Warning
34 Result.Result i Warning.Warning Error.Error
41canonicalize :: Env.Env -> Index.ZeroBased -> Src.Pattern -> Result () (Can.Pattern, Can.Destructors)
42canonicalize env index pattern =
43 case process env (Can.DRoot index) pattern of
44 Result.Result bag warnings (Result.Ok cpattern) ->
45 do let toError name () () = Error.DuplicateArg name
46 destructors <- Dups.detect toError (Bag.toList bag)
47 Result.Result () warnings $ Result.Ok (cpattern, destructors)
49 Result.Result _ warnings (Result.Err err) ->
50 Result.Result () warnings (Result.Err err)
57canonicalizeArgs :: Env.Env -> [Src.Pattern] -> Result () Can.Args
58canonicalizeArgs env patterns =
59 case Index.indexedTraverse (canonicalizeArg env) patterns of
60 Result.Result bag warnings (Result.Ok args) ->
61 do let toError name () () = Error.DuplicateArg name
62 destructors <- Dups.detect toError (Bag.toList bag)
63 Result.Result () warnings $ Result.Ok $
64 Can.Args args destructors
66 Result.Result _ warnings (Result.Err err) ->
67 Result.Result () warnings (Result.Err err)
70canonicalizeArg :: Env.Env -> Index.ZeroBased -> Src.Pattern -> Result Bag Can.Arg
71canonicalizeArg env index pattern =
72 Can.Arg index <$> process env (Can.DRoot index) pattern
76-- CANONICALIZE BINDINGS
80 = Define R.Region Int (A.Located N.Name) [Src.Pattern] Valid.Expr (Maybe Src.Type)
81 | Destruct R.Region Int Can.Pattern Can.Destructors Valid.Expr
84canonicalizeBindings :: Env.Env -> [Valid.Def] -> Result () ( [Binding], Map.Map N.Name (A.Located Int) )
85canonicalizeBindings env defs =
86 case zipWithM (canonicalizeBinding env) defs [ 0 .. length defs ] of
87 Result.Result bag warnings (Result.Ok cdefs) ->
88 do let toError name () () = Error.DuplicateBindingName name
89 nodes <- Dups.detect toError (Bag.toList bag)
90 Result.Result () warnings (Result.Ok (cdefs, nodes))
92 Result.Result _ warnings (Result.Err err) ->
93 Result.Result () warnings (Result.Err err)
97 Bag.Bag ( N.Name, [Dups.Info () (A.Located Int)] )
100canonicalizeBinding :: Env.Env -> Valid.Def -> Int -> Result KeyBag Binding
101canonicalizeBinding env def index =
103 Valid.Define region aname@(A.A reg name) args body maybeType ->
104 let info = Dups.info name reg () (A.A region index) in
105 Result.accumulate (Bag.one info) $
106 Define region index aname args body maybeType
108 Valid.Destruct region pattern body ->
109 case process env (Can.DRoot Index.first) pattern of
110 Result.Result bag warnings (Result.Ok cpattern) ->
111 do let toError name () () = Error.DuplicateBindingName name
112 destructors <- Result.untracked (Dups.detect toError (Bag.toList bag))
113 Result.Result (toKeyBag index bag) warnings $ Result.Ok $
114 Destruct region index cpattern destructors body
116 Result.Result bag warnings (Result.Err err) ->
117 Result.Result (toKeyBag index bag) warnings (Result.Err err)
120toKeyBag :: Int -> Bag -> KeyBag
123 redoInfo (Dups.Info region () _) =
124 Dups.Info region () (A.A region index)
126 replaceWithIndex ( name, infos ) =
127 ( name, map redoInfo infos )
129 Bag.map replaceWithIndex bag
137 Bag.Bag (N.Name, [Dups.Info () (A.Located Can.Destructor)])
140process :: Env.Env -> Can.Destructor -> Src.Pattern -> Result Bag Can.Pattern
141process env destructor (A.A region pattern) =
145 Result.ok Can.PAnything
149 (Bag.one (Dups.info name region () (A.A region destructor)))
152 Src.PRecord fields ->
154 fieldToInfo (A.A reg name) =
155 Dups.info name reg () (A.A reg (Can.DField name destructor))
158 (Bag.fromList fieldToInfo fields)
159 (Can.PRecord (map A.drop fields))
166 <$> process env (Can.DIndex Index.first destructor) a
167 <*> process env (Can.DIndex Index.second destructor) b
168 <*> processTuple region env destructor cs
170 Src.PCtor nameRegion maybePrefix name patterns ->
172 toCanonicalArg index ptrn tipe =
173 Can.PatternCtorArg index tipe
174 <$> process env (Can.DIndex index destructor) ptrn
176 do (Env.Pattern home tipe vars args) <- Env.findPattern nameRegion env maybePrefix name
177 verifiedList <- Index.indexedZipWithA toCanonicalArg patterns args
179 Index.LengthMatch cargs ->
180 Result.ok $ Can.PCtor home tipe vars name cargs
182 Index.LengthMismatch actualLength expectedLength ->
183 Result.throw region (error "TODO" actualLength expectedLength)
185 Src.PList patterns ->
186 Can.PList <$> processList env destructor patterns
188 Src.PCons first rest ->
190 <$> process env (Can.DIndex Index.first destructor) first
191 <*> process env (Can.DIndex Index.second destructor) rest
193 Src.PAlias ptrn (A.A reg name) ->
194 do cpattern <- process env destructor ptrn
195 let info = Dups.info name reg () (A.A reg destructor)
196 Result.accumulate (Bag.one info) (Can.PAlias cpattern name)
199 Result.ok (Can.PChr chr)
202 Result.ok (Can.PStr str)
205 Result.ok (Can.PInt int)
208processTuple :: R.Region -> Env.Env -> Can.Destructor -> [Src.Pattern] -> Result Bag (Maybe Can.Pattern)
209processTuple tupleRegion env destructor extras =
215 Just <$> process env (Can.DIndex Index.third destructor) three
218 let (A.A r1 _, A.A r2 _) = (head others, last others) in
219 Result.throw tupleRegion (Error.TupleLargerThanThree (R.merge r1 r2))
222processList :: Env.Env -> Can.Destructor -> [Src.Pattern] -> Result Bag [Can.Pattern]
223processList env destructor list =
228 pattern : otherPatterns ->
230 <$> process env (Can.DIndex Index.first destructor) pattern
231 <*> processList env (Can.DIndex Index.second destructor) otherPatterns
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list