// arguments: complex arguments (expressions, maplets, splat, block)
// singleArgument: siple argument (complex are not used)
// assignmentRhsArgument: rhs of the assignment: target.method=(rhs)
/*!*/
internal static MSA.Expression TransformRead(Expression/*!*/ node, AstGenerator/*!*/ gen, bool hasImplicitSelf,
string/*!*/ methodName, MSA.Expression/*!*/ transformedTarget,
Arguments arguments, Block block, MSA.Expression singleArgument, MSA.Expression assignmentRhsArgument)
{
Debug.Assert(assignmentRhsArgument == null || block == null, "Block not allowed in assignment");
Debug.Assert(singleArgument == null || arguments == null && assignmentRhsArgument == null);
Assert.NotNull(gen, transformedTarget);
Assert.NotEmpty(methodName);
// Pass args in this order:
// 1. instance
// 2. block (if present)
// 3. passed args: normal args, maplets, array
// 4. RHS of assignment (if present)
MSA.Expression blockArgVariable;
MSA.Expression transformedBlock;
if (block != null) {
blockArgVariable = gen.CurrentScope.DefineHiddenVariable("#block-def", typeof(Proc));
transformedBlock = block.Transform(gen);
} else {
blockArgVariable = transformedBlock = null;
}
var siteBuilder = new CallSiteBuilder(gen, transformedTarget, blockArgVariable);
if (arguments != null) {
arguments.TransformToCall(gen, siteBuilder);
} else if (singleArgument != null) {
siteBuilder.Add(singleArgument);
}
MSA.Expression rhsVariable = null;
if (assignmentRhsArgument != null) {
rhsVariable = gen.CurrentScope.DefineHiddenVariable("#rhs", assignmentRhsArgument.Type);
siteBuilder.RhsArgument = Ast.Assign(rhsVariable, assignmentRhsArgument);
}
var dynamicSite = siteBuilder.MakeCallAction(methodName, hasImplicitSelf);
#if FEATURE_CALL_SITE_TRACER
if (gen.Context.CallSiteCreated != null) {
gen.Context.CallSiteCreated(node, dynamicSite);
}
#endif
MSA.Expression result = gen.DebugMark(dynamicSite, methodName);
if (block != null) {
result = gen.DebugMark(MakeCallWithBlockRetryable(gen, result, blockArgVariable, transformedBlock, block.IsDefinition),
"#RB: method call with a block ('" + methodName + "')");
}
if (assignmentRhsArgument != null) {
result = Ast.Block(result, rhsVariable);
}
return result;
}