package mumbler.truffle.node.call;
import java.util.Arrays;
import mumbler.truffle.node.MumblerNode;
import mumbler.truffle.type.MumblerFunction;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.dsl.UnsupportedSpecializationException;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.source.SourceSection;
public class InvokeNode extends MumblerNode {
@Child protected MumblerNode functionNode;
@Children protected final MumblerNode[] argumentNodes;
@Child protected DispatchNode dispatchNode;
public InvokeNode(MumblerNode functionNode, MumblerNode[] argumentNodes,
SourceSection sourceSection) {
this.functionNode = functionNode;
this.argumentNodes = argumentNodes;
this.dispatchNode = new UninitializedDispatchNode();
setSourceSection(sourceSection);
}
@Override
@ExplodeLoop
public Object execute(VirtualFrame virtualFrame) {
MumblerFunction function = this.evaluateFunction(virtualFrame);
CompilerAsserts.compilationConstant(this.argumentNodes.length);
CompilerAsserts.compilationConstant(this.isTail());
Object[] argumentValues = new Object[this.argumentNodes.length + 1];
argumentValues[0] = function.getLexicalScope();
for (int i=0; i<this.argumentNodes.length; i++) {
argumentValues[i+1] = this.argumentNodes[i].execute(virtualFrame);
}
return call(virtualFrame, function.callTarget, argumentValues);
}
protected Object call(VirtualFrame virtualFrame, CallTarget callTarget,
Object[] arguments) {
return this.dispatchNode.executeDispatch(virtualFrame,
callTarget, arguments);
}
private MumblerFunction evaluateFunction(VirtualFrame virtualFrame) {
try {
return this.functionNode.executeMumblerFunction(virtualFrame);
} catch (UnexpectedResultException e) {
throw new UnsupportedSpecializationException(this,
new Node[] {this.functionNode}, e);
}
}
@Override
public String toString() {
return "(apply " + this.functionNode + " " +
Arrays.toString(this.argumentNodes) + ")";
}
}