git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
More Haddock comments
commit1cb455bec8cbac657cd7126abd9968b54b44a0b4 authorPhil Freeman <paf31@cantab.net> dateMon 27 Jan 2014, 22:31 (13 years ago) parent464a1ed
22 files changed+720−38
purescript.cabal+1−1 src/Language/PureScript/CodeGen/Externs.hs+4 src/Language/PureScript/CodeGen/JS.hs+7 src/Language/PureScript/CodeGen/JS/AST.hs+91−2 src/Language/PureScript/CodeGen/Monad.hs+12 src/Language/PureScript/CodeGen/Optimize.hs+20 src/Language/PureScript/Parser/Common.hs+165−20 src/Language/PureScript/Parser/Declarations.hs+10 src/Language/PureScript/Parser/JS.hs+4 src/Language/PureScript/Parser/Kinds.hs+4−1 src/Language/PureScript/Parser/State.hs+10−2 src/Language/PureScript/Parser/Types.hs+8−2 src/Language/PureScript/Parser/Values.hs+17−2 src/Language/PureScript/Sugar/BindingGroups.hs+14 src/Language/PureScript/Sugar/CaseDeclarations.hs+8−1 src/Language/PureScript/Sugar/DoNotation.hs+6 src/Language/PureScript/Sugar/Operators.hs+8 src/Language/PureScript/Sugar/TypeClasses.hs+13 src/Language/PureScript/Sugar/TypeDeclarations.hs+8 src/Language/PureScript/TypeChecker.hs+14 src/Language/PureScript/TypeChecker/Types.hs+19 src/Language/PureScript/Values.hs+277−7
purescript.cabal+1−1
@@ -1,5 +1,5 @@
11name: purescript
2−version: 0.3.3
2+version: 0.3.4
33cabal-version: >=1.8
44build-type: Simple
55license: MIT
src/Language/PureScript/CodeGen/Externs.hs+4
@@ -9,6 +9,7 @@
99-- Portability :
1010--
1111-- |
12+-- This module generates code for \"externs\" files, i.e. files containing only foreign import declarations.
1213--
1314-----------------------------------------------------------------------------
1415
@@ -24,6 +25,9 @@ import Language.PureScript.Pretty
2425import Language.PureScript.Names
2526import Data.List (intercalate)
2627
28+-- |
29+-- Generate foreign imports for all declarations in a module
30+--
2731moduleToPs :: Module -> Environment -> String
2832moduleToPs (Module pname@(ProperName moduleName) decls) env =
2933 "module " ++ moduleName ++ " where\n" ++
src/Language/PureScript/CodeGen/JS.hs+7
@@ -9,6 +9,7 @@
99-- Portability :
1010--
1111-- |
12+-- This module generates code in the simplified Javascript intermediate representation from Purescript code
1213--
1314-----------------------------------------------------------------------------
1415
@@ -41,6 +42,9 @@ import Language.PureScript.CodeGen.JS.AST as AST
4142import Language.PureScript.Types
4243import Language.PureScript.CodeGen.Optimize
4344
45+-- |
46+-- Generate code in the simplified Javascript intermediate representation for all declarations in a module
47+--
4448moduleToJs :: Options -> Module -> Environment -> [JS]
4549moduleToJs opts (Module pname@(ProperName name) decls) env =
4650 mapMaybe filterRawDecls decls ++
@@ -58,6 +62,9 @@ moduleToJs opts (Module pname@(ProperName name) decls) env =
5862 typeClassesLast _ (ExternDeclaration TypeClassDictionaryImport _ _ _) = LT
5963 typeClassesLast _ _ = EQ
6064
65+-- |
66+-- Generate code in the simplified Javascript intermediate representation for a declaration
67+--
6168declToJs :: Options -> ModuleName -> Declaration -> Environment -> Maybe [JS]
6269declToJs opts mp (ValueDeclaration ident _ _ val) e =
6370 Just [ JSVariableIntroduction ident (Just (valueToJs opts mp e val)),
src/Language/PureScript/CodeGen/JS/AST.hs+91−2
@@ -9,6 +9,7 @@
99-- Portability :
1010--
1111-- |
12+-- Data types for the intermediate simplified-Javascript AST
1213--
1314-----------------------------------------------------------------------------
1415
@@ -21,36 +22,124 @@ import Language.PureScript.Values
2122
2223import Data.Data
2324
25+-- |
26+-- Data type for simplified Javascript expressions
27+--
2428data JS
29+ -- |
30+ -- A numeric literal
31+ --
2532 = JSNumericLiteral (Either Integer Double)
33+ -- |
34+ -- A string literal
35+ --
2636 | JSStringLiteral String
37+ -- |
38+ -- A boolean literal
39+ --
2740 | JSBooleanLiteral Bool
41+ -- |
42+ -- A unary operator application
43+ --
2844 | JSUnary UnaryOperator JS
45+ -- |
46+ -- A binary operator application
47+ --
2948 | JSBinary BinaryOperator JS JS
49+ -- |
50+ -- An array literal
51+ --
3052 | JSArrayLiteral [JS]
53+ -- |
54+ -- An array indexer expression
55+ --
3156 | JSIndexer JS JS
57+ -- |
58+ -- An object literal
59+ --
3260 | JSObjectLiteral [(String, JS)]
61+ -- |
62+ -- An object property accessor expression
63+ --
3364 | JSAccessor String JS
65+ -- |
66+ -- A function introduction (optional name, arguments, body)
67+ --
3468 | JSFunction (Maybe Ident) [Ident] JS
69+ -- |
70+ -- Function application
71+ --
3572 | JSApp JS [JS]
73+ -- |
74+ -- Variable
75+ --
3676 | JSVar Ident
77+ -- |
78+ -- Conditional expression
79+ --
3780 | JSConditional JS JS JS
81+ -- |
82+ -- A block of expressions in braces
83+ --
3884 | JSBlock [JS]
85+ -- |
86+ -- A variable introduction and optional initialization
87+ --
3988 | JSVariableIntroduction Ident (Maybe JS)
89+ -- |
90+ -- A variable assignment
91+ --
4092 | JSAssignment JSAssignment JS
93+ -- |
94+ -- While loop
95+ --
4196 | JSWhile JS JS
97+ -- |
98+ -- For loop
99+ --
42100 | JSFor Ident JS JS JS
101+ -- |
102+ -- If-then-else statement
103+ --
43104 | JSIfElse JS JS (Maybe JS)
105+ -- |
106+ -- Return statement
107+ --
44108 | JSReturn JS
109+ -- |
110+ -- Throw statement
111+ --
45112 | JSThrow JS
113+ -- |
114+ -- Type-Of operator
115+ --
46116 | JSTypeOf JS
117+ -- |
118+ -- Labelled statement
119+ --
47120 | JSLabel String JS
121+ -- |
122+ -- Break statement
123+ --
48124 | JSBreak String
125+ -- |
126+ -- Continue statement
127+ --
49128 | JSContinue String
129+ -- |
130+ -- Raw Javascript (generated when parsing fails for an inline foreign import declaration)
131+ --
50132 | JSRaw String deriving (Show, Data, Typeable)
51133
134+-- |
135+-- Data type for expressions which can appear on the left hand side of an assignment
136+--
52137data JSAssignment
138+ -- |
139+ -- Assign a variable
140+ --
53141 = JSAssignVariable Ident
142+ -- |
143+ -- Assign an object property
144+ --
54145 | JSAssignProperty String JSAssignment deriving (Show, Data, Typeable)
55−
56−
src/Language/PureScript/CodeGen/Monad.hs+12
@@ -9,6 +9,9 @@
99-- Portability :
1010--
1111-- |
12+-- Code generation monad
13+--
14+-- This monad provides a supply of fresh names which can be used to create variables.
1215--
1316-----------------------------------------------------------------------------
1417
@@ -20,11 +23,20 @@ import Control.Monad.State
2023import Control.Applicative
2124import Language.PureScript.Names
2225
26+-- |
27+-- Code generation monad data type
28+--
2329newtype Gen a = Gen { unGen :: State [Ident] a } deriving (Functor, Applicative, Monad, MonadState [Ident])
2430
31+-- |
32+-- Run a computation in the code generation monad
33+--
2534runGen :: [Ident] -> Gen a -> a
2635runGen names = flip evalState names . unGen
2736
37+-- |
38+-- Generate a fresh name
39+--
2840fresh :: Gen Ident
2941fresh = do
3042 (s:ss) <- get
src/Language/PureScript/CodeGen/Optimize.hs+20
@@ -9,6 +9,23 @@
99-- Portability :
1010--
1111-- |
12+-- This module optimizes code in the simplified-Javascript intermediate representation.
13+--
14+-- The following optimizations are supported:
15+--
16+-- * Collapsing nested blocks
17+--
18+-- * Tail call elimination
19+--
20+-- * Inlining of (>>=) and ret for the Eff monad
21+--
22+-- * Removal of unused variables
23+--
24+-- * Removal of unnecessary thunks
25+--
26+-- * Eta conversion
27+--
28+-- * Inlining variables
1229--
1330-----------------------------------------------------------------------------
1431
@@ -28,6 +45,9 @@ import Language.PureScript.Sugar.TypeClasses
2845 (mkDictionaryValueName)
2946import Language.PureScript.Types (Type(..))
3047
48+-- |
49+-- Apply a series of optimizer passes to simplified Javascript code
50+--
3151optimize :: Options -> JS -> JS
3252optimize opts =
3353 collapseNestedBlocks
src/Language/PureScript/Parser/Common.hs+165−20
@@ -9,6 +9,7 @@
99-- Portability :
1010--
1111-- |
12+-- Constants, and utility functions to be used when parsing
1213--
1314-----------------------------------------------------------------------------
1415
@@ -25,6 +26,9 @@ import qualified Text.Parsec.Token as PT
2526
2627import Language.PureScript.Names
2728
29+-- |
30+-- A list of reserved identifiers
31+--
2832reservedNames :: [String]
2933reservedNames = [ "case"
3034 , "of"
@@ -76,28 +80,52 @@ reservedNames = [ "case"
7680 , "instance"
7781 , "where" ]
7882
83+-- |
84+-- A list of built-in operator names
85+--
7986builtInOperators :: [String]
8087builtInOperators = [ "~", "-", "<=", ">=", "<", ">", "*", "/", "%", "++", "+", "<<", ">>>", ">>"
8188 , "==", "!=", "&&", "||", "&", "^", "|", "!!", "!" ]
8289
90+-- |
91+-- A list of reserved operators
92+--
8393reservedOpNames :: [String]
8494reservedOpNames = builtInOperators ++ [ "=>", "->", "=", ".", "\\" ]
8595
96+-- |
97+-- Valid first characters for an identifier
98+--
8699identStart :: P.Parsec String u Char
87100identStart = P.lower <|> P.oneOf "_"
88101
102+-- |
103+-- Valid first characters for a proper name
104+--
89105properNameStart :: P.Parsec String u Char
90106properNameStart = P.upper
91107
108+-- |
109+-- Valid identifier characters
110+--
92111identLetter :: P.Parsec String u Char
93112identLetter = P.alphaNum <|> P.oneOf "_'"
94113
114+-- |
115+-- Valid first characters for an operator
116+--
95117opStart :: P.Parsec String u Char
96118opStart = P.oneOf ":!#$%&*+./<=>?@\\^|-~"
97119
120+-- |
121+-- Valid operators characters
122+--
98123opLetter :: P.Parsec String u Char
99124opLetter = P.oneOf ":!#$%&*+./<=>?@\\^|-~"
100125
126+-- |
127+-- The PureScript language definition
128+--
101129langDef :: PT.GenLanguageDef String u Identity
102130langDef = PT.LanguageDef
103131 { PT.reservedNames = reservedNames
@@ -113,104 +141,209 @@ langDef = PT.LanguageDef
113141 , PT.caseSensitive = True
114142 }
115143
144+-- |
145+-- A token parser based on the language definition
146+--
116147tokenParser :: PT.GenTokenParser String u Identity
117148tokenParser = PT.makeTokenParser langDef
118149
150+-- |
151+-- Parse a token
152+--
119153lexeme :: P.Parsec String u a -> P.Parsec String u a
120154lexeme = PT.lexeme tokenParser
121155
156+-- |
157+-- Parse an identifier
158+--
122159identifier :: P.Parsec String u String
123160identifier = PT.identifier tokenParser
124161
162+-- |
163+-- Parse a reserved word
164+--
125165reserved :: String -> P.Parsec String u ()
126166reserved = PT.reserved tokenParser
127167
168+-- |
169+-- Parse a reserved operator
170+--
128171reservedOp :: String -> P.Parsec String u ()
129172reservedOp = PT.reservedOp tokenParser
130173
174+-- |
175+-- Parse an operator
176+--
131177operator :: P.Parsec String u String
132178operator = PT.operator tokenParser
133179
180+-- |
181+-- Parse a string literal
182+--
134183stringLiteral :: P.Parsec String u String
135184stringLiteral = PT.stringLiteral tokenParser
136185
186+-- |
187+-- Parse whitespace
188+--
137189whiteSpace :: P.Parsec String u ()
138190whiteSpace = PT.whiteSpace tokenParser
139191
192+-- |
193+-- Semicolon
194+--
140195semi :: P.Parsec String u String
141196semi = PT.semi tokenParser
142197
198+-- |
199+-- Colon
200+--
143201colon :: P.Parsec String u String
144202colon = PT.colon tokenParser
145203
204+-- |
205+-- Period
206+--
146207dot :: P.Parsec String u String
147208dot = PT.dot tokenParser
148209
210+-- |
211+-- Comma
212+--
149213comma :: P.Parsec String u String
150214comma = PT.comma tokenParser
151215
216+-- |
217+-- Backtick
218+--
152219tick :: P.Parsec String u Char
153220tick = lexeme $ P.char '`'
154221
222+-- |
223+-- Pipe character
224+--
155225pipe :: P.Parsec String u Char
156226pipe = lexeme $ P.char '|'
157227
228+-- |
229+-- Natural number
230+--
158231natural :: P.Parsec String u Integer
159232natural = PT.natural tokenParser
160233
234+-- |
235+-- Parse a proper name
236+--
237+properName :: P.Parsec String u ProperName
238+properName = lexeme $ ProperName <$> P.try ((:) <$> P.upper <*> many (PT.identLetter langDef) P.<?> "name")
239+
240+-- |
241+-- Parse a qualified name, i.e. M.name or just name
242+--
243+parseQualified :: P.Parsec String ParseState a -> P.Parsec String ParseState (Qualified a)
244+parseQualified parser = qual
245+ where
246+ qual = (Qualified <$> (Just . ModuleName <$> P.try (properName <* delimiter)) <*> parser)
247+ <|> (Qualified Nothing <$> P.try parser)
248+ delimiter = indented *> dot
249+
250+-- |
251+-- Parse an integer or floating point value
252+--
253+integerOrFloat :: P.Parsec String u (Either Integer Double)
254+integerOrFloat = (Left <$> P.try (PT.natural tokenParser) <|>
255+ Right <$> P.try (PT.float tokenParser)) P.<?> "number"
256+
257+-- |
258+-- Parse an operator or a built-in operator
259+--
260+operatorOrBuiltIn :: P.Parsec String u String
261+operatorOrBuiltIn = P.try operator <|> P.choice (map (\s -> P.try (reservedOp s) >> return s) builtInOperators)
262+
263+-- |
264+-- Parse an identifier or parenthesized operator
265+--
266+parseIdent :: P.Parsec String ParseState Ident
267+parseIdent = (Ident <$> identifier) <|> (Op <$> parens operatorOrBuiltIn)
268+
269+-- |
270+-- Parse a token inside square brackets
271+--
161272squares :: P.Parsec String ParseState a -> P.Parsec String ParseState a
162273squares = P.between (lexeme $ P.char '[') (lexeme $ indented *> P.char ']') . (indented *>)
163274
275+-- |
276+-- Parse a token inside parentheses
277+--
164278parens :: P.Parsec String ParseState a -> P.Parsec String ParseState a
165279parens = P.between (lexeme $ P.char '(') (lexeme $ indented *> P.char ')') . (indented *>)
166280
281+-- |
282+-- Parse a token inside braces
283+--
167284braces :: P.Parsec String ParseState a -> P.Parsec String ParseState a
168285braces = P.between (lexeme $ P.char '{') (lexeme $ indented *> P.char '}') . (indented *>)
169286
287+-- |
288+-- Parse a token inside angle brackets
289+--
170290angles :: P.Parsec String ParseState a -> P.Parsec String ParseState a
171291angles = P.between (lexeme $ P.char '<') (lexeme $ indented *> P.char '>') . (indented *>)
172292
293+-- |
294+-- Parse zero or more values separated by a separator token
295+--
173296sepBy :: P.Parsec String ParseState a -> P.Parsec String ParseState sep -> P.Parsec String ParseState [a]
174297sepBy p s = P.sepBy (indented *> p) (indented *> s)
175298
299+-- |
300+-- Parse one or more values separated by a separator token
301+--
176302sepBy1 :: P.Parsec String ParseState a -> P.Parsec String ParseState sep -> P.Parsec String ParseState [a]
177303sepBy1 p s = P.sepBy1 (indented *> p) (indented *> s)
178304
305+-- |
306+-- Parse zero or more values separated by semicolons
307+--
179308semiSep :: P.Parsec String ParseState a -> P.Parsec String ParseState [a]
180309semiSep = flip sepBy semi
181310
311+-- |
312+-- Parse one or more values separated by semicolons
313+--
182314semiSep1 :: P.Parsec String ParseState a -> P.Parsec String ParseState [a]
183315semiSep1 = flip sepBy1 semi
184316
317+-- |
318+-- Parse zero or more values separated by commas
319+--
185320commaSep :: P.Parsec String ParseState a -> P.Parsec String ParseState [a]
186321commaSep = flip sepBy comma
187322
323+-- |
324+-- Parse one or more values separated by commas
325+--
188326commaSep1 :: P.Parsec String ParseState a -> P.Parsec String ParseState [a]
189327commaSep1 = flip sepBy1 comma
190328
191−properName :: P.Parsec String u ProperName
192−properName = lexeme $ ProperName <$> P.try ((:) <$> P.upper <*> many (PT.identLetter langDef) P.<?> "name")
193−
194−parseQualified :: P.Parsec String ParseState a -> P.Parsec String ParseState (Qualified a)
195−parseQualified parser = qual
196− where
197− qual = (Qualified <$> (Just . ModuleName <$> P.try (properName <* delimiter)) <*> parser)
198− <|> (Qualified Nothing <$> P.try parser)
199− delimiter = indented *> dot
200−
201−integerOrFloat :: P.Parsec String u (Either Integer Double)
202−integerOrFloat = (Left <$> P.try (PT.natural tokenParser) <|>
203− Right <$> P.try (PT.float tokenParser)) P.<?> "number"
204−
329+-- |
330+-- Run the first parser, then match the second if possible, applying the specified function on a successful match
331+--
205332augment :: P.Stream s m t => P.ParsecT s u m a -> P.ParsecT s u m b -> (a -> b -> a) -> P.ParsecT s u m a
206333augment p q f = flip (maybe id $ flip f) <$> p <*> P.optionMaybe q
207334
335+-- |
336+-- Run the first parser, then match the second zero or more times, applying the specified function for each match
337+--
208338fold :: P.Stream s m t => P.ParsecT s u m a -> P.ParsecT s u m b -> (a -> b -> a) -> P.ParsecT s u m a
209339fold first more combine = do
210340 a <- first
211341 bs <- P.many more
212342 return $ foldl combine a bs
213343
344+-- |
345+-- Build a parser from a smaller parser and a list of parsers for postfix operators
346+--
214347buildPostfixParser :: P.Stream s m t => [a -> P.ParsecT s u m a] -> P.ParsecT s u m a -> P.ParsecT s u m a
215348buildPostfixParser fs first = do
216349 a <- first
@@ -222,15 +355,15 @@ buildPostfixParser fs first = do
222355 Nothing -> return a
223356 Just a' -> go a'
224357
225−operatorOrBuiltIn :: P.Parsec String u String
226−operatorOrBuiltIn = P.try operator <|> P.choice (map (\s -> P.try (reservedOp s) >> return s) builtInOperators)
227−
228−parseIdent :: P.Parsec String ParseState Ident
229−parseIdent = (Ident <$> identifier) <|> (Op <$> parens operatorOrBuiltIn)
230−
358+-- |
359+-- Parse an identifier in backticks or an operator
360+--
231361parseIdentInfix :: P.Parsec String ParseState (Qualified Ident)
232362parseIdentInfix = (P.between tick tick (parseQualified (Ident <$> identifier))) <|> parseQualified (Op <$> operatorOrBuiltIn)
233363
364+-- |
365+-- Mark the current indentation level
366+--
234367mark :: P.Parsec String ParseState a -> P.Parsec String ParseState a
235368mark p = do
236369 current <- indentationLevel <$> P.getState
@@ -240,17 +373,29 @@ mark p = do
240373 P.modifyState $ \st -> st { indentationLevel = current }
241374 return a
242375
376+-- |
377+-- Check that the current identation level matches a predicate
378+--
243379checkIndentation :: (P.Column -> P.Column -> Bool) -> P.Parsec String ParseState ()
244380checkIndentation rel = do
245381 col <- P.sourceColumn <$> P.getPosition
246382 current <- indentationLevel <$> P.getState
247383 guard (col `rel` current)
248384
385+-- |
386+-- Check that the current indentation level is past the current mark
387+--
249388indented :: P.Parsec String ParseState ()
250389indented = checkIndentation (>) P.<?> "indentation"
251390
391+-- |
392+-- Check that the current indentation level is at the same indentation as the current mark
393+--
252394same :: P.Parsec String ParseState ()
253395same = checkIndentation (==) P.<?> "no indentation"
254396
397+-- |
398+-- Run a parser which supports indentation
399+--
255400runIndentParser :: P.Parsec String ParseState a -> String -> Either P.ParseError a
256401runIndentParser p = P.runParser p (ParseState 0) ""
src/Language/PureScript/Parser/Declarations.hs+10
@@ -9,6 +9,7 @@
99-- Portability :
1010--
1111-- |
12+-- Parsers for module definitions and declarations
1213--
1314-----------------------------------------------------------------------------
1415
@@ -120,6 +121,9 @@ parseTypeInstanceDeclaration = do
120121 members <- mark (P.many (same *> parseValueDeclaration))
121122 return $ TypeInstanceDeclaration (fromMaybe [] deps) className ty members
122123
124+-- |
125+-- Parse a single declaration
126+--
123127parseDeclaration :: P.Parsec String ParseState Declaration
124128parseDeclaration = P.choice
125129 [ parseDataDeclaration
@@ -132,6 +136,9 @@ parseDeclaration = P.choice
132136 , parseTypeClassDeclaration
133137 , parseTypeInstanceDeclaration ] P.<?> "declaration"
134138
139+-- |
140+-- Parse a module header and a collection of declarations
141+--
135142parseModule :: P.Parsec String ParseState Module
136143parseModule = do
137144 reserved "module"
@@ -141,5 +148,8 @@ parseModule = do
141148 decls <- mark (P.many (same *> parseDeclaration))
142149 return $ Module name decls
143150
151+-- |
152+-- Parse a collection of modules
153+--
144154parseModules :: P.Parsec String ParseState [Module]
145155parseModules = whiteSpace *> mark (P.many (same *> parseModule)) <* P.eof
src/Language/PureScript/Parser/JS.hs+4
@@ -9,6 +9,7 @@
99-- Portability :
1010--
1111-- |
12+-- A parser for a small fragment of Javascript
1213--
1314-----------------------------------------------------------------------------
1415
@@ -99,6 +100,9 @@ binary op s f = P.Infix (P.try $ C.reservedOp s >> return (JSBinary op)) f
99100unary :: UnaryOperator -> String -> P.Operator String u Identity JS
100101unary op s = P.Prefix (P.try $ C.reservedOp s >> return (JSUnary op))
101102
103+-- |
104+-- Parse a simplified Javascript expression
105+--
102106parseJS :: P.Parsec String u JS
103107parseJS =
104108 (P.buildExpressionParser operators
src/Language/PureScript/Parser/Kinds.hs+4−1
@@ -9,6 +9,7 @@
99-- Portability :
1010--
1111-- |
12+-- A parser for kinds
1213--
1314-----------------------------------------------------------------------------
1415
@@ -34,7 +35,9 @@ parseTypeAtom = indented *> P.choice (map P.try
3435 [ parseStar
3536 , parseBang
3637 , parens parseKind ])
37−
38+-- |
39+-- Parse a kind
40+--
3841parseKind :: P.Parsec String ParseState Kind
3942parseKind = P.buildExpressionParser operators parseTypeAtom P.<?> "kind"
4043 where
src/Language/PureScript/Parser/State.hs+10−2
@@ -9,6 +9,7 @@
99-- Portability :
1010--
1111-- |
12+-- State for the parser monad
1213--
1314-----------------------------------------------------------------------------
1415
@@ -16,7 +17,14 @@ module Language.PureScript.Parser.State where
1617
1718import qualified Text.Parsec as P
1819
19−data ParseState = ParseState
20− { indentationLevel :: P.Column } deriving Show
20+-- |
21+-- State for the parser monad
22+--
23+data ParseState = ParseState {
24+ -- |
25+ -- The most recently marked indentation level
26+ --
27+ indentationLevel :: P.Column
28+ } deriving Show
2129
2230
src/Language/PureScript/Parser/Types.hs+8−2
@@ -9,13 +9,13 @@
99-- Portability :
1010--
1111-- |
12+-- Parsers for types
1213--
1314-----------------------------------------------------------------------------
1415
1516module Language.PureScript.Parser.Types (
1617 parseType,
17− parsePolyType,
18− parseRow
18+ parsePolyType
1919) where
2020
2121import Language.PureScript.Types
@@ -97,12 +97,18 @@ parseAnyType = (P.buildExpressionParser operators . buildPostfixParser postfixTa
9797 postfixTable = [ \x -> TypeApp x <$> P.try (indented *> parseTypeAtom) ]
9898 operators = [ [ P.Infix (lexeme (P.try (P.string "->")) >> return (\t1 t2 -> Function [t1] t2)) P.AssocRight ] ]
9999
100+-- |
101+-- Parse a monotype
102+--
100103parseType :: P.Parsec String ParseState Type
101104parseType = do
102105 ty <- parseAnyType
103106 unless (isMonoType ty) $ P.unexpected "polymorphic type"
104107 return ty
105108
109+-- |
110+-- Parse a polytype
111+--
106112parsePolyType :: P.Parsec String ParseState Type
107113parsePolyType = do
108114 ty <- parseAnyType
src/Language/PureScript/Parser/Values.hs+17−2
@@ -9,15 +9,16 @@
99-- Portability :
1010--
1111-- |
12+-- Parsers for values, statements, binders and guards
1213--
1314-----------------------------------------------------------------------------
1415
1516module Language.PureScript.Parser.Values (
1617 parseValue,
18+ parseStatement,
1719 parseGuard,
1820 parseBinder,
1921 parseBinderNoParens,
20− parseDoNotationElement
2122) where
2223
2324import Language.PureScript.Values
@@ -146,6 +147,9 @@ parseDoNotationElement = P.choice
146147 , parseDoNotationLet
147148 , P.try (DoNotationValue <$> parseValue) ]
148149
150+-- |
151+-- Parse a value
152+--
149153parseValue :: P.Parsec String ParseState Value
150154parseValue =
151155 (buildExpressionParser operators
@@ -212,6 +216,9 @@ parseElseStatement = C.reserved "else" >> (ElseIf <$> parseIfStatement
212216parseReturn :: P.Parsec String ParseState Statement
213217parseReturn = Return <$> (C.reserved "return" *> parseValue <* C.indented <* C.semi)
214218
219+-- |
220+-- Parse a statement
221+--
215222parseStatement :: P.Parsec String ParseState Statement
216223parseStatement = P.choice
217224 [ parseVariableIntroduction
@@ -273,11 +280,17 @@ parseBinderAtom = P.choice (map P.try
273280 , parseArrayBinder
274281 , C.parens parseBinder ]) P.<?> "binder"
275282
283+-- |
284+-- Parse a binder
285+--
276286parseBinder :: P.Parsec String ParseState Binder
277287parseBinder = (buildExpressionParser operators parseBinderAtom) P.<?> "expression"
278288 where
279289 operators = [ [ Infix ( C.lexeme (P.try $ C.indented *> C.reservedOp ":") >> return ConsBinder) AssocRight ] ]
280290
291+-- |
292+-- Parse a binder as it would appear in a top level declaration
293+--
281294parseBinderNoParens :: P.Parsec String ParseState Binder
282295parseBinderNoParens = P.choice (map P.try
283296 [ parseNullBinder
@@ -290,7 +303,9 @@ parseBinderNoParens = P.choice (map P.try
290303 , parseObjectBinder
291304 , parseArrayBinder
292305 , C.parens parseBinder ]) P.<?> "binder"
293−
306+-- |
307+-- Parse a guard
308+--
294309parseGuard :: P.Parsec String ParseState Guard
295310parseGuard = C.indented *> C.pipe *> C.indented *> parseValue
296311
src/Language/PureScript/Sugar/BindingGroups.hs+14
@@ -9,6 +9,8 @@
99-- Portability :
1010--
1111-- |
12+-- This module implements the desugaring pass which creates binding groups from sets of
13+-- mutually-recursive value declarations and mutually-recursive type declarations.
1214--
1315-----------------------------------------------------------------------------
1416
@@ -30,12 +32,21 @@ import Language.PureScript.Names
3032import Language.PureScript.Values
3133import Language.PureScript.Types
3234
35+-- |
36+-- Replace all sets of mutually-recursive declarations in a module with binding groups
37+--
3338createBindingGroupsModule :: [Module] -> Either String [Module]
3439createBindingGroupsModule = mapM $ \(Module name ds) -> Module name <$> createBindingGroups ds
3540
41+-- |
42+-- Collapse all binding groups in a module to individual declarations
43+--
3644collapseBindingGroupsModule :: [Module] -> [Module]
3745collapseBindingGroupsModule = map $ \(Module name ds) -> Module name (collapseBindingGroups ds)
3846
47+-- |
48+-- Replace all sets of mutually-recursive declarations with binding groups
49+--
3950createBindingGroups :: [Declaration] -> Either String [Declaration]
4051createBindingGroups ds = do
4152 let values = filter isValueDecl ds
@@ -54,6 +65,9 @@ createBindingGroups ds = do
5465 filter isExternDecl ds ++
5566 bindingGroupDecls
5667
68+-- |
69+-- Collapse all binding groups to individual declarations
70+--
5771collapseBindingGroups :: [Declaration] -> [Declaration]
5872collapseBindingGroups ds = concatMap go ds
5973 where
src/Language/PureScript/Sugar/CaseDeclarations.hs+8−1
@@ -9,6 +9,8 @@
99-- Portability :
1010--
1111-- |
12+-- This module implements the desugaring pass which replaces top-level binders with
13+-- case expressions.
1214--
1315-----------------------------------------------------------------------------
1416
@@ -27,9 +29,14 @@ import Language.PureScript.Values
2729import Language.PureScript.Declarations
2830import Language.PureScript.Scope
2931
32+-- |
33+-- Replace all top-level binders in a module with case expressions.
34+--
3035desugarCasesModule :: [Module] -> Either String [Module]
3136desugarCasesModule ms = forM ms $ \(Module name ds) -> Module name <$> desugarCases ds
32−
37+-- |
38+-- Replace all top-level binders with case expressions.
39+--
3340desugarCases :: [Declaration] -> Either String [Declaration]
3441desugarCases = fmap join . mapM toDecls . groupBy inSameGroup
3542
src/Language/PureScript/Sugar/DoNotation.hs+6
@@ -9,6 +9,8 @@
99-- Portability :
1010--
1111-- |
12+-- This module implements the desugaring pass which replaces do-notation statements with
13+-- appropriate calls to (>>=) from the Prelude.Monad type class.
1214--
1315-----------------------------------------------------------------------------
1416
@@ -23,6 +25,10 @@ import Language.PureScript.Values
2325import Language.PureScript.Names
2426import Language.PureScript.Scope
2527
28+-- |
29+-- Replace all @DoNotationBind@ and @DoNotationValue@ constructors with applications of the Prelude.(>>=) function,
30+-- and all @DoNotationLet@ constructors with let expressions.
31+--
2632desugarDo :: (Data d) => d -> Either String d
2733desugarDo = everywhereM (mkM replace)
2834 where
src/Language/PureScript/Sugar/Operators.hs+8
@@ -9,6 +9,11 @@
99-- Portability :
1010--
1111-- |
12+-- This module implements the desugaring pass which reapplies binary operators based
13+-- on their fixity data and removes explicit parentheses.
14+--
15+-- The value parser ignores fixity data when parsing binary operator applications, so
16+-- it is necessary to reorder them here.
1217--
1318-----------------------------------------------------------------------------
1419
@@ -33,6 +38,9 @@ import qualified Text.Parsec as P
3338import qualified Text.Parsec.Pos as P
3439import qualified Text.Parsec.Expr as P
3540
41+-- |
42+-- Remove explicit parentheses and reorder binary operator applications
43+--
3644rebracket :: [Module] -> Either String [Module]
3745rebracket = go M.empty []
3846 where
src/Language/PureScript/Sugar/TypeClasses.hs+13
@@ -9,6 +9,8 @@
99-- Portability :
1010--
1111-- |
12+-- This module implements the desugaring pass which creates type synonyms for type class dictionaries
13+-- and dictionary expressions for type class instances.
1214--
1315-----------------------------------------------------------------------------
1416
@@ -38,6 +40,10 @@ type MemberMap = M.Map (ModuleName, ProperName) (String, [(String, Type)])
3840
3941type Desugar = StateT MemberMap (Either String)
4042
43+-- |
44+-- Add type synonym declarations for type class dictionary types, and value declarations for type class
45+-- instance dictionary expressions.
46+--
4147desugarTypeClasses :: [Module] -> Either String [Module]
4248desugarTypeClasses = flip evalStateT M.empty . mapM desugarModule
4349
@@ -120,6 +126,9 @@ quantify ty' = foldr ForAll ty' tyVars
120126 collect (TypeVar v) = [v]
121127 collect _ = []
122128
129+-- |
130+-- Generate a name for a type class dictionary, based on the module name, class name and type name
131+--
123132mkDictionaryValueName :: ModuleName -> Qualified ProperName -> Type -> Either String Ident
124133mkDictionaryValueName mn cl ty = do
125134 tyStr <- typeToString mn ty
@@ -135,6 +144,10 @@ typeToString mn (TypeConstructor ty') = return $ qualifiedToString mn ty'
135144typeToString mn (TypeApp ty' (TypeVar _)) = typeToString mn ty'
136145typeToString a b = Left $ "Type class instance must be of the form T a1 ... an " ++ show (a, b)
137146
147+-- |
148+-- Generate a name for a type class dictionary member, based on the module name, class name, type name and
149+-- member name
150+--
138151mkDictionaryEntryName :: ModuleName -> Qualified ProperName -> Type -> Ident -> Desugar Ident
139152mkDictionaryEntryName mn name ty ident = do
140153 Ident dictName <- lift $ mkDictionaryValueName mn name ty
src/Language/PureScript/Sugar/TypeDeclarations.hs+8
@@ -9,6 +9,8 @@
99-- Portability :
1010--
1111-- |
12+-- This module implements the desugaring pass which replaces top-level type declarations with
13+-- type annotations on the corresponding expression.
1214--
1315-----------------------------------------------------------------------------
1416
@@ -24,9 +26,15 @@ import Control.Monad (forM)
2426import Language.PureScript.Declarations
2527import Language.PureScript.Values
2628
29+-- |
30+-- Replace all top level type declarations in a module with type annotations
31+--
2732desugarTypeDeclarationsModule :: [Module] -> Either String [Module]
2833desugarTypeDeclarationsModule ms = forM ms $ \(Module name ds) -> Module name <$> desugarTypeDeclarations ds
2934
35+-- |
36+-- Replace all top level type declarations with type annotations
37+--
3038desugarTypeDeclarations :: [Declaration] -> Either String [Declaration]
3139desugarTypeDeclarations (TypeDeclaration name ty : ValueDeclaration name' [] Nothing val : rest) | name == name' =
3240 desugarTypeDeclarations (ValueDeclaration name [] Nothing (TypedValue True val ty) : rest)
src/Language/PureScript/TypeChecker.hs+14
@@ -9,6 +9,7 @@
99-- Portability :
1010--
1111-- |
12+-- The top-level type checker, which checks all declarations in a module.
1213--
1314-----------------------------------------------------------------------------
1415
@@ -88,6 +89,19 @@ addTypeClassDictionaries :: [TypeClassDictionaryInScope] -> Check ()
8889addTypeClassDictionaries entries = do
8990 modify $ \st -> st { checkEnv = (checkEnv st) { typeClassDictionaries = entries ++ (typeClassDictionaries . checkEnv $ st) } }
9091
92+-- |
93+-- Type check all declarations in a module
94+--
95+-- At this point, many declarations will have been desugared, but it is still necessary to
96+--
97+-- * Kind-check all types and add them to the @Environment@
98+--
99+-- * Type-check all values and add them to the @Environment@
100+--
101+-- * Bring type class instances into scope
102+--
103+-- * Process module imports
104+--
91105typeCheckAll :: ModuleName -> [Declaration] -> Check [Declaration]
92106typeCheckAll _ [] = return []
93107typeCheckAll moduleName (d@(DataDeclaration name args dctors) : rest) = do
src/Language/PureScript/TypeChecker/Types.hs+19
@@ -20,6 +20,25 @@ module Language.PureScript.TypeChecker.Types (
2020 typesOf
2121) where
2222
23+{-
24+ The following functions represent the corresponding type checking judgements:
25+
26+ infer
27+ Synthesize a type for a value
28+
29+ check
30+ Check a value has a given type
31+
32+ checkProperties
33+ Check an object with a given type contains specified properties
34+
35+ checkFunctionApplication
36+ Check a function of a given type returns a value of another type when applied to its arguments
37+
38+ subsumes
39+ Check a type subsumes another type
40+-}
41+
2342import Data.List
2443import Data.Maybe (maybeToList, isNothing, isJust, fromMaybe)
2544import qualified Data.Data as D
src/Language/PureScript/Values.hs+277−7
@@ -9,6 +9,7 @@
99-- Portability :
1010--
1111-- |
12+-- Data types for values, statements, binders and do notation
1213--
1314-----------------------------------------------------------------------------
1415
@@ -21,100 +22,369 @@ import Language.PureScript.Names
2122
2223import Data.Data
2324
25+-- |
26+-- A guard is just a boolean-valued expression that appears alongside a set of binders
27+--
2428type Guard = Value
2529
30+-- |
31+-- Built-in unary operators
32+--
2633data UnaryOperator
34+ -- |
35+ -- Numeric negation
36+ --
2737 = Negate
38+ -- |
39+ -- Boolean negation
40+ --
2841 | Not
42+ -- |
43+ -- Bitwise negation
44+ --
2945 | BitwiseNot
46+ -- |
47+ -- Numeric unary \'plus\'
48+ --
3049 | Positive deriving (Show, Eq, Data, Typeable)
3150
51+-- |
52+-- Built-in binary operators
53+--
3254data BinaryOperator
55+ -- |
56+ -- Numeric addition
57+ --
3358 = Add
59+ -- |
60+ -- Numeric subtraction
61+ --
3462 | Subtract
63+ -- |
64+ -- Numeric multiplication
65+ --
3566 | Multiply
67+ -- |
68+ -- Numeric division
69+ --
3670 | Divide
71+ -- |
72+ -- Remainder
73+ --
3774 | Modulus
75+ -- |
76+ -- Generic equality test
77+ --
3878 | EqualTo
79+ -- |
80+ -- Generic inequality test
81+ --
3982 | NotEqualTo
83+ -- |
84+ -- Numeric less-than
85+ --
4086 | LessThan
87+ -- |
88+ -- Numeric less-than-or-equal
89+ --
4190 | LessThanOrEqualTo
91+ -- |
92+ -- Numeric greater-than
93+ --
4294 | GreaterThan
95+ -- |
96+ -- Numeric greater-than-or-equal
97+ --
4398 | GreaterThanOrEqualTo
99+ -- |
100+ -- Boolean and
101+ --
44102 | And
103+ -- |
104+ -- Boolean or
105+ --
45106 | Or
107+ -- |
108+ -- Bitwise and
109+ --
46110 | BitwiseAnd
111+ -- |
112+ -- Bitwise or
113+ --
47114 | BitwiseOr
115+ -- |
116+ -- Bitwise xor
117+ --
48118 | BitwiseXor
119+ -- |
120+ -- Bitwise left shift
121+ --
49122 | ShiftLeft
123+ -- |
124+ -- Bitwise right shift
125+ --
50126 | ShiftRight
127+ -- |
128+ -- Bitwise right shift with zero-fill
129+ --
51130 | ZeroFillShiftRight
131+ -- |
132+ -- String concatenation
133+ --
52134 | Concat deriving (Show, Eq, Data, Typeable)
53135
136+-- |
137+-- Data type for values
138+--
54139data Value
140+ -- |
141+ -- A numeric literal
142+ --
55143 = NumericLiteral (Either Integer Double)
144+ -- |
145+ -- A string literal
146+ --
56147 | StringLiteral String
148+ -- |
149+ -- A boolean literal
150+ --
57151 | BooleanLiteral Bool
152+ -- |
153+ -- Unary operator application
154+ --
58155 | Unary UnaryOperator Value
156+ -- |
157+ -- Binary operator application
158+ --
59159 | Binary BinaryOperator Value Value
160+ -- |
161+ -- Binary operator application. During the rebracketing phase of desugaring, this data constructor
162+ -- will be removed.
163+ --
60164 | BinaryNoParens (Qualified Ident) Value Value
165+ -- |
166+ -- Explicit parentheses. During the rebracketing phase of desugaring, this data constructor
167+ -- will be removed.
168+ --
61169 | Parens Value
170+ -- |
171+ -- An array literal
172+ --
62173 | ArrayLiteral [Value]
174+ -- |
175+ -- An array indexing expression
176+ --
63177 | Indexer Value Value
178+ -- |
179+ -- An object literal
180+ --
64181 | ObjectLiteral [(String, Value)]
182+ -- |
183+ -- An record property accessor expression
184+ --
65185 | Accessor String Value
186+ -- |
187+ -- Partial record update
188+ --
66189 | ObjectUpdate Value [(String, Value)]
190+ -- |
191+ -- Function introduction
192+ --
67193 | Abs [Ident] Value
194+ -- |
195+ -- Function application
196+ --
68197 | App Value [Value]
198+ -- |
199+ -- Variable
200+ --
69201 | Var (Qualified Ident)
202+ -- |
203+ -- Conditional (if-then-else expression)
204+ --
70205 | IfThenElse Value Value Value
206+ -- |
207+ -- A \"Block\" i.e. a collection of statements which evaluate to a value
208+ --
71209 | Block [Statement]
210+ -- |
211+ -- A data constructor
212+ --
72213 | Constructor (Qualified ProperName)
214+ -- |
215+ -- A case expression. During the case expansion phase of desugaring, top-level binders will get
216+ -- desugared into case expressions, hence the need for guards and multiple binders per branch here.
217+ --
73218 | Case [Value] [([Binder], Maybe Guard, Value)]
219+ -- |
220+ -- A value with a type annotation
221+ --
74222 | TypedValue Bool Value Type
223+ -- |
224+ -- A do-notation block
225+ --
75226 | Do [DoNotationElement]
227+ -- |
228+ -- A placeholder for a type class dictionary to be inserted later. At the end of type checking, these
229+ -- placeholders will be replaced with actual expressions representing type classes dictionaries which
230+ -- can be evaluated at runtime. The constructor arguments represent (in order): the type class name and
231+ -- instance type, and the type class dictionaries in scope.
232+ --
76233 | TypeClassDictionary (Qualified ProperName, Type) [TypeClassDictionaryInScope] deriving (Show, Data, Typeable)
77234
235+-- |
236+-- The type of a type class dictionary
237+--
78238data TypeClassDictionaryType
239+ -- |
240+ -- A regular type class dictionary
241+ --
79242 = TCDRegular
243+ -- |
244+ -- A type class dictionary which is an alias for an imported dictionary from another module
245+ --
80246 | TCDAlias (Qualified Ident) deriving (Show, Eq, Data, Typeable)
81247
248+-- |
249+-- Data representing a type class dictionary which is in scope
250+--
82251data TypeClassDictionaryInScope
83− = TypeClassDictionaryInScope { tcdName :: Qualified Ident
84− , tcdClassName :: Qualified ProperName
85− , tcdInstanceType :: Type
86− , tcdDependencies :: Maybe [(Qualified ProperName, Type)]
87− , tcdType :: TypeClassDictionaryType
88− } deriving (Show, Data, Typeable)
252+ = TypeClassDictionaryInScope {
253+ -- |
254+ -- The identifier with which the dictionary can be accessed at runtime
255+ --
256+ tcdName :: Qualified Ident
257+ -- |
258+ -- The name of the type class to which this type class instance applies
259+ --
260+ , tcdClassName :: Qualified ProperName
261+ -- |
262+ -- The type to which this type class instance applies
263+ --
264+ , tcdInstanceType :: Type
265+ -- |
266+ -- Type class dependencies which must be satisfied to construct this dictionary
267+ --
268+ , tcdDependencies :: Maybe [(Qualified ProperName, Type)]
269+ -- |
270+ -- The type of this dictionary
271+ --
272+ , tcdType :: TypeClassDictionaryType
273+ } deriving (Show, Data, Typeable)
89274
275+-- |
276+-- A statement in a do-notation block
277+--
90278data DoNotationElement
279+ -- |
280+ -- A monadic value without a binder
281+ --
91282 = DoNotationValue Value
283+ -- |
284+ -- A monadic value with a binder
285+ --
92286 | DoNotationBind Binder Value
287+ -- |
288+ -- A let statement, i.e. a pure value with a binder
289+ --
93290 | DoNotationLet Binder Value deriving (Show, Data, Typeable)
94291
292+-- |
293+-- Data type for statements which can appear inside a @Block@ expression
294+--
95295data Statement
296+ -- |
297+ -- A variable introduction and initial assignment
298+ --
96299 = VariableIntroduction Ident Value
300+ -- |
301+ -- A variable reassignment
302+ --
97303 | Assignment Ident Value
304+ -- |
305+ -- A while loop
306+ --
98307 | While Value [Statement]
308+ -- |
309+ -- A for loop
310+ --
99311 | For Ident Value Value [Statement]
312+ -- |
313+ -- An if-then-else statement
314+ --
100315 | If IfStatement
316+ -- |
317+ -- A return statement
318+ --
101319 | Return Value deriving (Show, Data, Typeable)
102320
103−data IfStatement = IfStatement Value [Statement] (Maybe ElseStatement) deriving (Show, Data, Typeable)
321+-- |
322+-- Data type for if-statements
323+--
324+data IfStatement
325+ -- |
326+ -- An if statement. Arguments are (in order): boolean condition, true branch, optional else branch.
327+ --
328+ = IfStatement Value [Statement] (Maybe ElseStatement) deriving (Show, Data, Typeable)
104329
330+-- |
331+-- Data type for the else branch in an if-statement
332+--
105333data ElseStatement
334+ -- |
335+ -- An else branch
336+ --
106337 = Else [Statement]
338+ -- |
339+ -- An else-if branch
340+ --
107341 | ElseIf IfStatement deriving (Show, Data, Typeable)
108342
343+-- |
344+-- Data type for binders
345+--
109346data Binder
347+ -- |
348+ -- Wildcard binder
349+ --
110350 = NullBinder
351+ -- |
352+ -- A binder which matches a boolean literal
353+ --
111354 | BooleanBinder Bool
355+ -- |
356+ -- A binder which matches a string literal
357+ --
112358 | StringBinder String
359+ -- |
360+ -- A binder which matches a numeric literal
361+ --
113362 | NumberBinder (Either Integer Double)
363+ -- |
364+ -- A binder which binds an identifier
365+ --
114366 | VarBinder Ident
367+ -- |
368+ -- A binder which matches a data constructor with no argument
369+ --
115370 | NullaryBinder (Qualified ProperName)
371+ -- |
372+ -- A binder which matches a data constructor with one argument
373+ --
116374 | UnaryBinder (Qualified ProperName) Binder
375+ -- |
376+ -- A binder which matches a record and binds its properties
377+ --
117378 | ObjectBinder [(String, Binder)]
379+ -- |
380+ -- A binder which matches an array and binds its elements
381+ --
118382 | ArrayBinder [Binder]
383+ -- |
384+ -- A binder which matches an array and binds its head and tail
385+ --
119386 | ConsBinder Binder Binder
387+ -- |
388+ -- A binder which binds its input to an identifier
389+ --
120390 | NamedBinder Ident Binder deriving (Show, Data, Typeable)