void ImplementByRefICallableCall( Method call, InternalCallableType type, ClassDefinition node, CallableSignature signature, int byRefCount) { MethodInvocationExpression mie = CreateInvokeInvocation(type); IParameter[] parameters = signature.Parameters; ReferenceExpression args = CodeBuilder.CreateReference(call.Parameters[0]); InternalLocal[] temporaries = new InternalLocal[byRefCount]; int byRefIndex = 0; for (int i=0; i<parameters.Length; ++i) { SlicingExpression slice = CodeBuilder.CreateSlicing(args.CloneNode(), i); IParameter parameter = parameters[i]; if (parameter.IsByRef) { IType tempType = parameter.Type; if (tempType.IsByRef) { tempType = tempType.ElementType; } temporaries[byRefIndex] = CodeBuilder.DeclareLocal(call, "__temp_" + parameter.Name, tempType); call.Body.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateReference(temporaries[byRefIndex]), CodeBuilder.CreateCast( tempType, slice))); mie.Arguments.Add( CodeBuilder.CreateReference( temporaries[byRefIndex])); ++byRefIndex; } else { mie.Arguments.Add(slice); } } if (TypeSystemServices.VoidType == signature.ReturnType) { call.Body.Add(mie); PropagateByRefParameterChanges(call, parameters, temporaries); } else { InternalLocal invokeReturnValue = CodeBuilder.DeclareLocal(call, "__returnValue", signature.ReturnType); call.Body.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateReference(invokeReturnValue), mie)); PropagateByRefParameterChanges(call, parameters, temporaries); call.Body.Add( new ReturnStatement( CodeBuilder.CreateReference(invokeReturnValue))); } }
void ImplementRegularICallableCall( Method call, InternalCallableType type, ClassDefinition node, CallableSignature signature) { MethodInvocationExpression mie = CreateInvokeInvocation(type); IParameter[] parameters = signature.Parameters; int fixedParametersLength = signature.AcceptVarArgs ? parameters.Length - 1 : parameters.Length; for (int i=0; i<fixedParametersLength; ++i) { SlicingExpression slice = CodeBuilder.CreateSlicing( CodeBuilder.CreateReference(call.Parameters[0]), i); mie.Arguments.Add(slice); } if (signature.AcceptVarArgs) { if (parameters.Length == 1) { mie.Arguments.Add(CodeBuilder.CreateReference(call.Parameters[0])); } else { mie.Arguments.Add( CodeBuilder.CreateMethodInvocation( RuntimeServices_GetRange1, CodeBuilder.CreateReference(call.Parameters[0]), CodeBuilder.CreateIntegerLiteral(fixedParametersLength))); } } if (TypeSystemServices.VoidType == signature.ReturnType) { call.Body.Add(mie); } else { call.Body.Add(new ReturnStatement(mie)); } }
MethodInvocationExpression CreateInvokeInvocation(InternalCallableType type) { return CodeBuilder.CreateMethodInvocation( CodeBuilder.CreateSelfReference(type), type.GetInvokeMethod()); }
void ImplementICallableCall(InternalCallableType type, ClassDefinition node) { Method call = (Method)node.Members["Call"]; Debug.Assert(null != call); Debug.Assert(call.Body.IsEmpty); CallableSignature signature = type.GetSignature(); int byRefCount = GetByRefParamCount(signature); if (byRefCount > 0) { ImplementByRefICallableCall(call, type, node, signature, byRefCount); } else { ImplementRegularICallableCall(call, type, node, signature); } }