git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Finally get indentation working
eec09d8Phil Freeman
PureScript.cabal+2−4
@@ -14,8 +14,7 @@ data-dir: ""
14
14
15library
15library
16 build-depends: base -any, syb -any, cmdtheline -any,
16 build-depends: base -any, syb -any, cmdtheline -any,
17− containers -any, mtl -any, parsec -any, utf8-string -any,
17+ containers -any, mtl -any, parsec -any, utf8-string -any
18− indents -any
19 exposed-modules: PureScript
18 exposed-modules: PureScript
20 exposed: True
19 exposed: True
21 buildable: True
20 buildable: True
@@ -32,8 +31,7 @@ library
32
31
33executable psc
32executable psc
34 build-depends: base -any, cmdtheline -any, containers -any,
33 build-depends: base -any, cmdtheline -any, containers -any,
35− mtl -any, parsec -any, utf8-string -any,
34+ mtl -any, parsec -any, utf8-string -any
36− indents -any
37 main-is: Main.hs
35 main-is: Main.hs
38 buildable: True
36 buildable: True
39 hs-source-dirs: src
37 hs-source-dirs: src
examples/Arrays.ps−1
@@ -11,4 +11,3 @@ data Tree = One Number | Some [Tree]
11test3 = \tree, sum -> case tree of
11test3 = \tree, sum -> case tree of
12 One n -> n
12 One n -> n
13 Some [n1, n2 : rest] -> test3(n1, sum) * 10 + test3(n2, sum) * 5 + sum(rest)
13 Some [n1, n2 : rest] -> test3(n1, sum) * 10 + test3(n2, sum) * 5 + sum(rest)
14−
examples/Assign.ps+5−7
@@ -1,7 +1,5 @@
1−test = \ -> {
1+test = \ -> do
2− var x = [];
2+ var x = []
3− for (var i = 0; i < 10; i = i + 1) {
3+ for (var i = 0; i < 10; i = i + 1):
4− x[i] = i;
4+ x[i] = i
5− }
6− return x;
5+ return x
7− }
examples/IfThenElse.psnew file+24
@@ -0,0 +1,24 @@
1+testIf = do
2+ var x = 0
3+ if x == 0:
4+ x = x + 1
5+ return x
6+
7+testIfElse = do
8+ var x = 0
9+ if x == 0:
10+ x = x + 1
11+ else:
12+ x = x - 1
13+ return x
14+
15+testIfElseIf = \x -> do
16+ var y = x
17+ while y > 1:
18+ if y % 3 == 0:
19+ y = y / 3
20+ else if y % 3 == 1:
21+ y = (y - 1) % 3
22+ else:
23+ y = y * 4 + 1
24+ return y
examples/List.ps+1
@@ -19,3 +19,4 @@ concat = \l1 -> \l2 -> case l1 of
19flatten = \xss -> case xss of
19flatten = \xss -> case xss of
20 Nil -> Nil
20 Nil -> Nil
21 Cons cons -> concat(cons.head)(flatten(cons.tail))
21 Cons cons -> concat(cons.head)(flatten(cons.tail))
22+
examples/TypeDecl.ps+5−7
@@ -5,10 +5,8 @@ k :: (String) -> (Number) -> String
5k = \x -> \y -> x
5k = \x -> \y -> x
6
6
7iterate :: forall a. (Number) -> ((a) -> a) -> (a) -> a
7iterate :: forall a. (Number) -> ((a) -> a) -> (a) -> a
8−iterate = \n -> \f -> \a -> {
8+iterate = \n -> \f -> \a -> do
9− var result = a;
9+ var result = a
10− for (var i = 0; i < n; i = i + 1) {
10+ for (var i = 0; i < n; i = i + 1):
11− result = f(result);
11+ result = f(result)
12− }
13− return result;
12+ return result
14− }
examples/TypeSynonyms.ps+4−5
@@ -6,9 +6,8 @@ type Lens a b =
6composeLenses :: forall a b c. (Lens a b) -> (Lens b c) -> Lens a c
6composeLenses :: forall a b c. (Lens a b) -> (Lens b c) -> Lens a c
7composeLenses = \l1 -> \l2 ->
7composeLenses = \l1 -> \l2 ->
8 { get: \a -> (l2.get)((l1.get)(a))
8 { get: \a -> (l2.get)((l1.get)(a))
9− , set: \a -> \c -> {
9+ , set: \a -> \c -> do
10− var b = (l1.get)(a);
10+ var b = (l1.get)(a)
11− var b1 = (l2.set)(b)(c);
11+ var b1 = (l2.set)(b)(c)
12− return (l1.set)(a)(b1);
12+ return (l1.set)(a)(b1)
13− }
14 }
13 }
src/Main.hs+2−1
@@ -20,13 +20,14 @@ import Data.List (intercalate)
20import System.Console.CmdTheLine
20import System.Console.CmdTheLine
21import Control.Applicative
21import Control.Applicative
22import System.Exit (exitSuccess, exitFailure)
22import System.Exit (exitSuccess, exitFailure)
23+import qualified Text.Parsec as P
23import qualified System.IO.UTF8 as U
24import qualified System.IO.UTF8 as U
24import qualified Data.Map as M
25import qualified Data.Map as M
25
26
26compile :: [FilePath] -> Maybe FilePath -> Maybe FilePath -> IO ()
27compile :: [FilePath] -> Maybe FilePath -> Maybe FilePath -> IO ()
27compile inputFiles outputFile externsFile = do
28compile inputFiles outputFile externsFile = do
28 input <- fmap concat $ mapM U.readFile inputFiles
29 input <- fmap concat $ mapM U.readFile inputFiles
29− let ast = parseDeclarations input
30+ let ast = runIndentParser 0 parseDeclarations input
30 case ast of
31 case ast of
31 Left err -> do
32 Left err -> do
32 U.print err
33 U.print err
src/PureScript/CodeGen/JS.hs+13−6
@@ -48,7 +48,7 @@ declToJs _ = Nothing
48literals :: Pattern Value String
48literals :: Pattern Value String
49literals = Pattern $ A.Kleisli match
49literals = Pattern $ A.Kleisli match
50 where
50 where
51− match (NumericLiteral n) = Just n
51+ match (NumericLiteral n) = Just $ either show show n
52 match (StringLiteral s) = Just $ show s
52 match (StringLiteral s) = Just $ show s
53 match (BooleanLiteral True) = Just "true"
53 match (BooleanLiteral True) = Just "true"
54 match (BooleanLiteral False) = Just "false"
54 match (BooleanLiteral False) = Just "false"
@@ -177,7 +177,7 @@ binderToJs :: String -> String -> Binder -> Gen String
177binderToJs varName done (StringBinder str) =
177binderToJs varName done (StringBinder str) =
178 return $ "if (" ++ varName ++ " === \"" ++ str ++ "\") {" ++ done ++ " }"
178 return $ "if (" ++ varName ++ " === \"" ++ str ++ "\") {" ++ done ++ " }"
179binderToJs varName done (NumberBinder num) =
179binderToJs varName done (NumberBinder num) =
180− return $ "if (" ++ varName ++ " === \"" ++ num ++ "\") {" ++ done ++ " }"
180+ return $ "if (" ++ varName ++ " === \"" ++ either show show num ++ "\") {" ++ done ++ " }"
181binderToJs varName done (BooleanBinder True) =
181binderToJs varName done (BooleanBinder True) =
182 return $ "if (" ++ varName ++ ") {" ++ done ++ " }"
182 return $ "if (" ++ varName ++ ") {" ++ done ++ " }"
183binderToJs varName done (BooleanBinder False) =
183binderToJs varName done (BooleanBinder False) =
@@ -228,12 +228,19 @@ statementToJs (For (init, cond, done) sts) = "for (" ++
228 ++ "; " ++ valueToJs cond
228 ++ "; " ++ valueToJs cond
229 ++ "; " ++ statementToJs done
229 ++ "; " ++ statementToJs done
230 ++ ") {" ++ intercalate ";" (map statementToJs sts) ++ "}"
230 ++ ") {" ++ intercalate ";" (map statementToJs sts) ++ "}"
231−statementToJs (IfThenElse cond thens elses) = "if ("
231+statementToJs (If ifst) = ifStatementToJs ifst
232+statementToJs (Return value) = "return " ++ valueToJs value
233+
234+ifStatementToJs :: IfStatement -> String
235+ifStatementToJs (IfStatement cond thens elst) =
236+ "if ("
232 ++ valueToJs cond ++ ") {"
237 ++ valueToJs cond ++ ") {"
233 ++ intercalate ";" (map statementToJs thens) ++ "}"
238 ++ intercalate ";" (map statementToJs thens) ++ "}"
234− ++ flip (maybe "") elses (\sts ->
239+ ++ maybe "" elseStatementToJs elst
240+
241+elseStatementToJs :: ElseStatement -> String
235− " else {" ++ intercalate ";" (map statementToJs sts) ++ "}")
242+elseStatementToJs (Else sts) = " else {" ++ intercalate ";" (map statementToJs sts) ++ "}"
236−statementToJs (Return value) = "return " ++ valueToJs value
243+elseStatementToJs (ElseIf ifst) = " else " ++ ifStatementToJs ifst
237
244
238assignmentTargetToJs :: AssignmentTarget -> String
245assignmentTargetToJs :: AssignmentTarget -> String
239assignmentTargetToJs (AssignVariable ident) = identToJs ident
246assignmentTargetToJs (AssignVariable ident) = identToJs ident
src/PureScript/Parser.hs+2
@@ -13,11 +13,13 @@
13-----------------------------------------------------------------------------
13-----------------------------------------------------------------------------
14
14
15module PureScript.Parser (
15module PureScript.Parser (
16+ module PureScript.Parser.Common,
16 module PureScript.Parser.Types,
17 module PureScript.Parser.Types,
17 module PureScript.Parser.Values,
18 module PureScript.Parser.Values,
18 module PureScript.Parser.Declarations
19 module PureScript.Parser.Declarations
19) where
20) where
20
21
22+import PureScript.Parser.Common
21import PureScript.Parser.Types
23import PureScript.Parser.Types
22import PureScript.Parser.Values
24import PureScript.Parser.Values
23import PureScript.Parser.Declarations
25import PureScript.Parser.Declarations
src/PureScript/Parser/Common.hs+83−114
@@ -12,12 +12,17 @@
12--
12--
13-----------------------------------------------------------------------------
13-----------------------------------------------------------------------------
14
14
15+{-# LANGUAGE FlexibleContexts #-}
16+
15module PureScript.Parser.Common where
17module PureScript.Parser.Common where
16
18
19+import Data.Char (isSpace)
17import Control.Applicative
20import Control.Applicative
18import Control.Monad
21import Control.Monad
22+import Control.Monad.State
19import qualified Text.Parsec as P
23import qualified Text.Parsec as P
20−import qualified Text.Parsec.Indent as I
24+import qualified Text.Parsec.Pos as P
25+import qualified Text.Parsec.Token as PT
21
26
22import PureScript.Names
27import PureScript.Names
23
28
@@ -26,6 +31,7 @@ reservedNames = [ "case"
26 , "data"
31 , "data"
27 , "type"
32 , "type"
28 , "var"
33 , "var"
34+ , "val"
29 , "while"
35 , "while"
30 , "for"
36 , "for"
31 , "if"
37 , "if"
@@ -35,134 +41,73 @@ reservedNames = [ "case"
35 , "true"
41 , "true"
36 , "false"
42 , "false"
37 , "extern"
43 , "extern"
38− , "forall" ]
44+ , "forall"
45+ , "do" ]
39
46
40reservedOpNames :: [String]
47reservedOpNames :: [String]
41reservedOpNames = [ "!", "~", "-", "<=", ">=", "<", ">", "*", "/", "%", "++", "+", "<<", ">>>", ">>"
48reservedOpNames = [ "!", "~", "-", "<=", ">=", "<", ">", "*", "/", "%", "++", "+", "<<", ">>>", ">>"
42 , "==", "!=", "&", "^", "|", "&&", "||" ]
49 , "==", "!=", "&", "^", "|", "&&", "||" ]
43
50
44−identStart :: I.IndentParser String u Char
51+identStart :: P.Parsec String u Char
45identStart = P.lower <|> P.oneOf "_$"
52identStart = P.lower <|> P.oneOf "_$"
46
53
47−properNameStart :: I.IndentParser String u Char
54+properNameStart :: P.Parsec String u Char
48properNameStart = P.upper
55properNameStart = P.upper
49
56
50−identLetter :: I.IndentParser String u Char
57+identLetter :: P.Parsec String u Char
51identLetter = P.alphaNum <|> P.oneOf "_'"
58identLetter = P.alphaNum <|> P.oneOf "_'"
52
59
53−opStart :: I.IndentParser String u Char
60+opStart :: P.Parsec String u Char
54−opStart = P.oneOf ":!#$%&*+/<=>?@^|-~"
61+opStart = P.oneOf "!#$%&*+/<=>?@^|-~"
55
62
56−opLetter :: I.IndentParser String u Char
63+opLetter :: P.Parsec String u Char
57opLetter = P.oneOf ":#$%&*+./<=>?@^|"
64opLetter = P.oneOf ":#$%&*+./<=>?@^|"
58
65
59−whiteSpace :: I.IndentParser String u ()
66+langDef = PT.LanguageDef
60−whiteSpace = P.skipMany $ P.choice
67+ { PT.reservedNames = reservedNames
61− [ P.oneOf " \t" >> return ()
68+ , PT.reservedOpNames = reservedOpNames
62− , P.try $ P.skipMany1 (P.oneOf " \t\r\n") >> I.indented
69+ , PT.commentStart = "{-"
63− , P.try lineComment
70+ , PT.commentEnd = "-}"
64− , P.try blockComment ]
71+ , PT.commentLine = "--"
65−
72+ , PT.nestedComments = True
66−unindentedBlock :: I.IndentParser String u a -> I.IndentParser String u [a]
73+ , PT.identStart = identStart
67−unindentedBlock p = I.block $ I.withPos (p <* P.skipMany (P.oneOf "\r\n"))
74+ , PT.identLetter = identLetter
68−
75+ , PT.opStart = opStart
69−indentedBlock :: I.IndentParser String u a -> I.IndentParser String u [a]
76+ , PT.opLetter = opLetter
70−indentedBlock p = I.block $ I.withPos (p <* P.skipMany (P.oneOf " \t\r\n"))
77+ , PT.caseSensitive = True
71−
78+ }
72−lineComment :: I.IndentParser String u ()
79+
73−lineComment = do
80+tokenParser = PT.makeTokenParser langDef
74− P.string "--"
81+
75− P.skipMany $ P.satisfy (/= '\n')
82+lexeme = PT.lexeme tokenParser
76− return ()
83+identifier = PT.identifier tokenParser
77−
84+reserved = PT.reserved tokenParser
78−blockComment :: I.IndentParser String u ()
85+reservedOp = PT.reservedOp tokenParser
79−blockComment = do
86+operator = PT.operator tokenParser
80− P.string "{--"
87+stringLiteral = PT.stringLiteral tokenParser
81− P.manyTill P.anyChar $ P.try $ P.string "--}"
88+whiteSpace = PT.whiteSpace tokenParser
82− return ()
89+parens = PT.parens tokenParser
83−
90+braces = PT.braces tokenParser
84−lexeme :: I.IndentParser String u a -> I.IndentParser String u a
91+angles = PT.angles tokenParser
85−lexeme p = p <* whiteSpace
92+squares = PT.squares tokenParser
86−
93+semi = PT.semi tokenParser
87−identifier :: I.IndentParser String u String
94+comma = PT.comma tokenParser
88−identifier = lexeme $ do
95+colon = PT.colon tokenParser
89− name <- (:) <$> identStart <*> P.many identLetter
96+dot = PT.dot tokenParser
90− when (name `elem` reservedNames) $ P.unexpected ("reserved word " ++ show name)
97+semiSep = PT.semiSep tokenParser
91− return name
98+semiSep1 = PT.semiSep1 tokenParser
92−
99+commaSep = PT.commaSep tokenParser
93−properName :: I.IndentParser String u String
100+commaSep1 = PT.commaSep1 tokenParser
94−properName = lexeme $ do
101+
95− (:) <$> properNameStart <*> many identLetter P.<?> "name"
96−
97−reserved :: String -> I.IndentParser String u String
98−reserved name = lexeme $ P.string name <* P.notFollowedBy identLetter
99−
100−reservedOp :: String -> I.IndentParser String u String
101−reservedOp name = lexeme $ P.string name <* P.notFollowedBy opLetter
102−
103−operator :: I.IndentParser String u String
104−operator = lexeme $ do
105− name <- (:) <$> opStart <*> P.many opLetter
106− when (name `elem` reservedOpNames) $ P.unexpected ("reserved operator " ++ show name)
107− return name
108−
109−stringLiteral :: I.IndentParser String u String
110−stringLiteral = lexeme $ P.between (P.char '"') (P.char '"') (P.many (P.noneOf "\""))
111−
112−number :: I.IndentParser String u String
113−number = do
114− intPart <- P.many1 P.digit
115− fracPart <- P.option "" $ (:) <$> P.char '.' <*> P.many1 P.digit
116− expPart <- P.option "" $ (:) <$> P.oneOf "eE" <*> P.many1 P.digit
117− return $ intPart ++ fracPart ++ expPart
118−
119−signedNumber :: I.IndentParser String u String
120−signedNumber = do
121− s <- P.optionMaybe $ P.oneOf "-+"
122− n <- number
123− return $ maybe id (:) s n
124−
125−unsignedNumber :: I.IndentParser String u String
126−unsignedNumber = lexeme number
127−
128−semi :: I.IndentParser String u Char
129−semi = lexeme $ P.char ';'
130−
131−comma :: I.IndentParser String u Char
132−comma = lexeme $ P.char ','
133−
134−colon :: I.IndentParser String u Char
135−colon = lexeme $ P.char ':'
136−
137−dot :: I.IndentParser String u Char
138−dot = lexeme $ P.char '.'
139−
140−tick :: I.IndentParser String u Char
102+tick :: P.Parsec String u Char
141tick = lexeme $ P.char '`'
103tick = lexeme $ P.char '`'
142
104
143−semiSep :: I.IndentParser String u a -> I.IndentParser String u [a]
105+properName :: P.Parsec String u String
144−semiSep p = P.sepBy p semi
106+properName = lexeme $ P.try ((:) <$> P.upper <*> many (PT.identLetter langDef) P.<?> "name")
145−
146−semiSep1 :: I.IndentParser String u a -> I.IndentParser String u [a]
147−semiSep1 p = P.sepBy1 p semi
148
107
149−commaSep :: I.IndentParser String u a -> I.IndentParser String u [a]
108+integerOrFloat :: P.Parsec String u (Either Integer Double)
150−commaSep p = P.sepBy p comma
109+integerOrFloat = Left <$> P.try (PT.integer tokenParser) <|>
151−
110+ Right <$> P.try (PT.float tokenParser)
152−commaSep1 :: I.IndentParser String u a -> I.IndentParser String u [a]
153−commaSep1 p = P.sepBy1 p comma
154−
155−parens :: I.IndentParser String u a -> I.IndentParser String u a
156−parens p = lexeme (P.char '(') *> lexeme p <* lexeme (P.char ')')
157−
158−braces :: I.IndentParser String u a -> I.IndentParser String u a
159−braces p = lexeme (P.char '{') *> lexeme p <* lexeme (P.char '}')
160−
161−angles :: I.IndentParser String u a -> I.IndentParser String u a
162−angles p = lexeme (P.char '<') *> lexeme p <* lexeme (P.char '>')
163−
164−squares :: I.IndentParser String u a -> I.IndentParser String u a
165−squares p = lexeme (P.char '[') *> lexeme p <* lexeme (P.char ']')
166
111
167augment :: 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
112augment :: 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
168augment p q f = (flip $ maybe id $ flip f) <$> p <*> P.optionMaybe q
113augment p q f = (flip $ maybe id $ flip f) <$> p <*> P.optionMaybe q
@@ -173,8 +118,32 @@ fold first more combine = do
173 bs <- P.many more
118 bs <- P.many more
174 return $ foldl combine a bs
119 return $ foldl combine a bs
175
120
176−parseIdent :: I.IndentParser String () Ident
121+parseIdent :: P.Parsec String u Ident
177parseIdent = (Ident <$> identifier) <|> (Op <$> parens operator)
122parseIdent = (Ident <$> identifier) <|> (Op <$> parens operator)
178
123
179−parseIdentInfix :: I.IndentParser String () Ident
124+parseIdentInfix :: P.Parsec String u Ident
180parseIdentInfix = (Ident <$> P.between tick tick identifier) <|> (Op <$> operator)
125parseIdentInfix = (Ident <$> P.between tick tick identifier) <|> (Op <$> operator)
126+
127+mark :: P.Parsec String P.Column a -> P.Parsec String P.Column a
128+mark p = do
129+ current <- P.getState
130+ pos <- P.sourceColumn <$> P.getPosition
131+ P.putState pos
132+ a <- p
133+ P.putState current
134+ return a
135+
136+checkIndentation :: (P.Column -> P.Column -> Bool) -> P.Parsec String P.Column ()
137+checkIndentation rel = (do
138+ col <- P.sourceColumn <$> P.getPosition
139+ current <- P.getState
140+ guard $ col `rel` current) <|> P.parserFail "Indentation check"
141+
142+indented :: P.Parsec String P.Column ()
143+indented = checkIndentation (>)
144+
145+same :: P.Parsec String P.Column ()
146+same = checkIndentation (==)
147+
148+runIndentParser :: P.Column -> P.Parsec String P.Column a -> String -> Either P.ParseError a
149+runIndentParser col p = P.runParser p 0 ""
src/PureScript/Parser/Declarations.hs+25−21
@@ -26,7 +26,6 @@ import Control.Arrow (Arrow(..))
26import Control.Monad.State
26import Control.Monad.State
27import qualified Text.Parsec as P
27import qualified Text.Parsec as P
28import qualified Text.Parsec.Pos as P
28import qualified Text.Parsec.Pos as P
29−import qualified Text.Parsec.Indent as I
30
29
31import PureScript.Values
30import PureScript.Values
32import PureScript.Types
31import PureScript.Types
@@ -35,28 +34,37 @@ import PureScript.Declarations
35import PureScript.Parser.Values
34import PureScript.Parser.Values
36import PureScript.Parser.Types
35import PureScript.Parser.Types
37
36
38−parseDataDeclaration :: I.IndentParser String () Declaration
37+parseDataDeclaration :: P.Parsec String P.Column Declaration
39parseDataDeclaration = do
38parseDataDeclaration = do
40 reserved "data"
39 reserved "data"
41− name <- properName
40+ name <- indented *> properName
42− tyArgs <- many identifier
41+ tyArgs <- many (indented *> identifier)
43− lexeme $ P.char '='
42+ lexeme $ indented *> P.char '='
44− ctors <- P.sepBy1 ((,) <$> properName <*> P.optionMaybe parseType) (lexeme $ P.char '|')
43+ ctors <- P.sepBy1 ((,) <$> (indented *> properName) <*> P.optionMaybe parseType) (lexeme $ indented *> P.char '|')
45 return $ DataDeclaration name tyArgs ctors
44 return $ DataDeclaration name tyArgs ctors
46
45
47−parseTypeDeclaration :: I.IndentParser String () Declaration
46+parseTypeDeclaration :: P.Parsec String P.Column Declaration
47+parseTypeDeclaration =
48−parseTypeDeclaration = TypeDeclaration <$> parseIdent <*> (lexeme (P.string "::") *> parsePolyType)
48+ TypeDeclaration <$> parseIdent
49+ <*> (lexeme (indented *> P.string "::") *> parsePolyType)
49
50
50−parseTypeSynonymDeclaration :: I.IndentParser String () Declaration
51+parseTypeSynonymDeclaration :: P.Parsec String P.Column Declaration
52+parseTypeSynonymDeclaration =
51−parseTypeSynonymDeclaration = TypeSynonymDeclaration <$> (reserved "type" *> properName) <*> many identifier <*> (lexeme (P.char '=') *> parseType)
53+ TypeSynonymDeclaration <$> (reserved "type" *> indented *> properName)
54+ <*> many (indented *> identifier)
55+ <*> (lexeme (indented *> P.char '=') *> parseType)
52
56
53−parseValueDeclaration :: I.IndentParser String () Declaration
57+parseValueDeclaration :: P.Parsec String P.Column Declaration
58+parseValueDeclaration =
54−parseValueDeclaration = ValueDeclaration <$> parseIdent <*> (lexeme (P.char '=') *> parseValue)
59+ ValueDeclaration <$> parseIdent
60+ <*> (lexeme (indented *> P.char '=') *> parseValue)
55
61
56−parseExternDeclaration :: I.IndentParser String () Declaration
62+parseExternDeclaration :: P.Parsec String P.Column Declaration
63+parseExternDeclaration =
57−parseExternDeclaration = ExternDeclaration <$> (reserved "extern" *> parseIdent) <*> (lexeme (P.string "::") *> parsePolyType)
64+ ExternDeclaration <$> (reserved "extern" *> indented *> parseIdent)
65+ <*> (lexeme (indented *> P.string "::") *> parsePolyType)
58
66
59−parseDeclaration :: I.IndentParser String () Declaration
67+parseDeclaration :: P.Parsec String P.Column Declaration
60parseDeclaration = P.choice $ map P.try
68parseDeclaration = P.choice $ map P.try
61 [ parseDataDeclaration
69 [ parseDataDeclaration
62 , parseTypeDeclaration
70 , parseTypeDeclaration
@@ -64,9 +72,5 @@ parseDeclaration = P.choice $ map P.try
64 , parseValueDeclaration
72 , parseValueDeclaration
65 , parseExternDeclaration ]
73 , parseExternDeclaration ]
66
74
67−parseManyDeclarations :: I.IndentParser String () [Declaration]
75+parseDeclarations :: P.Parsec String P.Column [Declaration]
68−parseManyDeclarations = I.withPos $ unindentedBlock parseDeclaration
76+parseDeclarations = whiteSpace *> mark (same *> P.many parseDeclaration) <* P.eof
69−
70−parseDeclarations :: String -> Either P.ParseError [Declaration]
71−parseDeclarations = flip evalState (P.initialPos "Declarations") . P.runPT (parseManyDeclarations <* P.eof) () "Declarations"
72−
src/PureScript/Parser/Types.hs+20−21
@@ -22,39 +22,38 @@ import PureScript.Types
22import PureScript.Parser.Common
22import PureScript.Parser.Common
23import Control.Applicative
23import Control.Applicative
24import qualified Text.Parsec as P
24import qualified Text.Parsec as P
25−import qualified Text.Parsec.Indent as I
26import Control.Arrow (Arrow(..))
25import Control.Arrow (Arrow(..))
27
26
28−parseNumber :: I.IndentParser String () Type
27+parseNumber :: P.Parsec String P.Column Type
29parseNumber = const Number <$> P.string "Number"
28parseNumber = const Number <$> P.string "Number"
30
29
31−parseString :: I.IndentParser String () Type
30+parseString :: P.Parsec String P.Column Type
32parseString = const String <$> P.string "String"
31parseString = const String <$> P.string "String"
33
32
34−parseBoolean :: I.IndentParser String () Type
33+parseBoolean :: P.Parsec String P.Column Type
35parseBoolean = const Boolean <$> P.string "Boolean"
34parseBoolean = const Boolean <$> P.string "Boolean"
36
35
37−parseArray :: I.IndentParser String () Type
36+parseArray :: P.Parsec String P.Column Type
38parseArray = squares $ Array <$> parseType
37parseArray = squares $ Array <$> parseType
39
38
40−parseObject :: I.IndentParser String () Type
39+parseObject :: P.Parsec String P.Column Type
41parseObject = braces $ Object <$> parseRow
40parseObject = braces $ Object <$> parseRow
42
41
43−parseFunction :: I.IndentParser String () Type
42+parseFunction :: P.Parsec String P.Column Type
44parseFunction = do
43parseFunction = do
45 args <- lexeme $ parens $ commaSep parseType
44 args <- lexeme $ parens $ commaSep parseType
46 lexeme $ P.string "->"
45 lexeme $ P.string "->"
47 resultType <- parseType
46 resultType <- parseType
48 return $ Function args resultType
47 return $ Function args resultType
49
48
50−parseTypeVariable :: I.IndentParser String () Type
49+parseTypeVariable :: P.Parsec String P.Column Type
51parseTypeVariable = TypeVar <$> identifier
50parseTypeVariable = TypeVar <$> identifier
52
51
53−parseTypeConstructor :: I.IndentParser String () Type
52+parseTypeConstructor :: P.Parsec String P.Column Type
54parseTypeConstructor = TypeConstructor <$> properName
53parseTypeConstructor = TypeConstructor <$> properName
55
54
56−parseTypeAtom :: I.IndentParser String () Type
55+parseTypeAtom :: P.Parsec String P.Column Type
57−parseTypeAtom = P.choice $ map P.try
56+parseTypeAtom = indented *> P.choice (map P.try
58 [ parseNumber
57 [ parseNumber
59 , parseString
58 , parseString
60 , parseBoolean
59 , parseBoolean
@@ -63,23 +62,23 @@ parseTypeAtom = P.choice $ map P.try
63 , parseFunction
62 , parseFunction
64 , parseTypeVariable
63 , parseTypeVariable
65 , parseTypeConstructor
64 , parseTypeConstructor
66− , parens parseType ]
65+ , parens parseType ])
67
66
68−parsePolyType :: I.IndentParser String () PolyType
67+parsePolyType :: P.Parsec String P.Column PolyType
69−parsePolyType = PolyType <$> (P.option [] (reserved "forall" *> many identifier <* dot))
68+parsePolyType = PolyType <$> (P.option [] (indented *> reserved "forall" *> many (indented *> identifier) <* indented <* dot))
70 <*> parseType
69 <*> parseType
71
70
72−parseType :: I.IndentParser String () Type
71+parseType :: P.Parsec String P.Column Type
73parseType = fold (lexeme parseTypeAtom) (lexeme parseTypeAtom) TypeApp
72parseType = fold (lexeme parseTypeAtom) (lexeme parseTypeAtom) TypeApp
74
73
75−parseNameAndType :: I.IndentParser String () (String, Type)
74+parseNameAndType :: P.Parsec String P.Column (String, Type)
76−parseNameAndType = (,) <$> (identifier <* lexeme (P.string "::")) <*> parseType
75+parseNameAndType = (,) <$> (indented *> identifier <* indented <* lexeme (P.string "::")) <*> parseType
77
76
78−parseRowEnding :: I.IndentParser String () Row
77+parseRowEnding :: P.Parsec String P.Column Row
79−parseRowEnding = P.option REmpty (RowVar <$> (lexeme (P.char '|') *> identifier))
78+parseRowEnding = P.option REmpty (RowVar <$> (lexeme (indented *> P.char '|') *> indented *> identifier))
80
79
81−parseRow :: I.IndentParser String () Row
80+parseRow :: P.Parsec String P.Column Row
82−parseRow = fromList <$> semiSep parseNameAndType <*> parseRowEnding
81+parseRow = fromList <$> (parseNameAndType `P.sepBy` (indented *> semi)) <*> parseRowEnding
83 where
82 where
84 fromList :: [(String, Type)] -> Row -> Row
83 fromList :: [(String, Type)] -> Row -> Row
85 fromList [] r = r
84 fromList [] r = r
src/PureScript/Parser/Values.hs+119−117
@@ -21,68 +21,67 @@ import PureScript.Values
21import qualified PureScript.Parser.Common as C
21import qualified PureScript.Parser.Common as C
22import Control.Applicative
22import Control.Applicative
23import qualified Text.Parsec as P
23import qualified Text.Parsec as P
24−import qualified Text.Parsec.Indent as I
25import Text.Parsec.Expr
24import Text.Parsec.Expr
26import Control.Monad
25import Control.Monad
27import Control.Arrow (Arrow(..))
26import Control.Arrow (Arrow(..))
28import PureScript.Parser.Types
27import PureScript.Parser.Types
29import PureScript.Types
28import PureScript.Types
30
29
31−booleanLiteral :: I.IndentParser String () Bool
30+booleanLiteral :: P.Parsec String P.Column Bool
32booleanLiteral = (C.reserved "true" >> return True) P.<|> (C.reserved "false" >> return False)
31booleanLiteral = (C.reserved "true" >> return True) P.<|> (C.reserved "false" >> return False)
33
32
34−parseNumericLiteral :: I.IndentParser String () Value
33+parseNumericLiteral :: P.Parsec String P.Column Value
35−parseNumericLiteral = NumericLiteral <$> C.signedNumber
34+parseNumericLiteral = NumericLiteral <$> C.integerOrFloat
36
35
37−parseStringLiteral :: I.IndentParser String () Value
36+parseStringLiteral :: P.Parsec String P.Column Value
38parseStringLiteral = StringLiteral <$> C.stringLiteral
37parseStringLiteral = StringLiteral <$> C.stringLiteral
39
38
40−parseBooleanLiteral :: I.IndentParser String () Value
39+parseBooleanLiteral :: P.Parsec String P.Column Value
41parseBooleanLiteral = BooleanLiteral <$> booleanLiteral
40parseBooleanLiteral = BooleanLiteral <$> booleanLiteral
42
41
43−parseArrayLiteral :: I.IndentParser String () Value
42+parseArrayLiteral :: P.Parsec String P.Column Value
44−parseArrayLiteral = ArrayLiteral <$> (C.squares $ C.commaSep parseValue)
43+parseArrayLiteral = ArrayLiteral <$> (C.squares $ parseValue `P.sepBy` (C.indented *> C.comma))
45
44
46−parseObjectLiteral :: I.IndentParser String () Value
45+parseObjectLiteral :: P.Parsec String P.Column Value
47−parseObjectLiteral = ObjectLiteral <$> (C.braces $ C.commaSep parseIdentifierAndValue)
46+parseObjectLiteral = ObjectLiteral <$> (C.braces $ parseIdentifierAndValue `P.sepBy` (C.indented *> C.comma))
48
47
49−parseIdentifierAndValue :: I.IndentParser String () (String, Value)
48+parseIdentifierAndValue :: P.Parsec String P.Column (String, Value)
50−parseIdentifierAndValue = do
49+parseIdentifierAndValue = (,) <$> (C.indented *> C.identifier <* C.indented <* C.colon)
51− name <- C.lexeme C.identifier
52− C.colon
53− value <- parseValue
50+ <*> (C.indented *> parseValue)
54− return (name, value)
55
51
56−parseAbs :: I.IndentParser String () Value
52+parseAbs :: P.Parsec String P.Column Value
57parseAbs = do
53parseAbs = do
58 C.lexeme $ P.char '\\'
54 C.lexeme $ P.char '\\'
59− args <- C.commaSep C.parseIdent
55+ args <- (C.indented *> C.parseIdent) `P.sepBy` (C.indented *> C.comma)
60− C.lexeme $ P.string "->"
56+ C.lexeme $ C.indented *> P.string "->"
61 value <- parseValue
57 value <- parseValue
62 return $ Abs args value
58 return $ Abs args value
63
59
64−parseApp :: I.IndentParser String () Value
60+parseApp :: P.Parsec String P.Column Value
65parseApp = App <$> parseValue
61parseApp = App <$> parseValue
66− <*> (C.parens $ C.commaSep parseValue)
62+ <*> (C.indented *> C.parens (parseValue `P.sepBy` (C.indented *> C.comma)))
67
63
68−parseVar :: I.IndentParser String () Value
64+parseVar :: P.Parsec String P.Column Value
69parseVar = Var <$> C.parseIdent
65parseVar = Var <$> C.parseIdent
70
66
71−parseConstructor :: I.IndentParser String () Value
67+parseConstructor :: P.Parsec String P.Column Value
72parseConstructor = Constructor <$> C.properName
68parseConstructor = Constructor <$> C.properName
73
69
74−parseCase :: I.IndentParser String () Value
70+parseCase :: P.Parsec String P.Column Value
75−parseCase = Case <$> P.between (C.reserved "case") (C.reserved "of") parseValue
71+parseCase = Case <$> (P.between (C.reserved "case") (C.indented *> C.reserved "of") parseValue)
76− <*> I.withPos (C.indentedBlock parseCaseAlternative)
72+ <*> (C.indented *> C.mark (P.many (C.same *> C.mark parseCaseAlternative)))
77
73
78−parseCaseAlternative :: I.IndentParser String () (Binder, Value)
74+parseCaseAlternative :: P.Parsec String P.Column (Binder, Value)
79parseCaseAlternative = (,) <$> (parseBinder <* C.lexeme (P.string "->")) <*> parseValue
75parseCaseAlternative = (,) <$> (parseBinder <* C.lexeme (P.string "->")) <*> parseValue
80
76
81−parseBlock :: I.IndentParser String () Value
77+parseBlock :: P.Parsec String P.Column Value
82−parseBlock = Block <$> (C.braces $ I.withPos $ C.indentedBlock $ parseStatement True)
78+parseBlock = Block <$> (C.reserved "do" *> parseManyStatements)
83
79
84−parseValueAtom :: I.IndentParser String () Value
80+parseManyStatements :: P.Parsec String P.Column [Statement]
81+parseManyStatements = C.indented *> (C.mark $ P.many $ C.same *> C.mark parseStatement)
82+
83+parseValueAtom :: P.Parsec String P.Column Value
85−parseValueAtom = P.choice $ map P.try
84+parseValueAtom = C.indented *> P.choice (map P.try
86 [ parseNumericLiteral
85 [ parseNumericLiteral
87 , parseStringLiteral
86 , parseStringLiteral
88 , parseBooleanLiteral
87 , parseBooleanLiteral
@@ -93,125 +92,128 @@ parseValueAtom = P.choice $ map P.try
93 , parseConstructor
92 , parseConstructor
94 , parseBlock
93 , parseBlock
95 , parseCase
94 , parseCase
96− , C.parens parseValue ]
95+ , C.parens parseValue ])
97
96
98−parseValue :: I.IndentParser String () Value
97+parseValue :: P.Parsec String P.Column Value
99parseValue = buildExpressionParser operators $ C.fold (C.lexeme typedValue) (C.lexeme funArgs) App
98parseValue = buildExpressionParser operators $ C.fold (C.lexeme typedValue) (C.lexeme funArgs) App
100 where
99 where
101 typedValue = C.augment parseValueAtom parseTypeAnnotation TypedValue
100 typedValue = C.augment parseValueAtom parseTypeAnnotation TypedValue
102− funArgs = C.parens $ C.commaSep parseValue
101+ funArgs = C.indented *> C.parens (parseValue `P.sepBy` (C.indented *> C.comma))
103− parseTypeAnnotation = C.lexeme (P.string "::") *> parsePolyType
102+ parseTypeAnnotation = P.try $ C.lexeme (C.indented *> P.string "::") *> parsePolyType
104− operators = [ [ Postfix $ Accessor <$> (C.dot *> C.identifier)
103+ operators = [ [ Postfix $ Accessor <$> (C.indented *> C.dot *> C.indented *> C.identifier)
105− , Postfix $ Indexer <$> C.squares parseValue ]
104+ , Postfix $ Indexer <$> (C.indented *> C.squares parseValue) ]
106− , [ Prefix $ C.lexeme (P.try $ C.reservedOp "!") >> return (Unary Not)
105+ , [ Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "!") >> return (Unary Not)
107− , Prefix $ C.lexeme (P.try $ C.reservedOp "~") >> return (Unary BitwiseNot)
106+ , Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "~") >> return (Unary BitwiseNot)
108− , Prefix $ C.lexeme (P.try $ C.reservedOp "-") >> return (Unary Negate) ]
107+ , Prefix $ C.lexeme (P.try $ C.indented *> C.reservedOp "-") >> return (Unary Negate) ]
109− , [ Infix (C.lexeme (P.try C.parseIdentInfix >>= \ident -> return $ \t1 t2 -> App (App (Var ident) [t1]) [t2])) AssocRight ]
108+ , [ Infix (C.lexeme (P.try (C.indented *> C.parseIdentInfix) >>= \ident -> return $ \t1 t2 -> App (App (Var ident) [t1]) [t2])) AssocRight ]
110− , [ Infix (C.lexeme (P.try $ C.reservedOp "<=") >> return (Binary LessThanOrEqualTo)) AssocRight
109+ , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "<=") >> return (Binary LessThanOrEqualTo)) AssocRight
111− , Infix (C.lexeme (P.try $ C.reservedOp ">=") >> return (Binary GreaterThanOrEqualTo)) AssocRight ]
110+ , Infix (C.lexeme (P.try $ C.indented *> C.reservedOp ">=") >> return (Binary GreaterThanOrEqualTo)) AssocRight ]
112− , [ Infix (C.lexeme (P.try $ C.reservedOp "<") >> return (Binary LessThan)) AssocRight
111+ , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "<") >> return (Binary LessThan)) AssocRight
113− , Infix (C.lexeme (P.try $ C.reservedOp ">") >> return (Binary GreaterThan)) AssocRight ]
112+ , Infix (C.lexeme (P.try $ C.indented *> C.reservedOp ">") >> return (Binary GreaterThan)) AssocRight ]
114− , [ Infix (C.lexeme (P.try $ C.reservedOp "*") >> return (Binary Multiply)) AssocRight
113+ , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "*") >> return (Binary Multiply)) AssocRight
115− , Infix (C.lexeme (P.try $ C.reservedOp "/") >> return (Binary Divide)) AssocRight
114+ , Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "/") >> return (Binary Divide)) AssocRight
116− , Infix (C.lexeme (P.try $ C.reservedOp "%") >> return (Binary Modulus)) AssocRight ]
115+ , Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "%") >> return (Binary Modulus)) AssocRight ]
117− , [ Infix (C.lexeme (P.try $ C.reservedOp "++") >> return (Binary Concat)) AssocRight
116+ , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "++") >> return (Binary Concat)) AssocRight
118− , Infix (C.lexeme (P.try $ C.reservedOp "+") >> return (Binary Add)) AssocRight
117+ , Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "+") >> return (Binary Add)) AssocRight
119− , Infix (C.lexeme (P.try $ C.reservedOp "-") >> return (Binary Subtract)) AssocRight ]
118+ , Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "-") >> return (Binary Subtract)) AssocRight ]
120− , [ Infix (C.lexeme (P.try $ C.reservedOp "<<") >> return (Binary ShiftLeft)) AssocRight
119+ , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "<<") >> return (Binary ShiftLeft)) AssocRight
121− , Infix (C.lexeme (P.try $ C.reservedOp ">>>") >> return (Binary ZeroFillShiftRight)) AssocRight
120+ , Infix (C.lexeme (P.try $ C.indented *> C.reservedOp ">>>") >> return (Binary ZeroFillShiftRight)) AssocRight
122− , Infix (C.lexeme (P.try $ C.reservedOp ">>") >> return (Binary ShiftRight)) AssocRight ]
121+ , Infix (C.lexeme (P.try $ C.indented *> C.reservedOp ">>") >> return (Binary ShiftRight)) AssocRight ]
123− , [ Infix (C.lexeme (P.try $ C.reservedOp "==") >> return (Binary EqualTo)) AssocRight
122+ , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "==") >> return (Binary EqualTo)) AssocRight
124− , Infix (C.lexeme (P.try $ C.reservedOp "!=") >> return (Binary NotEqualTo)) AssocRight ]
123+ , Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "!=") >> return (Binary NotEqualTo)) AssocRight ]
125− , [ Infix (C.lexeme (P.try $ C.reservedOp "&") >> return (Binary BitwiseAnd)) AssocRight ]
124+ , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "&") >> return (Binary BitwiseAnd)) AssocRight ]
126− , [ Infix (C.lexeme (P.try $ C.reservedOp "^") >> return (Binary BitwiseXor)) AssocRight ]
125+ , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "^") >> return (Binary BitwiseXor)) AssocRight ]
127− , [ Infix (C.lexeme (P.try $ C.reservedOp "|") >> return (Binary BitwiseOr)) AssocRight ]
126+ , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "|") >> return (Binary BitwiseOr)) AssocRight ]
128− , [ Infix (C.lexeme (P.try $ C.reservedOp "&&") >> return (Binary And)) AssocRight ]
127+ , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "&&") >> return (Binary And)) AssocRight ]
129− , [ Infix (C.lexeme (P.try $ C.reservedOp "||") >> return (Binary Or)) AssocRight ]
128+ , [ Infix (C.lexeme (P.try $ C.indented *> C.reservedOp "||") >> return (Binary Or)) AssocRight ]
130 ]
129 ]
131
130
132−parseVariableIntroduction :: Bool -> I.IndentParser String () Statement
131+parseVariableIntroduction :: P.Parsec String P.Column Statement
133−parseVariableIntroduction requireSemi = do
132+parseVariableIntroduction = do
134 C.reserved "var"
133 C.reserved "var"
135− name <- C.parseIdent
134+ name <- C.indented *> C.parseIdent
136− C.lexeme $ P.char '='
135+ C.lexeme $ C.indented *> P.char '='
137 value <- parseValue
136 value <- parseValue
138− when requireSemi (void C.semi)
139 return $ VariableIntroduction name value
137 return $ VariableIntroduction name value
140
138
141−parseAssignment :: Bool -> I.IndentParser String () (Statement)
139+parseAssignment :: P.Parsec String P.Column Statement
142−parseAssignment requireSemi = do
140+parseAssignment = do
143 tgt <- parseAssignmentTarget
141 tgt <- parseAssignmentTarget
144− C.lexeme $ P.char '='
142+ C.lexeme $ C.indented *> P.char '='
145 value <- parseValue
143 value <- parseValue
146− when requireSemi (void C.semi)
147 return $ Assignment tgt value
144 return $ Assignment tgt value
148
145
149−parseManyStatements :: I.IndentParser String () [Statement]
150−parseManyStatements = C.braces $ I.withPos $ C.indentedBlock $ parseStatement True
151−
152−parseWhile :: I.IndentParser String () Statement
146+parseWhile :: P.Parsec String P.Column Statement
153−parseWhile = While <$> (C.reserved "while" *> C.parens parseValue)
147+parseWhile = While <$> (C.reserved "while" *> C.indented *> parseValue <* C.indented <* C.colon)
154 <*> parseManyStatements
148 <*> parseManyStatements
155
149
156−parseFor :: I.IndentParser String () Statement
150+parseFor :: P.Parsec String P.Column Statement
157−parseFor = For <$> (C.reserved "for" *> C.parens forIntro)
151+parseFor = For <$> (C.reserved "for" *> C.indented *> C.parens forIntro <* C.indented <* C.colon)
158 <*> parseManyStatements
152 <*> parseManyStatements
159 where
153 where
160− forIntro = (,,) <$> parseStatement False
154+ forIntro = (,,) <$> (C.indented *> parseStatement)
161− <*> (C.semi *> parseValue)
155+ <*> (C.indented *> C.semi *> C.indented *> parseValue)
162− <*> (C.semi *> parseStatement False)
156+ <*> (C.indented *> C.semi *> C.indented *> parseStatement)
163−
157+
164−parseIfThenElse :: I.IndentParser String () Statement
158+parseIf :: P.Parsec String P.Column Statement
165−parseIfThenElse = IfThenElse
159+parseIf = If <$> parseIfStatement
160+
161+parseIfStatement :: P.Parsec String P.Column IfStatement
162+parseIfStatement =
166− <$> (C.reserved "if" *> C.parens parseValue)
163+ IfStatement <$> (C.reserved "if" *> C.indented *> parseValue <* C.indented <* C.colon)
167− <*> parseManyStatements
164+ <*> parseManyStatements
165+ <*> P.optionMaybe (C.same *> parseElseStatement)
166+
167+parseElseStatement :: P.Parsec String P.Column ElseStatement
168+parseElseStatement = C.reserved "else" >> (ElseIf <$> (C.indented *> parseIfStatement)
168− <*> P.optionMaybe (C.reserved "else" *> parseManyStatements)
169+ <|> Else <$> (C.indented *> C.colon *> parseManyStatements))
169−
170+
170−parseReturn :: Bool -> I.IndentParser String () Statement
171+parseReturn :: P.Parsec String P.Column Statement
171−parseReturn requireSemi = Return <$> (C.reserved "return" *> parseValue <* when requireSemi (void C.semi))
172+parseReturn = Return <$> (C.reserved "return" *> parseValue)
172−
173+
173−parseStatement :: Bool -> I.IndentParser String () Statement
174+parseStatement :: P.Parsec String P.Column Statement
174−parseStatement requireSemi = P.choice $ map P.try
175+parseStatement = P.choice (map P.try
175− [ parseVariableIntroduction requireSemi
176+ [ parseVariableIntroduction
176− , parseAssignment requireSemi
177+ , parseAssignment
177 , parseWhile
178 , parseWhile
178 , parseFor
179 , parseFor
179− , parseIfThenElse
180+ , parseIf
180− , parseReturn requireSemi ]
181+ , parseReturn ])
181
182
182−parseStringBinder :: I.IndentParser String () Binder
183+parseStringBinder :: P.Parsec String P.Column Binder
183parseStringBinder = StringBinder <$> C.stringLiteral
184parseStringBinder = StringBinder <$> C.stringLiteral
184
185
185−parseBooleanBinder :: I.IndentParser String () Binder
186+parseBooleanBinder :: P.Parsec String P.Column Binder
186parseBooleanBinder = BooleanBinder <$> booleanLiteral
187parseBooleanBinder = BooleanBinder <$> booleanLiteral
187
188
188−parseNumberBinder :: I.IndentParser String () Binder
189+parseNumberBinder :: P.Parsec String P.Column Binder
189−parseNumberBinder = NumberBinder <$> C.signedNumber
190+parseNumberBinder = NumberBinder <$> C.integerOrFloat
190
191
191−parseVarBinder :: I.IndentParser String () Binder
192+parseVarBinder :: P.Parsec String P.Column Binder
192parseVarBinder = VarBinder <$> C.parseIdent
193parseVarBinder = VarBinder <$> C.parseIdent
193
194
194−parseNullaryBinder :: I.IndentParser String () Binder
195+parseNullaryBinder :: P.Parsec String P.Column Binder
195parseNullaryBinder = NullaryBinder <$> C.lexeme C.properName
196parseNullaryBinder = NullaryBinder <$> C.lexeme C.properName
196
197
197−parseUnaryBinder :: I.IndentParser String () Binder
198+parseUnaryBinder :: P.Parsec String P.Column Binder
198−parseUnaryBinder = UnaryBinder <$> C.lexeme C.properName <*> parseBinder
199+parseUnaryBinder = UnaryBinder <$> C.lexeme C.properName <*> (C.indented *> parseBinder)
199
200
200−parseObjectBinder :: I.IndentParser String () Binder
201+parseObjectBinder :: P.Parsec String P.Column Binder
201−parseObjectBinder = ObjectBinder <$> C.braces (C.commaSep parseIdentifierAndBinder)
202+parseObjectBinder = ObjectBinder <$> C.braces ((C.indented *> parseIdentifierAndBinder) `P.sepBy` (C.indented *> C.comma))
202
203
203−parseArrayBinder :: I.IndentParser String () Binder
204+parseArrayBinder :: P.Parsec String P.Column Binder
204−parseArrayBinder = C.squares $ ArrayBinder <$> (C.commaSep parseBinder) <*> P.optionMaybe (C.colon *> parseBinder)
205+parseArrayBinder = C.squares $ ArrayBinder <$> ((C.indented *> parseBinder) `P.sepBy` (C.indented *> C.comma))
206+ <*> P.optionMaybe (C.indented *> C.colon *> C.indented *> parseBinder)
205
207
206−parseIdentifierAndBinder :: I.IndentParser String () (String, Binder)
208+parseIdentifierAndBinder :: P.Parsec String P.Column (String, Binder)
207parseIdentifierAndBinder = do
209parseIdentifierAndBinder = do
208 name <- C.lexeme C.identifier
210 name <- C.lexeme C.identifier
209− C.lexeme $ P.char '='
211+ C.lexeme $ C.indented *> P.char '='
210− binder <- parseBinder
212+ binder <- C.indented *> parseBinder
211 return (name, binder)
213 return (name, binder)
212
214
213−parseBinder :: I.IndentParser String () Binder
215+parseBinder :: P.Parsec String P.Column Binder
214−parseBinder = P.choice $ map P.try
216+parseBinder = P.choice (map P.try
215 [ parseStringBinder
217 [ parseStringBinder
216 , parseBooleanBinder
218 , parseBooleanBinder
217 , parseNumberBinder
219 , parseNumberBinder
@@ -220,10 +222,10 @@ parseBinder = P.choice $ map P.try
220 , parseNullaryBinder
222 , parseNullaryBinder
221 , parseObjectBinder
223 , parseObjectBinder
222 , parseArrayBinder
224 , parseArrayBinder
223− , C.parens parseBinder ]
225+ , C.parens parseBinder ])
224
226
225−parseAssignmentTarget :: I.IndentParser String () AssignmentTarget
227+parseAssignmentTarget :: P.Parsec String P.Column AssignmentTarget
226parseAssignmentTarget = buildExpressionParser operators (AssignVariable <$> C.parseIdent)
228parseAssignmentTarget = buildExpressionParser operators (AssignVariable <$> C.parseIdent)
227 where
229 where
228− operators = [ [ Postfix $ AssignArrayIndex <$> C.squares parseValue
230+ operators = [ [ Postfix $ AssignArrayIndex <$> (C.indented *> C.squares parseValue)
229− , Postfix $ AssignObjectProperty <$> (C.dot *> C.identifier) ] ]
231+ , Postfix $ AssignObjectProperty <$> (C.indented *> C.dot *> C.indented *> C.identifier) ] ]
src/PureScript/TypeChecker/Types.hs+22−9
@@ -383,15 +383,9 @@ typeConstraintsForStatement m mass ret (While val inner) = do
383 (cs1, n1) <- typeConstraints m val
383 (cs1, n1) <- typeConstraints m val
384 (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock m mass ret inner
384 (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock m mass ret inner
385 return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2, allCodePathsReturn, mass)
385 return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2, allCodePathsReturn, mass)
386−typeConstraintsForStatement m mass ret (IfThenElse val thens Nothing) = do
386+typeConstraintsForStatement m mass ret (If ifst) = do
387− (cs1, n1) <- typeConstraints m val
388− (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock m mass ret thens
387+ (cs, allCodePathsReturn) <- typeConstraintsForIfStatement m mass ret ifst
389− return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2, allCodePathsReturn, mass)
388+ return $ (cs, allCodePathsReturn, mass)
390−typeConstraintsForStatement m mass ret (IfThenElse val thens (Just elses)) = do
391− (cs1, n1) <- typeConstraints m val
392− (cs2, allCodePathsReturn1, _) <- typeConstraintsForBlock m mass ret thens
393− (cs3, allCodePathsReturn2, _) <- typeConstraintsForBlock m mass ret elses
394− return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2 ++ cs3, allCodePathsReturn1 && allCodePathsReturn2, mass)
395typeConstraintsForStatement m mass ret (For (init, cond, cont) inner) = do
389typeConstraintsForStatement m mass ret (For (init, cond, cont) inner) = do
396 (cs1, b1, mass1) <- typeConstraintsForStatement m mass ret init
390 (cs1, b1, mass1) <- typeConstraintsForStatement m mass ret init
397 guardWith "Cannot return from inside for" $ not b1
391 guardWith "Cannot return from inside for" $ not b1
@@ -404,6 +398,25 @@ typeConstraintsForStatement m mass ret (Return val) = do
404 (cs1, n1) <- typeConstraints (m `M.union` mass) val
398 (cs1, n1) <- typeConstraints (m `M.union` mass) val
405 return ((TypeConstraint n1 (TUnknown ret)) : cs1, True, mass)
399 return ((TypeConstraint n1 (TUnknown ret)) : cs1, True, mass)
406
400
401+typeConstraintsForIfStatement :: M.Map Ident Int -> M.Map Ident Int -> Int -> IfStatement -> Check ([TypeConstraint], Bool)
402+typeConstraintsForIfStatement m mass ret (IfStatement val thens Nothing) = do
403+ (cs1, n1) <- typeConstraints m val
404+ (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock m mass ret thens
405+ return ((TypeConstraint n1 Boolean) : cs1 ++ cs2, allCodePathsReturn)
406+typeConstraintsForIfStatement m mass ret (IfStatement val thens (Just elses)) = do
407+ (cs1, n1) <- typeConstraints m val
408+ (cs2, allCodePathsReturn1, _) <- typeConstraintsForBlock m mass ret thens
409+ (cs3, allCodePathsReturn2) <- typeConstraintsForElseStatement m mass ret elses
410+ return ((TypeConstraint n1 Boolean) : cs1 ++ cs2 ++ cs3, allCodePathsReturn1 && allCodePathsReturn2)
411+
412+typeConstraintsForElseStatement :: M.Map Ident Int -> M.Map Ident Int -> Int -> ElseStatement -> Check ([TypeConstraint], Bool)
413+typeConstraintsForElseStatement m mass ret (Else elses) = do
414+ (cs, allCodePathsReturn, _) <- typeConstraintsForBlock m mass ret elses
415+ return (cs, allCodePathsReturn)
416+typeConstraintsForElseStatement m mass ret (ElseIf ifst) = do
417+ (cs, allCodePathsReturn) <- typeConstraintsForIfStatement m mass ret ifst
418+ return (cs, allCodePathsReturn)
419+
407typeConstraintsForAssignmentTarget :: M.Map Ident Int -> M.Map Ident Int -> Int -> AssignmentTarget -> Check [TypeConstraint]
420typeConstraintsForAssignmentTarget :: M.Map Ident Int -> M.Map Ident Int -> Int -> AssignmentTarget -> Check [TypeConstraint]
408typeConstraintsForAssignmentTarget m mass nval (AssignVariable var) =
421typeConstraintsForAssignmentTarget m mass nval (AssignVariable var) =
409 case M.lookup var mass of
422 case M.lookup var mass of
src/PureScript/Values.hs+9−3
@@ -49,7 +49,7 @@ data BinaryOperator
49 | Concat deriving (Show, Eq, Data, Typeable)
49 | Concat deriving (Show, Eq, Data, Typeable)
50
50
51data Value
51data Value
52− = NumericLiteral String
52+ = NumericLiteral (Either Integer Double)
53 | StringLiteral String
53 | StringLiteral String
54 | BooleanLiteral Bool
54 | BooleanLiteral Bool
55 | Unary UnaryOperator Value
55 | Unary UnaryOperator Value
@@ -71,13 +71,19 @@ data Statement
71 | Assignment AssignmentTarget Value
71 | Assignment AssignmentTarget Value
72 | While Value [Statement]
72 | While Value [Statement]
73 | For (Statement, Value, Statement) [Statement]
73 | For (Statement, Value, Statement) [Statement]
74− | IfThenElse (Value) [Statement] (Maybe [Statement])
74+ | If IfStatement
75 | Return Value deriving (Show, Data, Typeable)
75 | Return Value deriving (Show, Data, Typeable)
76
76
77+data IfStatement = IfStatement Value [Statement] (Maybe ElseStatement) deriving (Show, Data, Typeable)
78+
79+data ElseStatement
80+ = Else [Statement]
81+ | ElseIf IfStatement deriving (Show, Data, Typeable)
82+
77data Binder
83data Binder
78 = BooleanBinder Bool
84 = BooleanBinder Bool
79 | StringBinder String
85 | StringBinder String
80− | NumberBinder String
86+ | NumberBinder (Either Integer Double)
81 | VarBinder Ident
87 | VarBinder Ident
82 | NullaryBinder String
88 | NullaryBinder String
83 | UnaryBinder String Binder
89 | UnaryBinder String Binder