summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2006-11-29 17:26:59 +0000
committerMartin Odersky <odersky@gmail.com>2006-11-29 17:26:59 +0000
commit8809b3edf2ca73f0c584507dcf09da58fddc7648 (patch)
treeff48034ee024941943f5985fd2572aa4c40620f1
parentf8b32f27f6cebfa2136da27d9bb2fb1fed9b6e80 (diff)
downloadscala-8809b3edf2ca73f0c584507dcf09da58fddc7648.tar.gz
scala-8809b3edf2ca73f0c584507dcf09da58fddc7648.tar.bz2
scala-8809b3edf2ca73f0c584507dcf09da58fddc7648.zip
fixed bug851
added "Function" module to library/scala
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala3
-rw-r--r--src/library/scala/Function.scala118
-rw-r--r--test/files/neg/implicits.check8
-rwxr-xr-xtest/files/neg/implicits.scala22
-rw-r--r--test/files/pos/bug851.scala28
5 files changed, 179 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index 8004976cf5..d612148cfc 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -289,7 +289,10 @@ trait Scanners requires SyntaxAnalyzer {
in.next
if (in.ch == '\"') {
in.next
+ val saved = in.lineStartPos
getMultiLineStringLit
+ if (in.lineStartPos != saved) // ignore linestarts within a mulit-line string
+ in.lastLineStartPos = saved
} else {
token = STRINGLIT
name = nme.EMPTY
diff --git a/src/library/scala/Function.scala b/src/library/scala/Function.scala
new file mode 100644
index 0000000000..7e6e29b0f0
--- /dev/null
+++ b/src/library/scala/Function.scala
@@ -0,0 +1,118 @@
+package scala
+
+/** A module defining utility methods for higher-order functional programming.
+ */
+object Function extends Application {
+
+ /** Given a sequence of functions f_1, ..., f_n, return the
+ * function `f_1 andThen ... andThen f_n'.
+ * @param fs The given sequence of functions
+ */
+ def chain[a](fs: Seq[a => a]): a => a = { x => (x /: fs) ((x, f) => f(x)) }
+
+ /** Currying for functions of arity 2. This transforms a function
+ * of arity 2 into a a unary function returning another unary function.
+ */
+ def curried[a1, a2, b](f: (a1, a2) => b): a1 => a2 => b = {
+ x1 => x2 => f(x1, x2)
+ }
+
+ /** Currying for functions of arity 3.
+ */
+ def curried[a1, a2, a3, b](f: (a1, a2, a3) => b): a1 => a2 => a3 => b = {
+ x1 => x2 => x3 => f(x1, x2, x3)
+ }
+
+ /** Currying for functions of arity 4.
+ */
+ def curried[a1, a2, a3, a4, b](f: (a1, a2, a3, a4) => b): a1 => a2 => a3 => a4 => b = {
+ x1 => x2 => x3 => x4 => f(x1, x2, x3, x4)
+ }
+
+ /** Currying for functions of arity 5.
+ */
+ def curried[a1, a2, a3, a4, a5, b](f: (a1, a2, a3, a4, a5) => b): a1 => a2 => a3 => a4 => a5 => b = {
+ x1 => x2 => x3 => x4 => x5 => f(x1, x2, x3, x4, x5)
+ }
+
+ /** Uncurrying for functions of arity 2. This transforms a unary function
+ * returning another unary function into a function of arity 2.
+ */
+ def uncurried[a1, a2, b](f: a1 => a2 => b): (a1, a2) => b = {
+ (x1, x2) => f(x1)(x2)
+ }
+
+ /** Uncurrying for functions of arity 3.
+ */
+ def uncurried[a1, a2, a3, b](f: a1 => a2 => a3 => b): (a1, a2, a3) => b = {
+ (x1, x2, x3) => f(x1)(x2)(x3)
+ }
+
+ /** Uncurrying for functions of arity 4.
+ */
+ def uncurried[a1, a2, a3, a4, b](f: a1 => a2 => a3 => a4 => b): (a1, a2, a3, a4) => b = {
+ (x1, x2, x3, x4) => f(x1)(x2)(x3)(x4)
+ }
+
+ /** Uncurrying for functions of arity 5.
+ */
+ def uncurried[a1, a2, a3, a4, a5, b](f: a1 => a2 => a3 => a4 => a5 => b): (a1, a2, a3, a4, a5) => b = {
+ (x1, x2, x3, x4, x5) => f(x1)(x2)(x3)(x4)(x5)
+ }
+
+ /** Tupling for functions of arity 2. This transforms a function
+ * of arity 2 into a unary function that takes a pair of arguments.
+ */
+ def tupled[a1, a2, b](f: (a1, a2) => b): Tuple2[a1, a2] => b = {
+ case Tuple2(x1, x2) => f(x1, x2)
+ }
+
+ /** Tupling for functions of arity 3. This transforms a function
+ * of arity 3 into a unary function that takes a triple of arguments.
+ */
+ def tupled[a1, a2, a3, b](f: (a1, a2, a3) => b): Tuple3[a1, a2, a3] => b = {
+ case Tuple3(x1, x2, x3) => f(x1, x2, x3)
+ }
+
+ /** Tupling for functions of arity 4. This transforms a function
+ * of arity 4 into a unary function that takes a 4-tuple of arguments.
+ */
+ def tupled[a1, a2, a3, a4, b](f: (a1, a2, a3, a4) => b): Tuple4[a1, a2, a3, a4] => b = {
+ case Tuple4(x1, x2, x3, x4) => f(x1, x2, x3, x4)
+ }
+
+ /** Tupling for functions of arity 5. This transforms a function
+ * of arity 5 into a unary function that takes a 5-tuple of arguments.
+ */
+ def tupled[a1, a2, a3, a4, a5, b](f: (a1, a2, a3, a4, a5) => b): Tuple5[a1, a2, a3, a4, a5] => b = {
+ case Tuple5(x1, x2, x3, x4, x5) => f(x1, x2, x3, x4, x5)
+ }
+
+ /** Un-tupling for functions of arity 2. This transforms a function taking
+ * a pair of arguments into a binary function which takes each argument separately.
+ */
+ def untupled[a1, a2, b](f: Tuple2[a1, a2] => b): (a1, a2) => b = {
+ (x1, x2) => f(Tuple2(x1, x2))
+ }
+
+ /** Un-tupling for functions of arity 3. This transforms a function taking
+ * a triple of arguments into a ternary function which takes each argument separately.
+ */
+ def untupled[a1, a2, a3, b](f: Tuple3[a1, a2, a3] => b): (a1, a2, a3) => b = {
+ (x1, x2, x3) => f(Tuple3(x1, x2, x3))
+ }
+
+ /** Un-tupling for functions of arity 4. This transforms a function taking
+ * a 4-tuple of arguments into a function of arity 4 which takes each argument separately.
+ */
+ def untupled[a1, a2, a3, a4, b](f: Tuple4[a1, a2, a3, a4] => b): (a1, a2, a3, a4) => b = {
+ (x1, x2, x3, x4) => f(Tuple4(x1, x2, x3, x4))
+ }
+
+ /** Un-tupling for functions of arity 5. This transforms a function taking
+ * a 5-tuple of arguments into a function of arity 5 which takes each argument separately.
+ */
+ def untupled[a1, a2, a3, a4, a5, b](f: Tuple5[a1, a2, a3, a4, a5] => b): (a1, a2, a3, a4, a5) => b = {
+ (x1, x2, x3, x4, x5) => f(Tuple5(x1, x2, x3, x4, x5))
+ }
+}
diff --git a/test/files/neg/implicits.check b/test/files/neg/implicits.check
new file mode 100644
index 0000000000..d1bbd2b3f0
--- /dev/null
+++ b/test/files/neg/implicits.check
@@ -0,0 +1,8 @@
+implicits.scala:21 error: ambiguous implicit value:
+ most specific definition is: method pos2int in object Super of type (Pos)scala.Int
+ yet alternative definition method any2plus in object Sub of type (scala.Any)Sub.Plus
+ is defined in a subclass.
+ Both definitions are possible conversion functions from Pos to ?{val +: ?}
+ f(p+1)
+ ^
+one error found
diff --git a/test/files/neg/implicits.scala b/test/files/neg/implicits.scala
new file mode 100755
index 0000000000..710ffc94fc
--- /dev/null
+++ b/test/files/neg/implicits.scala
@@ -0,0 +1,22 @@
+class Pos
+
+class Super
+
+object Super {
+ implicit def pos2int(p: Pos): int = 0
+}
+
+object Sub extends Super {
+ class Plus(x: Any) {
+ def +(y: String): String = x.toString + y
+ }
+ implicit def any2plus(x: Any): Plus = new Plus(x)
+}
+
+object Test {
+ import Super._
+ import Sub._
+ val p = new Pos
+ def f(x: int): int = x
+ f(p+1)
+}
diff --git a/test/files/pos/bug851.scala b/test/files/pos/bug851.scala
new file mode 100644
index 0000000000..afe4b79d3c
--- /dev/null
+++ b/test/files/pos/bug851.scala
@@ -0,0 +1,28 @@
+object test {
+ def ok1: String = {
+ val x = 1
+ """ok1"""
+ }
+ def ok2: String = {
+ val x = "0".length
+ """ok2"""
+ }
+ def ok3: String = {
+ val x = "0".length
+ """ok3
+ """//
+ }
+ def ok4: String = {
+ val x = "0".length
+ """ok4
+ """ + x
+ }
+ def bad: String = {
+ val x = "0".length
+ """bad
+ """
+ }
+ def main(args: Array[String]) {
+ Console.println(ok1 + ok2 + ok3 + ok4 + bad)
+ }
+}