private DynamicMetaObject /*!*/ MakeConvertToIEnumerable(DynamicMetaObjectBinder /*!*/ conversion)
        {
            ParameterExpression tmp  = Ast.Variable(typeof(IEnumerable), "res");
            DynamicMetaObject   self = Restrict(typeof(OldInstance));

            return(new DynamicMetaObject(
                       Ast.Block(
                           new ParameterExpression[] { tmp },
                           Ast.Condition(
                               Ast.NotEqual(
                                   Ast.Assign(
                                       tmp,
                                       Ast.Call(
                                           typeof(PythonOps).GetMethod("OldInstanceConvertToIEnumerableNonThrowing"),
                                           AstUtils.Constant(PythonContext.GetPythonContext(conversion).SharedContext),
                                           self.Expression
                                           )
                                       ),
                                   AstUtils.Constant(null)
                                   ),
                               tmp,
                               AstUtils.Convert(
                                   AstUtils.Convert( // first to object (incase it's a throw), then to IEnumerable
                                       FallbackConvert(conversion).Expression,
                                       typeof(object)
                                       ),
                                   typeof(IEnumerable)
                                   )
                               )
                           ),
                       self.Restrictions
                       ));
        }
Пример #2
0
        private static Expression /*!*/ AddExtensibleSelfCheck(DynamicMetaObjectBinder /*!*/ convertToAction, Type toType, DynamicMetaObject /*!*/ self, Expression /*!*/ callExpr)
        {
            ParameterExpression  tmp     = Ast.Variable(callExpr.Type, "tmp");
            ConversionResultKind resKind = GetResultKind(convertToAction);
            Type retType = (resKind == ConversionResultKind.ExplicitTry || resKind == ConversionResultKind.ImplicitTry) ? typeof(object) : toType;

            callExpr = Ast.Block(
                new ParameterExpression[] { tmp },
                Ast.Block(
                    Ast.Assign(tmp, callExpr),
                    Ast.Condition(
                        Ast.Equal(tmp, self.Expression),
                        AstUtils.Convert(
                            Ast.Property(
                                AstUtils.Convert(self.Expression, self.GetLimitType()),
                                self.GetLimitType().GetProperty("Value")
                                ),
                            retType
                            ),
                        Ast.Dynamic(
                            new PythonConversionBinder(
                                PythonContext.GetPythonContext(convertToAction),
                                toType,
                                GetResultKind(convertToAction)
                                ),
                            retType,
                            tmp
                            )
                        )
                    )
                );
            return(callExpr);
        }
Пример #3
0
        /// <code>
        /// End-exclusive range:
        ///   if state
        ///     state = IsFalse({end})
        ///     true
        ///   else
        ///     state = IsTrue({begin})
        ///   end
        ///
        /// End-inclusive range:
        ///   if state || IsTrue({begin})
        ///     state = IsFalse({end})
        ///     true
        ///   else
        ///     false
        ///   end
        /// </code>
        private MSA.Expression /*!*/ TransformReadCondition(AstGenerator /*!*/ gen)
        {
            // Define state variable in the inner most method scope.
            var stateVariable = gen.CurrentMethod.Builder.DefineHiddenVariable("#in_range", typeof(bool));

            var begin = AstFactory.Box(_begin.TransformRead(gen));
            var end   = AstFactory.Box(_end.TransformRead(gen));

            if (_isExclusive)
            {
                return(Ast.Condition(
                           stateVariable,
                           Ast.Block(Ast.Assign(stateVariable, Methods.IsFalse.OpCall(end)), Ast.Constant(true)),
                           Ast.Assign(stateVariable, Methods.IsTrue.OpCall(begin))
                           ));
            }
            else
            {
                return(Ast.Condition(
                           Ast.OrElse(stateVariable, Methods.IsTrue.OpCall(begin)),
                           Ast.Block(Ast.Assign(stateVariable, Methods.IsFalse.OpCall(end)), Ast.Constant(true)),
                           Ast.Constant(false)
                           ));
            }
        }
Пример #4
0
        private DynamicMetaObject /*!*/ MakeConvertToIEnumerable(DynamicMetaObjectBinder /*!*/ conversion, Type toType, Type genericType)
        {
            ParameterExpression tmp  = Ast.Variable(toType, "res");
            DynamicMetaObject   self = Restrict(typeof(OldInstance));

            return(new DynamicMetaObject(
                       Ast.Block(
                           new ParameterExpression[] { tmp },
                           Ast.Condition(
                               Ast.NotEqual(
                                   Ast.Assign(
                                       tmp,
                                       Ast.Call(
                                           typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceConvertToIEnumerableOfTNonThrowing)).MakeGenericMethod(genericType),
                                           AstUtils.Constant(PythonContext.GetPythonContext(conversion).SharedContext),
                                           self.Expression
                                           )
                                       ),
                                   AstUtils.Constant(null)
                                   ),
                               tmp,
                               AstUtils.Convert(
                                   AstUtils.Convert(
                                       FallbackConvert(conversion).Expression,
                                       typeof(object)
                                       ),
                                   toType
                                   )
                               )
                           ),
                       self.Restrictions
                       ));
        }
Пример #5
0
 public static Expression Not(params Expression[] obj)
 {
     if (obj.Length == 1)
     {
         Expression e = Unwrap(obj[0]);
         if (e is UnaryExpression)
         {
             UnaryExpression ue = (UnaryExpression)e;
             if (ue.NodeType == AstNodeType.Not)
             {
                 return(ue.Operand);
             }
         }
         if (e is ConditionalExpression)
         {
             ConditionalExpression ce = (ConditionalExpression)e;
             return(Ast.Condition(ce.Test, Not(ce.IfTrue), Not(ce.IfFalse)));
         }
         if (e.Type == typeof(bool))
         {
             return(Ast.Not(e));
         }
         //return Ast.Equal(Ast.Constant(false), obj[0]);
         return(Ast.Not(Ast.Call(IsTrue, obj[0])));
     }
     return(null);
 }
Пример #6
0
        /// <summary>
        /// Gets the resulting meta object for the full body.  FinishCondition
        /// must have been called.
        /// </summary>
        public DynamicMetaObject /*!*/ GetMetaObject(params DynamicMetaObject /*!*/[] /*!*/ types)
        {
            if (_body == null)
            {
                throw new InvalidOperationException("FinishCondition not called before GetMetaObject");
            }

            Expression body = _body;

            for (int i = _bodies.Count - 1; i >= 0; i--)
            {
                body = Ast.Condition(
                    _conditions[i],
                    AstUtils.Convert(_bodies[i], _retType),
                    AstUtils.Convert(body, _retType)
                    );
            }

            body = Ast.Block(_variables, body);

            return(new DynamicMetaObject(
                       body,
                       BindingRestrictions.Combine(types)
                       ));
        }
Пример #7
0
        public override MSAst.Expression Reduce()
        {
            MSAst.Expression left  = _left;
            MSAst.Expression right = _right;

            Type t = Type;

            MSAst.ParameterExpression tmp = Ast.Variable(t, "__all__");

            return(Ast.Block(
                       new[] { tmp },
                       Ast.Condition(
                           GlobalParent.Convert(
                               typeof(bool),
                               ConversionResultKind.ExplicitCast,
                               Ast.Assign(
                                   tmp,
                                   AstUtils.Convert(
                                       left,
                                       t
                                       )
                                   )
                               ),
                           tmp,
                           AstUtils.Convert(
                               right,
                               t
                               )
                           )
                       ));
        }
Пример #8
0
        private DynamicMetaObject /*!*/ MakeConvertToBool(DynamicMetaObjectBinder /*!*/ conversion)
        {
            DynamicMetaObject self = Restrict(typeof(OldInstance));

            ParameterExpression tmp      = Ast.Variable(typeof(bool?), "tmp");
            DynamicMetaObject   fallback = FallbackConvert(conversion);
            Type resType = BindingHelpers.GetCompatibleType(typeof(bool), fallback.Expression.Type);

            return(new DynamicMetaObject(
                       Ast.Block(
                           new ParameterExpression[] { tmp },
                           Ast.Condition(
                               Ast.NotEqual(
                                   Ast.Assign(
                                       tmp,
                                       Ast.Call(
                                           typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceConvertToBoolNonThrowing)),
                                           AstUtils.Constant(PythonContext.GetPythonContext(conversion).SharedContext),
                                           self.Expression
                                           )
                                       ),
                                   AstUtils.Constant(null)
                                   ),
                               AstUtils.Convert(tmp, resType),
                               AstUtils.Convert(fallback.Expression, resType)
                               )
                           ),
                       self.Restrictions
                       ));
        }
Пример #9
0
        internal static DynamicMetaObject /*!*/ AddDynamicTestAndDefer(DynamicMetaObjectBinder /*!*/ operation, DynamicMetaObject /*!*/ res, DynamicMetaObject /*!*/[] args, ValidationInfo typeTest, Type deferType, params ParameterExpression[] temps)
        {
            if (typeTest != null)
            {
                if (typeTest.Test != null)
                {
                    // add the test and a validator if persent
                    Expression defer = operation.GetUpdateExpression(deferType ?? typeof(object));

                    Type bestType = BindingHelpers.GetCompatibleType(defer.Type, res.Expression.Type);

                    res = new DynamicMetaObject(
                        Ast.Condition(
                            typeTest.Test,
                            AstUtils.Convert(res.Expression, bestType),
                            AstUtils.Convert(defer, bestType)
                            ),
                        res.Restrictions
                        );
                }
            }

            if (temps.Length > 0)
            {
                // finally add the scoped variables
                res = new DynamicMetaObject(
                    Ast.Block(temps, res.Expression),
                    res.Restrictions,
                    null
                    );
            }

            return(res);
        }
Пример #10
0
        internal override Expression ToExpression(MethodBinderContext context, Expression[] parameters)
        {
            // Ideally we'd pass in Ast.ReadField(parameters[Index], "Value") but due to
            // a bug in partial trust we can't access the generic field.

            // arg is boxType ? &_tmp : throw new ArgumentTypeException()
            //   IncorrectBoxType throws the exception to avoid stack imbalance issues.
            return(Ast.Condition(
                       Ast.TypeIs(parameters[Index], BoxType),
                       Ast.Comma(
                           Ast.Assign(
                               _tmp,
                               Ast.Call(
                                   typeof(BinderOps).GetMethod("GetBox").MakeGenericMethod(_elementType),
                                   Ast.ConvertHelper(parameters[Index], typeof(StrongBox <>).MakeGenericType(_elementType))
                                   )
                               ),
                           Ast.Read(_tmp)
                           ),
                       // Condition requires types of both expressions to be identical.
                       // Putting the cast here is a temporary workaround until the
                       // emit address and reference argument passing is finished.
                       Ast.Convert(
                           Ast.Call(
                               typeof(BinderOps).GetMethod("IncorrectBoxType"),
                               Ast.Constant(BoxType),
                               Ast.ConvertHelper(parameters[Index], typeof(object))
                               ),
                           _elementType
                           )
                       ));
        }
Пример #11
0
        internal DynamicMetaObject /*!*/ CreateMetaObject(DynamicMetaObjectBinder /*!*/ binder, Type /*!*/ returnType)
        {
            Debug.Assert(ControlFlowBuilder == null, "Control flow required but not built");

            var restrictions = _restrictions;
            var expr         = _error ? Ast.Throw(_result, returnType) : AstUtils.Convert(_result, returnType);

            if (_condition != null)
            {
                var deferral = binder.GetUpdateExpression(returnType);
                expr = Ast.Condition(_condition, expr, deferral);
            }

            if (_temps != null || _initializations != null)
            {
                AddInitialization(expr);
                if (_temps != null)
                {
                    expr = Ast.Block(_temps, _initializations);
                }
                else
                {
                    expr = Ast.Block(_initializations);
                }
            }

            Clear();
            RubyBinder.DumpRule(binder, restrictions, expr);
            return(new DynamicMetaObject(expr, restrictions));
        }
Пример #12
0
        private MSAst.Expression ReduceWorker(bool optimizeDynamicConvert)
        {
            MSAst.Expression result;

            if (_else != null)
            {
                result = _else;
            }
            else
            {
                result = AstUtils.Empty();
            }

            // Now build from the inside out
            int i = _tests.Length;

            while (i-- > 0)
            {
                IfStatementTest ist = _tests[i];

                result = GlobalParent.AddDebugInfoAndVoid(
                    Ast.Condition(
                        optimizeDynamicConvert ?
                        TransformAndDynamicConvert(ist.Test, typeof(bool)) :
                        GlobalParent.Convert(typeof(bool), Microsoft.Scripting.Actions.ConversionResultKind.ExplicitCast, ist.Test),
                        TransformMaybeSingleLineSuite(ist.Body, ist.Test.Start),
                        result
                        ),
                    new SourceSpan(ist.Start, ist.Header)
                    );
            }

            return(result);
        }
 internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
 {
     return(Ast.Condition(
                _condition.TransformReadBoolean(gen, !_negateCondition),
                AstUtils.Box(_body.TransformRead(gen)),
                (_elseStatement != null) ? AstUtils.Box(_elseStatement.TransformRead(gen)) : (MSA.Expression)AstUtils.Constant(null)
                ));
 }
Пример #14
0
 internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
 {
     return(Ast.Condition(
                TransformCondition(gen),
                AstFactory.Box(_body.TransformRead(gen)),
                (_elseStatement != null) ? AstFactory.Box(_elseStatement.TransformRead(gen)) : (MSA.Expression)Ast.Constant(null)
                ));
 }
Пример #15
0
        private DynamicMetaObject /*!*/ MakeCallRule(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject[] args)
        {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldClass Invoke w/ " + args.Length + " args");
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "OldClass Invoke");

            CallSignature signature = BindingHelpers.GetCallSignature(call);

            // TODO: If we know __init__ wasn't present we could construct the OldInstance directly.

            Expression[] exprArgs = new Expression[args.Length];
            for (int i = 0; i < args.Length; i++)
            {
                exprArgs[i] = args[i].Expression;
            }

            ParameterExpression init    = Ast.Variable(typeof(object), "init");
            ParameterExpression instTmp = Ast.Variable(typeof(object), "inst");
            DynamicMetaObject   self    = Restrict(typeof(OldClass));

            return(new DynamicMetaObject(
                       Ast.Block(
                           new ParameterExpression[] { init, instTmp },
                           Ast.Assign(
                               instTmp,
                               Ast.New(
                                   typeof(OldInstance).GetConstructor(new Type[] { typeof(CodeContext), typeof(OldClass) }),
                                   codeContext,
                                   self.Expression
                                   )
                               ),
                           Ast.Condition(
                               Expression.Not(
                                   Expression.TypeIs(
                                       Expression.Assign(
                                           init,
                                           Ast.Call(
                                               typeof(PythonOps).GetMethod("OldClassTryLookupInit"),
                                               self.Expression,
                                               instTmp
                                               )
                                           ),
                                       typeof(OperationFailed)
                                       )
                                   ),
                               Ast.Dynamic(
                                   PythonContext.GetPythonContext(call).Invoke(
                                       signature
                                       ),
                                   typeof(object),
                                   ArrayUtils.Insert <Expression>(codeContext, init, exprArgs)
                                   ),
                               NoInitCheckNoArgs(signature, self, args)
                               ),
                           instTmp
                           ),
                       self.Restrictions.Merge(BindingRestrictions.Combine(args))
                       ));
        }
Пример #16
0
        private DynamicMetaObject /*!*/ InvokeWorker(DynamicMetaObjectBinder /*!*/ invoke, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] args)
        {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldClass Invoke");

            DynamicMetaObject self = Restrict(typeof(OldInstance));

            Expression[] exprArgs = new Expression[args.Length + 1];
            for (int i = 0; i < args.Length; i++)
            {
                exprArgs[i + 1] = args[i].Expression;
            }

            ParameterExpression tmp = Ast.Variable(typeof(object), "callFunc");

            exprArgs[0] = tmp;
            return(new DynamicMetaObject(
                       // we could get better throughput w/ a more specific rule against our current custom old class but
                       // this favors less code generation.

                       Ast.Block(
                           new ParameterExpression[] { tmp },
                           Ast.Condition(
                               Ast.Call(
                                   typeof(PythonOps).GetMethod("OldInstanceTryGetBoundCustomMember"),
                                   codeContext,
                                   self.Expression,
                                   AstUtils.Constant("__call__"),
                                   tmp
                                   ),
                               Ast.Block(
                                   Utils.Try(
                                       Ast.Call(typeof(PythonOps).GetMethod("FunctionPushFrameCodeContext"), codeContext),
                                       Ast.Assign(
                                           tmp,
                                           Ast.Dynamic(
                                               PythonContext.GetPythonContext(invoke).Invoke(
                                                   BindingHelpers.GetCallSignature(invoke)
                                                   ),
                                               typeof(object),
                                               ArrayUtils.Insert(codeContext, exprArgs)
                                               )
                                           )
                                       ).Finally(
                                       Ast.Call(typeof(PythonOps).GetMethod("FunctionPopFrame"))
                                       ),
                                   tmp
                                   ),
                               Utils.Convert(
                                   BindingHelpers.InvokeFallback(invoke, codeContext, this, args).Expression,
                                   typeof(object)
                                   )
                               )
                           ),
                       self.Restrictions.Merge(BindingRestrictions.Combine(args))
                       ));
        }
        public override MSAst.Expression Reduce()
        {
            MSAst.Expression ifTrue  = AstUtils.Convert(_trueExpr, typeof(object));
            MSAst.Expression ifFalse = AstUtils.Convert(_falseExpr, typeof(object));

            return(Ast.Condition(
                       GlobalParent.Convert(typeof(bool), ConversionResultKind.ExplicitCast, _testExpr),
                       ifTrue,
                       ifFalse
                       ));
        }
Пример #18
0
        // Function Body Code Generation
        //
        // object Func(object self, object[] args) {
        //     object p1 = ...;
        //     object p2 = ...;
        //     ...
        //     object pn = ...;
        //     (..Body..)
        // }
        //
        // <if has_default(p[i]) then>
        //     <p[i]> = <i> < args.Length ? (args[<i>] == void ? <default(p[i])> : args[<i>]) : <default(p[i])>;
        // <else if any_length_args(p[i]) then>
        //     <if has_name(p[i]) then>
        //         <p[i]> = new Array(args.Skip(<i>));
        //     <else>
        //         <p[i]> = new UnnamedSpreadArguments(args, <i>);
        //     <end if>
        // <else>
        //     <p[i]> = <i> < args.Length ? args[<i>] : void;
        // <end if>

        public System.Linq.Expressions.Expression <Func <object, object, object[], object> > TransformLambda()
        {
            List <Ast> body = new List <Ast>();

            for (int i = 0; i < Parameters.Count; i++)
            {
                var capCheck = Ast.LessThan(Ast.Constant(i), Ast.Property(_arguments, "Length"));
                Ast exp;
                if (Parameters[i].HasDefaultValue)
                {
                    exp = Ast.Condition(capCheck,
                                        Ast.Condition(Ast.TypeEqual(Ast.ArrayAccess(_arguments, Ast.Constant(i)), typeof(Builtins.Void)),
                                                      Ast.Constant(Parameters[i].DefaultValue, typeof(object)),
                                                      Ast.ArrayAccess(_arguments, Ast.Constant(i))
                                                      ),
                                        Ast.Constant(Parameters[i].DefaultValue, typeof(object))
                                        );
                }
                else if (Parameters[i].ExpandToArray)
                {
                    if (Parameters[i].ParameterVariable.Name != null)
                    {
                        exp = Ast.New((System.Reflection.ConstructorInfo)Utils.GetMember(() => new Builtins.Array(null)),
                                      Ast.Call(new Func <IEnumerable <object>, int, IEnumerable <object> >(Enumerable.Skip).Method, _arguments, Ast.Constant(i))
                                      );
                    }
                    else
                    {
                        exp = Ast.New((System.Reflection.ConstructorInfo)Utils.GetMember(() => new Runtime.UnnamedSpreadArguments(null, 0)),
                                      _arguments,
                                      Ast.Constant(i)
                                      );
                    }
                }
                else
                {
                    exp = Ast.Condition(capCheck,
                                        Ast.ArrayAccess(_arguments, Ast.Constant(i)),
                                        Ast.Constant(Builtins.Void.Value, typeof(object))
                                        );
                }
                body.Add(Ast.Assign(Parameters[i].ParameterVariable, exp));
            }
            foreach (var statement in Body)
            {
                body.Add(statement.Transform());
            }
            body.Add(Ast.Label(ReturnLabel, Ast.Constant(Builtins.Void.Value)));
            return(Ast.Lambda <Func <object, object, object[], object> >(Ast.Block(_variables.Values.Concat(Parameters.Select(x => x.ParameterVariable)), body), Name, new[] { _global, _context, _arguments }));
        }
Пример #19
0
        static Expression RewriteExpression(CodeBlock cb, Expression e)
        {
            if (e is MethodCallExpression)
            {
                MethodCallExpression mce  = (MethodCallExpression)e;
                List <Expression>    args = new List <Expression>();
                foreach (var arg in mce.Arguments)
                {
                    args.Add(RewriteExpression(cb, arg));
                }

                return(Ast.Call(RewriteExpression(cb, mce.Instance), mce.Method, args.ToArray()));
            }
            if (e is BoundExpression)
            {
                BoundExpression be = (BoundExpression)e;
                return(Ast.Read(cb.Lookup(be.Variable.Name)));
            }

            if (e is BinaryExpression)
            {
                BinaryExpression be = (BinaryExpression)e;
                return(new BinaryExpression(be.NodeType, RewriteExpression(cb, be.Left), RewriteExpression(cb, be.Right)));
            }

            if (e is UnaryExpression)
            {
                UnaryExpression ue = (UnaryExpression)e;
                if (ue.NodeType == AstNodeType.Convert)
                {
                    return(Ast.ConvertHelper(RewriteExpression(cb, ue.Operand), ue.Type));
                }
                return(null);
            }

            if (e is TypeBinaryExpression)
            {
                TypeBinaryExpression tbe = (TypeBinaryExpression)e;
                return(Ast.TypeIs(RewriteExpression(cb, tbe.Expression), tbe.TypeOperand));
            }

            if (e is ConditionalExpression)
            {
                ConditionalExpression ce = (ConditionalExpression)e;
                return(Ast.Condition(RewriteExpression(cb, ce.Test), RewriteExpression(cb, ce.IfTrue), RewriteExpression(cb, ce.IfFalse)));
            }

            return(e);
        }
Пример #20
0
        /// <summary>
        /// Helper to produce the rule for converting T to Nullable of T
        /// </summary>
        private DynamicMetaObject MakeConvertingToTToNullableOfTTarget(OverloadResolverFactory resolverFactory, Type toType, ConversionResultKind kind, BindingRestrictions restrictions, DynamicMetaObject arg)
        {
            Type valueType = toType.GetGenericArguments()[0];

            // ConvertSelfToT -> Nullable<T>
            if (kind == ConversionResultKind.ExplicitCast)
            {
                // if the conversion to T fails we just throw
                Expression conversion = ConvertExpression(arg.Expression, valueType, kind, resolverFactory);

                return(new DynamicMetaObject(
                           Ast.New(
                               toType.GetConstructor(new Type[] { valueType }),
                               conversion
                               ),
                           restrictions
                           ));
            }
            else
            {
                Expression conversion = ConvertExpression(arg.Expression, valueType, kind, resolverFactory);

                // if the conversion to T succeeds then produce the nullable<T>, otherwise return default(retType)
                ParameterExpression tmp = Ast.Variable(typeof(object), "tmp");
                return(new DynamicMetaObject(
                           Ast.Block(
                               new ParameterExpression[] { tmp },
                               Ast.Condition(
                                   Ast.NotEqual(
                                       Ast.Assign(tmp, conversion),
                                       AstUtils.Constant(null)
                                       ),
                                   Ast.New(
                                       toType.GetConstructor(new Type[] { valueType }),
                                       Ast.Convert(
                                           tmp,
                                           valueType
                                           )
                                       ),
                                   GetTryConvertReturnValue(toType)
                                   )
                               ),
                           restrictions
                           ));
            }
        }
Пример #21
0
        private Expression /*!*/ MakeCheckSelf(DynamicMetaObjectBinder /*!*/ binder, CallSignature signature, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            ArgumentType firstArgKind = signature.GetArgumentKind(0);

            Expression res;

            if (firstArgKind == ArgumentType.Simple || firstArgKind == ArgumentType.Instance)
            {
                res = CheckSelf(binder, AstUtils.Convert(Expression, typeof(Method)), args[0].Expression);
            }
            else if (firstArgKind != ArgumentType.List)
            {
                res = CheckSelf(binder, AstUtils.Convert(Expression, typeof(Method)), AstUtils.Constant(null));
            }
            else
            {
                // list, check arg[0] and then return original list.  If not a list,
                // or we have no items, then check against null & throw.
                res = CheckSelf(
                    binder,
                    AstUtils.Convert(Expression, typeof(Method)),
                    Ast.Condition(
                        Ast.AndAlso(
                            Ast.TypeIs(args[0].Expression, typeof(IList <object>)),
                            Ast.NotEqual(
                                Ast.Property(
                                    Ast.Convert(args[0].Expression, typeof(ICollection)),
                                    typeof(ICollection).GetProperty("Count")
                                    ),
                                AstUtils.Constant(0)
                                )
                            ),
                        Ast.Call(
                            Ast.Convert(args[0].Expression, typeof(IList <object>)),
                            typeof(IList <object>).GetMethod("get_Item"),
                            AstUtils.Constant(0)
                            ),
                        AstUtils.Constant(null)
                        )
                    );
            }

            return(res);
        }
Пример #22
0
        /// <code>
        /// End-exclusive range:
        ///   if state
        ///     state = IsFalse({end})
        ///     true
        ///   else
        ///     state = IsTrue({begin})
        ///   end
        ///
        /// End-inclusive range:
        ///   if state || IsTrue({begin})
        ///     state = IsFalse({end})
        ///     true
        ///   else
        ///     false
        ///   end
        /// </code>
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            var begin = AstUtils.Box(_range.Begin.TransformRead(gen));
            var end   = AstUtils.Box(_range.End.TransformRead(gen));

            // state:
            // false <=> null
            // true <=> non-null
            if (_range.IsExclusive)
            {
                return(Ast.Condition(
                           Ast.ReferenceNotEqual(
                               _stateVariable.TransformReadVariable(gen, false),
                               AstUtils.Constant(null)
                               ),
                           Ast.Block(
                               _stateVariable.TransformWriteVariable(gen, Methods.NullIfTrue.OpCall(end)),
                               AstUtils.Constant(true)
                               ),
                           Ast.ReferenceNotEqual(
                               _stateVariable.TransformWriteVariable(gen, Methods.NullIfFalse.OpCall(begin)),
                               AstUtils.Constant(null)
                               )
                           ));
            }
            else
            {
                return(Ast.Condition(
                           Ast.OrElse(
                               Ast.ReferenceNotEqual(
                                   _stateVariable.TransformReadVariable(gen, false),
                                   AstUtils.Constant(null)
                                   ),
                               Methods.IsTrue.OpCall(begin)
                               ),
                           Ast.Block(
                               _stateVariable.TransformWriteVariable(gen, Methods.NullIfTrue.OpCall(end)),
                               AstUtils.Constant(true)
                               ),
                           AstUtils.Constant(false)
                           ));
            }
        }
Пример #23
0
        internal static DynamicMetaObject /*!*/ FilterShowCls(DynamicMetaObject /*!*/ codeContext, DynamicMetaObjectBinder /*!*/ action, DynamicMetaObject /*!*/ res, Expression /*!*/ failure)
        {
            if (action is IPythonSite)
            {
                return(new DynamicMetaObject(
                           Ast.Condition(
                               Ast.Call(
                                   typeof(PythonOps).GetMethod("IsClsVisible"),
                                   codeContext.Expression
                                   ),
                               AstUtils.Convert(res.Expression, typeof(object)),
                               AstUtils.Convert(failure, typeof(object))

                               ),
                           res.Restrictions
                           ));
            }

            return(res);
        }
        protected override MSAst.Expression VisitConditional(MSAst.ConditionalExpression node)
        {
            MSAst.Expression t = Visit(node.Test);

            MSAst.Expression l;
            MSAst.Expression r;

            _insideConditionalBlock = true;
            try {
                l = Visit(node.IfTrue);
                r = Visit(node.IfFalse);
            } finally {
                _insideConditionalBlock = false;
            }

            if (t == node.Test && l == node.IfTrue && r == node.IfFalse)
            {
                return(node);
            }
            return(Ast.Condition(t, l, r, node.Type));
        }
Пример #25
0
        private DynamicMetaObject /*!*/ MakeConvertToCommon(DynamicMetaObjectBinder /*!*/ conversion, Type toType, Type retType, string name)
        {
            // TODO: support trys
            ParameterExpression tmp  = Ast.Variable(typeof(object), "convertResult");
            DynamicMetaObject   self = Restrict(typeof(OldInstance));

            return(new DynamicMetaObject(
                       Ast.Block(
                           new ParameterExpression[] { tmp },
                           Ast.Condition(
                               MakeOneConvert(conversion, self, name, tmp),
                               Expression.Convert(
                                   tmp,
                                   retType
                                   ),
                               FallbackConvert(conversion).Expression
                               )
                           ),
                       self.Restrictions
                       ));
        }
        /// <summary>
        /// Adds the non-conditional terminating node.
        /// </summary>
        public void FinishCondition(Expression body)
        {
            if (_body != null)
            {
                throw new InvalidOperationException();
            }

            for (int i = _bodies.Count - 1; i >= 0; i--)
            {
                Type t = _bodies[i].Type;
                if (t != body.Type)
                {
                    if (t.IsSubclassOf(body.Type))
                    {
                        // subclass
                        t = body.Type;
                    }
                    else if (body.Type.IsSubclassOf(t))
                    {
                        // keep t
                    }
                    else
                    {
                        // incompatible, both go to object
                        t = typeof(object);
                    }
                }

                body = Ast.Condition(
                    _conditions[i],
                    AstUtils.Convert(_bodies[i], t),
                    AstUtils.Convert(body, t)
                    );
            }

            _body = Ast.Block(
                _variables,
                body
                );
        }
Пример #27
0
        public static MSA.Expression /*!*/ Condition(MSA.Expression /*!*/ test, MSA.Expression /*!*/ ifTrue, MSA.Expression /*!*/ ifFalse)
        {
            Assert.NotNull(test, ifTrue, ifFalse);
            Debug.Assert(test.Type == typeof(bool));

            if (ifTrue.Type != ifFalse.Type)
            {
                if (ifTrue.Type.IsAssignableFrom(ifFalse.Type))
                {
                    ifFalse = Ast.Convert(ifFalse, ifTrue.Type);
                }
                else if (ifFalse.Type.IsAssignableFrom(ifTrue.Type))
                {
                    ifTrue = Ast.Convert(ifTrue, ifFalse.Type);
                }
                else
                {
                    ifTrue  = AstUtils.Box(ifTrue);
                    ifFalse = AstUtils.Box(ifFalse);
                }
            }

            return(Ast.Condition(test, ifTrue, ifFalse));
        }
Пример #28
0
        private DynamicMetaObject /*!*/ MakeConvertRuleForCall(DynamicMetaObjectBinder /*!*/ convertToAction, Type toType, DynamicMetaObject /*!*/ self, string name, string returner, Func <DynamicMetaObject> fallback, Func <Expression, Expression> resultConverter)
        {
            PythonType     pt = ((IPythonObject)self.Value).PythonType;
            PythonTypeSlot pts;
            CodeContext    context = PythonContext.GetPythonContext(convertToAction).SharedContext;
            ValidationInfo valInfo = BindingHelpers.GetValidationInfo(this, pt);

            if (pt.TryResolveSlot(context, name, out pts) && !IsBuiltinConversion(context, pts, name, pt))
            {
                ParameterExpression tmp = Ast.Variable(typeof(object), "func");

                Expression callExpr = resultConverter(
                    Ast.Call(
                        PythonOps.GetConversionHelper(returner, GetResultKind(convertToAction)),
                        Ast.Dynamic(
                            PythonContext.GetPythonContext(convertToAction).InvokeNone,
                            typeof(object),
                            PythonContext.GetCodeContext(convertToAction),
                            tmp
                            )
                        )
                    );

                if (typeof(Extensible <>).MakeGenericType(toType).IsAssignableFrom(self.GetLimitType()))
                {
                    // if we're doing a conversion to the underlying type and we're an
                    // Extensible<T> of that type:

                    // if an extensible type returns it's self in a conversion, then we need
                    // to actually return the underlying value.  If an extensible just keeps
                    // returning more instances  of it's self a stack overflow occurs - both
                    // behaviors match CPython.
                    callExpr = AstUtils.Convert(AddExtensibleSelfCheck(convertToAction, toType, self, callExpr), typeof(object));
                }

                return(BindingHelpers.AddDynamicTestAndDefer(
                           convertToAction,
                           new DynamicMetaObject(
                               Ast.Condition(
                                   MakeTryGetTypeMember(
                                       PythonContext.GetPythonContext(convertToAction),
                                       pts,
                                       self.Expression,
                                       tmp
                                       ),
                                   callExpr,
                                   AstUtils.Convert(
                                       ConversionFallback(convertToAction),
                                       typeof(object)
                                       )
                                   ),
                               self.Restrict(self.GetRuntimeType()).Restrictions
                               ),
                           new DynamicMetaObject[] { this },
                           valInfo,
                           tmp
                           ));
            }

            return(fallback());
        }
Пример #29
0
        internal DynamicMetaObject FallbackConvert(Type returnType, DynamicMetaObject self, DynamicMetaObject errorSuggestion)
        {
            Type type             = Type;
            DynamicMetaObject res = null;

            switch (Type.GetTypeCode(type))
            {
            case TypeCode.Boolean:
                res = MakeToBoolConversion(self);
                break;

            case TypeCode.Char:
                res = TryToCharConversion(self);
                break;

            case TypeCode.String:
                if (self.GetLimitType() == typeof(Bytes) && !_context.PythonOptions.Python30)
                {
                    res = new DynamicMetaObject(
                        Ast.Call(
                            typeof(PythonOps).GetMethod("MakeString"),
                            AstUtils.Convert(self.Expression, typeof(IList <byte>))
                            ),
                        BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, typeof(Bytes))
                        );
                }
                break;

            case TypeCode.Object:
                // !!! Deferral?
                if (type.IsArray && self.Value is PythonTuple && type.GetArrayRank() == 1)
                {
                    res = MakeToArrayConversion(self, type);
                }
                else if (type.IsGenericType && !type.IsAssignableFrom(CompilerHelpers.GetType(self.Value)))
                {
                    Type genTo = type.GetGenericTypeDefinition();

                    // Interface conversion helpers...
                    if (genTo == typeof(IList <>))
                    {
                        if (self.LimitType == typeof(string))
                        {
                            res = new DynamicMetaObject(
                                Ast.Call(
                                    typeof(PythonOps).GetMethod("MakeByteArray"),
                                    AstUtils.Convert(self.Expression, typeof(string))
                                    ),
                                BindingRestrictions.GetTypeRestriction(
                                    self.Expression,
                                    typeof(string)
                                    )
                                );
                        }
                        else
                        {
                            res = TryToGenericInterfaceConversion(self, type, typeof(IList <object>), typeof(ListGenericWrapper <>));
                        }
                    }
                    else if (genTo == typeof(IDictionary <,>))
                    {
                        res = TryToGenericInterfaceConversion(self, type, typeof(IDictionary <object, object>), typeof(DictionaryGenericWrapper <,>));
                    }
                    else if (genTo == typeof(IEnumerable <>))
                    {
                        res = TryToGenericInterfaceConversion(self, type, typeof(IEnumerable), typeof(IEnumerableOfTWrapper <>));
                    }
                }
                else if (type == typeof(IEnumerable))
                {
                    if (!typeof(IEnumerable).IsAssignableFrom(self.GetLimitType()) && IsIndexless(self))
                    {
                        res = ConvertToIEnumerable(this, self.Restrict(self.GetLimitType()));
                    }
                }
                else if (type == typeof(IEnumerator))
                {
                    if (!typeof(IEnumerator).IsAssignableFrom(self.GetLimitType()) &&
                        !typeof(IEnumerable).IsAssignableFrom(self.GetLimitType()) &&
                        IsIndexless(self))
                    {
                        res = ConvertToIEnumerator(this, self.Restrict(self.GetLimitType()));
                    }
                }
                break;
            }

            if (type.IsEnum && Enum.GetUnderlyingType(type) == self.GetLimitType())
            {
                // numeric type to enum, this is ok if the value is zero
                object value = Activator.CreateInstance(type);

                return(new DynamicMetaObject(
                           Ast.Condition(
                               Ast.Equal(
                                   AstUtils.Convert(self.Expression, Enum.GetUnderlyingType(type)),
                                   AstUtils.Constant(Activator.CreateInstance(self.GetLimitType()))
                                   ),
                               AstUtils.Constant(value),
                               Ast.Call(
                                   typeof(PythonOps).GetMethod("TypeErrorForBadEnumConversion").MakeGenericMethod(type),
                                   AstUtils.Convert(self.Expression, typeof(object))
                                   )
                               ),
                           self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, self.GetLimitType())),
                           value
                           ));
            }

            return(res ?? EnsureReturnType(returnType, Context.Binder.ConvertTo(Type, ResultKind, self, _context.SharedOverloadResolverFactory, errorSuggestion)));
        }
Пример #30
0
        private DynamicMetaObject /*!*/ MakeDynamicMemberAccess(DynamicMetaObjectBinder /*!*/ member, string /*!*/ name, MemberAccess access, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            DynamicMetaObject self = Restrict(typeof(OldInstance));
            Expression        target;

            ParameterExpression tmp = Ast.Variable(typeof(object), "result");

            switch (access)
            {
            case MemberAccess.Invoke:

                target = Ast.Block(
                    new ParameterExpression[] { tmp },
                    Ast.Condition(
                        Expression.Not(
                            Expression.TypeIs(
                                Expression.Assign(
                                    tmp,
                                    Ast.Call(
                                        typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceTryGetBoundCustomMember)),
                                        AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                                        self.Expression,
                                        AstUtils.Constant(name)
                                        )
                                    ),
                                typeof(OperationFailed)
                                )
                            ),
                        ((InvokeMemberBinder)member).FallbackInvoke(new DynamicMetaObject(tmp, BindingRestrictions.Empty), args, null).Expression,
                        AstUtils.Convert(
                            ((InvokeMemberBinder)member).FallbackInvokeMember(this, args).Expression,
                            typeof(object)
                            )
                        )
                    );
                break;

            case MemberAccess.Get:
                target = Ast.Block(
                    new ParameterExpression[] { tmp },
                    Ast.Condition(
                        Expression.Not(
                            Expression.TypeIs(
                                Expression.Assign(
                                    tmp,
                                    Ast.Call(
                                        typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceTryGetBoundCustomMember)),
                                        AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                                        self.Expression,
                                        AstUtils.Constant(name)
                                        )
                                    ),
                                typeof(OperationFailed)
                                )
                            ),
                        tmp,
                        AstUtils.Convert(
                            FallbackGet(member, args),
                            typeof(object)
                            )
                        )
                    );
                break;

            case MemberAccess.Set:
                target = Ast.Call(
                    typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceSetCustomMember)),
                    AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                    self.Expression,
                    AstUtils.Constant(name),
                    AstUtils.Convert(args[1].Expression, typeof(object))
                    );
                break;

            case MemberAccess.Delete:
                target = Ast.Call(
                    typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceDeleteCustomMember)),
                    AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                    self.Expression,
                    AstUtils.Constant(name)
                    );
                break;

            default:
                throw new InvalidOperationException();
            }

            return(new DynamicMetaObject(
                       target,
                       self.Restrictions.Merge(BindingRestrictions.Combine(args))
                       ));
        }