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)
65 , _neq :: IO Constraint
68 { _rigidVars :: [Variable]
69 , _flexVars :: [Variable]
70 , _header :: Map.Map N.Name (A.Located Type)
71 , _headerCon :: Constraint
72 , _bodyCon :: Constraint
76exists :: [Variable] -> Constraint -> Constraint
77exists flexVars constraint =
78 CLet [] flexVars Map.empty constraint CTrue
90 = App1 ModuleName.Canonical N.Name [Variable]
91 | Fun1 Variable Variable
93 | Record1 (Map.Map N.Name Variable) Variable
95 | Tuple1 Variable Variable (Maybe Variable)
100 | AliasN ModuleName.Canonical N.Name [(N.Name, Type)] Type
102 | AppN ModuleName.Canonical N.Name [Type]
105 | RecordN (Map.Map N.Name Type) Type
107 | TupleN Type Type (Maybe Type)
116 { _content :: Content
119 , _copy :: Maybe Variable
124 = FlexVar (Maybe N.Name)
125 | FlexSuper SuperType (Maybe N.Name)
127 | RigidSuper SuperType N.Name
129 | Alias ModuleName.Canonical N.Name [(N.Name,Variable)] Variable
141makeDescriptor :: Content -> Descriptor
142makeDescriptor content =
143 Descriptor content noRank noMark Nothing
164newtype Mark = Mark Word32
178getVarNamesMark :: Mark
183{-# INLINE nextMark #-}
184nextMark :: Mark -> Mark
185nextMark (Mark mark) =
197(==>) :: Type -> Type -> Type
208int = AppN ModuleName.basics "Int" []
211{-# NOINLINE float #-}
213float = AppN ModuleName.basics "Float" []
218char = AppN ModuleName.char "Char" []
221{-# NOINLINE string #-}
223string = AppN ModuleName.string "String" []
228bool = AppN ModuleName.basics "Bool" []
231{-# NOINLINE never #-}
233never = AppN ModuleName.basics "Never" []
242vec2 = AppN ModuleName.vector2 "Vec2" []
247vec3 = AppN ModuleName.vector3 "Vec3" []
252vec4 = AppN ModuleName.vector4 "Vec4" []
257mat4 = AppN ModuleName.matrix4 "Mat4" []
260{-# NOINLINE texture #-}
262texture = AppN ModuleName.webgl "Texture" []
266-- MAKE FLEX VARIABLES
269mkFlexVar :: IO Variable
271 UF.fresh flexVarDescriptor
274{-# NOINLINE flexVarDescriptor #-}
275flexVarDescriptor :: Descriptor
277 makeDescriptor unnamedFlexVar
280{-# NOINLINE unnamedFlexVar #-}
281unnamedFlexVar :: Content
290mkFlexNumber :: IO Variable
292 UF.fresh flexNumberDescriptor
295{-# NOINLINE flexNumberDescriptor #-}
296flexNumberDescriptor :: Descriptor
297flexNumberDescriptor =
298 makeDescriptor (unnamedFlexSuper Number)
301unnamedFlexSuper :: SuperType -> Content
302unnamedFlexSuper super =
303 FlexSuper super Nothing
307-- MAKE NAMED VARIABLES
310nameToFlex :: N.Name -> IO Variable
312 UF.fresh $ makeDescriptor $
313 maybe FlexVar FlexSuper (toSuper name) (Just name)
316nameToRigid :: N.Name -> IO Variable
318 UF.fresh $ makeDescriptor $
319 maybe RigidVar RigidSuper (toSuper name) name
322toSuper :: N.Name -> Maybe SuperType
324 if N.startsWith "number" name then
327 else if N.startsWith "comparable" name then
330 else if N.startsWith "appendable" name then
333 else if N.startsWith "compappend" name then
344toAnnotation :: Variable -> IO Can.Annotation
345toAnnotation variable =
346 do userNames <- getVarNames variable Map.empty
347 (tipe, NameState allNames _ _ _ _ _) <-
348 State.runStateT (variableToCanType variable) (makeNameState userNames)
349 return $ Can.Forall (Map.map (const ()) allNames) tipe
352variableToCanType :: Variable -> StateT NameState IO Can.Type
353variableToCanType variable =
354 do (Descriptor content _ _ _) <- liftIO $ UF.get variable
362 return (Can.TVar name)
365 do name <- getFreshVarName
366 liftIO $ UF.modify variable (\desc -> desc { _content = FlexVar (Just name) })
367 return (Can.TVar name)
369 FlexSuper super maybeName ->
372 return (Can.TVar name)
375 do name <- getFreshSuperName super
376 liftIO $ UF.modify variable (\desc -> desc { _content = FlexSuper super (Just name) })
377 return (Can.TVar name)
380 return (Can.TVar name)
383 return (Can.TVar name)
385 Alias home name args realVariable ->
386 do canArgs <- traverse (traverse variableToCanType) args
387 canType <- variableToCanType realVariable
388 return (Can.TAlias home name canArgs (Can.Filled canType))
391 error "cannot handle Error types in variableToCanType"
394termToCanType :: FlatType -> StateT NameState IO Can.Type
397 App1 home name args ->
398 Can.TType home name <$> traverse variableToCanType args
402 <$> variableToCanType a
403 <*> variableToCanType b
406 return $ Can.TRecord Map.empty Nothing
408 Record1 fields extension ->
409 do canFields <- traverse variableToCanType fields
410 canExt <- Type.iteratedDealias <$> variableToCanType extension
413 Can.TRecord subFields subExt ->
414 Can.TRecord (Map.union subFields canFields) subExt
417 Can.TRecord canFields (Just name)
420 error "Used toAnnotation on a type that is not well-formed"
427 <$> variableToCanType a
428 <*> variableToCanType b
429 <*> traverse variableToCanType maybeC
436toErrorType :: Variable -> IO ET.Type
437toErrorType variable =
438 do userNames <- getVarNames variable Map.empty
439 State.evalStateT (variableToErrorType variable) (makeNameState userNames)
442variableToErrorType :: Variable -> StateT NameState IO ET.Type
443variableToErrorType variable =
444 do descriptor <- liftIO $ UF.get variable
445 let mark = _mark descriptor
446 if mark == occursMark
451 do liftIO $ UF.modify variable (\desc -> desc { _mark = occursMark })
452 errType <- contentToErrorType variable (_content descriptor)
453 liftIO $ UF.modify variable (\desc -> desc { _mark = mark })
457contentToErrorType :: Variable -> Content -> StateT NameState IO ET.Type
458contentToErrorType variable content =
466 return (ET.FlexVar name)
469 do name <- getFreshVarName
470 liftIO $ UF.modify variable (\desc -> desc { _content = FlexVar (Just name) })
471 return (ET.FlexVar name)
473 FlexSuper super maybeName ->
476 return (ET.FlexSuper (superToSuper super) name)
479 do name <- getFreshSuperName super
480 liftIO $ UF.modify variable (\desc -> desc { _content = FlexSuper super (Just name) })
481 return (ET.FlexSuper (superToSuper super) name)
484 return (ET.RigidVar name)
486 RigidSuper super name ->
487 return (ET.RigidSuper (superToSuper super) name)
489 Alias home name args realVariable ->
490 do errArgs <- traverse (traverse variableToErrorType) args
491 errType <- variableToErrorType realVariable
492 return (ET.Alias home name errArgs errType)
498superToSuper :: SuperType -> ET.Super
502 Comparable -> ET.Comparable
503 Appendable -> ET.Appendable
504 CompAppend -> ET.CompAppend
507termToErrorType :: FlatType -> StateT NameState IO ET.Type
508termToErrorType term =
510 App1 home name args ->
511 ET.Type home name <$> traverse variableToErrorType args
514 do arg <- variableToErrorType a
515 result <- variableToErrorType b
518 ET.Lambda arg1 arg2 others ->
519 ET.Lambda arg arg1 (arg2:others)
522 ET.Lambda arg result []
525 return $ ET.Record Map.empty ET.Closed
527 Record1 fields extension ->
528 do errFields <- traverse variableToErrorType fields
529 errExt <- ET.iteratedDealias <$> variableToErrorType extension
532 ET.Record subFields subExt ->
533 ET.Record (Map.union subFields errFields) subExt
536 ET.Record errFields (ET.FlexOpen ext)
539 ET.Record errFields (ET.RigidOpen ext)
542 error "Used toErrorType on a type that is not well-formed"
549 <$> variableToErrorType a
550 <*> variableToErrorType b
551 <*> traverse variableToErrorType maybeC
555-- MANAGE FRESH VARIABLE NAMES
560 { _taken :: TakenNames
563 , _comparables :: Int
564 , _appendables :: Int
565 , _compAppends :: Int
569type TakenNames = Map.Map N.Name Variable
572makeNameState :: TakenNames -> NameState
574 NameState taken 0 0 0 0 0
577getFreshVarName :: (Monad m) => StateT NameState m N.Name
579 do index <- State.gets _normals
580 taken <- State.gets _taken
581 let (uniqueName, newIndex) = getFreshNormal index taken
582 State.modify (\state -> state { _normals = newIndex })
586getFreshSuperName :: (Monad m) => SuperType -> StateT NameState m N.Name
587getFreshSuperName super =
590 getFreshSuper "number" _numbers (\index state -> state { _numbers = index })
593 getFreshSuper "comparable" _comparables (\index state -> state { _comparables = index })
596 getFreshSuper "appendable" _appendables (\index state -> state { _appendables = index })
599 getFreshSuper "compappend" _compAppends (\index state -> state { _compAppends = index })
602getFreshNormal :: Int -> TakenNames -> (N.Name, Int)
603getFreshNormal index taken =
608 chr = N.fromLetter letter
609 name = if postfix <= 0 then chr else N.addIndex chr postfix
611 if Map.member name taken then
612 getFreshNormal (index + 1) taken
621 -> (NameState -> Int)
622 -> (Int -> NameState -> NameState)
623 -> StateT NameState m N.Name
624getFreshSuper name getter setter =
625 do index <- State.gets getter
626 taken <- State.gets _taken
627 let (uniqueName, newIndex) = getFreshSuperHelp name index taken
628 State.modify (setter newIndex)
632getFreshSuperHelp :: N.Name -> Int -> TakenNames -> (N.Name, Int)
633getFreshSuperHelp name index taken =
636 if index <= 0 then name else N.addIndex name index
638 if Map.member newName taken then
639 getFreshSuperHelp name (index + 1) taken
646-- GET ALL VARIABLE NAMES
649getVarNames :: Variable -> TakenNames -> IO TakenNames
650getVarNames var takenNames =
651 do (Descriptor content rank mark copy) <- UF.get var
652 if mark == getVarNamesMark
653 then return takenNames
655 do UF.set var (Descriptor content rank getVarNamesMark copy)
666 addName 0 name var (FlexVar . Just) takenNames
668 FlexSuper super maybeName ->
674 addName 0 name var (FlexSuper super . Just) takenNames
677 addName 0 name var RigidVar takenNames
679 RigidSuper super name ->
680 addName 0 name var (RigidSuper super) takenNames
683 foldrM getVarNames takenNames (map snd args)
685 Structure flatType ->
688 foldrM getVarNames takenNames args
691 getVarNames arg =<< getVarNames body takenNames
696 Record1 fields extension ->
697 getVarNames extension =<<
698 foldrM getVarNames takenNames (Map.elems fields)
703 Tuple1 a b Nothing ->
704 getVarNames a =<< getVarNames b takenNames
706 Tuple1 a b (Just c) ->
707 getVarNames a =<< getVarNames b =<< getVarNames c takenNames
711-- REGISTER NAME / RENAME DUPLICATES
714addName :: Int -> N.Name -> Variable -> (N.Name -> Content) -> TakenNames -> IO TakenNames
715addName index givenName var makeContent takenNames =
721 N.addSafeIndex givenName index
723 case Map.lookup indexedName takenNames of
725 do if indexedName == givenName then return () else
726 UF.modify var $ \(Descriptor _ rank mark copy) ->
727 Descriptor (makeContent indexedName) rank mark copy
728 return $ Map.insert indexedName var takenNames
731 do same <- UF.equivalent var otherVar
733 then return takenNames
734 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