public override UncollectableCompilationMode.ConstantInfo GetContext()
        {
            lock (StorageData.Contexts) {
                int  index       = StorageData.ContextCount++;
                int  arrIndex    = index - StorageData.ContextTypes * StorageData.StaticFields;
                Type storageType = StorageData.ContextStorageType(index);

                MSAst.Expression expr;
                FieldInfo        fieldInfo;
                if (arrIndex < 0)
                {
                    fieldInfo = storageType.GetField(string.Format("Context{0:000}", index % StorageData.StaticFields));
                    expr      = Ast.Field(null, fieldInfo);
                }
                else
                {
                    fieldInfo = typeof(StorageData).GetField(nameof(StorageData.Contexts));
                    expr      = Ast.ArrayIndex(
                        Ast.Field(null, fieldInfo),
                        Ast.Constant(arrIndex, typeof(int))
                        );
                }

                return(new ConstantInfo(new CodeContextExpression(expr), fieldInfo, index));
            }
        }
Exemple #2
0
        internal void AddVersionTest(RubyClass /*!*/ cls)
        {
            cls.Context.RequiresClassHierarchyLock();

            // check for module version (do not burn a module reference to the rule):
            AddCondition(Ast.Equal(Ast.Field(AstUtils.Constant(cls.Version), Fields.VersionHandle_Method), AstUtils.Constant(cls.Version.Method)));
        }
Exemple #3
0
        public override MSAst.Expression Reduce()
        {
            if (_expandable)
            {
                return(Ast.NewArrayInit(
                           typeof(object),
                           ToObjectArray(Items)
                           ));
            }

            if (Items.Count == 0)
            {
                return(Ast.Field(
                           null,
                           typeof(PythonOps).GetField(nameof(PythonOps.EmptyTuple))
                           ));
            }

            return(Ast.Call(
                       AstMethods.MakeTuple,
                       Ast.NewArrayInit(
                           typeof(object),
                           ToObjectArray(Items)
                           )
                       ));
        }
        // public for accessibility via GetMethod("NextSite")
        public static SiteInfo /*!*/ NextSite <T>(DynamicMetaObjectBinder /*!*/ binder) where T : class
        {
            lock (StorageData.SiteLockObj) {
                int index = SiteStorage <T> .SiteCount++;

                int  arrIndex    = index - StorageData.SiteTypes * StorageData.StaticFields;
                Type storageType = SiteStorage <T> .SiteStorageType(index);

                MSAst.Expression expr;
                FieldInfo        fieldInfo;
                if (arrIndex < 0)
                {
                    fieldInfo = storageType.GetField(string.Format("Site{0:000}", index % StorageData.StaticFields));
                    expr      = Ast.Field(null, fieldInfo);
                }
                else
                {
                    fieldInfo = typeof(SiteStorage <T>).GetField("Sites");
                    expr      = Ast.ArrayIndex(
                        Ast.Field(null, fieldInfo),
                        Ast.Constant(arrIndex, typeof(int))
                        );
                }

                return(PublishSite(new SiteInfo <T>(binder, expr, fieldInfo, index)));
            }
        }
        // Note: This should stay non-public to avoid name conflicts when accessing the
        //       generic overload via GetMethod("NextSite")
        private static SiteInfo /*!*/ NextSite(DynamicMetaObjectBinder /*!*/ binder, Type /*!*/ delegateType)
        {
            Type siteType = typeof(SiteStorage <>).MakeGenericType(delegateType);

            lock (StorageData.SiteLockObj) {
                int index = (int)siteType.GetField("SiteCount").GetValue(null);
                siteType.GetField("SiteCount").SetValue(null, index + 1);
                int  arrIndex    = index - StorageData.SiteTypes * StorageData.StaticFields;
                Type storageType = (Type)siteType.GetMethod("SiteStorageType").Invoke(null, new object[] { index });

                MSAst.Expression expr;
                FieldInfo        fieldInfo;
                if (arrIndex < 0)
                {
                    fieldInfo = storageType.GetField(string.Format("Site{0:000}", index % StorageData.StaticFields));
                    expr      = Ast.Field(null, fieldInfo);
                }
                else
                {
                    fieldInfo = siteType.GetField("Sites");
                    expr      = Ast.ArrayIndex(
                        Ast.Field(null, fieldInfo),
                        Ast.Constant(arrIndex, typeof(int))
                        );
                }

                return(PublishSite(new SiteInfoLarge(binder, expr, fieldInfo, index, delegateType)));
            }
        }
Exemple #6
0
        public override Expression GetValue(Expression context, ActionBinder binder, Type type)
        {
            if (Field.IsLiteral)
            {
                return(Ast.Constant(Field.GetValue(null)));
            }

            if (!IsStatic)
            {
                // return the field tracker...
                return(binder.ReturnMemberTracker(type, this));
            }

            if (Field.DeclaringType.ContainsGenericParameters)
            {
                return(null);
            }

            if (IsPublic && DeclaringType.IsPublic)
            {
                return(Ast.Field(null, Field));
            }

            return(Ast.Call(
                       AstUtils.Convert(Ast.Constant(Field), typeof(FieldInfo)),
                       typeof(FieldInfo).GetMethod("GetValue"),
                       Ast.Constant(null)
                       ));
        }
Exemple #7
0
 private MemberExpression /*!*/ ReadStrongBoxValue(Expression instance)
 {
     return(Ast.Field(
                AstUtils.Convert(instance, Value.BindingSelf.GetType()),
                Value.BindingSelf.GetType().GetField("Value")
                ));
 }
Exemple #8
0
        /// <summary> if a member-injector is defined-on or registered-for this type call it </summary>
        private void MakeOperatorGetMemberBody(GetMemberInfo getMemInfo, Expression instance, Type type, string name)
        {
            MethodInfo getMem = GetMethod(type, name);

            if (getMem != null && getMem.IsSpecialName)
            {
                ParameterExpression tmp = Ast.Variable(typeof(object), "getVal");
                getMemInfo.Body.AddVariable(tmp);

                getMemInfo.Body.AddCondition(
                    Ast.NotEqual(
                        Ast.Assign(
                            tmp,
                            MakeCallExpression(
                                getMemInfo.CodeContext,
                                getMem,
                                AstUtils.Convert(instance, type),
                                Ast.Constant(getMemInfo.Name)
                                )
                            ),
                        Ast.Field(null, typeof(OperationFailed).GetField("Value"))
                        ),
                    tmp
                    );
            }
        }
Exemple #9
0
        internal MSA.Expression /*!*/ TransformOptionalsInitialization(AstGenerator /*!*/ gen)
        {
            Assert.NotNull(gen);

            if (_optional.Length == 0)
            {
                return(AstUtils.Empty());
            }

            MSA.Expression singleton = gen.CurrentScope.DefineHiddenVariable("#default", typeof(object));

            MSA.Expression result = AstUtils.Empty();
            for (int i = 0; i < _optional.Length; i++)
            {
                result = AstUtils.IfThen(
                    Ast.Equal(_optional[i].Left.TransformRead(gen), singleton),
                    Ast.Block(
                        result,
                        _optional[i].TransformRead(gen) // assignment
                        )
                    );
            }

            return(Ast.Block(
                       Ast.Assign(singleton, Ast.Field(null, Fields.DefaultArgument)),
                       result,
                       AstUtils.Empty()
                       ));
        }
Exemple #10
0
        /// <summary> if a member-injector is defined-on or registered-for this type call it </summary>
        private void MakeOperatorGetMemberBody(GetMemberInfo getMemInfo, DynamicMetaObject instance, Type instanceType, string name)
        {
            MethodInfo getMem = GetMethod(instanceType, name);

            if (getMem != null)
            {
                ParameterExpression tmp = Ast.Variable(typeof(object), "getVal");
                getMemInfo.Body.AddVariable(tmp);

                getMemInfo.Body.AddCondition(
                    Ast.NotEqual(
                        Ast.Assign(
                            tmp,
                            MakeCallExpression(
                                getMemInfo.ResolutionFactory,
                                getMem,
                                new DynamicMetaObject(
                                    Expression.Convert(instance.Expression, instanceType),
                                    instance.Restrictions,
                                    instance.Value
                                    ),
                                new DynamicMetaObject(
                                    Expression.Constant(getMemInfo.Name),
                                    BindingRestrictions.Empty,
                                    getMemInfo.Name
                                    )
                                ).Expression
                            ),
                        Ast.Field(null, typeof(OperationFailed).GetDeclaredField("Value"))
                        ),
                    tmp
                    );
            }
        }
Exemple #11
0
        /// <summary>
        /// Takes current result and wraps it into try-filter(MethodUnwinder)-finally block that ensures correct "break" behavior for
        /// Ruby method calls with a block given in arguments.
        ///
        /// Sets up a RFC frame similarly to MethodDeclaration.
        /// </summary>
        public static void RuleControlFlowBuilder(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            Debug.Assert(args.Signature.HasBlock);
            if (metaBuilder.Error)
            {
                return;
            }

            // TODO (improvement):
            // We don't special case null block here, although we could (we would need a test for that then).
            // We could also statically know (via call-site flag) that the current method is not a proc-converter (passed by ref),
            // which would make such calls faster.
            var rfcVariable    = metaBuilder.GetTemporary(typeof(RuntimeFlowControl), "#rfc");
            var resultVariable = metaBuilder.GetTemporary(typeof(object), "#result");

            MSA.ParameterExpression unwinder;

            metaBuilder.Result = Ast.Block(
                // initialize frame (RFC):
                Ast.Assign(rfcVariable, Methods.CreateRfcForMethod.OpCall(AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)))),
                AstUtils.Try(
                    Ast.Assign(resultVariable, metaBuilder.Result)
                    ).Filter(unwinder = Ast.Parameter(typeof(MethodUnwinder), "#unwinder"),
                             Ast.Equal(Ast.Field(unwinder, MethodUnwinder.TargetFrameField), rfcVariable),

                             // return unwinder.ReturnValue;
                             Ast.Assign(resultVariable, Ast.Field(unwinder, MethodUnwinder.ReturnValueField))

                             ).Finally(
                    // we need to mark the RFC dead snce the block might escape and break later:
                    Methods.LeaveMethodFrame.OpCall(rfcVariable)
                    ),
                resultVariable
                );
        }
        public override MSAst.Expression Reduce()
        {
            UnicodeWrapper wrapper;

            if (_value == Ellipsis.Value)
            {
                return(Ast.Property(
                           null,
                           typeof(PythonOps).GetProperty("Ellipsis")
                           ));
            }
            else if (_value is bool)
            {
                if ((bool)_value)
                {
                    return(Ast.Field(null, typeof(ScriptingRuntimeHelpers).GetField("True")));
                }
                else
                {
                    return(Ast.Field(null, typeof(ScriptingRuntimeHelpers).GetField("False")));
                }
            }
            else if ((wrapper = _value as UnicodeWrapper) != null)
            {
                return(GlobalParent.Constant(wrapper.Value));
            }

            return(GlobalParent.Constant(_value));
        }
        private Expression FallbackGet(DynamicMetaObjectBinder member, DynamicMetaObject[] args)
        {
            if (member is GetMemberBinder sa)
            {
                return(sa.FallbackGetMember(args[0]).Expression);
            }

            PythonGetMemberBinder pyGetMem = member as PythonGetMemberBinder;

            if (pyGetMem.IsNoThrow)
            {
                return(Ast.Field(
                           null,
                           typeof(OperationFailed).GetDeclaredField("Value")
                           ));
            }
            else
            {
                return(member.Throw(
                           Ast.Call(
                               typeof(PythonOps).GetMethod(nameof(PythonOps.AttributeError)),
                               AstUtils.Constant("{0} instance has no attribute '{1}'"),
                               Ast.NewArrayInit(
                                   typeof(object),
                                   AstUtils.Constant(((OldInstance)Value)._class._name),
                                   AstUtils.Constant(pyGetMem.Name)
                                   )
                               )
                           ));
            }
        }
Exemple #14
0
        internal static MethodCallExpression /*!*/ CheckTypeVersion(Expression /*!*/ tested, int version)
        {
#if FEATURE_REFEMIT
            FieldInfo fi = tested.Type.GetField(NewTypeMaker.ClassFieldName);
#else
            FieldInfo fi = null;
#endif
            if (fi == null)
            {
                return(Ast.Call(
                           typeof(PythonOps).GetMethod("CheckTypeVersion"),
                           AstUtils.Convert(tested, typeof(object)),
                           AstUtils.Constant(version)
                           ));
            }

            Debug.Assert(tested.Type != typeof(object));
            return(Ast.Call(
                       typeof(PythonOps).GetMethod("CheckSpecificTypeVersion"),
                       Ast.Field(
                           tested,
                           fi
                           ),
                       AstUtils.Constant(version)
                       ));
        }
Exemple #15
0
 /// <summary>
 /// Fills missing arguments with the missing argument placeholder (RubyOps.DefaultArgument singleton).
 /// </summary>
 public void FillMissingArguments()
 {
     for (int i = _explicitArgCount; i < _mandatoryParamCount + _optionalParamCount; i++)
     {
         // TODO: optimize field read?
         _arguments[_nextArgIndex++] = Ast.Field(null, Fields.DefaultArgument);
     }
 }
Exemple #16
0
        internal static MSAst.Expression /*!*/ Delete(MSAst.Expression /*!*/ expression)
        {
            if (expression is IPythonVariableExpression pyGlobal)
            {
                return(pyGlobal.Delete());
            }

            return(Ast.Assign(expression, Ast.Field(null, typeof(Uninitialized).GetField(nameof(Uninitialized.Instance)))));
        }
Exemple #17
0
        private static MSAst.Expression GetSliceValue(Expression expr)
        {
            if (expr != null)
            {
                return(expr);
            }

            return(Ast.Field(null, typeof(MissingParameter).GetField(nameof(MissingParameter.Value))));
        }
Exemple #18
0
        internal static MSAst.Expression /*!*/ Delete(MSAst.Expression /*!*/ expression)
        {
            IPythonVariableExpression pyGlobal = expression as IPythonVariableExpression;

            if (pyGlobal != null)
            {
                return(pyGlobal.Delete());
            }

            return(Ast.Assign(expression, Ast.Field(null, typeof(Uninitialized).GetField("Instance"))));
        }
Exemple #19
0
 private void MakeMissingMemberRuleForGet(Type type)
 {
     if (!Action.IsNoThrow)
     {
         MakeMissingMemberError(type);
     }
     else
     {
         AddToBody(Rule.MakeReturn(Binder, Ast.Field(null, typeof(OperationFailed).GetField("Value"))));
         Rule.IsError = true;
     }
 }
Exemple #20
0
        protected internal override Expression GetBoundValue(Expression context, ActionBinder binder, Type type, Expression instance)
        {
            if (IsPublic && DeclaringType.IsVisible)
            {
                return(Ast.Field(
                           Ast.Convert(instance, Field.DeclaringType),
                           Field
                           ));
            }

            return(DefaultBinder.MakeError(((DefaultBinder)binder).MakeNonPublicMemberGetError(context, this, type, instance)));
        }
Exemple #21
0
        internal override void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
        {
            Expression expr     = null;
            Expression instance = _fieldInfo.IsStatic ? null : Ast.Convert(args.TargetExpression, _fieldInfo.DeclaringType);

            if (_isSetter)
            {
                // parameters should be: instance/type, value
                if (args.SimpleArgumentCount == 0 && args.Signature.HasRhsArgument)
                {
                    expr = Ast.Assign(
                        Ast.Field(instance, _fieldInfo),
                        // TODO: remove
                        args.RubyContext.Binder.ConvertExpression(
                            args.GetRhsArgumentExpression(),
                            _fieldInfo.FieldType,
                            ConversionResultKind.ExplicitCast,
                            args.ScopeExpression
                            )
                        );
                }
            }
            else
            {
                // parameter should be: instance/type
                if (args.SimpleArgumentCount == 0)
                {
                    if (_fieldInfo.IsLiteral)
                    {
                        // TODO: seems like Compiler should correctly handle the literal field case
                        // (if you emit a read to a literal field, you get a NotSupportedExpception from
                        // FieldHandle when we try to emit)
                        expr = Ast.Constant(_fieldInfo.GetValue(null));
                    }
                    else
                    {
                        expr = Ast.Field(instance, _fieldInfo);
                    }
                }
            }

            if (expr != null)
            {
                metaBuilder.Result = expr;
            }
            else
            {
                metaBuilder.SetError(
                    Methods.MakeInvalidArgumentTypesError.OpCall(Ast.Constant(_isSetter ? name + "=" : name))
                    );
            }
        }
Exemple #22
0
 private static Expression /*!*/ GetFailureExpression(Type /*!*/ limitType, DynamicMetaObject self, string name, bool isNoThrow, DynamicMetaObjectBinder action)
 {
     return(isNoThrow ?
            Ast.Field(null, typeof(OperationFailed).GetField("Value")) :
            DefaultBinder.MakeError(
                PythonContext.GetPythonContext(action).Binder.MakeMissingMemberError(
                    limitType,
                    self,
                    name
                    ),
                typeof(object)
                ).Expression);
 }
Exemple #23
0
        internal static MSA.Expression /*!*/ MakeUserMethodBody(AstGenerator gen, int lastLine,
                                                                MSA.Expression /*!*/ blockParameter, MSA.Expression /*!*/ rfcVariable,
                                                                MSA.ParameterExpression /*!*/ methodUnwinder, MSA.Expression /*!*/ bodyStatement, ResultOperation resultOperation,
                                                                int profileTickIndex, MSA.ParameterExpression stampVariable, MSA.LabelTarget returnLabel)
        {
            Assert.NotNull(blockParameter, rfcVariable, bodyStatement, methodUnwinder);
            Debug.Assert(!resultOperation.IsIgnore, "return value should not be ignored");
            Debug.Assert(returnLabel != null || resultOperation.Variable != null, "return label needed");

            MSA.Expression resultExpression = Ast.Field(methodUnwinder, MethodUnwinder.ReturnValueField);
            if (resultOperation.Variable != null)
            {
                resultExpression = Ast.Assign(resultOperation.Variable, resultExpression);
            }
            else
            {
                resultExpression = Ast.Return(returnLabel, resultExpression);
            }

            // TODO: move this to the caller:
            MSA.Expression profileStart, profileEnd;
            if (stampVariable != null)
            {
                profileStart = Ast.Assign(stampVariable, Methods.Stopwatch_GetTimestamp.OpCall());
                profileEnd   = Methods.UpdateProfileTicks.OpCall(Ast.Constant(profileTickIndex), stampVariable);
            }
            else
            {
                profileStart = profileEnd = Ast.Empty();
            }

            return(AstUtils.Try(
                       // initialize frame (RFC):
                       profileStart,
                       Ast.Assign(rfcVariable, Methods.CreateRfcForMethod.OpCall(AstUtils.Convert(blockParameter, typeof(Proc)))),
                       bodyStatement
                       ).Filter(methodUnwinder, Ast.Equal(Ast.Field(methodUnwinder, MethodUnwinder.TargetFrameField), rfcVariable),

                                // return unwinder.ReturnValue;
                                resultExpression

                                ).Finally(
                       Ast.Assign(Ast.Field(rfcVariable, RuntimeFlowControl.IsActiveMethodField), Ast.Constant(false)),
                       profileEnd,
                       gen != null && gen.TraceEnabled ? Methods.TraceMethodReturn.OpCall(
                           gen.CurrentScopeVariable,
                           Ast.Convert(Ast.Constant(gen.SourceUnit.Path), typeof(string)),
                           Ast.Constant(lastLine)
                           ) : Ast.Empty()
                       ));
        }
Exemple #24
0
 private void MakeMissingMemberRuleForGet(GetMemberInfo getMemInfo, Type type)
 {
     if (getMemInfo.IsNoThrow)
     {
         getMemInfo.Body.FinishCondition(
             Ast.Field(null, typeof(OperationFailed).GetField("Value"))
             );
     }
     else
     {
         getMemInfo.Body.FinishCondition(
             MakeError(MakeMissingMemberError(type, getMemInfo.Name))
             );
     }
 }
        internal static MSA.Expression /*!*/ MakeCallWithBlockRetryable(AstGenerator /*!*/ gen, MSA.Expression /*!*/ invoke,
                                                                        MSA.Expression blockArgVariable, MSA.Expression transformedBlock, bool isBlockDefinition)
        {
            Assert.NotNull(invoke);
            Debug.Assert((blockArgVariable == null) == (transformedBlock == null));

            // see Ruby Language.doc/Control Flow Implementation/Method Call With a Block
            MSA.Expression          resultVariable = gen.CurrentScope.DefineHiddenVariable("#method-result", typeof(object));
            MSA.ParameterExpression evalUnwinder;

            MSA.LabelTarget retryLabel = Ast.Label("retry");

            var result = new AstBlock {
                Ast.Assign(blockArgVariable, Ast.Convert(transformedBlock, blockArgVariable.Type)),

                Ast.Label(retryLabel),

                (isBlockDefinition) ? Methods.InitializeBlock.OpCall(blockArgVariable) : null,

                AstUtils.Try(
                    Ast.Assign(resultVariable, invoke)
                    ).Catch(evalUnwinder = Ast.Parameter(typeof(EvalUnwinder), "#u"),
                            Ast.Assign(
                                resultVariable,
                                Ast.Field(evalUnwinder, EvalUnwinder.ReturnValueField)
                                )
                            ),

                Ast.IfThen(Ast.TypeEqual(resultVariable, typeof(BlockReturnResult)),
                           Ast.IfThenElse(Methods.IsRetrySingleton.OpCall(resultVariable),
                                          // retry:
                                          AstUtils.IfThenElse(Ast.Equal(gen.MakeMethodBlockParameterRead(), blockArgVariable),
                                                              RetryStatement.TransformRetry(gen),
                                                              Ast.Goto(retryLabel)
                                                              ),
                                          // return:
                                          gen.Return(ReturnStatement.Propagate(gen, resultVariable))
                                          )
                           ),

                resultVariable
            };

            return(result);
        }
        protected internal override DynamicMetaObject GetBoundValue(OverloadResolverFactory resolverFactory, ActionBinder binder, Type type, DynamicMetaObject instance)
        {
            if (IsPublic && DeclaringType.IsVisible)
            {
                return(new DynamicMetaObject(
                           AstUtils.Convert(
                               Ast.Field(
                                   AstUtils.Convert(instance.Expression, Field.DeclaringType),
                                   Field
                                   ),
                               typeof(object)
                               ),
                           BindingRestrictions.Empty
                           ));
            }

            return(DefaultBinder.MakeError(((DefaultBinder)binder).MakeNonPublicMemberGetError(resolverFactory, this, type, instance), BindingRestrictions.Empty, typeof(object)));
        }
Exemple #27
0
        /// <summary>
        /// Takes current result and wraps it into try-filter(MethodUnwinder)-finally block that ensures correct "break" behavior for
        /// library method calls with block given in bfcVariable (BlockParam).
        /// </summary>
        public static void RuleControlFlowBuilder(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            if (metaBuilder.Error)
            {
                return;
            }

            var metaBlock = args.GetMetaBlock();

            Debug.Assert(metaBlock != null, "RuleControlFlowBuilder should only be used if the signature has a block");

            // We construct CF only for non-nil blocks thus we need a test for it:
            if (metaBlock.Value == null)
            {
                metaBuilder.AddRestriction(Ast.Equal(metaBlock.Expression, AstUtils.Constant(null)));
                return;
            }

            // don't need to test the exact type of the Proc since the code is subclass agnostic:
            metaBuilder.AddRestriction(Ast.NotEqual(metaBlock.Expression, AstUtils.Constant(null)));
            Expression bfcVariable = metaBuilder.BfcVariable;

            Debug.Assert(bfcVariable != null);

            // Method call with proc can invoke control flow that returns an arbitrary value from the call, so we need to type result to Object.
            // Otherwise, the result could only be result of targetExpression unless its return type is void.
            Expression          resultVariable = metaBuilder.GetTemporary(typeof(object), "#result");
            ParameterExpression unwinder;

            metaBuilder.Result = Ast.Block(
                Ast.Assign(bfcVariable, Methods.CreateBfcForLibraryMethod.OpCall(AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)))),
                AstUtils.Try(
                    Ast.Assign(resultVariable, AstUtils.Convert(metaBuilder.Result, typeof(object)))
                    ).Filter(unwinder = Ast.Parameter(typeof(MethodUnwinder), "#unwinder"),
                             Methods.IsProcConverterTarget.OpCall(bfcVariable, unwinder),

                             Ast.Assign(resultVariable, Ast.Field(unwinder, MethodUnwinder.ReturnValueField)),
                             AstUtils.Default(typeof(object))
                             ).Finally(
                    Methods.LeaveProcConverter.OpCall(bfcVariable)
                    ),
                resultVariable
                );
        }
Exemple #28
0
        /// <summary>
        /// Resolves an library method overload and builds call expression.
        /// The resulting expression on meta-builder doesn't handle block control flow yet.
        /// </summary>
        internal static void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name,
                                             IList <OverloadInfo> /*!*/ overloads, SelfCallConvention callConvention, bool implicitProtocolConversions)
        {
            RubyOverloadResolver resolver;
            var bindingTarget = ResolveOverload(metaBuilder, args, name, overloads, callConvention, implicitProtocolConversions, out resolver);

            if (bindingTarget.Success)
            {
                // TODO: create a custom overload info:
                if (ReferenceEquals(bindingTarget.Overload.ReflectionInfo, Methods.CreateDefaultInstance))
                {
                    Debug.Assert(args.TargetClass.TypeTracker.Type.IsValueType);
                    metaBuilder.Result = Ast.New(args.TargetClass.TypeTracker.Type);
                }
                else if (args.Signature.IsVirtualCall && bindingTarget.Overload.IsVirtual)
                {
                    // Virtual methods that have been detached from the CLR type and
                    // defined on the corresponding Ruby class or its subclass are not
                    // directly invoked from a dynamic virtual call to prevent recursion.
                    // Instead the base call is performed.
                    //
                    // Example:
                    // class C < ArrayList
                    //   define_method(:Add, instance_method(:Add))
                    // end
                    //
                    // C.new.Add(1)
                    //
                    // C.new.Add dispatches to the virtual ArrayList::Add, which in turn dispatches to the auto-generated override C$1::Add.
                    // That gets here since the defined method is a Ruby method (a detached CLR method group). If we called it directly
                    // it would invoke the C$1::Add override again leading to a stack overflow. So we need to use a base call instead.
                    metaBuilder.Result = Ast.Field(null, Fields.ForwardToBase);
                }
                else
                {
                    metaBuilder.Result = bindingTarget.MakeExpression();
                }
            }
            else
            {
                metaBuilder.SetError(resolver.MakeInvalidParametersError(bindingTarget).Expression);
            }
        }
            public override MSAst.Expression /*!*/ Reduce()
            {
                Debug.Assert(_start >= 0);
                Assert.NotNull(_fieldInfo);

                int index    = _offset + _start;
                int arrIndex = index - FieldCount;

                if (arrIndex < 0)
                {
                    return(Ast.Field(null, _fieldInfo));
                }
                else
                {
                    return(Ast.ArrayIndex(
                               Ast.Field(null, _fieldInfo),
                               Ast.Constant(arrIndex, typeof(int))
                               ));
                }
            }
Exemple #30
0
        /// <summary> if a member-injector is defined-on or registered-for this type call it </summary>
        protected void MakeOperatorGetMemberBody(Type type, string name)
        {
            MethodInfo getMem = GetMethod(type, name);

            if (getMem != null && getMem.IsSpecialName)
            {
                ParameterExpression tmp = Rule.GetTemporary(typeof(object), "getVal");
                AddToBody(
                    AstUtils.If(
                        Ast.NotEqual(
                            Ast.Assign(
                                tmp,
                                Binder.MakeCallExpression(Rule.Context, getMem, Instance, Ast.Constant(StringName))
                                ),
                            Ast.Field(null, typeof(OperationFailed).GetField("Value"))
                            ),
                        Rule.MakeReturn(Binder, tmp)
                        )
                    );
            }
        }