git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
For Each
aabb9d3Phil Freeman
examples/Assign.ps+4−4
@@ -1,5 +1,5 @@
1−test = \ -> do
1+sum = \n -> do
2− var x = []
2+ var x = 0
3− for (var i = 0; i < 10; i = i + 1):
3+ for i <- 0 until n:
4− x[i] = i
4+ x = x + i
5 return x
5 return x
examples/Foreach.jsnew file+1
@@ -0,0 +1 @@
1+console.log(sum([1,2,3,4,5]));
examples/Foreach.psnew file+5
@@ -0,0 +1,5 @@
1+sum = \ns -> do
2+ var total = 0
3+ foreach n in ns:
4+ total = total + n
5+ return total
examples/runAll.test+8
@@ -13,3 +13,11 @@ mkdir -p tests && ../dist/build/psc/psc List.ps -o tests/List.js && cat tests/L
13[ 1, 2 ]
13[ 1, 2 ]
14>>>2
14>>>2
15>>>= 0
15>>>= 0
16+
17+# Foreach
18+mkdir -p tests && ../dist/build/psc/psc Foreach.ps -o tests/Foreach.js && cat tests/Foreach.js Foreach.js | node
19+<<<
20+>>>
21+15
22+>>>2
23+>>>= 0
src/PureScript/CodeGen/JS.hs+8−5
@@ -223,11 +223,14 @@ statementToJs (Assignment target value) = assignmentTargetToJs target ++ " = " +
223statementToJs (While cond sts) = "while ("
223statementToJs (While cond sts) = "while ("
224 ++ valueToJs cond ++ ") {"
224 ++ valueToJs cond ++ ") {"
225 ++ intercalate ";" (map statementToJs sts) ++ "}"
225 ++ intercalate ";" (map statementToJs sts) ++ "}"
226−statementToJs (For (init, cond, done) sts) = "for (" ++
226+statementToJs (For ident start end sts) = "for (" ++
227− statementToJs init
227+ identToJs ident ++ " = " ++ valueToJs start ++ ";"
228− ++ "; " ++ valueToJs cond
228+ ++ identToJs ident ++ " < " ++ valueToJs end ++ ";"
229+ ++ identToJs ident ++ "++) {"
230+ ++ intercalate ";" (map statementToJs sts) ++ "}"
229− ++ "; " ++ statementToJs done
231+statementToJs (ForEach ident arr sts) = valueToJs arr
232+ ++ ".forEach(function(" ++ identToJs ident ++ ") {"
230− ++ ") {" ++ intercalate ";" (map statementToJs sts) ++ "}"
233+ ++ intercalate ";" (map statementToJs sts) ++ "})"
231statementToJs (If ifst) = ifStatementToJs ifst
234statementToJs (If ifst) = ifStatementToJs ifst
232statementToJs (Return value) = "return " ++ valueToJs value
235statementToJs (Return value) = "return " ++ valueToJs value
233
236
src/PureScript/Parser/Common.hs+4−1
@@ -34,6 +34,7 @@ reservedNames = [ "case"
34 , "val"
34 , "val"
35 , "while"
35 , "while"
36 , "for"
36 , "for"
37+ , "foreach"
37 , "if"
38 , "if"
38 , "then"
39 , "then"
39 , "else"
40 , "else"
@@ -42,7 +43,9 @@ reservedNames = [ "case"
42 , "false"
43 , "false"
43 , "extern"
44 , "extern"
44 , "forall"
45 , "forall"
45− , "do" ]
46+ , "do"
47+ , "until"
48+ , "in" ]
46
49
47reservedOpNames :: [String]
50reservedOpNames :: [String]
48reservedOpNames = [ "!", "~", "-", "<=", ">=", "<", ">", "*", "/", "%", "++", "+", "<<", ">>>", ">>"
51reservedOpNames = [ "!", "~", "-", "<=", ">=", "<", ">", "*", "/", "%", "++", "+", "<<", ">>>", ">>"
src/PureScript/Parser/Values.hs+9−5
@@ -148,12 +148,15 @@ parseWhile = While <$> (C.reserved "while" *> C.indented *> parseValue <* C.inde
148 <*> parseManyStatements
148 <*> parseManyStatements
149
149
150parseFor :: P.Parsec String P.Column Statement
150parseFor :: P.Parsec String P.Column Statement
151−parseFor = For <$> (C.reserved "for" *> C.indented *> C.parens forIntro <* C.indented <* C.colon)
151+parseFor = For <$> (C.reserved "for" *> C.indented *> C.parseIdent)
152+ <*> (C.indented *> C.lexeme (P.string "<-") *> parseValue)
153+ <*> (C.indented *> C.reserved "until" *> parseValue <* C.colon)
152 <*> parseManyStatements
154 <*> parseManyStatements
153− where
155+
154− forIntro = (,,) <$> (C.indented *> parseStatement)
156+parseForEach :: P.Parsec String P.Column Statement
157+parseForEach = ForEach <$> (C.reserved "foreach" *> C.indented *> C.parseIdent)
155− <*> (C.indented *> C.semi *> C.indented *> parseValue)
158+ <*> (C.indented *> C.reserved "in" *> parseValue <* C.colon)
156− <*> (C.indented *> C.semi *> C.indented *> parseStatement)
159+ <*> parseManyStatements
157
160
158parseIf :: P.Parsec String P.Column Statement
161parseIf :: P.Parsec String P.Column Statement
159parseIf = If <$> parseIfStatement
162parseIf = If <$> parseIfStatement
@@ -177,6 +180,7 @@ parseStatement = P.choice (map P.try
177 , parseAssignment
180 , parseAssignment
178 , parseWhile
181 , parseWhile
179 , parseFor
182 , parseFor
183+ , parseForEach
180 , parseIf
184 , parseIf
181 , parseReturn ])
185 , parseReturn ])
182
186
src/PureScript/TypeChecker/Types.hs+24−13
@@ -368,13 +368,17 @@ typeConstraintsForBinders m nval ret ((binder, val):bs) = do
368 cs3 <- typeConstraintsForBinders m nval ret bs
368 cs3 <- typeConstraintsForBinders m nval ret bs
369 return ((TypeConstraint n2 (TUnknown ret)) : cs1 ++ cs2 ++ cs3)
369 return ((TypeConstraint n2 (TUnknown ret)) : cs1 ++ cs2 ++ cs3)
370
370
371+assignVariable :: Ident -> M.Map Ident Int -> Check ()
372+assignVariable name m =
373+ case M.lookup name m of
374+ Nothing -> return ()
375+ Just _ -> throwError $ "Variable with name " ++ show name ++ " already exists."
376+
371typeConstraintsForStatement :: M.Map Ident Int -> M.Map Ident Int -> Int -> Statement -> Check ([TypeConstraint], Bool, M.Map Ident Int)
377typeConstraintsForStatement :: M.Map Ident Int -> M.Map Ident Int -> Int -> Statement -> Check ([TypeConstraint], Bool, M.Map Ident Int)
372typeConstraintsForStatement m mass ret (VariableIntroduction name val) = do
378typeConstraintsForStatement m mass ret (VariableIntroduction name val) = do
373− case M.lookup name (m `M.union` mass) of
379+ assignVariable name (m `M.union` mass)
374− Nothing -> do
375− (cs1, n1) <- typeConstraints m val
380+ (cs1, n1) <- typeConstraints m val
376− return $ (cs1, False, M.insert name n1 mass)
381+ return $ (cs1, False, M.insert name n1 mass)
377− Just ty -> throwError $ "Variable with name " ++ show name ++ " already exists."
378typeConstraintsForStatement m mass ret (Assignment tgt val) = do
382typeConstraintsForStatement m mass ret (Assignment tgt val) = do
379 (cs1, n1) <- typeConstraints m val
383 (cs1, n1) <- typeConstraints m val
380 cs2 <- typeConstraintsForAssignmentTarget m mass n1 tgt
384 cs2 <- typeConstraintsForAssignmentTarget m mass n1 tgt
@@ -386,14 +390,21 @@ typeConstraintsForStatement m mass ret (While val inner) = do
386typeConstraintsForStatement m mass ret (If ifst) = do
390typeConstraintsForStatement m mass ret (If ifst) = do
387 (cs, allCodePathsReturn) <- typeConstraintsForIfStatement m mass ret ifst
391 (cs, allCodePathsReturn) <- typeConstraintsForIfStatement m mass ret ifst
388 return $ (cs, allCodePathsReturn, mass)
392 return $ (cs, allCodePathsReturn, mass)
389−typeConstraintsForStatement m mass ret (For (init, cond, cont) inner) = do
393+typeConstraintsForStatement m mass ret (For ident start end inner) = do
390− (cs1, b1, mass1) <- typeConstraintsForStatement m mass ret init
394+ assignVariable ident (m `M.union` mass)
391− guardWith "Cannot return from inside for" $ not b1
395+ (cs1, n1) <- typeConstraints (m `M.union` mass) start
392− (cs2, n1) <- typeConstraints (m `M.union` mass1) cond
396+ (cs2, n2) <- typeConstraints (m `M.union` mass) end
393− (cs3, b2, mass2) <- typeConstraintsForStatement (m `M.union` mass1) mass1 ret cont
397+ let mass1 = M.insert ident n1 mass
394− guardWith "Cannot return from inside for" $ not b2
398+ (cs3, allCodePathsReturn, _) <- typeConstraintsForBlock (m `M.union` mass1) mass1 ret inner
399+ return $ ((TypeConstraint n1 Number) : (TypeConstraint n2 Number) : cs1 ++ cs2 ++ cs3, allCodePathsReturn, mass)
400+typeConstraintsForStatement m mass ret (ForEach ident vals inner) = do
401+ assignVariable ident (m `M.union` mass)
402+ val <- fresh
403+ (cs1, n1) <- typeConstraints (m `M.union` mass) vals
404+ let mass1 = M.insert ident val mass
395− (cs4, allCodePathsReturn, _) <- typeConstraintsForBlock (m `M.union` mass2) mass2 ret inner
405+ (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock (m `M.union` mass1) mass1 ret inner
406+ guardWith "Cannot return from within a foreach block" $ not allCodePathsReturn
396− return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2 ++ cs3 ++ cs4, allCodePathsReturn, mass)
407+ return $ ((TypeConstraint n1 (Array (TUnknown val))) : cs1 ++ cs2, False, mass)
397typeConstraintsForStatement m mass ret (Return val) = do
408typeConstraintsForStatement m mass ret (Return val) = do
398 (cs1, n1) <- typeConstraints (m `M.union` mass) val
409 (cs1, n1) <- typeConstraints (m `M.union` mass) val
399 return ((TypeConstraint n1 (TUnknown ret)) : cs1, True, mass)
410 return ((TypeConstraint n1 (TUnknown ret)) : cs1, True, mass)
src/PureScript/Values.hs+2−1
@@ -70,7 +70,8 @@ data Statement
70 = VariableIntroduction Ident Value
70 = VariableIntroduction Ident Value
71 | Assignment AssignmentTarget Value
71 | Assignment AssignmentTarget Value
72 | While Value [Statement]
72 | While Value [Statement]
73− | For (Statement, Value, Statement) [Statement]
73+ | For Ident Value Value [Statement]
74+ | ForEach Ident Value [Statement]
74 | If IfStatement
75 | If IfStatement
75 | Return Value deriving (Show, Data, Typeable)
76 | Return Value deriving (Show, Data, Typeable)
76
77