git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Multi-let #258
commit503caca1f3b77d67f8d3facf9353ca93cb8a6d39 authorPhil Freeman <paf31@cantab.net> dateSun 23 Mar 2014, 14:22 (13 years ago) parentf8da0b9
32 files changed+646−630
examples/passing/EmptyDataDecls.purs+3−4 examples/passing/Let.purs+31−6 examples/passing/MonadState.purs+2−2 psci/Main.hs−1 psci/Parser.hs+1−2 purescript.cabal+1−3 src/Language/PureScript.hs−1 src/Language/PureScript/CodeGen/Externs.hs+1−1 src/Language/PureScript/CodeGen/JS.hs+1−1 src/Language/PureScript/DeadCodeElimination.hs−1 src/Language/PureScript/Declarations.hs+192−1 src/Language/PureScript/Environment.hs+1−1 src/Language/PureScript/Optimizer/MagicDo.hs+12−7 src/Language/PureScript/Parser.hs−1 src/Language/PureScript/Parser/Declarations.hs+220−3 src/Language/PureScript/Parser/Values.hs−246 src/Language/PureScript/Pretty/Values.hs+2−1 src/Language/PureScript/Scope.hs+1−1 src/Language/PureScript/Sugar.hs+2−7 src/Language/PureScript/Sugar/BindingGroups.hs+14−4 src/Language/PureScript/Sugar/CaseDeclarations.hs+7−2 src/Language/PureScript/Sugar/DoNotation.hs+1−1 src/Language/PureScript/Sugar/Let.hs−34 src/Language/PureScript/Sugar/Names.hs+8−2 src/Language/PureScript/Sugar/Operators.hs−1 src/Language/PureScript/Sugar/TypeClasses.hs−1 src/Language/PureScript/Sugar/TypeDeclarations.hs+8−1 src/Language/PureScript/TypeChecker.hs+1−1 src/Language/PureScript/TypeChecker/Monad.hs+1−1 src/Language/PureScript/TypeChecker/Types.hs+74−38 src/Language/PureScript/TypeClassDictionaries.hs+62 src/Language/PureScript/Values.hs−254
examples/passing/EmptyDataDecls.purs+3−4
@@ -25,7 +25,6 @@ foreign import error
2525 \ throw msg;\
2626 \}" :: forall a. String -> a
2727
28−main = let (Array xs) = cons 1 $ cons 2 $ cons 3 nil
29− in if xs == [1, 2, 3]
30− then Debug.Trace.trace "Done"
31− else error "Failed"
28+main = case cons 1 $ cons 2 $ cons 3 nil of
29+ Array [1, 2, 3] -> Debug.Trace.trace "Done"
30+ _ -> error "Failed"
examples/passing/Let.purs+31−6
@@ -2,25 +2,50 @@ module Main where
22
33import Prelude
44import Control.Monad.Eff
5+import Control.Monad.ST
56
6−test1 x = let y = x + 1 in y
7+test1 x = let
8+ y :: Number
9+ y = x + 1
10+ in y
711
812test2 x y =
913 let x' = x + 1 in
1014 let y' = y + 1 in
1115 x' + y'
1216
13−test3 x = let 1 = x in 2
14−
15−test4 = let f x y z = x + y + z in
17+test3 = let f x y z = x + y + z in
1618 f 1 2 3
1719
18−test5 = let f x [y, z] = x y z in
20+test4 = let f x [y, z] = x y z in
1921 f (+) [1, 2]
2022
23+test5 = let
24+ f x | x > 0 = g (x / 2) + 1
25+ f x = 0
26+ g x = f (x - 1) + 1
27+ in g 10
28+
29+test6 = runPure (runST (do
30+ r <- newSTRef 0
31+ (let
32+ go [] = readSTRef r
33+ go (n : ns) = do
34+ modifySTRef r ((+) n)
35+ go ns
36+ in go [1, 2, 3, 4, 5])
37+ ))
38+
39+test7 = let
40+ f :: forall a. a -> a
41+ f x = x
42+ in if f true then f 1 else f 2
43+
2144main = do
2245 Debug.Trace.print (test1 1)
2346 Debug.Trace.print (test2 1 2)
24− Debug.Trace.print (test3 1)
47+ Debug.Trace.print test3
2548 Debug.Trace.print test4
2649 Debug.Trace.print test5
50+ Debug.Trace.print test6
51+ Debug.Trace.print test7
examples/passing/MonadState.purs+2−2
@@ -14,8 +14,8 @@ runState s (State f) = f s
1414
1515instance monadState :: Prelude.Monad (State s) where
1616 return a = State $ \s -> Tuple s a
17− (>>=) f g = State $ \s -> let (Tuple s1 a) = runState s f in
18− runState s1 (g a)
17+ (>>=) f g = State $ \s -> case runState s f of
18+ Tuple s1 a -> runState s1 (g a)
1919
2020instance monadStateState :: MonadState s (State s) where
2121 get = State (\s -> Tuple s s)
psci/Main.hs−1
@@ -161,7 +161,6 @@ quitMessage = "See ya!"
161161
162162-- |
163163-- Loads module, function, and file completions.
164−-- TODO: filter names to only include exported decls
165164--
166165completion :: CompletionFunc (StateT PSCiState IO)
167166completion = completeWord Nothing " \t\n\r" findCompletions
psci/Parser.hs+1−2
@@ -34,8 +34,7 @@ import qualified Language.PureScript as P
3434-- we actually want the normal @let@.
3535--
3636psciLet :: Parsec String P.ParseState Command
37−psciLet = Let <$> (P.Let <$> (P.reserved "let" *> P.indented *> (Left <$> P.parseBinder))
38− <*> (P.indented *> P.reservedOp "=" *> P.parseValue))
37+psciLet = Let <$> (P.Let <$> (P.reserved "let" *> P.indented *> many1 P.parseDeclaration))
3938
4039-- |
4140-- Parses PSCI metacommands or expressions input from the user.
purescript.cabal+1−3
@@ -33,8 +33,8 @@ library
3333 Language.PureScript.Kinds
3434 Language.PureScript.Names
3535 Language.PureScript.Types
36− Language.PureScript.Values
3736 Language.PureScript.Scope
37+ Language.PureScript.TypeClassDictionaries
3838 Language.PureScript.DeadCodeElimination
3939 Language.PureScript.Sugar
4040 Language.PureScript.ModuleDependencies
@@ -44,7 +44,6 @@ library
4444 Language.PureScript.Sugar.BindingGroups
4545 Language.PureScript.Sugar.Operators
4646 Language.PureScript.Sugar.TypeClasses
47− Language.PureScript.Sugar.Let
4847 Language.PureScript.Sugar.Names
4948 Language.PureScript.CodeGen
5049 Language.PureScript.CodeGen.Common
@@ -65,7 +64,6 @@ library
6564 Language.PureScript.Parser.Kinds
6665 Language.PureScript.Parser.State
6766 Language.PureScript.Parser.Types
68− Language.PureScript.Parser.Values
6967 Language.PureScript.Pretty
7068 Language.PureScript.Pretty.Common
7169 Language.PureScript.Pretty.JS
src/Language/PureScript.hs−1
@@ -15,7 +15,6 @@
1515
1616module Language.PureScript (module P, compile, compile', MonadMake(..), make) where
1717
18−import Language.PureScript.Values as P
1918import Language.PureScript.Types as P
2019import Language.PureScript.Kinds as P
2120import Language.PureScript.Declarations as P
src/Language/PureScript/CodeGen/Externs.hs+1−1
@@ -24,10 +24,10 @@ import qualified Data.Map as M
2424
2525import Control.Monad.Writer
2626
27+import Language.PureScript.TypeClassDictionaries
2728import Language.PureScript.Declarations
2829import Language.PureScript.Pretty
2930import Language.PureScript.Names
30−import Language.PureScript.Values
3131import Language.PureScript.Environment
3232
3333-- |
src/Language/PureScript/CodeGen/JS.hs+1−1
@@ -30,7 +30,6 @@ import Control.Monad (replicateM, forM)
3030
3131import qualified Data.Map as M
3232
33−import Language.PureScript.Values
3433import Language.PureScript.Names
3534import Language.PureScript.Scope
3635import Language.PureScript.Declarations
@@ -134,6 +133,7 @@ valueToJs opts m e (Case values binders) = bindersToJs opts m e binders (map (va
134133valueToJs opts m e (IfThenElse cond th el) = JSConditional (valueToJs opts m e cond) (valueToJs opts m e th) (valueToJs opts m e el)
135134valueToJs opts m e (Accessor prop val) = JSAccessor prop (valueToJs opts m e val)
136135valueToJs opts m e (App val arg) = JSApp (valueToJs opts m e val) [valueToJs opts m e arg]
136+valueToJs opts m e (Let ds val) = JSApp (JSFunction Nothing [] (JSBlock (concat (mapMaybe (flip (declToJs opts m) e) ds) ++ [JSReturn $ valueToJs opts m e val]))) []
137137valueToJs opts m e (Abs (Left arg) val) = JSFunction Nothing [identToJs arg] (JSBlock [JSReturn (valueToJs opts m (bindName m arg e) val)])
138138valueToJs opts m e (TypedValue _ (Abs (Left arg) val) ty) | optionsPerformRuntimeTypeChecks opts = let arg' = identToJs arg in JSFunction Nothing [arg'] (JSBlock $ runtimeTypeChecks arg' ty ++ [JSReturn (valueToJs opts m e val)])
139139valueToJs _ m _ (Var ident) = varToJs m ident
src/Language/PureScript/DeadCodeElimination.hs−1
@@ -23,7 +23,6 @@ import Data.Generics
2323import Data.Maybe (mapMaybe)
2424
2525import Language.PureScript.Names
26−import Language.PureScript.Values
2726import Language.PureScript.Declarations
2827
2928-- |
src/Language/PureScript/Declarations.hs+192−1
@@ -16,14 +16,15 @@
1616
1717module Language.PureScript.Declarations where
1818
19−import Language.PureScript.Values
2019import Language.PureScript.Types
2120import Language.PureScript.Names
2221import Language.PureScript.Kinds
22+import Language.PureScript.TypeClassDictionaries
2323import Language.PureScript.CodeGen.JS.AST
2424import Language.PureScript.Environment
2525
2626import qualified Data.Data as D
27+import Data.Generics (mkQ, everything)
2728
2829-- |
2930-- A precedence level for an infix operator
@@ -189,3 +190,193 @@ isTypeClassDeclaration :: Declaration -> Bool
189190isTypeClassDeclaration TypeClassDeclaration{} = True
190191isTypeClassDeclaration TypeInstanceDeclaration{} = True
191192isTypeClassDeclaration _ = False
193+
194+-- |
195+-- A guard is just a boolean-valued expression that appears alongside a set of binders
196+--
197+type Guard = Value
198+
199+-- |
200+-- Data type for values
201+--
202+data Value
203+ -- |
204+ -- A numeric literal
205+ --
206+ = NumericLiteral (Either Integer Double)
207+ -- |
208+ -- A string literal
209+ --
210+ | StringLiteral String
211+ -- |
212+ -- A boolean literal
213+ --
214+ | BooleanLiteral Bool
215+ -- |
216+ -- Binary operator application. During the rebracketing phase of desugaring, this data constructor
217+ -- will be removed.
218+ --
219+ | BinaryNoParens (Qualified Ident) Value Value
220+ -- |
221+ -- Explicit parentheses. During the rebracketing phase of desugaring, this data constructor
222+ -- will be removed.
223+ --
224+ | Parens Value
225+ -- |
226+ -- An array literal
227+ --
228+ | ArrayLiteral [Value]
229+ -- |
230+ -- An object literal
231+ --
232+ | ObjectLiteral [(String, Value)]
233+ -- |
234+ -- An record property accessor expression
235+ --
236+ | Accessor String Value
237+ -- |
238+ -- Partial record update
239+ --
240+ | ObjectUpdate Value [(String, Value)]
241+ -- |
242+ -- Function introduction
243+ --
244+ | Abs (Either Ident Binder) Value
245+ -- |
246+ -- Function application
247+ --
248+ | App Value Value
249+ -- |
250+ -- Variable
251+ --
252+ | Var (Qualified Ident)
253+ -- |
254+ -- Conditional (if-then-else expression)
255+ --
256+ | IfThenElse Value Value Value
257+ -- |
258+ -- A data constructor
259+ --
260+ | Constructor (Qualified ProperName)
261+ -- |
262+ -- A case expression. During the case expansion phase of desugaring, top-level binders will get
263+ -- desugared into case expressions, hence the need for guards and multiple binders per branch here.
264+ --
265+ | Case [Value] [CaseAlternative]
266+ -- |
267+ -- A value with a type annotation
268+ --
269+ | TypedValue Bool Value Type
270+ -- |
271+ -- A let binding
272+ --
273+ | Let [Declaration] Value
274+ -- |
275+ -- A do-notation block
276+ --
277+ | Do [DoNotationElement]
278+ -- |
279+ -- A placeholder for a type class dictionary to be inserted later. At the end of type checking, these
280+ -- placeholders will be replaced with actual expressions representing type classes dictionaries which
281+ -- can be evaluated at runtime. The constructor arguments represent (in order): the type class name and
282+ -- instance type, and the type class dictionaries in scope.
283+ --
284+ | TypeClassDictionary (Qualified ProperName, [Type]) [TypeClassDictionaryInScope] deriving (Show, D.Data, D.Typeable)
285+
286+-- |
287+-- An alternative in a case statement
288+--
289+data CaseAlternative = CaseAlternative
290+ { -- |
291+ -- A collection of binders with which to match the inputs
292+ --
293+ caseAlternativeBinders :: [Binder]
294+ -- |
295+ -- An optional guard
296+ --
297+ , caseAlternativeGuard :: Maybe Guard
298+ -- |
299+ -- The result expression
300+ --
301+ , caseAlternativeResult :: Value
302+ } deriving (Show, D.Data, D.Typeable)
303+
304+-- |
305+-- Find the original dictionary which a type class dictionary in scope refers to
306+--
307+canonicalizeDictionary :: TypeClassDictionaryInScope -> Qualified Ident
308+canonicalizeDictionary (TypeClassDictionaryInScope { tcdType = TCDRegular, tcdName = nm }) = nm
309+canonicalizeDictionary (TypeClassDictionaryInScope { tcdType = TCDAlias nm }) = nm
310+
311+-- |
312+-- A statement in a do-notation block
313+--
314+data DoNotationElement
315+ -- |
316+ -- A monadic value without a binder
317+ --
318+ = DoNotationValue Value
319+ -- |
320+ -- A monadic value with a binder
321+ --
322+ | DoNotationBind Binder Value
323+ -- |
324+ -- A let statement, i.e. a pure value with a binder
325+ --
326+ | DoNotationLet Binder Value deriving (Show, D.Data, D.Typeable)
327+
328+-- |
329+-- Data type for binders
330+--
331+data Binder
332+ -- |
333+ -- Wildcard binder
334+ --
335+ = NullBinder
336+ -- |
337+ -- A binder which matches a boolean literal
338+ --
339+ | BooleanBinder Bool
340+ -- |
341+ -- A binder which matches a string literal
342+ --
343+ | StringBinder String
344+ -- |
345+ -- A binder which matches a numeric literal
346+ --
347+ | NumberBinder (Either Integer Double)
348+ -- |
349+ -- A binder which binds an identifier
350+ --
351+ | VarBinder Ident
352+ -- |
353+ -- A binder which matches a data constructor
354+ --
355+ | ConstructorBinder (Qualified ProperName) [Binder]
356+ -- |
357+ -- A binder which matches a record and binds its properties
358+ --
359+ | ObjectBinder [(String, Binder)]
360+ -- |
361+ -- A binder which matches an array and binds its elements
362+ --
363+ | ArrayBinder [Binder]
364+ -- |
365+ -- A binder which matches an array and binds its head and tail
366+ --
367+ | ConsBinder Binder Binder
368+ -- |
369+ -- A binder which binds its input to an identifier
370+ --
371+ | NamedBinder Ident Binder deriving (Show, D.Data, D.Typeable)
372+
373+
374+-- |
375+-- Collect all names introduced in binders in an expression
376+--
377+binderNames :: (D.Data d) => d -> [Ident]
378+binderNames = everything (++) (mkQ [] go)
379+ where
380+ go (VarBinder ident) = [ident]
381+ go (NamedBinder ident _) = [ident]
382+ go _ = []
src/Language/PureScript/Environment.hs+1−1
@@ -21,7 +21,7 @@ import Data.Data
2121import Language.PureScript.Names
2222import Language.PureScript.Types
2323import Language.PureScript.Kinds
24−import Language.PureScript.Values
24+import Language.PureScript.TypeClassDictionaries
2525import qualified Language.PureScript.Constants as C
2626
2727import qualified Data.Map as M
src/Language/PureScript/Optimizer/MagicDo.hs+12−7
@@ -58,12 +58,14 @@ magicDo' = everywhere (mkT undo) . everywhere' (mkT convert)
5858 convert :: JS -> JS
5959 -- Desugar return
6060 convert (JSApp (JSApp ret [val]) []) | isReturn ret = val
61− -- Desugae >>
62− convert (JSApp (JSApp bind [m]) [JSFunction Nothing ["_"] (JSBlock [JSReturn ret])]) | isBind bind =
63− JSFunction (Just fnName) [] $ JSBlock [ JSApp m [], JSReturn (JSApp ret []) ]
61+ -- Desugar >>
62+ convert (JSApp (JSApp bind [m]) [JSFunction Nothing ["_"] (JSBlock js)]) | isBind bind && isJSReturn (last js) =
63+ let JSReturn ret = last js in
64+ JSFunction (Just fnName) [] $ JSBlock (JSApp m [] : init js ++ [JSReturn (JSApp ret [])] )
6465 -- Desugar >>=
65− convert (JSApp (JSApp bind [m]) [JSFunction Nothing [arg] (JSBlock [JSReturn ret])]) | isBind bind =
66− JSFunction (Just fnName) [] $ JSBlock [ JSVariableIntroduction arg (Just (JSApp m [])), JSReturn (JSApp ret []) ]
66+ convert (JSApp (JSApp bind [m]) [JSFunction Nothing [arg] (JSBlock js)]) | isBind bind && isJSReturn (last js) =
67+ let JSReturn ret = last js in
68+ JSFunction (Just fnName) [] $ JSBlock (JSVariableIntroduction arg (Just (JSApp m [])) : init js ++ [JSReturn (JSApp ret [])] )
6769 -- Desugar untilE
6870 convert (JSApp (JSApp f [arg]) []) | isEffFunc C.untilE f =
6971 JSApp (JSFunction Nothing [] (JSBlock [ JSWhile (JSUnary Not (JSApp arg [])) (JSBlock []), JSReturn (JSObjectLiteral []) ])) []
@@ -109,6 +111,9 @@ magicDo' = everywhere (mkT undo) . everywhere' (mkT convert)
109111 undo (JSReturn (JSApp (JSFunction (Just ident) [] body) [])) | ident == fnName = body
110112 undo other = other
111113
114+ isJSReturn (JSReturn _) = True
115+ isJSReturn _ = False
116+
112117-- |
113118-- Inline functions in the ST module
114119--
@@ -128,8 +133,8 @@ inlineST = everywhere (mkT convertBlock)
128133 -- Convert a block in a safe way, preserving object wrappers of references,
129134 -- or in a more aggressive way, turning wrappers into local variables depending on the
130135 -- agg(ressive) parameter.
131− convert agg (JSApp (JSApp f [arg]) []) | isSTFunc C.newSTRef f =
132− if agg then arg else JSObjectLiteral [(C.stRefValue, arg)]
136+ convert agg (JSApp f [arg]) | isSTFunc C.newSTRef f =
137+ JSFunction Nothing [] (JSBlock [JSReturn $ if agg then arg else JSObjectLiteral [(C.stRefValue, arg)]])
133138 convert agg (JSApp (JSApp f [ref]) []) | isSTFunc C.readSTRef f =
134139 if agg then ref else JSAccessor C.stRefValue ref
135140 convert agg (JSApp (JSApp (JSApp f [ref]) [arg]) []) | isSTFunc C.writeSTRef f =
src/Language/PureScript/Parser.hs−1
@@ -29,7 +29,6 @@ module Language.PureScript.Parser (module P) where
2929
3030import Language.PureScript.Parser.Common as P
3131import Language.PureScript.Parser.Types as P
32−import Language.PureScript.Parser.Values as P
3332import Language.PureScript.Parser.State as P
3433import Language.PureScript.Parser.Kinds as P
3534import Language.PureScript.Parser.Declarations as P
src/Language/PureScript/Parser/Declarations.hs+220−3
@@ -16,22 +16,29 @@
1616module Language.PureScript.Parser.Declarations (
1717 parseDeclaration,
1818 parseModule,
19− parseModules
19+ parseModules,
20+ parseValue,
21+ parseGuard,
22+ parseBinder,
23+ parseBinderNoParens,
2024) where
2125
2226import Data.Maybe (isJust, fromMaybe)
2327import Control.Applicative
24−import qualified Text.Parsec as P
2528
2629import Language.PureScript.Parser.State
2730import Language.PureScript.Parser.Common
2831import Language.PureScript.Declarations
29−import Language.PureScript.Parser.Values
3032import Language.PureScript.Parser.Types
3133import Language.PureScript.Parser.Kinds
3234import Language.PureScript.CodeGen.JS.AST
3335import Language.PureScript.Environment
3436
37+import Text.Parsec.Expr
38+
39+import qualified Language.PureScript.Parser.Common as C
40+import qualified Text.Parsec as P
41+
3542parseDataDeclaration :: P.Parsec String ParseState Declaration
3643parseDataDeclaration = do
3744 reserved "data"
@@ -179,3 +186,213 @@ parseModule = do
179186--
180187parseModules :: P.Parsec String ParseState [Module]
181188parseModules = whiteSpace *> mark (P.many (same *> parseModule)) <* P.eof
189+
190+booleanLiteral :: P.Parsec String ParseState Bool
191+booleanLiteral = (C.reserved "true" >> return True) P.<|> (C.reserved "false" >> return False)
192+
193+parseNumericLiteral :: P.Parsec String ParseState Value
194+parseNumericLiteral = NumericLiteral <$> C.integerOrFloat
195+
196+parseStringLiteral :: P.Parsec String ParseState Value
197+parseStringLiteral = StringLiteral <$> C.stringLiteral
198+
199+parseBooleanLiteral :: P.Parsec String ParseState Value
200+parseBooleanLiteral = BooleanLiteral <$> booleanLiteral
201+
202+parseArrayLiteral :: P.Parsec String ParseState Value
203+parseArrayLiteral = ArrayLiteral <$> C.squares (C.commaSep parseValue)
204+
205+parseObjectLiteral :: P.Parsec String ParseState Value
206+parseObjectLiteral = ObjectLiteral <$> C.braces (C.commaSep parseIdentifierAndValue)
207+
208+parseIdentifierAndValue :: P.Parsec String ParseState (String, Value)
209+parseIdentifierAndValue = (,) <$> (C.indented *> C.identifier <* C.indented <* C.colon)
210+ <*> (C.indented *> parseValue)
211+
212+parseAbs :: P.Parsec String ParseState Value
213+parseAbs = do
214+ C.reservedOp "\\"
215+ args <- P.many1 (C.indented *> (Abs <$> (Left <$> P.try C.parseIdent <|> Right <$> parseBinderNoParens)))
216+ C.indented *> C.reservedOp "->"
217+ value <- parseValue
218+ return $ toFunction args value
219+ where
220+ toFunction :: [Value -> Value] -> Value -> Value
221+ toFunction args value = foldr ($) value args
222+
223+parseVar :: P.Parsec String ParseState Value
224+parseVar = Var <$> C.parseQualified C.parseIdent
225+
226+parseConstructor :: P.Parsec String ParseState Value
227+parseConstructor = Constructor <$> C.parseQualified C.properName
228+
229+parseCase :: P.Parsec String ParseState Value
230+parseCase = Case <$> P.between (P.try (C.reserved "case")) (C.indented *> C.reserved "of") (return <$> parseValue)
231+ <*> (C.indented *> C.mark (P.many (C.same *> C.mark parseCaseAlternative)))
232+
233+parseCaseAlternative :: P.Parsec String ParseState CaseAlternative
234+parseCaseAlternative = CaseAlternative <$> (return <$> parseBinder)
235+ <*> P.optionMaybe parseGuard
236+ <*> (C.indented *> C.reservedOp "->" *> parseValue)
237+ P.<?> "case alternative"
238+
239+parseIfThenElse :: P.Parsec String ParseState Value
240+parseIfThenElse = IfThenElse <$> (P.try (C.reserved "if") *> C.indented *> parseValue)
241+ <*> (C.indented *> C.reserved "then" *> C.indented *> parseValue)
242+ <*> (C.indented *> C.reserved "else" *> C.indented *> parseValue)
243+
244+parseLet :: P.Parsec String ParseState Value
245+parseLet = do
246+ C.reserved "let"
247+ C.indented
248+ ds <- C.mark $ P.many1 (C.same *> parseDeclaration)
249+ C.indented
250+ C.reserved "in"
251+ result <- parseValue
252+ return $ Let ds result
253+
254+parseValueAtom :: P.Parsec String ParseState Value
255+parseValueAtom = P.choice
256+ [ P.try parseNumericLiteral
257+ , P.try parseStringLiteral
258+ , P.try parseBooleanLiteral
259+ , parseArrayLiteral
260+ , P.try parseObjectLiteral
261+ , parseAbs
262+ , P.try parseConstructor
263+ , P.try parseVar
264+ , parseCase
265+ , parseIfThenElse
266+ , parseDo
267+ , parseLet
268+ , Parens <$> C.parens parseValue ]
269+
270+parsePropertyUpdate :: P.Parsec String ParseState (String, Value)
271+parsePropertyUpdate = do
272+ name <- C.lexeme C.identifier
273+ _ <- C.lexeme $ C.indented *> P.char '='
274+ value <- C.indented *> parseValue
275+ return (name, value)
276+
277+parseAccessor :: Value -> P.Parsec String ParseState Value
278+parseAccessor (Constructor _) = P.unexpected "constructor"
279+parseAccessor obj = P.try $ Accessor <$> (C.indented *> C.dot *> P.notFollowedBy C.opLetter *> C.indented *> C.identifier) <*> pure obj
280+
281+parseDo :: P.Parsec String ParseState Value
282+parseDo = do
283+ C.reserved "do"
284+ C.indented
285+ Do <$> C.mark (P.many (C.same *> C.mark parseDoNotationElement))
286+
287+parseDoNotationLet :: P.Parsec String ParseState DoNotationElement
288+parseDoNotationLet = DoNotationLet <$> (C.reserved "let" *> C.indented *> parseBinder)
289+ <*> (C.indented *> C.reservedOp "=" *> parseValue)
290+
291+parseDoNotationBind :: P.Parsec String ParseState DoNotationElement
292+parseDoNotationBind = DoNotationBind <$> parseBinder <*> (C.indented *> C.reservedOp "<-" *> parseValue)
293+
294+parseDoNotationElement :: P.Parsec String ParseState DoNotationElement
295+parseDoNotationElement = P.choice
296+ [ P.try parseDoNotationBind
297+ , parseDoNotationLet
298+ , P.try (DoNotationValue <$> parseValue) ]
299+
300+-- |
301+-- Parse a value
302+--
303+parseValue :: P.Parsec String ParseState Value
304+parseValue =
305+ (buildExpressionParser operators
306+ . C.buildPostfixParser postfixTable2
307+ $ indexersAndAccessors) P.<?> "expression"
308+ where
309+ indexersAndAccessors = C.buildPostfixParser postfixTable1 parseValueAtom
310+ postfixTable1 = [ parseAccessor
311+ , \v -> P.try $ flip ObjectUpdate <$> (C.indented *> C.braces (C.commaSep1 (C.indented *> parsePropertyUpdate))) <*> pure v ]
312+ postfixTable2 = [ \v -> P.try (flip App <$> (C.indented *> indexersAndAccessors)) <*> pure v
313+ , \v -> flip (TypedValue True) <$> (P.try (C.lexeme (C.indented *> P.string "::")) *> parsePolyType) <*> pure v
314+ ]
315+ operators = [ [ Infix (C.lexeme (P.try (C.indented *> C.parseIdentInfix P.<?> "operator") >>= \ident ->
316+ return (BinaryNoParens ident))) AssocRight ]
317+ ]
318+
319+parseStringBinder :: P.Parsec String ParseState Binder
320+parseStringBinder = StringBinder <$> C.stringLiteral
321+
322+parseBooleanBinder :: P.Parsec String ParseState Binder
323+parseBooleanBinder = BooleanBinder <$> booleanLiteral
324+
325+parseNumberBinder :: P.Parsec String ParseState Binder
326+parseNumberBinder = NumberBinder <$> C.integerOrFloat
327+
328+parseVarBinder :: P.Parsec String ParseState Binder
329+parseVarBinder = VarBinder <$> C.parseIdent
330+
331+parseNullaryConstructorBinder :: P.Parsec String ParseState Binder
332+parseNullaryConstructorBinder = ConstructorBinder <$> C.lexeme (C.parseQualified C.properName) <*> pure []
333+
334+parseConstructorBinder :: P.Parsec String ParseState Binder
335+parseConstructorBinder = ConstructorBinder <$> C.lexeme (C.parseQualified C.properName) <*> many (C.indented *> parseBinderNoParens)
336+
337+parseObjectBinder :: P.Parsec String ParseState Binder
338+parseObjectBinder = ObjectBinder <$> C.braces (C.commaSep (C.indented *> parseIdentifierAndBinder))
339+
340+parseArrayBinder :: P.Parsec String ParseState Binder
341+parseArrayBinder = C.squares $ ArrayBinder <$> C.commaSep (C.indented *> parseBinder)
342+
343+parseNamedBinder :: P.Parsec String ParseState Binder
344+parseNamedBinder = NamedBinder <$> (C.parseIdent <* C.indented <* C.lexeme (P.char '@'))
345+ <*> (C.indented *> parseBinder)
346+
347+parseNullBinder :: P.Parsec String ParseState Binder
348+parseNullBinder = C.lexeme (P.char '_') *> P.notFollowedBy C.identLetter *> return NullBinder
349+
350+parseIdentifierAndBinder :: P.Parsec String ParseState (String, Binder)
351+parseIdentifierAndBinder = do
352+ name <- C.lexeme C.identifier
353+ _ <- C.lexeme $ C.indented *> P.char '='
354+ binder <- C.indented *> parseBinder
355+ return (name, binder)
356+
357+-- |
358+-- Parse a binder
359+--
360+parseBinder :: P.Parsec String ParseState Binder
361+parseBinder = buildExpressionParser operators parseBinderAtom P.<?> "expression"
362+ where
363+ operators = [ [ Infix ( C.lexeme (P.try $ C.indented *> C.reservedOp ":") >> return ConsBinder) AssocRight ] ]
364+ parseBinderAtom :: P.Parsec String ParseState Binder
365+ parseBinderAtom = P.choice (map P.try
366+ [ parseNullBinder
367+ , parseStringBinder
368+ , parseBooleanBinder
369+ , parseNumberBinder
370+ , parseNamedBinder
371+ , parseVarBinder
372+ , parseConstructorBinder
373+ , parseObjectBinder
374+ , parseArrayBinder
375+ , C.parens parseBinder ]) P.<?> "binder"
376+
377+-- |
378+-- Parse a binder as it would appear in a top level declaration
379+--
380+parseBinderNoParens :: P.Parsec String ParseState Binder
381+parseBinderNoParens = P.choice (map P.try
382+ [ parseNullBinder
383+ , parseStringBinder
384+ , parseBooleanBinder
385+ , parseNumberBinder
386+ , parseNamedBinder
387+ , parseVarBinder
388+ , parseNullaryConstructorBinder
389+ , parseObjectBinder
390+ , parseArrayBinder
391+ , C.parens parseBinder ]) P.<?> "binder"
392+-- |
393+-- Parse a guard
394+--
395+parseGuard :: P.Parsec String ParseState Guard
396+parseGuard = C.indented *> C.pipe *> C.indented *> parseValue
397+
398+
src/Language/PureScript/Parser/Values.hsdeleted−246
@@ -1,246 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Parser.Values
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Parsers for values, statements, binders and guards
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Parser.Values (
17− parseValue,
18− parseGuard,
19− parseBinder,
20− parseBinderNoParens,
21−) where
22−
23−import Control.Applicative
24−
25−import Language.PureScript.Values
26−import Language.PureScript.Parser.State
27−import Language.PureScript.Parser.Types
28−
29−import Text.Parsec.Expr
30−
31−import qualified Language.PureScript.Parser.Common as C
32−import qualified Text.Parsec as P
33−
34−booleanLiteral :: P.Parsec String ParseState Bool
35−booleanLiteral = (C.reserved "true" >> return True) P.<|> (C.reserved "false" >> return False)
36−
37−parseNumericLiteral :: P.Parsec String ParseState Value
38−parseNumericLiteral = NumericLiteral <$> C.integerOrFloat
39−
40−parseStringLiteral :: P.Parsec String ParseState Value
41−parseStringLiteral = StringLiteral <$> C.stringLiteral
42−
43−parseBooleanLiteral :: P.Parsec String ParseState Value
44−parseBooleanLiteral = BooleanLiteral <$> booleanLiteral
45−
46−parseArrayLiteral :: P.Parsec String ParseState Value
47−parseArrayLiteral = ArrayLiteral <$> C.squares (C.commaSep parseValue)
48−
49−parseObjectLiteral :: P.Parsec String ParseState Value
50−parseObjectLiteral = ObjectLiteral <$> C.braces (C.commaSep parseIdentifierAndValue)
51−
52−parseIdentifierAndValue :: P.Parsec String ParseState (String, Value)
53−parseIdentifierAndValue = (,) <$> (C.indented *> C.identifier <* C.indented <* C.colon)
54− <*> (C.indented *> parseValue)
55−
56−parseAbs :: P.Parsec String ParseState Value
57−parseAbs = do
58− C.reservedOp "\\"
59− args <- P.many1 (C.indented *> (Abs <$> (Left <$> P.try C.parseIdent <|> Right <$> parseBinderNoParens)))
60− C.indented *> C.reservedOp "->"
61− value <- parseValue
62− return $ toFunction args value
63− where
64− toFunction :: [Value -> Value] -> Value -> Value
65− toFunction args value = foldr ($) value args
66−
67−parseVar :: P.Parsec String ParseState Value
68−parseVar = Var <$> C.parseQualified C.parseIdent
69−
70−parseConstructor :: P.Parsec String ParseState Value
71−parseConstructor = Constructor <$> C.parseQualified C.properName
72−
73−parseCase :: P.Parsec String ParseState Value
74−parseCase = Case <$> P.between (P.try (C.reserved "case")) (C.indented *> C.reserved "of") (return <$> parseValue)
75− <*> (C.indented *> C.mark (P.many (C.same *> C.mark parseCaseAlternative)))
76−
77−parseCaseAlternative :: P.Parsec String ParseState CaseAlternative
78−parseCaseAlternative = CaseAlternative <$> (return <$> parseBinder)
79− <*> P.optionMaybe parseGuard
80− <*> (C.indented *> C.reservedOp "->" *> parseValue)
81− P.<?> "case alternative"
82−
83−parseIfThenElse :: P.Parsec String ParseState Value
84−parseIfThenElse = IfThenElse <$> (P.try (C.reserved "if") *> C.indented *> parseValue)
85− <*> (C.indented *> C.reserved "then" *> C.indented *> parseValue)
86− <*> (C.indented *> C.reserved "else" *> C.indented *> parseValue)
87−
88−parseLet :: P.Parsec String ParseState Value
89−parseLet = do
90− C.reserved "let"
91− C.indented
92− binder <- P.try (Right <$> ((,) <$> C.parseIdent <*> P.many (Left <$> P.try C.parseIdent <|> Right <$> parseBinderNoParens)))
93− <|> (Left <$> parseBinder)
94− C.indented
95− C.reservedOp "="
96− C.indented
97− value <- parseValue
98− C.indented
99− C.reserved "in"
100− result <- parseValue
101− return $ Let binder value result
102−
103−parseValueAtom :: P.Parsec String ParseState Value
104−parseValueAtom = P.choice
105− [ P.try parseNumericLiteral
106− , P.try parseStringLiteral
107− , P.try parseBooleanLiteral
108− , parseArrayLiteral
109− , P.try parseObjectLiteral
110− , parseAbs
111− , P.try parseConstructor
112− , P.try parseVar
113− , parseCase
114− , parseIfThenElse
115− , parseDo
116− , parseLet
117− , Parens <$> C.parens parseValue ]
118−
119−parsePropertyUpdate :: P.Parsec String ParseState (String, Value)
120−parsePropertyUpdate = do
121− name <- C.lexeme C.identifier
122− _ <- C.lexeme $ C.indented *> P.char '='
123− value <- C.indented *> parseValue
124− return (name, value)
125−
126−parseAccessor :: Value -> P.Parsec String ParseState Value
127−parseAccessor (Constructor _) = P.unexpected "constructor"
128−parseAccessor obj = P.try $ Accessor <$> (C.indented *> C.dot *> P.notFollowedBy C.opLetter *> C.indented *> C.identifier) <*> pure obj
129−
130−parseDo :: P.Parsec String ParseState Value
131−parseDo = do
132− C.reserved "do"
133− C.indented
134− Do <$> C.mark (P.many (C.same *> C.mark parseDoNotationElement))
135−
136−parseDoNotationLet :: P.Parsec String ParseState DoNotationElement
137−parseDoNotationLet = DoNotationLet <$> (C.reserved "let" *> C.indented *> parseBinder)
138− <*> (C.indented *> C.reservedOp "=" *> parseValue)
139−
140−parseDoNotationBind :: P.Parsec String ParseState DoNotationElement
141−parseDoNotationBind = DoNotationBind <$> parseBinder <*> (C.indented *> C.reservedOp "<-" *> parseValue)
142−
143−parseDoNotationElement :: P.Parsec String ParseState DoNotationElement
144−parseDoNotationElement = P.choice
145− [ P.try parseDoNotationBind
146− , parseDoNotationLet
147− , P.try (DoNotationValue <$> parseValue) ]
148−
149−-- |
150−-- Parse a value
151−--
152−parseValue :: P.Parsec String ParseState Value
153−parseValue =
154− (buildExpressionParser operators
155− . C.buildPostfixParser postfixTable2
156− $ indexersAndAccessors) P.<?> "expression"
157− where
158− indexersAndAccessors = C.buildPostfixParser postfixTable1 parseValueAtom
159− postfixTable1 = [ parseAccessor
160− , \v -> P.try $ flip ObjectUpdate <$> (C.indented *> C.braces (C.commaSep1 (C.indented *> parsePropertyUpdate))) <*> pure v ]
161− postfixTable2 = [ \v -> P.try (flip App <$> (C.indented *> indexersAndAccessors)) <*> pure v
162− , \v -> flip (TypedValue True) <$> (P.try (C.lexeme (C.indented *> P.string "::")) *> parsePolyType) <*> pure v
163− ]
164− operators = [ [ Infix (C.lexeme (P.try (C.indented *> C.parseIdentInfix P.<?> "operator") >>= \ident ->
165− return (BinaryNoParens ident))) AssocRight ]
166− ]
167−
168−parseStringBinder :: P.Parsec String ParseState Binder
169−parseStringBinder = StringBinder <$> C.stringLiteral
170−
171−parseBooleanBinder :: P.Parsec String ParseState Binder
172−parseBooleanBinder = BooleanBinder <$> booleanLiteral
173−
174−parseNumberBinder :: P.Parsec String ParseState Binder
175−parseNumberBinder = NumberBinder <$> C.integerOrFloat
176−
177−parseVarBinder :: P.Parsec String ParseState Binder
178−parseVarBinder = VarBinder <$> C.parseIdent
179−
180−parseNullaryConstructorBinder :: P.Parsec String ParseState Binder
181−parseNullaryConstructorBinder = ConstructorBinder <$> C.lexeme (C.parseQualified C.properName) <*> pure []
182−
183−parseConstructorBinder :: P.Parsec String ParseState Binder
184−parseConstructorBinder = ConstructorBinder <$> C.lexeme (C.parseQualified C.properName) <*> many (C.indented *> parseBinderNoParens)
185−
186−parseObjectBinder :: P.Parsec String ParseState Binder
187−parseObjectBinder = ObjectBinder <$> C.braces (C.commaSep (C.indented *> parseIdentifierAndBinder))
188−
189−parseArrayBinder :: P.Parsec String ParseState Binder
190−parseArrayBinder = C.squares $ ArrayBinder <$> C.commaSep (C.indented *> parseBinder)
191−
192−parseNamedBinder :: P.Parsec String ParseState Binder
193−parseNamedBinder = NamedBinder <$> (C.parseIdent <* C.indented <* C.lexeme (P.char '@'))
194− <*> (C.indented *> parseBinder)
195−
196−parseNullBinder :: P.Parsec String ParseState Binder
197−parseNullBinder = C.lexeme (P.char '_') *> P.notFollowedBy C.identLetter *> return NullBinder
198−
199−parseIdentifierAndBinder :: P.Parsec String ParseState (String, Binder)
200−parseIdentifierAndBinder = do
201− name <- C.lexeme C.identifier
202− _ <- C.lexeme $ C.indented *> P.char '='
203− binder <- C.indented *> parseBinder
204− return (name, binder)
205−
206−-- |
207−-- Parse a binder
208−--
209−parseBinder :: P.Parsec String ParseState Binder
210−parseBinder = buildExpressionParser operators parseBinderAtom P.<?> "expression"
211− where
212− operators = [ [ Infix ( C.lexeme (P.try $ C.indented *> C.reservedOp ":") >> return ConsBinder) AssocRight ] ]
213− parseBinderAtom :: P.Parsec String ParseState Binder
214− parseBinderAtom = P.choice (map P.try
215− [ parseNullBinder
216− , parseStringBinder
217− , parseBooleanBinder
218− , parseNumberBinder
219− , parseNamedBinder
220− , parseVarBinder
221− , parseConstructorBinder
222− , parseObjectBinder
223− , parseArrayBinder
224− , C.parens parseBinder ]) P.<?> "binder"
225−
226−-- |
227−-- Parse a binder as it would appear in a top level declaration
228−--
229−parseBinderNoParens :: P.Parsec String ParseState Binder
230−parseBinderNoParens = P.choice (map P.try
231− [ parseNullBinder
232− , parseStringBinder
233− , parseBooleanBinder
234− , parseNumberBinder
235− , parseNamedBinder
236− , parseVarBinder
237− , parseNullaryConstructorBinder
238− , parseObjectBinder
239− , parseArrayBinder
240− , C.parens parseBinder ]) P.<?> "binder"
241−-- |
242−-- Parse a guard
243−--
244−parseGuard :: P.Parsec String ParseState Guard
245−parseGuard = C.indented *> C.pipe *> C.indented *> parseValue
246−
src/Language/PureScript/Pretty/Values.hs+2−1
@@ -24,7 +24,7 @@ import Control.Arrow ((<+>))
2424import Control.PatternArrows
2525
2626import Language.PureScript.Types
27−import Language.PureScript.Values
27+import Language.PureScript.Declarations
2828import Language.PureScript.Pretty.Common
2929import Language.PureScript.Pretty.Types
3030
@@ -40,6 +40,7 @@ literals = mkPattern match
4040 match (Constructor name) = Just $ show name
4141 match (Case values binders) = Just $ "case " ++ unwords (map prettyPrintValue values) ++
4242 " of { " ++ intercalate " ; " (map prettyPrintCaseAlternative binders) ++ " }"
43+ match (Let _ val) = Just $ "let ... in " ++ prettyPrintValue val
4344 match (Var ident) = Just $ show ident
4445 match (Do els) = Just $ " do { " ++ intercalate "; " (map prettyPrintDoNotationElement els) ++ " }"
4546 match (TypeClassDictionary _ _) = error "Type class dictionary was not replaced"
src/Language/PureScript/Scope.hs+1−1
@@ -24,7 +24,7 @@ import Data.Data
2424import Data.List ((\\), nub)
2525import Data.Generics (extQ, mkQ, everything)
2626
27−import Language.PureScript.Values
27+import Language.PureScript.Declarations
2828import Language.PureScript.Names
2929import Language.PureScript.CodeGen.JS.AST
3030
src/Language/PureScript/Sugar.hs+2−7
@@ -16,7 +16,6 @@
1616module Language.PureScript.Sugar (desugar, module S) where
1717
1818import Control.Monad
19−import Control.Arrow ((>>>))
2019
2120import Language.PureScript.Declarations
2221
@@ -26,14 +25,11 @@ import Language.PureScript.Sugar.CaseDeclarations as S
2625import Language.PureScript.Sugar.TypeDeclarations as S
2726import Language.PureScript.Sugar.BindingGroups as S
2827import Language.PureScript.Sugar.TypeClasses as S
29−import Language.PureScript.Sugar.Let as S
3028import Language.PureScript.Sugar.Names as S
3129
3230-- |
3331-- The desugaring pipeline proceeds as follows:
3432--
35−-- * Desugar let bindings
36−--
3733-- * Introduce type synonyms for type class dictionaries
3834--
3935-- * Rebracket user-defined binary operators
@@ -50,10 +46,9 @@ import Language.PureScript.Sugar.Names as S
5046--
5147desugar :: [Module] -> Either String [Module]
5248desugar = desugarDo
53− >=> desugarLetBindings
54− >>> desugarCasesModule
49+ >=> desugarCasesModule
50+ >=> desugarTypeDeclarationsModule
5551 >=> desugarImports
5652 >=> rebracket
57− >=> desugarTypeDeclarationsModule
5853 >=> desugarTypeClasses
5954 >=> createBindingGroupsModule
src/Language/PureScript/Sugar/BindingGroups.hs+14−4
@@ -24,13 +24,13 @@ module Language.PureScript.Sugar.BindingGroups (
2424import Data.Data
2525import Data.Graph
2626import Data.Generics
27+import Data.Generics.Extras
2728import Data.List (nub, intersect)
2829import Data.Maybe (mapMaybe)
2930import Control.Applicative ((<$>), (<*>), pure)
3031
3132import Language.PureScript.Declarations
3233import Language.PureScript.Names
33−import Language.PureScript.Values
3434import Language.PureScript.Types
3535import Language.PureScript.Environment
3636
@@ -51,8 +51,8 @@ collapseBindingGroupsModule = map $ \(Module name ds exps) -> Module name (colla
5151--
5252createBindingGroups :: ModuleName -> [Declaration] -> Either String [Declaration]
5353createBindingGroups moduleName ds = do
54− let values = filter isValueDecl ds
55− dataDecls = filter isDataDecl ds
54+ values <- mapM (createBindingGroupsForValue moduleName) $ filter isValueDecl ds
55+ let dataDecls = filter isDataDecl ds
5656 allProperNames = map getProperName dataDecls
5757 dataVerts = map (\d -> (d, getProperName d, usedProperNames moduleName d `intersect` allProperNames)) dataDecls
5858 dataBindingGroupDecls <- mapM toDataBindingGroup $ stronglyConnComp dataVerts
@@ -68,16 +68,26 @@ createBindingGroups moduleName ds = do
6868 filter isExternDecl ds ++
6969 bindingGroupDecls
7070
71+createBindingGroupsForValue :: ModuleName -> Declaration -> Either String Declaration
72+createBindingGroupsForValue moduleName = everywhereM' (mkM go)
73+ where
74+ go (Let ds val) = Let <$> createBindingGroups moduleName ds <*> pure val
75+ go other = return other
76+
7177-- |
7278-- Collapse all binding groups to individual declarations
7379--
7480collapseBindingGroups :: [Declaration] -> [Declaration]
75−collapseBindingGroups = concatMap go
81+collapseBindingGroups = everywhere (mkT collapseBindingGroupsForValue) . concatMap go
7682 where
7783 go (DataBindingGroupDeclaration ds) = ds
7884 go (BindingGroupDeclaration ds) = map (\(ident, nameKind, val) -> ValueDeclaration ident nameKind [] Nothing val) ds
7985 go other = [other]
8086
87+collapseBindingGroupsForValue :: Value -> Value
88+collapseBindingGroupsForValue (Let ds val) = Let (collapseBindingGroups ds) val
89+collapseBindingGroupsForValue other = other
90+
8191usedIdents :: (Data d) => ModuleName -> d -> [Ident]
8292usedIdents moduleName = nub . everything (++) (mkQ [] usedNames)
8393 where
src/Language/PureScript/Sugar/CaseDeclarations.hs+7−2
@@ -20,14 +20,14 @@ module Language.PureScript.Sugar.CaseDeclarations (
2020) where
2121
2222import Data.List (groupBy)
23−import Data.Generics (mkT, everywhere)
23+import Data.Generics (mkM, mkT, everywhere)
24+import Data.Generics.Extras
2425
2526import Control.Applicative
2627import Control.Monad ((<=<), forM, join, unless)
2728import Control.Monad.Error.Class
2829
2930import Language.PureScript.Names
30−import Language.PureScript.Values
3131import Language.PureScript.Declarations
3232import Language.PureScript.Scope
3333import Language.PureScript.Environment
@@ -57,6 +57,11 @@ desugarCases = desugarRest <=< fmap join . mapM toDecls . groupBy inSameGroup
5757 desugarRest :: [Declaration] -> Either String [Declaration]
5858 desugarRest (TypeInstanceDeclaration name constraints className tys ds : rest) =
5959 (:) <$> (TypeInstanceDeclaration name constraints className tys <$> desugarCases ds) <*> desugarRest rest
60+ desugarRest (ValueDeclaration name nameKind bs g val : rest) = do
61+ (:) <$> (ValueDeclaration name nameKind bs g <$> everywhereM' (mkM go) val) <*> desugarRest rest
62+ where
63+ go (Let ds val') = Let <$> desugarCases ds <*> pure val'
64+ go other = return other
6065 desugarRest (d : ds) = (:) d <$> desugarRest ds
6166 desugarRest [] = pure []
6267
src/Language/PureScript/Sugar/DoNotation.hs+1−1
@@ -21,9 +21,9 @@ module Language.PureScript.Sugar.DoNotation (
2121import Data.Data
2222import Data.Generics
2323
24−import Language.PureScript.Values
2524import Language.PureScript.Names
2625import Language.PureScript.Scope
26+import Language.PureScript.Declarations
2727
2828import qualified Language.PureScript.Constants as C
2929
src/Language/PureScript/Sugar/Let.hsdeleted−34
@@ -1,34 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Sugar.Let
4−-- Copyright : (c) Phil Freeman 2014
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module implements the desugaring pass which turns let bindings into function applications.
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Sugar.Let (
17− desugarLetBindings
18−) where
19−
20−import Data.Generics (mkT, everywhere)
21−
22−import Language.PureScript.Values
23−import Language.PureScript.Declarations
24−
25−-- |
26−-- Turn let bindings into function applications
27−--
28−desugarLetBindings :: [Module] -> [Module]
29−desugarLetBindings = everywhere (mkT go)
30− where
31− go (Let (Left (VarBinder ident)) value result) = App (Abs (Left ident) result) value
32− go (Let (Left binder) value result) = Case [value] [CaseAlternative [binder] Nothing result]
33− go (Let (Right (ident, binders)) value result) = App (Abs (Left ident) result) (foldr Abs value binders)
34− go other = other
src/Language/PureScript/Sugar/Names.hs+8−2
@@ -28,7 +28,6 @@ import qualified Data.Map as M
2828import Language.PureScript.Declarations
2929import Language.PureScript.Names
3030import Language.PureScript.Types
31−import Language.PureScript.Values
3231import Language.PureScript.Environment
3332
3433-- |
@@ -177,7 +176,7 @@ elaborateExports exps (Module mn decls _) = Module mn decls (Just $
177176--
178177renameInModule :: ImportEnvironment -> ExportEnvironment -> Module -> Either String Module
179178renameInModule imports exports (Module mn decls exps) =
180− Module mn <$> (mapM updateDecl decls >>= everywhereM (mkM updateType `extM` updateValue `extM` updateBinder `extM` updateVars)) <*> pure exps
179+ Module mn <$> (mapM updateDecl decls >>= (mapM updateVars >=> everywhereM (mkM updateType `extM` updateValue `extM` updateBinder))) <*> pure exps
181180 where
182181 updateDecl (TypeInstanceDeclaration name cs cn ts ds) =
183182 TypeInstanceDeclaration name <$> updateConstraints cs <*> updateClassName cn <*> pure ts <*> pure ds
@@ -190,6 +189,8 @@ renameInModule imports exports (Module mn decls exps) =
190189 ValueDeclaration name nameKind [] Nothing <$> everywhereWithContextM' [] (mkS bindFunctionArgs `extS` bindBinders) val
191190 where
192191 bindFunctionArgs bound (Abs (Left arg) val') = return (arg : bound, Abs (Left arg) val')
192+ bindFunctionArgs bound (Let ds val') = let args = map letBoundVariable ds in
193+ return (args ++ bound, Let ds val')
193194 bindFunctionArgs bound (Var name'@(Qualified Nothing ident)) | ident `notElem` bound =
194195 (,) bound <$> (Var <$> updateValueName name')
195196 bindFunctionArgs bound (Var name'@(Qualified (Just _) _)) =
@@ -201,7 +202,12 @@ renameInModule imports exports (Module mn decls exps) =
201202 bindFunctionArgs bound other = return (bound, other)
202203 bindBinders :: [Ident] -> CaseAlternative -> Either String ([Ident], CaseAlternative)
203204 bindBinders bound c@(CaseAlternative bs _ _) = return (binderNames bs ++ bound, c)
205+
206+ letBoundVariable :: Declaration -> Ident
207+ letBoundVariable (ValueDeclaration ident _ _ _ _) = ident
208+ letBoundVariable _ = error "Invalid argument to letBoundVariable"
204209 updateVars (ValueDeclaration name _ _ _ _) = error $ "Binders should have been desugared in " ++ show name
210+ updateVars (TypeInstanceDeclaration name deps className tys ds) = TypeInstanceDeclaration name deps className tys <$> mapM updateVars ds
205211 updateVars other = return other
206212 updateValue (Constructor name) = Constructor <$> updateDataConstructorName name
207213 updateValue v = return v
src/Language/PureScript/Sugar/Operators.hs−1
@@ -25,7 +25,6 @@ module Language.PureScript.Sugar.Operators (
2525
2626import Language.PureScript.Names
2727import Language.PureScript.Declarations
28−import Language.PureScript.Values
2928
3029import Control.Applicative
3130import Control.Monad.State
src/Language/PureScript/Sugar/TypeClasses.hs−1
@@ -22,7 +22,6 @@ module Language.PureScript.Sugar.TypeClasses (
2222import Language.PureScript.Declarations
2323import Language.PureScript.Names
2424import Language.PureScript.Types
25−import Language.PureScript.Values
2625import Language.PureScript.CodeGen.JS.AST
2726import Language.PureScript.Sugar.CaseDeclarations
2827import Language.PureScript.Environment
src/Language/PureScript/Sugar/TypeDeclarations.hs+8−1
@@ -19,12 +19,14 @@ module Language.PureScript.Sugar.TypeDeclarations (
1919 desugarTypeDeclarationsModule
2020) where
2121
22+import Data.Generics (mkM)
23+import Data.Generics.Extras
24+
2225import Control.Applicative
2326import Control.Monad.Error.Class
2427import Control.Monad (forM)
2528
2629import Language.PureScript.Declarations
27−import Language.PureScript.Values
2830
2931-- |
3032-- Replace all top level type declarations in a module with type annotations
@@ -39,5 +41,10 @@ desugarTypeDeclarations :: [Declaration] -> Either String [Declaration]
3941desugarTypeDeclarations (TypeDeclaration name ty : ValueDeclaration name' nameKind [] Nothing val : rest) | name == name' =
4042 desugarTypeDeclarations (ValueDeclaration name nameKind [] Nothing (TypedValue True val ty) : rest)
4143desugarTypeDeclarations (TypeDeclaration name _ : _) = throwError $ "Orphan type declaration for " ++ show name
44+desugarTypeDeclarations (ValueDeclaration name nameKind bs g val : rest) = do
45+ (:) <$> (ValueDeclaration name nameKind bs g <$> everywhereM' (mkM go) val) <*> desugarTypeDeclarations rest
46+ where
47+ go (Let ds val') = Let <$> desugarTypeDeclarations ds <*> pure val'
48+ go other = return other
4249desugarTypeDeclarations (d:ds) = (:) d <$> desugarTypeDeclarations ds
4350desugarTypeDeclarations [] = return []
src/Language/PureScript/TypeChecker.hs+1−1
@@ -32,9 +32,9 @@ import Control.Monad.Error
3232
3333import Language.PureScript.Types
3434import Language.PureScript.Names
35−import Language.PureScript.Values
3635import Language.PureScript.Kinds
3736import Language.PureScript.Declarations
37+import Language.PureScript.TypeClassDictionaries
3838import Language.PureScript.Environment
3939import Language.PureScript.Pretty.Types
4040
src/Language/PureScript/TypeChecker/Monad.hs+1−1
@@ -20,9 +20,9 @@ module Language.PureScript.TypeChecker.Monad where
2020
2121import Language.PureScript.Types
2222import Language.PureScript.Kinds
23−import Language.PureScript.Values
2423import Language.PureScript.Names
2524import Language.PureScript.Environment
25+import Language.PureScript.TypeClassDictionaries
2626
2727import Data.Maybe
2828
src/Language/PureScript/TypeChecker/Types.hs+74−38
@@ -48,10 +48,11 @@ import Data.Generics
4848 something, everywhere, mkQ)
4949import Data.Generics.Extras
5050
51−import Language.PureScript.Values
51+import Language.PureScript.Declarations
5252import Language.PureScript.Types
5353import Language.PureScript.Kinds
5454import Language.PureScript.Names
55+import Language.PureScript.TypeClassDictionaries
5556import Language.PureScript.TypeChecker.Monad
5657import Language.PureScript.TypeChecker.Kinds
5758import Language.PureScript.TypeChecker.Synonyms
@@ -163,48 +164,15 @@ unifyRows r1 r2 =
163164typesOf :: Maybe ModuleName -> ModuleName -> [(Ident, Value)] -> Check [(Ident, (Value, Type))]
164165typesOf mainModuleName moduleName vals = do
165166 tys <- fmap tidyUp . liftUnify $ do
166− let
167− -- Map each declaration to a name/value pair, with an optional type, if the declaration is typed
168− es = map isTyped vals
169− -- Filter the typed and untyped declarations
170− typed = filter (isJust . snd . snd) es
171− untyped = filter (isNothing . snd . snd) es
172− -- Make a map of names to typed declarations
173− typedDict = map (\(ident, (_, Just (ty, _))) -> (ident, ty)) typed
174− -- Create fresh unification variables for the types of untyped declarations
175− untypedNames <- replicateM (length untyped) fresh
176− let
177− -- Make a map of names to the unification variables of untyped declarations
178− untypedDict = zip (map fst untyped) untypedNames
179− -- Create the dictionary of all name/type pairs, which will be added to the environment during type checking
180− dict = M.fromList (map (\(ident, ty) -> ((moduleName, ident), (ty, LocalVariable))) $ typedDict ++ untypedDict)
181− forM es $ \e@(_, (val, _)) -> do
182− -- If the declaration is a function, it has access to other values in the binding group.
183− -- If not, the generated code might fail at runtime since those values might be undefined.
184− let dict' = if isFunction val then dict else M.empty
185− triple@(_, (_, ty)) <- case e of
186− -- Typed declarations
187− (ident, (val', Just (ty, checkType))) -> do
188− -- Kind check
189− kind <- liftCheck $ kindOf moduleName ty
190− guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
191− -- Check the type with the new names in scope
192− ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
193− val'' <- bindNames dict' $ if checkType
194− then TypedValue True <$> check val' ty' <*> pure ty'
195− else return (TypedValue False val' ty')
196− return (ident, (val'', ty'))
197− -- Untyped declarations
198− (ident, (val', Nothing)) -> do
199− -- Infer the type with the new names in scope
200− TypedValue _ val'' ty <- bindNames dict' $ infer val'
201− ty =?= fromMaybe (error "name not found in dictionary") (lookup ident untypedDict)
202− return (ident, (TypedValue True val'' ty, ty))
167+ (es, dict, untypedDict) <- typeDictionaryForBindingGroup moduleName vals
168+ forM es $ \e -> do
169+ triple@(_, (_, ty)) <- typeForBindingGroupElement moduleName e dict untypedDict
203170 -- If --main is enabled, need to check that `main` has type Eff eff a for some eff, a
204171 when (Just moduleName == mainModuleName && fst e == Ident C.main) $ do
205172 [eff, a] <- replicateM 2 fresh
206173 ty =?= TypeApp (TypeApp (TypeConstructor (Qualified (Just (ModuleName [ProperName "Control", ProperName "Monad", ProperName "Eff"])) (ProperName "Eff"))) eff) a
207174 return triple
175+
208176 forM tys $ \(ident, (val, ty)) -> do
209177 -- Replace type class dictionary placeholders with actual dictionaries
210178 val' <- replaceTypeClassDictionaries moduleName val
@@ -219,6 +187,51 @@ typesOf mainModuleName moduleName vals = do
219187 -- Apply the substitution that was returned from runUnify to both types and (type-annotated) values
220188 tidyUp (ts, sub) = map (\(i, (val, ty)) -> (i, (overTypes (sub $?) val, sub $? ty))) ts
221189
190+typeDictionaryForBindingGroup :: ModuleName -> [(Ident, Value)] -> UnifyT Type Check ([(Ident, (Value, Maybe (Type, Bool)))], M.Map (ModuleName, Ident) (Type, NameKind), [(Ident, Type)])
191+typeDictionaryForBindingGroup moduleName vals = do
192+ let
193+ -- Map each declaration to a name/value pair, with an optional type, if the declaration is typed
194+ es = map isTyped vals
195+ -- Filter the typed and untyped declarations
196+ typed = filter (isJust . snd . snd) es
197+ untyped = filter (isNothing . snd . snd) es
198+ -- Make a map of names to typed declarations
199+ typedDict = map (\(ident, (_, Just (ty, _))) -> (ident, ty)) typed
200+
201+ -- Create fresh unification variables for the types of untyped declarations
202+ untypedNames <- replicateM (length untyped) fresh
203+
204+ let
205+ -- Make a map of names to the unification variables of untyped declarations
206+ untypedDict = zip (map fst untyped) untypedNames
207+ -- Create the dictionary of all name/type pairs, which will be added to the environment during type checking
208+ dict = M.fromList (map (\(ident, ty) -> ((moduleName, ident), (ty, LocalVariable))) $ typedDict ++ untypedDict)
209+ return (es, dict, untypedDict)
210+
211+typeForBindingGroupElement :: ModuleName -> (Ident, (Value, Maybe (Type, Bool))) -> M.Map (ModuleName, Ident) (Type, NameKind) -> [(Ident, Type)] -> UnifyT Type Check (Ident, (Value, Type))
212+typeForBindingGroupElement moduleName e@(_, (val, _)) dict untypedDict = do
213+ -- If the declaration is a function, it has access to other values in the binding group.
214+ -- If not, the generated code might fail at runtime since those values might be undefined.
215+ let dict' = if isFunction val then dict else M.empty
216+ case e of
217+ -- Typed declarations
218+ (ident, (val', Just (ty, checkType))) -> do
219+ -- Kind check
220+ kind <- liftCheck $ kindOf moduleName ty
221+ guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
222+ -- Check the type with the new names in scope
223+ ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
224+ val'' <- bindNames dict' $ if checkType
225+ then TypedValue True <$> check val' ty' <*> pure ty'
226+ else return (TypedValue False val' ty')
227+ return (ident, (val'', ty'))
228+ -- Untyped declarations
229+ (ident, (val', Nothing)) -> do
230+ -- Infer the type with the new names in scope
231+ TypedValue _ val'' ty <- bindNames dict' $ infer val'
232+ ty =?= fromMaybe (error "name not found in dictionary") (lookup ident untypedDict)
233+ return (ident, (TypedValue True val'' ty, ty))
234+
222235-- |
223236-- Check if a value introduces a function
224237--
@@ -547,6 +560,9 @@ infer' (IfThenElse cond th el) = do
547560 v3@(TypedValue _ _ t3) <- infer el
548561 t2 =?= t3
549562 return $ TypedValue True (IfThenElse cond' v2 v3) t2
563+infer' (Let ds val) = do
564+ (ds', val'@(TypedValue _ _ valTy)) <- inferLetBinding [] ds val infer
565+ return $ TypedValue True (Let ds' val') valTy
550566infer' (TypedValue checkType val ty) = do
551567 Just moduleName <- checkCurrentModule <$> get
552568 kind <- liftCheck $ kindOf moduleName ty
@@ -556,6 +572,23 @@ infer' (TypedValue checkType val ty) = do
556572 return $ TypedValue True val' ty'
557573infer' _ = error "Invalid argument to infer"
558574
575+inferLetBinding :: [Declaration] -> [Declaration] -> Value -> (Value -> UnifyT Type Check Value) -> UnifyT Type Check ([Declaration], Value)
576+inferLetBinding seen [] ret j = (,) seen <$> j ret
577+inferLetBinding seen (ValueDeclaration ident nameKind [] Nothing val : rest) ret j = do
578+ valTy <- fresh
579+ Just moduleName <- checkCurrentModule <$> get
580+ TypedValue _ val' valTy' <- bindNames (M.singleton (moduleName, ident) (valTy, nameKind)) $ infer val
581+ valTy =?= valTy'
582+ bindNames (M.singleton (moduleName, ident) (valTy', nameKind)) $ inferLetBinding (seen ++ [ValueDeclaration ident nameKind [] Nothing val']) rest ret j
583+inferLetBinding seen (BindingGroupDeclaration ds : rest) ret j = do
584+ Just moduleName <- checkCurrentModule <$> get
585+ (es, dict, untypedDict) <- typeDictionaryForBindingGroup moduleName (map (\(i, _, v) -> (i, v)) ds)
586+ ds' <- forM es $ \e -> do
587+ (ident, (val', _)) <- typeForBindingGroupElement moduleName e dict untypedDict
588+ return $ (ident, LocalVariable, val')
589+ bindNames dict $ inferLetBinding (seen ++ [BindingGroupDeclaration ds']) rest ret j
590+inferLetBinding _ _ _ _ = error "Invalid argument to fromValueDeclaration"
591+
559592-- |
560593-- Infer the type of a property inside a record with a given type
561594--
@@ -784,6 +817,9 @@ check' (Constructor c) ty = do
784817 repl <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty1
785818 _ <- subsumes Nothing repl ty
786819 return $ TypedValue True (Constructor c) ty
820+check' (Let ds val) ty = do
821+ (ds', val') <- inferLetBinding [] ds val (flip check ty)
822+ return $ TypedValue True (Let ds' val') ty
787823check' val ty = throwError $ prettyPrintValue val ++ " does not have type " ++ prettyPrintType ty
788824
789825-- |
src/Language/PureScript/TypeClassDictionaries.hsnew file+62
@@ -0,0 +1,62 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.TypeClassDictionaries
4+-- Copyright : (c) 2014 Phil Freeman
5+-- License : MIT
6+--
7+-- Maintainer : Phil Freeman <paf31@cantab.net>
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- |
12+--
13+-----------------------------------------------------------------------------
14+
15+{-# LANGUAGE DeriveDataTypeable #-}
16+
17+module Language.PureScript.TypeClassDictionaries where
18+
19+import Data.Data
20+
21+import Language.PureScript.Names
22+import Language.PureScript.Types
23+
24+-- |
25+-- Data representing a type class dictionary which is in scope
26+--
27+data TypeClassDictionaryInScope
28+ = TypeClassDictionaryInScope {
29+ -- |
30+ -- The identifier with which the dictionary can be accessed at runtime
31+ --
32+ tcdName :: Qualified Ident
33+ -- |
34+ -- The name of the type class to which this type class instance applies
35+ --
36+ , tcdClassName :: Qualified ProperName
37+ -- |
38+ -- The types to which this type class instance applies
39+ --
40+ , tcdInstanceTypes :: [Type]
41+ -- |
42+ -- Type class dependencies which must be satisfied to construct this dictionary
43+ --
44+ , tcdDependencies :: Maybe [(Qualified ProperName, [Type])]
45+ -- |
46+ -- The type of this dictionary
47+ --
48+ , tcdType :: TypeClassDictionaryType
49+ } deriving (Show, Data, Typeable)
50+
51+-- |
52+-- The type of a type class dictionary
53+--
54+data TypeClassDictionaryType
55+ -- |
56+ -- A regular type class dictionary
57+ --
58+ = TCDRegular
59+ -- |
60+ -- A type class dictionary which is an alias for an imported dictionary from another module
61+ --
62+ | TCDAlias (Qualified Ident) deriving (Show, Eq, Data, Typeable)
src/Language/PureScript/Values.hsdeleted−254
@@ -1,254 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Values
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Data types for values, statements, binders and do notation
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# LANGUAGE DeriveDataTypeable #-}
17−
18−module Language.PureScript.Values where
19−
20−import Language.PureScript.Types
21−import Language.PureScript.Names
22−
23−import Data.Data
24−import Data.Generics (mkQ, everything)
25−
26−-- |
27−-- A guard is just a boolean-valued expression that appears alongside a set of binders
28−--
29−type Guard = Value
30−
31−-- |
32−-- Data type for values
33−--
34−data Value
35− -- |
36− -- A numeric literal
37− --
38− = NumericLiteral (Either Integer Double)
39− -- |
40− -- A string literal
41− --
42− | StringLiteral String
43− -- |
44− -- A boolean literal
45− --
46− | BooleanLiteral Bool
47− -- |
48− -- Binary operator application. During the rebracketing phase of desugaring, this data constructor
49− -- will be removed.
50− --
51− | BinaryNoParens (Qualified Ident) Value Value
52− -- |
53− -- Explicit parentheses. During the rebracketing phase of desugaring, this data constructor
54− -- will be removed.
55− --
56− | Parens Value
57− -- |
58− -- An array literal
59− --
60− | ArrayLiteral [Value]
61− -- |
62− -- An object literal
63− --
64− | ObjectLiteral [(String, Value)]
65− -- |
66− -- An record property accessor expression
67− --
68− | Accessor String Value
69− -- |
70− -- Partial record update
71− --
72− | ObjectUpdate Value [(String, Value)]
73− -- |
74− -- Function introduction
75− --
76− | Abs (Either Ident Binder) Value
77− -- |
78− -- Function application
79− --
80− | App Value Value
81− -- |
82− -- Variable
83− --
84− | Var (Qualified Ident)
85− -- |
86− -- Conditional (if-then-else expression)
87− --
88− | IfThenElse Value Value Value
89− -- |
90− -- A data constructor
91− --
92− | Constructor (Qualified ProperName)
93− -- |
94− -- A case expression. During the case expansion phase of desugaring, top-level binders will get
95− -- desugared into case expressions, hence the need for guards and multiple binders per branch here.
96− --
97− | Case [Value] [CaseAlternative]
98− -- |
99− -- A value with a type annotation
100− --
101− | TypedValue Bool Value Type
102− -- |
103− -- A let binding
104− --
105− | Let (Either Binder (Ident, [Either Ident Binder])) Value Value
106− -- |
107− -- A do-notation block
108− --
109− | Do [DoNotationElement]
110− -- |
111− -- A placeholder for a type class dictionary to be inserted later. At the end of type checking, these
112− -- placeholders will be replaced with actual expressions representing type classes dictionaries which
113− -- can be evaluated at runtime. The constructor arguments represent (in order): the type class name and
114− -- instance type, and the type class dictionaries in scope.
115− --
116− | TypeClassDictionary (Qualified ProperName, [Type]) [TypeClassDictionaryInScope] deriving (Show, Data, Typeable)
117−
118−-- |
119−-- An alternative in a case statement
120−--
121−data CaseAlternative = CaseAlternative
122− { -- |
123− -- A collection of binders with which to match the inputs
124− --
125− caseAlternativeBinders :: [Binder]
126− -- |
127− -- An optional guard
128− --
129− , caseAlternativeGuard :: Maybe Guard
130− -- |
131− -- The result expression
132− --
133− , caseAlternativeResult :: Value
134− } deriving (Show, Data, Typeable)
135−
136−-- |
137−-- Data representing a type class dictionary which is in scope
138−--
139−data TypeClassDictionaryInScope
140− = TypeClassDictionaryInScope {
141− -- |
142− -- The identifier with which the dictionary can be accessed at runtime
143− --
144− tcdName :: Qualified Ident
145− -- |
146− -- The name of the type class to which this type class instance applies
147− --
148− , tcdClassName :: Qualified ProperName
149− -- |
150− -- The types to which this type class instance applies
151− --
152− , tcdInstanceTypes :: [Type]
153− -- |
154− -- Type class dependencies which must be satisfied to construct this dictionary
155− --
156− , tcdDependencies :: Maybe [(Qualified ProperName, [Type])]
157− -- |
158− -- The type of this dictionary
159− --
160− , tcdType :: TypeClassDictionaryType
161− } deriving (Show, Data, Typeable)
162−
163−-- |
164−-- The type of a type class dictionary
165−--
166−data TypeClassDictionaryType
167− -- |
168− -- A regular type class dictionary
169− --
170− = TCDRegular
171− -- |
172− -- A type class dictionary which is an alias for an imported dictionary from another module
173− --
174− | TCDAlias (Qualified Ident) deriving (Show, Eq, Data, Typeable)
175−
176−-- |
177−-- Find the original dictionary which a type class dictionary in scope refers to
178−--
179−canonicalizeDictionary :: TypeClassDictionaryInScope -> Qualified Ident
180−canonicalizeDictionary (TypeClassDictionaryInScope { tcdType = TCDRegular, tcdName = nm }) = nm
181−canonicalizeDictionary (TypeClassDictionaryInScope { tcdType = TCDAlias nm }) = nm
182−
183−-- |
184−-- A statement in a do-notation block
185−--
186−data DoNotationElement
187− -- |
188− -- A monadic value without a binder
189− --
190− = DoNotationValue Value
191− -- |
192− -- A monadic value with a binder
193− --
194− | DoNotationBind Binder Value
195− -- |
196− -- A let statement, i.e. a pure value with a binder
197− --
198− | DoNotationLet Binder Value deriving (Show, Data, Typeable)
199−
200−-- |
201−-- Data type for binders
202−--
203−data Binder
204− -- |
205− -- Wildcard binder
206− --
207− = NullBinder
208− -- |
209− -- A binder which matches a boolean literal
210− --
211− | BooleanBinder Bool
212− -- |
213− -- A binder which matches a string literal
214− --
215− | StringBinder String
216− -- |
217− -- A binder which matches a numeric literal
218− --
219− | NumberBinder (Either Integer Double)
220− -- |
221− -- A binder which binds an identifier
222− --
223− | VarBinder Ident
224− -- |
225− -- A binder which matches a data constructor
226− --
227− | ConstructorBinder (Qualified ProperName) [Binder]
228− -- |
229− -- A binder which matches a record and binds its properties
230− --
231− | ObjectBinder [(String, Binder)]
232− -- |
233− -- A binder which matches an array and binds its elements
234− --
235− | ArrayBinder [Binder]
236− -- |
237− -- A binder which matches an array and binds its head and tail
238− --
239− | ConsBinder Binder Binder
240− -- |
241− -- A binder which binds its input to an identifier
242− --
243− | NamedBinder Ident Binder deriving (Show, Data, Typeable)
244−
245−
246−-- |
247−-- Collect all names introduced in binders in an expression
248−--
249−binderNames :: (Data d) => d -> [Ident]
250−binderNames = everything (++) (mkQ [] go)
251− where
252− go (VarBinder ident) = [ident]
253− go (NamedBinder ident _) = [ident]
254− go _ = []