package com.oracle.truffle.js.nodes.function;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrumentation.Tag;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.js.nodes.JavaScriptNode;
import com.oracle.truffle.js.nodes.access.GetIteratorNode;
import com.oracle.truffle.js.nodes.access.IteratorGetNextValueNode;
import com.oracle.truffle.js.nodes.access.JSConstantNode;
import com.oracle.truffle.js.runtime.Errors;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.objects.IteratorRecord;
import com.oracle.truffle.js.runtime.util.SimpleArrayList;
import java.util.Set;
public final class SpreadArgumentNode extends JavaScriptNode {
@Child private GetIteratorNode getIteratorNode;
@Child private IteratorGetNextValueNode iteratorStepNode;
private final BranchProfile errorBranch = BranchProfile.create();
private final BranchProfile listGrowProfile = BranchProfile.create();
private final JSContext context;
private SpreadArgumentNode(JSContext context, JavaScriptNode arg) {
this.context = context;
this.getIteratorNode = GetIteratorNode.create(context, arg);
this.iteratorStepNode = IteratorGetNextValueNode.create(context, null, JSConstantNode.create(null), false);
}
@Override
public boolean isInstrumentable() {
return false;
}
public static SpreadArgumentNode create(JSContext context, JavaScriptNode arg) {
return new SpreadArgumentNode(context, arg);
}
@Override
public Object[] execute(VirtualFrame frame) {
SimpleArrayList<Object> argList = new SimpleArrayList<>();
executeToList(frame, argList, listGrowProfile);
return argList.toArray();
}
public void executeToList(VirtualFrame frame, SimpleArrayList<Object> argList, BranchProfile growProfile) {
IteratorRecord iteratorRecord = getIteratorNode.execute(frame);
for (;;) {
Object nextArg = iteratorStepNode.execute(frame, iteratorRecord);
if (nextArg == null) {
break;
}
if (argList.size() >= context.getFunctionArgumentsLimit()) {
errorBranch.enter();
throw Errors.createRangeError("spreaded function argument count exceeds limit");
}
argList.add(nextArg, growProfile);
}
}
@Override
protected JavaScriptNode copyUninitialized(Set<Class<? extends Tag>> materializedTags) {
SpreadArgumentNode copy = (SpreadArgumentNode) copy();
copy.getIteratorNode = cloneUninitialized(getIteratorNode, materializedTags);
copy.iteratorStepNode = cloneUninitialized(iteratorStepNode, materializedTags);
return copy;
}
}