@@ -11,6 +11,7 @@ import NameKinds.{UniqueName, ContextBoundParamName, ContextFunctionParamName, D
1111import typer .{Namer , Checking }
1212import util .{Property , SourceFile , SourcePosition , SrcPos , Chars }
1313import config .{Feature , Config }
14+ import config .Feature .{sourceVersion , migrateTo3 , enabled , betterForsEnabled }
1415import config .SourceVersion .*
1516import collection .mutable
1617import reporting .*
@@ -1807,7 +1808,7 @@ object desugar {
18071808 *
18081809 * 1.
18091810 *
1810- * for (P <- G) E ==> G.foreach (P => E)
1811+ * for (P <- G) do E ==> G.foreach (P => E)
18111812 *
18121813 * Here and in the following (P => E) is interpreted as the function (P => E)
18131814 * if P is a variable pattern and as the partial function { case P => E } otherwise.
@@ -1816,11 +1817,11 @@ object desugar {
18161817 *
18171818 * for (P <- G) yield P ==> G
18181819 *
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.
18201821 *
18211822 * for (P <- G) yield E ==> G.map (P => E)
18221823 *
1823- * otherwise
1824+ * Otherwise
18241825 *
18251826 * 3.
18261827 *
@@ -1830,25 +1831,48 @@ object desugar {
18301831 *
18311832 * 4.
18321833 *
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); ...) ...
18361837 *
18371838 * 5. For any N:
18381839 *
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 )
18401841 * ==>
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
18441852 * ...
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; ...)
18481856 *
18491857 * If any of the P_i are variable patterns, the corresponding `x_i @ P_i` is not generated
18501858 * and the variable constituting P_i is used instead of x_i
18511859 *
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+ *
18521876 * @param mapName The name to be used for maps (either map or foreach)
18531877 * @param flatMapName The name to be used for flatMaps (either flatMap or foreach)
18541878 * @param enums The enumerators in the for expression
@@ -1973,37 +1997,86 @@ object desugar {
19731997 case (Tuple (ts1), Tuple (ts2)) => ts1.corresponds(ts2)(deepEquals)
19741998 case _ => false
19751999
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+ }
20072080 }
20082081 }
20092082
0 commit comments