void ImplementRegularICallableCall( Method call, InternalCallableType type, ClassDefinition node, CallableSignature signature) { MethodInvocationExpression mie = CreateInvokeInvocation(type); IParameter[] parameters = signature.Parameters; for (int i = 0; i < parameters.Length; ++i) { SlicingExpression slice = CodeBuilder.CreateSlicing( CodeBuilder.CreateReference(call.Parameters[0]), i); mie.Arguments.Add(slice); } if (TypeSystemServices.VoidType == signature.ReturnType) { call.Body.Add(mie); } else { call.Body.Add(new ReturnStatement(mie)); } }
override public void OnClassDefinition(ClassDefinition node) { Visit(node.Members, NodeType.ClassDefinition); InternalCallableType type = node.Entity as InternalCallableType; if (null != type) { ImplementICallableCall(type, node); } }
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); } }
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)); } CheckMethodGenerics(call, node); }
void ImplementICallableCall(InternalCallableType type, ClassDefinition node) { Method call = (Method)node.Members["Call"]; Debug.Assert(null != call); Debug.Assert(0 == call.Body.Statements.Count); CallableSignature signature = type.GetSignature(); int byRefCount = GetByRefParamCount(signature); if (byRefCount > 0) { ImplementByRefICallableCall(call, type, node, signature, byRefCount); } else { ImplementRegularICallableCall(call, type, node, signature); } }
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.GetElementType(); } 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))); } }
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(0 == call.Body.Statements.Count); CallableSignature signature = type.GetSignature(); MethodInvocationExpression mie = CodeBuilder.CreateMethodInvocation( CodeBuilder.CreateSelfReference(type), type.GetInvokeMethod()); int byrefcount = 0; ILocalEntity invokeresults = null; ILocalEntity[] tempvals; IParameter[] parameters = signature.Parameters; ReferenceExpression args = null; foreach (IParameter param in parameters) { if (param.IsByRef) { ++byrefcount; } } tempvals = new InternalLocal[byrefcount]; if (parameters.Length > 0) { args = CodeBuilder.CreateReference(call.Parameters[0]); } int byrefindex = 0; for (int i = 0; i < parameters.Length; ++i) { SlicingExpression slice = CodeBuilder.CreateSlicing(args.CloneNode(), i); if (parameters[i].IsByRef) { tempvals[byrefindex] = CodeBuilder.DeclareLocal(call, "__temp_" + parameters[i].Name, parameters[i].Type); call.Body.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateReference(tempvals[byrefindex]), CodeBuilder.CreateCast( parameters[i].Type, slice))); mie.Arguments.Add(CodeBuilder.CreateReference(tempvals[byrefindex])); ++byrefindex; } else { mie.Arguments.Add(slice); } } if (TypeSystemServices.VoidType == signature.ReturnType) { call.Body.Add(mie); } else if (byrefcount > 0) { invokeresults = CodeBuilder.DeclareLocal(call, "__result", signature.ReturnType); call.Body.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateReference(invokeresults), mie)); } byrefindex = 0; for (int i = 0; i < parameters.Length; ++i) { if (parameters[i].IsByRef) { SlicingExpression slice = CodeBuilder.CreateSlicing(args.CloneNode(), i); call.Body.Add( CodeBuilder.CreateAssignment( slice, CodeBuilder.CreateReference(tempvals[byrefindex]))); ++byrefindex; } } if (TypeSystemServices.VoidType != signature.ReturnType) { if (byrefcount > 0) { call.Body.Add(new ReturnStatement( CodeBuilder.CreateReference(invokeresults))); } else { call.Body.Add(new ReturnStatement(mie)); } } }
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))); } }
MethodInvocationExpression CreateInvokeInvocation(InternalCallableType type) { return CodeBuilder.CreateMethodInvocation( CodeBuilder.CreateSelfReference(type), type.GetInvokeMethod()); }
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)); } }