1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
15import qualified Data.Map as Map
16import qualified Data.Maybe as Maybe
17import Data.Monoid ((<>))
19import qualified AST.Module.Name as ModuleName
20import qualified Data.Bag as Bag
21import qualified Elm.Name as N
22import qualified Reporting.Helpers as H
23import qualified Reporting.Render.Type as RT
31 = Lambda Type Type [Type]
38 | Type ModuleName.Canonical N.Name [Type]
39 | Record (Map.Map N.Name Type) Extension
41 | Tuple Type Type (Maybe Type)
42 | Alias ModuleName.Canonical N.Name [(N.Name, Type)] Type
51iteratedDealias :: Type -> Type
54 Alias _ _ _ realType ->
55 iteratedDealias realType
65type Localizer = Map.Map (ModuleName.Canonical, N.Name) String
68nameToDoc :: Localizer -> ModuleName.Canonical -> N.Name -> H.Doc
69nameToDoc dict home@(ModuleName.Canonical _ moduleName) name =
70 case Map.lookup (home, name) dict of
72 H.nameToDoc moduleName <> "." <> H.nameToDoc name
78toDoc :: Localizer -> RT.Context -> Type -> H.Doc
83 (toDoc dict RT.Func a)
84 (toDoc dict RT.Func b)
85 (map (toDoc dict RT.Func) cs)
105 Type home name args ->
107 (nameToDoc dict home name)
108 (map (toDoc dict RT.App) args)
112 entryToDocs (fieldName, fieldType) =
113 ( H.nameToDoc fieldName, toDoc dict RT.None fieldType )
116 map entryToDocs (Map.toList fields)
118 RT.record fieldDocs $
121 FlexOpen x -> Just (H.nameToDoc x)
122 RigidOpen x -> Just (H.nameToDoc x)
130 (toDoc dict RT.None a)
131 (toDoc dict RT.None b)
132 (map (toDoc dict RT.None) (Maybe.maybeToList maybeC))
134 Alias home name args _ ->
136 (nameToDoc dict home name)
137 (map (toDoc dict RT.App . snd) args)
144toDiffDocs :: Localizer -> Type -> Type -> (H.Doc, H.Doc, [Problem])
146 case diff dict RT.None a b of
150 Different aDoc bDoc problems ->
151 (aDoc, bDoc, Bag.toList problems)
156 | Different a a (Bag.Bag Problem)
159instance Functor Diff where
162 Similar a b -> Similar (func a) (func b)
163 Different a b ps -> Different (func a) (func b) ps
166instance Applicative Diff where
172 Similar aFunc bFunc ->
174 Similar a b -> Similar (aFunc a) (bFunc b)
175 Different a b ps -> Different (aFunc a) (bFunc b) ps
177 Different aFunc bFunc ps ->
179 Similar a b -> Different (aFunc a) (bFunc b) ps
180 Different a b ps2 -> Different (aFunc a) (bFunc b) (Bag.append ps ps2)
190 | ReturnMismatch Int Int
192 | BadFlexSuper N.Name Type
193 | BadRigidVar N.Name Type
194 | BadRigidSuper N.Name Type
201diff :: Localizer -> RT.Context -> Type -> Type -> Diff H.Doc
202diff dict ctx tipe1 tipe2 =
203 case (tipe1, tipe2) of
204 (FlexVar x, FlexVar y) | x == y -> pure (H.nameToDoc x)
205 (FlexSuper x, FlexSuper y) | x == y -> pure (H.nameToDoc x)
206 (RigidVar x, RigidVar y) | x == y -> pure (H.nameToDoc x)
207 (RigidSuper x, RigidSuper y) | x == y -> pure (H.nameToDoc x)
209 (Infinite, Infinite) -> pure "∞"
210 (Error, Error) -> pure "?"
211 (Unit, Unit) -> pure "()"
213 (Tuple a b maybeC, Tuple x y maybeZ) ->
215 <$> diff dict RT.None a x
216 <*> diff dict RT.None b y
218 case (maybeC, maybeZ) of
219 (Nothing, Nothing) -> pure []
220 (Just c , Nothing) -> Different [H.dullyellow (toDoc dict RT.None c)] [] (Bag.one TupleMismatch)
221 (Nothing, Just z ) -> Different [] [H.dullyellow (toDoc dict RT.None z)] (Bag.one TupleMismatch)
222 (Just c , Just z ) -> (:[]) <$> diff dict RT.None c z
224 (Record fields1 ext1, Record fields2 ext2) -> diffRecord dict fields1 ext1 fields2 ext2
226 (Type home1 name1 args1, Type home2 name2 args2) | home1 == home2 && name1 == name2 ->
227 RT.apply ctx (nameToDoc dict home1 name1) <$>
228 sequenceA (zipWith (diff dict RT.App) args1 args2)
230 (Alias home1 name1 args1 _, Alias home2 name2 args2 _) | home1 == home2 && name1 == name2 ->
231 RT.apply ctx (nameToDoc dict home1 name1) <$>
232 sequenceA (zipWith (diff dict RT.App) (map snd args1) (map snd args2))
234 (Alias _ _ _ alias1, other) -> diff dict ctx alias1 other
235 (other, Alias _ _ _ alias2) -> diff dict ctx other alias2
237 (Lambda a b cs, Lambda x y zs) -> diffLambda dict ctx (a:b:cs) (x:y:zs)
238 (Lambda a b cs, result ) -> diffLambda dict ctx (a:b:cs) [result]
239 (result , Lambda x y zs) -> diffLambda dict ctx [result] (x:y:zs)
241 (FlexVar x, other) -> Similar (H.nameToDoc x) (toDoc dict ctx other)
242 (other, FlexVar x) -> Similar (toDoc dict ctx other) (H.nameToDoc x)
246 doc1 = H.dullyellow (toDoc dict ctx tipe1)
247 doc2 = H.dullyellow (toDoc dict ctx tipe2)
249 Different doc1 doc2 $
251 (RigidVar x, other) -> Bag.one $ BadRigidVar x other
252 (FlexSuper x, other) -> Bag.one $ BadFlexSuper x other
253 (RigidSuper x, other) -> Bag.one $ BadRigidSuper x other
254 (other, RigidVar x) -> Bag.one $ BadRigidVar x other
255 (other, FlexSuper x) -> Bag.one $ BadFlexSuper x other
256 (other, RigidSuper x) -> Bag.one $ BadRigidSuper x other
258 (Type home1 name1 [], Type home2 name2 []) | isIntFloat home1 name1 home2 name2 -> Bag.one IntFloat
263isIntFloat :: ModuleName.Canonical -> N.Name -> ModuleName.Canonical -> N.Name -> Bool
264isIntFloat home1 name1 home2 name2 =
265 home1 == ModuleName.basics
267 home2 == ModuleName.basics
270 (name1 == N.int && name2 == N.float)
272 (name1 == N.float && name2 == N.int)
281-- INVARIANT: notNull types1 && notNull types2
283diffLambda :: Localizer -> RT.Context -> [Type] -> [Type] -> Diff H.Doc
284diffLambda dict ctx types1 types2 =
286 (result1:revArgs1) = reverse types1
287 (result2:revArgs2) = reverse types2
289 numArgs1 = length revArgs1
290 numArgs2 = length revArgs2
292 resultDiff = diff dict RT.Func result1 result2
295 Similar resultDoc1 resultDoc2 ->
296 if numArgs1 == numArgs2 then
297 (\resultDoc revArgsDoc ->
298 let (x:y:zs) = reverse (resultDoc:revArgsDoc) in
302 <*> sequenceA (zipWith (diff dict RT.Func) revArgs1 revArgs2)
304 else if numArgs1 < numArgs2 then
305 diffArgMismatch dict ctx revArgs1 resultDoc1 revArgs2 resultDoc2
308 diffArgMismatch dict ctx revArgs2 resultDoc2 revArgs1 resultDoc1
310 Different resultDoc1 resultDoc2 problems ->
312 (x1:y1:zs1) = reverse (resultDoc1 : map (toDoc dict RT.Func) revArgs1)
313 (x2:y2:zs2) = reverse (resultDoc2 : map (toDoc dict RT.Func) revArgs2)
316 (RT.lambda ctx x1 y1 zs1)
317 (RT.lambda ctx x2 y2 zs2)
318 (Bag.append (Bag.one (ReturnMismatch numArgs1 numArgs2)) problems)
322-- INVARIANT: notNull shortRevArgs && notNull longRevArgs
324diffArgMismatch :: Localizer -> RT.Context -> [Type] -> H.Doc -> [Type] -> H.Doc -> Diff H.Doc
325diffArgMismatch dict ctx shortRevArgs shortResult longRevArgs longResult =
326 case toGreedyMatch dict shortRevArgs longRevArgs (GreedyMatch [] []) of
327 Just (GreedyMatch shortRevArgDocs longRevArgDocs) ->
329 (a:b:cs) = reverse (shortResult:shortRevArgDocs)
330 (x:y:zs) = reverse (longResult:longRevArgDocs)
333 (RT.lambda ctx a b cs)
334 (RT.lambda ctx x y zs)
335 (Bag.one (MissingArgs (length longRevArgs - length shortRevArgs)))
338 case toGreedyMatch dict (reverse shortRevArgs) (reverse longRevArgs) (GreedyMatch [] []) of
339 Just (GreedyMatch shortArgDocs longArgDocs) ->
341 (a:b:cs) = shortArgDocs ++ [shortResult]
342 (x:y:zs) = longArgDocs ++ [longResult ]
345 (RT.lambda ctx a b cs)
346 (RT.lambda ctx x y zs)
347 (Bag.one (MissingArgs (length longRevArgs - length shortRevArgs)))
352 H.dullyellow (toDoc dict RT.Func tipe)
354 (a:b:cs) = reverse (shortResult : map toYellowDoc shortRevArgs)
355 (x:y:zs) = reverse (longResult : map toYellowDoc longRevArgs )
358 (RT.lambda ctx a b cs)
359 (RT.lambda ctx x y zs)
360 (Bag.one (MissingArgs (length longRevArgs - length shortRevArgs)))
368 GreedyMatch [H.Doc] [H.Doc]
371toGreedyMatch :: Localizer -> [Type] -> [Type] -> GreedyMatch -> Maybe GreedyMatch
372toGreedyMatch dict shorterArgs longerArgs match@(GreedyMatch shorterDocs longerDocs) =
375 H.dullyellow (toDoc dict RT.Func tipe)
377 case (shorterArgs, longerArgs) of
379 case diff dict RT.Func x y of
381 toGreedyMatch dict xs ys $
382 GreedyMatch (a:shorterDocs) (b:longerDocs)
385 toGreedyMatch dict shorterArgs ys $
386 GreedyMatch shorterDocs (toYellowDoc y : longerDocs)
392 Just (GreedyMatch shorterDocs (map toYellowDoc longerArgs))
402diffRecord :: Localizer -> Map.Map N.Name Type -> Extension -> Map.Map N.Name Type -> Extension -> Diff H.Doc
403diffRecord dict fields1 ext1 fields2 ext2 =
404 error "TODO" dict fields1 ext1 fields2 ext2
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