git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Guards, named patterns, fixed array patterns
0c57401Phil Freeman
examples/Guards.psnew file+3
@@ -0,0 +1,3 @@
1+collatz = \x -> case x of
2+ y | y % 2 == 0 -> y / 2
3+ y -> y * 3 + 1
examples/NamedPatterns.psnew file+6
@@ -0,0 +1,6 @@
1+foo = \x -> case x of
2+ y@{ foo = "Foo" } -> y
3+ y -> (do
4+ var copy = y
5+ copy.foo = "Bar"
6+ return copy)
src/PureScript/CodeGen/JS.hs+8−1
@@ -167,6 +167,7 @@ binaryOperatorString Or = "||"
167binaryOperatorString Concat = "+"
167binaryOperatorString Concat = "+"
168
168
169binderToJs :: String -> String -> Binder -> Gen String
169binderToJs :: String -> String -> Binder -> Gen String
170+binderToJs varName done NullBinder = return done
170binderToJs varName done (StringBinder str) =
171binderToJs varName done (StringBinder str) =
171 return $ "if (" ++ varName ++ " === \"" ++ str ++ "\") {" ++ done ++ " }"
172 return $ "if (" ++ varName ++ " === \"" ++ str ++ "\") {" ++ done ++ " }"
172binderToJs varName done (NumberBinder num) =
173binderToJs varName done (NumberBinder num) =
@@ -191,7 +192,7 @@ binderToJs varName done (ObjectBinder bs) = go done bs
191 done' <- go done bs
192 done' <- go done bs
192 js <- binderToJs propVar done' binder
193 js <- binderToJs propVar done' binder
193 return $ "var " ++ propVar ++ " = " ++ varName ++ "." ++ prop ++ ";" ++ js
194 return $ "var " ++ propVar ++ " = " ++ varName ++ "." ++ prop ++ ";" ++ js
194−binderToJs done varName (ArrayBinder bs rest) = do
195+binderToJs varName done (ArrayBinder bs rest) = do
195 js <- go done rest 0 bs
196 js <- go done rest 0 bs
196 return $ "if (" ++ varName ++ ".length " ++ cmp ++ " " ++ show (length bs) ++ ") { " ++ js ++ " }"
197 return $ "if (" ++ varName ++ ".length " ++ cmp ++ " " ++ show (length bs) ++ ") { " ++ js ++ " }"
197 where
198 where
@@ -206,6 +207,12 @@ binderToJs done varName (ArrayBinder bs rest) = do
206 done' <- go done rest (index + 1) bs
207 done' <- go done rest (index + 1) bs
207 js <- binderToJs elVar done' binder
208 js <- binderToJs elVar done' binder
208 return $ "var " ++ elVar ++ " = " ++ varName ++ "[" ++ show index ++ "]; " ++ js
209 return $ "var " ++ elVar ++ " = " ++ varName ++ "[" ++ show index ++ "]; " ++ js
210+binderToJs varName done (NamedBinder ident binder) = do
211+ js <- binderToJs varName done binder
212+ return $ "var " ++ identToJs ident ++ " = " ++ varName ++ "; " ++ js
213+binderToJs varName done (GuardedBinder cond binder) = binderToJs varName done' binder
214+ where
215+ done' = "if (" ++ valueToJs cond ++ ") { " ++ done ++ "}"
209
216
210objectPropertyToJs :: (String, Value) -> String
217objectPropertyToJs :: (String, Value) -> String
211objectPropertyToJs (key, value) = key ++ ":" ++ valueToJs value
218objectPropertyToJs (key, value) = key ++ ":" ++ valueToJs value
src/PureScript/Parser/Values.hs+14−2
@@ -72,7 +72,7 @@ parseCase = Case <$> (P.between (C.reserved "case") (C.indented *> C.reserved "o
72 <*> (C.indented *> C.mark (P.many (C.same *> C.mark parseCaseAlternative)))
72 <*> (C.indented *> C.mark (P.many (C.same *> C.mark parseCaseAlternative)))
73
73
74parseCaseAlternative :: P.Parsec String P.Column (Binder, Value)
74parseCaseAlternative :: P.Parsec String P.Column (Binder, Value)
75−parseCaseAlternative = (,) <$> (parseBinder <* C.lexeme (P.string "->")) <*> parseValue
75+parseCaseAlternative = (,) <$> (parseGuardedBinder <* C.lexeme (P.string "->")) <*> parseValue
76
76
77parseBlock :: P.Parsec String P.Column Value
77parseBlock :: P.Parsec String P.Column Value
78parseBlock = Block <$> (C.reserved "do" *> parseManyStatements)
78parseBlock = Block <$> (C.reserved "do" *> parseManyStatements)
@@ -211,6 +211,13 @@ parseArrayBinder :: P.Parsec String P.Column Binder
211parseArrayBinder = C.squares $ ArrayBinder <$> ((C.indented *> parseBinder) `P.sepBy` (C.indented *> C.comma))
211parseArrayBinder = C.squares $ ArrayBinder <$> ((C.indented *> parseBinder) `P.sepBy` (C.indented *> C.comma))
212 <*> P.optionMaybe (C.indented *> C.colon *> C.indented *> parseBinder)
212 <*> P.optionMaybe (C.indented *> C.colon *> C.indented *> parseBinder)
213
213
214+parseNamedBinder :: P.Parsec String P.Column Binder
215+parseNamedBinder = NamedBinder <$> (C.parseIdent <* C.indented <* C.lexeme (P.char '@'))
216+ <*> (C.indented *> parseBinder)
217+
218+parseNullBinder :: P.Parsec String P.Column Binder
219+parseNullBinder = C.lexeme (P.char '_') *> P.notFollowedBy C.identLetter *> return NullBinder
220+
214parseIdentifierAndBinder :: P.Parsec String P.Column (String, Binder)
221parseIdentifierAndBinder :: P.Parsec String P.Column (String, Binder)
215parseIdentifierAndBinder = do
222parseIdentifierAndBinder = do
216 name <- C.lexeme C.identifier
223 name <- C.lexeme C.identifier
@@ -220,9 +227,11 @@ parseIdentifierAndBinder = do
220
227
221parseBinder :: P.Parsec String P.Column Binder
228parseBinder :: P.Parsec String P.Column Binder
222parseBinder = P.choice (map P.try
229parseBinder = P.choice (map P.try
230+ [ parseNullBinder
223− [ parseStringBinder
231+ , parseStringBinder
224 , parseBooleanBinder
232 , parseBooleanBinder
225 , parseNumberBinder
233 , parseNumberBinder
234+ , parseNamedBinder
226 , parseVarBinder
235 , parseVarBinder
227 , parseUnaryBinder
236 , parseUnaryBinder
228 , parseNullaryBinder
237 , parseNullaryBinder
@@ -230,6 +239,9 @@ parseBinder = P.choice (map P.try
230 , parseArrayBinder
239 , parseArrayBinder
231 , C.parens parseBinder ])
240 , C.parens parseBinder ])
232
241
242+parseGuardedBinder :: P.Parsec String P.Column Binder
243+parseGuardedBinder = flip ($) <$> parseBinder <*> P.option id (GuardedBinder <$> (C.indented *> C.lexeme (P.char '|') *> C.indented *> parseValue))
244+
233parseAssignmentTarget :: P.Parsec String P.Column AssignmentTarget
245parseAssignmentTarget :: P.Parsec String P.Column AssignmentTarget
234parseAssignmentTarget = buildExpressionParser operators (AssignVariable <$> C.parseIdent)
246parseAssignmentTarget = buildExpressionParser operators (AssignVariable <$> C.parseIdent)
235 where
247 where
src/PureScript/TypeChecker/Types.hs+9
@@ -317,6 +317,7 @@ asymBinOpConstraints :: Type -> Type -> Int -> Int -> Int -> [TypeConstraint]
317asymBinOpConstraints ty res left right result = [TypeConstraint left ty, TypeConstraint right ty, TypeConstraint result res]
317asymBinOpConstraints ty res left right result = [TypeConstraint left ty, TypeConstraint right ty, TypeConstraint result res]
318
318
319typeConstraintsForBinder :: Int -> Binder -> Check ([TypeConstraint], M.Map Ident Int)
319typeConstraintsForBinder :: Int -> Binder -> Check ([TypeConstraint], M.Map Ident Int)
320+typeConstraintsForBinder _ NullBinder = return ([], M.empty)
320typeConstraintsForBinder val (StringBinder _) = constantBinder val String
321typeConstraintsForBinder val (StringBinder _) = constantBinder val String
321typeConstraintsForBinder val (NumberBinder _) = constantBinder val Number
322typeConstraintsForBinder val (NumberBinder _) = constantBinder val Number
322typeConstraintsForBinder val (BooleanBinder _) = constantBinder val Boolean
323typeConstraintsForBinder val (BooleanBinder _) = constantBinder val Boolean
@@ -363,6 +364,14 @@ typeConstraintsForBinder val (ArrayBinder binders rest) = do
363 Just binder -> do
364 Just binder -> do
364 (cs2, m2) <- typeConstraintsForBinder val binder
365 (cs2, m2) <- typeConstraintsForBinder val binder
365 return (arrayConstraint : cs1 ++ cs2, M.union m1 m2)
366 return (arrayConstraint : cs1 ++ cs2, M.union m1 m2)
367+typeConstraintsForBinder val (NamedBinder name binder) = do
368+ me <- fresh
369+ (cs, m) <- typeConstraintsForBinder val binder
370+ return (TypeConstraint me (TUnknown val) : cs, M.insert name me m)
371+typeConstraintsForBinder val (GuardedBinder cond binder) = do
372+ (cs1, m) <- typeConstraintsForBinder val binder
373+ (cs2, n) <- typeConstraints m cond
374+ return (TypeConstraint n Boolean : cs1 ++ cs2, m)
366
375
367constantBinder :: Int -> Type -> Check ([TypeConstraint], M.Map Ident Int)
376constantBinder :: Int -> Type -> Check ([TypeConstraint], M.Map Ident Int)
368constantBinder val ty = return ([TypeConstraint val ty], M.empty)
377constantBinder val ty = return ([TypeConstraint val ty], M.empty)
src/PureScript/Values.hs+5−2
@@ -82,14 +82,17 @@ data ElseStatement
82 | ElseIf IfStatement deriving (Show, Data, Typeable)
82 | ElseIf IfStatement deriving (Show, Data, Typeable)
83
83
84data Binder
84data Binder
85+ = NullBinder
85− = BooleanBinder Bool
86+ | BooleanBinder Bool
86 | StringBinder String
87 | StringBinder String
87 | NumberBinder (Either Integer Double)
88 | NumberBinder (Either Integer Double)
88 | VarBinder Ident
89 | VarBinder Ident
89 | NullaryBinder String
90 | NullaryBinder String
90 | UnaryBinder String Binder
91 | UnaryBinder String Binder
91 | ObjectBinder [(String, Binder)]
92 | ObjectBinder [(String, Binder)]
92− | ArrayBinder [Binder] (Maybe Binder) deriving (Show, Data, Typeable)
93+ | ArrayBinder [Binder] (Maybe Binder)
94+ | NamedBinder Ident Binder
95+ | GuardedBinder Value Binder deriving (Show, Data, Typeable)
93
96
94data AssignmentTarget
97data AssignmentTarget
95 = AssignVariable Ident
98 = AssignVariable Ident