@@ -11,6 +11,7 @@ import NameKinds.{UniqueName, ContextBoundParamName, ContextFunctionParamName, D
11
11
import typer .{Namer , Checking }
12
12
import util .{Property , SourceFile , SourcePosition , SrcPos , Chars }
13
13
import config .{Feature , Config }
14
+ import config .Feature .{sourceVersion , migrateTo3 , enabled , betterForsEnabled }
14
15
import config .SourceVersion .*
15
16
import collection .mutable
16
17
import reporting .*
@@ -1807,7 +1808,7 @@ object desugar {
1807
1808
*
1808
1809
* 1.
1809
1810
*
1810
- * for (P <- G) E ==> G.foreach (P => E)
1811
+ * for (P <- G) do E ==> G.foreach (P => E)
1811
1812
*
1812
1813
* Here and in the following (P => E) is interpreted as the function (P => E)
1813
1814
* if P is a variable pattern and as the partial function { case P => E } otherwise.
@@ -1816,11 +1817,11 @@ object desugar {
1816
1817
*
1817
1818
* for (P <- G) yield P ==> G
1818
1819
*
1819
- * if P is a variable or a tuple of variables and G is not a withFilter.
1820
+ * If P is a variable or a tuple of variables and G is not a withFilter.
1820
1821
*
1821
1822
* for (P <- G) yield E ==> G.map (P => E)
1822
1823
*
1823
- * otherwise
1824
+ * Otherwise
1824
1825
*
1825
1826
* 3.
1826
1827
*
@@ -1830,25 +1831,48 @@ object desugar {
1830
1831
*
1831
1832
* 4.
1832
1833
*
1833
- * for (P <- G; E; ...) ...
1834
- * =>
1835
- * for (P <- G.filter (P => E); ...) ...
1834
+ * for (P <- G; if E; ...) ...
1835
+ * == >
1836
+ * for (P <- G.withFilter (P => E); ...) ...
1836
1837
*
1837
1838
* 5. For any N:
1838
1839
*
1839
- * for (P_1 <- G; P_2 = E_2; val P_N = E_N; ... )
1840
+ * for (P <- G; P_1 = E_1; ... P_N = E_N; rest )
1840
1841
* ==>
1841
- * for (TupleN(P_1, P_2, ... P_N) <-
1842
- * for (x_1 @ P_1 <- G) yield {
1843
- * val x_2 @ P_2 = E_2
1842
+ * G.flatMap (P => for (P_1 = E_1; ... P_N = E_N; ...)) if rest contains (<-)
1843
+ * G.map (P => for (P_1 = E_1; ... P_N = E_N; ...)) otherwise
1844
+ *
1845
+ * 6. For any N:
1846
+ *
1847
+ * for (P <- G; P_1 = E_1; ... P_N = E_N; if E; ...)
1848
+ * ==>
1849
+ * for (TupleN(P, P_1, ... P_N) <-
1850
+ * for (x @ P <- G) yield {
1851
+ * val x_1 @ P_1 = E_2
1844
1852
* ...
1845
- * val x_N & P_N = E_N
1846
- * TupleN(x_1, ..., x_N)
1847
- * } ...)
1853
+ * val x_N @ P_N = E_N
1854
+ * TupleN(x, x_1, ..., x_N)
1855
+ * }; if E; ...)
1848
1856
*
1849
1857
* If any of the P_i are variable patterns, the corresponding `x_i @ P_i` is not generated
1850
1858
* and the variable constituting P_i is used instead of x_i
1851
1859
*
1860
+ * 7. For any N:
1861
+ *
1862
+ * for (P_1 = E_1; ... P_N = E_N; ...)
1863
+ * ==>
1864
+ * {
1865
+ * val x_N @ P_N = E_N
1866
+ * for (...)
1867
+ * }
1868
+ *
1869
+ * 8.
1870
+ * for () yield E ==> E
1871
+ *
1872
+ * (Where empty for-comprehensions are excluded by the parser)
1873
+ *
1874
+ * If the aliases are not followed by a guard, otherwise an error.
1875
+ *
1852
1876
* @param mapName The name to be used for maps (either map or foreach)
1853
1877
* @param flatMapName The name to be used for flatMaps (either flatMap or foreach)
1854
1878
* @param enums The enumerators in the for expression
@@ -1973,37 +1997,86 @@ object desugar {
1973
1997
case (Tuple (ts1), Tuple (ts2)) => ts1.corresponds(ts2)(deepEquals)
1974
1998
case _ => false
1975
1999
1976
- enums match {
1977
- case (gen : GenFrom ) :: Nil =>
1978
- if gen.checkMode != GenCheckMode .Filtered // results of withFilter have the wrong type
1979
- && deepEquals(gen.pat, body)
1980
- then gen.expr // avoid a redundant map with identity
1981
- else Apply (rhsSelect(gen, mapName), makeLambda(gen, body))
1982
- case (gen : GenFrom ) :: (rest @ (GenFrom (_, _, _) :: _)) =>
1983
- val cont = makeFor(mapName, flatMapName, rest, body)
1984
- Apply (rhsSelect(gen, flatMapName), makeLambda(gen, cont))
1985
- case (gen : GenFrom ) :: (rest @ GenAlias (_, _) :: _) =>
1986
- val (valeqs, rest1) = rest.span(_.isInstanceOf [GenAlias ])
1987
- val pats = valeqs map { case GenAlias (pat, _) => pat }
1988
- val rhss = valeqs map { case GenAlias (_, rhs) => rhs }
1989
- val (defpat0, id0) = makeIdPat(gen.pat)
1990
- val (defpats, ids) = (pats map makeIdPat).unzip
1991
- val pdefs = valeqs.lazyZip(defpats).lazyZip(rhss).map { (valeq, defpat, rhs) =>
1992
- val mods = defpat match
1993
- case defTree : DefTree => defTree.mods
1994
- case _ => Modifiers ()
1995
- makePatDef(valeq, mods, defpat, rhs)
1996
- }
1997
- val rhs1 = makeFor(nme.map, nme.flatMap, GenFrom (defpat0, gen.expr, gen.checkMode) :: Nil , Block (pdefs, makeTuple(id0 :: ids)))
1998
- val allpats = gen.pat :: pats
1999
- val vfrom1 = GenFrom (makeTuple(allpats), rhs1, GenCheckMode .Ignore )
2000
- makeFor(mapName, flatMapName, vfrom1 :: rest1, body)
2001
- case (gen : GenFrom ) :: test :: rest =>
2002
- val filtered = Apply (rhsSelect(gen, nme.withFilter), makeLambda(gen, test))
2003
- val genFrom = GenFrom (gen.pat, filtered, GenCheckMode .Filtered )
2004
- makeFor(mapName, flatMapName, genFrom :: rest, body)
2005
- case _ =>
2006
- EmptyTree // may happen for erroneous input
2000
+ if betterForsEnabled then
2001
+ enums match {
2002
+ case Nil => body
2003
+ case (gen : GenFrom ) :: Nil =>
2004
+ if gen.checkMode != GenCheckMode .Filtered // results of withFilter have the wrong type
2005
+ && deepEquals(gen.pat, body)
2006
+ then gen.expr // avoid a redundant map with identity
2007
+ else Apply (rhsSelect(gen, mapName), makeLambda(gen, body))
2008
+ case (gen : GenFrom ) :: rest
2009
+ if rest.dropWhile(_.isInstanceOf [GenAlias ]).headOption.forall(e => e.isInstanceOf [GenFrom ]) =>
2010
+ val cont = makeFor(mapName, flatMapName, rest, body)
2011
+ val selectName =
2012
+ if rest.exists(_.isInstanceOf [GenFrom ]) then flatMapName
2013
+ else mapName
2014
+ Apply (rhsSelect(gen, selectName), makeLambda(gen, cont))
2015
+ case (gen : GenFrom ) :: (rest @ GenAlias (_, _) :: _) =>
2016
+ val (valeqs, rest1) = rest.span(_.isInstanceOf [GenAlias ])
2017
+ val pats = valeqs map { case GenAlias (pat, _) => pat }
2018
+ val rhss = valeqs map { case GenAlias (_, rhs) => rhs }
2019
+ val (defpat0, id0) = makeIdPat(gen.pat)
2020
+ val (defpats, ids) = (pats map makeIdPat).unzip
2021
+ val pdefs = valeqs.lazyZip(defpats).lazyZip(rhss).map { (valeq, defpat, rhs) =>
2022
+ val mods = defpat match
2023
+ case defTree : DefTree => defTree.mods
2024
+ case _ => Modifiers ()
2025
+ makePatDef(valeq, mods, defpat, rhs)
2026
+ }
2027
+ val rhs1 = makeFor(nme.map, nme.flatMap, GenFrom (defpat0, gen.expr, gen.checkMode) :: Nil , Block (pdefs, makeTuple(id0 :: ids)))
2028
+ val allpats = gen.pat :: pats
2029
+ val vfrom1 = GenFrom (makeTuple(allpats), rhs1, GenCheckMode .Ignore )
2030
+ makeFor(mapName, flatMapName, vfrom1 :: rest1, body)
2031
+ case (gen : GenFrom ) :: test :: rest =>
2032
+ val filtered = Apply (rhsSelect(gen, nme.withFilter), makeLambda(gen, test))
2033
+ val genFrom = GenFrom (gen.pat, filtered, GenCheckMode .Filtered )
2034
+ makeFor(mapName, flatMapName, genFrom :: rest, body)
2035
+ case GenAlias (_, _) :: _ =>
2036
+ val (valeqs, rest) = enums.span(_.isInstanceOf [GenAlias ])
2037
+ val pats = valeqs.map { case GenAlias (pat, _) => pat }
2038
+ val rhss = valeqs.map { case GenAlias (_, rhs) => rhs }
2039
+ val (defpats, ids) = pats.map(makeIdPat).unzip
2040
+ val pdefs = valeqs.lazyZip(defpats).lazyZip(rhss).map { (valeq, defpat, rhs) =>
2041
+ val mods = defpat match
2042
+ case defTree : DefTree => defTree.mods
2043
+ case _ => Modifiers ()
2044
+ makePatDef(valeq, mods, defpat, rhs)
2045
+ }
2046
+ Block (pdefs, makeFor(mapName, flatMapName, rest, body))
2047
+ case _ =>
2048
+ EmptyTree // may happen for erroneous input
2049
+ }
2050
+ else {
2051
+ enums match {
2052
+ case (gen : GenFrom ) :: Nil =>
2053
+ Apply (rhsSelect(gen, mapName), makeLambda(gen, body))
2054
+ case (gen : GenFrom ) :: (rest @ (GenFrom (_, _, _) :: _)) =>
2055
+ val cont = makeFor(mapName, flatMapName, rest, body)
2056
+ Apply (rhsSelect(gen, flatMapName), makeLambda(gen, cont))
2057
+ case (gen : GenFrom ) :: (rest @ GenAlias (_, _) :: _) =>
2058
+ val (valeqs, rest1) = rest.span(_.isInstanceOf [GenAlias ])
2059
+ val pats = valeqs map { case GenAlias (pat, _) => pat }
2060
+ val rhss = valeqs map { case GenAlias (_, rhs) => rhs }
2061
+ val (defpat0, id0) = makeIdPat(gen.pat)
2062
+ val (defpats, ids) = (pats map makeIdPat).unzip
2063
+ val pdefs = valeqs.lazyZip(defpats).lazyZip(rhss).map { (valeq, defpat, rhs) =>
2064
+ val mods = defpat match
2065
+ case defTree : DefTree => defTree.mods
2066
+ case _ => Modifiers ()
2067
+ makePatDef(valeq, mods, defpat, rhs)
2068
+ }
2069
+ val rhs1 = makeFor(nme.map, nme.flatMap, GenFrom (defpat0, gen.expr, gen.checkMode) :: Nil , Block (pdefs, makeTuple(id0 :: ids)))
2070
+ val allpats = gen.pat :: pats
2071
+ val vfrom1 = GenFrom (makeTuple(allpats), rhs1, GenCheckMode .Ignore )
2072
+ makeFor(mapName, flatMapName, vfrom1 :: rest1, body)
2073
+ case (gen : GenFrom ) :: test :: rest =>
2074
+ val filtered = Apply (rhsSelect(gen, nme.withFilter), makeLambda(gen, test))
2075
+ val genFrom = GenFrom (gen.pat, filtered, GenCheckMode .Ignore )
2076
+ makeFor(mapName, flatMapName, genFrom :: rest, body)
2077
+ case _ =>
2078
+ EmptyTree // may happen for erroneous input
2079
+ }
2007
2080
}
2008
2081
}
2009
2082
0 commit comments