예제 #1
0
 internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
 {
     return(Ast.Block(Transform(gen), AstUtils.Constant(null)));
 }
예제 #2
0
        private DynamicMetaObject /*!*/ MakeSelfCall(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            BindingRestrictions selfRestrict = Restrictions.Merge(
                BindingRestrictionsHelpers.GetRuntimeTypeRestriction(
                    Expression,
                    LimitType
                    )
                ).Merge(
                BindingRestrictions.GetExpressionRestriction(
                    Value.MakeBoundFunctionTest(
                        AstUtils.Convert(Expression, typeof(BuiltinFunction))
                        )
                    )
                );

            Expression instance = Ast.Call(
                typeof(PythonOps).GetMethod(nameof(PythonOps.GetBuiltinFunctionSelf)),
                AstUtils.Convert(
                    Expression,
                    typeof(BuiltinFunction)
                    )
                );

            DynamicMetaObject self = GetInstance(instance, CompilerHelpers.GetType(Value.BindingSelf));

            return(Value.MakeBuiltinFunctionCall(
                       call,
                       codeContext,
                       this,
                       ArrayUtils.Insert(self, args),
                       true, // has self
                       selfRestrict,
                       (newArgs) => {
                CallSignature signature = BindingHelpers.GetCallSignature(call);
                DynamicMetaObject res;
                PythonContext state = PythonContext.GetPythonContext(call);
                BindingTarget target;
                PythonOverloadResolver resolver;
                if (Value.IsReversedOperator)
                {
                    resolver = new PythonOverloadResolver(
                        state.Binder,
                        newArgs,
                        GetReversedSignature(signature),
                        codeContext
                        );
                }
                else
                {
                    resolver = new PythonOverloadResolver(
                        state.Binder,
                        self,
                        args,
                        signature,
                        codeContext
                        );
                }

                res = state.Binder.CallMethod(
                    resolver,
                    Value.Targets,
                    self.Restrictions,
                    Value.Name,
                    NarrowingLevel.None,
                    Value.IsBinaryOperator ? PythonNarrowing.BinaryOperator : NarrowingLevel.All,
                    out target
                    );

                return BindingHelpers.CheckLightThrow(call, res, target);
            }
                       ));
        }
예제 #3
0
 internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
 {
     return(AstUtils.Constant(gen.Encoding));
 }
 public override DynamicMetaObject GetValue(OverloadResolverFactory resolverFactory, ActionBinder binder, Type type)
 {
     return(new DynamicMetaObject(AstUtils.Constant(GetSlot(), typeof(PythonTypeSlot)), BindingRestrictions.Empty));
 }
예제 #5
0
        internal override void BuildMethodMissingCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
        {
            var globalScope = args.TargetClass.GlobalScope;
            var context     = globalScope.Context;

            if (name.LastCharacter() == '=')
            {
                var normalizedArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 1, 1);
                if (!metaBuilder.Error)
                {
                    var scopeVar = metaBuilder.GetTemporary(typeof(Scope), "#scope");

                    metaBuilder.AddInitialization(
                        Ast.Assign(scopeVar, Methods.GetGlobalScopeFromScope.OpCall(AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope))))
                        );

                    var interopSetter = context.MetaBinderFactory.InteropSetMember(name.Substring(0, name.Length - 1));

                    metaBuilder.SetMetaResult(
                        interopSetter.Bind(
                            new DynamicMetaObject(
                                scopeVar,
                                BindingRestrictions.Empty,
                                globalScope.Scope
                                ),
                            new[] { normalizedArgs[0] }
                            ),
                        true
                        );
                }
            }
            else
            {
                RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, 0);
                Expression errorExpr = metaBuilder.Error ? Ast.Throw(metaBuilder.Result, typeof(object)) : null;

                var scopeVar             = metaBuilder.GetTemporary(typeof(Scope), "#scope");
                var scopeLookupResultVar = metaBuilder.GetTemporary(typeof(object), "#result");

                metaBuilder.AddInitialization(
                    Ast.Assign(scopeVar, Methods.GetGlobalScopeFromScope.OpCall(AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope))))
                    );

                Expression scopeLookupResultExpr = errorExpr ?? scopeLookupResultVar;
                Expression fallbackExp;

                if (name == "scope")
                {
                    fallbackExp = errorExpr ?? args.TargetExpression;
                }
                else
                {
                    // super(methodName, ...args...) - ignore argument error:
                    args.InsertMethodName(name);
                    fallbackExp = AstUtils.LightDynamic(
                        context.MetaBinderFactory.Call(Symbols.MethodMissing,
                                                       new RubyCallSignature(
                                                           args.Signature.ArgumentCount + 1,
                                                           args.Signature.Flags | RubyCallFlags.HasImplicitSelf | RubyCallFlags.IsSuperCall
                                                           )
                                                       ),
                        typeof(object),
                        args.GetCallSiteArguments(args.TargetExpression)
                        );
                }

                var scopeLookup = Ast.NotEqual(
                    Ast.Assign(scopeLookupResultVar, AstUtils.LightDynamic(RubyMetaBinderFactory.InteropTryGetMemberExact(name), typeof(object), scopeVar)),
                    Expression.Constant(OperationFailed.Value)
                    );

                string unmanagled = RubyUtils.TryUnmangleMethodName(name);
                if (unmanagled != null)
                {
                    scopeLookup = Ast.OrElse(
                        scopeLookup,
                        Ast.NotEqual(
                            Ast.Assign(scopeLookupResultVar, AstUtils.LightDynamic(RubyMetaBinderFactory.InteropTryGetMemberExact(unmanagled), typeof(object), scopeVar)),
                            Expression.Constant(OperationFailed.Value)
                            )
                        );
                }

                metaBuilder.Result = Ast.Condition(
                    scopeLookup,
                    scopeLookupResultExpr,
                    fallbackExp
                    );
            }
        }
예제 #6
0
        public override MSAst.Expression Reduce()
        {
            MSAst.Expression destination = _dest;

            if (_expressions.Length == 0)
            {
                MSAst.Expression result;
                if (destination != null)
                {
                    result = Ast.Call(
                        AstMethods.PrintNewlineWithDest,
                        Parent.LocalContext,
                        destination
                        );
                }
                else
                {
                    result = Ast.Call(
                        AstMethods.PrintNewline,
                        Parent.LocalContext
                        );
                }
                return(GlobalParent.AddDebugInfo(result, Span));
            }
            else
            {
                // Create list for the individual statements
                ReadOnlyCollectionBuilder <MSAst.Expression> statements = new ReadOnlyCollectionBuilder <MSAst.Expression>();

                // Store destination in a temp, if we have one
                MSAst.ParameterExpression temp = null;
                if (destination != null)
                {
                    temp = Ast.Variable(typeof(object), "destination");

                    statements.Add(MakeAssignment(temp, destination));

                    destination = temp;
                }
                for (int i = 0; i < _expressions.Length; i++)
                {
                    bool       withComma = (i < _expressions.Length - 1 || _trailingComma);// ? "PrintComma" : "Print";
                    Expression current   = _expressions[i];
                    MSAst.MethodCallExpression mce;

                    if (destination != null)
                    {
                        mce = Ast.Call(
                            withComma ? AstMethods.PrintCommaWithDest : AstMethods.PrintWithDest,
                            Parent.LocalContext,
                            destination,
                            AstUtils.Convert(current, typeof(object))
                            );
                    }
                    else
                    {
                        mce = Ast.Call(
                            withComma ? AstMethods.PrintComma : AstMethods.Print,
                            Parent.LocalContext,
                            AstUtils.Convert(current, typeof(object))
                            );
                    }

                    statements.Add(mce);
                }

                statements.Add(AstUtils.Empty());
                MSAst.Expression res;
                if (temp != null)
                {
                    res = Ast.Block(new[] { temp }, statements.ToReadOnlyCollection());
                }
                else
                {
                    res = Ast.Block(statements.ToReadOnlyCollection());
                }
                return(GlobalParent.AddDebugInfo(res, Span));
            }
        }
예제 #7
0
        private DynamicMetaObject TryToCharConversion(DynamicMetaObject /*!*/ self)
        {
            DynamicMetaObject res;
            // we have an implicit conversion to char if the
            // string length == 1, but we can only represent
            // this is implicit via a rule.
            string     strVal  = self.Value as string;
            Expression strExpr = self.Expression;

            if (strVal == null)
            {
                Extensible <string> extstr = self.Value as Extensible <string>;
                if (extstr != null)
                {
                    strVal  = extstr.Value;
                    strExpr =
                        Ast.Property(
                            AstUtils.Convert(
                                strExpr,
                                typeof(Extensible <string>)
                                ),
                            typeof(Extensible <string>).GetProperty("Value")
                            );
                }
            }

            // we can only produce a conversion if we have a string value...
            if (strVal != null)
            {
                self = self.Restrict(self.GetRuntimeType());

                Expression getLen = Ast.Property(
                    AstUtils.Convert(
                        strExpr,
                        typeof(string)
                        ),
                    typeof(string).GetProperty("Length")
                    );

                if (strVal.Length == 1)
                {
                    res = new DynamicMetaObject(
                        Ast.Call(
                            AstUtils.Convert(strExpr, typeof(string)),
                            typeof(string).GetMethod("get_Chars"),
                            AstUtils.Constant(0)
                            ),
                        self.Restrictions.Merge(BindingRestrictions.GetExpressionRestriction(Ast.Equal(getLen, AstUtils.Constant(1))))
                        );
                }
                else
                {
                    res = new DynamicMetaObject(
                        this.Throw(
                            Ast.Call(
                                typeof(PythonOps).GetMethod("TypeError"),
                                AstUtils.Constant("expected string of length 1 when converting to char, got '{0}'"),
                                Ast.NewArrayInit(typeof(object), self.Expression)
                                ),
                            ReturnType
                            ),
                        self.Restrictions.Merge(BindingRestrictions.GetExpressionRestriction(Ast.NotEqual(getLen, AstUtils.Constant(1))))
                        );
                }
            }
            else
            {
                // let the base class produce the rule
                res = null;
            }

            return(res);
        }
예제 #8
0
 internal MSA.Expression DebugMarker(string /*!*/ marker)
 {
     return(_debugCompiler ? Methods.X.OpCall(AstUtils.Constant(marker)) : null);
 }
예제 #9
0
 internal MSA.Expression /*!*/ DebugMark(MSA.Expression /*!*/ expression, string /*!*/ marker)
 {
     return(_debugCompiler ? Ast.Block(Methods.X.OpCall(AstUtils.Constant(marker)), expression) : expression);
 }
예제 #10
0
        internal MSA.Expression /*!*/ TransformStatements(MSA.Expression prologue, Statements /*!*/ statements, MSA.Expression epilogue,
                                                          ResultOperation resultOperation)
        {
            Assert.NotNull(statements);

            int count = statements.Count + (prologue != null ? 1 : 0) + (epilogue != null ? 1 : 0);

            if (count == 0)
            {
                if (resultOperation.IsIgnore)
                {
                    return(AstUtils.Empty());
                }
                else if (resultOperation.Variable != null)
                {
                    return(Ast.Assign(resultOperation.Variable, AstUtils.Constant(null, resultOperation.Variable.Type)));
                }
                else
                {
                    return(Ast.Return(CurrentFrame.ReturnLabel, AstUtils.Constant(null)));
                }
            }
            else if (count == 1)
            {
                if (prologue != null)
                {
                    return(prologue);
                }

                if (epilogue != null)
                {
                    return(epilogue);
                }

                if (resultOperation.IsIgnore)
                {
                    return(statements.First.Transform(this));
                }
                else
                {
                    return(statements.First.TransformResult(this, resultOperation));
                }
            }
            else
            {
                var result = new AstBlock();

                if (prologue != null)
                {
                    result.Add(prologue);
                }

                // transform all but the last statement if it is an expression stmt:
                foreach (var statement in statements.AllButLast)
                {
                    result.Add(statement.Transform(this));
                }

                if (statements.Count > 0)
                {
                    if (resultOperation.IsIgnore)
                    {
                        result.Add(statements.Last.Transform(this));
                    }
                    else
                    {
                        result.Add(statements.Last.TransformResult(this, resultOperation));
                    }
                }

                if (epilogue != null)
                {
                    result.Add(epilogue);
                }

                result.Add(AstUtils.Empty());
                return(result);
            }
        }
예제 #11
0
 internal MSA.Expression /*!*/ MakeHashOpCall(IEnumerable <MSA.Expression> /*!*/ expressions)
 {
     return(Methods.MakeHash.OpCall(CurrentScopeVariable, AstUtils.NewArrayHelper(typeof(object), expressions)));
 }
예제 #12
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());
        }
예제 #13
0
        internal override MSA.Expression /*!*/ MakeDefinitionExpression(AstGenerator /*!*/ gen)
        {
            MSA.Expression transformedQualifier;
            MSA.Expression name             = QualifiedName.TransformName(gen);
            MSA.Expression transformedSuper = (_superClass != null) ? AstUtils.Box(_superClass.TransformRead(gen)) : AstUtils.Constant(null);

            switch (QualifiedName.TransformQualifier(gen, out transformedQualifier))
            {
            case StaticScopeKind.Global:
                return(Methods.DefineGlobalClass.OpCall(gen.CurrentScopeVariable, name, transformedSuper));

            case StaticScopeKind.EnclosingModule:
                return(Methods.DefineNestedClass.OpCall(gen.CurrentScopeVariable, name, transformedSuper));

            case StaticScopeKind.Explicit:
                return(Methods.DefineClass.OpCall(gen.CurrentScopeVariable, transformedQualifier, name, transformedSuper));
            }

            throw Assert.Unreachable;
        }
예제 #14
0
 internal static Expression AddPythonBoxing(Expression res)
 {
     return(AstUtils.Convert(res, typeof(object)));
 }
예제 #15
0
        internal static DynamicMetaObject TranslateArguments(DynamicMetaObjectBinder call, Expression codeContext, DynamicMetaObject function, DynamicMetaObject /*!*/[] args, bool hasSelf, string name)
        {
            if (hasSelf)
            {
                args = ArrayUtils.RemoveFirst(args);
            }

            CallSignature sig = BindingHelpers.GetCallSignature(call);

            if (sig.HasDictionaryArgument())
            {
                int index = sig.IndexOf(ArgumentType.Dictionary);

                DynamicMetaObject dict = args[index];

                if (!(dict.Value is IDictionary) && dict.Value != null)
                {
                    // The DefaultBinder only handles types that implement IDictionary.  Here we have an
                    // arbitrary user-defined mapping type.  We'll convert it into a PythonDictionary
                    // and then have an embedded dynamic site pass that dictionary through to the default
                    // binder.
                    DynamicMetaObject[] dynamicArgs = ArrayUtils.Insert(function, args);

                    dynamicArgs[index + 1] = new DynamicMetaObject(
                        Expression.Call(
                            typeof(PythonOps).GetMethod(nameof(PythonOps.UserMappingToPythonDictionary)),
                            codeContext,
                            args[index].Expression,
                            AstUtils.Constant(name)
                            ),
                        BindingRestrictionsHelpers.GetRuntimeTypeRestriction(dict.Expression, dict.GetLimitType()),
                        PythonOps.UserMappingToPythonDictionary(PythonContext.GetPythonContext(call).SharedContext, dict.Value, name)
                        );

                    if (call is IPythonSite)
                    {
                        dynamicArgs = ArrayUtils.Insert(
                            new DynamicMetaObject(codeContext, BindingRestrictions.Empty),
                            dynamicArgs
                            );
                    }

                    return(new DynamicMetaObject(
                               DynamicExpression.Dynamic(
                                   call,
                                   typeof(object),
                                   DynamicUtils.GetExpressions(dynamicArgs)
                                   ),
                               BindingRestrictions.Combine(dynamicArgs).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(dict.Expression, dict.GetLimitType()))
                               ));
                }
            }

            if (sig.HasListArgument())
            {
                int index = sig.IndexOf(ArgumentType.List);
                DynamicMetaObject list = args[index];

                if (!(list.Value is IList <object>) && list.Value != null)
                {
                    // The DefaultBinder only handles types that implement IList<object>.  Here we have a
                    // arbitrary user-defined sequence type.  We'll convert it into a tuple and then have
                    // an embedded dynamic site pass that tuple through to the default binder.
                    DynamicMetaObject[] dynamicArgs = ArrayUtils.Insert(function, args);

                    dynamicArgs[index + 1] = new DynamicMetaObject(
                        Expression.Call(
                            typeof(PythonOps).GetMethod(nameof(PythonOps.UserMappingToPythonTuple)),
                            codeContext,
                            args[index].Expression,
                            AstUtils.Constant(name)
                            ),
                        BindingRestrictions.Empty
                        );

                    if (call is IPythonSite)
                    {
                        dynamicArgs = ArrayUtils.Insert(
                            new DynamicMetaObject(codeContext, BindingRestrictions.Empty),
                            dynamicArgs
                            );
                    }

                    return(new DynamicMetaObject(
                               DynamicExpression.Dynamic(
                                   call,
                                   typeof(object),
                                   DynamicUtils.GetExpressions(dynamicArgs)
                                   ),
                               function.Restrictions.Merge(
                                   BindingRestrictions.Combine(args).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(list.Expression, list.GetLimitType()))
                                   )
                               ));
                }
            }
            return(null);
        }
예제 #16
0
        private DynamicMetaObject /*!*/ MakeGetMember(DynamicMetaObjectBinder /*!*/ member, DynamicMetaObject codeContext)
        {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldClass GetMember");
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "OldClass GetMember");
            DynamicMetaObject self = Restrict(typeof(OldClass));

            Expression target;
            string     memberName = GetGetMemberName(member);

            switch (memberName)
            {
            case "__dict__":
                target = Ast.Block(
                    Ast.Call(
                        typeof(PythonOps).GetMethod(nameof(PythonOps.OldClassDictionaryIsPublic)),
                        self.Expression
                        ),
                    Ast.Call(
                        typeof(PythonOps).GetMethod(nameof(PythonOps.OldClassGetDictionary)),
                        self.Expression
                        )
                    );
                break;

            case "__bases__":
                target = Ast.Call(
                    typeof(PythonOps).GetMethod(nameof(PythonOps.OldClassGetBaseClasses)),
                    self.Expression
                    );
                break;

            case "__name__":
                target = Ast.Call(
                    typeof(PythonOps).GetMethod(nameof(PythonOps.OldClassGetName)),
                    self.Expression
                    );
                break;

            default:
                ParameterExpression tmp = Ast.Variable(typeof(object), "lookupVal");
                return(new DynamicMetaObject(
                           Ast.Block(
                               new ParameterExpression[] { tmp },
                               Ast.Condition(
                                   Expression.Not(
                                       Expression.TypeIs(
                                           Expression.Assign(
                                               tmp,
                                               Ast.Call(
                                                   typeof(PythonOps).GetMethod(nameof(PythonOps.OldClassTryLookupValue)),
                                                   AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                                                   self.Expression,
                                                   AstUtils.Constant(memberName)
                                                   )
                                               ),
                                           typeof(OperationFailed)
                                           )
                                       ),
                                   tmp,
                                   AstUtils.Convert(
                                       GetMemberFallback(this, member, codeContext).Expression,
                                       typeof(object)
                                       )
                                   )
                               ),
                           self.Restrictions
                           ));
            }

            return(new DynamicMetaObject(
                       target,
                       self.Restrictions
                       ));
        }
예제 #17
0
        protected override Expression VisitGoto(GotoExpression node)
        {
            BranchLabel label;

            var target = node.Target;
            var value  = Visit(node.Value);

            // TODO: Is it possible for an inner reducible node of the loop to rely on nodes produced by reducing outer reducible nodes?

            // Unknown label => must be within the loop:
            if (!_labelMapping.TryGetValue(target, out label))
            {
                return(node.Update(target, value));
            }

            // Known label within the loop:
            if (label.TargetIndex >= _loopStartInstructionIndex && label.TargetIndex < _loopEndInstructionIndex)
            {
                return(node.Update(target, value));
            }

            return(Expression.Return(_returnLabel,
                                     (value != null) ?
                                     Expression.Call(_frameVar, InterpretedFrame.GotoMethod, Expression.Constant(label.LabelIndex), AstUtils.Box(value)) :
                                     Expression.Call(_frameVar, InterpretedFrame.VoidGotoMethod, Expression.Constant(label.LabelIndex)),
                                     node.Type
                                     ));
        }
예제 #18
0
 public override DynamicMetaObject /*!*/ BindInvoke(InvokeBinder /*!*/ call, params DynamicMetaObject /*!*/[] /*!*/ args)
 {
     return(MakeCallRule(call, AstUtils.Constant(PythonContext.GetPythonContext(call).SharedContext), args));
 }
예제 #19
0
        internal DynamicMetaObject FallbackConvert(Type returnType, DynamicMetaObject self, DynamicMetaObject errorSuggestion)
        {
            Type type             = Type;
            DynamicMetaObject res = null;

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

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

            case TypeCode.String:
                var limitType = self.GetLimitType();
                if ((limitType == typeof(Bytes) || limitType == typeof(PythonBuffer) || limitType == typeof(ByteArray)) &&
                    !_context.PythonOptions.Python30)
                {
                    res = new DynamicMetaObject(
                        Ast.Call(
                            typeof(PythonOps).GetMethod("MakeString"),
                            AstUtils.Convert(self.Expression, typeof(IList <byte>))
                            ),
                        BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, limitType)
                        );
                }
                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()))
                    {
                        res = ConvertToIEnumerable(this, self.Restrict(self.GetLimitType()));
                    }
                }
                else if (type == typeof(IEnumerator))
                {
                    if (!typeof(IEnumerator).IsAssignableFrom(self.GetLimitType()) &&
                        !typeof(IEnumerable).IsAssignableFrom(self.GetLimitType()))
                    {
                        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)));
        }
예제 #20
0
 public override DynamicMetaObject /*!*/ BindCreateInstance(CreateInstanceBinder /*!*/ create, params DynamicMetaObject /*!*/[] /*!*/ args)
 {
     return(MakeCallRule(create, AstUtils.Constant(PythonContext.GetPythonContext(create).SharedContext), args));
 }
 public override DynamicMetaObject GetValue(OverloadResolverFactory factory, ActionBinder binder, Type instanceType)
 {
     return(GetBoundValue(factory, binder, instanceType, new DynamicMetaObject(AstUtils.Constant(null), BindingRestrictions.Empty)));
 }
예제 #22
0
        protected virtual void _Generate(AstNodeStmSwitch Switch)
        {
            var allCaseValues = Switch.Cases.Select(Case => Case.CaseValue);
            var caseValues    = allCaseValues as IList <object> ?? allCaseValues.ToList();

            if (caseValues.Count != caseValues.Distinct().Count())
            {
                throw new Exception("Repeated case in switch!");
            }

            // Check types and unique values.

            var endCasesLabel = AstLabel.CreateLabel("EndCasesLabel");
            var defaultLabel  = AstLabel.CreateLabel("DefaultLabel");

            if (Switch.Cases.Length > 0)
            {
                var commonType = Switch.Cases.First().CaseValue.GetType();
                if (Switch.Cases.Any(Case => Case.CaseValue.GetType() != commonType))
                {
                    throw new Exception("All cases should have the same type");
                }

                var doneSpecialized = false;

                // Specialized constant-time integer switch (if possible)
                if (AstUtils.IsIntegerType(commonType))
                {
                    var commonMin   = Switch.Cases.Min(Case => AstUtils.CastType <long>(Case.CaseValue));
                    var commonMax   = Switch.Cases.Max(Case => AstUtils.CastType <long>(Case.CaseValue));
                    var casesLength = commonMax - commonMin + 1;

                    // No processing tables greater than 4096 elements.
                    if (casesLength <= 4096)
                    {
                        var labels = new AstLabel[casesLength];
                        for (var n = 0; n < casesLength; n++)
                        {
                            labels[n] = defaultLabel;
                        }

                        foreach (var Case in Switch.Cases)
                        {
                            var realValue = AstUtils.CastType <long>(Case.CaseValue);
                            var offset    = realValue - commonMin;
                            labels[offset] = AstLabel.CreateLabel("Case_" + realValue);
                        }

                        /*
                         * //var SwitchVarLocal = AstLocal.Create(AllCaseValues.First().GetType(), "SwitchVarLocal" + SwitchVarCount++);
                         * //Generate(new AstNodeStmAssign(new AstNodeExprLocal(SwitchVarLocal), Switch.SwitchValue - new AstNodeExprCast(CommonType, CommonMin)));
                         * //Generate(new AstNodeStmIfElse(new AstNodeExprBinop(new AstNodeExprLocal(SwitchVarLocal), "<", 0), new AstNodeStmGotoAlways(DefaultLabel)));
                         * //Generate(new AstNodeStmIfElse(new AstNodeExprBinop(new AstNodeExprLocal(SwitchVarLocal), ">=", CasesLength), new AstNodeStmGotoAlways(DefaultLabel)));
                         * //Generate(new AstNodeExprLocal(SwitchVarLocal));
                         */

                        Generate(Switch.SwitchValue - new AstNodeExprCast(commonType, commonMin));
                        Emit(OpCodes.Switch, labels);
                        Generate(new AstNodeStmGotoAlways(defaultLabel));
                        foreach (var Case in Switch.Cases)
                        {
                            var realValue = AstUtils.CastType <long>(Case.CaseValue);
                            var offset    = realValue - commonMin;
                            Generate(new AstNodeStmLabel(labels[offset]));
                            {
                                Generate(Case.Code);
                            }
                            Generate(new AstNodeStmGotoAlways(endCasesLabel));
                        }

                        doneSpecialized = true;
                    }
                    else
                    {
                        // TODO: find a common shift and masks for all the values to reduce CasesLength.
                        // TODO: On too large test cases, split them recursively in:
                        // if (Var < Half) { switch(Var - LowerPartMin) { ... } } else { switch(Var - Half - UpperPartMin) { ... } }
                    }
                }
                // Specialized switch for strings (checking length, then hash, then contents)
                else if (commonType == typeof(string))
                {
                    // TODO!
                }

                // Generic if/else
                if (!doneSpecialized)
                {
                    var switchVarLocal =
                        AstLocal.Create(caseValues.First().GetType(), "SwitchVarLocal" + _switchVarCount++);
                    Generate(new AstNodeStmAssign(new AstNodeExprLocal(switchVarLocal), Switch.SwitchValue));
                    //Switch.Cases
                    foreach (var Case in Switch.Cases)
                    {
                        var labelSkipThisCase = AstLabel.CreateLabel("LabelCase" + Case.CaseValue);
                        Generate(new AstNodeStmGotoIfFalse(labelSkipThisCase,
                                                           new AstNodeExprBinop(new AstNodeExprLocal(switchVarLocal), "==",
                                                                                new AstNodeExprImm(Case.CaseValue))));
                        Generate(Case.Code);
                        Generate(new AstNodeStmGotoAlways(endCasesLabel));
                        Generate(new AstNodeStmLabel(labelSkipThisCase));
                    }
                }
            }

            Generate(new AstNodeStmLabel(defaultLabel));
            if (Switch.CaseDefault != null)
            {
                Generate(Switch.CaseDefault.Code);
            }

            Generate(new AstNodeStmLabel(endCasesLabel));
        }
 public override DynamicMetaObject SetValue(OverloadResolverFactory resolverFactory, ActionBinder binder, Type type, DynamicMetaObject value)
 {
     return(SetBoundValue(resolverFactory, binder, type, value, new DynamicMetaObject(AstUtils.Constant(null), BindingRestrictions.Empty)));
 }
예제 #24
0
        protected virtual void _Generate(AstNodeExprImm item)
        {
            var itemType  = AstUtils.GetSignedType(item.Type);
            var itemValue = item.Value;

            if (itemType.IsEnum)
            {
                itemType  = itemType.GetEnumUnderlyingType();
                itemValue = AstUtils.CastType(itemValue, itemType);
            }

            if (
                itemType == typeof(int) ||
                itemType == typeof(sbyte) ||
                itemType == typeof(short) ||
                itemType == typeof(bool)
                )
            {
                var value = (int)Convert.ToInt64(itemValue);
                switch (value)
                {
                case -1:
                    Emit(OpCodes.Ldc_I4_M1);
                    break;

                case 0:
                    Emit(OpCodes.Ldc_I4_0);
                    break;

                case 1:
                    Emit(OpCodes.Ldc_I4_1);
                    break;

                case 2:
                    Emit(OpCodes.Ldc_I4_2);
                    break;

                case 3:
                    Emit(OpCodes.Ldc_I4_3);
                    break;

                case 4:
                    Emit(OpCodes.Ldc_I4_4);
                    break;

                case 5:
                    Emit(OpCodes.Ldc_I4_5);
                    break;

                case 6:
                    Emit(OpCodes.Ldc_I4_6);
                    break;

                case 7:
                    Emit(OpCodes.Ldc_I4_7);
                    break;

                case 8:
                    Emit(OpCodes.Ldc_I4_8);
                    break;

                default:
                    Emit(OpCodes.Ldc_I4, value);
                    break;
                }
            }
            else if (itemType == typeof(long) || itemType == typeof(ulong))
            {
                Emit(OpCodes.Ldc_I8, Convert.ToInt64(itemValue));
            }
            else if (itemType == typeof(IntPtr))
            {
#if false
                Emit(OpCodes.Ldc_I8, ((IntPtr)Item.Value).ToInt64());
                Emit(OpCodes.Conv_I);
#else
                if (Environment.Is64BitProcess)
                {
                    Emit(OpCodes.Ldc_I8, ((IntPtr)item.Value).ToInt64());
                    Emit(OpCodes.Conv_I);
                }
                else
                {
                    Emit(OpCodes.Ldc_I4, ((IntPtr)item.Value).ToInt32());
                    Emit(OpCodes.Conv_I);
                }
#endif
            }
            else if (itemType == typeof(float))
            {
                Emit(OpCodes.Ldc_R4, (float)item.Value);
            }
            else if (item.Value == null)
            {
                Emit(OpCodes.Ldnull);
            }
            else if (itemType == typeof(string))
            {
                Emit(OpCodes.Ldstr, (string)item.Value);
            }
            else if (itemType == typeof(Type))
            {
                Emit(OpCodes.Ldtoken, (Type)item.Value);
                Emit(OpCodes.Call, ((Func <RuntimeTypeHandle, Type>)Type.GetTypeFromHandle).Method);
                //IL_0005: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
            }
            else
            {
                throw new NotImplementedException($"Can't handle immediate type {itemType}");
            }
        }
예제 #25
0
        private DynamicMetaObject /*!*/ MakeSelflessCall(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            // just check if it's the same built-in function.  Because built-in functions are
            // immutable the identity check will suffice.  Because built-in functions are uncollectible
            // anyway we don't use the typical InstanceRestriction.
            BindingRestrictions selfRestrict = BindingRestrictions.GetExpressionRestriction(Ast.Equal(Expression, AstUtils.Constant(Value))).Merge(Restrictions);

            return(Value.MakeBuiltinFunctionCall(
                       call,
                       codeContext,
                       this,
                       args,
                       false, // no self
                       selfRestrict,
                       (newArgs) => {
                BindingTarget target;
                var binder = PythonContext.GetPythonContext(call).Binder;

                DynamicMetaObject res = binder.CallMethod(
                    new PythonOverloadResolver(
                        binder,
                        newArgs,
                        BindingHelpers.GetCallSignature(call),
                        codeContext
                        ),
                    Value.Targets,
                    selfRestrict,
                    Value.Name,
                    PythonNarrowing.None,
                    Value.IsBinaryOperator ? PythonNarrowing.BinaryOperator : NarrowingLevel.All,
                    out target
                    );

                return BindingHelpers.CheckLightThrow(call, res, target);
            }
                       ));
        }
예제 #26
0
        // @TODO: Rewrite using C# 7 features
        protected virtual void _Generate(AstNodeStmAssign assign)
        {
            //Assign.Local.LocalBuilder.LocalIndex
            var astNodeExprLocal             = assign.LeftValue as AstNodeExprLocal;
            var astNodeExprArgument          = assign.LeftValue as AstNodeExprArgument;
            var astNodeExprFieldAccess       = assign.LeftValue as AstNodeExprFieldAccess;
            var astNodeExprStaticFieldAccess = assign.LeftValue as AstNodeExprStaticFieldAccess;
            var astNodeExprIndirect          = assign.LeftValue as AstNodeExprIndirect;
            var astNodeExprArrayAccess       = assign.LeftValue as AstNodeExprArrayAccess;
            var astNodeExprPropertyAccess    = assign.LeftValue as AstNodeExprPropertyAccess;
            var astNodeExprSetGetLValue      = assign.LeftValue as AstNodeExprSetGetLValue;


            if (astNodeExprLocal != null)
            {
                Generate(assign.Value);
                Emit(OpCodes.Stloc, _GetLocalBuilderFromAstLocal(astNodeExprLocal.AstLocal));
            }
            else if (astNodeExprArgument != null)
            {
                Generate(assign.Value);
                Emit(OpCodes.Starg, astNodeExprArgument.AstArgument.Index);
            }
            else if (astNodeExprFieldAccess != null)
            {
                Generate(astNodeExprFieldAccess.Instance);
                Generate(assign.Value);
                Emit(OpCodes.Stfld, astNodeExprFieldAccess.Field);
            }
            else if (astNodeExprStaticFieldAccess != null)
            {
                Generate(assign.Value);
                Emit(OpCodes.Stsfld, astNodeExprStaticFieldAccess.Field);
            }
            else if (astNodeExprArrayAccess != null)
            {
                Generate(astNodeExprArrayAccess.ArrayInstance);
                Generate(astNodeExprArrayAccess.Index);
                Generate(assign.Value);
                Emit(OpCodes.Stelem, astNodeExprArrayAccess.ArrayInstance.Type.GetElementType());
            }
            else if (astNodeExprIndirect != null)
            {
                var pointerType = AstUtils.GetSignedType(astNodeExprIndirect.PointerExpression.Type.GetElementType());

                Generate(astNodeExprIndirect.PointerExpression);
                Generate(assign.Value);

                if (pointerType == typeof(sbyte))
                {
                    Emit(OpCodes.Stind_I1);
                }
                else if (pointerType == typeof(short))
                {
                    Emit(OpCodes.Stind_I2);
                }
                else if (pointerType == typeof(int))
                {
                    Emit(OpCodes.Stind_I4);
                }
                else if (pointerType == typeof(long))
                {
                    Emit(OpCodes.Stind_I8);
                }
                else if (pointerType == typeof(float))
                {
                    Emit(OpCodes.Stind_R4);
                }
                else if (pointerType == typeof(double))
                {
                    Emit(OpCodes.Stind_R8);
                }
                else if (pointerType == typeof(bool))
                {
                    Emit(OpCodes.Stind_I1);
                }
                else
                {
                    throw new NotImplementedException("Can't store indirect value");
                }
            }
            else if (astNodeExprPropertyAccess != null)
            {
                Generate(astNodeExprPropertyAccess.Instance);
                Generate(assign.Value);
                Emit(OpCodes.Callvirt, astNodeExprPropertyAccess.Property.SetMethod);
            }
            else if (astNodeExprSetGetLValue != null)
            {
                _placeholderStack.Push(assign.Value);
                Generate(astNodeExprSetGetLValue.SetExpression);
                if (astNodeExprSetGetLValue.SetExpression.Type != typeof(void))
                {
                    Emit(OpCodes.Pop);
                }
            }
            else
            {
                throw new NotImplementedException("Not implemented AstNodeStmAssign LValue: " +
                                                  assign.LeftValue.GetType());
            }
            //Assign.Local
        }
예제 #27
0
        private DynamicMetaObject /*!*/ GetInstance(Expression /*!*/ instance, Type /*!*/ testType)
        {
            Assert.NotNull(instance, testType);
            object instanceValue = Value.BindingSelf;

            BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(instance, testType);

            // cast the instance to the correct type
            if (CompilerHelpers.IsStrongBox(instanceValue))
            {
                instance      = ReadStrongBoxValue(instance);
                instanceValue = ((IStrongBox)instanceValue).Value;
            }
            else if (!testType.IsEnum())
            {
                // We need to deal w/ wierd types like MarshalByRefObject.
                // We could have an MBRO whos DeclaringType is completely different.
                // Therefore we special case it here and cast to the declaring type

                Type selfType = CompilerHelpers.GetType(Value.BindingSelf);
                selfType = CompilerHelpers.GetVisibleType(selfType);

                if (selfType == typeof(object) && Value.DeclaringType.IsInterface())
                {
                    selfType = Value.DeclaringType;

                    Type genericTypeDefinition = null;
                    // the behavior is different on Mono, it sets FullName for the DeclaringType
                    if (Value.DeclaringType.IsGenericType() &&
                        (ClrModule.IsMono || Value.DeclaringType.FullName == null) &&
                        Value.DeclaringType.ContainsGenericParameters() &&
                        !Value.DeclaringType.IsGenericTypeDefinition())
                    {
                        // from MSDN: If the current type contains generic type parameters that have not been replaced by
                        // specific types (that is, the ContainsGenericParameters property returns true), but the type
                        // is not a generic type definition (that is, the IsGenericTypeDefinition property returns false),
                        // this property returns Nothing. For example, consider the classes Base and Derived in the following code.

                        // if this type is completely generic (no type arguments specified) then we'll go ahead and get the
                        // generic type definition for the this parameter - that'll let us successfully type infer on it later.
                        var  genericArgs     = Value.DeclaringType.GetGenericArguments();
                        bool hasOnlyGenerics = genericArgs.Length > 0;
                        foreach (var genericParam in genericArgs)
                        {
                            if (!genericParam.IsGenericParameter)
                            {
                                hasOnlyGenerics = false;
                                break;
                            }
                        }
                        if (hasOnlyGenerics)
                        {
                            genericTypeDefinition = Value.DeclaringType.GetGenericTypeDefinition();
                        }
                    }
                    else if (Value.DeclaringType.IsGenericTypeDefinition())
                    {
                        genericTypeDefinition = Value.DeclaringType;
                    }

                    if (genericTypeDefinition != null)
                    {
                        // we're a generic interface method on a non-public type.
                        // We need to see if we can match any types implemented on
                        // the concrete selfType.
                        var interfaces = CompilerHelpers.GetType(Value.BindingSelf).GetInterfaces();
                        foreach (var iface in interfaces)
                        {
                            if (iface.IsGenericType() && iface.GetGenericTypeDefinition() == genericTypeDefinition)
                            {
                                selfType = iface;
                                break;
                            }
                        }
                    }
                }

                if (Value.DeclaringType.IsInterface() && selfType.IsValueType())
                {
                    // explicit interface implementation dispatch on a value type, don't
                    // unbox the value type before the dispatch.
                    instance = AstUtils.Convert(instance, Value.DeclaringType);
                }
                else if (selfType.IsValueType())
                {
                    // We might be calling a a mutating method (like
                    // Rectangle.Intersect). If so, we want it to mutate
                    // the boxed value directly
                    instance = Ast.Unbox(instance, selfType);
                }
                else
                {
#if FEATURE_REMOTING
                    Type convType = selfType == typeof(MarshalByRefObject) ? CompilerHelpers.GetVisibleType(Value.DeclaringType) : selfType;
                    instance = AstUtils.Convert(instance, convType);
#else
                    instance = AstUtils.Convert(instance, selfType);
#endif
                }
            }
            else
            {
                // we don't want to cast the enum to its real type, it will unbox it
                // and turn it into its underlying type.  We presumably want to call
                // a method on the Enum class though - so we cast to Enum instead.
                instance = AstUtils.Convert(instance, typeof(Enum));
            }
            return(new DynamicMetaObject(
                       instance,
                       restrictions,
                       instanceValue
                       ));
        }
예제 #28
0
        protected virtual void _Generate(AstNodeExprBinop item)
        {
            var leftType = item.LeftNode.Type;

            //var rightType = item.RightNode.Type;

            //if (LeftType != RightType) throw(new Exception(String.Format("BinaryOp Type mismatch ({0}) != ({1})", LeftType, RightType)));

            //Item.GetType().GenericTypeArguments[0]
            Generate(item.LeftNode);
            Generate(item.RightNode);

            //switch (Item.Operator)
            //{
            //	case "||":
            //	case "&&":
            //		if (LeftType != typeof(bool) || RightType != typeof(bool))
            //		{
            //			throw(new InvalidOperationException(String.Format("Operator '{0}' requires boolean types but found {1}, {2}", Item.Operator, LeftType, RightType)));
            //		}
            //		break;
            //}

            switch (item.Operator)
            {
            case "+":
                Emit(OpCodes.Add);
                break;

            case "-":
                Emit(OpCodes.Sub);
                break;

            case "*":
                Emit(OpCodes.Mul);
                break;

            case "/":
                Emit(AstUtils.IsTypeSigned(leftType) ? OpCodes.Div : OpCodes.Div_Un);
                break;

            case "%":
                Emit(AstUtils.IsTypeSigned(leftType) ? OpCodes.Rem : OpCodes.Rem_Un);
                break;

            case "==":
                Emit(OpCodes.Ceq);
                break;

            case "!=":
                Emit(OpCodes.Ceq);
                Emit(OpCodes.Ldc_I4_0);
                Emit(OpCodes.Ceq);
                break;

            case "<":
                Emit(AstUtils.IsTypeSigned(leftType) ? OpCodes.Clt : OpCodes.Clt_Un);
                break;

            case ">":
                Emit(AstUtils.IsTypeSigned(leftType) ? OpCodes.Cgt : OpCodes.Cgt_Un);
                break;

            case "<=":
                Emit(AstUtils.IsTypeSigned(leftType) ? OpCodes.Cgt : OpCodes.Cgt_Un);
                Emit(OpCodes.Ldc_I4_0);
                Emit(OpCodes.Ceq);
                break;

            case ">=":
                Emit(AstUtils.IsTypeSigned(leftType) ? OpCodes.Clt : OpCodes.Clt_Un);
                Emit(OpCodes.Ldc_I4_0);
                Emit(OpCodes.Ceq);
                break;

            case "&":
            case "&&":
                Emit(OpCodes.And);
                break;

            case "|":
            case "||":
                Emit(OpCodes.Or);
                break;

            case "^":
                Emit(OpCodes.Xor);
                break;

            case "<<":
                Emit(OpCodes.Shl);
                break;

            case ">>":
                Emit(AstUtils.IsTypeSigned(leftType) ? OpCodes.Shr : OpCodes.Shr_Un);
                break;

            default: throw new NotImplementedException($"Not implemented operator '{item.Operator}'");
            }
        }
예제 #29
0
        // see Ruby Language.doc/Runtime/Control Flow Implementation/Return
        internal override MSA.Expression /*!*/ Transform(AstGenerator /*!*/ gen)
        {
            MSA.Expression transformedReturnValue = TransformReturnValue(gen);

            // eval:
            if (gen.CompilerOptions.IsEval)
            {
                return(gen.Return(Methods.EvalReturn.OpCall(gen.CurrentScopeVariable, AstUtils.Box(transformedReturnValue))));
            }

            // block:
            if (gen.CurrentBlock != null)
            {
                return(gen.Return(Methods.BlockReturn.OpCall(gen.CurrentBlock.BfcVariable, AstUtils.Box(transformedReturnValue))));
            }

            // method:
            return(gen.Return(transformedReturnValue));
        }
예제 #30
0
        private DynamicMetaObject /*!*/ MakeSetMember(SetMemberBinder /*!*/ member, DynamicMetaObject /*!*/ value)
        {
            PythonContext     state = PythonContext.GetPythonContext(member);
            DynamicMetaObject self  = Restrict(Value.GetType());

            if (Value.GetType() != typeof(PythonType) && DynamicHelpers.GetPythonType(Value).IsSystemType)
            {
                // built-in subclass of .NET type.  Usually __setattr__ is handled by MetaUserObject
                // but we can have a built-in subtype that's not a user type.
                PythonTypeSlot pts;
                if (Value.TryGetCustomSetAttr(state.SharedContext, out pts))
                {
                    Debug.Assert(pts.GetAlwaysSucceeds);

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

                    return(BindingHelpers.AddDynamicTestAndDefer(
                               member,
                               new DynamicMetaObject(
                                   Ast.Block(
                                       new[] { tmp },
                                       DynamicExpression.Dynamic(
                                           state.Invoke(new CallSignature(2)),
                                           typeof(object),
                                           AstUtils.Constant(state.SharedContext),
                                           Ast.Block(
                                               Ast.Call(
                                                   typeof(PythonOps).GetMethod(nameof(PythonOps.SlotTryGetValue)),
                                                   AstUtils.Constant(state.SharedContext),
                                                   AstUtils.Convert(AstUtils.WeakConstant(pts), typeof(PythonTypeSlot)),
                                                   AstUtils.Convert(Expression, typeof(object)),
                                                   AstUtils.Convert(AstUtils.WeakConstant(DynamicHelpers.GetPythonType(Value)), typeof(PythonType)),
                                                   tmp
                                                   ),
                                               tmp
                                               ),
                                           Ast.Constant(member.Name),
                                           value.Expression
                                           )
                                       ),
                                   self.Restrictions
                                   ),
                               new DynamicMetaObject[] { this, value },
                               TestUserType()
                               ));
                }
            }

            return(BindingHelpers.AddDynamicTestAndDefer(
                       member,
                       new DynamicMetaObject(
                           Ast.Call(
                               typeof(PythonOps).GetMethod("PythonTypeSetCustomMember"),
                               AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                               self.Expression,
                               AstUtils.Constant(member.Name),
                               AstUtils.Convert(
                                   value.Expression,
                                   typeof(object)
                                   )
                               ),
                           self.Restrictions.Merge(value.Restrictions)
                           ),
                       new DynamicMetaObject[] { this, value },
                       TestUserType()
                       ));
        }