package orc.run.porce;

import com.oracle.truffle.api.frame.VirtualFrame;

import orc.run.porce.runtime.CPSCallResponseHandler;
import orc.run.porce.runtime.Counter;
import orc.run.porce.runtime.PorcEClosure;
import orc.run.porce.runtime.PorcEExecutionRef;
import orc.run.porce.runtime.Terminator;

public class InterceptedCall extends CallBase {
	protected InterceptedCall(Expression target, Expression[] arguments, PorcEExecutionRef execution) {
		super(target, arguments, execution);
	}

	public Object executeWithValues(final VirtualFrame frame, final Object newTarget, final Object[] newArguments) {
		final PorcEClosure pub = (PorcEClosure) newArguments[0];
		final Counter counter = (Counter) newArguments[1];
		final Terminator term = (Terminator) newArguments[2];

		// Token: Passed to handle from arguments.
		final CPSCallResponseHandler handle = new CPSCallResponseHandler(execution.get(), pub, counter, term, getCallSiteId());

		execution.get().invokeIntercepted(handle, newTarget, buildArgumentValues(newArguments));
		return PorcEUnit.SINGLETON;
	}

	@Override
	public Object execute(final VirtualFrame frame) {
		final Object targetValue = executeTargetClosure(frame);
		final Object[] argumentValues = new Object[arguments.length];
		executeArguments(argumentValues, 0, 0, frame);

		return executeWithValues(frame, targetValue, argumentValues);
	}

	protected Object[] buildArgumentValues(final Object[] newArguments) {
		final Object[] argumentValues = new Object[newArguments.length - 3];
		System.arraycopy(newArguments, 3, argumentValues, 0, argumentValues.length);
		return argumentValues;
	}

	public static InterceptedCall create(Expression target, Expression[] arguments, PorcEExecutionRef execution) {
		return new InterceptedCall(target, arguments, execution);
	}
}

@@ -13,24 +13,90 @@
 run.porce;%0A%0A
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;%0A
 import com.o
@@ -1001,16 +1001,273 @@
 Id());%0A%0A
+%09%09invokeInterceptedWithBoundary(handle, newTarget, newArguments);%0A%09%09return PorcEUnit.SINGLETON;%0A%09%7D%0A%0A%09@TruffleBoundary%0A%09private void invokeInterceptedWithBoundary(final CPSCallResponseHandler handle, final Object newTarget,%0A%09%09%09final Object%5B%5D newArguments) %7B%0A
 %09%09execut
@@ -1353,38 +1353,8 @@
 ));%0A
-%09%09return PorcEUnit.SINGLETON;%0A
 %09%7D%0A%0A

Put a call boundary before calling into DOrc.