/// <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))); } }
/// <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)); } }
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)); } }
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()); }
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()); }
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()); }
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()); }
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))); }
/// <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)); }
/// <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)); }
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); }