예제 #1
0
파일: BinderOps.cs 프로젝트: hanabi1224/dlr
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] // TODO: fix
        public static void SetEvent(EventTracker eventTracker, object value)
        {
            if (value is EventTracker et)
            {
                if (et != eventTracker)
                {
                    throw new ArgumentException(String.Format("expected event from {0}.{1}, got event from {2}.{3}",
                                                              eventTracker.DeclaringType.Name,
                                                              eventTracker.Name,
                                                              et.DeclaringType.Name,
                                                              et.Name));
                }
                return;
            }

            BoundMemberTracker bmt = value as BoundMemberTracker;

            if (bmt == null)
            {
                throw new ArgumentTypeException("expected bound event, got " + CompilerHelpers.GetType(value).Name);
            }
            if (bmt.BoundTo.MemberType != TrackerTypes.Event)
            {
                throw new ArgumentTypeException("expected bound event, got " + bmt.BoundTo.MemberType.ToString());
            }

            if (bmt.BoundTo != eventTracker)
            {
                throw new ArgumentException(
                          $"expected event from {eventTracker.DeclaringType.Name}.{eventTracker.Name}, got event from {bmt.BoundTo.DeclaringType.Name}.{bmt.BoundTo.Name}");
            }
        }
예제 #2
0
        public static MethodBase[] GetMethodTargets(object obj)
        {
            Type t = CompilerHelpers.GetType(obj);

            if (typeof(Delegate).IsAssignableFrom(t))
            {
                MethodInfo mi = t.GetMethod("Invoke");
                return(new MethodBase[] { mi });
            }

            if (typeof(BoundMemberTracker).IsAssignableFrom(t))
            {
                BoundMemberTracker bmt = obj as BoundMemberTracker;
                if (bmt.BoundTo.MemberType == TrackerTypes.Method)
                {
                }
            }
            else if (typeof(MethodGroup).IsAssignableFrom(t))
            {
            }
            else if (typeof(MemberGroup).IsAssignableFrom(t))
            {
            }
            else
            {
                return(MakeCallSignatureForCallableObject(t));
            }

            return(null);
        }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] // TODO: fix
        public static void SetEvent(EventTracker eventTracker, object value)
        {
            if (value is EventTracker et)
            {
                if (et != eventTracker)
                {
                    throw Error.UnexpectedEvent(eventTracker.DeclaringType.Name,
                                                eventTracker.Name,
                                                et.DeclaringType.Name,
                                                et.Name);
                }
                return;
            }

            BoundMemberTracker bmt = value as BoundMemberTracker;

            if (bmt == null)
            {
                throw Error.ExpectedBoundEvent(CompilerHelpers.GetType(value).Name);
            }
            if (bmt.BoundTo.MemberType != TrackerTypes.Event)
            {
                throw Error.ExpectedBoundEvent(bmt.BoundTo.MemberType.ToString());
            }

            if (bmt.BoundTo != eventTracker)
            {
                throw Error.UnexpectedEvent(
                          eventTracker.DeclaringType.Name,
                          eventTracker.Name,
                          bmt.BoundTo.DeclaringType.Name,
                          bmt.BoundTo.Name);
            }
        }
예제 #4
0
        public static BoundMemberTracker BoundEventTrackerInPlaceRemove <T>(BoundMemberTracker self, T target)
        {
            if (self.BoundTo.MemberType == TrackerTypes.Event)
            {
                EventTracker et = (EventTracker)self.BoundTo;

                MethodInfo remove = et.Event.GetRemoveMethod(ScriptDomainManager.Options.PrivateBinding);
                remove.Invoke(self.ObjectInstance, new object[] { target });
                return(self);
            }
            throw new InvalidOperationException();
        }
예제 #5
0
 public static object GetItem(BoundMemberTracker self, params object[] keys)
 {
     throw new NotImplementedException();
 }
예제 #6
0
        public DynamicMetaObject FallbackOperation(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
        {
            Expression convertedTarget = Expression.Convert(target.Expression, target.LimitType);

            Expression[] convertedArgs = args.Select(x => Expression.Convert(x.Expression, x.LimitType)).ToArray();
            Expression   exp           = null;
            var          restrictions  = target.Restrictions.Merge(GetTypeRestriction(target));
            int          usedArgs      = 0;

            switch (OperationKind)
            {
            // Unary
            case TjsOperationKind.CharCodeToChar:
                exp = Expression.Call(Context.Convert(convertedTarget, typeof(char)), "ToString", null);
                break;

            case TjsOperationKind.CharToCharCode:
                exp = Expression.Call(new Func <string, long>(TjsOperationHelper.CharToCharCode).Method, Context.Convert(convertedTarget, typeof(string)));
                break;

            case TjsOperationKind.Evaluate:
            case TjsOperationKind.Invalidate:
            case TjsOperationKind.IsValid:
                //MARK: not implemented?
                if (errorSuggestion == null)
                {
                    errorSuggestion = new DynamicMetaObject(Expression.Throw(Expression.Constant(new NotImplementedException())), BindingRestrictions.Empty);
                }
                break;

            case TjsOperationKind.TypeOf:
                if (target.RuntimeType == null)
                {
                    exp = Expression.Constant("Object");
                }
                else if (target.RuntimeType == typeof(Builtins.Void))
                {
                    exp = Expression.Constant("void");
                }
                else if (target.RuntimeType == typeof(string))
                {
                    exp = Expression.Constant("String");
                }
                else if (Binders.IsInteger(target.RuntimeType))
                {
                    exp = Expression.Constant("Integer");
                }
                else if (Binders.IsFloatingPoint(target.RuntimeType))
                {
                    exp = Expression.Constant("Real");
                }
                else
                {
                    exp = Expression.Constant("Object");
                }
                break;

            // Unary (Special)
            case TjsOperationKind.InvokePropertyHandler:
                if (target.LimitType == typeof(Property))
                {
                    if (args.Length == 0)
                    {
                        exp = Expression.Property(convertedTarget, (System.Reflection.PropertyInfo)Utils.GetMember <Property>(x => x.Value));
                    }
                    else if (args.Length == 1)
                    {
                        exp      = Expression.Assign(Expression.Property(convertedTarget, (System.Reflection.PropertyInfo)Utils.GetMember <Property>(x => x.Value)), args[0].Expression);
                        usedArgs = 1;
                    }
                    else
                    {
                        if (errorSuggestion == null)
                        {
                            errorSuggestion = new DynamicMetaObject(Expression.Throw(Expression.Constant(new InvalidOperationException("引数の数が * 演算子に適用できる許容範囲を超えています。"))), BindingRestrictions.Empty);
                        }
                    }
                }
                else if (target.LimitType == typeof(BoundMemberTracker))
                {
                    var tracker = (BoundMemberTracker)target.Value;
                    if (tracker.Instance == null)
                    {
                        tracker = new BoundMemberTracker(tracker.BoundTo, new DynamicMetaObject(Expression.Constant(tracker.ObjectInstance), BindingRestrictions.Empty, tracker.ObjectInstance));
                    }
                    var type = tracker.Instance.GetLimitType();
                    if (args.Length == 0)
                    {
                        var res = tracker.GetValue(new TjsOverloadResolverFactory(Context.Binder), Context.Binder, type);
                        if (res != null)
                        {
                            exp          = res.Expression;
                            restrictions = restrictions.Merge(res.Restrictions);
                        }
                        else
                        {
                            if (errorSuggestion == null)
                            {
                                errorSuggestion = new DynamicMetaObject(Expression.Throw(Expression.Constant(new InvalidOperationException("メンバの取得に失敗しました。"))), BindingRestrictions.Empty);
                            }
                        }
                    }
                    else if (args.Length == 1)
                    {
                        var res = tracker.SetValue(new TjsOverloadResolverFactory(Context.Binder), Context.Binder, type, args[0]);
                        if (res != null)
                        {
                            exp          = res.Expression;
                            restrictions = restrictions.Merge(res.Restrictions);
                            usedArgs     = 1;
                        }
                        else
                        {
                            if (errorSuggestion == null)
                            {
                                errorSuggestion = new DynamicMetaObject(Expression.Throw(Expression.Constant(new InvalidOperationException("メンバの設定に失敗しました。"))), BindingRestrictions.Empty);
                            }
                        }
                    }
                    else
                    {
                        if (errorSuggestion == null)
                        {
                            errorSuggestion = new DynamicMetaObject(Expression.Throw(Expression.Constant(new InvalidOperationException("引数の数が * 演算子に適用できる許容範囲を超えています。"))), BindingRestrictions.Empty);
                        }
                    }
                }
                else
                {
                    if (errorSuggestion == null)
                    {
                        errorSuggestion = new DynamicMetaObject(Expression.Throw(Expression.Constant(new InvalidOperationException("プロパティ以外に対して * 演算子が使用されました。"))), BindingRestrictions.Empty);
                    }
                }
                break;

            // Binary (Arithmetic & Logical)
            case TjsOperationKind.FloorDivide:
                exp      = Expression.Divide(Context.Convert(convertedTarget, typeof(long)), Context.Convert(convertedArgs[0], typeof(long)));
                usedArgs = 1;
                break;

            case TjsOperationKind.RightShiftLogical:
                exp      = Expression.Convert(Expression.RightShift(Context.Convert(convertedTarget, typeof(ulong)), Context.Convert(convertedArgs[0], typeof(int))), typeof(long));
                usedArgs = 1;
                break;

            // Binary (Comparison)
            case TjsOperationKind.DistinctEqual:
                if (convertedTarget.Type == convertedArgs[0].Type)
                {
                    exp = Expression.Condition(Expression.Equal(convertedTarget, convertedArgs[0]), Expression.Constant(1L), Expression.Constant(0L));
                }
                else
                {
                    exp = Expression.Constant(0L);
                }
                usedArgs = 1;
                break;

            case TjsOperationKind.DistinctNotEqual:
                if (convertedTarget.Type == convertedArgs[0].Type)
                {
                    exp = Expression.Condition(Expression.Equal(convertedTarget, convertedArgs[0]), Expression.Constant(0L), Expression.Constant(1L));
                }
                else
                {
                    exp = Expression.Constant(1L);
                }
                usedArgs = 1;
                break;

            // Binary (Special)
            case TjsOperationKind.InstanceOf:
                exp = Expression.Condition(Expression.Equal(Expression.Constant(convertedTarget.Type.Name), Context.Convert(convertedArgs[0], typeof(string))),
                                           Expression.Constant(1L),
                                           Expression.Constant(0L)
                                           );
                usedArgs = 1;
                break;

            case TjsOperationKind.InContextOf:
                if (target.Value is IContextChangeable)
                {
                    exp = Expression.Call(Expression.Convert(convertedTarget, typeof(IContextChangeable)), "ChangeContext", null, args[0].Expression);
                }
                else if (target.LimitType == typeof(BoundMemberTracker))
                {
                    exp = Expression.New((System.Reflection.ConstructorInfo)Utils.GetMember(() => new BoundMemberTracker(null, (object)null)), Expression.PropertyOrField(convertedTarget, "BoundTo"), args[0].Expression);
                }
                else
                {
                    if (errorSuggestion == null)
                    {
                        errorSuggestion = new DynamicMetaObject(Expression.Throw(Expression.Constant(new InvalidOperationException("incontextof 演算子は指定されたオブジェクトに適用できません。"))), BindingRestrictions.Empty);
                    }
                }
                usedArgs = 1;
                break;
            }
            for (int i = 0; i < usedArgs; i++)
            {
                restrictions = restrictions.Merge(args[i].Restrictions).Merge(GetTypeRestriction(args[i]));
            }
            if (exp == null)
            {
                return(new DynamicMetaObject(errorSuggestion.Expression, errorSuggestion.Restrictions.Merge(restrictions)));
            }
            if (exp.Type != typeof(object))
            {
                exp = Expression.Convert(exp, typeof(object));
            }
            return(new DynamicMetaObject(exp, restrictions));
        }
예제 #7
0
        public static BoundMemberTracker BoundEventTrackerInPlaceAdd <T>(CodeContext context, BoundMemberTracker self, T target)
        {
            if (self.BoundTo.MemberType == TrackerTypes.Event)
            {
                EventTracker et = (EventTracker)self.BoundTo;

                MethodInfo add = et.Event.GetAddMethod(context.LanguageContext.DomainManager.Configuration.PrivateBinding);
                add.Invoke(self.ObjectInstance, new object[] { target });
                return(self);
            }
            throw new InvalidOperationException();
        }