purescript 0.3.6.1 → 0.3.7
raw patch · 22 files changed
+348/−286 lines, 22 files
Files
- libraries/prelude/prelude.purs +87/−21
- psci/Main.hs +1/−1
- purescript.cabal +1/−1
- src/Language/PureScript/CodeGen/JS.hs +17/−17
- src/Language/PureScript/Declarations.hs +1/−1
- src/Language/PureScript/Names.hs +6/−1
- src/Language/PureScript/Parser/Declarations.hs +1/−4
- src/Language/PureScript/Parser/Types.hs +12/−16
- src/Language/PureScript/Parser/Values.hs +2/−10
- src/Language/PureScript/Pretty/Common.hs +21/−0
- src/Language/PureScript/Pretty/Types.hs +2/−12
- src/Language/PureScript/Pretty/Values.hs +5/−5
- src/Language/PureScript/Scope.hs +1/−1
- src/Language/PureScript/Sugar/CaseDeclarations.hs +7/−11
- src/Language/PureScript/Sugar/DoNotation.hs +3/−3
- src/Language/PureScript/Sugar/Operators.hs +2/−2
- src/Language/PureScript/Sugar/TypeClasses.hs +11/−15
- src/Language/PureScript/TypeChecker.hs +2/−2
- src/Language/PureScript/TypeChecker/Kinds.hs +0/−10
- src/Language/PureScript/TypeChecker/Types.hs +127/−119
- src/Language/PureScript/Types.hs +37/−32
- src/Language/PureScript/Values.hs +2/−2
libraries/prelude/prelude.purs view
@@ -1,5 +1,11 @@ module Prelude where + foreign import data String :: *+ foreign import data Number :: *+ foreign import data Boolean :: *+ foreign import data Array :: * -> *+ foreign import data Function :: * -> * -> *+ id :: forall a. a -> a id = \x -> x @@ -401,28 +407,76 @@ module Math where - type Math = - { abs :: Number -> Number- , acos :: Number -> Number- , asin :: Number -> Number- , atan :: Number -> Number- , atan2 :: (Number, Number) -> Number- , aceil :: Number -> Number- , cos :: Number -> Number- , exp :: Number -> Number- , floor :: Number -> Number- , log :: Number -> Number- , max :: (Number, Number) -> Number- , pow :: (Number, Number) -> Number- , random :: () -> Number- , round :: Number -> Number- , sin :: Number -> Number- , sqrt :: Number -> Number- , tan :: Number -> Number- }+ foreign import abs "function abs(n){\+ \ return Math.abs(n);\+ \}" :: Number -> Number - foreign import math "var math = Math;" :: Math- + foreign import acos "function acos(n){\+ \ return Math.acos(n);\+ \}" :: Number -> Number++ foreign import asin "function asin(n){\+ \ return Math.asin(n);\+ \}" :: Number -> Number++ foreign import atan "function atan(n){\+ \ return Math.atan(n);\+ \}" :: Number -> Number++ foreign import atan2 "function atan2(y){\+ \ return function (x) {\+ \ return Math.atan2(y, x);\+ \ };\+ \}" :: Number -> Number -> Number++ foreign import aceil "function aceil(n){\+ \ return Math.aceil(n);\+ \}" :: Number -> Number++ foreign import cos "function cos(n){\+ \ return Math.cos(n);\+ \}" :: Number -> Number++ foreign import exp "function exp(n){\+ \ return Math.exp(n);\+ \}" :: Number -> Number++ foreign import floor "function floor(n){\+ \ return Math.floor(n);\+ \}" :: Number -> Number++ foreign import log "function log(n){\+ \ return Math.log(n);\+ \}" :: Number -> Number++ foreign import max "function max(n){\+ \ return Math.max(n);\+ \}" :: Number -> Number++ foreign import min "function min(n){\+ \ return Math.min(n);\+ \}" :: Number -> Number++ foreign import pow "function pow(n){\+ \ return Math.pow(n);\+ \}" :: Number -> Number++ foreign import round "function round(n){\+ \ return Math.round(n);\+ \}" :: Number -> Number++ foreign import sin "function sin(n){\+ \ return Math.sin(n);\+ \}" :: Number -> Number++ foreign import sqrt "function sqrt(n){\+ \ return Math.sqrt(n);\+ \}" :: Number -> Number++ foreign import tan "function tan(n){\+ \ return Math.tan(n);\+ \}" :: Number -> Number+ module Eff where foreign import data Eff :: # ! -> * -> *@@ -450,6 +504,18 @@ instance Prelude.Monad (Eff e) where ret = retEff (>>=) = bindEff++module Random where++ import Eff++ foreign import data Random :: !++ foreign import random "function random() {\+ \ return function() {\+ \ return Math.random();\+ \ };\+ \}" :: forall e. Eff (random :: Random | e) Number module Errors where
psci/Main.hs view
@@ -64,7 +64,7 @@ trace = P.Var (P.Qualified (Just traceModule) (P.Ident "print")) mainDecl = P.ValueDeclaration (P.Ident "main") [] Nothing (P.Do [ P.DoNotationBind (P.VarBinder (P.Ident "it")) value- , P.DoNotationValue (P.App trace [ P.Var (P.Qualified Nothing (P.Ident "it")) ] )+ , P.DoNotationValue (P.App trace (P.Var (P.Qualified Nothing (P.Ident "it"))) ) ]) in P.Module moduleName $ map (importDecl . P.ModuleName) imports ++ [mainDecl]
purescript.cabal view
@@ -1,5 +1,5 @@ name: purescript-version: 0.3.6.1+version: 0.3.7 cabal-version: >=1.8 build-type: Simple license: MIT
src/Language/PureScript/CodeGen/JS.hs view
@@ -110,9 +110,9 @@ valueToJs opts m e (IfThenElse cond th el) = JSConditional (valueToJs opts m e cond) (valueToJs opts m e th) (valueToJs opts m e el) valueToJs opts m e (Accessor prop val) = JSAccessor prop (valueToJs opts m e val) valueToJs opts m e (Indexer index val) = JSIndexer (valueToJs opts m e index) (valueToJs opts m e val)-valueToJs opts m e (App val args) = JSApp (valueToJs opts m e val) (map (valueToJs opts m e) args)-valueToJs opts m e (Abs args val) = JSFunction Nothing args (JSBlock [JSReturn (valueToJs opts m e val)])-valueToJs opts m e (TypedValue _ (Abs args val) ty) | optionsPerformRuntimeTypeChecks opts = JSFunction Nothing args (JSBlock $ runtimeTypeChecks args ty ++ [JSReturn (valueToJs opts m e val)])+valueToJs opts m e (App val arg) = JSApp (valueToJs opts m e val) [valueToJs opts m e arg]+valueToJs opts m e (Abs arg val) = JSFunction Nothing [arg] (JSBlock [JSReturn (valueToJs opts m e val)])+valueToJs opts m e (TypedValue _ (Abs arg val) ty) | optionsPerformRuntimeTypeChecks opts = JSFunction Nothing [arg] (JSBlock $ runtimeTypeChecks arg ty ++ [JSReturn (valueToJs opts m e val)]) valueToJs opts m e (Unary op val) = JSUnary op (valueToJs opts m e val) valueToJs opts m e (Binary op v1 v2) = JSBinary op (valueToJs opts m e v1) (valueToJs opts m e v2) valueToJs _ m e (Var ident) = varToJs m e ident@@ -120,28 +120,28 @@ valueToJs _ _ _ (TypeClassDictionary _ _) = error "Type class dictionary was not replaced" valueToJs _ _ _ _ = error "Invalid argument to valueToJs" -runtimeTypeChecks :: [Ident] -> Type -> [JS]-runtimeTypeChecks args ty =+runtimeTypeChecks :: Ident -> Type -> [JS]+runtimeTypeChecks arg ty = let- argTys = getFunctionArgumentTypes ty+ argTy = getFunctionArgumentType ty in- concat $ zipWith argumentCheck (map JSVar args) argTys+ maybe [] (argumentCheck (JSVar arg)) argTy where- getFunctionArgumentTypes :: Type -> [Type]- getFunctionArgumentTypes (Function funArgs _) = funArgs- getFunctionArgumentTypes (ForAll _ ty') = getFunctionArgumentTypes ty'- getFunctionArgumentTypes _ = []+ getFunctionArgumentType :: Type -> Maybe Type+ getFunctionArgumentType (TypeApp (TypeApp t funArg) _) | t == tyFunction = Just funArg+ getFunctionArgumentType (ForAll _ ty') = getFunctionArgumentType ty'+ getFunctionArgumentType _ = Nothing argumentCheck :: JS -> Type -> [JS]- argumentCheck val Number = [typeCheck val "number"]- argumentCheck val String = [typeCheck val "string"]- argumentCheck val Boolean = [typeCheck val "boolean"]- argumentCheck val (TypeApp Array _) = [arrayCheck val]+ argumentCheck val t | t == tyNumber = [typeCheck val "number"]+ argumentCheck val t | t == tyString = [typeCheck val "string"]+ argumentCheck val t | t == tyBoolean = [typeCheck val "boolean"]+ argumentCheck val (TypeApp t _) | t == tyArray = [arrayCheck val] argumentCheck val (Object row) = let (pairs, _) = rowToList row in typeCheck val "object" : concatMap (\(prop, ty') -> argumentCheck (JSAccessor prop val) ty') pairs- argumentCheck val (Function _ _) = [typeCheck val "function"]+ argumentCheck val (TypeApp (TypeApp t _) _) | t == tyFunction = [typeCheck val "function"] argumentCheck val (ForAll _ ty') = argumentCheck val ty' argumentCheck _ _ = [] typeCheck :: JS -> String -> JS@@ -253,7 +253,7 @@ numConstructors ty = length $ filter (\(ty1, _) -> ((==) `on` typeConstructor) ty ty1) $ M.elems $ dataConstructors e typeConstructor (TypeConstructor qual) = qualify m qual typeConstructor (ForAll _ ty) = typeConstructor ty- typeConstructor (Function _ ty) = typeConstructor ty+ typeConstructor (TypeApp (TypeApp t _) ty) | t == tyFunction = typeConstructor ty typeConstructor (TypeApp ty _) = typeConstructor ty typeConstructor fn = error $ "Invalid arguments to typeConstructor: " ++ show fn
src/Language/PureScript/Declarations.hs view
@@ -88,7 +88,7 @@ -- | -- A value declaration (name, top-level binders, optional guard, value) --- | ValueDeclaration Ident [[Binder]] (Maybe Guard) Value+ | ValueDeclaration Ident [Binder] (Maybe Guard) Value -- | -- A minimal mutually recursive set of value declarations --
src/Language/PureScript/Names.hs view
@@ -30,11 +30,16 @@ -- | -- A symbolic name for an infix operator --- | Op String deriving (Eq, Ord, Data, Typeable)+ | Op String+ -- |+ -- An escaped name+ --+ | Escaped String deriving (Eq, Ord, Data, Typeable) instance Show Ident where show (Ident s) = s show (Op op) = '(':op ++ ")"+ show (Escaped s) = s -- | -- Proper names, i.e. capitalized names for e.g. module names, type//data constructors.
src/Language/PureScript/Parser/Declarations.hs view
@@ -58,12 +58,9 @@ parseValueDeclaration :: P.Parsec String ParseState Declaration parseValueDeclaration = ValueDeclaration <$> parseNonReservedIdent- <*> P.many parseTopLevelBinder+ <*> P.many parseBinderNoParens <*> P.optionMaybe parseGuard <*> ((lexeme (indented *> P.char '=')) *> parseValue)--parseTopLevelBinder :: P.Parsec String ParseState [Binder]-parseTopLevelBinder = return <$> P.try parseBinderNoParens <|> parens (commaSep parseBinder) parseExternDeclaration :: P.Parsec String ParseState Declaration parseExternDeclaration = P.try (reserved "foreign") *> indented *> (reserved "import") *> indented *>
src/Language/PureScript/Parser/Types.hs view
@@ -27,30 +27,26 @@ import Control.Monad (when, unless) parseNumber :: P.Parsec String ParseState Type-parseNumber = const Number <$> reserved "Number"+parseNumber = const tyNumber <$> reserved "Number" parseString :: P.Parsec String ParseState Type-parseString = const String <$> reserved "String"+parseString = const tyString <$> reserved "String" parseBoolean :: P.Parsec String ParseState Type-parseBoolean = const Boolean <$> reserved "Boolean"+parseBoolean = const tyBoolean <$> reserved "Boolean" parseArray :: P.Parsec String ParseState Type-parseArray = squares $ return Array+parseArray = squares $ return tyArray parseArrayOf :: P.Parsec String ParseState Type-parseArrayOf = squares $ TypeApp Array <$> parseType+parseArrayOf = squares $ TypeApp tyArray <$> parseType +parseFunction :: P.Parsec String ParseState Type+parseFunction = parens $ P.try (lexeme (P.string "->")) >> return tyFunction+ parseObject :: P.Parsec String ParseState Type parseObject = braces $ Object <$> parseRow False -parseFunction :: P.Parsec String ParseState Type-parseFunction = do- args <- lexeme $ parens $ commaSep parsePolyType- _ <- lexeme $ P.string "->"- resultType <- parseType- return $ Function args resultType- parseTypeVariable :: P.Parsec String ParseState Type parseTypeVariable = TypeVar <$> identifier @@ -68,12 +64,13 @@ , parseBoolean , parseArray , parseArrayOf+ , parseFunction , parseObject , parseTypeVariable , parseTypeConstructor , parseForAll , parens (parseRow True)- , parens parseType ])+ , parens parsePolyType ]) parseConstrainedType :: P.Parsec String ParseState Type parseConstrainedType = do@@ -90,10 +87,10 @@ return $ maybe ty (flip ConstrainedType ty) constraints parseAnyType :: P.Parsec String ParseState Type-parseAnyType = (P.buildExpressionParser operators $ parseTypeAtom) <|> parseFunction P.<?> "type"+parseAnyType = (P.buildExpressionParser operators $ parseTypeAtom) P.<?> "type" where operators = [ [ P.Infix (return TypeApp) P.AssocLeft ]- , [ P.Infix (P.try (lexeme (P.string "->")) >> return (\t1 t2 -> Function [t1] t2)) P.AssocRight ] ]+ , [ P.Infix (P.try (lexeme (P.string "->")) >> return function) P.AssocRight ] ] -- | -- Parse a monotype@@ -110,7 +107,6 @@ parsePolyType :: P.Parsec String ParseState Type parsePolyType = do ty <- parseAnyType- unless (isPolyType ty) $ P.unexpected "polymorphic type" return ty parseNameAndType :: P.Parsec String ParseState t -> P.Parsec String ParseState (String, t)
src/Language/PureScript/Parser/Values.hs view
@@ -54,19 +54,12 @@ parseAbs :: P.Parsec String ParseState Value parseAbs = do C.reservedOp "\\"- args <- P.many (C.indented *> (P.try singleArg <|> manyArgs))+ args <- P.many1 (C.indented *> (Abs <$> C.parseIdent)) C.indented *> C.reservedOp "->" value <- parseValue return $ toFunction args value where- manyArgs :: P.Parsec String ParseState (Value -> Value)- manyArgs = do- args <- C.parens (C.commaSep C.parseIdent)- return $ Abs args- singleArg :: P.Parsec String ParseState (Value -> Value)- singleArg = Abs . return <$> C.parseIdent toFunction :: [Value -> Value] -> Value -> Value- toFunction [] value = Abs [] value toFunction args value = foldr (($)) value args parseVar :: P.Parsec String ParseState Value@@ -159,8 +152,7 @@ indexersAndAccessors = C.buildPostfixParser postfixTable1 parseValueAtom postfixTable1 = [ parseAccessor , \v -> P.try $ flip ObjectUpdate <$> (C.indented *> C.braces (C.commaSep1 (C.indented *> parsePropertyUpdate))) <*> pure v ]- postfixTable2 = [ \v -> P.try (C.indented *> indexersAndAccessors >>= \t2 -> return (\t1 -> App t1 [t2])) <*> pure v- , \v -> P.try $ flip App <$> (C.indented *> C.parens (C.commaSep parseValue)) <*> pure v+ postfixTable2 = [ \v -> P.try (C.indented *> indexersAndAccessors >>= return . flip App) <*> pure v , \v -> flip (TypedValue True) <$> (P.try (C.lexeme (C.indented *> P.string "::")) *> parsePolyType) <*> pure v ] operators = [ [ Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "!") >> return (Unary Not)
src/Language/PureScript/Pretty/Common.hs view
@@ -36,10 +36,31 @@ identToJs :: Ident -> String identToJs (Ident name) = concatMap identCharToString name identToJs (Op op) = concatMap identCharToString op+identToJs (Escaped name) = name identCharToString :: Char -> String identCharToString c | isAlphaNum c = [c] identCharToString '_' = "_"+identCharToString '.' = "$dot"+identCharToString '$' = "$dollar"+identCharToString '~' = "$tilde"+identCharToString '=' = "$eq"+identCharToString '<' = "$less"+identCharToString '>' = "$greater"+identCharToString '!' = "$bang"+identCharToString '#' = "$hash"+identCharToString '%' = "$percent"+identCharToString '^' = "$up"+identCharToString '&' = "$amp"+identCharToString '|' = "$bar"+identCharToString '*' = "$times"+identCharToString '/' = "$div"+identCharToString '+' = "$plus"+identCharToString '-' = "$minus"+identCharToString ':' = "$colon"+identCharToString '\\' = "$bslash"+identCharToString '?' = "$qmark"+identCharToString '@' = "$at" identCharToString c = '$' : show (ord c) -- |
src/Language/PureScript/Pretty/Types.hs view
@@ -31,12 +31,9 @@ typeLiterals :: Pattern () Type String typeLiterals = mkPattern match where- match Number = Just "Number"- match String = Just "String"- match Boolean = Just "Boolean"- match Array = Just $ "[]" match (Object row) = Just $ "{ " ++ prettyPrintType row ++ " }" match (TypeVar var) = Just var+ match (TypeApp arr ty) | arr == tyArray = Just $ "[" ++ prettyPrintType ty ++ "]" match (TypeConstructor ctor) = Just $ show ctor match (TUnknown (TypedUnknown (Unknown u))) = Just $ 'u' : show u match (Skolem s) = Just $ 's' : show s@@ -74,13 +71,7 @@ singleArgumentFunction :: Pattern () Type (Type, Type) singleArgumentFunction = mkPattern match where- match (Function [arg] ret) = Just (arg, ret)- match _ = Nothing--function :: Pattern () Type ([Type], Type)-function = mkPattern match- where- match (Function args ret) = Just (args, ret)+ match (TypeApp (TypeApp t arg) ret) | t == tyFunction = Just (arg, ret) match _ = Nothing -- |@@ -95,6 +86,5 @@ operators = OperatorTable [ [ AssocL typeApp $ \f x -> f ++ " " ++ x ] , [ AssocR singleArgumentFunction $ \arg ret -> arg ++ " -> " ++ ret- , Wrap function $ \args ret -> "(" ++ intercalate ", " (map prettyPrintType args) ++ ") -> " ++ ret ] ]
src/Language/PureScript/Pretty/Values.hs view
@@ -77,13 +77,13 @@ app :: Pattern () Value (String, Value) app = mkPattern match where- match (App val args) = Just (intercalate "," (map prettyPrintValue args), val)+ match (App val arg) = Just (prettyPrintValue arg, val) match _ = Nothing -lam :: Pattern () Value ([String], Value)+lam :: Pattern () Value (String, Value) lam = mkPattern match where- match (Abs args val) = Just (map show args, val)+ match (Abs arg val) = Just (show arg, val) match _ = Nothing typed :: Pattern () Value (Type, Value)@@ -127,8 +127,8 @@ operators = OperatorTable [ [ Wrap accessor $ \prop val -> val ++ "." ++ prop ] , [ Wrap objectUpdate $ \ps val -> val ++ "{ " ++ intercalate ", " ps ++ " }" ]- , [ Wrap app $ \args val -> val ++ "(" ++ args ++ ")" ]- , [ Split lam $ \args val -> "\\" ++ intercalate ", " args ++ " -> " ++ prettyPrintValue val ]+ , [ Wrap app $ \arg val -> val ++ "(" ++ arg ++ ")" ]+ , [ Split lam $ \arg val -> "\\" ++ arg ++ " -> " ++ prettyPrintValue val ] , [ Wrap ifThenElse $ \(th, el) cond -> cond ++ " ? " ++ prettyPrintValue th ++ " : " ++ prettyPrintValue el ] , [ Wrap typed $ \ty val -> val ++ " :: " ++ prettyPrintType ty ] , [ AssocR indexer (\index val -> val ++ " !! " ++ index) ]
src/Language/PureScript/Scope.hs view
@@ -33,7 +33,7 @@ usedNames val = nub $ everything (++) (mkQ [] namesV `extQ` namesS `extQ` namesB `extQ` namesJS) val where namesV :: Value -> [Ident]- namesV (Abs args _) = args+ namesV (Abs arg _) = [arg] namesV (Var (Qualified Nothing name)) = [name] namesV _ = [] namesS :: Statement -> [Ident]
src/Language/PureScript/Sugar/CaseDeclarations.hs view
@@ -48,27 +48,23 @@ toDecls d@[ValueDeclaration _ [] Nothing _] = return d toDecls ds@(ValueDeclaration ident bs _ _ : _) = do let tuples = map toTuple ds- unless (all ((== map length bs) . map length . fst) tuples) $+ unless (all ((== length bs) . length . fst) tuples) $ throwError $ "Argument list lengths differ in declaration " ++ show ident return [makeCaseDeclaration ident tuples] toDecls ds = return ds -toTuple :: Declaration -> ([[Binder]], (Maybe Guard, Value))+toTuple :: Declaration -> ([Binder], (Maybe Guard, Value)) toTuple (ValueDeclaration _ bs g val) = (bs, (g, val)) toTuple _ = error "Not a value declaration" -makeCaseDeclaration :: Ident -> [([[Binder]], (Maybe Guard, Value))] -> Declaration+makeCaseDeclaration :: Ident -> [([Binder], (Maybe Guard, Value))] -> Declaration makeCaseDeclaration ident alternatives = let- argPattern = map length . fst . head $ alternatives- args = take (sum argPattern) $ unusedNames (ident, alternatives)+ argPattern = length . fst . head $ alternatives+ args = take argPattern $ unusedNames (ident, alternatives) vars = map (\arg -> Var (Qualified Nothing arg)) args- binders = [ (join bs, g, val) | (bs, (g, val)) <- alternatives ]- value = foldr (\args' ret -> Abs args' ret) (Case vars binders) (rearrange argPattern args)+ binders = [ (bs, g, val) | (bs, (g, val)) <- alternatives ]+ value = foldr (\args' ret -> Abs args' ret) (Case vars binders) args in ValueDeclaration ident [] Nothing value--rearrange :: [Int] -> [a] -> [[a]]-rearrange [] _ = []-rearrange (n:ns) xs = take n xs : rearrange ns (drop n xs)
src/Language/PureScript/Sugar/DoNotation.hs view
@@ -46,16 +46,16 @@ go [DoNotationValue val] = return val go (DoNotationValue val : rest) = do rest' <- go rest- return $ App (App bind [val]) [Abs [Ident "_"] rest']+ return $ App (App bind val) (Abs (Ident "_") rest') go [DoNotationBind _ _] = Left "Bind statement cannot be the last statement in a do block" go (DoNotationBind NullBinder val : rest) = go (DoNotationValue val : rest) go (DoNotationBind (VarBinder ident) val : rest) = do rest' <- go rest- return $ App (App bind [val]) [Abs [ident] rest']+ return $ App (App bind val) (Abs ident rest') go (DoNotationBind binder val : rest) = do rest' <- go rest let ident = head $ unusedNames rest'- return $ App (App bind [val]) [Abs [ident] (Case [Var (Qualified Nothing ident)] [([binder], Nothing, rest')])]+ return $ App (App bind val) (Abs ident (Case [Var (Qualified Nothing ident)] [([binder], Nothing, rest')])) go [DoNotationLet _ _] = Left "Let statement cannot be the last statement in a do block" go (DoNotationLet binder val : rest) = do rest' <- go rest
src/Language/PureScript/Sugar/Operators.hs view
@@ -58,7 +58,7 @@ customOperatorTable :: M.Map (Qualified Ident) Fixity -> [[(Qualified Ident, Value -> Value -> Value, Associativity)]] customOperatorTable fixities = let- applyUserOp name t1 t2 = App (App (Var name) [t1]) [t2]+ applyUserOp name t1 t2 = App (App (Var name) t1) t2 userOps = map (\(name, Fixity a p) -> (name, applyUserOp name, p, a)) . M.toList $ fixities sorted = sortBy (compare `on` (\(_, _, p, _) -> p)) (userOps ++ builtIns) groups = groupBy ((==) `on` (\(_, _, p, _) -> p)) sorted@@ -79,7 +79,7 @@ bracketChain :: Chain -> Either String Value bracketChain = either (Left . show) Right . P.parse (P.buildExpressionParser opTable parseValue <* P.eof) "operator expression" opTable = map (map (\(name, f, a) -> P.Infix (P.try (matchOp moduleName name) >> return f) (toAssoc a))) ops- ++ [[P.Infix (P.try (parseOp >>= \ident -> return (\t1 t2 -> App (App (Var ident) [t1]) [t2]))) P.AssocLeft]]+ ++ [[P.Infix (P.try (parseOp >>= \ident -> return (\t1 t2 -> App (App (Var ident) t1) t2))) P.AssocLeft]] toAssoc :: Associativity -> P.Assoc toAssoc Infixl = P.AssocLeft
src/Language/PureScript/Sugar/TypeClasses.hs view
@@ -87,10 +87,8 @@ memberNames <- mapM (memberToNameAndValue memberTypes) decls return $ ValueDeclaration entryName [] Nothing (TypedValue True- (Abs- (map (\n -> Ident ('_' : show n)) [1..length deps])- (ObjectLiteral memberNames))- (quantify (Function (map (\(pn, ty') -> TypeApp (TypeConstructor pn) ty') deps) (TypeApp (TypeConstructor name) ty)))+ (foldr Abs (ObjectLiteral memberNames) (map (\n -> Ident ('_' : show n)) [1..length deps]))+ (quantify (foldr function (TypeApp (TypeConstructor name) ty) (map (\(pn, ty') -> TypeApp (TypeConstructor pn) ty') deps))) ) where memberToNameAndValue :: [(String, Type)] -> Declaration -> Desugar (String, Value)@@ -99,20 +97,22 @@ memberName <- mkDictionaryEntryName mn name ty ident return (identToJs ident, TypedValue False (if null deps then Var (Qualified Nothing memberName)- else App (Var (Qualified Nothing memberName)) (map (\n -> Var (Qualified Nothing (Ident ('_' : show n)))) [1..length deps]))+ else foldl App (Var (Qualified Nothing memberName)) (map (\n -> Var (Qualified Nothing (Ident ('_' : show n)))) [1..length deps])) (quantify memberType)) memberToNameAndValue _ _ = error "Invalid declaration in type instance definition" typeInstanceDictionaryEntryDeclaration :: ModuleName -> [(Qualified ProperName, Type)] -> Qualified ProperName -> Type -> Declaration -> Desugar Declaration typeInstanceDictionaryEntryDeclaration mn deps name ty (ValueDeclaration ident [] _ val) = do m <- get- valTy <- lift $ maybe (Left $ "Type class " ++ show name ++ " is undefined. Type class names must be qualified.") Right $- do (arg, members) <- M.lookup (qualify mn name) m- ty' <- lookup (identToJs ident) members- return $ replaceTypeVars arg ty ty'+ valTy <- lift $ do (arg, members) <- lookupTypeClass m+ ty' <- lookupIdent members+ return $ replaceTypeVars arg ty ty' entryName <- mkDictionaryEntryName mn name ty ident return $ ValueDeclaration entryName [] Nothing (TypedValue True val (quantify (if null deps then valTy else ConstrainedType deps valTy)))+ where+ lookupTypeClass m = maybe (Left $ "Type class " ++ show name ++ " is undefined. Type class names must be qualified.") Right $ M.lookup (qualify mn name) m+ lookupIdent members = maybe (Left $ "Type class " ++ show name ++ " does not have method " ++ show ident) Right $ lookup (identToJs ident) members typeInstanceDictionaryEntryDeclaration _ _ _ _ _ = error "Invalid declaration in type instance definition" qualifiedToString :: ModuleName -> Qualified ProperName -> String@@ -135,14 +135,10 @@ return $ Ident $ "__" ++ qualifiedToString mn cl ++ "_" ++ tyStr typeToString :: ModuleName -> Type -> Either String String-typeToString _ String = return "string"-typeToString _ Number = return "number"-typeToString _ Boolean = return "boolean"-typeToString _ Array = return "array" typeToString _ (TypeVar _) = return "var" typeToString mn (TypeConstructor ty') = return $ qualifiedToString mn ty' typeToString mn (TypeApp ty' (TypeVar _)) = typeToString mn ty'-typeToString a b = Left $ "Type class instance must be of the form T a1 ... an " ++ show (a, b)+typeToString _ _ = Left "Type class instance must be of the form T a1 ... an" -- | -- Generate a name for a type class dictionary member, based on the module name, class name, type name and@@ -151,4 +147,4 @@ mkDictionaryEntryName :: ModuleName -> Qualified ProperName -> Type -> Ident -> Desugar Ident mkDictionaryEntryName mn name ty ident = do Ident dictName <- lift $ mkDictionaryValueName mn name ty- return $ Ident $ dictName ++ "_" ++ identToJs ident+ return $ Escaped $ dictName ++ "_" ++ identToJs ident
src/Language/PureScript/TypeChecker.hs view
@@ -51,7 +51,7 @@ env <- getEnv dataConstructorIsNotDefined moduleName dctor let retTy = foldl TypeApp (TypeConstructor (Qualified (Just moduleName) name)) (map TypeVar args)- let dctorTy = maybe retTy (\ty -> Function [ty] retTy) maybeTy+ let dctorTy = maybe retTy (flip function retTy) maybeTy let polyType = mkForAll args dctorTy putEnv $ env { dataConstructors = M.insert (moduleName, dctor) (qualifyAllUnqualifiedNames moduleName env polyType, DataConstructor) (dataConstructors env) } @@ -231,7 +231,7 @@ constructs (TypeConstructor (Qualified (Just mn) pn')) pn = mn == moduleName && pn' == pn constructs (ForAll _ ty) pn = ty `constructs` pn- constructs (Function _ ty) pn = ty `constructs` pn+ constructs (TypeApp (TypeApp t _) ty) pn | t == tyFunction = ty `constructs` pn constructs (TypeApp ty _) pn = ty `constructs` pn constructs fn _ = error $ "Invalid arguments to constructs: " ++ show fn typeCheckAll moduleName (d@(TypeClassDeclaration _ _ _) : rest) = do
src/Language/PureScript/TypeChecker/Kinds.hs view
@@ -117,19 +117,9 @@ -- Infer a kind for a type -- infer :: Type -> UnifyT Check Kind-infer Number = return Star-infer String = return Star-infer Boolean = return Star-infer Array = return $ FunKind Star Star infer (Object row) = do k <- infer row k ?= Row Star- return Star-infer (Function args ret) = do- ks <- mapM infer args- k <- infer ret- k ?= Star- forM_ ks (?= Star) return Star infer (TypeVar v) = do Just moduleName <- checkCurrentModule <$> get
src/Language/PureScript/TypeChecker/Types.hs view
@@ -95,15 +95,7 @@ sk <- skolemize ident ty1 sk `unifyTypes` ty2 unifyTypes' ty f@(ForAll _ _) = f `unifyTypes` ty- unifyTypes' Number Number = return ()- unifyTypes' String String = return ()- unifyTypes' Boolean Boolean = return ()- unifyTypes' Array Array = return () unifyTypes' (Object row1) (Object row2) = row1 ?= row2- unifyTypes' (Function args1 ret1) (Function args2 ret2) = do- guardWith "Function applied to incorrect number of args" $ length args1 == length args2- zipWithM_ unifyTypes args1 args2- ret1 `unifyTypes` ret2 unifyTypes' (TypeVar v1) (TypeVar v2) | v1 == v2 = return () unifyTypes' (TypeConstructor c1) (TypeConstructor c2) = do env <- getEnv@@ -235,14 +227,19 @@ , typeConstructorsAreEqual env moduleName className' (tcdClassName tcd) , subst <- maybeToList $ typeHeadsAreEqual moduleName env ty' (tcdInstanceType tcd) , args <- solveSubgoals env subst (tcdDependencies tcd) ]+ solveSubgoals :: Environment -> [(String, Type)] -> Maybe [(Qualified ProperName, Type)] -> [Maybe [Value]] solveSubgoals _ _ Nothing = return Nothing solveSubgoals env subst (Just subgoals) = do dict <- mapM (go env) (replaceAllTypeVars subst subgoals) return $ Just dict- mkDictionary fnName args = maybe id (flip App) args $ (Var fnName)+ mkDictionary :: Qualified Ident -> Maybe [Value] -> Value+ mkDictionary fnName Nothing = Var fnName+ mkDictionary fnName (Just dicts) = foldr (flip App) (Var fnName) dicts+ filterModule :: TypeClassDictionaryInScope -> Bool filterModule (TypeClassDictionaryInScope { tcdName = Qualified (Just mn) _ }) | mn == moduleName = True filterModule (TypeClassDictionaryInScope { tcdName = Qualified Nothing _ }) = True filterModule _ = False+ canonicalizeDictionary :: TypeClassDictionaryInScope -> Qualified Ident canonicalizeDictionary (TypeClassDictionaryInScope { tcdType = TCDRegular, tcdName = nm }) = nm canonicalizeDictionary (TypeClassDictionaryInScope { tcdType = TCDAlias nm }) = nm @@ -251,11 +248,7 @@ -- and return a substitution from type variables to types which makes the type heads unify. -- typeHeadsAreEqual :: ModuleName -> Environment -> Type -> Type -> Maybe [(String, Type)]-typeHeadsAreEqual _ _ String String = Just []-typeHeadsAreEqual _ _ Number Number = Just []-typeHeadsAreEqual _ _ Boolean Boolean = Just [] typeHeadsAreEqual _ _ (Skolem s1) (Skolem s2) | s1 == s2 = Just []-typeHeadsAreEqual _ _ Array Array = Just [] typeHeadsAreEqual m e (TypeConstructor c1) (TypeConstructor c2) | typeConstructorsAreEqual e m c1 c2 = Just [] typeHeadsAreEqual m e (TypeApp h1 (TypeVar v)) (TypeApp h2 arg) = (:) (v, arg) <$> typeHeadsAreEqual m e h1 h2 typeHeadsAreEqual m e t1@(TypeApp _ _) t2@(TypeApp _ (TypeVar _)) = typeHeadsAreEqual m e t2 t1@@ -387,13 +380,13 @@ -- Infer a type for a value -- infer' :: Value -> UnifyT Check Value-infer' v@(NumericLiteral _) = return $ TypedValue True v Number-infer' v@(StringLiteral _) = return $ TypedValue True v String-infer' v@(BooleanLiteral _) = return $ TypedValue True v Boolean+infer' v@(NumericLiteral _) = return $ TypedValue True v tyNumber+infer' v@(StringLiteral _) = return $ TypedValue True v tyString+infer' v@(BooleanLiteral _) = return $ TypedValue True v tyBoolean infer' (ArrayLiteral vals) = do ts <- mapM infer vals els <- fresh- forM_ ts $ \(TypedValue _ _ t) -> els ?= TypeApp Array t+ forM_ ts $ \(TypedValue _ _ t) -> els ?= TypeApp tyArray t return $ TypedValue True (ArrayLiteral ts) els infer' (Unary op val) = do v <- infer val@@ -418,9 +411,9 @@ return $ TypedValue True (ObjectUpdate o' newVals) $ Object $ rowFromList (newTys, row) infer' (Indexer index val) = do el <- fresh- index' <- check index Number- val' <- check val (TypeApp Array el)- return $ TypedValue True (Indexer (TypedValue True index' Number) (TypedValue True val' (TypeApp Array el))) el+ index' <- check index tyNumber+ val' <- check val (TypeApp tyArray el)+ return $ TypedValue True (Indexer (TypedValue True index' tyNumber) (TypedValue True val' (TypeApp tyArray el))) el infer' (Accessor prop val) = do typed@(TypedValue _ _ objTy) <- infer val propTy <- inferProperty objTy prop@@ -428,19 +421,19 @@ Nothing -> do field <- fresh rest <- fresh- objTy `subsumes` Object (RCons prop field rest)+ _ <- subsumes Nothing objTy (Object (RCons prop field rest)) return $ TypedValue True (Accessor prop typed) field Just ty -> return $ TypedValue True (Accessor prop typed) ty-infer' (Abs args ret) = do- ts <- replicateM (length args) fresh+infer' (Abs arg ret) = do+ ty <- fresh Just moduleName <- checkCurrentModule <$> get- bindLocalVariables moduleName (zip args ts) $ do+ bindLocalVariables moduleName [(arg, ty)] $ do body@(TypedValue _ _ bodyTy) <- infer' ret- return $ TypedValue True (Abs args body) $ Function ts bodyTy-infer' (App f args) = do+ return $ TypedValue True (Abs arg body) $ function ty bodyTy+infer' (App f arg) = do f'@(TypedValue _ _ ft) <- infer f ret <- fresh- app <- checkFunctionApplication f' ft args ret+ app <- checkFunctionApplication f' ft arg ret return $ TypedValue True app ret infer' (Var var) = do Just moduleName <- checkCurrentModule <$> get@@ -450,7 +443,7 @@ ConstrainedType constraints _ -> do env <- getEnv dicts <- getTypeClassDictionaries- return $ TypedValue True (App (Var var) (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) ty'+ return $ TypedValue True (foldl App (Var var) (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) ty' _ -> return $ TypedValue True (Var var) ty' infer' (Block ss) = do ret <- fresh@@ -470,7 +463,7 @@ binders' <- checkBinders (map (\(TypedValue _ _ t) -> t) ts) ret binders return $ TypedValue True (Case ts binders') ret infer' (IfThenElse cond th el) = do- cond' <- check cond Boolean+ cond' <- check cond tyBoolean v2@(TypedValue _ _ t2) <- infer th v3@(TypedValue _ _ t3) <- infer el t2 ?= t3@@ -525,9 +518,9 @@ -- Built-in unary operators -- unaryOps :: [(UnaryOperator, (Type, Type))]-unaryOps = [ (Negate, (Number, Number))- , (Not, (Boolean, Boolean))- , (BitwiseNot, (Number, Number))+unaryOps = [ (Negate, (tyNumber, tyNumber))+ , (Not, (tyBoolean, tyBoolean))+ , (BitwiseNot, (tyNumber, tyNumber)) ] -- |@@ -536,7 +529,7 @@ inferBinary :: BinaryOperator -> Value -> Value -> UnifyT Check Value inferBinary op left@(TypedValue _ _ leftTy) right@(TypedValue _ _ rightTy) | isEqualityTest op = do leftTy ?= rightTy- return $ TypedValue True (Binary op left right) Boolean+ return $ TypedValue True (Binary op left right) tyBoolean inferBinary op left@(TypedValue _ _ leftTy) right@(TypedValue _ _ rightTy) = case fromMaybe (error "Invalid operator") $ lookup op binaryOps of (valTy, resTy) -> do@@ -550,7 +543,7 @@ -- checkBinary :: BinaryOperator -> Value -> Value -> Type -> UnifyT Check Value checkBinary op left right res | isEqualityTest op = do- res ?= Boolean+ res ?= tyBoolean left'@(TypedValue _ _ t1) <- infer left right'@(TypedValue _ _ t2) <- infer right t1 ?= t2@@ -575,24 +568,24 @@ -- Built-in binary operators -- binaryOps :: [(BinaryOperator, (Type, Type))]-binaryOps = [ (Add, (Number, Number))- , (Subtract, (Number, Number))- , (Multiply, (Number, Number))- , (Divide, (Number, Number))- , (Modulus, (Number, Number))- , (BitwiseAnd, (Number, Number))- , (BitwiseOr, (Number, Number))- , (BitwiseXor, (Number, Number))- , (ShiftRight, (Number, Number))- , (ZeroFillShiftRight, (Number, Number))- , (And, (Boolean, Boolean))- , (Or, (Boolean, Boolean))- , (Concat, (String, String))- , (Modulus, (Number, Number))- , (LessThan, (Number, Boolean))- , (LessThanOrEqualTo, (Number, Boolean))- , (GreaterThan, (Number, Boolean))- , (GreaterThanOrEqualTo, (Number, Boolean))+binaryOps = [ (Add, (tyNumber, tyNumber))+ , (Subtract, (tyNumber, tyNumber))+ , (Multiply, (tyNumber, tyNumber))+ , (Divide, (tyNumber, tyNumber))+ , (Modulus, (tyNumber, tyNumber))+ , (BitwiseAnd, (tyNumber, tyNumber))+ , (BitwiseOr, (tyNumber, tyNumber))+ , (BitwiseXor, (tyNumber, tyNumber))+ , (ShiftRight, (tyNumber, tyNumber))+ , (ZeroFillShiftRight, (tyNumber, tyNumber))+ , (And, (tyBoolean, tyBoolean))+ , (Or, (tyBoolean, tyBoolean))+ , (Concat, (tyString, tyString))+ , (Modulus, (tyNumber, tyNumber))+ , (LessThan, (tyNumber, tyBoolean))+ , (LessThanOrEqualTo, (tyNumber, tyBoolean))+ , (GreaterThan, (tyNumber, tyBoolean))+ , (GreaterThanOrEqualTo, (tyNumber, tyBoolean)) ] -- |@@ -600,16 +593,16 @@ -- inferBinder :: Type -> Binder -> UnifyT Check (M.Map Ident Type) inferBinder _ NullBinder = return M.empty-inferBinder val (StringBinder _) = val ?= String >> return M.empty-inferBinder val (NumberBinder _) = val ?= Number >> return M.empty-inferBinder val (BooleanBinder _) = val ?= Boolean >> return M.empty+inferBinder val (StringBinder _) = val ?= tyString >> return M.empty+inferBinder val (NumberBinder _) = val ?= tyNumber >> return M.empty+inferBinder val (BooleanBinder _) = val ?= tyBoolean >> return M.empty inferBinder val (VarBinder name) = return $ M.singleton name val inferBinder val (NullaryBinder ctor) = do env <- getEnv Just moduleName <- checkCurrentModule <$> get case M.lookup (qualify moduleName ctor) (dataConstructors env) of Just (ty, _) -> do- ty `subsumes` val+ _ <- subsumes Nothing ty val return M.empty _ -> throwError $ "Constructor " ++ show ctor ++ " is not defined" inferBinder val (UnaryBinder ctor binder) = do@@ -619,8 +612,8 @@ Just (ty, _) -> do fn <- replaceAllVarsWithUnknowns ty case fn of- Function [obj] ret -> do- val `subsumes` ret+ TypeApp (TypeApp t obj) ret | t == tyFunction -> do+ _ <- subsumes Nothing val ret inferBinder obj binder _ -> throwError $ "Constructor " ++ show ctor ++ " is not a unary constructor" _ -> throwError $ "Constructor " ++ show ctor ++ " is not defined"@@ -641,13 +634,13 @@ inferBinder val (ArrayBinder binders) = do el <- fresh m1 <- M.unions <$> mapM (inferBinder el) binders- val ?= TypeApp Array el+ val ?= TypeApp tyArray el return m1 inferBinder val (ConsBinder headBinder tailBinder) = do el <- fresh m1 <- inferBinder el headBinder m2 <- inferBinder val tailBinder- val ?= TypeApp Array el+ val ?= TypeApp tyArray el return $ m1 `M.union` m2 inferBinder val (NamedBinder name binder) = do m <- inferBinder val binder@@ -666,7 +659,7 @@ case grd of Nothing -> return (binders, Nothing, val') Just g -> do- g' <- check g Boolean+ g' <- check g tyBoolean return (binders, Just g', val') rs <- checkBinders nvals ret bs return $ r : rs@@ -698,7 +691,7 @@ Just ty -> do t ?= ty return (False, mass, Assignment ident val') checkStatement mass ret (While val inner) = do- val' <- check val Boolean+ val' <- check val tyBoolean (allCodePathsReturn, _, inner') <- checkBlock mass ret inner return (allCodePathsReturn, mass, While val' inner') checkStatement mass ret (If ifst) = do@@ -707,9 +700,9 @@ checkStatement mass ret (For ident start end inner) = do Just moduleName <- checkCurrentModule <$> get assignVariable ident- start' <- check start Number- end' <- check end Number- (allCodePathsReturn, _, inner') <- bindLocalVariables moduleName [(ident, Number)] $ checkBlock mass ret inner+ start' <- check start tyNumber+ end' <- check end tyNumber+ (allCodePathsReturn, _, inner') <- bindLocalVariables moduleName [(ident, tyNumber)] $ checkBlock mass ret inner return (allCodePathsReturn, mass, For ident start' end' inner') checkStatement mass ret (Return val) = do val' <- check val ret@@ -720,11 +713,11 @@ -- checkIfStatement :: M.Map Ident Type -> Type -> IfStatement -> UnifyT Check (Bool, IfStatement) checkIfStatement mass ret (IfStatement val thens Nothing) = do- val' <- check val Boolean+ val' <- check val tyBoolean (_, _, thens') <- checkBlock mass ret thens return (False, IfStatement val' thens' Nothing) checkIfStatement mass ret (IfStatement val thens (Just elses)) = do- val' <- check val Boolean+ val' <- check val tyBoolean (allCodePathsReturn1, _, thens') <- checkBlock mass ret thens (allCodePathsReturn2, elses') <- checkElseStatement mass ret elses return (allCodePathsReturn1 && allCodePathsReturn2, IfStatement val' thens' (Just elses'))@@ -792,52 +785,56 @@ TypeClassDictionaryInScope name className instanceTy Nothing TCDRegular) (map (Qualified Nothing) dictNames) (qualifyAllUnqualifiedNames moduleName env constraints)) $ check val ty- return $ Abs dictNames val'+ return $ foldr Abs val' dictNames check' val u@(TUnknown _) = do val'@(TypedValue _ _ ty) <- infer val -- Don't unify an unknown with an inferred polytype ty' <- replaceAllVarsWithUnknowns ty ty' ?= u return val'-check' v@(NumericLiteral _) Number = return v-check' v@(StringLiteral _) String = return v-check' v@(BooleanLiteral _) Boolean = return v+check' v@(NumericLiteral _) t | t == tyNumber = return v+check' v@(StringLiteral _) t | t == tyString = return v+check' v@(BooleanLiteral _) t | t == tyBoolean = return v check' (Unary op val) ty = checkUnary op val ty check' (Binary op left right) ty = checkBinary op left right ty-check' (ArrayLiteral vals) (TypeApp Array ty) = ArrayLiteral <$> forM vals (\val -> check val ty)+check' (ArrayLiteral vals) (TypeApp a ty) | a == tyArray = ArrayLiteral <$> forM vals (\val -> check val ty) check' (Indexer index vals) ty = do- index' <- check index Number- vals' <- check vals (TypeApp Array ty)+ index' <- check index tyNumber+ vals' <- check vals (TypeApp tyArray ty) return $ Indexer index' vals'-check' (Abs args ret) (Function argTys retTy) = do+check' (Abs arg ret) (TypeApp (TypeApp t argTy) retTy) | t == tyFunction = do Just moduleName <- checkCurrentModule <$> get- guardWith "Incorrect number of function arguments" (length args == length argTys)- ret' <- bindLocalVariables moduleName (zip args argTys) $ check ret retTy- return $ Abs args ret'-check' (App f args) ret = do+ ret' <- bindLocalVariables moduleName [(arg, argTy)] $ check ret retTy+ return $ Abs arg ret'+check' (App f arg) ret = do f'@(TypedValue _ _ ft) <- infer f- app <- checkFunctionApplication f' ft args ret+ app <- checkFunctionApplication f' ft arg ret return $ app-check' (Var var) ty = do+check' v@(Var var) ty = do Just moduleName <- checkCurrentModule <$> get ty1 <- lookupVariable moduleName var repl <- replaceAllTypeSynonyms ty1- repl `subsumes` ty- return $ Var var+ v' <- subsumes (Just v) repl ty+ case v' of+ Nothing -> throwError "Unable to check type subsumption"+ Just v'' -> return v'' check' (TypedValue checkType val ty1) ty2 = do Just moduleName <- checkCurrentModule <$> get kind <- liftCheck $ kindOf moduleName ty1 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star- ty1 `subsumes` ty2- val' <- if checkType then check val ty1 else return val- return $ TypedValue True val' ty1+ val' <- subsumes (Just val) ty1 ty2+ case val' of+ Nothing -> throwError "Unable to check type subsumption"+ Just val'' -> do+ val''' <- if checkType then check val'' ty1 else return val''+ return $ TypedValue True val''' ty1 check' (Case vals binders) ret = do vals' <- mapM infer vals let ts = map (\(TypedValue _ _ t) -> t) vals' binders' <- checkBinders ts ret binders return $ Case vals' binders' check' (IfThenElse cond th el) ty = do- cond' <- check cond Boolean+ cond' <- check cond tyBoolean th' <- check th ty el' <- check el ty return $ IfThenElse cond' th' el'@@ -869,7 +866,7 @@ Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined" Just (ty1, _) -> do repl <- replaceAllTypeSynonyms ty1- repl `subsumes` ty+ _ <- subsumes Nothing repl ty return $ Constructor c check' val (SaturatedTypeSynonym name args) = do ty <- expandTypeSynonym name args@@ -913,49 +910,51 @@ -- | -- Check the type of a function application, rethrowing errors to provide a better error message ---checkFunctionApplication :: Value -> Type -> [Value] -> Type -> UnifyT Check Value-checkFunctionApplication fn fnTy args ret = rethrow errorMessage $ checkFunctionApplication' fn fnTy args ret+checkFunctionApplication :: Value -> Type -> Value -> Type -> UnifyT Check Value+checkFunctionApplication fn fnTy arg ret = rethrow errorMessage $ checkFunctionApplication' fn fnTy arg ret where errorMessage msg = "Error applying function of type " ++ prettyPrintType fnTy- ++ " to arguments " ++ intercalate ", " (map prettyPrintValue args)+ ++ " to argument " ++ prettyPrintValue arg ++ ":\n" ++ msg -- | -- Check the type of a function application ---checkFunctionApplication' :: Value -> Type -> [Value] -> Type -> UnifyT Check Value-checkFunctionApplication' fn (Function argTys retTy) args ret = do- guardWith "Incorrect number of function arguments" (length args == length argTys)- args' <- zipWithM check args argTys- retTy `subsumes` ret- return $ App fn args'-checkFunctionApplication' fn (ForAll ident ty) args ret = do+checkFunctionApplication' :: Value -> Type -> Value -> Type -> UnifyT Check Value+checkFunctionApplication' fn (TypeApp (TypeApp tyFunction' argTy) retTy) arg ret = do+ tyFunction' ?= tyFunction+ arg' <- check arg argTy+ _ <- subsumes Nothing retTy ret+ return $ App fn arg'+checkFunctionApplication' fn (ForAll ident ty) arg ret = do replaced <- replaceVarWithUnknown ident ty- checkFunctionApplication fn replaced args ret-checkFunctionApplication' fn u@(TUnknown _) args ret = do- args' <- mapM (\arg -> infer arg >>= \(TypedValue _ v t) -> TypedValue True v <$> replaceAllVarsWithUnknowns t) args- let tys = map (\(TypedValue _ _ t) -> t) args'- u ?= Function tys ret- return $ App fn args'-checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) args ret = do+ checkFunctionApplication fn replaced arg ret+checkFunctionApplication' fn u@(TUnknown _) arg ret = do+ arg' <- do+ TypedValue _ v t <- infer arg+ TypedValue True v <$> replaceAllVarsWithUnknowns t+ let ty = (\(TypedValue _ _ t) -> t) arg'+ u ?= function ty ret+ return $ App fn arg'+checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) arg ret = do ty <- expandTypeSynonym name tyArgs- checkFunctionApplication fn ty args ret-checkFunctionApplication' fn (ConstrainedType constraints fnTy) args ret = do+ checkFunctionApplication fn ty arg ret+checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg ret = do env <- getEnv dicts <- getTypeClassDictionaries Just moduleName <- checkCurrentModule <$> get- checkFunctionApplication' (App fn (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) fnTy args ret-checkFunctionApplication' _ fnTy args ret = throwError $ "Applying a function of type "+ checkFunctionApplication' (foldl App fn (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) fnTy arg ret+checkFunctionApplication' _ fnTy arg ret = throwError $ "Applying a function of type " ++ prettyPrintType fnTy- ++ " to argument(s) " ++ intercalate ", " (map prettyPrintValue args)+ ++ " to argument(s) " ++ prettyPrintValue arg ++ " does not yield a value of type " ++ prettyPrintType ret ++ "." -- | -- Check whether one type subsumes another, rethrowing errors to provide a better error message ---subsumes :: Type -> Type -> UnifyT Check ()-subsumes ty1 ty2 = rethrow errorMessage $ subsumes' ty1 ty2+subsumes :: Maybe Value -> Type -> Type -> UnifyT Check (Maybe Value)+subsumes val ty1 ty2 = rethrow errorMessage $ subsumes' val ty1 ty2 where errorMessage msg = "Error checking that type " ++ prettyPrintType ty1@@ -966,12 +965,21 @@ -- | -- Check whether one type subsumes another ---subsumes' :: Type -> Type -> UnifyT Check ()-subsumes' (ForAll ident ty1) ty2 = do+subsumes' :: Maybe Value -> Type -> Type -> UnifyT Check (Maybe Value)+subsumes' val (ForAll ident ty1) ty2 = do replaced <- replaceVarWithUnknown ident ty1- replaced `subsumes` ty2-subsumes' (Function args1 ret1) (Function args2 ret2) = do- zipWithM_ subsumes args2 args1- ret1 `subsumes` ret2-subsumes' ty1 ty2 = ty1 ?= ty2+ subsumes val replaced ty2+subsumes' val (TypeApp (TypeApp f1 arg1) ret1) (TypeApp (TypeApp f2 arg2) ret2) | f1 == tyFunction && f2 == tyFunction = do+ subsumes Nothing arg2 arg1+ subsumes Nothing ret1 ret2+ return val+subsumes' (Just val) (ConstrainedType constraints ty1) ty2 = do+ env <- getEnv+ dicts <- getTypeClassDictionaries+ Just moduleName <- checkCurrentModule <$> get+ _ <- subsumes' Nothing ty1 ty2+ return . Just $ foldl App val (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))+subsumes' val ty1 ty2 = do+ ty1 ?= ty2+ return val
src/Language/PureScript/Types.hs view
@@ -35,28 +35,8 @@ -- | -- Javascript numbers --- | Number- -- |- -- Javascript strings- --- | String- -- |- -- Javascript booleans- --- | Boolean- -- |- -- Javascript array type constructor- --- | Array- -- |- -- Records, parameterized by a row of types- -- | Object Type -- |- -- A function, with zero or more arguments- --- | Function [Type] Type- -- | -- A named type variable -- | TypeVar String@@ -94,6 +74,42 @@ | RCons String Type Type deriving (Show, Eq, Data, Typeable) -- |+-- Type constructor for functions+--+tyFunction :: Type+tyFunction = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "Function")++-- |+-- Type constructor for strings+--+tyString :: Type+tyString = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "String")++-- |+-- Type constructor for numbers+--+tyNumber :: Type+tyNumber = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "Number")++-- |+-- Type constructor for booleans+--+tyBoolean :: Type+tyBoolean = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "Boolean")++-- |+-- Type constructor for arrays+--+tyArray :: Type+tyArray = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "Array")++-- |+-- Smart constructor for function types+--+function :: Type -> Type -> Type+function t1 t2 = TypeApp (TypeApp tyFunction t1) t2++-- | -- Convert a row to a list of pairs of labels and types -- rowToList :: Type -> ([(String, Type)], Type)@@ -113,18 +129,7 @@ -- isMonoType :: Type -> Bool isMonoType (ForAll _ _) = False-isMonoType ty = isPolyType ty---- |--- Check whather a type is a valid polytype----isPolyType :: Type -> Bool-isPolyType (Object ps) = all isPolyType (map snd . fst $ rowToList ps)-isPolyType (Function args ret) = all isPolyType args && isPolyType ret-isPolyType (TypeApp t1 t2) = isMonoType t1 && isMonoType t2-isPolyType (SaturatedTypeSynonym _ args) = all isPolyType args-isPolyType (ForAll _ ty) = isPolyType ty-isPolyType _ = True+isMonoType ty = True -- | -- Universally quantify a type
src/Language/PureScript/Values.hs view
@@ -190,11 +190,11 @@ -- | -- Function introduction --- | Abs [Ident] Value+ | Abs Ident Value -- | -- Function application --- | App Value [Value]+ | App Value Value -- | -- Variable --