@@ -1,7 +1,7 @@
1module Type.Unify (unify) where
1module Type.Unify (unify) where
3import Control.Applicative ((<|>))
3import Control.Applicative ((<|>))
4−import Control.Monad.Error (ErrorT, throwError, runErrorT)
4+import Control.Monad.Except (ExceptT, throwError, runExceptT)
5import Control.Monad.State as State
5import Control.Monad.State as State
6import qualified Data.List as List
6import qualified Data.List as List
7import qualified Data.Map as Map
7import qualified Data.Map as Map
@@ -9,52 +9,55 @@ import qualified Data.Maybe as Maybe
9import qualified Data.UnionFind.IO as UF
9import qualified Data.UnionFind.IO as UF
10import Text.PrettyPrint (render)
10import Text.PrettyPrint (render)
12−import qualified AST.Annotation as A
13import qualified AST.Variable as Var
12import qualified AST.Variable as Var
13+import qualified Reporting.Region as R
14+import qualified Reporting.Error.Type as Error
14import qualified Type.State as TS
15import qualified Type.State as TS
15import Type.Type
16import Type.Type
16import Type.PrettyPrint
17import Type.PrettyPrint
17−import qualified Type.Hint as Hint
18import Elm.Utils ((|>))
18import Elm.Utils ((|>))
21−unify :: A.Region -> Variable -> Variable -> StateT TS.SolverState IO ()
21+unify :: R.Region -> Variable -> Variable -> StateT TS.SolverState IO ()
22unify region variable1 variable2 =
22unify region variable1 variable2 =
23− do result <- runErrorT (unifyHelp region variable1 variable2)
23+ do result <- runExceptT (unifyHelp variable1 variable2)
24− either TS.addHint return result
24+ case result of
29+ TS.addError region (Error.Mismatch mismatch)
27-- ACTUALLY UNIFY STUFF
32-- ACTUALLY UNIFY STUFF
29−type Unify = ErrorT Hint.Hint (StateT TS.SolverState IO)
34+type Unify = ExceptT Error.Mismatch (StateT TS.SolverState IO)
34− -> Maybe String
38+ :: Maybe String
35 -> UF.Point Descriptor
39 -> UF.Point Descriptor
36 -> UF.Point Descriptor
40 -> UF.Point Descriptor
37 -> Unify a
41 -> Unify a
38−typeError region hint t1 t2 =
42+typeError hint leftType rightType =
39− do msg <- liftIO (Hint.create region hint t1 t2)
43+ do leftSrcType <- liftIO (toSrcType leftType)
40− throwError msg
44+ rightSrcType <- liftIO (toSrcType rightType)
45+ throwError (Error.MismatchInfo hint leftSrcType rightSrcType)
43−unifyHelp :: A.Region -> Variable -> Variable -> Unify ()
48+unifyHelp :: Variable -> Variable -> Unify ()
44−unifyHelp region variable1 variable2 = do
49+unifyHelp variable1 variable2 =
45− equivalent <- liftIO $ UF.equivalent variable1 variable2
50+ do equivalent <- liftIO $ UF.equivalent variable1 variable2
46− if equivalent
51+ if equivalent
47− then return ()
52+ then return ()
48− else actuallyUnify region variable1 variable2
53+ else actuallyUnify variable1 variable2
51−actuallyUnify :: A.Region -> Variable -> Variable -> Unify ()
56+actuallyUnify :: Variable -> Variable -> Unify ()
52−actuallyUnify region variable1 variable2 = do
57+actuallyUnify variable1 variable2 = do
53 desc1 <- liftIO $ UF.descriptor variable1
58 desc1 <- liftIO $ UF.descriptor variable1
54 desc2 <- liftIO $ UF.descriptor variable2
59 desc2 <- liftIO $ UF.descriptor variable2
55− let unifyHelp' = unifyHelp region
57− (name', flex', rank', alias') = combinedDescriptors desc1 desc2
60+ let (name', flex', rank', alias') = combinedDescriptors desc1 desc2
59 merge1 :: Unify ()
62 merge1 :: Unify ()
@@ -100,7 +103,7 @@ actuallyUnify region variable1 variable2 = do
101 flexAndUnify v =
104 flexAndUnify v =
102 do liftIO $ UF.modifyDescriptor v $ \desc -> desc { flex = Flexible }
105 do liftIO $ UF.modifyDescriptor v $ \desc -> desc { flex = Flexible }
103− unifyHelp' variable1 variable2
106+ unifyHelp variable1 variable2
105 unifyNumber svar (Var.Canonical home name) =
108 unifyNumber svar (Var.Canonical home name) =
106 case home of
109 case home of
@@ -109,17 +112,17 @@ actuallyUnify region variable1 variable2 = do
110 let hint = "Looks like something besides an Int or Float is being used as a number."
113 let hint = "Looks like something besides an Int or Float is being used as a number."
112− typeError region (Just hint) variable1 variable2
115+ typeError (Just hint) variable1 variable2
114 comparableError maybe =
117 comparableError maybe =
115− typeError region (Just $ Maybe.fromMaybe msg maybe) variable1 variable2
118+ typeError (Just $ Maybe.fromMaybe msg maybe) variable1 variable2
118 "Looks like you want something comparable, but the only valid comparable\n\
121 "Looks like you want something comparable, but the only valid comparable\n\
119 \types are Int, Float, Char, String, lists, or tuples."
122 \types are Int, Float, Char, String, lists, or tuples."
121 appendableError maybe =
124 appendableError maybe =
122− typeError region (Just $ Maybe.fromMaybe msg maybe) variable1 variable2
125+ typeError (Just $ Maybe.fromMaybe msg maybe) variable1 variable2
125 "Looks like you want something appendable, but the only Strings, Lists,\n\
128 "Looks like you want something appendable, but the only Strings, Lists,\n\
@@ -139,7 +142,7 @@ actuallyUnify region variable1 variable2 = do
140 List v ->
143 List v ->
141 do flexAndUnify varSuper
144 do flexAndUnify varSuper
142− unifyHelp' v =<< liftIO (variable $ Is Comparable)
145+ unifyHelp v =<< liftIO (variable $ Is Comparable)
145 | length vs > 6 ->
148 | length vs > 6 ->
@@ -147,7 +150,7 @@ actuallyUnify region variable1 variable2 = do
147 | otherwise ->
150 | otherwise ->
148 do flexAndUnify varSuper
151 do flexAndUnify varSuper
149 cmpVars <- liftIO $ forM [1..length vs] $ \_ -> variable (Is Comparable)
152 cmpVars <- liftIO $ forM [1..length vs] $ \_ -> variable (Is Comparable)
150− zipWithM_ unifyHelp' vs cmpVars
153+ zipWithM_ unifyHelp vs cmpVars
152 unifyAppendable varSuper varFlex =
155 unifyAppendable varSuper varFlex =
153 do struct <- liftIO $ collectApps varFlex
156 do struct <- liftIO $ collectApps varFlex
@@ -156,7 +159,7 @@ actuallyUnify region variable1 variable2 = do
156 _ -> appendableError Nothing
159 _ -> appendableError Nothing
158 rigidError var =
161 rigidError var =
159− typeError region (Just hint) variable1 variable2
162+ typeError (Just hint) variable1 variable2
162 "Could not unify rigid type variable '" ++ render (pretty Never var) ++ "'.\n" ++
165 "Could not unify rigid type variable '" ++ render (pretty Never var) ++ "'.\n" ++
@@ -187,7 +190,7 @@ actuallyUnify region variable1 variable2 = do
188 (Rigid, _, _, _) -> rigidError variable1
191 (Rigid, _, _, _) -> rigidError variable1
189 (_, Rigid, _, _) -> rigidError variable2
192 (_, Rigid, _, _) -> rigidError variable2
190− _ -> typeError region Nothing variable1 variable2
193+ _ -> typeError Nothing variable1 variable2
192 case (structure desc1, structure desc2) of
195 case (structure desc1, structure desc2) of
193 (Nothing, Nothing) | flex desc1 == Flexible && flex desc1 == Flexible ->
196 (Nothing, Nothing) | flex desc1 == Flexible && flex desc1 == Flexible ->
@@ -200,10 +203,10 @@ actuallyUnify region variable1 variable2 = do
202 (Just (Var1 v), _) ->
205 (Just (Var1 v), _) ->
203− unifyHelp' v variable2
206+ unifyHelp v variable2
205 (_, Just (Var1 v)) ->
208 (_, Just (Var1 v)) ->
206− unifyHelp' variable1 v
209+ unifyHelp variable1 v
208 (Nothing, _) ->
211 (Nothing, _) ->
209 superUnify
212 superUnify
@@ -215,38 +218,37 @@ actuallyUnify region variable1 variable2 = do
215 case (type1,type2) of
218 case (type1,type2) of
216 (App1 term1 term2, App1 term1' term2') ->
219 (App1 term1 term2, App1 term1' term2') ->
218− unifyHelp' term1 term1'
221+ unifyHelp term1 term1'
219− unifyHelp' term2 term2'
222+ unifyHelp term2 term2'
220 (Fun1 term1 term2, Fun1 term1' term2') ->
223 (Fun1 term1 term2, Fun1 term1' term2') ->
222− unifyHelp' term1 term1'
225+ unifyHelp term1 term1'
223− unifyHelp' term2 term2'
226+ unifyHelp term2 term2'
225 (EmptyRecord1, EmptyRecord1) ->
228 (EmptyRecord1, EmptyRecord1) ->
226 return ()
229 return ()
228− (Record1 fields ext, EmptyRecord1) | Map.null fields -> unifyHelp' ext variable2
231+ (Record1 fields ext, EmptyRecord1) | Map.null fields -> unifyHelp ext variable2
229− (EmptyRecord1, Record1 fields ext) | Map.null fields -> unifyHelp' variable1 ext
232+ (EmptyRecord1, Record1 fields ext) | Map.null fields -> unifyHelp variable1 ext
231 (Record1 _ _, Record1 _ _) ->
234 (Record1 _ _, Record1 _ _) ->
232− recordUnify region fresh variable1 variable2
235+ recordUnify fresh variable1 variable2
234− _ -> typeError region Nothing variable1 variable2
237+ _ -> typeError Nothing variable1 variable2
237-- RECORD UNIFICATION
240-- RECORD UNIFICATION
239recordUnify
242recordUnify
241− -> (Maybe (Term1 Variable) -> Unify Variable)
243+ :: (Maybe (Term1 Variable) -> Unify Variable)
242 -> Variable
244 -> Variable
243 -> Variable
245 -> Variable
244 -> Unify ()
246 -> Unify ()
245−recordUnify region fresh variable1 variable2 =
247+recordUnify fresh variable1 variable2 =
246 do (ExpandedRecord fields1 ext1) <- liftIO (gatherFields variable1)
248 do (ExpandedRecord fields1 ext1) <- liftIO (gatherFields variable1)
247 (ExpandedRecord fields2 ext2) <- liftIO (gatherFields variable2)
249 (ExpandedRecord fields2 ext2) <- liftIO (gatherFields variable2)
249− unifyOverlappingFields region fields1 fields2
251+ unifyOverlappingFields fields1 fields2
251 let freshRecord fields ext =
253 let freshRecord fields ext =
252 fresh (Just (Record1 fields ext))
254 fresh (Just (Record1 fields ext))
@@ -257,57 +259,56 @@ recordUnify region fresh variable1 variable2 =
257 let addFieldMismatchError missingFields =
259 let addFieldMismatchError missingFields =
258 let msg = fieldMismatchError missingFields
260 let msg = fieldMismatchError missingFields
260− typeError region (Just msg) variable1 variable2
262+ typeError (Just msg) variable1 variable2
262 case (ext1, ext2) of
264 case (ext1, ext2) of
263 (Empty _, Empty _) ->
265 (Empty _, Empty _) ->
264 case Map.null uniqueFields1 && Map.null uniqueFields2 of
266 case Map.null uniqueFields1 && Map.null uniqueFields2 of
265 True -> return ()
267 True -> return ()
266− False -> typeError region Nothing variable1 variable2
268+ False -> typeError Nothing variable1 variable2
268 (Empty var1, Extension var2) ->
270 (Empty var1, Extension var2) ->
269 case (Map.null uniqueFields1, Map.null uniqueFields2) of
271 case (Map.null uniqueFields1, Map.null uniqueFields2) of
270 (_, False) -> addFieldMismatchError uniqueFields2
272 (_, False) -> addFieldMismatchError uniqueFields2
271− (True, True) -> unifyHelp region var1 var2
273+ (True, True) -> unifyHelp var1 var2
272 (False, True) ->
274 (False, True) ->
273 do subRecord <- freshRecord uniqueFields1 var1
275 do subRecord <- freshRecord uniqueFields1 var1
274− unifyHelp region subRecord var2
276+ unifyHelp subRecord var2
276 (Extension var1, Empty var2) ->
278 (Extension var1, Empty var2) ->
277 case (Map.null uniqueFields1, Map.null uniqueFields2) of
279 case (Map.null uniqueFields1, Map.null uniqueFields2) of
278 (False, _) -> addFieldMismatchError uniqueFields1
280 (False, _) -> addFieldMismatchError uniqueFields1
279− (True, True) -> unifyHelp region var1 var2
281+ (True, True) -> unifyHelp var1 var2
280 (True, False) ->
282 (True, False) ->
281 do subRecord <- freshRecord uniqueFields2 var2
283 do subRecord <- freshRecord uniqueFields2 var2
282− unifyHelp region var1 subRecord
284+ unifyHelp var1 subRecord
284 (Extension var1, Extension var2) ->
286 (Extension var1, Extension var2) ->
285 case (Map.null uniqueFields1, Map.null uniqueFields2) of
287 case (Map.null uniqueFields1, Map.null uniqueFields2) of
286 (True, True) ->
288 (True, True) ->
287− unifyHelp region var1 var2
289+ unifyHelp var1 var2
289 (True, False) ->
291 (True, False) ->
290 do subRecord <- freshRecord uniqueFields2 var2
292 do subRecord <- freshRecord uniqueFields2 var2
291− unifyHelp region var1 subRecord
293+ unifyHelp var1 subRecord
293 (False, True) ->
295 (False, True) ->
294 do subRecord <- freshRecord uniqueFields1 var1
296 do subRecord <- freshRecord uniqueFields1 var1
295− unifyHelp region subRecord var2
297+ unifyHelp subRecord var2
297 (False, False) ->
299 (False, False) ->
298 do record1' <- freshRecord uniqueFields1 =<< fresh Nothing
300 do record1' <- freshRecord uniqueFields1 =<< fresh Nothing
299 record2' <- freshRecord uniqueFields2 =<< fresh Nothing
301 record2' <- freshRecord uniqueFields2 =<< fresh Nothing
300− unifyHelp region record1' var2
302+ unifyHelp record1' var2
301− unifyHelp region var1 record2'
303+ unifyHelp var1 record2'
304unifyOverlappingFields
306unifyOverlappingFields
306− -> Map.Map String [Variable]
307+ :: Map.Map String [Variable]
307 -> Map.Map String [Variable]
308 -> Map.Map String [Variable]
308 -> Unify ()
309 -> Unify ()
309−unifyOverlappingFields region fields1 fields2 =
310+unifyOverlappingFields fields1 fields2 =
310− Map.intersectionWith (zipWith (unifyHelp region)) fields1 fields2
311+ Map.intersectionWith (zipWith unifyHelp) fields1 fields2
311 |> Map.elems
312 |> Map.elems
312 |> concat
313 |> concat
313 |> sequence_
314 |> sequence_