git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge @garyb's core functional AST changes, fixes #710
commit513ded4e7bcff70f8cd20850bcaeaa3eb8bb88f5 authorPhil Freeman <paf31@cantab.net> dateTue 23 Dec 2014, 17:26 (12 years ago) parent1d06e2c
34 files changed+1162−571
examples/manual/passing/TransitiveImport.purs+21 examples/passing/ForeignInstance.purs+4 purescript.cabal+23−14 src/Language/PureScript.hs+38−38 src/Language/PureScript/AST/Declarations.hs+4−4 src/Language/PureScript/CodeGen/Externs.hs+5−8 src/Language/PureScript/CodeGen/JS.hs+175−215 src/Language/PureScript/CodeGen/Common.hs → src/Language/PureScript/CodeGen/JS/Common.hs+1−53 src/Language/PureScript/Optimizer.hs → src/Language/PureScript/CodeGen/JS/Optimizer.hs+8−8 src/Language/PureScript/Optimizer/Blocks.hs → src/Language/PureScript/CodeGen/JS/Optimizer/Blocks.hs+2−2 src/Language/PureScript/Optimizer/Common.hs → src/Language/PureScript/CodeGen/JS/Optimizer/Common.hs+2−2 src/Language/PureScript/Optimizer/Inliner.hs → src/Language/PureScript/CodeGen/JS/Optimizer/Inliner.hs+4−5 src/Language/PureScript/Optimizer/MagicDo.hs → src/Language/PureScript/CodeGen/JS/Optimizer/MagicDo.hs+5−6 src/Language/PureScript/Optimizer/TCO.hs → src/Language/PureScript/CodeGen/JS/Optimizer/TCO.hs+2−2 src/Language/PureScript/Optimizer/Unused.hs → src/Language/PureScript/CodeGen/JS/Optimizer/Unused.hs+3−3 src/Language/PureScript/CoreFn.hs+26 src/Language/PureScript/CoreFn/Ann.hs+30 src/Language/PureScript/CoreFn/Binders.hs+47 src/Language/PureScript/CoreFn/Desugar.hs+242 src/Language/PureScript/CoreFn/Expr.hs+97 src/Language/PureScript/CoreFn/Literals.hs+45 src/Language/PureScript/CoreFn/Meta.hs+54 src/Language/PureScript/CoreFn/Module.hs+30 src/Language/PureScript/CoreFn/Traversals.hs+85 src/Language/PureScript/DeadCodeElimination.hs+57−71 src/Language/PureScript/Environment.hs+20−5 src/Language/PureScript/Names.hs+2−2 src/Language/PureScript/Pretty/JS.hs+9−7 src/Language/PureScript/Renamer.hs+58−75 src/Language/PureScript/Sugar/TypeClasses.hs+38−35 src/Language/PureScript/TypeChecker.hs+12−8 src/Language/PureScript/TypeChecker/Entailment.hs+2−2 src/Language/PureScript/TypeClassDictionaries.hs+1−1 src/Language/PureScript/Types.hs+10−5
examples/manual/passing/TransitiveImport.pursnew file+21
@@ -0,0 +1,21 @@
1+module Test where
2+
3+ class TestCls a where
4+ test :: a -> a
5+
6+ instance unitTestCls :: TestCls Unit where
7+ test _ = unit
8+
9+module Middle where
10+
11+ middle = Test.test
12+
13+module Main where
14+
15+ import Middle
16+ import Debug.Trace
17+
18+ main = do
19+ print (middle unit)
20+ trace "Done"
21+ return unit
examples/passing/ForeignInstance.purs+4
@@ -9,6 +9,10 @@ foreign import instance fooNumber :: Foo Number
99
1010foreign import instance fooString :: Foo String
1111
12+foreign import fooString "var fooString = {};" :: Unit
13+foreign import fooNumber "var fooNumber = {};" :: Unit
14+foreign import fooArray "var fooArray = {};" :: Unit
15+
1216test1 _ = foo [1, 2, 3]
1317
1418test2 _ = foo "Test"
purescript.cabal+23−14
@@ -45,24 +45,33 @@ library
4545 Language.PureScript.AST.SourcePos
4646 Language.PureScript.AST.Traversals
4747 Language.PureScript.CodeGen
48− Language.PureScript.CodeGen.Common
4948 Language.PureScript.CodeGen.Externs
5049 Language.PureScript.CodeGen.JS
5150 Language.PureScript.CodeGen.JS.AST
51+ Language.PureScript.CodeGen.JS.Common
52+ Language.PureScript.CodeGen.JS.Optimizer
53+ Language.PureScript.CodeGen.JS.Optimizer.Blocks
54+ Language.PureScript.CodeGen.JS.Optimizer.Common
55+ Language.PureScript.CodeGen.JS.Optimizer.Inliner
56+ Language.PureScript.CodeGen.JS.Optimizer.MagicDo
57+ Language.PureScript.CodeGen.JS.Optimizer.TCO
58+ Language.PureScript.CodeGen.JS.Optimizer.Unused
5259 Language.PureScript.Constants
60+ Language.PureScript.CoreFn
61+ Language.PureScript.CoreFn.Ann
62+ Language.PureScript.CoreFn.Binders
63+ Language.PureScript.CoreFn.Desugar
64+ Language.PureScript.CoreFn.Expr
65+ Language.PureScript.CoreFn.Literals
66+ Language.PureScript.CoreFn.Meta
67+ Language.PureScript.CoreFn.Module
68+ Language.PureScript.CoreFn.Traversals
5369 Language.PureScript.DeadCodeElimination
5470 Language.PureScript.Environment
5571 Language.PureScript.Errors
5672 Language.PureScript.Kinds
5773 Language.PureScript.ModuleDependencies
5874 Language.PureScript.Names
59− Language.PureScript.Optimizer
60− Language.PureScript.Optimizer.Blocks
61− Language.PureScript.Optimizer.Common
62− Language.PureScript.Optimizer.Inliner
63− Language.PureScript.Optimizer.MagicDo
64− Language.PureScript.Optimizer.TCO
65− Language.PureScript.Optimizer.Unused
6675 Language.PureScript.Options
6776 Language.PureScript.Parser
6877 Language.PureScript.Parser.Common
@@ -106,7 +115,7 @@ library
106115 ghc-options: -Wall -O2
107116
108117executable psc
109− build-depends: base >=4 && <5, containers -any, directory -any, filepath -any,
118+ build-depends: base >=4 && <5, containers -any, directory -any, filepath -any,
110119 mtl -any, optparse-applicative >= 0.10.0, parsec -any, purescript -any,
111120 transformers -any, utf8-string -any
112121 main-is: Main.hs
@@ -116,8 +125,8 @@ executable psc
116125 ghc-options: -Wall -O2 -fno-warn-unused-do-bind
117126
118127executable psc-make
119− build-depends: base >=4 && <5, containers -any, directory -any, filepath -any,
120− mtl -any, optparse-applicative >= 0.10.0, parsec -any, purescript -any,
128+ build-depends: base >=4 && <5, containers -any, directory -any, filepath -any,
129+ mtl -any, optparse-applicative >= 0.10.0, parsec -any, purescript -any,
121130 transformers -any, utf8-string -any
122131 main-is: Main.hs
123132 buildable: True
@@ -127,10 +136,10 @@ executable psc-make
127136
128137executable psci
129138 build-depends: base >=4 && <5, containers -any, directory -any, filepath -any,
130− mtl -any, optparse-applicative >= 0.10.0, parsec -any,
131− haskeline >= 0.7.0.0, purescript -any, transformers -any,
139+ mtl -any, optparse-applicative >= 0.10.0, parsec -any,
140+ haskeline >= 0.7.0.0, purescript -any, transformers -any,
132141 utf8-string -any, process -any
133−
142+
134143 main-is: Main.hs
135144 buildable: True
136145 hs-source-dirs: psci
src/Language/PureScript.hs+38−38
@@ -1,7 +1,7 @@
11-----------------------------------------------------------------------------
22--
33-- Module : Language.PureScript
4−-- Copyright : (c) Phil Freeman 2013
4+-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
55-- License : MIT
66--
77-- Maintainer : Phil Freeman <paf31@cantab.net>
@@ -17,42 +17,40 @@
1717
1818module Language.PureScript (module P, compile, compile', RebuildPolicy(..), MonadMake(..), make, prelude) where
1919
20−import Language.PureScript.Types as P
21−import Language.PureScript.Kinds as P
20+import Data.FileEmbed (embedFile)
21+import Data.Function (on)
22+import Data.List (sortBy, groupBy, intercalate)
23+import Data.Maybe (fromMaybe)
24+import Data.Time.Clock
25+import qualified Data.ByteString.UTF8 as BU
26+import qualified Data.Map as M
27+import qualified Data.Set as S
28+
29+import Control.Applicative
30+import Control.Arrow ((&&&))
31+import Control.Monad.Error
32+
33+import System.FilePath ((</>))
34+
2235import Language.PureScript.AST as P
36+import Language.PureScript.CodeGen as P
37+import Language.PureScript.DeadCodeElimination as P
38+import Language.PureScript.Environment as P
39+import Language.PureScript.Errors as P
40+import Language.PureScript.Kinds as P
41+import Language.PureScript.ModuleDependencies as P
2342import Language.PureScript.Names as P
43+import Language.PureScript.Options as P
2444import Language.PureScript.Parser as P
25−import Language.PureScript.CodeGen as P
26−import Language.PureScript.CodeGen.Common as P
27−import Language.PureScript.TypeChecker as P
2845import Language.PureScript.Pretty as P
46+import Language.PureScript.Renamer as P
2947import Language.PureScript.Sugar as P
30−import Language.PureScript.Options as P
31−import Language.PureScript.ModuleDependencies as P
32−import Language.PureScript.Environment as P
33−import Language.PureScript.Errors as P
34−import Language.PureScript.DeadCodeElimination as P
3548import Language.PureScript.Supply as P
36−import Language.PureScript.Renamer as P
37−
49+import Language.PureScript.TypeChecker as P
50+import Language.PureScript.Types as P
51+import qualified Language.PureScript.CoreFn as CoreFn
3852import qualified Language.PureScript.Constants as C
3953
40−import Data.List (sortBy, groupBy, intercalate)
41−import Data.Time.Clock
42−import Data.Function (on)
43−import Data.Maybe (fromMaybe)
44−import Data.FileEmbed (embedFile)
45−
46−import Control.Monad.Error
47−import Control.Arrow ((&&&))
48−import Control.Applicative
49−
50−import qualified Data.Map as M
51−import qualified Data.Set as S
52−import qualified Data.ByteString.UTF8 as BU
53−
54−import System.FilePath ((</>))
55−
5654-- |
5755-- Compile a collection of modules
5856--
@@ -77,17 +75,18 @@ compile = compile' initEnvironment
7775
7876compile' :: Environment -> Options Compile -> [Module] -> [String] -> Either String (String, String, Environment)
7977compile' env opts ms prefix = do
80− (sorted, _) <- sortModules $ map importPrim $ if optionsNoPrelude opts then ms else (map importPrelude ms)
78+ (sorted, _) <- sortModules $ map importPrim $ if optionsNoPrelude opts then ms else map importPrelude ms
8179 (desugared, nextVar) <- stringifyErrorStack True $ runSupplyT 0 $ desugar sorted
8280 (elaborated, env') <- runCheck' opts env $ forM desugared $ typeCheckModule mainModuleIdent
8381 regrouped <- stringifyErrorStack True $ createBindingGroupsModule . collapseBindingGroupsModule $ elaborated
82+ let corefn = map (CoreFn.moduleToCoreFn env') regrouped
8483 let entryPoints = moduleNameFromString `map` entryPointModules (optionsAdditional opts)
85− let elim = if null entryPoints then regrouped else eliminateDeadCode entryPoints regrouped
84+ let elim = if null entryPoints then corefn else eliminateDeadCode entryPoints corefn
8685 let renamed = renameInModules elim
8786 let codeGenModuleNames = moduleNameFromString `map` codeGenModules (optionsAdditional opts)
88− let modulesToCodeGen = if null codeGenModuleNames then renamed else filter (\(Module mn _ _) -> mn `elem` codeGenModuleNames) renamed
89− let js = evalSupply nextVar $ concat <$> mapM (\m -> moduleToJs opts m env') modulesToCodeGen
90− let exts = intercalate "\n" . map (`moduleToPs` env') $ modulesToCodeGen
87+ let modulesToCodeGen = if null codeGenModuleNames then renamed else filter (\(CoreFn.Module mn _ _ _ _) -> mn `elem` codeGenModuleNames) renamed
88+ let js = evalSupply nextVar $ concat <$> mapM (moduleToJs opts) modulesToCodeGen
89+ let exts = intercalate "\n" . map (`moduleToPs` env') $ regrouped
9190 js' <- generateMain env' opts js
9291 let pjs = unlines $ map ("// " ++) prefix ++ [prettyPrintJS js']
9392 return (pjs, exts, env')
@@ -156,7 +155,7 @@ make :: (Functor m, Applicative m, Monad m, MonadMake m) => FilePath -> Options
156155make outputDir opts ms prefix = do
157156 let filePathMap = M.fromList (map (\(fp, Module mn _ _) -> (mn, fp)) ms)
158157
159− (sorted, graph) <- liftError $ sortModules $ map importPrim $ if optionsNoPrelude opts then map snd ms else (map (importPrelude . snd) ms)
158+ (sorted, graph) <- liftError $ sortModules $ map importPrim $ if optionsNoPrelude opts then map snd ms else map (importPrelude . snd) ms
160159
161160 toRebuild <- foldM (\s (Module moduleName' _ _) -> do
162161 let filePath = runModuleName moduleName'
@@ -199,11 +198,12 @@ make outputDir opts ms prefix = do
199198 regrouped <- lift . liftError . stringifyErrorStack True . createBindingGroups moduleName' . collapseBindingGroups $ elaborated
200199
201200 let mod' = Module moduleName' regrouped exps
202− let [renamed] = renameInModules [mod']
201+ let corefn = CoreFn.moduleToCoreFn env' mod'
202+ let [renamed] = renameInModules [corefn]
203203
204− pjs <- prettyPrintJS <$> moduleToJs opts renamed env'
204+ pjs <- prettyPrintJS <$> moduleToJs opts renamed
205205 let js = unlines $ map ("// " ++) prefix ++ [pjs]
206− let exts = unlines $ map ("-- " ++ ) prefix ++ [moduleToPs renamed env']
206+ let exts = unlines $ map ("-- " ++) prefix ++ [moduleToPs mod' env']
207207
208208 lift $ writeTextFile jsFile js
209209 lift $ writeTextFile externsFile exts
src/Language/PureScript/AST/Declarations.hs+4−4
@@ -171,7 +171,7 @@ data Declaration
171171 -- |
172172 -- A type class instance foreign import
173173 --
174− | ExternInstanceDeclaration Ident [(Qualified ProperName, [Type])] (Qualified ProperName) [Type]
174+ | ExternInstanceDeclaration Ident [Constraint] (Qualified ProperName) [Type]
175175 -- |
176176 -- A fixity declaration (fixity data, operator name)
177177 --
@@ -183,12 +183,12 @@ data Declaration
183183 -- |
184184 -- A type class declaration (name, argument, implies, member declarations)
185185 --
186− | TypeClassDeclaration ProperName [(String, Maybe Kind)] [(Qualified ProperName, [Type])] [Declaration]
186+ | TypeClassDeclaration ProperName [(String, Maybe Kind)] [Constraint] [Declaration]
187187 -- |
188188 -- A type instance declaration (name, dependencies, class name, instance types, member
189189 -- declarations)
190190 --
191− | TypeInstanceDeclaration Ident [(Qualified ProperName, [Type])] (Qualified ProperName) [Type] [Declaration]
191+ | TypeInstanceDeclaration Ident [Constraint] (Qualified ProperName) [Type] [Declaration]
192192 -- |
193193 -- A declaration with source position information
194194 --
@@ -361,7 +361,7 @@ data Expr
361361 -- at superclass implementations when searching for a dictionary, the type class name and
362362 -- instance type, and the type class dictionaries in scope.
363363 --
364− | TypeClassDictionary Bool (Qualified ProperName, [Type]) [TypeClassDictionaryInScope]
364+ | TypeClassDictionary Bool Constraint [TypeClassDictionaryInScope]
365365 -- |
366366 -- A placeholder for a superclass dictionary to be turned into a TypeClassDictionary during typechecking
367367 --
src/Language/PureScript/CodeGen/Externs.hs+5−8
@@ -17,21 +17,19 @@ module Language.PureScript.CodeGen.Externs (
1717 moduleToPs
1818) where
1919
20−import Data.Maybe (fromMaybe, mapMaybe)
2120import Data.List (intercalate, find)
22−
21+import Data.Maybe (fromMaybe, mapMaybe)
2322import qualified Data.Map as M
2423
2524import Control.Monad.Writer
2625
27−import Language.PureScript.CodeGen.Common
28−import Language.PureScript.TypeClassDictionaries
2926import Language.PureScript.AST
30−import Language.PureScript.Pretty
31−import Language.PureScript.Names
27+import Language.PureScript.Environment
3228import Language.PureScript.Kinds
29+import Language.PureScript.Names
30+import Language.PureScript.Pretty
31+import Language.PureScript.TypeClassDictionaries
3332import Language.PureScript.Types
34−import Language.PureScript.Environment
3533
3634-- |
3735-- Generate foreign imports for all declarations in a module
@@ -109,4 +107,3 @@ moduleToPs (Module moduleName ds (Just exts)) env = intercalate "\n" . execWrite
109107
110108 isValueExported :: Ident -> Bool
111109 isValueExported ident = ValueRef ident `elem` exts
112−
src/Language/PureScript/CodeGen/JS.hs+175−215
@@ -13,32 +13,29 @@
1313--
1414-----------------------------------------------------------------------------
1515
16−{-# LANGUAGE GADTs, DoAndIfThenElse #-}
16+{-# LANGUAGE GADTs #-}
1717
1818module Language.PureScript.CodeGen.JS (
1919 module AST,
20− declToJs,
21− moduleToJs,
22− identNeedsEscaping
20+ module Common,
21+ bindToJs,
22+ moduleToJs
2323) where
2424
25−import Data.Maybe (catMaybes)
2625import Data.Function (on)
27−import Data.List (nub, (\\), delete, sortBy)
26+import Data.List ((\\), delete, sortBy)
27+import Data.Maybe (catMaybes, mapMaybe)
2828
29−import qualified Data.Map as M
30−
31−import Control.Monad (foldM, replicateM, forM)
3229import Control.Applicative
33−import Control.Arrow (second)
30+import Control.Arrow ((&&&))
31+import Control.Monad (foldM, replicateM, forM)
3432
33+import Language.PureScript.CodeGen.JS.AST as AST
34+import Language.PureScript.CodeGen.JS.Common as Common
35+import Language.PureScript.CoreFn
3536import Language.PureScript.Names
36−import Language.PureScript.AST
37+import Language.PureScript.CodeGen.JS.Optimizer
3738import Language.PureScript.Options
38−import Language.PureScript.CodeGen.JS.AST as AST
39−import Language.PureScript.Optimizer
40−import Language.PureScript.CodeGen.Common
41−import Language.PureScript.Environment
4239import Language.PureScript.Supply
4340import Language.PureScript.Traversals (sndM)
4441import qualified Language.PureScript.Constants as C
@@ -47,25 +44,28 @@ import qualified Language.PureScript.Constants as C
4744-- Generate code in the simplified Javascript intermediate representation for all declarations in a
4845-- module.
4946--
50−moduleToJs :: (Functor m, Applicative m, Monad m) => Options mode -> Module -> Environment -> SupplyT m [JS]
51−moduleToJs opts (Module name decls (Just exps)) env = do
52− let jsImports = map (importToJs opts) . delete (ModuleName [ProperName C.prim]) . (\\ [name]) . nub $ concatMap imports decls
53− jsDecls <- mapM (\decl -> declToJs opts name decl env) decls
54− let optimized = concat $ map (map $ optimize opts) $ catMaybes jsDecls
47+moduleToJs :: (Functor m, Applicative m, Monad m) => Options mode -> Module Ann -> SupplyT m [JS]
48+moduleToJs opts (Module name imps exps foreigns decls) = do
49+ let jsImports = map (importToJs opts) . delete (ModuleName [ProperName C.prim]) . (\\ [name]) $ imps
50+ let foreigns' = mapMaybe (\(_, js, _) -> js) foreigns
51+ jsDecls <- mapM (bindToJs name) decls
52+ let optimized = concatMap (map $ optimize opts) $ catMaybes jsDecls
5553 let isModuleEmpty = null exps
56− let moduleBody = JSStringLiteral "use strict" : jsImports ++ optimized
57− let moduleExports = JSObjectLiteral . map (second var) . M.toList . M.unions $ map exportToJs exps
54+ let moduleBody = JSStringLiteral "use strict" : jsImports ++ foreigns' ++ optimized
55+ let exps' = JSObjectLiteral $ map (runIdent &&& JSVar . identToJs) exps
5856 return $ case optionsAdditional opts of
59− MakeOptions -> moduleBody ++ [JSAssignment (JSAccessor "exports" (JSVar "module")) moduleExports]
57+ MakeOptions -> moduleBody ++ [JSAssignment (JSAccessor "exports" (JSVar "module")) exps']
6058 CompileOptions ns _ _ | not isModuleEmpty ->
6159 [ JSVariableIntroduction ns
6260 (Just (JSBinary Or (JSVar ns) (JSObjectLiteral [])) )
6361 , JSAssignment (JSAccessor (moduleNameToJs name) (JSVar ns))
64− (JSApp (JSFunction Nothing [] (JSBlock (moduleBody ++ [JSReturn moduleExports]))) [])
62+ (JSApp (JSFunction Nothing [] (JSBlock (moduleBody ++ [JSReturn exps']))) [])
6563 ]
6664 _ -> []
67−moduleToJs _ _ _ = error "Exports should have been elaborated in name desugaring"
6865
66+-- |
67+-- Generates Javascript code for a module import.
68+--
6969importToJs :: Options mode -> ModuleName -> JS
7070importToJs opts mn =
7171 JSVariableIntroduction (moduleNameToJs mn) (Just moduleBody)
@@ -74,95 +74,18 @@ importToJs opts mn =
7474 MakeOptions -> JSApp (JSVar "require") [JSStringLiteral (runModuleName mn)]
7575 CompileOptions ns _ _ -> JSAccessor (moduleNameToJs mn) (JSVar ns)
7676
77−imports :: Declaration -> [ModuleName]
78−imports (ImportDeclaration mn _ _) = [mn]
79−imports other =
80− let (f, _, _, _, _) = everythingOnValues (++) (const []) collectV collectB (const []) (const [])
81− in f other
82− where
83− collectV :: Expr -> [ModuleName]
84− collectV (Var (Qualified (Just mn) _)) = [mn]
85− collectV (Constructor (Qualified (Just mn) _)) = [mn]
86− collectV (TypeClassDictionaryConstructorApp (Qualified (Just mn) _) _) = [mn]
87− collectV _ = []
88− collectB :: Binder -> [ModuleName]
89− collectB (ConstructorBinder (Qualified (Just mn) _) _) = [mn]
90− collectB _ = []
91−
9277-- |
9378-- Generate code in the simplified Javascript intermediate representation for a declaration
9479--
95−declToJs :: (Functor m, Applicative m, Monad m) => Options mode -> ModuleName -> Declaration -> Environment -> SupplyT m (Maybe [JS])
96−declToJs opts mp (ValueDeclaration ident _ _ (Right val)) e = do
97− js <- valueToJs opts mp e val
80+bindToJs :: (Functor m, Applicative m, Monad m) => ModuleName -> Bind Ann -> SupplyT m (Maybe [JS])
81+bindToJs mp (NonRec ident val) = do
82+ js <- valueToJs mp val
9883 return $ Just [JSVariableIntroduction (identToJs ident) (Just js)]
99−declToJs opts mp (BindingGroupDeclaration vals) e = do
100− jss <- forM vals $ \(ident, _, val) -> do
101− js <- valueToJs opts mp e val
84+bindToJs mp (Rec vals) = do
85+ jss <- forM vals $ \(ident, val) -> do
86+ js <- valueToJs mp val
10287 return $ JSVariableIntroduction (identToJs ident) (Just js)
10388 return $ Just jss
104−declToJs _ _ (DataDeclaration Newtype _ _ [((ProperName ctor), _)]) _ =
105− return $ Just $ [JSVariableIntroduction ctor (Just $
106− JSObjectLiteral [("create",
107− JSFunction Nothing ["value"]
108− (JSBlock [JSReturn $ JSVar "value"]))])]
109−declToJs _ _ (DataDeclaration Newtype _ _ _) _ =
110− error "newtype has multiple constructors"
111−declToJs _ mp (DataDeclaration Data _ _ ctors) e = do
112− return $ Just $ flip concatMap ctors $ \(pn@(ProperName ctor), tys) ->
113− let propName = if isNullaryConstructor e (Qualified (Just mp) pn) then "value" else "create"
114− in [ makeConstructor ctor (length tys)
115− , JSAssignment (JSAccessor propName (JSVar ctor)) (go pn 0 (length tys) [])
116− ]
117− where
118− makeConstructor :: String -> Int -> JS
119− makeConstructor ctorName n =
120− let
121− args = [ "value" ++ show index | index <- [0..n-1] ]
122− body = [ JSAssignment (JSAccessor arg (JSVar "this")) (JSVar arg) | arg <- args ]
123− in JSFunction (Just ctorName) args (JSBlock body)
124− go :: ProperName -> Int -> Int -> [JS] -> JS
125− go pn _ 0 values = JSUnary JSNew $ JSApp (JSVar $ runProperName pn) (reverse values)
126− go pn index n values =
127− JSFunction Nothing ["value" ++ show index]
128− (JSBlock [JSReturn (go pn (index + 1) (n - 1) (JSVar ("value" ++ show index) : values))])
129−declToJs opts mp (DataBindingGroupDeclaration ds) e = do
130− jss <- mapM (\decl -> declToJs opts mp decl e) ds
131− return $ Just $ concat $ catMaybes jss
132−declToJs _ _ (TypeClassDeclaration name _ supers members) _ =
133− return $ Just $ [
134− JSFunction (Just $ runProperName name) (identToJs `map` args)
135− (JSBlock $ assn `map` args)]
136− where
137− assn :: Ident -> JS
138− assn arg = JSAssignment (accessor arg (JSVar "this")) (var arg)
139− args :: [Ident]
140− args = sortBy (compare `on` runIdent) $ memberNames ++ superNames
141− memberNames :: [Ident]
142− memberNames = memberToName `map` members
143− superNames :: [Ident]
144− superNames = [ toSuperName superclass index
145− | (index, (superclass, _)) <- zip [0..] supers
146− ]
147− toSuperName :: Qualified ProperName -> Integer -> Ident
148− toSuperName pn index = Ident $ C.__superclass_ ++ show pn ++ "_" ++ show index
149− memberToName :: Declaration -> Ident
150− memberToName (TypeDeclaration ident _) = ident
151− memberToName (PositionedDeclaration _ d) = memberToName d
152− memberToName _ = error "Invalid declaration in type class definition"
153−declToJs _ _ (ExternDeclaration _ _ (Just js) _) _ = return $ Just [js]
154−declToJs opts mp (PositionedDeclaration _ d) e = declToJs opts mp d e
155−declToJs _ _ _ _ = return Nothing
156−
157−-- |
158−-- Generate key//value pairs for an object literal exporting values from a module.
159−--
160−exportToJs :: DeclarationRef -> M.Map String Ident
161−exportToJs (TypeRef _ (Just dctors)) = M.fromList [ (n, Ident n) | (ProperName n) <- dctors ]
162−exportToJs (ValueRef name) = M.singleton (runIdent name) name
163−exportToJs (TypeInstanceRef name) = M.singleton (runIdent name) name
164−exportToJs (TypeClassRef name) = M.singleton (runProperName name) (Ident $ runProperName name)
165−exportToJs _ = M.empty
16689
16790-- |
16891-- Generate code in the simplified Javascript intermediate representation for a variable based on a
@@ -187,54 +110,89 @@ accessorString prop | identNeedsEscaping prop = JSIndexer (JSStringLiteral prop)
187110-- |
188111-- Generate code in the simplified Javascript intermediate representation for a value or expression.
189112--
190−valueToJs :: (Functor m, Applicative m, Monad m) => Options mode -> ModuleName -> Environment -> Expr -> SupplyT m JS
191−valueToJs _ _ _ (NumericLiteral n) = return $ JSNumericLiteral n
192−valueToJs _ _ _ (StringLiteral s) = return $ JSStringLiteral s
193−valueToJs _ _ _ (BooleanLiteral b) = return $ JSBooleanLiteral b
194−valueToJs opts m e (ArrayLiteral xs) = JSArrayLiteral <$> mapM (valueToJs opts m e) xs
195−valueToJs opts m e (ObjectLiteral ps) = JSObjectLiteral <$> mapM (sndM (valueToJs opts m e)) ps
196−valueToJs opts m e (TypeClassDictionaryConstructorApp name (TypedValue _ (ObjectLiteral ps) _)) =
197− JSUnary JSNew . JSApp (qualifiedToJS m (Ident . runProperName) name) <$> mapM (valueToJs opts m e . snd) (sortBy (compare `on` fst) ps)
198−valueToJs _ _ _ TypeClassDictionaryConstructorApp{} =
199− error "TypeClassDictionaryConstructorApp did not contain object literal"
200−valueToJs opts m e (ObjectUpdate o ps) = do
201− obj <- valueToJs opts m e o
202− sts <- mapM (sndM (valueToJs opts m e)) ps
113+valueToJs :: (Functor m, Applicative m, Monad m) => ModuleName -> Expr Ann -> SupplyT m JS
114+valueToJs m (Literal _ l) =
115+ literalToValueJS m l
116+valueToJs m (Var (_, _, Just (IsConstructor _ 0)) name) =
117+ return $ JSAccessor "value" $ qualifiedToJS m id name
118+valueToJs m (Var (_, _, Just (IsConstructor _ _)) name) =
119+ return $ JSAccessor "create" $ qualifiedToJS m id name
120+valueToJs m (Accessor _ prop val) =
121+ accessorString prop <$> valueToJs m val
122+valueToJs m (ObjectUpdate _ o ps) = do
123+ obj <- valueToJs m o
124+ sts <- mapM (sndM (valueToJs m)) ps
203125 extendObj obj sts
204−valueToJs _ m e (Constructor name) =
205− let propName = if isNullaryConstructor e name then "value" else "create"
206− in return $ JSAccessor propName $ qualifiedToJS m (Ident . runProperName) name
207−valueToJs opts m e (Case values binders) = do
208− vals <- mapM (valueToJs opts m e) values
209− bindersToJs opts m e binders vals
210−valueToJs opts m e (IfThenElse cond th el) = JSConditional <$> valueToJs opts m e cond <*> valueToJs opts m e th <*> valueToJs opts m e el
211−valueToJs opts m e (Accessor prop val) = accessorString prop <$> valueToJs opts m e val
212−valueToJs opts m e v@App{} = do
213− let (f, args) = unApp v []
214− args' <- mapM (valueToJs opts m e) args
126+valueToJs _ e@(Abs (_, _, Just IsTypeClassConstructor) _ val) =
127+ let args = unAbs e
128+ in return $ JSFunction Nothing (map identToJs args) (JSBlock $ map assign args)
129+ where
130+ unAbs :: Expr Ann -> [Ident]
131+ unAbs (Abs _ arg val) = arg : unAbs val
132+ unAbs _ = []
133+ assign :: Ident -> JS
134+ assign name = JSAssignment (accessorString (runIdent name) (JSVar "this"))
135+ (var name)
136+valueToJs m (Abs _ arg val) = do
137+ ret <- valueToJs m val
138+ return $ JSFunction Nothing [identToJs arg] (JSBlock [JSReturn ret])
139+valueToJs m e@App{} = do
140+ let (f, args) = unApp e []
141+ args' <- mapM (valueToJs m) args
215142 case f of
216− Constructor name | isNewtypeConstructor e name && length args == 1 -> return (head args')
217− Constructor name | getConstructorArity e name == length args ->
218− return $ JSUnary JSNew $ JSApp (qualifiedToJS m (Ident . runProperName) name) args'
219− _ -> flip (foldl (\fn a -> JSApp fn [a])) args' <$> valueToJs opts m e f
143+ Var (_, _, Just IsNewtype) _ -> return (head args')
144+ Var (_, _, Just (IsConstructor _ arity)) name | arity == length args ->
145+ return $ JSUnary JSNew $ JSApp (qualifiedToJS m id name) args'
146+ Var (_, _, Just IsTypeClassConstructor) name ->
147+ return $ JSUnary JSNew $ JSApp (qualifiedToJS m id name) args'
148+ _ -> flip (foldl (\fn a -> JSApp fn [a])) args' <$> valueToJs m f
220149 where
221− unApp :: Expr -> [Expr] -> (Expr, [Expr])
222− unApp (App val arg) args = unApp val (arg : args)
223− unApp (PositionedValue _ val) args = unApp val args
224− unApp (TypedValue _ val _) args = unApp val args
150+ unApp :: Expr Ann -> [Expr Ann] -> (Expr Ann, [Expr Ann])
151+ unApp (App _ val arg) args = unApp val (arg : args)
225152 unApp other args = (other, args)
226−valueToJs opts m e (Let ds val) = do
227− decls <- concat . catMaybes <$> mapM (flip (declToJs opts m) e) ds
228− ret <- valueToJs opts m e val
153+valueToJs m (Var _ ident) =
154+ return $ varToJs m ident
155+valueToJs m (Case _ values binders) = do
156+ vals <- mapM (valueToJs m) values
157+ bindersToJs m binders vals
158+valueToJs m (Let _ ds val) = do
159+ decls <- concat . catMaybes <$> mapM (bindToJs m) ds
160+ ret <- valueToJs m val
229161 return $ JSApp (JSFunction Nothing [] (JSBlock (decls ++ [JSReturn ret]))) []
230−valueToJs opts m e (Abs (Left arg) val) = do
231− ret <- valueToJs opts m e val
232− return $ JSFunction Nothing [identToJs arg] (JSBlock [JSReturn ret])
233−valueToJs _ m _ (Var ident) = return $ varToJs m ident
234−valueToJs opts m e (TypedValue _ val _) = valueToJs opts m e val
235−valueToJs opts m e (PositionedValue _ val) = valueToJs opts m e val
236−valueToJs _ _ _ (TypeClassDictionary _ _ _) = error "Type class dictionary was not replaced"
237−valueToJs _ _ _ _ = error "Invalid argument to valueToJs"
162+valueToJs _ (Constructor (_, _, Just IsNewtype) _ (ProperName ctor) _) =
163+ return $ JSVariableIntroduction ctor (Just $
164+ JSObjectLiteral [("create",
165+ JSFunction Nothing ["value"]
166+ (JSBlock [JSReturn $ JSVar "value"]))])
167+valueToJs _ (Constructor _ _ (ProperName ctor) 0) =
168+ return $ iife ctor [ JSFunction (Just ctor) [] (JSBlock [])
169+ , JSAssignment (JSAccessor "value" (JSVar ctor))
170+ (JSUnary JSNew $ JSApp (JSVar ctor) []) ]
171+valueToJs _ (Constructor _ _ (ProperName ctor) arity) =
172+ return $ iife ctor [ makeConstructor ctor arity
173+ , JSAssignment (JSAccessor "create" (JSVar ctor)) (go ctor 0 arity [])
174+ ]
175+ where
176+ makeConstructor :: String -> Int -> JS
177+ makeConstructor ctorName n =
178+ let args = [ "value" ++ show index | index <- [0..n-1] ]
179+ body = [ JSAssignment (JSAccessor arg (JSVar "this")) (JSVar arg) | arg <- args ]
180+ in JSFunction (Just ctorName) args (JSBlock body)
181+ go :: String -> Int -> Int -> [JS] -> JS
182+ go pn _ 0 values = JSUnary JSNew $ JSApp (JSVar pn) (reverse values)
183+ go pn index n values =
184+ JSFunction Nothing ["value" ++ show index]
185+ (JSBlock [JSReturn (go pn (index + 1) (n - 1) (JSVar ("value" ++ show index) : values))])
186+
187+iife :: String -> [JS] -> JS
188+iife v exprs = JSApp (JSFunction Nothing [] (JSBlock $ exprs ++ [JSReturn $ JSVar v])) []
189+
190+literalToValueJS :: (Functor m, Applicative m, Monad m) => ModuleName -> Literal (Expr Ann) -> SupplyT m JS
191+literalToValueJS _ (NumericLiteral n) = return $ JSNumericLiteral n
192+literalToValueJS _ (StringLiteral s) = return $ JSStringLiteral s
193+literalToValueJS _ (BooleanLiteral b) = return $ JSBooleanLiteral b
194+literalToValueJS m (ArrayLiteral xs) = JSArrayLiteral <$> mapM (valueToJs m) xs
195+literalToValueJS m (ObjectLiteral ps) = JSObjectLiteral <$> mapM (sndM (valueToJs m)) ps
238196
239197-- |
240198-- Shallow copy an object.
@@ -276,109 +234,111 @@ qualifiedToJS _ f (Qualified _ a) = JSVar $ identToJs (f a)
276234-- Generate code in the simplified Javascript intermediate representation for pattern match binders
277235-- and guards.
278236--
279−bindersToJs :: (Functor m, Applicative m, Monad m) => Options mode -> ModuleName -> Environment -> [CaseAlternative] -> [JS] -> SupplyT m JS
280−bindersToJs opts m e binders vals = do
237+bindersToJs :: (Functor m, Applicative m, Monad m) => ModuleName -> [CaseAlternative Ann] -> [JS] -> SupplyT m JS
238+bindersToJs m binders vals = do
281239 valNames <- replicateM (length vals) freshName
282240 let assignments = zipWith JSVariableIntroduction valNames (map Just vals)
283241 jss <- forM binders $ \(CaseAlternative bs result) -> do
284242 ret <- guardsToJs result
285243 go valNames ret bs
286− return $ JSApp (JSFunction Nothing [] (JSBlock (assignments ++ concat jss ++ [JSThrow $ JSUnary JSNew $ JSApp (JSVar "Error") $ [JSStringLiteral "Failed pattern match"]])))
244+ return $ JSApp (JSFunction Nothing [] (JSBlock (assignments ++ concat jss ++ [JSThrow $ JSUnary JSNew $ JSApp (JSVar "Error") [JSStringLiteral "Failed pattern match"]])))
287245 []
288246 where
289− go :: (Functor m, Applicative m, Monad m) => [String] -> [JS] -> [Binder] -> SupplyT m [JS]
247+ go :: (Functor m, Applicative m, Monad m) => [String] -> [JS] -> [Binder Ann] -> SupplyT m [JS]
290248 go _ done [] = return done
291249 go (v:vs) done' (b:bs) = do
292250 done'' <- go vs done' bs
293− binderToJs m e v done'' b
251+ binderToJs m v done'' b
294252 go _ _ _ = error "Invalid arguments to bindersToJs"
295253
296− guardsToJs :: (Functor m, Applicative m, Monad m) => Either [(Guard, Expr)] Expr -> SupplyT m [JS]
254+ guardsToJs :: (Functor m, Applicative m, Monad m) => Either [(Guard Ann, Expr Ann)] (Expr Ann) -> SupplyT m [JS]
297255 guardsToJs (Left gs) = forM gs $ \(cond, val) -> do
298− cond' <- valueToJs opts m e cond
299− done <- valueToJs opts m e val
256+ cond' <- valueToJs m cond
257+ done <- valueToJs m val
300258 return $ JSIfElse cond' (JSBlock [JSReturn done]) Nothing
301− guardsToJs (Right v) = return . JSReturn <$> valueToJs opts m e v
259+ guardsToJs (Right v) = return . JSReturn <$> valueToJs m v
302260
303261-- |
304262-- Generate code in the simplified Javascript intermediate representation for a pattern match
305263-- binder.
306264--
307−binderToJs :: (Functor m, Applicative m, Monad m) => ModuleName -> Environment -> String -> [JS] -> Binder -> SupplyT m [JS]
308−binderToJs _ _ _ done NullBinder = return done
309−binderToJs _ _ varName done (StringBinder str) =
310− return [JSIfElse (JSBinary EqualTo (JSVar varName) (JSStringLiteral str)) (JSBlock done) Nothing]
311−binderToJs _ _ varName done (NumberBinder num) =
312− return [JSIfElse (JSBinary EqualTo (JSVar varName) (JSNumericLiteral num)) (JSBlock done) Nothing]
313−binderToJs _ _ varName done (BooleanBinder True) =
314− return [JSIfElse (JSVar varName) (JSBlock done) Nothing]
315−binderToJs _ _ varName done (BooleanBinder False) =
316− return [JSIfElse (JSUnary Not (JSVar varName)) (JSBlock done) Nothing]
317−binderToJs _ _ varName done (VarBinder ident) =
265+binderToJs :: (Functor m, Applicative m, Monad m) => ModuleName -> String -> [JS] -> Binder Ann -> SupplyT m [JS]
266+binderToJs _ _ done (NullBinder{}) = return done
267+binderToJs m varName done (LiteralBinder _ l) =
268+ literalToBinderJS m varName done l
269+binderToJs _ varName done (VarBinder _ ident) =
318270 return (JSVariableIntroduction (identToJs ident) (Just (JSVar varName)) : done)
319−binderToJs m e varName done (ConstructorBinder ctor bs) | isNewtypeConstructor e ctor =
320− case bs of
321− [b] -> binderToJs m e varName done b
322− _ -> error "binder for newtype constructor should have a single argument"
323−binderToJs m e varName done (ConstructorBinder ctor bs) = do
271+binderToJs m varName done (ConstructorBinder (_, _, Just IsNewtype) _ _ [b]) =
272+ binderToJs m varName done b
273+binderToJs m varName done (ConstructorBinder (_, _, Just (IsConstructor ctorType _)) _ ctor bs) = do
324274 js <- go 0 done bs
325− if isOnlyConstructor e ctor
326− then
327− return js
328− else
329− return [JSIfElse (JSInstanceOf (JSVar varName) (qualifiedToJS m (Ident . runProperName) ctor))
330− (JSBlock js)
331− Nothing]
275+ return $ case ctorType of
276+ ProductType -> js
277+ SumType ->
278+ [JSIfElse (JSInstanceOf (JSVar varName) (qualifiedToJS m (Ident . runProperName) ctor))
279+ (JSBlock js)
280+ Nothing]
332281 where
333− go :: (Functor m, Applicative m, Monad m) => Integer -> [JS] -> [Binder] -> SupplyT m [JS]
282+ go :: (Functor m, Applicative m, Monad m) => Integer -> [JS] -> [Binder Ann] -> SupplyT m [JS]
334283 go _ done' [] = return done'
335284 go index done' (binder:bs') = do
336285 argVar <- freshName
337286 done'' <- go (index + 1) done' bs'
338− js <- binderToJs m e argVar done'' binder
287+ js <- binderToJs m argVar done'' binder
339288 return (JSVariableIntroduction argVar (Just (JSAccessor ("value" ++ show index) (JSVar varName))) : js)
340−binderToJs m e varName done (ObjectBinder bs) = go done bs
341− where
342− go :: (Functor m, Applicative m, Monad m) => [JS] -> [(String, Binder)] -> SupplyT m [JS]
343− go done' [] = return done'
344− go done' ((prop, binder):bs') = do
345− propVar <- freshName
346− done'' <- go done' bs'
347− js <- binderToJs m e propVar done'' binder
348− return (JSVariableIntroduction propVar (Just (accessorString prop (JSVar varName))) : js)
349−binderToJs m e varName done (ArrayBinder bs) = do
350− js <- go done 0 bs
351− return [JSIfElse (JSBinary EqualTo (JSAccessor "length" (JSVar varName)) (JSNumericLiteral (Left (fromIntegral $ length bs)))) (JSBlock js) Nothing]
352− where
353− go :: (Functor m, Applicative m, Monad m) => [JS] -> Integer -> [Binder] -> SupplyT m [JS]
354− go done' _ [] = return done'
355− go done' index (binder:bs') = do
356− elVar <- freshName
357− done'' <- go done' (index + 1) bs'
358− js <- binderToJs m e elVar done'' binder
359− return (JSVariableIntroduction elVar (Just (JSIndexer (JSNumericLiteral (Left index)) (JSVar varName))) : js)
360−binderToJs m e varName done binder@(ConsBinder _ _) = do
289+binderToJs m varName done binder@(ConstructorBinder _ _ ctor _) | isCons ctor = do
361290 let (headBinders, tailBinder) = uncons [] binder
362291 numberOfHeadBinders = fromIntegral $ length headBinders
363292 js1 <- foldM (\done' (headBinder, index) -> do
364293 headVar <- freshName
365− jss <- binderToJs m e headVar done' headBinder
294+ jss <- binderToJs m headVar done' headBinder
366295 return (JSVariableIntroduction headVar (Just (JSIndexer (JSNumericLiteral (Left index)) (JSVar varName))) : jss)) done (zip headBinders [0..])
367296 tailVar <- freshName
368− js2 <- binderToJs m e tailVar js1 tailBinder
297+ js2 <- binderToJs m tailVar js1 tailBinder
369298 return [JSIfElse (JSBinary GreaterThanOrEqualTo (JSAccessor "length" (JSVar varName)) (JSNumericLiteral (Left numberOfHeadBinders))) (JSBlock
370299 ( JSVariableIntroduction tailVar (Just (JSApp (JSAccessor "slice" (JSVar varName)) [JSNumericLiteral (Left numberOfHeadBinders)])) :
371300 js2
372301 )) Nothing]
373302 where
374− uncons :: [Binder] -> Binder -> ([Binder], Binder)
375− uncons acc (ConsBinder h t) = uncons (h : acc) t
376− uncons acc (PositionedBinder _ b) = uncons acc b
303+ uncons :: [Binder Ann] -> Binder Ann -> ([Binder Ann], Binder Ann)
304+ uncons acc (ConstructorBinder _ _ ctor' [h, t]) | isCons ctor' = uncons (h : acc) t
377305 uncons acc tailBinder = (reverse acc, tailBinder)
378−binderToJs m e varName done (NamedBinder ident binder) = do
379− js <- binderToJs m e varName done binder
306+binderToJs _ _ _ b@(ConstructorBinder{}) =
307+ error $ "Invalid ConstructorBinder in binderToJs: " ++ show b
308+binderToJs m varName done (NamedBinder _ ident binder) = do
309+ js <- binderToJs m varName done binder
380310 return (JSVariableIntroduction (identToJs ident) (Just (JSVar varName)) : js)
381−binderToJs m e varName done (PositionedBinder _ binder) =
382− binderToJs m e varName done binder
383311
312+literalToBinderJS :: (Functor m, Applicative m, Monad m) => ModuleName -> String -> [JS] -> Literal (Binder Ann) -> SupplyT m [JS]
313+literalToBinderJS _ varName done (NumericLiteral num) =
314+ return [JSIfElse (JSBinary EqualTo (JSVar varName) (JSNumericLiteral num)) (JSBlock done) Nothing]
315+literalToBinderJS _ varName done (StringLiteral str) =
316+ return [JSIfElse (JSBinary EqualTo (JSVar varName) (JSStringLiteral str)) (JSBlock done) Nothing]
317+literalToBinderJS _ varName done (BooleanLiteral True) =
318+ return [JSIfElse (JSVar varName) (JSBlock done) Nothing]
319+literalToBinderJS _ varName done (BooleanLiteral False) =
320+ return [JSIfElse (JSUnary Not (JSVar varName)) (JSBlock done) Nothing]
321+literalToBinderJS m varName done (ObjectLiteral bs) = go done bs
322+ where
323+ go :: (Functor m, Applicative m, Monad m) => [JS] -> [(String, Binder Ann)] -> SupplyT m [JS]
324+ go done' [] = return done'
325+ go done' ((prop, binder):bs') = do
326+ propVar <- freshName
327+ done'' <- go done' bs'
328+ js <- binderToJs m propVar done'' binder
329+ return (JSVariableIntroduction propVar (Just (accessorString prop (JSVar varName))) : js)
330+literalToBinderJS m varName done (ArrayLiteral bs) = do
331+ js <- go done 0 bs
332+ return [JSIfElse (JSBinary EqualTo (JSAccessor "length" (JSVar varName)) (JSNumericLiteral (Left (fromIntegral $ length bs)))) (JSBlock js) Nothing]
333+ where
334+ go :: (Functor m, Applicative m, Monad m) => [JS] -> Integer -> [Binder Ann] -> SupplyT m [JS]
335+ go done' _ [] = return done'
336+ go done' index (binder:bs') = do
337+ elVar <- freshName
338+ done'' <- go done' (index + 1) bs'
339+ js <- binderToJs m elVar done'' binder
340+ return (JSVariableIntroduction elVar (Just (JSIndexer (JSNumericLiteral (Left index)) (JSVar varName))) : js)
384341
342+isCons :: Qualified ProperName -> Bool
343+isCons (Qualified (Just mn) ctor) = mn == ModuleName [ProperName C.prim] && ctor == ProperName "Array"
344+isCons name = error $ "Unexpected argument in isCons: " ++ show name
src/Language/PureScript/CodeGen/Common.hs → src/Language/PureScript/CodeGen/JS/Common.hsrenamed+1−53
@@ -13,18 +13,12 @@
1313--
1414-----------------------------------------------------------------------------
1515
16−module Language.PureScript.CodeGen.Common where
16+module Language.PureScript.CodeGen.JS.Common where
1717
1818import Data.Char
1919import Data.List (intercalate)
20−import Data.Maybe (fromMaybe)
21−import Data.Function (on)
22−
23−import qualified Data.Map as M
2420
2521import Language.PureScript.Names
26−import Language.PureScript.Environment
27−import Language.PureScript.Types
2822
2923-- |
3024-- Convert an Ident into a valid Javascript identifier:
@@ -145,49 +139,3 @@ nameIsJsReserved name =
145139
146140moduleNameToJs :: ModuleName -> String
147141moduleNameToJs (ModuleName pns) = intercalate "_" (runProperName `map` pns)
148−
149−-- |
150−-- Finds the value stored for a data constructor in the current environment.
151−-- This is a partial function, but if an invalid type has reached this far then
152−-- something has gone wrong in typechecking.
153−--
154−lookupConstructor :: Environment -> Qualified ProperName -> (DataDeclType, ProperName, Type)
155−lookupConstructor e ctor = fromMaybe (error "Data constructor not found") $ ctor `M.lookup` dataConstructors e
156−
157−-- |
158−-- Checks whether a data constructor is the only constructor for that type, used
159−-- to simplify the check when generating code for binders.
160−--
161−isOnlyConstructor :: Environment -> Qualified ProperName -> Bool
162−isOnlyConstructor e ctor = numConstructors (ctor, lookupConstructor e ctor) == 1
163− where
164− numConstructors :: (Qualified ProperName, (DataDeclType, ProperName, Type)) -> Int
165− numConstructors ty = length $ filter (((==) `on` typeConstructor) ty) $ M.toList $ dataConstructors e
166− typeConstructor :: (Qualified ProperName, (DataDeclType, ProperName, Type)) -> (ModuleName, ProperName)
167− typeConstructor (Qualified (Just moduleName) _, (_, tyCtor, _)) = (moduleName, tyCtor)
168− typeConstructor _ = error "Invalid argument to isOnlyConstructor"
169−
170−-- |
171−-- Checks whether a data constructor is for a newtype.
172−--
173−isNewtypeConstructor :: Environment -> Qualified ProperName -> Bool
174−isNewtypeConstructor e ctor = case lookupConstructor e ctor of
175− (Newtype, _, _) -> True
176− (Data, _, _) -> False
177−
178−-- |
179−-- Checks the number of arguments a data constructor accepts.
180−--
181−getConstructorArity :: Environment -> Qualified ProperName -> Int
182−getConstructorArity e = go . (\(_, _, ctors) -> ctors) . lookupConstructor e
183− where
184− go :: Type -> Int
185− go (TypeApp (TypeApp f _) t) | f == tyFunction = go t + 1
186− go (ForAll _ ty _) = go ty
187− go _ = 0
188−
189−-- |
190−-- Checks whether a data constructor has no arguments, for example, `Nothing`.
191−--
192−isNullaryConstructor :: Environment -> Qualified ProperName -> Bool
193−isNullaryConstructor e = (== 0) . getConstructorArity e
src/Language/PureScript/Optimizer.hs → src/Language/PureScript/CodeGen/JS/Optimizer.hsrenamed+8−8
@@ -1,6 +1,6 @@
11-----------------------------------------------------------------------------
22--
3−-- Module : Language.PureScript.Optimizer
3+-- Module : Language.PureScript.CodeGen.JS.Optimizer
44-- Copyright : (c) Phil Freeman 2013
55-- License : MIT
66--
@@ -31,7 +31,7 @@
3131--
3232-----------------------------------------------------------------------------
3333
34−module Language.PureScript.Optimizer (
34+module Language.PureScript.CodeGen.JS.Optimizer (
3535 optimize
3636) where
3737
@@ -39,12 +39,12 @@ import Language.PureScript.CodeGen.JS.AST
3939import Language.PureScript.Options
4040import qualified Language.PureScript.Constants as C
4141
42−import Language.PureScript.Optimizer.Common
43−import Language.PureScript.Optimizer.TCO
44−import Language.PureScript.Optimizer.MagicDo
45−import Language.PureScript.Optimizer.Inliner
46−import Language.PureScript.Optimizer.Unused
47−import Language.PureScript.Optimizer.Blocks
42+import Language.PureScript.CodeGen.JS.Optimizer.Common
43+import Language.PureScript.CodeGen.JS.Optimizer.TCO
44+import Language.PureScript.CodeGen.JS.Optimizer.MagicDo
45+import Language.PureScript.CodeGen.JS.Optimizer.Inliner
46+import Language.PureScript.CodeGen.JS.Optimizer.Unused
47+import Language.PureScript.CodeGen.JS.Optimizer.Blocks
4848
4949-- |
5050-- Apply a series of optimizer passes to simplified Javascript code
src/Language/PureScript/Optimizer/Blocks.hs → src/Language/PureScript/CodeGen/JS/Optimizer/Blocks.hsrenamed+2−2
@@ -1,6 +1,6 @@
11-----------------------------------------------------------------------------
22--
3−-- Module : Language.PureScript.Optimizer.Blocks
3+-- Module : Language.PureScript.CodeGen.JS.Optimizer.Blocks
44-- Copyright : (c) Phil Freeman 2013-14
55-- License : MIT
66--
@@ -13,7 +13,7 @@
1313--
1414-----------------------------------------------------------------------------
1515
16−module Language.PureScript.Optimizer.Blocks
16+module Language.PureScript.CodeGen.JS.Optimizer.Blocks
1717 ( collapseNestedBlocks
1818 , collapseNestedIfs
1919 ) where
src/Language/PureScript/Optimizer/Common.hs → src/Language/PureScript/CodeGen/JS/Optimizer/Common.hsrenamed+2−2
@@ -1,6 +1,6 @@
11-----------------------------------------------------------------------------
22--
3−-- Module : Language.PureScript.Optimizer.Common
3+-- Module : Language.PureScript.CodeGen.JS.Optimizer.Common
44-- Copyright : (c) Phil Freeman 2013-14
55-- License : MIT
66--
@@ -13,7 +13,7 @@
1313--
1414-----------------------------------------------------------------------------
1515
16−module Language.PureScript.Optimizer.Common where
16+module Language.PureScript.CodeGen.JS.Optimizer.Common where
1717
1818import Data.Maybe (fromMaybe)
1919
src/Language/PureScript/Optimizer/Inliner.hs → src/Language/PureScript/CodeGen/JS/Optimizer/Inliner.hsrenamed+4−5
@@ -1,6 +1,6 @@
11-----------------------------------------------------------------------------
22--
3−-- Module : Language.PureScript.Optimizer.Inliner
3+-- Module : Language.PureScript.CodeGen.JS.Optimizer.Inliner
44-- Copyright : (c) Phil Freeman 2013-14
55-- License : MIT
66--
@@ -13,7 +13,7 @@
1313--
1414-----------------------------------------------------------------------------
1515
16−module Language.PureScript.Optimizer.Inliner (
16+module Language.PureScript.CodeGen.JS.Optimizer.Inliner (
1717 inlineVariables,
1818 inlineOperator,
1919 inlineCommonOperators,
@@ -25,10 +25,9 @@ module Language.PureScript.Optimizer.Inliner (
2525import Data.Maybe (fromMaybe)
2626
2727import Language.PureScript.CodeGen.JS.AST
28−import Language.PureScript.CodeGen.Common (identToJs)
29−import Language.PureScript.Optimizer.Common
28+import Language.PureScript.CodeGen.JS.Common
3029import Language.PureScript.Names
31−
30+import Language.PureScript.CodeGen.JS.Optimizer.Common
3231import qualified Language.PureScript.Constants as C
3332
3433shouldInline :: JS -> Bool
src/Language/PureScript/Optimizer/MagicDo.hs → src/Language/PureScript/CodeGen/JS/Optimizer/MagicDo.hsrenamed+5−6
@@ -1,6 +1,6 @@
11-----------------------------------------------------------------------------
22--
3−-- Module : Language.PureScript.Optimizer.MagicDo
3+-- Module : Language.PureScript.CodeGen.JS.Optimizer.MagicDo
44-- Copyright : (c) Phil Freeman 2013-14
55-- License : MIT
66--
@@ -14,18 +14,17 @@
1414--
1515-----------------------------------------------------------------------------
1616
17−module Language.PureScript.Optimizer.MagicDo (
17+module Language.PureScript.CodeGen.JS.Optimizer.MagicDo (
1818 magicDo
1919) where
2020
2121import Data.List (nub)
2222import Data.Maybe (fromJust, isJust)
2323
24−import Language.PureScript.Options
2524import Language.PureScript.CodeGen.JS.AST
26−import Language.PureScript.CodeGen.Common (identToJs)
25+import Language.PureScript.CodeGen.JS.Common
2726import Language.PureScript.Names
28−
27+import Language.PureScript.Options
2928import qualified Language.PureScript.Constants as C
3029
3130magicDo :: Options mode -> JS -> JS
@@ -104,7 +103,7 @@ magicDo' = everywhereOnJS undo . everywhereOnJSTopDown convert
104103 undo :: JS -> JS
105104 undo (JSReturn (JSApp (JSFunction (Just ident) [] body) [])) | ident == fnName = body
106105 undo other = other
107−
106+
108107 applyReturns :: JS -> JS
109108 applyReturns (JSReturn ret) = JSReturn (JSApp ret [])
110109 applyReturns (JSBlock jss) = JSBlock (map applyReturns jss)
src/Language/PureScript/Optimizer/TCO.hs → src/Language/PureScript/CodeGen/JS/Optimizer/TCO.hsrenamed+2−2
@@ -1,6 +1,6 @@
11-----------------------------------------------------------------------------
22--
3−-- Module : Language.PureScript.Optimizer.TCO
3+-- Module : Language.PureScript.CodeGen.JS.Optimizer.TCO
44-- Copyright : (c) Phil Freeman 2013-14
55-- License : MIT
66--
@@ -13,7 +13,7 @@
1313--
1414-----------------------------------------------------------------------------
1515
16−module Language.PureScript.Optimizer.TCO (tco) where
16+module Language.PureScript.CodeGen.JS.Optimizer.TCO (tco) where
1717
1818import Language.PureScript.Options
1919import Language.PureScript.CodeGen.JS.AST
src/Language/PureScript/Optimizer/Unused.hs → src/Language/PureScript/CodeGen/JS/Optimizer/Unused.hsrenamed+3−3
@@ -1,6 +1,6 @@
11-----------------------------------------------------------------------------
22--
3−-- Module : Language.PureScript.Optimizer.Unused
3+-- Module : Language.PureScript.CodeGen.JS.Optimizer.Unused
44-- Copyright : (c) Phil Freeman 2013-14
55-- License : MIT
66--
@@ -13,14 +13,14 @@
1313--
1414-----------------------------------------------------------------------------
1515
16−module Language.PureScript.Optimizer.Unused
16+module Language.PureScript.CodeGen.JS.Optimizer.Unused
1717 ( removeCodeAfterReturnStatements
1818 , removeUnusedArg
1919 , removeUndefinedApp
2020 ) where
2121
2222import Language.PureScript.CodeGen.JS.AST
23−import Language.PureScript.Optimizer.Common
23+import Language.PureScript.CodeGen.JS.Optimizer.Common
2424
2525import qualified Language.PureScript.Constants as C
2626
src/Language/PureScript/CoreFn.hsnew file+26
@@ -0,0 +1,26 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.CoreFn
4+-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
5+-- License : MIT
6+--
7+-- Maintainer : Phil Freeman <paf31@cantab.net>, Gary Burgess <gary.burgess@gmail.com>
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- | The core functional representation
12+--
13+-----------------------------------------------------------------------------
14+
15+module Language.PureScript.CoreFn (
16+ module C
17+) where
18+
19+import Language.PureScript.CoreFn.Ann as C
20+import Language.PureScript.CoreFn.Binders as C
21+import Language.PureScript.CoreFn.Desugar as C
22+import Language.PureScript.CoreFn.Expr as C
23+import Language.PureScript.CoreFn.Literals as C
24+import Language.PureScript.CoreFn.Meta as C
25+import Language.PureScript.CoreFn.Module as C
26+import Language.PureScript.CoreFn.Traversals as C
src/Language/PureScript/CoreFn/Ann.hsnew file+30
@@ -0,0 +1,30 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.CoreFn.Ann
4+-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
5+-- License : MIT
6+--
7+-- Maintainer : Phil Freeman <paf31@cantab.net>, Gary Burgess <gary.burgess@gmail.com>
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- | Type alias for basic annotations
12+--
13+-----------------------------------------------------------------------------
14+
15+module Language.PureScript.CoreFn.Ann where
16+
17+import Language.PureScript.AST.SourcePos
18+import Language.PureScript.CoreFn.Meta
19+import Language.PureScript.Types
20+
21+-- |
22+-- Type alias for basic annotations
23+--
24+type Ann = (Maybe SourceSpan, Maybe Type, Maybe Meta)
25+
26+-- |
27+-- Initial annotation with no metadata
28+--
29+nullAnn :: Ann
30+nullAnn = (Nothing, Nothing, Nothing)
src/Language/PureScript/CoreFn/Binders.hsnew file+47
@@ -0,0 +1,47 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.CoreFn.Binders
4+-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
5+-- License : MIT
6+--
7+-- Maintainer : Phil Freeman <paf31@cantab.net>, Gary Burgess <gary.burgess@gmail.com>
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- | The core functional representation for binders
12+--
13+-----------------------------------------------------------------------------
14+
15+{-# LANGUAGE DeriveDataTypeable #-}
16+
17+module Language.PureScript.CoreFn.Binders where
18+
19+import qualified Data.Data as D
20+
21+import Language.PureScript.CoreFn.Literals
22+import Language.PureScript.Names
23+
24+-- |
25+-- Data type for binders
26+--
27+data Binder a
28+ -- |
29+ -- Wildcard binder
30+ --
31+ = NullBinder a
32+ -- |
33+ -- A binder which matches a literal value
34+ --
35+ | LiteralBinder a (Literal (Binder a))
36+ -- |
37+ -- A binder which binds an identifier
38+ --
39+ | VarBinder a Ident
40+ -- |
41+ -- A binder which matches a data constructor (type name, constructor name, binders)
42+ --
43+ | ConstructorBinder a (Qualified ProperName) (Qualified ProperName) [Binder a]
44+ -- |
45+ -- A binder which binds its input to an identifier
46+ --
47+ | NamedBinder a Ident (Binder a) deriving (Show, D.Data, D.Typeable)
src/Language/PureScript/CoreFn/Desugar.hsnew file+242
@@ -0,0 +1,242 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.CoreFn.Desugar
4+-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
5+-- License : MIT
6+--
7+-- Maintainer : Phil Freeman <paf31@cantab.net>, Gary Burgess <gary.burgess@gmail.com>
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- | The AST -> CoreFn desugaring step
12+--
13+-----------------------------------------------------------------------------
14+
15+module Language.PureScript.CoreFn.Desugar (moduleToCoreFn) where
16+
17+import Data.Function (on)
18+import Data.List (sort, sortBy, nub)
19+import Data.Maybe (mapMaybe)
20+import qualified Data.Map as M
21+
22+import Control.Arrow (second, (***))
23+
24+import Language.PureScript.AST.SourcePos
25+import Language.PureScript.AST.Traversals
26+import Language.PureScript.CoreFn.Ann
27+import Language.PureScript.CoreFn.Binders
28+import Language.PureScript.CoreFn.Expr
29+import Language.PureScript.CoreFn.Literals
30+import Language.PureScript.CoreFn.Meta
31+import Language.PureScript.CoreFn.Module
32+import Language.PureScript.Environment
33+import Language.PureScript.Names
34+import Language.PureScript.Sugar.TypeClasses (typeClassMemberName, superClassDictionaryNames)
35+import Language.PureScript.Types
36+import qualified Language.PureScript.AST as A
37+import qualified Language.PureScript.Constants as C
38+
39+-- |
40+-- Desugars a module from AST to CoreFn representation.
41+--
42+moduleToCoreFn :: Environment -> A.Module -> Module Ann
43+moduleToCoreFn env (A.Module mn decls (Just exps)) =
44+ let imports = nub $ mapMaybe importToCoreFn decls ++ findQualModules decls
45+ exps' = nub $ concatMap exportToCoreFn exps
46+ externs = nub $ mapMaybe externToCoreFn decls
47+ decls' = concatMap (declToCoreFn env Nothing) decls
48+ in Module mn imports exps' externs decls'
49+moduleToCoreFn _ (A.Module{}) =
50+ error "Module exports were not elaborated before moduleToCoreFn"
51+
52+findQualModules :: [A.Declaration] -> [ModuleName]
53+findQualModules decls =
54+ let (f, _, _, _, _) = everythingOnValues (++) (const []) fqValues (const []) (const []) (const [])
55+ in f `concatMap` decls
56+ where
57+ fqValues :: A.Expr -> [ModuleName]
58+ fqValues (A.Var (Qualified (Just mn) _)) = [mn]
59+ fqValues _ = []
60+
61+-- |
62+-- Desugars import declarations from AST to CoreFn representation.
63+--
64+importToCoreFn :: A.Declaration -> Maybe ModuleName
65+importToCoreFn (A.ImportDeclaration name _ _) = Just name
66+importToCoreFn (A.PositionedDeclaration _ d) = importToCoreFn d
67+importToCoreFn _ = Nothing
68+
69+-- |
70+-- Desugars foreign declarations from AST to CoreFn representation.
71+--
72+externToCoreFn :: A.Declaration -> Maybe ForeignDecl
73+externToCoreFn (A.ExternDeclaration _ name js ty) = Just (name, js, ty)
74+externToCoreFn (A.ExternInstanceDeclaration name _ _ _) = Just (name, Nothing, tyObject)
75+externToCoreFn (A.PositionedDeclaration _ d) = externToCoreFn d
76+externToCoreFn _ = Nothing
77+
78+-- |
79+-- Desugars export declarations references from AST to CoreFn representation.
80+-- CoreFn modules only export values, so all data constructors, class
81+-- constructor, instances and values are flattened into one list.
82+--
83+exportToCoreFn :: A.DeclarationRef -> [Ident]
84+exportToCoreFn (A.TypeRef _ (Just dctors)) = map properToIdent dctors
85+exportToCoreFn (A.ValueRef name) = [name]
86+exportToCoreFn (A.TypeClassRef name) = [properToIdent name]
87+exportToCoreFn (A.TypeInstanceRef name) = [name]
88+exportToCoreFn (A.PositionedDeclarationRef _ d) = exportToCoreFn d
89+exportToCoreFn _ = []
90+
91+-- |
92+-- Desugars member declarations from AST to CoreFn representation.
93+--
94+declToCoreFn :: Environment -> Maybe SourceSpan -> A.Declaration -> [Bind Ann]
95+declToCoreFn _ ss (A.DataDeclaration Newtype _ _ [(ctor, _)]) =
96+ [NonRec (properToIdent ctor) $
97+ Abs (ss, Nothing, Just IsNewtype) (Ident "x") (Var nullAnn $ Qualified Nothing (Ident "x"))]
98+declToCoreFn _ _ d@(A.DataDeclaration Newtype _ _ _) =
99+ error $ "Found newtype with multiple constructors: " ++ show d
100+declToCoreFn _ ss (A.DataDeclaration Data tyName _ ctors) =
101+ flip map ctors $ \(ctor, tys) ->
102+ NonRec (properToIdent ctor) $ Constructor (ss, Nothing, Nothing) tyName ctor (length tys)
103+declToCoreFn env ss (A.DataBindingGroupDeclaration ds) = concatMap (declToCoreFn env ss) ds
104+declToCoreFn env ss (A.ValueDeclaration name _ _ (Right e)) =
105+ [NonRec name (exprToCoreFn env ss Nothing e)]
106+declToCoreFn env ss (A.BindingGroupDeclaration ds) =
107+ [Rec $ map (\(name, _, e) -> (name, exprToCoreFn env ss Nothing e)) ds]
108+declToCoreFn _ ss (A.TypeClassDeclaration name _ supers members) =
109+ [NonRec (properToIdent name) $ mkTypeClassConstructor ss supers members]
110+declToCoreFn env _ (A.PositionedDeclaration ss d) =
111+ declToCoreFn env (Just ss) d
112+declToCoreFn _ _ _ = []
113+
114+-- |
115+-- Makes a typeclass dictionary constructor function. The returned expression
116+-- is a function that accepts the superclass instances and member
117+-- implementations and returns a record for the instance dictionary.
118+--
119+mkTypeClassConstructor :: Maybe SourceSpan -> [Constraint] -> [A.Declaration] -> Expr Ann
120+mkTypeClassConstructor ss [] [] = Literal (ss, Nothing, Just IsTypeClassConstructor) (ObjectLiteral [])
121+mkTypeClassConstructor ss supers members =
122+ let args@(a:as) = sort $ map typeClassMemberName members ++ superClassDictionaryNames supers
123+ props = [ (arg, Var nullAnn $ Qualified Nothing (Ident arg)) | arg <- args ]
124+ dict = Literal nullAnn (ObjectLiteral props)
125+ in Abs (ss, Nothing, Just IsTypeClassConstructor)
126+ (Ident a)
127+ (foldr (Abs nullAnn . Ident) dict as)
128+
129+-- |
130+-- Desugars expressions from AST to CoreFn representation.
131+--
132+exprToCoreFn :: Environment -> Maybe SourceSpan -> Maybe Type -> A.Expr -> Expr Ann
133+exprToCoreFn _ ss ty (A.NumericLiteral v) =
134+ Literal (ss, ty, Nothing) (NumericLiteral v)
135+exprToCoreFn _ ss ty (A.StringLiteral v) =
136+ Literal (ss, ty, Nothing) (StringLiteral v)
137+exprToCoreFn _ ss ty (A.BooleanLiteral v) =
138+ Literal (ss, ty, Nothing) (BooleanLiteral v)
139+exprToCoreFn env ss ty (A.ArrayLiteral vs) =
140+ Literal (ss, ty, Nothing) (ArrayLiteral $ map (exprToCoreFn env ss Nothing) vs)
141+exprToCoreFn env ss ty (A.ObjectLiteral vs) =
142+ Literal (ss, ty, Nothing) (ObjectLiteral $ map (second (exprToCoreFn env ss Nothing)) vs)
143+exprToCoreFn env ss ty (A.Accessor name v) =
144+ Accessor (ss, ty, Nothing) name (exprToCoreFn env ss Nothing v)
145+exprToCoreFn env ss ty (A.ObjectUpdate obj vs) =
146+ ObjectUpdate (ss, ty, Nothing) (exprToCoreFn env ss Nothing obj) $ map (second (exprToCoreFn env ss Nothing)) vs
147+exprToCoreFn env ss ty (A.Abs (Left name) v) =
148+ Abs (ss, ty, Nothing) name (exprToCoreFn env ss Nothing v)
149+exprToCoreFn _ _ _ (A.Abs _ _) =
150+ error "Abs with Binder argument was not desugared before exprToCoreFn"
151+exprToCoreFn env ss ty (A.App v1 v2) =
152+ App (ss, ty, Nothing) (exprToCoreFn env ss Nothing v1) (exprToCoreFn env ss Nothing v2)
153+exprToCoreFn _ ss ty (A.Var ident) =
154+ Var (ss, ty, Nothing) ident
155+exprToCoreFn env ss ty (A.IfThenElse v1 v2 v3) =
156+ Case (ss, ty, Nothing) [exprToCoreFn env ss Nothing v1]
157+ [ CaseAlternative [LiteralBinder nullAnn $ BooleanLiteral True]
158+ (Right $ exprToCoreFn env Nothing Nothing v2)
159+ , CaseAlternative [LiteralBinder nullAnn $ BooleanLiteral False]
160+ (Right $ exprToCoreFn env Nothing Nothing v3) ]
161+exprToCoreFn env ss ty (A.Constructor name) =
162+ Var (ss, ty, Just $ getConstructorMeta env name) $ fmap properToIdent name
163+exprToCoreFn env ss ty (A.Case vs alts) =
164+ Case (ss, ty, Nothing) (map (exprToCoreFn env ss Nothing) vs) (map (altToCoreFn env ss) alts)
165+exprToCoreFn env ss _ (A.TypedValue _ v ty) =
166+ exprToCoreFn env ss (Just ty) v
167+exprToCoreFn env ss ty (A.Let ds v) =
168+ Let (ss, ty, Nothing) (concatMap (declToCoreFn env ss) ds) (exprToCoreFn env ss Nothing v)
169+exprToCoreFn env ss ty (A.TypeClassDictionaryConstructorApp name (A.TypedValue _ (A.ObjectLiteral vs) _)) =
170+ let args = map (exprToCoreFn env ss Nothing . snd) $ sortBy (compare `on` fst) vs
171+ ctor = Var (ss, Nothing, Just IsTypeClassConstructor) (fmap properToIdent name)
172+ in foldl (App (ss, Nothing, Nothing)) ctor args
173+exprToCoreFn env _ ty (A.PositionedValue ss v) =
174+ exprToCoreFn env (Just ss) ty v
175+exprToCoreFn _ _ _ e =
176+ error $ "Unexpected value in exprToCoreFn: " ++ show e
177+
178+-- |
179+-- Desugars case alternatives from AST to CoreFn representation.
180+--
181+altToCoreFn :: Environment -> Maybe SourceSpan -> A.CaseAlternative -> CaseAlternative Ann
182+altToCoreFn env ss (A.CaseAlternative bs vs) = CaseAlternative (map (binderToCoreFn env ss) bs) (go vs)
183+ where
184+ go :: Either [(A.Guard, A.Expr)] A.Expr -> Either [(Guard Ann, Expr Ann)] (Expr Ann)
185+ go (Left ges) = Left $ map (exprToCoreFn env ss Nothing *** exprToCoreFn env ss Nothing) ges
186+ go (Right e) = Right (exprToCoreFn env ss Nothing e)
187+
188+-- |
189+-- Desugars case binders from AST to CoreFn representation.
190+--
191+binderToCoreFn :: Environment -> Maybe SourceSpan -> A.Binder -> Binder Ann
192+binderToCoreFn _ ss (A.NullBinder) =
193+ NullBinder (ss, Nothing, Nothing)
194+binderToCoreFn _ ss (A.BooleanBinder b) =
195+ LiteralBinder (ss, Nothing, Nothing) (BooleanLiteral b)
196+binderToCoreFn _ ss (A.StringBinder s) =
197+ LiteralBinder (ss, Nothing, Nothing) (StringLiteral s)
198+binderToCoreFn _ ss (A.NumberBinder n) =
199+ LiteralBinder (ss, Nothing, Nothing) (NumericLiteral n)
200+binderToCoreFn _ ss (A.VarBinder name) =
201+ VarBinder (ss, Nothing, Nothing) name
202+binderToCoreFn env ss (A.ConstructorBinder dctor@(Qualified mn _) bs) =
203+ let (_, tctor, _) = lookupConstructor env dctor
204+ in ConstructorBinder (ss, Nothing, Just $ getConstructorMeta env dctor) (Qualified mn tctor) dctor (map (binderToCoreFn env ss) bs)
205+binderToCoreFn env ss (A.ObjectBinder bs) =
206+ LiteralBinder (ss, Nothing, Nothing) (ObjectLiteral $ map (second (binderToCoreFn env ss)) bs)
207+binderToCoreFn env ss (A.ArrayBinder bs) =
208+ LiteralBinder (ss, Nothing, Nothing) (ArrayLiteral $ map (binderToCoreFn env ss) bs)
209+binderToCoreFn env ss (A.ConsBinder b1 b2) =
210+ let arrCtor = Qualified (Just $ ModuleName [ProperName "Prim"]) (ProperName "Array")
211+ in ConstructorBinder (ss, Nothing, Nothing) arrCtor arrCtor $ map (binderToCoreFn env ss) [b1, b2]
212+binderToCoreFn env ss (A.NamedBinder name b) =
213+ NamedBinder (ss, Nothing, Nothing) name (binderToCoreFn env ss b)
214+binderToCoreFn env _ (A.PositionedBinder ss b) =
215+ binderToCoreFn env (Just ss) b
216+
217+-- |
218+-- Converts a ProperName to an Ident.
219+--
220+properToIdent :: ProperName -> Ident
221+properToIdent = Ident . runProperName
222+
223+-- |
224+-- Gets metadata for data constructors.
225+--
226+getConstructorMeta :: Environment -> Qualified ProperName -> Meta
227+getConstructorMeta env ctor =
228+ case lookupConstructor env ctor of
229+ (Newtype, _, _) -> IsNewtype
230+ dc@(Data, _, ty) ->
231+ let constructorType = if numConstructors (ctor, dc) == 1 then ProductType else SumType
232+ in IsConstructor constructorType (getArity ty)
233+ where
234+ getArity :: Type -> Int
235+ getArity (TypeApp (TypeApp f _) t) | f == tyFunction = getArity t + 1
236+ getArity (ForAll _ ty _) = getArity ty
237+ getArity _ = 0
238+ numConstructors :: (Qualified ProperName, (DataDeclType, ProperName, Type)) -> Int
239+ numConstructors ty = length $ filter (((==) `on` typeConstructor) ty) $ M.toList $ dataConstructors env
240+ typeConstructor :: (Qualified ProperName, (DataDeclType, ProperName, Type)) -> (ModuleName, ProperName)
241+ typeConstructor (Qualified (Just mn) _, (_, tyCtor, _)) = (mn, tyCtor)
242+ typeConstructor _ = error "Invalid argument to typeConstructor"
src/Language/PureScript/CoreFn/Expr.hsnew file+97
@@ -0,0 +1,97 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.CoreFn.Expr
4+-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
5+-- License : MIT
6+--
7+-- Maintainer : Phil Freeman <paf31@cantab.net>, Gary Burgess <gary.burgess@gmail.com>
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- | The core functional representation
12+--
13+-----------------------------------------------------------------------------
14+
15+{-# LANGUAGE DeriveDataTypeable #-}
16+
17+module Language.PureScript.CoreFn.Expr where
18+
19+import qualified Data.Data as D
20+
21+import Language.PureScript.CoreFn.Binders
22+import Language.PureScript.CoreFn.Literals
23+import Language.PureScript.CoreFn.Meta
24+import Language.PureScript.Names
25+
26+-- |
27+-- Data type for expressions and terms
28+--
29+data Expr a
30+ -- |
31+ -- A literal value
32+ --
33+ = Literal a (Literal (Expr a))
34+ -- |
35+ -- A data constructor (type name, constructor name, arity)
36+ --
37+ | Constructor a ProperName ProperName Arity
38+ -- |
39+ -- A record property accessor
40+ --
41+ | Accessor a String (Expr a)
42+ -- |
43+ -- Partial record update
44+ --
45+ | ObjectUpdate a (Expr a) [(String, Expr a)]
46+ -- |
47+ -- Function introduction
48+ --
49+ | Abs a Ident (Expr a)
50+ -- |
51+ -- Function application
52+ --
53+ | App a (Expr a) (Expr a)
54+ -- |
55+ -- Variable
56+ --
57+ | Var a (Qualified Ident)
58+ -- |
59+ -- A case expression
60+ --
61+ | Case a [Expr a] [CaseAlternative a]
62+ -- |
63+ -- A let binding
64+ --
65+ | Let a [Bind a] (Expr a) deriving (Show, D.Data, D.Typeable)
66+
67+-- |
68+-- A let or module binding.
69+--
70+data Bind a
71+ -- |
72+ -- Non-recursive binding for a single value
73+ --
74+ = NonRec Ident (Expr a)
75+ -- |
76+ -- Mutually recursive binding group for several values
77+ --
78+ | Rec [(Ident, Expr a)] deriving (Show, D.Data, D.Typeable)
79+
80+-- |
81+-- A guard is just a boolean-valued expression that appears alongside a set of binders
82+--
83+type Guard a = Expr a
84+
85+-- |
86+-- An alternative in a case statement
87+--
88+data CaseAlternative a = CaseAlternative
89+ { -- |
90+ -- A collection of binders with which to match the inputs
91+ --
92+ caseAlternativeBinders :: [Binder a]
93+ -- |
94+ -- The result expression or a collect of guarded expressions
95+ --
96+ , caseAlternativeResult :: Either [(Guard a, Expr a)] (Expr a)
97+ } deriving (Show, D.Data, D.Typeable)
src/Language/PureScript/CoreFn/Literals.hsnew file+45
@@ -0,0 +1,45 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.CoreFn.Literals
4+-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
5+-- License : MIT
6+--
7+-- Maintainer : Phil Freeman <paf31@cantab.net>, Gary Burgess <gary.burgess@gmail.com>
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- | The core functional representation for literal values.
12+--
13+-----------------------------------------------------------------------------
14+
15+{-# LANGUAGE DeriveDataTypeable #-}
16+
17+module Language.PureScript.CoreFn.Literals where
18+
19+import qualified Data.Data as D
20+
21+-- |
22+-- Data type for literal values. Parameterised so it can be used for Exprs and
23+-- Binders.
24+--
25+data Literal a
26+ -- |
27+ -- A numeric literal
28+ --
29+ = NumericLiteral (Either Integer Double)
30+ -- |
31+ -- A string literal
32+ --
33+ | StringLiteral String
34+ -- |
35+ -- A boolean literal
36+ --
37+ | BooleanLiteral Bool
38+ -- |
39+ -- An array literal
40+ --
41+ | ArrayLiteral [a]
42+ -- |
43+ -- An object literal
44+ --
45+ | ObjectLiteral [(String, a)] deriving (Show, D.Data, D.Typeable)
src/Language/PureScript/CoreFn/Meta.hsnew file+54
@@ -0,0 +1,54 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.CoreFn.Meta
4+-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
5+-- License : MIT
6+--
7+-- Maintainer : Phil Freeman <paf31@cantab.net>, Gary Burgess <gary.burgess@gmail.com>
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- | Metadata annotations for core functional representation
12+--
13+-----------------------------------------------------------------------------
14+
15+{-# LANGUAGE DeriveDataTypeable #-}
16+
17+module Language.PureScript.CoreFn.Meta where
18+
19+import qualified Data.Data as D
20+
21+-- |
22+-- Metadata annotations
23+--
24+data Meta
25+ -- |
26+ -- The contained value is a data constructor
27+ --
28+ = IsConstructor ConstructorType Arity
29+ -- |
30+ -- The contained value is a newtype
31+ --
32+ | IsNewtype
33+ -- |
34+ -- The contained value is a typeclass dictionary constructor
35+ --
36+ | IsTypeClassConstructor deriving (Show, D.Data, D.Typeable)
37+
38+-- |
39+-- Type alias for constructor arity
40+--
41+type Arity = Int
42+
43+-- |
44+-- Data constructor metadata
45+--
46+data ConstructorType
47+ -- |
48+ -- The constructor is for a type with a single construcor
49+ --
50+ = ProductType
51+ -- |
52+ -- The constructor is for a type with multiple construcors
53+ --
54+ | SumType deriving (Show, D.Data, D.Typeable)
src/Language/PureScript/CoreFn/Module.hsnew file+30
@@ -0,0 +1,30 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.CoreFn.Module
4+-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
5+-- License : MIT
6+--
7+-- Maintainer : Phil Freeman <paf31@cantab.net>, Gary Burgess <gary.burgess@gmail.com>
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- | The CoreFn module representation
12+--
13+-----------------------------------------------------------------------------
14+
15+module Language.PureScript.CoreFn.Module where
16+
17+import Language.PureScript.CodeGen.JS.AST
18+import Language.PureScript.CoreFn.Expr
19+import Language.PureScript.Names
20+import Language.PureScript.Types
21+
22+data Module a = Module
23+ { moduleName :: ModuleName
24+ , moduleImports :: [ModuleName]
25+ , moduleExports :: [Ident]
26+ , moduleForeign :: [ForeignDecl]
27+ , moduleDecls :: [Bind a]
28+ } deriving (Show)
29+
30+type ForeignDecl = (Ident, Maybe JS, Type)
src/Language/PureScript/CoreFn/Traversals.hsnew file+85
@@ -0,0 +1,85 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.CoreFn.Traversals
4+-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
5+-- License : MIT
6+--
7+-- Maintainer : Phil Freeman <paf31@cantab.net>, Gary Burgess <gary.burgess@gmail.com>
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- | CoreFn traversal helpers
12+--
13+-----------------------------------------------------------------------------
14+
15+module Language.PureScript.CoreFn.Traversals where
16+
17+import Control.Arrow (second, (***), (+++))
18+
19+import Language.PureScript.CoreFn.Binders
20+import Language.PureScript.CoreFn.Expr
21+import Language.PureScript.CoreFn.Literals
22+
23+everywhereOnValues :: (Bind a -> Bind a) ->
24+ (Expr a -> Expr a) ->
25+ (Binder a -> Binder a) ->
26+ (Bind a -> Bind a, Expr a -> Expr a, Binder a -> Binder a)
27+everywhereOnValues f g h = (f', g', h')
28+ where
29+ f' (NonRec name e) = f (NonRec name (g' e))
30+ f' (Rec es) = f (Rec (map (second g') es))
31+
32+ g' (Literal ann e) = g (Literal ann (handleLiteral g' e))
33+ g' (Accessor ann prop e) = g (Accessor ann prop (g' e))
34+ g' (ObjectUpdate ann obj vs) = g (ObjectUpdate ann (g' obj) (map (fmap g') vs))
35+ g' (Abs ann name e) = g (Abs ann name (g' e))
36+ g' (App ann v1 v2) = g (App ann (g' v1) (g' v2))
37+ g' (Case ann vs alts) = g (Case ann (map g' vs) (map handleCaseAlternative alts))
38+ g' (Let ann ds e) = g (Let ann (map f' ds) (g' e))
39+ g' e = g e
40+
41+ h' (LiteralBinder a b) = h (LiteralBinder a (handleLiteral h' b))
42+ h' (NamedBinder a name b) = h (NamedBinder a name (h' b))
43+ h' b = h b
44+
45+ handleCaseAlternative ca =
46+ ca { caseAlternativeBinders = map h' (caseAlternativeBinders ca)
47+ , caseAlternativeResult = (map (g' *** g') +++ g') (caseAlternativeResult ca)
48+ }
49+
50+ handleLiteral :: (a -> a) -> Literal a -> Literal a
51+ handleLiteral i (ArrayLiteral ls) = ArrayLiteral (map i ls)
52+ handleLiteral i (ObjectLiteral ls) = ObjectLiteral (map (fmap i) ls)
53+ handleLiteral _ other = other
54+
55+everythingOnValues :: (r -> r -> r) ->
56+ (Bind a -> r) ->
57+ (Expr a -> r) ->
58+ (Binder a -> r) ->
59+ (CaseAlternative a -> r) ->
60+ (Bind a -> r, Expr a -> r, Binder a -> r, CaseAlternative a -> r)
61+everythingOnValues (<>) f g h i = (f', g', h', i')
62+ where
63+ f' b@(NonRec _ e) = f b <> g' e
64+ f' b@(Rec es) = foldl (<>) (f b) (map (g' . snd) es)
65+
66+ g' v@(Literal _ l) = foldl (<>) (g v) (map g' (extractLiteral l))
67+ g' v@(Accessor _ _ e1) = g v <> g' e1
68+ g' v@(ObjectUpdate _ obj vs) = foldl (<>) (g v <> g' obj) (map (g' . snd) vs)
69+ g' v@(Abs _ _ e1) = g v <> g' e1
70+ g' v@(App _ e1 e2) = g v <> g' e1 <> g' e2
71+ g' v@(Case _ vs alts) = foldl (<>) (foldl (<>) (g v) (map g' vs)) (map i' alts)
72+ g' v@(Let _ ds e1) = foldl (<>) (g v) (map f' ds) <> g' e1
73+ g' v = g v
74+
75+ h' b@(LiteralBinder _ l) = foldl (<>) (h b) (map h' (extractLiteral l))
76+ h' b@(ConstructorBinder _ _ _ bs) = foldl (<>) (h b) (map h' bs)
77+ h' b@(NamedBinder _ _ b1) = h b <> h' b1
78+ h' b = h b
79+
80+ i' ca@(CaseAlternative bs (Right val)) = foldl (<>) (i ca) (map h' bs) <> g' val
81+ i' ca@(CaseAlternative bs (Left gs)) = foldl (<>) (i ca) (map h' bs ++ concatMap (\(grd, val) -> [g' grd, g' val]) gs)
82+
83+ extractLiteral (ArrayLiteral xs) = xs
84+ extractLiteral (ObjectLiteral xs) = map snd xs
85+ extractLiteral _ = []
src/Language/PureScript/DeadCodeElimination.hs+57−71
@@ -8,7 +8,7 @@
88-- Stability : experimental
99-- Portability :
1010--
11−-- |
11+-- | Dead code elimination.
1212--
1313-----------------------------------------------------------------------------
1414
@@ -16,98 +16,84 @@ module Language.PureScript.DeadCodeElimination (
1616 eliminateDeadCode
1717) where
1818
19−import Data.List
2019import Data.Graph
20+import Data.List
2121import Data.Maybe (mapMaybe)
2222
23+import Language.PureScript.CoreFn
2324import Language.PureScript.Names
24−import Language.PureScript.AST
2525
2626-- |
2727-- Eliminate all declarations which are not a transitive dependency of the entry point module
2828--
29−eliminateDeadCode :: [ModuleName] -> [Module] -> [Module]
29+eliminateDeadCode :: [ModuleName] -> [Module a] -> [Module a]
3030eliminateDeadCode entryPoints ms = map go ms
3131 where
32− go (Module moduleName ds (Just exps)) = Module moduleName ds' (Just exps')
32+ go (Module mn imps exps foreigns ds) = Module mn imps exps' foreigns' ds'
3333 where
34− ds' = filter (isUsed moduleName graph vertexFor entryPointVertices) ds
35− exps' = mapMaybe (filterExport ds') exps
36− go _ = error "Exports should have been elaborated in name desugaring"
34+ ds' = filter (isUsed mn graph vertexFor entryPointVertices) ds
35+ foreigns' = filter (isUsed' mn graph vertexFor entryPointVertices . foreignIdent) foreigns
36+ names = concatMap bindIdents ds' ++ map foreignIdent foreigns'
37+ exps' = filter (`elem` names) exps
3738 declarations = concatMap declarationsByModule ms
3839 (graph, _, vertexFor) = graphFromEdges $ map (\(key, deps) -> (key, key, deps)) declarations
3940 entryPointVertices = mapMaybe (vertexFor . fst) . filter (\((mn, _), _) -> mn `elem` entryPoints) $ declarations
4041
41− filterExport :: [Declaration] -> DeclarationRef -> Maybe DeclarationRef
42− filterExport decls r@(TypeRef name _) | (any $ typeOrClassExists name) decls = Just r
43− filterExport decls r@(TypeClassRef name) | (any $ typeOrClassExists name) decls = Just r
44− filterExport decls r@(ValueRef name) | (any $ valueExists name) decls = Just r
45− filterExport decls r@(TypeInstanceRef name) | (any $ valueExists name) decls = Just r
46− filterExport _ _ = Nothing
47−
48− valueExists :: Ident -> Declaration -> Bool
49− valueExists name (ValueDeclaration name' _ _ _) = name == name'
50− valueExists name (ExternDeclaration _ name' _ _) = name == name'
51− valueExists name (BindingGroupDeclaration decls) = any (\(name', _, _) -> name == name') decls
52− valueExists name (PositionedDeclaration _ d) = valueExists name d
53− valueExists _ _ = False
42+-- |
43+-- Extract declaration names for a binding group.
44+--
45+bindIdents :: Bind a -> [Ident]
46+bindIdents (NonRec name _) = [name]
47+bindIdents (Rec names) = map fst names
5448
55− typeOrClassExists :: ProperName -> Declaration -> Bool
56− typeOrClassExists name (DataDeclaration _ name' _ _) = name == name'
57− typeOrClassExists name (TypeClassDeclaration name' _ _ _) = name == name'
58− typeOrClassExists name (DataBindingGroupDeclaration decls) = any (typeOrClassExists name) decls
59− typeOrClassExists name (PositionedDeclaration _ d) = typeOrClassExists name d
60− typeOrClassExists _ _ = False
49+-- |
50+-- Extract the ident for a foreign declaration.
51+--
52+foreignIdent :: ForeignDecl -> Ident
53+foreignIdent (name, _, _) = name
6154
62−type Key = (ModuleName, Either Ident ProperName)
55+-- |
56+-- Key type to use in graph
57+--
58+type Key = (ModuleName, Ident)
6359
64−declarationsByModule :: Module -> [(Key, [Key])]
65−declarationsByModule (Module moduleName ds _) = concatMap go ds
60+-- |
61+-- Find dependencies for each member in a module.
62+--
63+declarationsByModule :: Module a -> [(Key, [Key])]
64+declarationsByModule (Module mn _ _ fs ds) =
65+ let fs' = map ((\name -> ((mn, name), [])) . foreignIdent) fs
66+ in fs' ++ concatMap go ds
6667 where
67− go :: Declaration -> [(Key, [Key])]
68− go d@(ValueDeclaration name _ _ _) = [((moduleName, Left name), dependencies moduleName d)]
69− go (DataDeclaration _ _ _ dctors) = map (\(name, _) -> ((moduleName, Right name), [])) dctors
70− go (ExternDeclaration _ name _ _) = [((moduleName, Left name), [])]
71− go d@(BindingGroupDeclaration names') = map (\(name, _, _) -> ((moduleName, Left name), dependencies moduleName d)) names'
72− go (DataBindingGroupDeclaration ds') = concatMap go ds'
73− go (TypeClassDeclaration name _ _ _) = [((moduleName, Right name), [])]
74− go (PositionedDeclaration _ d) = go d
75− go _ = []
68+ go :: Bind a -> [(Key, [Key])]
69+ go d@(NonRec name _) = [((mn, name), dependencies d)]
70+ go d@(Rec names') = map (\(name, _) -> ((mn, name), dependencies d)) names'
7671
77−dependencies :: ModuleName -> Declaration -> [Key]
78−dependencies moduleName =
79− let (f, _, _, _, _) = everythingOnValues (++) (const []) values (const []) (const []) (const [])
72+-- |
73+-- Find all referenced values within a binding group.
74+--
75+dependencies :: Bind a -> [Key]
76+dependencies =
77+ let (f, _, _, _) = everythingOnValues (++) (const []) values (const []) (const [])
8078 in nub . f
8179 where
82− values :: Expr -> [Key]
83− values (Var ident) = let (mn, name) = qualify moduleName ident in [(mn, Left name)]
84− values (Constructor (Qualified (Just mn) name)) = [(mn, Right name)]
85− values (Constructor (Qualified Nothing _)) = error "Found unqualified data constructor"
86− values (TypeClassDictionaryConstructorApp (Qualified (Just mn) name) _) = [(mn, Right name)]
87− values (TypeClassDictionaryConstructorApp (Qualified Nothing _) _) = error "Found unqualified class dictionary constructor"
80+ values :: Expr a -> [Key]
81+ values (Var _ (Qualified (Just mn) ident)) = [(mn, ident)]
8882 values _ = []
8983
90−isUsed :: ModuleName -> Graph -> (Key -> Maybe Vertex) -> [Vertex] -> Declaration -> Bool
91−isUsed moduleName graph vertexFor entryPointVertices (ValueDeclaration name _ _ _) =
92− let Just v' = vertexFor (moduleName, Left name)
93− in any (\v -> path graph v v') entryPointVertices
94−isUsed moduleName graph vertexFor entryPointVertices (FixityDeclaration _ name) =
95− let Just v' = vertexFor (moduleName, Left $ Op name)
96− in any (\v -> path graph v v') entryPointVertices
97−isUsed moduleName graph vertexFor entryPointVertices (DataDeclaration _ _ _ dctors) =
98− any (\(pn, _) -> let Just v' = vertexFor (moduleName, Right pn)
99− in any (\v -> path graph v v') entryPointVertices) dctors
100−isUsed moduleName graph vertexFor entryPointVertices (ExternDeclaration _ name _ _) =
101− let Just v' = vertexFor (moduleName, Left name)
102− in any (\v -> path graph v v') entryPointVertices
103−isUsed moduleName graph vertexFor entryPointVertices (BindingGroupDeclaration ds) =
104− any (\(name, _, _) -> let Just v' = vertexFor (moduleName, Left name)
105− in any (\v -> path graph v v') entryPointVertices) ds
106−isUsed moduleName graph vertexFor entryPointVertices (DataBindingGroupDeclaration ds) =
107− any (isUsed moduleName graph vertexFor entryPointVertices) ds
108−isUsed moduleName graph vertexFor entryPointVertices (TypeClassDeclaration name _ _ _) =
109− let Just v' = vertexFor (moduleName, Right name)
84+-- |
85+-- Check whether a binding group is used.
86+--
87+isUsed :: ModuleName -> Graph -> (Key -> Maybe Vertex) -> [Vertex] -> Bind a -> Bool
88+isUsed mn graph vertexFor entryPointVertices (NonRec name _) =
89+ isUsed' mn graph vertexFor entryPointVertices name
90+isUsed mn graph vertexFor entryPointVertices (Rec ds) =
91+ any (isUsed' mn graph vertexFor entryPointVertices . fst) ds
92+
93+-- |
94+-- Check whether a named declaration is used.
95+--
96+isUsed' :: ModuleName -> Graph -> (Key -> Maybe Vertex) -> [Vertex] -> Ident -> Bool
97+isUsed' mn graph vertexFor entryPointVertices name =
98+ let Just v' = vertexFor (mn, name)
11099 in any (\v -> path graph v v') entryPointVertices
111−isUsed moduleName graph vertexFor entryPointVertices (PositionedDeclaration _ d) =
112− isUsed moduleName graph vertexFor entryPointVertices d
113−isUsed _ _ _ _ _ = True
src/Language/PureScript/Environment.hs+20−5
@@ -17,15 +17,15 @@
1717module Language.PureScript.Environment where
1818
1919import Data.Data
20+import Data.Maybe (fromMaybe)
21+import qualified Data.Map as M
2022
21−import Language.PureScript.Names
22−import Language.PureScript.Types
2323import Language.PureScript.Kinds
24+import Language.PureScript.Names
2425import Language.PureScript.TypeClassDictionaries
26+import Language.PureScript.Types
2527import qualified Language.PureScript.Constants as C
2628
27−import qualified Data.Map as M
28−
2929-- |
3030-- The @Environment@ defines all values and types which are currently in scope:
3131--
@@ -53,7 +53,7 @@ data Environment = Environment {
5353 -- |
5454 -- Type classes
5555 --
56− , typeClasses :: M.Map (Qualified ProperName) ([(String, Maybe Kind)], [(Ident, Type)], [(Qualified ProperName, [Type])])
56+ , typeClasses :: M.Map (Qualified ProperName) ([(String, Maybe Kind)], [(Ident, Type)], [Constraint])
5757 } deriving (Show)
5858
5959-- |
@@ -219,3 +219,18 @@ primTypes = M.fromList [ (primName "Function" , (FunKind Star (FunKind Star Star
219219 , (primName "String" , (Star, ExternData))
220220 , (primName "Number" , (Star, ExternData))
221221 , (primName "Boolean" , (Star, ExternData)) ]
222+
223+-- |
224+-- Finds information about data constructors from the current environment.
225+--
226+lookupConstructor :: Environment -> Qualified ProperName -> (DataDeclType, ProperName, Type)
227+lookupConstructor env ctor =
228+ fromMaybe (error "Data constructor not found") $ ctor `M.lookup` dataConstructors env
229+
230+-- |
231+-- Checks whether a data constructor is for a newtype.
232+--
233+isNewtypeConstructor :: Environment -> Qualified ProperName -> Bool
234+isNewtypeConstructor e ctor = case lookupConstructor e ctor of
235+ (Newtype, _, _) -> True
236+ (Data, _, _) -> False
src/Language/PureScript/Names.hs+2−2
@@ -13,7 +13,7 @@
1313--
1414-----------------------------------------------------------------------------
1515
16−{-# LANGUAGE DeriveDataTypeable #-}
16+{-# LANGUAGE DeriveDataTypeable, DeriveFunctor #-}
1717
1818module Language.PureScript.Names where
1919
@@ -71,7 +71,7 @@ instance Show ModuleName where
7171-- |
7272-- A qualified name, i.e. a name with an optional module name
7373--
74−data Qualified a = Qualified (Maybe ModuleName) a deriving (Eq, Ord, Data, Typeable)
74+data Qualified a = Qualified (Maybe ModuleName) a deriving (Eq, Ord, Data, Typeable, Functor)
7575
7676instance (Show a) => Show (Qualified a) where
7777 show (Qualified Nothing a) = show a
src/Language/PureScript/Pretty/JS.hs+9−7
@@ -17,17 +17,19 @@ module Language.PureScript.Pretty.JS (
1717 prettyPrintJS
1818) where
1919
20−import Language.PureScript.Pretty.Common
21−import Language.PureScript.CodeGen.JS (identNeedsEscaping)
22−import Language.PureScript.CodeGen.JS.AST
23−
2420import Data.List
2521import Data.Maybe (fromMaybe)
26−import qualified Control.Arrow as A
27−import Control.Arrow ((<+>))
28−import Control.PatternArrows
22+
2923import Control.Applicative
24+import Control.Arrow ((<+>))
3025import Control.Monad.State
26+import Control.PatternArrows
27+import qualified Control.Arrow as A
28+
29+import Language.PureScript.CodeGen.JS.AST
30+import Language.PureScript.CodeGen.JS.Common
31+import Language.PureScript.Pretty.Common
32+
3133import Numeric
3234
3335literals :: Pattern PrinterState JS String
src/Language/PureScript/Renamer.hs+58−75
@@ -1,4 +1,5 @@
11-----------------------------------------------------------------------------
2+-----------------------------------------------------------------------------
23--
34-- Module : Language.PureScript.Renamer
45-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
@@ -23,8 +24,7 @@ import Data.List (find)
2324import qualified Data.Map as M
2425import qualified Data.Set as S
2526
26−import Language.PureScript.AST
27−import Language.PureScript.Environment
27+import Language.PureScript.CoreFn
2828import Language.PureScript.Names
2929import Language.PureScript.Traversals
3030
@@ -100,25 +100,21 @@ lookupIdent name = do
100100-- |
101101-- Finds idents introduced by declarations.
102102--
103−findDeclIdents :: [Declaration] -> [Ident]
103+findDeclIdents :: [Bind Ann] -> [Ident]
104104findDeclIdents = concatMap go
105105 where
106− go (ValueDeclaration ident _ _ _) = [ident]
107− go (BindingGroupDeclaration ds) = map (\(name, _, _) -> name) ds
108− go (ExternDeclaration _ ident _ _) = [ident]
109− go (TypeClassDeclaration _ _ _ ds) = findDeclIdents ds
110− go (PositionedDeclaration _ d) = go d
111− go _ = []
106+ go (NonRec ident _) = [ident]
107+ go (Rec ds) = map fst ds
112108
113109-- |
114110-- Renames within each declaration in a module.
115111--
116−renameInModules :: [Module] -> [Module]
112+renameInModules :: [Module Ann] -> [Module Ann]
117113renameInModules = map go
118114 where
119− go :: Module -> Module
120− go (Module mn decls exps) = Module mn (renameInDecl' (findDeclIdents decls) `map` decls) exps
121− renameInDecl' :: [Ident] -> Declaration -> Declaration
115+ go :: Module Ann -> Module Ann
116+ go m@(Module _ _ _ _ decls) = m { moduleDecls = renameInDecl' (findDeclIdents decls) `map` decls }
117+ renameInDecl' :: [Ident] -> Bind Ann -> Bind Ann
122118 renameInDecl' scope = runRename scope . renameInDecl True
123119
124120-- |
@@ -128,65 +124,57 @@ renameInModules = map go
128124-- been added), whereas in a Let declarations are renamed if their name shadows
129125-- another in the current scope.
130126--
131−renameInDecl :: Bool -> Declaration -> Rename Declaration
132−renameInDecl isTopLevel (ValueDeclaration name nameKind [] (Right val)) = do
127+renameInDecl :: Bool -> Bind Ann -> Rename (Bind Ann)
128+renameInDecl isTopLevel (NonRec name val) = do
133129 name' <- if isTopLevel then return name else updateScope name
134− ValueDeclaration name' nameKind [] . Right <$> renameInValue val
135−renameInDecl isTopLevel (BindingGroupDeclaration ds) = do
130+ NonRec name' <$> renameInValue val
131+renameInDecl isTopLevel (Rec ds) = do
136132 ds' <- mapM updateNames ds
137− BindingGroupDeclaration <$> mapM updateValues ds'
133+ Rec <$> mapM updateValues ds'
138134 where
139− updateNames :: (Ident, NameKind, Expr) -> Rename (Ident, NameKind, Expr)
140− updateNames (name, nameKind, val) = do
135+ updateNames :: (Ident, Expr Ann) -> Rename (Ident, Expr Ann)
136+ updateNames (name, val) = do
141137 name' <- if isTopLevel then return name else updateScope name
142− return (name', nameKind, val)
143− updateValues :: (Ident, NameKind, Expr) -> Rename (Ident, NameKind, Expr)
144− updateValues (name, nameKind, val) =
145− (,,) name nameKind <$> renameInValue val
146−renameInDecl _ (TypeInstanceDeclaration name cs className args ds) =
147− TypeInstanceDeclaration name cs className args <$> mapM (renameInDecl True) ds
148−renameInDecl isTopLevel (PositionedDeclaration pos d) =
149− PositionedDeclaration pos <$> renameInDecl isTopLevel d
150−renameInDecl _ other = return other
138+ return (name', val)
139+ updateValues :: (Ident, Expr Ann) -> Rename (Ident, Expr Ann)
140+ updateValues (name, val) = (,) name <$> renameInValue val
151141
152142-- |
153143-- Renames within a value.
154144--
155−renameInValue :: Expr -> Rename Expr
156−renameInValue (UnaryMinus v) =
157− UnaryMinus <$> renameInValue v
158−renameInValue (ArrayLiteral vs) =
159− ArrayLiteral <$> mapM renameInValue vs
160−renameInValue (ObjectLiteral vs) =
161− ObjectLiteral <$> mapM (\(name, v) -> (,) name <$> renameInValue v) vs
162−renameInValue (Accessor prop v) =
163− Accessor prop <$> renameInValue v
164−renameInValue (ObjectUpdate obj vs) =
165− ObjectUpdate <$> renameInValue obj <*> mapM (\(name, v) -> (,) name <$> renameInValue v) vs
166−renameInValue (Abs (Left name) v) =
167− newScope $ Abs . Left <$> updateScope name <*> renameInValue v
168−renameInValue (App v1 v2) =
169− App <$> renameInValue v1 <*> renameInValue v2
170−renameInValue (Var (Qualified Nothing name)) =
171− Var . Qualified Nothing <$> lookupIdent name
172−renameInValue (IfThenElse v1 v2 v3) =
173− IfThenElse <$> renameInValue v1 <*> renameInValue v2 <*> renameInValue v3
174−renameInValue (Case vs alts) =
175− newScope $ Case <$> mapM renameInValue vs <*> mapM renameInCaseAlternative alts
176−renameInValue (TypedValue check v ty) =
177− TypedValue check <$> renameInValue v <*> pure ty
178−renameInValue (Let ds v) =
179− newScope $ Let <$> mapM (renameInDecl False) ds <*> renameInValue v
180−renameInValue (TypeClassDictionaryConstructorApp name v) =
181− TypeClassDictionaryConstructorApp name <$> renameInValue v
182−renameInValue (PositionedValue pos v) =
183− PositionedValue pos <$> renameInValue v
184−renameInValue v = return v
145+renameInValue :: Expr Ann -> Rename (Expr Ann)
146+renameInValue (Literal ann l) =
147+ Literal ann <$> renameInLiteral renameInValue l
148+renameInValue c@(Constructor{}) = return c
149+renameInValue (Accessor ann prop v) =
150+ Accessor ann prop <$> renameInValue v
151+renameInValue (ObjectUpdate ann obj vs) =
152+ ObjectUpdate ann <$> renameInValue obj <*> mapM (\(name, v) -> (,) name <$> renameInValue v) vs
153+renameInValue e@(Abs (_, _, Just IsTypeClassConstructor) _ _) = return e
154+renameInValue (Abs ann name v) =
155+ newScope $ Abs ann <$> updateScope name <*> renameInValue v
156+renameInValue (App ann v1 v2) =
157+ App ann <$> renameInValue v1 <*> renameInValue v2
158+renameInValue (Var ann (Qualified Nothing name)) =
159+ Var ann . Qualified Nothing <$> lookupIdent name
160+renameInValue v@(Var{}) = return v
161+renameInValue (Case ann vs alts) =
162+ newScope $ Case ann <$> mapM renameInValue vs <*> mapM renameInCaseAlternative alts
163+renameInValue (Let ann ds v) =
164+ newScope $ Let ann <$> mapM (renameInDecl False) ds <*> renameInValue v
165+
166+-- |
167+-- Renames within literals.
168+--
169+renameInLiteral :: (a -> Rename a) -> Literal a -> Rename (Literal a)
170+renameInLiteral rename (ArrayLiteral bs) = ArrayLiteral <$> mapM rename bs
171+renameInLiteral rename (ObjectLiteral bs) = ObjectLiteral <$> mapM (sndM rename) bs
172+renameInLiteral _ l = return l
185173
186174-- |
187175-- Renames within case alternatives.
188176--
189−renameInCaseAlternative :: CaseAlternative -> Rename CaseAlternative
177+renameInCaseAlternative :: CaseAlternative Ann -> Rename (CaseAlternative Ann)
190178renameInCaseAlternative (CaseAlternative bs v) =
191179 CaseAlternative <$> mapM renameInBinder bs
192180 <*> eitherM (mapM (pairM renameInValue renameInValue)) renameInValue v
@@ -194,18 +182,13 @@ renameInCaseAlternative (CaseAlternative bs v) =
194182-- |
195183-- Renames within binders.
196184--
197−renameInBinder :: Binder -> Rename Binder
198−renameInBinder (VarBinder name) =
199− VarBinder <$> updateScope name
200−renameInBinder (ConstructorBinder name bs) =
201− ConstructorBinder name <$> mapM renameInBinder bs
202−renameInBinder (ObjectBinder bs) =
203− ObjectBinder <$> mapM (sndM renameInBinder) bs
204−renameInBinder (ArrayBinder bs) =
205− ArrayBinder <$> mapM renameInBinder bs
206−renameInBinder (ConsBinder b1 b2) =
207− ConsBinder <$> renameInBinder b1 <*> renameInBinder b2
208−renameInBinder (NamedBinder name b) =
209− NamedBinder <$> updateScope name <*> renameInBinder b
210−renameInBinder (PositionedBinder _ b) = renameInBinder b
211−renameInBinder other = return other
185+renameInBinder :: Binder a -> Rename (Binder a)
186+renameInBinder n@(NullBinder{}) = return n
187+renameInBinder (LiteralBinder ann b) =
188+ LiteralBinder ann <$> renameInLiteral renameInBinder b
189+renameInBinder (VarBinder ann name) =
190+ VarBinder ann <$> updateScope name
191+renameInBinder (ConstructorBinder ann tctor dctor bs) =
192+ ConstructorBinder ann tctor dctor <$> mapM renameInBinder bs
193+renameInBinder (NamedBinder ann name b) =
194+ NamedBinder ann <$> updateScope name <*> renameInBinder b
src/Language/PureScript/Sugar/TypeClasses.hs+38−35
@@ -14,9 +14,11 @@
1414--
1515-----------------------------------------------------------------------------
1616
17−module Language.PureScript.Sugar.TypeClasses (
18− desugarTypeClasses
19−) where
17+module Language.PureScript.Sugar.TypeClasses
18+ ( desugarTypeClasses
19+ , typeClassMemberName
20+ , superClassDictionaryNames
21+ ) where
2022
2123import Language.PureScript.AST hiding (isExported)
2224import Language.PureScript.Names
@@ -198,13 +200,12 @@ memberToNameAndType (TypeDeclaration ident ty) = (ident, ty)
198200memberToNameAndType (PositionedDeclaration _ d) = memberToNameAndType d
199201memberToNameAndType _ = error "Invalid declaration in type class definition"
200202
201−typeClassDictionaryDeclaration :: ProperName -> [(String, Maybe Kind)] -> [(Qualified ProperName, [Type])] -> [Declaration] -> Declaration
203+typeClassDictionaryDeclaration :: ProperName -> [(String, Maybe Kind)] -> [Constraint] -> [Declaration] -> Declaration
202204typeClassDictionaryDeclaration name args implies members =
203− let superclassTypes = [ (fieldName, function unit tySynApp)
204− | (index, (superclass, tyArgs)) <- zip [0..] implies
205− , let tySynApp = foldl TypeApp (TypeConstructor superclass) tyArgs
206− , let fieldName = mkSuperclassDictionaryName superclass index
207− ]
205+ let superclassTypes = superClassDictionaryNames implies `zip`
206+ [ function unit (foldl TypeApp (TypeConstructor superclass) tyArgs)
207+ | (superclass, tyArgs) <- implies
208+ ]
208209 members' = map (first runIdent . memberToNameAndType) members
209210 mtys = members' ++ superclassTypes
210211 in TypeSynonymDeclaration name args (TypeApp tyObject $ rowFromList (mtys, REmpty))
@@ -218,13 +219,10 @@ typeClassMemberToDictionaryAccessor mn name args (PositionedDeclaration pos d) =
218219 PositionedDeclaration pos $ typeClassMemberToDictionaryAccessor mn name args d
219220typeClassMemberToDictionaryAccessor _ _ _ _ = error "Invalid declaration in type class definition"
220221
221−mkSuperclassDictionaryName :: Qualified ProperName -> Integer -> String
222−mkSuperclassDictionaryName pn index = C.__superclass_ ++ show pn ++ "_" ++ show index
223−
224222unit :: Type
225223unit = TypeApp tyObject REmpty
226224
227−typeInstanceDictionaryDeclaration :: Ident -> ModuleName -> [(Qualified ProperName, [Type])] -> Qualified ProperName -> [Type] -> [Declaration] -> Desugar Declaration
225+typeInstanceDictionaryDeclaration :: Ident -> ModuleName -> [Constraint] -> Qualified ProperName -> [Type] -> [Declaration] -> Desugar Declaration
228226typeInstanceDictionaryDeclaration name mn deps className tys decls =
229227 rethrow (strMsg ("Error in type class instance " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys) ++ ":") <>) $ do
230228 m <- get
@@ -242,22 +240,23 @@ typeInstanceDictionaryDeclaration name mn deps className tys decls =
242240
243241 -- Replace the type arguments with the appropriate types in the member types
244242 let memberTypes = map (second (replaceAllTypeVars (zip (map fst args) tys))) instanceTys
243+
245244 -- Create values for the type instance members
246− memberNames <- map (first runIdent) <$> mapM (memberToNameAndValue memberTypes) decls
245+ members <- zip (map typeClassMemberName decls) <$> mapM (memberToValue memberTypes) decls
246+
247247 -- Create the type of the dictionary
248248 -- The type is an object type, but depending on type instance dependencies, may be constrained.
249249 -- The dictionary itself is an object literal.
250− let superclasses =
251− [ (fieldName, Abs (Left (Ident C.__unused)) (SuperClassDictionary superclass tyArgs))
252− | (index, (superclass, suTyArgs)) <- zip [0..] implies
250+ let superclasses = superClassDictionaryNames implies `zip`
251+ [ Abs (Left (Ident C.__unused)) (SuperClassDictionary superclass tyArgs)
252+ | (superclass, suTyArgs) <- implies
253253 , let tyArgs = map (replaceAllTypeVars (zip (map fst args) tys)) suTyArgs
254− , let fieldName = mkSuperclassDictionaryName superclass index
255254 ]
256255
257− let memberNames' = ObjectLiteral (memberNames ++ superclasses)
256+ let props = ObjectLiteral (members ++ superclasses)
258257 dictTy = foldl TypeApp (TypeConstructor className) tys
259258 constrainedTy = quantify (if null deps then dictTy else ConstrainedType deps dictTy)
260− dict = TypeClassDictionaryConstructorApp className memberNames'
259+ dict = TypeClassDictionaryConstructorApp className props
261260 result = ValueDeclaration name TypeInstanceDictionaryValue [] (Right (TypedValue True dict constrainedTy))
262261 return result
263262
@@ -269,19 +268,23 @@ typeInstanceDictionaryDeclaration name mn deps className tys decls =
269268 declName (TypeDeclaration ident _) = Just ident
270269 declName _ = Nothing
271270
272− memberToNameAndValue :: [(Ident, Type)] -> Declaration -> Desugar (Ident, Expr)
273− memberToNameAndValue tys' d@(ValueDeclaration ident _ _ _) = do
271+ memberToValue :: [(Ident, Type)] -> Declaration -> Desugar Expr
272+ memberToValue tys' (ValueDeclaration ident _ [] (Right val)) = do
274273 _ <- lift . lift . maybe (Left $ mkErrorStack ("Type class does not define member '" ++ show ident ++ "'") Nothing) Right $ lookup ident tys'
275− let memberValue = typeInstanceDictionaryEntryValue d
276− return (ident, memberValue)
277− memberToNameAndValue tys' (PositionedDeclaration pos d) = rethrowWithPosition pos $ do
278− (ident, val) <- memberToNameAndValue tys' d
279− return (ident, PositionedValue pos val)
280− memberToNameAndValue _ _ = error "Invalid declaration in type instance definition"
281−
282− typeInstanceDictionaryEntryValue :: Declaration -> Expr
283− typeInstanceDictionaryEntryValue (ValueDeclaration _ _ [] (Right val)) = val
284− typeInstanceDictionaryEntryValue (PositionedDeclaration pos d) = PositionedValue pos (typeInstanceDictionaryEntryValue d)
285− typeInstanceDictionaryEntryValue _ = error "Invalid declaration in type instance definition"
286−
287−
274+ return val
275+ memberToValue tys' (PositionedDeclaration pos d) = rethrowWithPosition pos $ do
276+ val <- memberToValue tys' d
277+ return (PositionedValue pos val)
278+ memberToValue _ _ = error "Invalid declaration in type instance definition"
279+
280+typeClassMemberName :: Declaration -> String
281+typeClassMemberName (TypeDeclaration ident _) = runIdent ident
282+typeClassMemberName (ValueDeclaration ident _ _ _) = runIdent ident
283+typeClassMemberName (PositionedDeclaration _ d) = typeClassMemberName d
284+typeClassMemberName d = error $ "Invalid declaration in type class definition: " ++ show d
285+
286+superClassDictionaryNames :: [Constraint] -> [String]
287+superClassDictionaryNames supers =
288+ [ C.__superclass_ ++ show pn ++ "_" ++ show (index :: Integer)
289+ | (index, (pn, _)) <- zip [0..] supers
290+ ]
src/Language/PureScript/TypeChecker.hs+12−8
@@ -78,7 +78,7 @@ addValue moduleName name ty nameKind = do
7878 env <- getEnv
7979 putEnv (env { names = M.insert (moduleName, name) (ty, nameKind, Defined) (names env) })
8080
81−addTypeClass :: ModuleName -> ProperName -> [(String, Maybe Kind)] -> [(Qualified ProperName, [Type])] -> [Declaration] -> Check ()
81+addTypeClass :: ModuleName -> ProperName -> [(String, Maybe Kind)] -> [Constraint] -> [Declaration] -> Check ()
8282addTypeClass moduleName pn args implies ds =
8383 let members = map toPair ds in
8484 modify $ \st -> st { checkEnv = (checkEnv st) { typeClasses = M.insert (Qualified (Just moduleName) pn) (args, members, implies) (typeClasses . checkEnv $ st) } }
@@ -235,15 +235,24 @@ typeCheckAll mainModuleName moduleName exps = go
235235 addTypeClass moduleName pn args implies tys
236236 ds <- go rest
237237 return $ d : ds
238− go (TypeInstanceDeclaration dictName deps className tys _ : rest) =
239− go (ExternInstanceDeclaration dictName deps className tys : rest)
238+ go (d@(TypeInstanceDeclaration dictName deps className tys _) : rest) = do
239+ goInstance d dictName deps className tys rest
240240 go (d@(ExternInstanceDeclaration dictName deps className tys) : rest) = do
241+ goInstance d dictName deps className tys rest
242+ go (PositionedDeclaration pos d : rest) =
243+ rethrowWithPosition pos $ do
244+ (d' : rest') <- go (d : rest)
245+ return (PositionedDeclaration pos d' : rest')
246+ goInstance :: Declaration -> Ident -> [Constraint] -> Qualified ProperName -> [Type] -> [Declaration] -> Check [Declaration]
247+ goInstance d dictName deps className tys rest = do
241248 mapM_ (checkTypeClassInstance moduleName) tys
242249 forM_ deps $ mapM_ (checkTypeClassInstance moduleName) . snd
243250 addTypeClassDictionaries [TypeClassDictionaryInScope (Qualified (Just moduleName) dictName) className tys (Just deps) TCDRegular isInstanceExported]
244251 ds <- go rest
245252 return $ d : ds
253+
246254 where
255+
247256 isInstanceExported :: Bool
248257 isInstanceExported = any exportsInstance exps
249258
@@ -252,11 +261,6 @@ typeCheckAll mainModuleName moduleName exps = go
252261 exportsInstance (PositionedDeclarationRef _ r) = exportsInstance r
253262 exportsInstance _ = False
254263
255− go (PositionedDeclaration pos d : rest) =
256− rethrowWithPosition pos $ do
257− (d' : rest') <- go (d : rest)
258− return (PositionedDeclaration pos d' : rest')
259−
260264 -- |
261265 -- This function adds the argument kinds for a type constructor so that they may appear in the externs file,
262266 -- extracted from the kind of the type constructor itself.
src/Language/PureScript/TypeChecker/Entailment.hs+2−2
@@ -64,7 +64,7 @@ data DictionaryValue
6464-- Check that the current set of type class dictionaries entail the specified type class goal, and, if so,
6565-- return a type class dictionary reference.
6666--
67−entails :: Environment -> ModuleName -> [TypeClassDictionaryInScope] -> (Qualified ProperName, [Type]) -> Bool -> Check Expr
67+entails :: Environment -> ModuleName -> [TypeClassDictionaryInScope] -> Constraint -> Bool -> Check Expr
6868entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filter filterModule context))
6969 where
7070 sortedNubBy :: (Ord k) => (v -> k) -> [v] -> [v]
@@ -107,7 +107,7 @@ entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filt
107107 -- Create dictionaries for subgoals which still need to be solved by calling go recursively
108108 -- E.g. the goal (Show a, Show b) => Show (Either a b) can be satisfied if the current type
109109 -- unifies with Either a b, and we can satisfy the subgoals Show a and Show b recursively.
110− solveSubgoals :: [(String, Type)] -> Maybe [(Qualified ProperName, [Type])] -> [Maybe [DictionaryValue]]
110+ solveSubgoals :: [(String, Type)] -> Maybe [Constraint] -> [Maybe [DictionaryValue]]
111111 solveSubgoals _ Nothing = return Nothing
112112 solveSubgoals subst (Just subgoals) = do
113113 dict <- mapM (uncurry (go True) . second (map (replaceAllTypeVars subst))) subgoals
src/Language/PureScript/TypeClassDictionaries.hs+1−1
@@ -41,7 +41,7 @@ data TypeClassDictionaryInScope
4141 -- |
4242 -- Type class dependencies which must be satisfied to construct this dictionary
4343 --
44− , tcdDependencies :: Maybe [(Qualified ProperName, [Type])]
44+ , tcdDependencies :: Maybe [Constraint]
4545 -- |
4646 -- The type of this dictionary
4747 --
src/Language/PureScript/Types.hs+10−5
@@ -69,7 +69,7 @@ data Type
6969 -- |
7070 -- A type with a set of type class constraints
7171 --
72− | ConstrainedType [(Qualified ProperName, [Type])] Type
72+ | ConstrainedType [Constraint] Type
7373 -- |
7474 -- A skolem constant
7575 --
@@ -84,7 +84,7 @@ data Type
8484 | RCons String Type Type
8585 -- |
8686 -- A type with a kind annotation
87− --
87+ --
8888 | KindedType Type Kind
8989 --
9090 -- |
@@ -104,6 +104,11 @@ data Type
104104 --
105105 | PrettyPrintForAll [String] Type deriving (Show, Eq, Data, Typeable)
106106
107+-- |
108+-- A typeclass constraint
109+--
110+type Constraint = (Qualified ProperName, [Type])
111+
107112-- |
108113-- Convert a row to a list of pairs of labels and types
109114--
@@ -144,9 +149,9 @@ replaceTypeVars v r = replaceAllTypeVars [(v, r)]
144149replaceAllTypeVars :: [(String, Type)] -> Type -> Type
145150replaceAllTypeVars = go []
146151 where
147−
152+
148153 go :: [String] -> [(String, Type)] -> Type -> Type
149− go _ m (TypeVar v) =
154+ go _ m (TypeVar v) =
150155 case v `lookup` m of
151156 Just r -> r
152157 Nothing -> TypeVar v
@@ -165,7 +170,7 @@ replaceAllTypeVars = go []
165170 go bs m (RCons name' t r) = RCons name' (go bs m t) (go bs m r)
166171 go bs m (KindedType t k) = KindedType (go bs m t) k
167172 go _ _ ty = ty
168−
173+
169174 genName orig inUse = try 0
170175 where
171176 try :: Integer -> String