// 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; }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { if (gen.CurrentMethod.IsTopLevelCode && gen.CurrentBlock == null && !gen.CompilerOptions.IsEval) { return(Ast.Throw(Methods.MakeTopLevelSuperException.OpCall())); } // invoke super member action: CallBuilder callBuilder = new CallBuilder(gen); // self: callBuilder.Instance = gen.CurrentSelfVariable; // arguments: if (Arguments != null) { Arguments.TransformToCall(gen, callBuilder); } else { // copy parameters from the method: // TODO: parameters in top-level eval LexicalScope.TransformParametersToSuperCall(gen, callBuilder, gen.CurrentMethod.Parameters); } // block: MSA.Expression transformedBlock; if (Block != null) { transformedBlock = Block.Transform(gen); } else { transformedBlock = gen.MakeMethodBlockParameterRead(); } // variable assigned to the transformed block in MakeCallWithBlockRetryable: MSA.Expression blockArgVariable = gen.CurrentScope.DefineHiddenVariable("#super-call-block", typeof(Proc)); callBuilder.Block = blockArgVariable; // TODO: this could be improved, currently the right method name and declaring module is always searched for at run-time (at the site): return(gen.DebugMark( MethodCall.MakeCallWithBlockRetryable(gen, callBuilder.MakeSuperCallAction(gen.CurrentFrame.UniqueId), blockArgVariable, transformedBlock, Block != null && Block.IsDefinition ), "#RB: super call ('" + gen.CurrentMethod.MethodName + "')" )); }
// 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; }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { // variable assigned to the transformed block in MakeCallWithBlockRetryable: MSA.Expression blockArgVariable = gen.CurrentScope.DefineHiddenVariable("#super-call-block", typeof(Proc)); // invoke super member action: var siteBuilder = new CallSiteBuilder(gen, gen.CurrentSelfVariable, blockArgVariable); // arguments: if (HasImplicitArguments) { // MRI 1.8: If a block is called via define_method stub its parameters are used here. // MRI 1.9: This scenario is not supported. // We don't support this either. Otherwise we would need to emit super call with dynamic parameters if gen.CurrentBlock != null. if (gen.CurrentMethod.Parameters != null) { gen.CurrentMethod.Parameters.TransformForSuperCall(gen, siteBuilder); } else if (gen.CompilerOptions.TopLevelParameterNames != null) { bool hasUnsplat = gen.CompilerOptions.TopLevelHasUnsplatParameter; string[] names = gen.CompilerOptions.TopLevelParameterNames; // dynamic lookup: for (int i = 0; i < names.Length - (hasUnsplat ? 1 : 0); i++) { siteBuilder.Add(Methods.GetLocalVariable.OpCall(gen.CurrentScopeVariable, AstUtils.Constant(names[i]))); } if (hasUnsplat) { siteBuilder.SplattedArgument = Methods.GetLocalVariable.OpCall(gen.CurrentScopeVariable, AstUtils.Constant(names[names.Length - 1])); } } else { // this means we are not inside any method scope -> an exception will be thrown at the call site } } else { Arguments.TransformToCall(gen, siteBuilder); } // block: MSA.Expression transformedBlock; if (Block != null) { transformedBlock = Block.Transform(gen); } else { transformedBlock = gen.MakeMethodBlockParameterRead(); } return(gen.DebugMark( MethodCall.MakeCallWithBlockRetryable(gen, siteBuilder.MakeSuperCallAction(gen.CurrentFrame.UniqueId, HasImplicitArguments), blockArgVariable, transformedBlock, Block != null && Block.IsDefinition ), "#RB: super call ('" + gen.CurrentMethod.MethodName + "')" )); }