From df50e05006b43b007c2587549030d24b5c154398 Mon Sep 17 00:00:00 2001 From: Gilles Dubochet Date: Fri, 16 Dec 2005 18:29:42 +0000 Subject: 'test-nsc' has been moved to 'test'. --- test/files/run/tailcalls.scala | 290 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 test/files/run/tailcalls.scala (limited to 'test/files/run/tailcalls.scala') 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; + } +} + +//############################################################################ -- cgit v1.2.3