//
// TailCallException.java -- Java class TailCallException
// Project PorcE
//
// Copyright (c) 2017 The University of Texas at Austin. All rights reserved.
//
// Use and redistribution of this file is governed by the license terms in
// the LICENSE file found in the project's top-level directory and also found at
// URL: http://orc.csres.utexas.edu/license.shtml .
//

package orc.run.porce.runtime;

import com.oracle.truffle.api.nodes.ControlFlowException;

/**
 * An internal PorcE exception which is used to implement universal TCO.
 * 
 * This exception is throw by calls to a different function in tail positions and
 * then caught in a trampoline wrapped around the current call and dispatched to
 * the specified closures. This unwinds the stack to avoid growing the stack in
 * co-recursive situations.
 * 
 * @author amp
 */
@SuppressWarnings("serial")
public final class TailCallException extends ControlFlowException {
	public PorcEClosure target;
	public Object[] arguments;

	private TailCallException(PorcEClosure target, Object[] arguments) {
		this.target = target;
		this.arguments = arguments;
	}
	
	public static TailCallException create(PorcEClosure target) {
		// FIXME: This sets a maximum working function arity to 16.
		TailCallException tce = new TailCallException(target, new Object[17]);
		tce.arguments[16] = tce;
		return tce;
	}
	
	public static TailCallException create(PorcEClosure target, Object[] arguments) {
		// FIXME: This sets a maximum working function arity to 16.
		TailCallException tce = new TailCallException(target, new Object[17]);
		System.arraycopy(arguments, 0, tce.arguments, 0, arguments.length);
		tce.arguments[16] = tce;
		return tce;
	}
}

@@ -399,16 +399,66 @@
 ntime;%0A%0A
+import com.oracle.truffle.api.frame.VirtualFrame;%0A
 import c
@@ -507,16 +507,16 @@
 eption;%0A
-
 %0A/**%0A * 
@@ -583,25 +583,24 @@
 rsal TCO.%0A *
- 
 %0A * This exc
@@ -861,17 +861,16 @@
 ions.%0A *
- 
 %0A * @aut
@@ -1158,25 +1158,390 @@
 guments;%0A%09%7D%0A
-%09
+%0A        public void assignFrom(TailCallException e) %7B%0A            this.target = e.target;%0A            // Copy at most 16 to avoid overwriting the self reference in the arguments.%0A            System.arraycopy(e.arguments, 0, this.arguments, 0, Math.min(e.arguments.length, 16));%0A            assert this.arguments.length %3C 17 %7C%7C this.arguments%5B16%5D == this;%0A        %7D%0A
 %0A%09public sta
@@ -1775,10 +1775,9 @@
 %0A%09%7D%0A
-%09
 %0A
+
 %09pub
@@ -2101,13 +2101,422 @@
 rn tce;%0A
-
 %09%7D
+%0A%0A        public static TailCallException get(final VirtualFrame frame) %7B%0A            Object%5B%5D thisArguments = frame.getArguments();%0A            if (thisArguments.length == 17 && thisArguments%5B16%5D instanceof TailCallException) %7B%0A                TailCallException tce = (TailCallException) thisArguments%5B16%5D;%0A                return tce;%0A            %7D else %7B%0A                return null;%0A            %7D%0A        %7D
 %0A%7D%0A

Add utilities to TailCallException.