summaryrefslogtreecommitdiff
path: root/test/files/run/tailcalls.scala
diff options
context:
space:
mode:
authorGilles Dubochet <gilles.dubochet@epfl.ch>2005-12-16 18:29:42 +0000
committerGilles Dubochet <gilles.dubochet@epfl.ch>2005-12-16 18:29:42 +0000
commitdf50e05006b43b007c2587549030d24b5c154398 (patch)
tree9edfb1fb5b8c04350a00c163cfcdb1fccd79e3aa /test/files/run/tailcalls.scala
parent17e2b1c2a6f69ba74e79c30d1e44195fe732e3e3 (diff)
downloadscala-df50e05006b43b007c2587549030d24b5c154398.tar.gz
scala-df50e05006b43b007c2587549030d24b5c154398.tar.bz2
scala-df50e05006b43b007c2587549030d24b5c154398.zip
'test-nsc' has been moved to 'test'.
Diffstat (limited to 'test/files/run/tailcalls.scala')
-rw-r--r--test/files/run/tailcalls.scala290
1 files changed, 290 insertions, 0 deletions
diff --git a/test/files/run/tailcalls.scala b/test/files/run/tailcalls.scala
new file mode 100644
index 0000000000..3279e6bf64
--- /dev/null
+++ b/test/files/run/tailcalls.scala
@@ -0,0 +1,290 @@
+//############################################################################
+// Tail Calls
+//############################################################################
+// $Id$
+
+//############################################################################
+// Calibration
+
+class Calibrator {
+ def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+}
+
+//############################################################################
+// Tail calls in different contexts
+
+class Class {
+ def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+}
+
+class SubClass extends Class {
+ override def f(n: Int, v: Int): Int = v;
+}
+
+sealed class Sealed {
+ def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+}
+
+class SubSealed extends Sealed {
+ override def f(n: Int, v: Int): Int = v;
+}
+
+final class Final {
+ def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+}
+
+object Object {
+ def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+}
+
+//############################################################################
+// Tail calls in nested objects/classes
+
+object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ val c: C = new C;
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ val c: C = new C;
+ }
+ val c: C = new C;
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ val c: C = new C;
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ val c: C = new C;
+ }
+ val c: C = new C;
+ }
+ val c: C = new C;
+}
+
+class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ val c: C = new C;
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ val c: C = new C;
+ }
+ val c: C = new C;
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ val c: C = new C;
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ object O {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ class C {
+ final def f(n: Int, v: Int): Int = if (n == 0) v else f(n - 1, v - 1);
+ }
+ val c: C = new C;
+ }
+ val c: C = new C;
+ }
+ val c: C = new C;
+}
+
+//############################################################################
+// Tail calls with different signatures
+
+class TailCall[S](s: S) {
+ def getS: S = s;
+
+ final def f1(n: Int, v: Int): Int =
+ if (n == 0) v else f1(n - 1, v - 1);
+ final def f2[T](n: Int, v: Int): Int =
+ if (n == 0) v else f2[T](n - 1, v - 1);
+ final def f3[T](n: Int, v: Int, ls: List[T]): Int =
+ if (n == 0) v else f3(n - 1, v - 1, ls);
+
+ final def g1(x: Int, y: Int): Int = {
+ def aux(n: Int, v: Int): Int =
+ if (n == 0) v else aux(n - 1, v - 1);
+ aux(x, y);
+ }
+ final def g2[T](x: Int, y: Int): Int = {
+ def aux[U](n: Int, v: Int): Int =
+ if (n == 0) v else aux[U](n - 1, v - 1);
+ aux[T](x, y);
+ }
+ final def g3[T](x: Int, y: Int, zs: List[T]): Int = {
+ def aux[U](n: Int, v: Int, ls: List[Pair[T,U]]): Int =
+ if (n == 0) v else aux(n - 1, v - 1, ls);
+ aux(x, y, Nil);
+ }
+
+ def h1(n: Int, v: Int): Int = hP(n, v);
+ private def hP(n: Int, v: Int): Int = if (n == 0) v else hP(n - 1, v - 1);
+
+ // !!! test return in non-tail-call position
+ // !!! test non-same-instance calls
+ // !!! test non-same-type calls
+
+}
+
+//############################################################################
+// Test code
+
+object Test {
+ def check_success(name: String, closure: => Int, expected: Int): Unit = {
+ Console.print("test " + name);
+ try {
+ val actual: Int = closure;
+ if (actual == expected) {
+ Console.print(" was successful");
+ } else {
+ Console.print(" failed: expected "+ expected +", found "+ actual);
+ }
+ } catch {
+ case exception: Throwable => {
+ Console.print(" raised exception " + exception);
+ }
+ }
+ Console.println;
+ }
+
+ def calibrate: Int = {
+ val calibrator = new Calibrator();
+ var stop = false;
+ var n = 1;
+ while (!stop) {
+ try {
+ calibrator.f(n, n);
+ if (n >= scala.runtime.compat.Math.MAX_INT / 2) error("calibration failure");
+ n = 2 * n;
+ } catch {
+ case exception: StackOverflowError => stop = true
+ }
+ }
+ 4 * n;
+ }
+
+ def main(args: Array[String]): Unit = {
+ // compute min and max iteration number
+ val min = 16;
+ val max = calibrate;
+
+ // test tail calls in different contexts
+ val Final = new Final();
+ val Class = new Class();
+ val SubClass = new SubClass();
+ val Sealed = new Sealed();
+ val SubSealed = new SubSealed();
+ check_success("Object .f", Object .f(max, max), 0);
+ check_success("Final .f", Final .f(max, max), 0);
+ check_success("Class .f", Class .f(max, max), 0);
+ check_success("SubClass .f", SubClass .f(max, max), max);
+ check_success("Sealed .f", Sealed .f(max, max), 0);
+ check_success("SubSealed.f", SubSealed.f(max, max), max);
+ Console.println;
+
+ // test tail calls in nested classes/objects
+ val c: C = new C;
+ check_success("O .f", O .f(max, max), 0);
+ check_success("c .f", c .f(max, max), 0);
+ check_success("O.O .f", O.O .f(max, max), 0);
+ check_success("O.c .f", O.c .f(max, max), 0);
+ check_success("c.O .f", c.O .f(max, max), 0);
+ check_success("c.c .f", c.c .f(max, max), 0);
+ check_success("O.O.O .f", O.O.O .f(max, max), 0);
+ check_success("O.O.c .f", O.O.c .f(max, max), 0);
+ check_success("O.c.O .f", O.c.O .f(max, max), 0);
+ check_success("O.c.c .f", O.c.c .f(max, max), 0);
+ check_success("c.O.O .f", c.O.O .f(max, max), 0);
+ check_success("c.O.c .f", c.O.c .f(max, max), 0);
+ check_success("c.c.O .f", c.c.O .f(max, max), 0);
+ check_success("c.c.c .f", c.c.c .f(max, max), 0);
+ check_success("O.O.O.O.f", O.O.O.O.f(max, max), 0);
+ check_success("O.O.O.c.f", O.O.O.c.f(max, max), 0);
+ check_success("O.O.c.O.f", O.O.c.O.f(max, max), 0);
+ check_success("O.O.c.c.f", O.O.c.c.f(max, max), 0);
+ check_success("O.c.O.O.f", O.c.O.O.f(max, max), 0);
+ check_success("O.c.O.c.f", O.c.O.c.f(max, max), 0);
+ check_success("O.c.c.O.f", O.c.c.O.f(max, max), 0);
+ check_success("O.c.c.c.f", O.c.c.c.f(max, max), 0);
+ check_success("c.O.O.O.f", c.O.O.O.f(max, max), 0);
+ check_success("c.O.O.c.f", c.O.O.c.f(max, max), 0);
+ check_success("c.O.c.O.f", c.O.c.O.f(max, max), 0);
+ check_success("c.O.c.c.f", c.O.c.c.f(max, max), 0);
+ check_success("c.c.O.O.f", c.c.O.O.f(max, max), 0);
+ check_success("c.c.O.c.f", c.c.O.c.f(max, max), 0);
+ check_success("c.c.c.O.f", c.c.c.O.f(max, max), 0);
+ check_success("c.c.c.c.f", c.c.c.c.f(max, max), 0);
+ Console.println;
+
+ // test tail calls with different signatures
+ val TailCall = new TailCall("S");
+ check_success("TailCall.f1", TailCall.f1(max, max ), 0);
+ check_success("TailCall.f2", TailCall.f2(max, max ), 0);
+ check_success("TailCall.f3", TailCall.f3(max, max, Nil), 0);
+ check_success("TailCall.g1", TailCall.g1(max, max ), 0);
+ check_success("TailCall.g2", TailCall.g2(max, max ), 0);
+ check_success("TailCall.g3", TailCall.g3(max, max, Nil), 0);
+ check_success("TailCall.h1", TailCall.h1(max, max ), 0);
+ Console.println;
+ }
+}
+
+//############################################################################