git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Fix #315 and fix #316
commit74c2628ada8e8e6667c94fee7633070b30a47775 authorPhil Freeman <paf31@cantab.net> dateMon 24 Mar 2014, 21:14 (13 years ago) parenta5566d8
11 files changed+88−57
examples/passing/LiberalTypeSynonyms.purs+19 examples/passing/STArray.purs+6−6 src/Language/PureScript/CodeGen/JS.hs+1−1 src/Language/PureScript/Environment.hs+7 src/Language/PureScript/Parser/Types.hs+1−1 src/Language/PureScript/Pretty/Types.hs+3−5 src/Language/PureScript/Sugar/TypeClasses.hs+4−1 src/Language/PureScript/TypeChecker.hs+2−2 src/Language/PureScript/TypeChecker/Kinds.hs+13−13 src/Language/PureScript/TypeChecker/Types.hs+28−16 src/Language/PureScript/Types.hs+4−12
examples/passing/LiberalTypeSynonyms.pursnew file+19
@@ -0,0 +1,19 @@
1+module Main where
2+
3+type Reader = (->) String
4+
5+foo :: Reader String
6+foo s = s
7+
8+type AndFoo r = (foo :: String | r)
9+
10+getFoo :: forall r. Prim.Object (AndFoo r) -> String
11+getFoo o = o.foo
12+
13+type F r = { | r } -> { | r }
14+
15+f :: (forall r. F r) -> String
16+f g = case g { x: "Hello" } of
17+ { x = x } -> x
18+
19+main = Debug.Trace.trace "Done"
examples/passing/STArray.purs+6−6
@@ -11,14 +11,14 @@ test = runSTArray (do
1111 pokeSTArray a 1 2
1212 return a)
1313
14−fromTo' lo hi _ arr | lo > hi = return arr
15−fromTo' lo hi i arr = do
16− pokeSTArray arr i lo
17− fromTo' (lo + 1) hi (i + 1) arr
18−
1914fromTo lo hi = runSTArray (do
2015 arr <- newSTArray (hi - lo + 1) 0
21− fromTo' lo hi 0 arr)
16+ (let
17+ go lo hi _ arr | lo > hi = return arr
18+ go lo hi i arr = do
19+ pokeSTArray arr i lo
20+ go (lo + 1) hi (i + 1) arr
21+ in go lo hi 0 arr))
2222
2323main = do
2424 let t1 = runPure (fromTo 10 20)
src/Language/PureScript/CodeGen/JS.hs+1−1
@@ -193,7 +193,7 @@ runtimeTypeChecks arg ty =
193193 argumentCheck val t | t == tyString = [typeCheck val "string"]
194194 argumentCheck val t | t == tyBoolean = [typeCheck val "boolean"]
195195 argumentCheck val (TypeApp t _) | t == tyArray = [arrayCheck val]
196− argumentCheck val (Object row) =
196+ argumentCheck val (TypeApp t row) | t == tyObject =
197197 let
198198 (pairs, _) = rowToList row
199199 in
src/Language/PureScript/Environment.hs+7
@@ -171,6 +171,12 @@ tyBoolean = primTy "Boolean"
171171tyArray :: Type
172172tyArray = primTy "Array"
173173
174+-- |
175+-- Type constructor for objects
176+--
177+tyObject :: Type
178+tyObject = primTy "Object"
179+
174180-- |
175181-- Smart constructor for function types
176182--
@@ -183,6 +189,7 @@ function t1 = TypeApp (TypeApp tyFunction t1)
183189primTypes :: M.Map (Qualified ProperName) (Kind, TypeKind)
184190primTypes = M.fromList [ (primName "Function" , (FunKind Star (FunKind Star Star), ExternData))
185191 , (primName "Array" , (FunKind Star Star, ExternData))
192+ , (primName "Object" , (FunKind (Row Star) Star, ExternData))
186193 , (primName "String" , (Star, ExternData))
187194 , (primName "Number" , (Star, ExternData))
188195 , (primName "Boolean" , (Star, ExternData)) ]
src/Language/PureScript/Parser/Types.hs+1−1
@@ -49,7 +49,7 @@ parseFunction :: P.Parsec String ParseState Type
4949parseFunction = parens $ P.try (lexeme (P.string "->")) >> return tyFunction
5050
5151parseObject :: P.Parsec String ParseState Type
52−parseObject = braces $ Object <$> parseRow False
52+parseObject = braces $ TypeApp tyObject <$> parseRow False
5353
5454parseTypeVariable :: P.Parsec String ParseState Type
5555parseTypeVariable = do
src/Language/PureScript/Pretty/Types.hs+3−5
@@ -34,8 +34,8 @@ import Language.PureScript.Environment
3434typeLiterals :: Pattern () Type String
3535typeLiterals = mkPattern match
3636 where
37− match (Object row) = Just $ "{ " ++ prettyPrintRow row ++ " }"
3837 match (TypeVar var) = Just var
38+ match (PrettyPrintObject row) = Just $ "{ " ++ prettyPrintRow row ++ " }"
3939 match (PrettyPrintArray ty) = Just $ "[" ++ prettyPrintType ty ++ "]"
4040 match (TypeConstructor ctor) = Just $ show ctor
4141 match (TUnknown (Unknown u)) = Just $ 'u' : show u
@@ -56,10 +56,7 @@ prettyPrintRow = (\(tys, rest) -> intercalate ", " (map (uncurry nameAndTypeToPs
5656 nameAndTypeToPs name ty = name ++ " :: " ++ prettyPrintType ty
5757 tailToPs :: Type -> String
5858 tailToPs REmpty = ""
59− tailToPs (TUnknown (Unknown u)) = " | u" ++ show u
60− tailToPs (TypeVar var) = " | " ++ var
61− tailToPs (Skolem s _) = " | s" ++ show s
62− tailToPs _ = error "Invalid row tail"
59+ tailToPs other = " | " ++ prettyPrintType other
6360 toList :: [(String, Type)] -> Type -> ([(String, Type)], Type)
6461 toList tys (RCons name ty row) = toList ((name, ty):tys) row
6562 toList tys r = (tys, r)
@@ -81,6 +78,7 @@ insertPlaceholders = everywhere' (mkT convertForAlls) . everywhere (mkT convert)
8178 where
8279 convert (TypeApp (TypeApp f arg) ret) | f == tyFunction = PrettyPrintFunction arg ret
8380 convert (TypeApp a el) | a == tyArray = PrettyPrintArray el
81+ convert (TypeApp o r) | o == tyObject = PrettyPrintObject r
8482 convert other = other
8583 convertForAlls (ForAll ident ty _) = go [ident] ty
8684 where
src/Language/PureScript/Sugar/TypeClasses.hs+4−1
@@ -107,7 +107,7 @@ memberToNameAndType _ = error "Invalid declaration in type class definition"
107107
108108typeClassDictionaryDeclaration :: ProperName -> [String] -> [Declaration] -> Declaration
109109typeClassDictionaryDeclaration name args members =
110− TypeSynonymDeclaration name args (Object $ rowFromList (map memberToNameAndType members, REmpty))
110+ TypeSynonymDeclaration name args (TypeApp tyObject $ rowFromList (map memberToNameAndType members, REmpty))
111111
112112typeClassMemberToDictionaryAccessor :: ModuleName -> ProperName -> [String] -> Declaration -> Declaration
113113typeClassMemberToDictionaryAccessor mn name args (TypeDeclaration ident ty) =
@@ -133,6 +133,9 @@ typeInstanceDictionaryDeclaration name mn deps className tys decls = do
133133 foldr (function . (\(pn, tys') -> foldl TypeApp (TypeConstructor pn) tys')) (foldl TypeApp (TypeConstructor className) tys) deps))
134134 )
135135 where
136+ unit :: Type
137+ unit = TypeApp tyObject REmpty
138+
136139 memberToNameAndValue :: [(String, Type)] -> Declaration -> Desugar (String, Value)
137140 memberToNameAndValue tys' (ValueDeclaration ident _ _ _ _) = do
138141 memberType <- lift . maybe (Left "Type class member type not found") Right $ lookup (identToJs ident) tys'
src/Language/PureScript/TypeChecker.hs+2−2
@@ -107,7 +107,7 @@ typeCheckAll :: Maybe ModuleName -> ModuleName -> [Declaration] -> Check [Declar
107107typeCheckAll _ _ [] = return []
108108typeCheckAll mainModuleName moduleName (d@(DataDeclaration name args dctors) : rest) = do
109109 rethrow (("Error in type constructor " ++ show name ++ ":\n") ++) $ do
110− ctorKind <- kindsOf moduleName name args (concatMap snd dctors)
110+ ctorKind <- kindsOf True moduleName name args (concatMap snd dctors)
111111 addDataType moduleName name args dctors ctorKind
112112 ds <- typeCheckAll mainModuleName moduleName rest
113113 return $ d : ds
@@ -129,7 +129,7 @@ typeCheckAll mainModuleName moduleName (d@(DataBindingGroupDeclaration tys) : re
129129 toDataDecl _ = Nothing
130130typeCheckAll mainModuleName moduleName (d@(TypeSynonymDeclaration name args ty) : rest) = do
131131 rethrow (("Error in type synonym " ++ show name ++ ":\n") ++) $ do
132− kind <- kindsOf moduleName name args [ty]
132+ kind <- kindsOf False moduleName name args [ty]
133133 addTypeSynonym moduleName name args ty kind
134134 ds <- typeCheckAll mainModuleName moduleName rest
135135 return $ d : ds
src/Language/PureScript/TypeChecker/Kinds.hs+13−13
@@ -67,13 +67,13 @@ kindOf _ ty =
6767-- |
6868-- Infer the kind of a type constructor with a collection of arguments and a collection of associated data constructors
6969--
70−kindsOf :: ModuleName -> ProperName -> [String] -> [Type] -> Check Kind
71−kindsOf moduleName name args ts = fmap tidyUp . liftUnify $ do
70+kindsOf :: Bool -> ModuleName -> ProperName -> [String] -> [Type] -> Check Kind
71+kindsOf isData moduleName name args ts = fmap tidyUp . liftUnify $ do
7272 tyCon <- fresh
7373 kargs <- replicateM (length args) fresh
7474 let dict = (name, tyCon) : zipWith (\arg kind -> (arg, kind)) (map ProperName args) kargs
7575 bindLocalTypeVariables moduleName dict $
76− solveTypes ts kargs tyCon
76+ solveTypes isData ts kargs tyCon
7777 where
7878 tidyUp (k, sub) = starIfUnknown $ sub $? k
7979
@@ -92,12 +92,12 @@ kindsOfAll moduleName syns tys = fmap tidyUp . liftUnify $ do
9292 kargs <- replicateM (length args) fresh
9393 let argDict = zip (map ProperName args) kargs
9494 bindLocalTypeVariables moduleName argDict $
95− solveTypes ts kargs tyCon) tyCons tys
95+ solveTypes True ts kargs tyCon) tyCons tys
9696 syn_ks <- zipWithM (\synVar (_, args, ty) -> do
9797 kargs <- replicateM (length args) fresh
9898 let argDict = zip (map ProperName args) kargs
9999 bindLocalTypeVariables moduleName argDict $
100− solveTypes [ty] kargs synVar) synVars syns
100+ solveTypes False [ty] kargs synVar) synVars syns
101101 return (syn_ks, data_ks)
102102 where
103103 tidyUp ((ks1, ks2), sub) = (map (starIfUnknown . (sub $?)) ks1, map (starIfUnknown . (sub $?)) ks2)
@@ -105,11 +105,14 @@ kindsOfAll moduleName syns tys = fmap tidyUp . liftUnify $ do
105105-- |
106106-- Solve the set of kind constraints associated with the data constructors for a type constructor
107107--
108−solveTypes :: [Type] -> [Kind] -> Kind -> UnifyT Kind Check Kind
109−solveTypes ts kargs tyCon = do
108+solveTypes :: Bool -> [Type] -> [Kind] -> Kind -> UnifyT Kind Check Kind
109+solveTypes isData ts kargs tyCon = do
110110 ks <- mapM infer ts
111− tyCon =?= foldr FunKind Star kargs
112− forM_ ks $ \k -> k =?= Star
111+ when isData $ do
112+ tyCon =?= foldr FunKind Star kargs
113+ forM_ ks $ \k -> k =?= Star
114+ when (not isData) $ do
115+ tyCon =?= foldr FunKind (head ks) kargs
113116 return tyCon
114117
115118-- |
@@ -117,6 +120,7 @@ solveTypes ts kargs tyCon = do
117120--
118121starIfUnknown :: Kind -> Kind
119122starIfUnknown (KUnknown _) = Star
123+starIfUnknown (Row k) = Row (starIfUnknown k)
120124starIfUnknown (FunKind k1 k2) = FunKind (starIfUnknown k1) (starIfUnknown k2)
121125starIfUnknown k = k
122126
@@ -124,10 +128,6 @@ starIfUnknown k = k
124128-- Infer a kind for a type
125129--
126130infer :: Type -> UnifyT Kind Check Kind
127−infer (Object row) = do
128− k <- infer row
129− k =?= Row Star
130− return Star
131131infer (TypeVar v) = do
132132 Just moduleName <- checkCurrentModule <$> get
133133 UnifyT . lift $ lookupTypeVariable moduleName (Qualified Nothing (ProperName v))
src/Language/PureScript/TypeChecker/Types.hs+28−16
@@ -107,7 +107,6 @@ unifyTypes t1 t2 = rethrow (\e -> "Error unifying type " ++ prettyPrintType t1 +
107107 sk `unifyTypes` ty2
108108 unifyTypes' ForAll{} _ = throwError "Skolem variable scope is unspecified"
109109 unifyTypes' ty f@ForAll{} = f `unifyTypes` ty
110− unifyTypes' (Object row1) (Object row2) = row1 =?= row2
111110 unifyTypes' (TypeVar v1) (TypeVar v2) | v1 == v2 = return ()
112111 unifyTypes' (TypeConstructor c1) (TypeConstructor c2) =
113112 guardWith ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".") (c1 == c2)
@@ -475,6 +474,12 @@ expandTypeSynonym name args = do
475474 env <- getEnv
476475 either throwError return $ expandTypeSynonym' env name args
477476
477+expandAllTypeSynonyms :: (Functor m, Monad m, MonadState CheckState m, MonadError String m) => Type -> m Type
478+expandAllTypeSynonyms = everywhereM' (mkM go)
479+ where
480+ go (SaturatedTypeSynonym name args) = expandTypeSynonym name args
481+ go other = return other
482+
478483-- |
479484-- Ensure a set of property names and value does not contain duplicate labels
480485--
@@ -503,7 +508,7 @@ infer' (ObjectLiteral ps) = do
503508 ensureNoDuplicateProperties ps
504509 ts <- mapM (infer . snd) ps
505510 let fields = zipWith (\name (TypedValue _ _ t) -> (name, t)) (map fst ps) ts
506− ty = Object $ rowFromList (fields, REmpty)
511+ ty = TypeApp tyObject $ rowFromList (fields, REmpty)
507512 return $ TypedValue True (ObjectLiteral (zip (map fst ps) ts)) ty
508513infer' (ObjectUpdate o ps) = do
509514 ensureNoDuplicateProperties ps
@@ -511,9 +516,9 @@ infer' (ObjectUpdate o ps) = do
511516 newVals <- zipWith (\(name, _) t -> (name, t)) ps <$> mapM (infer . snd) ps
512517 let newTys = map (\(name, TypedValue _ _ ty) -> (name, ty)) newVals
513518 oldTys <- zip (map fst ps) <$> replicateM (length ps) fresh
514− let oldTy = Object $ rowFromList (oldTys, row)
519+ let oldTy = TypeApp tyObject $ rowFromList (oldTys, row)
515520 o' <- TypedValue True <$> check o oldTy <*> pure oldTy
516− return $ TypedValue True (ObjectUpdate o' newVals) $ Object $ rowFromList (newTys, row)
521+ return $ TypedValue True (ObjectUpdate o' newVals) $ TypeApp tyObject $ rowFromList (newTys, row)
517522infer' (Accessor prop val) = do
518523 typed@(TypedValue _ _ objTy) <- infer val
519524 propTy <- inferProperty objTy prop
@@ -521,7 +526,7 @@ infer' (Accessor prop val) = do
521526 Nothing -> do
522527 field <- fresh
523528 rest <- fresh
524− _ <- subsumes Nothing objTy (Object (RCons prop field rest))
529+ _ <- subsumes Nothing objTy (TypeApp tyObject (RCons prop field rest))
525530 return $ TypedValue True (Accessor prop typed) field
526531 Just ty -> return $ TypedValue True (Accessor prop typed) ty
527532infer' (Abs (Left arg) ret) = do
@@ -593,7 +598,7 @@ inferLetBinding _ _ _ _ = error "Invalid argument to fromValueDeclaration"
593598-- Infer the type of a property inside a record with a given type
594599--
595600inferProperty :: Type -> String -> UnifyT Type Check (Maybe Type)
596−inferProperty (Object row) prop = do
601+inferProperty (TypeApp obj row) prop | obj == tyObject = do
597602 let (props, _) = rowToList row
598603 return $ lookup prop props
599604inferProperty (SaturatedTypeSynonym name args) prop = do
@@ -632,7 +637,7 @@ inferBinder val (ObjectBinder props) = do
632637 row <- fresh
633638 rest <- fresh
634639 m1 <- inferRowProperties row rest props
635− val =?= Object row
640+ val =?= TypeApp tyObject row
636641 return m1
637642 where
638643 inferRowProperties :: Type -> Type -> [(String, Binder)] -> UnifyT Type Check (M.Map Ident Type)
@@ -736,8 +741,7 @@ check' val t@(ConstrainedType constraints ty) = do
736741 return $ TypedValue True (foldr (Abs . Left) val' dictNames) t
737742check' val (SaturatedTypeSynonym name args) = do
738743 ty <- introduceSkolemScope <=< expandTypeSynonym name $ args
739− val' <- check val ty
740− return $ TypedValue True val' ty
744+ check val ty
741745check' val u@(TUnknown _) = do
742746 val'@(TypedValue _ _ ty) <- infer val
743747 -- Don't unify an unknown with an inferred polytype
@@ -792,22 +796,22 @@ check' (IfThenElse cond th el) ty = do
792796 th' <- check th ty
793797 el' <- check el ty
794798 return $ TypedValue True (IfThenElse cond' th' el') ty
795−check' (ObjectLiteral ps) t@(Object row) = do
799+check' (ObjectLiteral ps) t@(TypeApp obj row) | obj == tyObject = do
796800 ensureNoDuplicateProperties ps
797801 ps' <- checkProperties ps row False
798802 return $ TypedValue True (ObjectLiteral ps') t
799−check' (ObjectUpdate obj ps) t@(Object row) = do
803+check' (ObjectUpdate obj ps) t@(TypeApp o row) | o == tyObject = do
800804 ensureNoDuplicateProperties ps
801805 us <- zip (map fst ps) <$> replicateM (length ps) fresh
802806 let (propsToCheck, rest) = rowToList row
803807 propsToRemove = map fst ps
804808 remainingProps = filter (\(p, _) -> p `notElem` propsToRemove) propsToCheck
805− obj' <- check obj (Object (rowFromList (us ++ remainingProps, rest)))
809+ obj' <- check obj (TypeApp tyObject (rowFromList (us ++ remainingProps, rest)))
806810 ps' <- checkProperties ps row True
807811 return $ TypedValue True (ObjectUpdate obj' ps') t
808812check' (Accessor prop val) ty = do
809813 rest <- fresh
810− val' <- check val (Object (RCons prop ty rest))
814+ val' <- check val (TypeApp tyObject (RCons prop ty rest))
811815 return $ TypedValue True (Accessor prop val') ty
812816check' (Constructor c) ty = do
813817 env <- getEnv
@@ -820,8 +824,16 @@ check' (Constructor c) ty = do
820824check' (Let ds val) ty = do
821825 (ds', val') <- inferLetBinding [] ds val (flip check ty)
822826 return $ TypedValue True (Let ds' val') ty
827+check' val ty | containsTypeSynonyms ty = do
828+ ty' <- introduceSkolemScope <=< expandAllTypeSynonyms $ ty
829+ check val ty'
823830check' val ty = throwError $ prettyPrintValue val ++ " does not have type " ++ prettyPrintType ty
824831
832+containsTypeSynonyms :: Type -> Bool
833+containsTypeSynonyms = everything (||) (mkQ False go) where
834+ go (SaturatedTypeSynonym _ _) = True
835+ go _ = False
836+
825837-- |
826838-- Check the type of a collection of named record fields
827839--
@@ -854,7 +866,7 @@ checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
854866 v' <- check v ty
855867 ps'' <- go ps' (delete (p, ty) ts) r
856868 return $ (p, v') : ps''
857− go _ _ _ = throwError $ prettyPrintValue (ObjectLiteral ps) ++ " does not have type " ++ prettyPrintType (Object row)
869+ go _ _ _ = throwError $ prettyPrintValue (ObjectLiteral ps) ++ " does not have type " ++ prettyPrintType (TypeApp tyObject row)
858870
859871-- |
860872-- Check the type of a function application, rethrowing errors to provide a better error message
@@ -939,7 +951,7 @@ subsumes' (Just val) (ConstrainedType constraints ty1) ty2 = do
939951 dicts <- getTypeClassDictionaries
940952 _ <- subsumes' Nothing ty1 ty2
941953 return . Just $ foldl App val (map (flip TypeClassDictionary dicts) constraints)
942−subsumes' val (Object r1) (Object r2) = do
954+subsumes' val (TypeApp f1 r1) (TypeApp f2 r2) | f1 == tyObject && f2 == tyObject = do
943955 let
944956 (ts1, r1') = rowToList r1
945957 (ts2, r2') = rowToList r2
@@ -959,7 +971,7 @@ subsumes' val (Object r1) (Object r2) = do
959971 | otherwise = do rest <- fresh
960972 r1' =?= RCons p2 ty2 rest
961973 go ((p1, ty1) : ts1) ts2 rest r2'
962−subsumes' val ty1 ty2@(Object _) = subsumes val ty2 ty1
974+subsumes' val ty1 ty2@(TypeApp obj _) | obj == tyObject = subsumes val ty2 ty1
963975subsumes' val ty1 ty2 = do
964976 ty1 =?= ty2
965977 return val
src/Language/PureScript/Types.hs+4−12
@@ -40,10 +40,6 @@ data Type
4040 --
4141 = TUnknown Unknown
4242 -- |
43− -- Javascript numbers
44− --
45− | Object Type
46− -- |
4743 -- A named type variable
4844 --
4945 | TypeVar String
@@ -90,6 +86,10 @@ data Type
9086 -- |
9187 -- A placeholder used in pretty printing
9288 --
89+ | PrettyPrintObject Type
90+ -- |
91+ -- A placeholder used in pretty printing
92+ --
9393 | PrettyPrintForAll [String] Type deriving (Show, Eq, Data, Typeable)
9494
9595-- |
@@ -120,12 +120,6 @@ isMonoType _ = True
120120mkForAll :: [String] -> Type -> Type
121121mkForAll args ty = foldl (\t arg -> ForAll arg t Nothing) ty args
122122
123−-- |
124−-- The empty record type
125−--
126−unit :: Type
127−unit = Object REmpty
128−
129123-- |
130124-- Replace a type variable, taking into account variable shadowing
131125--
@@ -135,7 +129,6 @@ replaceTypeVars = replaceTypeVars' []
135129 replaceTypeVars' bound name replacement = go bound
136130 where
137131 go :: [String] -> Type -> Type
138− go bs (Object r) = Object $ go bs r
139132 go _ (TypeVar v) | v == name = replacement
140133 go bs (TypeApp t1 t2) = TypeApp (go bs t1) (go bs t2)
141134 go bs (SaturatedTypeSynonym name' ts) = SaturatedTypeSynonym name' $ map (go bs) ts
@@ -176,7 +169,6 @@ freeTypeVariables :: Type -> [String]
176169freeTypeVariables = nub . go []
177170 where
178171 go :: [String] -> Type -> [String]
179− go bound (Object r) = go bound r
180172 go bound (TypeVar v) | v `notElem` bound = [v]
181173 go bound (TypeApp t1 t2) = go bound t1 ++ go bound t2
182174 go bound (SaturatedTypeSynonym _ ts) = concatMap (go bound) ts