1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
9 , Descriptor(Descriptor)
18 , int, float, char, string, bool, never
19 , vec2, vec3, vec4, mat4, texture
32import Control.Monad.State.Strict (StateT, liftIO)
33import qualified Control.Monad.State.Strict as State
34import Data.Foldable (foldrM)
35import qualified Data.Map.Strict as Map
36import Data.Word (Word32)
38import qualified AST.Canonical as Can
39import qualified AST.Module.Name as ModuleName
40import qualified AST.Utils.Type as Type
41import qualified Elm.Name as N
42import qualified Reporting.Annotation as A
43import qualified Reporting.Error.Type as E
44import qualified Reporting.Region as R
45import qualified Type.Error as ET
46import qualified Type.UnionFind as UF
56 | CEqual R.Region E.Category Type (E.Expected Type)
57 | CLocal R.Region N.Name (E.Expected Type)
58 | CForeign R.Region N.Name Can.Annotation (E.Expected Type)
59 | CPattern R.Region E.PCategory Type (E.PExpected Type)
62 { _rigidVars :: [Variable]
63 , _flexVars :: [Variable]
64 , _header :: Map.Map N.Name (A.Located Type)
65 , _headerCon :: Constraint
66 , _bodyCon :: Constraint
70exists :: [Variable] -> Constraint -> Constraint
71exists flexVars constraint =
72 CLet [] flexVars Map.empty constraint CTrue
84 = App1 ModuleName.Canonical N.Name [Variable]
85 | Fun1 Variable Variable
87 | Record1 (Map.Map N.Name Variable) Variable
89 | Tuple1 Variable Variable (Maybe Variable)
94 | AliasN ModuleName.Canonical N.Name [(N.Name, Type)] Type
96 | AppN ModuleName.Canonical N.Name [Type]
99 | RecordN (Map.Map N.Name Type) Type
101 | TupleN Type Type (Maybe Type)
110 { _content :: Content
113 , _copy :: Maybe Variable
118 = FlexVar (Maybe N.Name)
119 | FlexSuper SuperType (Maybe N.Name)
121 | RigidSuper SuperType N.Name
123 | Alias ModuleName.Canonical N.Name [(N.Name,Variable)] Variable
135makeDescriptor :: Content -> Descriptor
136makeDescriptor content =
137 Descriptor content noRank noMark Nothing
158newtype Mark = Mark Word32
172getVarNamesMark :: Mark
177{-# INLINE nextMark #-}
178nextMark :: Mark -> Mark
179nextMark (Mark mark) =
191(==>) :: Type -> Type -> Type
202int = AppN ModuleName.basics "Int" []
205{-# NOINLINE float #-}
207float = AppN ModuleName.basics "Float" []
212char = AppN ModuleName.char "Char" []
215{-# NOINLINE string #-}
217string = AppN ModuleName.string "String" []
222bool = AppN ModuleName.basics "Bool" []
225{-# NOINLINE never #-}
227never = AppN ModuleName.basics "Never" []
236vec2 = AppN ModuleName.vector2 "Vec2" []
241vec3 = AppN ModuleName.vector3 "Vec3" []
246vec4 = AppN ModuleName.vector4 "Vec4" []
251mat4 = AppN ModuleName.matrix4 "Mat4" []
254{-# NOINLINE texture #-}
256texture = AppN ModuleName.webgl "Texture" []
260-- MAKE FLEX VARIABLES
263mkFlexVar :: IO Variable
265 UF.fresh flexVarDescriptor
268{-# NOINLINE flexVarDescriptor #-}
269flexVarDescriptor :: Descriptor
271 makeDescriptor unnamedFlexVar
274{-# NOINLINE unnamedFlexVar #-}
275unnamedFlexVar :: Content
284mkFlexNumber :: IO Variable
286 UF.fresh flexNumberDescriptor
289{-# NOINLINE flexNumberDescriptor #-}
290flexNumberDescriptor :: Descriptor
291flexNumberDescriptor =
292 makeDescriptor (unnamedFlexSuper Number)
295unnamedFlexSuper :: SuperType -> Content
296unnamedFlexSuper super =
297 FlexSuper super Nothing
301-- MAKE NAMED VARIABLES
304nameToFlex :: N.Name -> IO Variable
306 UF.fresh $ makeDescriptor $
307 maybe FlexVar FlexSuper (toSuper name) (Just name)
310nameToRigid :: N.Name -> IO Variable
312 UF.fresh $ makeDescriptor $
313 maybe RigidVar RigidSuper (toSuper name) name
316toSuper :: N.Name -> Maybe SuperType
318 if N.startsWith "number" name then
321 else if N.startsWith "comparable" name then
324 else if N.startsWith "appendable" name then
327 else if N.startsWith "compappend" name then
338toAnnotation :: Variable -> IO Can.Annotation
339toAnnotation variable =
340 do userNames <- getVarNames variable Map.empty
341 (tipe, NameState freeVars _ _ _ _ _) <-
342 State.runStateT (variableToCanType variable) (makeNameState userNames)
343 return $ Can.Forall freeVars tipe
346variableToCanType :: Variable -> StateT NameState IO Can.Type
347variableToCanType variable =
348 do (Descriptor content _ _ _) <- liftIO $ UF.get variable
356 return (Can.TVar name)
359 do name <- getFreshVarName
360 liftIO $ UF.modify variable (\desc -> desc { _content = FlexVar (Just name) })
361 return (Can.TVar name)
363 FlexSuper super maybeName ->
366 return (Can.TVar name)
369 do name <- getFreshSuperName super
370 liftIO $ UF.modify variable (\desc -> desc { _content = FlexSuper super (Just name) })
371 return (Can.TVar name)
374 return (Can.TVar name)
377 return (Can.TVar name)
379 Alias home name args realVariable ->
380 do canArgs <- traverse (traverse variableToCanType) args
381 canType <- variableToCanType realVariable
382 return (Can.TAlias home name canArgs (Can.Filled canType))
385 error "cannot handle Error types in variableToCanType"
388termToCanType :: FlatType -> StateT NameState IO Can.Type
391 App1 home name args ->
392 Can.TType home name <$> traverse variableToCanType args
396 <$> variableToCanType a
397 <*> variableToCanType b
400 return $ Can.TRecord Map.empty Nothing
402 Record1 fields extension ->
403 do canFields <- traverse variableToCanType fields
404 canExt <- Type.iteratedDealias <$> variableToCanType extension
407 Can.TRecord subFields subExt ->
408 Can.TRecord (Map.union subFields canFields) subExt
411 Can.TRecord canFields (Just name)
414 error "Used toAnnotation on a type that is not well-formed"
421 <$> variableToCanType a
422 <*> variableToCanType b
423 <*> traverse variableToCanType maybeC
430toErrorType :: Variable -> IO ET.Type
431toErrorType variable =
432 do userNames <- getVarNames variable Map.empty
433 State.evalStateT (variableToErrorType variable) (makeNameState userNames)
436variableToErrorType :: Variable -> StateT NameState IO ET.Type
437variableToErrorType variable =
438 do descriptor <- liftIO $ UF.get variable
439 let mark = _mark descriptor
440 if mark == occursMark
445 do liftIO $ UF.modify variable (\desc -> desc { _mark = occursMark })
446 errType <- contentToErrorType variable (_content descriptor)
447 liftIO $ UF.modify variable (\desc -> desc { _mark = mark })
451contentToErrorType :: Variable -> Content -> StateT NameState IO ET.Type
452contentToErrorType variable content =
460 return (ET.FlexVar name)
463 do name <- getFreshVarName
464 liftIO $ UF.modify variable (\desc -> desc { _content = FlexVar (Just name) })
465 return (ET.FlexVar name)
467 FlexSuper super maybeName ->
470 return (ET.FlexSuper (superToSuper super) name)
473 do name <- getFreshSuperName super
474 liftIO $ UF.modify variable (\desc -> desc { _content = FlexSuper super (Just name) })
475 return (ET.FlexSuper (superToSuper super) name)
478 return (ET.RigidVar name)
480 RigidSuper super name ->
481 return (ET.RigidSuper (superToSuper super) name)
483 Alias home name args realVariable ->
484 do errArgs <- traverse (traverse variableToErrorType) args
485 errType <- variableToErrorType realVariable
486 return (ET.Alias home name errArgs errType)
492superToSuper :: SuperType -> ET.Super
496 Comparable -> ET.Comparable
497 Appendable -> ET.Appendable
498 CompAppend -> ET.CompAppend
501termToErrorType :: FlatType -> StateT NameState IO ET.Type
502termToErrorType term =
504 App1 home name args ->
505 ET.Type home name <$> traverse variableToErrorType args
508 do arg <- variableToErrorType a
509 result <- variableToErrorType b
512 ET.Lambda arg1 arg2 others ->
513 ET.Lambda arg arg1 (arg2:others)
516 ET.Lambda arg result []
519 return $ ET.Record Map.empty ET.Closed
521 Record1 fields extension ->
522 do errFields <- traverse variableToErrorType fields
523 errExt <- ET.iteratedDealias <$> variableToErrorType extension
526 ET.Record subFields subExt ->
527 ET.Record (Map.union subFields errFields) subExt
530 ET.Record errFields (ET.FlexOpen ext)
533 ET.Record errFields (ET.RigidOpen ext)
536 error "Used toErrorType on a type that is not well-formed"
543 <$> variableToErrorType a
544 <*> variableToErrorType b
545 <*> traverse variableToErrorType maybeC
549-- MANAGE FRESH VARIABLE NAMES
554 { _taken :: Map.Map N.Name ()
557 , _comparables :: Int
558 , _appendables :: Int
559 , _compAppends :: Int
563makeNameState :: Map.Map N.Name Variable -> NameState
565 NameState (Map.map (const ()) taken) 0 0 0 0 0
572getFreshVarName :: (Monad m) => StateT NameState m N.Name
574 do index <- State.gets _normals
575 taken <- State.gets _taken
576 let (name, newIndex, newTaken) = getFreshVarNameHelp index taken
577 State.modify $ \state -> state { _taken = newTaken, _normals = newIndex }
581getFreshVarNameHelp :: Int -> Map.Map N.Name () -> (N.Name, Int, Map.Map N.Name ())
582getFreshVarNameHelp index taken =
587 chr = N.fromLetter letter
588 name = if postfix <= 0 then chr else N.addIndex chr postfix
590 if Map.member name taken then
591 getFreshVarNameHelp (index + 1) taken
593 ( name, index + 1, Map.insert name () taken )
600getFreshSuperName :: (Monad m) => SuperType -> StateT NameState m N.Name
601getFreshSuperName super =
604 getFreshSuper "number" _numbers (\index state -> state { _numbers = index })
607 getFreshSuper "comparable" _comparables (\index state -> state { _comparables = index })
610 getFreshSuper "appendable" _appendables (\index state -> state { _appendables = index })
613 getFreshSuper "compappend" _compAppends (\index state -> state { _compAppends = index })
616getFreshSuper :: (Monad m) => N.Name -> (NameState -> Int) -> (Int -> NameState -> NameState) -> StateT NameState m N.Name
617getFreshSuper prefix getter setter =
618 do index <- State.gets getter
619 taken <- State.gets _taken
620 let (name, newIndex, newTaken) = getFreshSuperHelp prefix index taken
621 State.modify (\state -> setter newIndex state { _taken = newTaken })
625getFreshSuperHelp :: N.Name -> Int -> Map.Map N.Name () -> (N.Name, Int, Map.Map N.Name ())
626getFreshSuperHelp prefix index taken =
629 if index <= 0 then prefix else N.addIndex prefix index
631 if Map.member name taken then
632 getFreshSuperHelp prefix (index + 1) taken
635 ( name, index + 1, Map.insert name () taken )
639-- GET ALL VARIABLE NAMES
642getVarNames :: Variable -> Map.Map N.Name Variable -> IO (Map.Map N.Name Variable)
643getVarNames var takenNames =
644 do (Descriptor content rank mark copy) <- UF.get var
645 if mark == getVarNamesMark
646 then return takenNames
648 do UF.set var (Descriptor content rank getVarNamesMark copy)
659 addName 0 name var (FlexVar . Just) takenNames
661 FlexSuper super maybeName ->
667 addName 0 name var (FlexSuper super . Just) takenNames
670 addName 0 name var RigidVar takenNames
672 RigidSuper super name ->
673 addName 0 name var (RigidSuper super) takenNames
676 foldrM getVarNames takenNames (map snd args)
678 Structure flatType ->
681 foldrM getVarNames takenNames args
684 getVarNames arg =<< getVarNames body takenNames
689 Record1 fields extension ->
690 getVarNames extension =<<
691 foldrM getVarNames takenNames (Map.elems fields)
696 Tuple1 a b Nothing ->
697 getVarNames a =<< getVarNames b takenNames
699 Tuple1 a b (Just c) ->
700 getVarNames a =<< getVarNames b =<< getVarNames c takenNames
704-- REGISTER NAME / RENAME DUPLICATES
707addName :: Int -> N.Name -> Variable -> (N.Name -> Content) -> Map.Map N.Name Variable -> IO (Map.Map N.Name Variable)
708addName index givenName var makeContent takenNames =
714 N.addSafeIndex givenName index
716 case Map.lookup indexedName takenNames of
718 do if indexedName == givenName then return () else
719 UF.modify var $ \(Descriptor _ rank mark copy) ->
720 Descriptor (makeContent indexedName) rank mark copy
721 return $ Map.insert indexedName var takenNames
724 do same <- UF.equivalent var otherVar
726 then return takenNames
727 else addName (index + 1) givenName var makeContent takenNames
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