Exemplo n.º 1
0
        /// <summary>
        /// Map関数を呼び出す。
        /// </summary>
        /// <param name="target">関数</param>
        /// <param name="arg">リスト</param>
        /// <param name="errorSuggestion"></param>
        /// <returns>リスト</returns>
        public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion)
        {
            Expression expr     = null;
            Expression rest     = null;
            var        funcType = typeof(Func <object, object>);

            if (target.LimitType == funcType)
            {
                var funcExpr = BinderHelper.Wrap(target.Expression, funcType);
                expr = ExpressionHelper.BetaReduction <Func <object, object>, object, object>(
                    (func, lst) => ListLib.Map(func, lst), funcExpr, arg.Expression);
                rest = Expression.TypeIs(target.Expression, funcType);
            }
            funcType = typeof(SuffixFunc <Func <object, object> >);
            if (target.LimitType == funcType)
            {
                expr = ExpressionHelper.BetaReduction <SuffixFunc <Func <object, object> >, object, object>(
                    (sfxFunc, lst) => ListLib.Map(sfxFunc.Func, lst),
                    BinderHelper.Wrap(target.Expression, funcType), arg.Expression);
                rest = Expression.TypeIs(target.Expression, funcType);
            }
            // ----- ----- ----- return ----- ----- -----
            if (expr != null && rest != null)
            {
                return(new DynamicMetaObject(
                           BinderHelper.Wrap(expr, this.ReturnType),
                           BindingRestrictions.GetExpressionRestriction(rest)));
            }
            else
            {
                return(ThrowArgumentException(
                           target.LimitType + "を用いて射影(それぞれ)できません。",
                           BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
            }
        }
Exemplo n.º 2
0
            /// <summary>
            /// 式をListCell.Consでリストにする。
            /// 必要に応じて,展開する。
            /// </summary>
            private Expression Cons(Expression head, Expression tail)
            {
                Contract.Requires <ArgumentNullException>(head != null);
                Contract.Requires <ArgumentNullException>(tail != null);
                Contract.Ensures(Contract.Result <Expression>() != null);
                var constHead = head as ConstantExpression;
                var constTail = tail as ConstantExpression;

                if (constHead != null && constTail != null)
                {
                    var cons = ListCell.Cons(constHead.Value, constTail.Value);
                    return(Expression.Constant(cons));
                }
                else
                {
                    if (head.Type != typeof(object))
                    {
                        head = Expression.Convert(head, typeof(object));
                    }
                    if (tail.Type != typeof(object))
                    {
                        tail = Expression.Convert(tail, typeof(object));
                    }
                    return(ExpressionHelper.BetaReduction <object, object, object>(
                               (left, right) => ListCell.Cons(left, right), head, tail));
                }
            }
Exemplo n.º 3
0
        public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
            const string errorMsg = "{0}を符号反転出来ません。";

            if (target.Value == null)
            {
                var msg      = String.Format(errorMsg, ConstantNames.NullText);
                var ctorInfo = typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) });
                var expr     = Expression.Throw(Expression.New(ctorInfo, Expression.Constant(errorMsg)), this.ReturnType);
                var rest     = BindingRestrictions.GetExpressionRestriction(BinderHelper.IsNull(target.Expression));
                return(new DynamicMetaObject(expr, rest));
            }
            try {
                var expr = BinderHelper.Wrap(Expression.Negate(Expression.Convert(target.Expression, target.LimitType)), this.ReturnType);
                var rest = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType);
                return(new DynamicMetaObject(expr, rest));
            }
            catch (InvalidOperationException) {
                var msgExpr = ExpressionHelper.BetaReduction <string, object, string>(
                    (format, obj) => String.Format(format, obj),
                    Expression.Constant(errorMsg), target.Expression);
                var ctorInfo = typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) });
                var expr     = Expression.Throw(Expression.New(ctorInfo, msgExpr), this.ReturnType);
                var rest     = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType);
                return(new DynamicMetaObject(expr, rest));
            }
        }
Exemplo n.º 4
0
        public void BetaReduction1()
        {
            var param = Expression.Parameter(typeof(int), "foo");
            var expr  = ExpressionHelper.BetaReduction((int a) => a + a, param);

            Assert.AreEqual(Expression.Add(param, param).ToString(), expr.ToString());
        }
Exemplo n.º 5
0
        public void BetaReduction2()
        {
            var param1 = Expression.Parameter(typeof(int), "foo");
            var param2 = Expression.Parameter(typeof(int), "bar");
            var expr   = ExpressionHelper.BetaReduction((int a, int b) => a - b, param1, param2);

            Assert.AreEqual(Expression.Subtract(param1, param2).ToString(), expr.ToString());
        }
Exemplo n.º 6
0
        public void BetaReductionLambda()
        {
            var param = Expression.Parameter(typeof(int), "foo");
            Expression <Func <int, int> > square = a => a * a;
            var lambda = (LambdaExpression)square;
            var expr   = ExpressionHelper.BetaReduction(lambda, param);

            Assert.AreEqual(Expression.Multiply(param, param).ToString(), expr.ToString());
            Assert.AreNotEqual(Expression.Multiply(param, param).ToString(), lambda.ToString());
        }
Exemplo n.º 7
0
        public void BetaReduction3()
        {
            var param1   = Expression.Parameter(typeof(int), "foo");
            var param2   = Expression.Parameter(typeof(int), "bar");
            var param3   = Expression.Parameter(typeof(bool), "baz");
            var actual   = ExpressionHelper.BetaReduction((int a, int b, bool c) => a < b != c, param1, param2, param3);
            var expected = Expression.NotEqual(Expression.LessThan(param1, param2), param3);

            Assert.AreEqual(expected.ToString(), actual.ToString());
        }
Exemplo n.º 8
0
        private DynamicMetaObject InvokeDelegate(DynamicMetaObject target, DynamicMetaObject[] args)
        {
            var  funcType = target.LimitType;
            var  typeArgs = funcType.GetGenericArguments();
            Type type     = null;

            if (Expression.TryGetFuncType(typeArgs, out type))
            {
                Expression[] argExprs = null;
                if (typeArgs.Length == args.Length + 1)
                {
                    argExprs = ConvertArguments(args, typeArgs);
                }
                else if (typeArgs.Length == (2 + 1) && args.Length == 1)
                {
                    // try inline tuple
                    if (args[0].LimitType == typeof(Tuple <object, object>))
                    {
                        var tupleExpr = BinderHelper.Wrap(args[0].Expression, typeof(Tuple <object, object>));
                        var fst       = ExpressionHelper.BetaReduction <Tuple <object, object>, object>(t => t.Item1, tupleExpr);
                        var snd       = ExpressionHelper.BetaReduction <Tuple <object, object>, object>(t => t.Item2, tupleExpr);
                        argExprs = new Expression[] {
                            BinderHelper.Wrap(fst, typeArgs[0]),
                            BinderHelper.Wrap(snd, typeArgs[1])
                        };
                    }
                }
                if (argExprs != null)
                {
                    return(new DynamicMetaObject(
                               Expression.Invoke(Expression.Convert(target.Expression, target.LimitType), argExprs),
                               BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
                }
            }
            if (Expression.TryGetActionType(typeArgs, out type))
            {
                if (typeArgs.Length == args.Length)
                {
                    return(new DynamicMetaObject(
                               Expression.Block(
                                   Expression.Invoke(
                                       Expression.Convert(target.Expression, target.LimitType),
                                       ConvertArguments(args, typeArgs)),
                                   Expression.Constant(null)),
                               BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
                }
            }
            return(ThrowArgumentException(
                       "引数の数が一致していません。",
                       BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)));
        }
Exemplo n.º 9
0
        /// <summary>
        /// 左辺と右辺を参照比較する。
        /// </summary>
        private DynamicMetaObject TryReferenceEqual(DynamicMetaObject left, DynamicMetaObject right)
        {
            if (left.LimitType.IsValueType || right.LimitType.IsValueType)
            {
                return(null);
            }
            var        boolResult = Expression.Constant(this.Operation == ExpressionType.Equal);
            Expression expr       = ExpressionHelper.BetaReduction(
                (object objA, object objB, bool result) => (object)(Object.ReferenceEquals(objA, objB) == result),
                left.Expression, right.Expression, boolResult);

            expr = BinderHelper.Wrap(expr, this.ReturnType);
            var rest = BinderHelper.GetTypeRestriction(left, right);

            return(new DynamicMetaObject(expr, rest));
        }
Exemplo n.º 10
0
        /// <summary>
        /// 左辺がIComparable<T>を実装している場合、CompareToメソッドを呼ぶことで比較する。
        /// </summary>
        private DynamicMetaObject TryUseIComparableT(DynamicMetaObject left, DynamicMetaObject right)
        {
            var types      = left.LimitType.GetInterfaces();
            var cmpType    = typeof(IComparable <>).MakeGenericType(right.LimitType);
            var hasGeneric = Array.IndexOf(types, cmpType) != -1;

            if (hasGeneric == false)
            {
                return(null);
            }
            var callExpr = Expression.Call(
                Expression.Convert(left.Expression, cmpType),
                cmpType.GetMethod("CompareTo", new[] { right.LimitType }),
                Expression.Convert(right.Expression, right.LimitType));
            var expr = BinderHelper.Wrap(ExpressionHelper.BetaReduction(_compareExpr, callExpr), this.ReturnType);
            var rest = BinderHelper.GetTypeRestriction(left, right);

            return(new DynamicMetaObject(expr, rest));
        }
Exemplo n.º 11
0
            private Expression GenBinary(BinaryExpr elem)
            {
                Contract.Requires <ArgumentNullException>(elem != null);
                Contract.Ensures(Contract.Result <Expression>() != null);
                var left   = GenElem(elem.Left);
                var right  = GenElem(elem.Right);
                var binder = SearchBinder(elem.ExprType);

                if (binder != null)
                {
                    return(Expression.Dynamic(binder, typeof(object), left, right));
                }
                switch (elem.ExprType)
                {
                case BinaryOperationType.Cons:
                    return(Cons(left, right));

                case BinaryOperationType.Concat: {
                    return(ExpressionHelper.BetaReduction <object, object, object>(
                               (arg0, arg1) => String.Concat(arg0, arg1), left, right));
                }
                }
                throw Error("未定義の演算が現れました。", elem.Range.Start);
            }