Example #1
0
 public static Expression IsNull(Expression[] values)
 {
     if (values.Length != 1)
     {
         return(null);
     }
     return(Ast.Equal(values[0], Ast.Null()));
 }
Example #2
0
 public static Expression FxOdd(params Expression[] args)
 {
     if (Expect <int>(args, 1))
     {
         return(Ast.Equal(Ast.Add(UnwrapAndCast <int>(args[0]), Ast.Constant(1)), Ast.Constant(1)));
     }
     return(null);
 }
Example #3
0
 public static Expression Eq(Expression[] obj)
 {
     if (obj.Length == 2)
     {
         return(Ast.Equal(obj[0], obj[1]));
     }
     return(null);
 }
Example #4
0
 public static Expression FxEquals(params Expression[] args)
 {
     if (Expect <int>(args, 2))
     {
         return(Ast.Equal(UnwrapAndCast <int>(args[0]), UnwrapAndCast <int>(args[1])));
     }
     return(null);
 }
Example #5
0
        public Expression MakeTypeTest(Type type, Expression tested)
        {
            if (type == null || type == typeof(Null))
            {
                return(Ast.Equal(tested, Ast.Constant(null)));
            }

            return(MakeTypeTestExpression(type, tested));
        }
Example #6
0
        private static Restrictions GetFallbackRestrictions(Type t, EventTracker et, MetaObject self)
        {
            if (t == typeof(EventTracker))
            {
                //
                // Test Generated:
                //   BinderOps.GetEventHandlerType(((EventTracker)args[0]).Event) == et.Event.EventHandlerType
                //
                return(Restrictions.GetExpressionRestriction(
                           Ast.Equal(
                               Ast.Call(
                                   typeof(BinderOps).GetMethod("GetEventHandlerType"),
                                   Ast.Property(
                                       Ast.Convert(
                                           self.Expression,
                                           typeof(EventTracker)
                                           ),
                                       typeof(EventTracker).GetProperty("Event")
                                       )
                                   ),
                               Ast.Constant(et.Event.EventHandlerType)
                               )
                           ));
            }
            else if (t == typeof(BoundMemberTracker))
            {
                //
                // Test Generated:
                //   BinderOps.GetEventHandlerType(((EventTracker)((BoundMemberTracker)args[0]).BountTo).Event) == et.Event.EventHandlerType
                //
                return(Restrictions.GetExpressionRestriction(
                           Ast.Equal(
                               Ast.Call(
                                   typeof(BinderOps).GetMethod("GetEventHandlerType"),
                                   Ast.Property(
                                       Ast.Convert(
                                           Ast.Property(
                                               Ast.Convert(
                                                   self.Expression,
                                                   typeof(BoundMemberTracker)
                                                   ),
                                               typeof(BoundMemberTracker).GetProperty("BoundTo")
                                               ),
                                           typeof(EventTracker)
                                           ),
                                       typeof(EventTracker).GetProperty("Event")
                                       )
                                   ),
                               Ast.Constant(et.Event.EventHandlerType)
                               )
                           ));
            }

            return(Restrictions.Empty);
        }
Example #7
0
 public static Expression /*!*/ GetObjectTypeTestExpression(object value, Expression /*!*/ expression)
 {
     if (value == null)
     {
         return(Ast.Equal(expression, AstUtils.Constant(null)));
     }
     else
     {
         return(MakeTypeTestExpression(value.GetType(), expression));
     }
 }
Example #8
0
        protected virtual MethodBase[] GetTargetMethods()
        {
            if (_targets != null)
            {
                return(_targets);
            }

            object target = Callable;

            MethodBase[]       targets;
            Delegate           d;
            MemberGroup        mg;
            MethodGroup        mthgrp;
            BoundMemberTracker bmt;

            if ((d = target as Delegate) != null)
            {
                targets = GetDelegateTargets(d);
            }
            else if ((mg = target as MemberGroup) != null)
            {
                List <MethodInfo> foundTargets = new List <MethodInfo>();
                foreach (MemberTracker mt in mg)
                {
                    if (mt.MemberType == TrackerTypes.Method)
                    {
                        foundTargets.Add(((MethodTracker)mt).Method);
                    }
                }
                targets = foundTargets.ToArray();
            }
            else if ((mthgrp = target as MethodGroup) != null)
            {
                _test = Ast.AndAlso(_test, Ast.Equal(Ast.Convert(Rule.Parameters[0], typeof(object)), Ast.Constant(target)));

                List <MethodBase> foundTargets = new List <MethodBase>();
                foreach (MethodTracker mt in mthgrp.Methods)
                {
                    foundTargets.Add(mt.Method);
                }

                targets = foundTargets.ToArray();
            }
            else if ((bmt = target as BoundMemberTracker) != null)
            {
                targets = GetBoundMemberTargets(bmt);
            }
            else
            {
                targets = GetOperatorTargets(target);
            }

            return(targets);
        }
Example #9
0
        private Expression /*!*/ MarshalArgument(MetaObjectBuilder /*!*/ metaBuilder, DynamicMetaObject /*!*/ arg, ArgType parameterType)
        {
            object value = arg.Value;

            if (value == null)
            {
                metaBuilder.AddRestriction(Ast.Equal(arg.Expression, AstUtils.Constant(null)));
            }
            else
            {
                metaBuilder.AddTypeRestriction(value.GetType(), arg.Expression);
            }

            switch (parameterType)
            {
            case ArgType.Buffer:
                if (value == null)
                {
                    return(AstUtils.Constant(null, typeof(byte[])));
                }

                if (value is int && (int)value == 0)
                {
                    metaBuilder.AddRestriction(Ast.Equal(AstUtils.Convert(arg.Expression, typeof(int)), AstUtils.Constant(0)));
                    return(AstUtils.Constant(null, typeof(byte[])));
                }

                if (value.GetType() == typeof(MutableString))
                {
                    return(Methods.GetMutableStringBytes.OpCall(
                               AstUtils.Convert(arg.Expression, typeof(MutableString))
                               ));
                }

                return(Methods.GetMutableStringBytes.OpCall(
                           AstUtils.LightDynamic(ConvertToStrAction.Make(_context), typeof(MutableString), arg.Expression)
                           ));

            case ArgType.Int32:
                if (value is int)
                {
                    return(AstUtils.Convert(arg.Expression, typeof(int)));
                }

                return(Ast.Convert(
                           Ast.Call(
                               AstUtils.LightDynamic(ConvertToIntAction.Make(_context), typeof(IntegerValue), arg.Expression),
                               Methods.IntegerValue_ToUInt32Unchecked
                               ),
                           typeof(int)
                           ));
            }
            throw Assert.Unreachable;
        }
Example #10
0
 public void AddObjectTypeRestriction(object value, Expression /*!*/ expression)
 {
     if (value == null)
     {
         AddRestriction(Ast.Equal(expression, AstUtils.Constant(null)));
     }
     else
     {
         AddTypeRestriction(value.GetType(), expression);
     }
 }
 private void AddFallbackMemberTest(Type t, EventTracker et)
 {
     if (t == typeof(EventTracker))
     {
         //
         // Test Generated:
         //   ScriptingRuntimeHelpers.GetEventHandlerType(((EventTracker)args[0]).Event) == et.Event.EventHandlerType
         //
         _rule.AddTest(
             Ast.Equal(
                 Ast.Call(
                     typeof(ScriptingRuntimeHelpers).GetMethod("GetEventHandlerType"),
                     Ast.Property(
                         Ast.Convert(
                             _rule.Parameters[0],
                             typeof(EventTracker)
                             ),
                         typeof(EventTracker).GetProperty("Event")
                         )
                     ),
                 Ast.Constant(et.Event.EventHandlerType)
                 )
             );
     }
     else if (t == typeof(BoundMemberTracker))
     {
         //
         // Test Generated:
         //   ScriptingRuntimeHelpers.GetEventHandlerType(((EventTracker)((BoundMemberTracker)args[0]).BountTo).Event) == et.Event.EventHandlerType
         //
         _rule.AddTest(
             Ast.Equal(
                 Ast.Call(
                     typeof(ScriptingRuntimeHelpers).GetMethod("GetEventHandlerType"),
                     Ast.Property(
                         Ast.Convert(
                             Ast.Property(
                                 Ast.Convert(
                                     _rule.Parameters[0],
                                     typeof(BoundMemberTracker)
                                     ),
                                 typeof(BoundMemberTracker).GetProperty("BoundTo")
                                 ),
                             typeof(EventTracker)
                             ),
                         typeof(EventTracker).GetProperty("Event")
                         )
                     ),
                 Ast.Constant(et.Event.EventHandlerType)
                 )
             );
     }
 }
Example #12
0
 public static Expression MakeParamsTest(StandardRule <T> rule, object paramArg, Expression listArg)
 {
     return(Ast.AndAlso(
                Ast.TypeIs(listArg, typeof(ICollection <object>)),
                Ast.Equal(
                    Ast.ReadProperty(
                        Ast.Convert(listArg, typeof(ICollection <object>)),
                        typeof(ICollection <object>).GetProperty("Count")
                        ),
                    rule.AddTemplatedConstant(typeof(int), ((IList <object>)paramArg).Count)
                    )
                ));
 }
Example #13
0
        internal virtual void BuildInvoke(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            Assert.NotNull(metaBuilder, args);
            Debug.Assert(args.Target == this);

            // first argument must be this method:
            metaBuilder.AddRestriction(Ast.Equal(args.TargetExpression, AstUtils.Constant(this)));

            // set the target (becomes self in the called method):
            args.SetTarget(AstUtils.Constant(_target, CompilerHelpers.GetVisibleType(_target)), _target);

            _info.BuildCall(metaBuilder, args, _name);
        }
Example #14
0
        /// <summary>
        /// Builds the restrictions for calling with a splatted argument array.  Ensures that the
        /// argument is still an ICollection of object and that it has the same number of arguments.
        /// </summary>
        private static BindingRestrictions MakeParamsTest(DynamicMetaObject splattee, bool testTypes)
        {
            IList <object> list = splattee.Value as IList <object>;

            if (list == null)
            {
                if (splattee.Value == null)
                {
                    return(BindingRestrictions.GetExpressionRestriction(Ast.Equal(splattee.Expression, AstUtils.Constant(null))));
                }
                else
                {
                    return(BindingRestrictions.GetTypeRestriction(splattee.Expression, splattee.Value.GetType()));
                }
            }

            BindingRestrictions res = BindingRestrictions.GetExpressionRestriction(
                Ast.AndAlso(
                    Ast.TypeIs(splattee.Expression, typeof(IList <object>)),
                    Ast.Equal(
                        Ast.Property(
                            Ast.Convert(splattee.Expression, typeof(IList <object>)),
                            typeof(ICollection <object>).GetDeclaredProperty("Count")
                            ),
                        AstUtils.Constant(list.Count)
                        )
                    )
                );

            if (testTypes)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    res = res.Merge(
                        BindingRestrictionsHelpers.GetRuntimeTypeRestriction(
                            Ast.Call(
                                AstUtils.Convert(
                                    splattee.Expression,
                                    typeof(IList <object>)
                                    ),
                                typeof(IList <object>).GetMethod("get_Item"),
                                AstUtils.Constant(i)
                                ),
                            CompilerHelpers.GetType(list[i])
                            )
                        );
                }
            }

            return(res);
        }
Example #15
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()
                       ));
        }
Example #16
0
        /// <summary>
        /// Creates a test which tests the specific version of the type.
        /// </summary>
        private ValidationInfo /*!*/ MakeVersionCheck()
        {
            int version = Value.Version;

            return(new ValidationInfo(
                       Ast.Equal(
                           Ast.Call(
                               typeof(PythonOps).GetMethod("GetTypeVersion"),
                               Ast.Convert(Expression, typeof(PythonType))
                               ),
                           AstUtils.Constant(version)
                           )
                       ));
        }
Example #17
0
        /// <summary>
        /// Binds to the BoundMemberTracker and uses the instance in the tracker and restricts
        /// based upon the object instance type.
        /// </summary>
        private TargetInfo TryGetBoundMemberTargets(DynamicMetaObject self, DynamicMetaObject[] args, BoundMemberTracker bmt)
        {
            if (bmt != null)
            {
                Debug.Assert(bmt.Instance == null); // should be null for trackers that leak to user code

                MethodBase[] targets;

                // instance is pulled from the BoundMemberTracker and restricted to the correct
                // type.
                DynamicMetaObject instance = new DynamicMetaObject(
                    AstUtils.Convert(
                        Ast.Property(
                            Ast.Convert(self.Expression, typeof(BoundMemberTracker)),
                            typeof(BoundMemberTracker).GetDeclaredProperty("ObjectInstance")
                            ),
                        bmt.BoundTo.DeclaringType
                        ),
                    self.Restrictions
                    ).Restrict(CompilerHelpers.GetType(bmt.ObjectInstance));

                // we also add a restriction to make sure we're going to the same BoundMemberTracker
                BindingRestrictions restrictions = BindingRestrictions.GetExpressionRestriction(
                    Ast.Equal(
                        Ast.Property(
                            Ast.Convert(self.Expression, typeof(BoundMemberTracker)),
                            typeof(BoundMemberTracker).GetDeclaredProperty("BoundTo")
                            ),
                        AstUtils.Constant(bmt.BoundTo)
                        )
                    );

                switch (bmt.BoundTo.MemberType)
                {
                case TrackerTypes.MethodGroup:
                    targets = ((MethodGroup)bmt.BoundTo).GetMethodBases();
                    break;

                case TrackerTypes.Method:
                    targets = new MethodBase[] { ((MethodTracker)bmt.BoundTo).Method };
                    break;

                default:
                    throw new InvalidOperationException();     // nothing else binds yet
                }

                return(new TargetInfo(instance, args, restrictions, targets));
            }
            return(null);
        }
Example #18
0
        protected override MethodBase[] GetTargetMethods()
        {
            object target = Arguments[0];
            Type   t      = GetTargetType(target);

            if (t != null)
            {
                Test = Ast.AndAlso(Test, Ast.Equal(Rule.Parameters[0], Ast.Constant(target)));

                return(CompilerHelpers.GetConstructors(t, Binder.PrivateBinding));
            }

            return(null);
        }
Example #19
0
        private void AddRuntimeTest(DynamicMetaObject /*!*/ metaContext)
        {
            Assert.NotNull(metaContext);

            // check for runtime (note that the module's runtime could be different from the call-site runtime):
            if (_siteContext == null)
            {
                // TODO: use holder
                AddRestriction(Ast.Equal(metaContext.Expression, AstUtils.Constant(metaContext.Value)));
            }
            else if (_siteContext != metaContext.Value)
            {
                throw new InvalidOperationException("Runtime-bound site called from a different runtime");
            }
        }
        public void MakeNewRule()
        {
            Type targetType = CompilerHelpers.GetType(Target);

            Rule.MakeTest(StrongBoxType ?? targetType);

            if (typeof(TypeTracker).IsAssignableFrom(targetType))
            {
                targetType = ((TypeTracker)Target).Type;
                _isStatic  = true;
                Rule.AddTest(Ast.Equal(Rule.Parameters[0], Ast.Constant(Arguments[0])));
            }

            MakeSetMemberRule(targetType);
            Rule.Target = Body;
        }
Example #21
0
        private MethodBase[] GetBoundMemberTargets(BoundMemberTracker bmt)
        {
            Debug.Assert(bmt.Instance == null); // should be null for trackers that leak to user code

            MethodBase[] targets;
            _instance = Ast.Convert(
                Ast.Property(
                    Ast.Convert(Rule.Parameters[0], typeof(BoundMemberTracker)),
                    typeof(BoundMemberTracker).GetProperty("ObjectInstance")
                    ),
                bmt.BoundTo.DeclaringType
                );
            _test = Ast.AndAlso(
                _test,
                Ast.Equal(
                    Ast.Property(
                        Ast.Convert(Rule.Parameters[0], typeof(BoundMemberTracker)),
                        typeof(BoundMemberTracker).GetProperty("BoundTo")
                        ),
                    Ast.Constant(bmt.BoundTo)
                    )
                );
            _test = Ast.AndAlso(
                _test,
                Rule.MakeTypeTest(
                    CompilerHelpers.GetType(bmt.ObjectInstance),
                    Ast.Property(
                        Ast.Convert(Rule.Parameters[0], typeof(BoundMemberTracker)),
                        typeof(BoundMemberTracker).GetProperty("ObjectInstance")
                        )
                    )
                );
            switch (bmt.BoundTo.MemberType)
            {
            case TrackerTypes.MethodGroup:
                targets = ((MethodGroup)bmt.BoundTo).GetMethodBases();
                break;

            case TrackerTypes.Method:
                targets = new MethodBase[] { ((MethodTracker)bmt.BoundTo).Method };
                break;

            default:
                throw new InvalidOperationException();     // nothing else binds yet
            }
            return(targets);
        }
Example #22
0
        internal static MethodResolutionResult Resolve(MetaObjectBuilder /*!*/ metaBuilder, string /*!*/ methodName, CallArguments /*!*/ args,
                                                       out RubyMemberInfo methodMissing)
        {
            MethodResolutionResult method;
            var targetClass       = args.TargetClass;
            var visibilityContext = GetVisibilityContext(args.Signature, args.Scope);

            using (targetClass.Context.ClassHierarchyLocker()) {
                metaBuilder.AddTargetTypeTest(args.Target, targetClass, args.TargetExpression, args.MetaContext,
                                              new[] { methodName, Symbols.MethodMissing }
                                              );

                if (args.Signature.IsSuperCall)
                {
                    Debug.Assert(!args.Signature.IsVirtualCall && args.Signature.HasImplicitSelf);
                    method = targetClass.ResolveSuperMethodNoLock(methodName, targetClass).InvalidateSitesOnOverride();
                }
                else
                {
                    var options = args.Signature.IsVirtualCall ? MethodLookup.Virtual : MethodLookup.Default;
                    method = targetClass.ResolveMethodForSiteNoLock(methodName, visibilityContext, options);
                }

                if (!method.Found)
                {
                    methodMissing = targetClass.ResolveMethodMissingForSite(methodName, method.IncompatibleVisibility);
                }
                else
                {
                    methodMissing = null;
                }
            }

            // Whenever the current self's class changes we need to invalidate the rule, if a protected method is being called.
            if (method.Info != null && method.Info.IsProtected && visibilityContext.Class != null)
            {
                // We don't need to compare versions, just the class objects (super-class relationship cannot be changed).
                // Since we don't want to hold on a class object (to make it collectible) we compare references to the version handlers.
                metaBuilder.AddCondition(Ast.Equal(
                                             Methods.GetSelfClassVersionHandle.OpCall(AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope))),
                                             Ast.Constant(visibilityContext.Class.Version)
                                             ));
            }

            return(method);
        }
Example #23
0
        private void BuildCall(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
        {
            var actualArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, Int32.MaxValue);

            if (metaBuilder.Error)
            {
                return;
            }

            metaBuilder.AddRestriction(
                Ast.Equal(
                    Ast.Property(Ast.Convert(args.TargetExpression, typeof(Win32API)), VersionProperty),
                    Ast.Constant(_version)
                    )
                );

            if (_function == IntPtr.Zero)
            {
                metaBuilder.SetError(Ast.Throw(new Func <Exception>(UninitializedFunctionError).Method.OpCall(), typeof(object)));
                return;
            }

            if (_signature.Length != actualArgs.Count)
            {
                metaBuilder.SetError(Ast.Throw(new Func <int, int, Exception>(InvalidParameterCountError).Method.OpCall(
                                                   Ast.Constant(_signature.Length), Ast.Constant(actualArgs.Count)), typeof(object)
                                               ));
                return;
            }

            var calliArgs = new AstExpressions();

            calliArgs.Add(Ast.Property(Ast.Convert(args.TargetExpression, typeof(Win32API)), FunctionProperty));
            for (int i = 0; i < actualArgs.Count; i++)
            {
                calliArgs.Add(MarshalArgument(metaBuilder, actualArgs[i], _signature[i]));
            }

            metaBuilder.Result = Ast.Call(EmitCalliStub(), calliArgs);

            // MRI returns 0 if void return type is given:
            if (_returnType == ArgType.None)
            {
                metaBuilder.Result = Ast.Block(metaBuilder.Result, AstUtils.Constant(0));
            }
        }
Example #24
0
        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);
        }
Example #25
0
        internal void AddSplattedArgumentTest(IList /*!*/ value, Expression /*!*/ expression, out int listLength, out ParameterExpression /*!*/ listVariable)
        {
            Expression assignment;

            listVariable = expression as ParameterExpression;
            if (listVariable != null && typeof(IList).IsAssignableFrom(expression.Type))
            {
                assignment = expression;
            }
            else
            {
                listVariable = GetTemporary(typeof(IList), "#list");
                assignment   = Ast.Assign(listVariable, AstUtils.Convert(expression, typeof(IList)));
            }

            listLength = value.Count;
            AddCondition(Ast.Equal(Ast.Property(assignment, typeof(ICollection).GetDeclaredProperty("Count")), AstUtils.Constant(value.Count)));
        }
Example #26
0
        /// <summary>
        /// Produces a rule for comparing a value to null - supports comparing object references and nullable types.
        /// </summary>
        private static DynamicMetaObject TryNullComparisonRule(DynamicMetaObject[] args)
        {
            Type otherType = args[1].GetLimitType();

            BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args));

            if (args[0].GetLimitType() == typeof(DynamicNull))
            {
                if (!otherType.IsValueType())
                {
                    return(new DynamicMetaObject(
                               Ast.Equal(args[0].Expression, AstUtils.Constant(null)),
                               restrictions
                               ));
                }

                if (otherType.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    return(new DynamicMetaObject(
                               Ast.Property(args[0].Expression, otherType.GetDeclaredProperty("HasValue")),
                               restrictions
                               ));
                }
            }
            else if (otherType == typeof(DynamicNull))
            {
                if (!args[0].GetLimitType().IsValueType())
                {
                    return(new DynamicMetaObject(
                               Ast.Equal(args[0].Expression, AstUtils.Constant(null)),
                               restrictions
                               ));
                }

                if (args[0].GetLimitType().GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    return(new DynamicMetaObject(
                               Ast.Property(args[0].Expression, otherType.GetDeclaredProperty("HasValue")),
                               restrictions
                               ));
                }
            }
            return(null);
        }
Example #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
                );
        }
Example #28
0
        /// <summary>
        /// Produces a rule for comparing a value to null - supports comparing object references and nullable types.
        /// </summary>
        private static MetaObject TryNullComparisonRule(MetaObject[] args)
        {
            Type otherType = args[0].LimitType;

            Restrictions restrictions = Restrictions.GetTypeRestriction(args[0].Expression, args[0].LimitType).Merge(Restrictions.Combine(args));

            if (args[0].LimitType == typeof(Null))
            {
                if (!otherType.IsValueType)
                {
                    return(new MetaObject(
                               Ast.Equal(args[0].Expression, Ast.Constant(null)),
                               restrictions
                               ));
                }
                else if (otherType.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    return(new MetaObject(
                               Ast.Property(args[0].Expression, otherType.GetProperty("HasValue")),
                               restrictions
                               ));
                }
            }
            else if (otherType == typeof(Null))
            {
                if (!args[0].LimitType.IsValueType)
                {
                    return(new MetaObject(
                               Ast.Equal(args[0].Expression, Ast.Constant(null)),
                               restrictions
                               ));
                }
                else if (args[0].LimitType.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    return(new MetaObject(
                               Ast.Property(args[0].Expression, otherType.GetProperty("HasValue")),
                               restrictions
                               ));
                }
            }

            return(null);
        }
Example #29
0
        private MetaObject TryNumericComparison(OperatorInfo info, MetaObject[] args)
        {
            MethodInfo[] targets = FilterNonMethods(
                args[0].LimitType,
                GetMember(OldDoOperationAction.Make(this, info.Operator),
                          args[0].LimitType,
                          "Compare")
                );

            if (targets.Length > 0)
            {
                MethodBinder  mb     = MethodBinder.MakeBinder(this, targets[0].Name, targets);
                BindingTarget target = mb.MakeBindingTarget(CallTypes.None, args);
                if (target.Success)
                {
                    Expression call = AstUtils.Convert(target.MakeExpression(), typeof(int));
                    switch (info.Operator)
                    {
                    case Operators.GreaterThan: call = Ast.GreaterThan(call, Ast.Constant(0)); break;

                    case Operators.LessThan: call = Ast.LessThan(call, Ast.Constant(0)); break;

                    case Operators.GreaterThanOrEqual: call = Ast.GreaterThanOrEqual(call, Ast.Constant(0)); break;

                    case Operators.LessThanOrEqual: call = Ast.LessThanOrEqual(call, Ast.Constant(0)); break;

                    case Operators.Equals: call = Ast.Equal(call, Ast.Constant(0)); break;

                    case Operators.NotEquals: call = Ast.NotEqual(call, Ast.Constant(0)); break;

                    case Operators.Compare:
                        break;
                    }

                    return(new MetaObject(
                               call,
                               Restrictions.Combine(target.RestrictedArguments)
                               ));
                }
            }

            return(null);
        }
Example #30
0
        private DynamicMetaObject TryNumericComparison(OperatorInfo info, OverloadResolverFactory resolverFactory, DynamicMetaObject[] args)
        {
            MethodInfo[] targets = FilterNonMethods(
                args[0].GetLimitType(),
                GetMember(
                    MemberRequestKind.Operation,
                    args[0].GetLimitType(),
                    "Compare"
                    )
                );

            if (targets.Length > 0)
            {
                var           resolver = resolverFactory.CreateOverloadResolver(args, new CallSignature(args.Length), CallTypes.None);
                BindingTarget target   = resolver.ResolveOverload(targets[0].Name, targets, NarrowingLevel.None, NarrowingLevel.All);
                if (target.Success)
                {
                    Expression call = AstUtils.Convert(target.MakeExpression(), typeof(int));
                    switch (info.Operator)
                    {
                    case ExpressionType.GreaterThan: call = Ast.GreaterThan(call, AstUtils.Constant(0)); break;

                    case ExpressionType.LessThan: call = Ast.LessThan(call, AstUtils.Constant(0)); break;

                    case ExpressionType.GreaterThanOrEqual: call = Ast.GreaterThanOrEqual(call, AstUtils.Constant(0)); break;

                    case ExpressionType.LessThanOrEqual: call = Ast.LessThanOrEqual(call, AstUtils.Constant(0)); break;

                    case ExpressionType.Equal: call = Ast.Equal(call, AstUtils.Constant(0)); break;

                    case ExpressionType.NotEqual: call = Ast.NotEqual(call, AstUtils.Constant(0)); break;
                    }

                    return(new DynamicMetaObject(
                               call,
                               target.RestrictedArguments.GetAllRestrictions()
                               ));
                }
            }

            return(null);
        }