Skip to content
This repository was archived by the owner on Jun 23, 2020. It is now read-only.

Commit 5e7e28e

Browse files
committed
SBT build, migrated tests to use toolbox compiler
1 parent e0c0f12 commit 5e7e28e

File tree

150 files changed

+1479
-1948
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

150 files changed

+1479
-1948
lines changed

.gitignore

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#
2+
# Are you tempted to edit this file?
3+
#
4+
# First consider if the changes make sense for all,
5+
# or if they are specific to your workflow/system.
6+
# If it is the latter, you can augment this list with
7+
# entries in .git/info/excludes
8+
#
9+
# see also test/files/.gitignore
10+
#
11+
12+
*.jar
13+
*~
14+
15+
build.properties
16+
17+
# target directories for ant build
18+
/build/
19+
/dists/
20+
21+
# other
22+
/out/
23+
/bin/
24+
/sandbox/
25+
26+
# eclipse, intellij
27+
/.classpath
28+
/.project
29+
/src/intellij/*.iml
30+
/src/intellij/*.ipr
31+
/src/intellij/*.iws
32+
/.cache
33+
/.idea
34+
/.settings
35+
36+
# bak files produced by ./cleanup-commit
37+
*.bak
38+
39+
# Standard symbolic link to build/quick/bin
40+
qbin
41+
42+
# Mac specific, but that is common enough a dev platform to warrant inclusion.
43+
.DS_Store
44+
45+
target/

.travis.yml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
language: scala
2+
script:
3+
- sbt ++$TRAVIS_SCALA_VERSION clean update compile test
4+
scala:
5+
- 2.11.0-SNAPSHOT
6+
jdk:
7+
- openjdk6
8+
- openjdk7
9+
notifications:
10+
email:
11+
12+
13+
# if we get weird timeouts, see https://github.com/spray/spray/pull/233
14+
# 'set concurrentRestrictions in Global += Tags.limit(Tags.Test, 1)'

LICENSE.md

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Copyright (c) 2010-2013 EPFL
2+
Copyright (c) 2011-2013 Typesafe, Inc.
3+
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without modification,
7+
are permitted provided that the following conditions are met:
8+
9+
* Redistributions of source code must retain the above copyright notice,
10+
this list of conditions and the following disclaimer.
11+
* Redistributions in binary form must reproduce the above copyright notice,
12+
this list of conditions and the following disclaimer in the documentation
13+
and/or other materials provided with the distribution.
14+
* Neither the name of the EPFL nor the names of its contributors
15+
may be used to endorse or promote products derived from this software
16+
without specific prior written permission.
17+
18+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
scala-continuations [<img src="https://api.travis-ci.org/scala/scala-continuations.png"/>](https://travis-ci.org/scala/scala-continuations)
2+
=========
3+
4+
The Scala Delimited Continuations Plugin and Library, which will continue to ship with Scala 2.11.0.
5+
6+
However, we're looking for a new maintainer for the scala-continuations project, as Typesafe does not have the resources to support and maintain it.
7+
8+
We believe most common use cases for CPS are met by https://github.com/scala/async.

build.sbt

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import Settings._
2+
import Keys.{`package` => packageTask }
3+
4+
// plugin logic of build based on https://github.com/retronym/boxer
5+
6+
lazy val commonSettings = scalaModuleSettings ++ Seq(
7+
repoName := "scala-continuations",
8+
organization := "org.scala-lang.plugins",
9+
version := "1.0.0-SNAPSHOT",
10+
scalaVersion := "2.11.0-M7",
11+
snapshotScalaBinaryVersion := "2.11.0-M7"
12+
)
13+
14+
lazy val root = project.in( file(".") ).settings( publishArtifact := false ).aggregate(plugin, library).settings(commonSettings : _*)
15+
16+
lazy val plugin = project settings (
17+
name := "scala-continuations-plugin",
18+
libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
19+
) settings (commonSettings : _*)
20+
21+
val pluginJar = packageTask in (plugin, Compile)
22+
23+
// TODO: the library project's test are really plugin tests, but we first need that jar
24+
lazy val library = project settings (
25+
name := "scala-continuations-library",
26+
scalacOptions ++= Seq(
27+
// add the plugin to the compiler
28+
s"-Xplugin:${pluginJar.value.getAbsolutePath}",
29+
// enable the plugin
30+
"-P:continuations:enable",
31+
// add plugin timestamp to compiler options to trigger recompile of
32+
// the library after editing the plugin. (Otherwise a 'clean' is needed.)
33+
s"-Jdummy=${pluginJar.value.lastModified}"),
34+
libraryDependencies ++= Seq(
35+
"org.scala-lang" % "scala-compiler" % scalaVersion.value % "test",
36+
"junit" % "junit" % "4.11" % "test",
37+
"com.novocode" % "junit-interface" % "0.10" % "test"),
38+
testOptions += Tests.Argument(
39+
TestFrameworks.JUnit,
40+
s"-Dscala-continuations-plugin.jar=${pluginJar.value.getAbsolutePath}"
41+
)
42+
) settings (commonSettings : _*)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
package scala.tools.selectivecps
2+
3+
import org.junit.Test
4+
5+
class CompilerErrors extends CompilerTesting {
6+
// @Test -- disabled
7+
def infer0 =
8+
expectCPSError("cannot cps-transform expression 8: type arguments [Int(8),String,Int] do not conform to method shiftUnit's type parameter bounds [A,B,C >: B]",
9+
"""|def test(x: => Int @cpsParam[String,Int]) = 7
10+
|
11+
|def main(args: Array[String]) = {
12+
| test(8)
13+
|}""")
14+
15+
@Test def function0 =
16+
expectCPSError("""|type mismatch;
17+
| found : () => Int @scala.util.continuations.cpsParam[Int,Int]
18+
| required: () => Int""".stripMargin,
19+
"""|def main(args: Array[String]): Any = {
20+
| val f = () => shift { k: (Int=>Int) => k(7) }
21+
| val g: () => Int = f
22+
|
23+
| println(reset(g()))
24+
|}""")
25+
26+
@Test def function2 =
27+
expectCPSError(
28+
"""|type mismatch;
29+
| found : () => Int
30+
| required: () => Int @scala.util.continuations.cpsParam[Int,Int]""".stripMargin,
31+
"""|def main(args: Array[String]): Any = {
32+
| val f = () => 7
33+
| val g: () => Int @cps[Int] = f
34+
|
35+
| println(reset(g()))
36+
|}""")
37+
38+
@Test def function3 =
39+
expectCPSError(
40+
"""|type mismatch;
41+
| found : Int @scala.util.continuations.cpsParam[Int,Int]
42+
| required: Int""".stripMargin,
43+
"""|def main(args: Array[String]): Any = {
44+
| val g: () => Int = () => shift { k: (Int=>Int) => k(7) }
45+
|
46+
| println(reset(g()))
47+
|}""")
48+
49+
@Test def infer2 =
50+
expectCPSError("illegal answer type modification: scala.util.continuations.cpsParam[String,Int] andThen scala.util.continuations.cpsParam[String,Int]",
51+
"""|def test(x: => Int @cpsParam[String,Int]) = 7
52+
|
53+
|def sym() = shift { k: (Int => String) => 9 }
54+
|
55+
|
56+
|def main(args: Array[String]): Any = {
57+
| test { sym(); sym() }
58+
|}""")
59+
60+
@Test def `lazy` =
61+
expectCPSError("implementation restriction: cps annotations not allowed on lazy value definitions",
62+
"""|def foo() = {
63+
| lazy val x = shift((k:Unit=>Unit)=>k())
64+
| println(x)
65+
|}
66+
|
67+
|def main(args: Array[String]) = {
68+
| reset {
69+
| foo()
70+
| }
71+
|}""")
72+
73+
@Test def t1929 =
74+
expectCPSError(
75+
"""|type mismatch;
76+
| found : Int @scala.util.continuations.cpsParam[String,String] @scala.util.continuations.cpsSynth
77+
| required: Int @scala.util.continuations.cpsParam[Int,String]""".stripMargin,
78+
"""|def main(args : Array[String]) {
79+
| reset {
80+
| println("up")
81+
| val x = shift((k:Int=>String) => k(8) + k(2))
82+
| println("down " + x)
83+
| val y = shift((k:Int=>String) => k(3))
84+
| println("down2 " + y)
85+
| y + x
86+
| }
87+
|}""")
88+
89+
@Test def t2285 =
90+
expectCPSError(
91+
"""|type mismatch;
92+
| found : Int @scala.util.continuations.cpsParam[String,String] @scala.util.continuations.cpsSynth
93+
| required: Int @scala.util.continuations.cpsParam[Int,String]""".stripMargin,
94+
"""|def bar() = shift { k: (String => String) => k("1") }
95+
|
96+
|def foo() = reset { bar(); 7 }""")
97+
98+
@Test def t2949 =
99+
expectCPSError(
100+
"""|type mismatch;
101+
| found : Int
102+
| required: ? @scala.util.continuations.cpsParam[List[?],Any]""".stripMargin,
103+
"""|def reflect[A,B](xs : List[A]) = shift{ xs.flatMap[B, List[B]] }
104+
|def reify[A, B](x : A @cpsParam[List[A], B]) = reset{ List(x) }
105+
|
106+
|def main(args: Array[String]): Unit = println(reify {
107+
| val x = reflect[Int, Int](List(1,2,3))
108+
| val y = reflect[Int, Int](List(2,4,8))
109+
| x * y
110+
|})""")
111+
112+
@Test def t3718 =
113+
expectCPSError(
114+
"cannot cps-transform malformed (possibly in shift/reset placement) expression",
115+
"scala.util.continuations.reset((_: Any).##)")
116+
117+
@Test def t5314_missing_result_type =
118+
expectCPSError(
119+
"method bar has return statement; needs result type",
120+
"""|def foo(x:Int): Int @cps[Int] = x
121+
|
122+
|def bar(x:Int) = return foo(x)
123+
|
124+
|reset {
125+
| val res = bar(8)
126+
| println(res)
127+
| res
128+
|}""")
129+
130+
@Test def t5314_npe =
131+
expectCPSError(
132+
"method bar has return statement; needs result type",
133+
"def bar(x:Int) = { return x; x } // NPE")
134+
135+
@Test def t5314_return_reset =
136+
expectCPSError(
137+
"return expression not allowed, since method calls CPS method",
138+
"""|val rnd = new scala.util.Random
139+
|
140+
|def foo(x: Int): Int @cps[Int] = shift { k => k(x) }
141+
|
142+
|def bar(x: Int): Int @cps[Int] = return foo(x)
143+
|
144+
|def caller(): Int = {
145+
| val v: Int = reset {
146+
| val res: Int = bar(8)
147+
| if (rnd.nextInt(100) > 50) return 5 // not allowed, since method is calling `reset`
148+
| 42
149+
| }
150+
| v
151+
|}
152+
|
153+
|caller()""")
154+
155+
@Test def t5314_type_error =
156+
expectCPSError(
157+
"""|type mismatch;
158+
| found : Int @scala.util.continuations.cpsParam[Int,Int]
159+
| required: Int @scala.util.continuations.cpsParam[String,String]""".stripMargin,
160+
"""|def foo(x:Int): Int @cps[Int] = shift { k => k(x) }
161+
|
162+
|// should be a type error
163+
|def bar(x:Int): Int @cps[String] = return foo(x)
164+
|
165+
|def caller(): Unit = {
166+
| val v: String = reset {
167+
| val res: Int = bar(8)
168+
| "hello"
169+
| }
170+
|}
171+
|
172+
|caller()""")
173+
174+
@Test def t5445 =
175+
expectCPSError(
176+
"cps annotations not allowed on by-value parameters or value definitions",
177+
"def foo(block: Unit @suspendable ): Unit @suspendable = {}")
178+
179+
@Test def trycatch2 =
180+
expectCPSErrors(2, "only simple cps types allowed in try/catch blocks (found: Int @scala.util.continuations.cpsParam[String,Int])",
181+
"""|def fatal[T]: T = throw new Exception
182+
|def cpsIntStringInt = shift { k:(Int=>String) => k(3); 7 }
183+
|def cpsIntIntString = shift { k:(Int=>Int) => k(3); "7" }
184+
|
185+
|def foo1 = try {
186+
| fatal[Int]
187+
| cpsIntStringInt
188+
|} catch {
189+
| case ex: Throwable =>
190+
| cpsIntStringInt
191+
|}
192+
|
193+
|def foo2 = try {
194+
| fatal[Int]
195+
| cpsIntStringInt
196+
|} catch {
197+
| case ex: Throwable =>
198+
| cpsIntStringInt
199+
|}
200+
|
201+
|
202+
|def main(args: Array[String]): Unit = {
203+
| println(reset { foo1; "3" })
204+
| println(reset { foo2; "3" })
205+
|}""")
206+
}
207+
208+
class CompilerTesting {
209+
def loadPlugin = s"-Xplugin:${sys.props("scala-continuations-plugin.jar")} -P:continuations:enable"
210+
211+
// note: `code` should have a | margin
212+
def cpsErrorMessages(msg: String, code: String) =
213+
errorMessages(msg, loadPlugin)(s"import scala.util.continuations._\nobject Test {\n${code.stripMargin}\n}")
214+
215+
def expectCPSError(msg: String, code: String) = {
216+
val errors = cpsErrorMessages(msg, code)
217+
assert(errors exists (_ contains msg), errors mkString "\n")
218+
}
219+
220+
def expectCPSErrors(msgCount: Int, msg: String, code: String) = {
221+
val errors = cpsErrorMessages(msg, code)
222+
val errorCount = errors.filter(_ contains msg).length
223+
assert(errorCount == msgCount, s"$errorCount occurrences of \'$msg\' found -- expected $msgCount in:\n${errors mkString "\n"}")
224+
}
225+
226+
// TODO: move to scala.tools.reflect.ToolboxFactory
227+
def errorMessages(errorSnippet: String, compileOptions: String)(code: String): List[String] = {
228+
import scala.tools.reflect._
229+
val m = scala.reflect.runtime.currentMirror
230+
val tb = m.mkToolBox(options = compileOptions) //: ToolBox[m.universe.type]
231+
val fe = tb.frontEnd
232+
233+
try {
234+
tb.eval(tb.parse(code))
235+
Nil
236+
} catch {
237+
case _: ToolBoxError =>
238+
import fe._
239+
infos.toList collect { case Info(_, msg, ERROR) => msg }
240+
}
241+
}
242+
}

test/pending/continuations-pos/t3620.scala renamed to library/src/test/scala/scala/tools/selectivecps/ShouldCompile.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import scala.collection.mutable.HashMap
22
import scala.util.continuations._
33

4-
object Test extends Application {
4+
// https://issues.scala-lang.org/browse/SI-3620
5+
object t3620 extends App {
56

67
class Store[K,V] {
78

0 commit comments

Comments
 (0)