static void CallPrimitive(Callable callable, Vm vm, int numArgs, bool saveReturnAddress, bool inApply)
{
bool isRequiredPrimitive = false;
if (callable.Prim0Name != null) {
isRequiredPrimitive = true;
if (callable.RequiredPrimitive == null) {
callable.RequiredPrimitive = Vm.Prim0Hash [callable.Prim0Name].RequiredPrimitive;
}
} else if (callable.UserDefinedPrimitive == null) {
callable.UserDefinedPrimitive = GetUdpByName (vm, callable.UdpName).UserDefinedPrimitive;
}
if (callable.Arity != null && callable.Arity.Value != numArgs) {
ArityError (vm, callable.Arity.Value, numArgs, inApply);
}
Value[] array;
int start;
if (isRequiredPrimitive) {
vm.stack.Pop (); // Remove the callable.
vm.stack.GetTopRange (numArgs, out array, out start);
FinishPrimitiveCall (
vm, numArgs, saveReturnAddress,
callable.RequiredPrimitive (vm.api, array, start, numArgs));
} else {
vm.stack.GetTopRange (numArgs + 1, out array, out start);
var udpResult = new UdpResult ();
Value[] args = new Value[numArgs];
Array.Copy (vm.stack.Storage, start, args, 0, numArgs);
try {
callable.UserDefinedPrimitive (vm.api, args, udpResult);
} catch (Exception ex) {
vm.userDefinedPrimitiveError = ex;
vm.shouldTakeANap = true;
}
switch (udpResult.After) {
case UdpResult.AfterCall.Continue:
vm.stack.Pop ();
FinishPrimitiveCall (vm, numArgs, saveReturnAddress, udpResult.Result);
break;
case UdpResult.AfterCall.Nap:
vm.stack.Pop ();
FinishPrimitiveCall (vm, numArgs, saveReturnAddress, udpResult.Result);
vm.shouldTakeANap = true;
break;
case UdpResult.AfterCall.NapAndRetryOnWakeUp:
vm.shouldTakeANap = true;
break;
}
}
}