// 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 void TransformToCall(AstGenerator /*!*/ gen, CallSiteBuilder /*!*/ siteBuilder) { if (_expressions != null) { foreach (var arg in _expressions) { siteBuilder.Add(arg.TransformRead(gen)); } } if (_maplets != null) { siteBuilder.Add(gen.TransformToHashConstructor(_maplets)); } if (_array != null) { siteBuilder.SplattedArgument = AstUtils.LightDynamic(SplatAction.Make(gen.Context), typeof(IList), _array.TransformRead(gen)); } }
internal void TransformForSuperCall(AstGenerator /*!*/ gen, CallSiteBuilder /*!*/ siteBuilder) { for (int i = 0; i < _leadingMandatoryCount; i++) { siteBuilder.Add(_mandatory[i].TransformRead(gen)); } foreach (SimpleAssignmentExpression s in _optional) { siteBuilder.Add(s.Left.TransformRead(gen)); } for (int i = _leadingMandatoryCount; i < _mandatory.Length; i++) { siteBuilder.Add(_mandatory[i].TransformRead(gen)); } if (_unsplat != null) { siteBuilder.SplattedArgument = _unsplat.TransformRead(gen); } }
internal void TransformForSuperCall(AstGenerator /*!*/ gen, CallSiteBuilder /*!*/ siteBuilder) { if (_mandatory != null) { foreach (Variable v in _mandatory) { siteBuilder.Add(v.TransformRead(gen)); } } if (_optional != null) { foreach (SimpleAssignmentExpression s in _optional) { siteBuilder.Add(s.Left.TransformRead(gen)); } } if (_array != null) { siteBuilder.SplattedArgument = _array.TransformRead(gen); } }
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 + "')" )); }