コード例 #1
0
        private MSAst.Expression AssignComplex(MSAst.Expression right)
        {
            // Python assignment semantics:
            // - only evaluate RHS once.
            // - evaluates assignment from left to right
            // - does not evaluate getters.
            //
            // So
            //   a=b[c]=d=f()
            // should be:
            //   $temp = f()
            //   a = $temp
            //   b[c] = $temp
            //   d = $temp

            List <MSAst.Expression> statements = new List <MSAst.Expression>();

            // 1. Create temp variable for the right value
            MSAst.ParameterExpression right_temp = Expression.Variable(typeof(object), "assignment");

            // 2. right_temp = right
            statements.Add(MakeAssignment(right_temp, right));

            // Do left to right assignment
            foreach (Expression e in _left)
            {
                if (e == null)
                {
                    continue;
                }

                // 3. e = right_temp
                MSAst.Expression transformed = e.TransformSet(Span, right_temp, PythonOperationKind.None);

                statements.Add(transformed);
            }

            // 4. Create and return the resulting suite
            statements.Add(AstUtils.Empty());
            return(GlobalParent.AddDebugInfoAndVoid(
                       Ast.Block(new[] { right_temp }, statements.ToArray()),
                       Span
                       ));
        }
コード例 #2
0
        internal void SetRule(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            RubyModule currentDeclaringModule;
            string     currentMethodName;

            var scope = args.Scope;

            object target;

            scope.GetSuperCallTarget(out currentDeclaringModule, out currentMethodName, out target);

            var targetExpression = metaBuilder.GetTemporary(typeof(object), "#super-self");

            metaBuilder.AddCondition(
                Methods.IsSuperCallTarget.OpCall(
                    AstUtils.Convert(args.ScopeExpression, typeof(RubyScope)),
                    Ast.Constant(currentDeclaringModule),
                    AstUtils.Constant(currentMethodName),
                    targetExpression
                    )
                );

            args.SetTarget(targetExpression, target);

            Debug.Assert(currentDeclaringModule != null);

            // target is stored in a local, therefore it cannot be part of the restrictions:
            metaBuilder.TreatRestrictionsAsConditions = true;
            metaBuilder.AddTargetTypeTest(target, targetExpression, scope.RubyContext, args.ContextExpression);
            metaBuilder.TreatRestrictionsAsConditions = false;

            RubyMemberInfo method = scope.RubyContext.ResolveSuperMethod(target, currentMethodName, currentDeclaringModule);

            // super calls don't go to method_missing
            if (method == null)
            {
                metaBuilder.SetError(Methods.MakeMissingSuperException.OpCall(Ast.Constant(currentMethodName)));
            }
            else
            {
                method.InvalidateSitesOnOverride = true;
                method.BuildSuperCall(metaBuilder, args, currentMethodName, currentDeclaringModule);
            }
        }
コード例 #3
0
        private static Expression CoalesceInternal(Expression left, Expression right, MethodInfo isTrue, bool isReverse, out ParameterExpression temp)
        {
            ContractUtils.RequiresNotNull(left, "left");
            ContractUtils.RequiresNotNull(right, "right");

            // A bit too strict, but on a safe side.
            ContractUtils.Requires(left.Type == right.Type, "Expression types must match");

            temp = Expression.Variable(left.Type, "tmp_left");

            Expression condition;

            if (isTrue != null)
            {
                ContractUtils.Requires(isTrue.ReturnType == typeof(bool), "isTrue", "Predicate must return bool.");
                ParameterInfo[] parameters = isTrue.GetParameters();
                ContractUtils.Requires(parameters.Length == 1, "isTrue", "Predicate must take one parameter.");
                ContractUtils.Requires(isTrue.IsStatic && isTrue.IsPublic, "isTrue", "Predicate must be public and static.");

                Type pt = parameters[0].ParameterType;
                ContractUtils.Requires(TypeUtils.CanAssign(pt, left.Type), "left", "Incorrect left expression type");
                condition = Expression.Call(isTrue, Expression.Assign(temp, left));
            }
            else
            {
                ContractUtils.Requires(TypeUtils.CanCompareToNull(left.Type), "left", "Incorrect left expression type");
                condition = Expression.Equal(Expression.Assign(temp, left), AstUtils.Constant(null, left.Type));
            }

            Expression t, f;

            if (isReverse)
            {
                t = temp;
                f = right;
            }
            else
            {
                t = right;
                f = temp;
            }

            return(Expression.Condition(condition, t, f));
        }
コード例 #4
0
        /// <summary>
        /// Produces a rule for comparing a value to null - supports comparing object references and nullable types.
        /// </summary>
        private static DynamicMetaObject TryNullComparisonRule(DynamicMetaObject[] args)
        {
            Type otherType = args[1].GetLimitType();

            BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args));

            if (args[0].GetLimitType() == typeof(DynamicNull))
            {
                if (!otherType.IsValueType)
                {
                    return(new DynamicMetaObject(
                               Expression.Equal(args[0].Expression, AstUtils.Constant(null)),
                               restrictions
                               ));
                }

                if (otherType.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    return(new DynamicMetaObject(
                               Expression.Property(args[0].Expression, otherType.GetDeclaredProperty("HasValue")),
                               restrictions
                               ));
                }
            }
            else if (otherType == typeof(DynamicNull))
            {
                if (!args[0].GetLimitType().IsValueType)
                {
                    return(new DynamicMetaObject(
                               Expression.Equal(args[0].Expression, AstUtils.Constant(null)),
                               restrictions
                               ));
                }

                if (args[0].GetLimitType().GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    return(new DynamicMetaObject(
                               Expression.Property(args[0].Expression, otherType.GetDeclaredProperty("HasValue")),
                               restrictions
                               ));
                }
            }
            return(null);
        }
コード例 #5
0
ファイル: ActionBinder.cs プロジェクト: gaybro8777/ironruby
        /// <summary>
        /// Builds an expression for a call to the provided method using the given expressions.  If the
        /// method is not static the first parameter is used for the instance.
        ///
        /// Parameters are converted using the binder's conversion rules.
        ///
        /// If an incorrect number of parameters is provided MakeCallExpression returns null.
        /// </summary>
        public Expression MakeCallExpression(Expression context, MethodInfo method, IList <Expression> parameters)
        {
            ParameterInfo[] infos = method.GetParameters();
            Expression      callInst = null;
            int             parameter = 0, startArg = 0;

            Expression[] callArgs = new Expression[infos.Length];

            if (!method.IsStatic)
            {
                callInst  = AstUtils.Convert(parameters[0], method.DeclaringType);
                parameter = 1;
            }
            if (infos.Length > 0 && typeof(CodeContext).IsAssignableFrom(infos[0].ParameterType))
            {
                startArg    = 1;
                callArgs[0] = context;
            }

            for (int arg = startArg; arg < infos.Length; arg++)
            {
                if (parameter < parameters.Count)
                {
                    callArgs[arg] = ConvertExpression(
                        parameters[parameter++],
                        infos[arg].ParameterType,
                        ConversionResultKind.ExplicitCast,
                        context
                        );
                }
                else
                {
                    return(null);
                }
            }

            // check that we used all parameters
            if (parameter != parameters.Count)
            {
                return(null);
            }

            return(AstUtils.SimpleCallHelper(callInst, method, callArgs));
        }
コード例 #6
0
        public override MSAst TransformCore(ScriptGenerator generator)
        {
            var target     = Target;
            var type       = (Type)null;
            var targetType = target as TypeExpression;

            MSAst transformedTarget;

            if (targetType != null)
            {
                type = targetType.Type;
                transformedTarget = MSAst.Constant(type, typeof(Type));
            }
            else
            {
                transformedTarget = target.Transform(generator);
            }

            var method = Method;

            if (method != null)
            {
                return(MSAstUtil.ComplexCallHelper(
                           (type != null) ? null : transformedTarget,
                           method,
                           Arguments.Select(o => o.Value.Transform(generator)).ToArray()));
            }

            if (type != null)
            {
                return(MSAst.Call(
                           type,
                           MethodName,
                           TypeArguments.ResolvedTypes,
                           _arguments.Transform(generator)));
            }

            return(MSAst.Call(
                       transformedTarget,
                       MethodName,
                       TypeArguments.ResolvedTypes,
                       _arguments.Transform(generator)));
        }
コード例 #7
0
        private void AddInitialiation(ReadOnlyCollectionBuilder <MSAst.Expression> block)
        {
            if (IsModule)
            {
                block.Add(AssignValue(GetVariableExpression(FileVariable), Ast.Constant(ModuleFileName)));
                block.Add(AssignValue(GetVariableExpression(NameVariable), Ast.Constant(ModuleName)));
            }

            if (_languageFeatures != ModuleOptions.None || IsModule)
            {
                block.Add(
                    Ast.Call(
                        AstMethods.ModuleStarted,
                        LocalContext,
                        AstUtils.Constant(_languageFeatures)
                        )
                    );
            }
        }
 /// <summary>
 /// Helper to wrap explicit conversion call into try/catch incase it throws an exception.  If
 /// it throws the default value is returned.
 /// </summary>
 private static Expression WrapForThrowingTry(ConversionResultKind kind, bool isImplicit, Expression ret, Type retType)
 {
     if (!isImplicit && kind == ConversionResultKind.ExplicitTry)
     {
         Expression          convFailed = GetTryConvertReturnValue(retType);
         ParameterExpression tmp        = Expression.Variable(convFailed.Type == typeof(object) ? typeof(object) : ret.Type, "tmp");
         ret = Expression.Block(
             new ParameterExpression[] { tmp },
             AstUtils.Try(
                 Expression.Assign(tmp, AstUtils.Convert(ret, tmp.Type))
                 ).Catch(
                 typeof(Exception),
                 Expression.Assign(tmp, convFailed)
                 ),
             tmp
             );
     }
     return(ret);
 }
コード例 #9
0
        private MetaObject TryNumericComparison(OperatorInfo info, MetaObject[] args)
        {
            MethodInfo[] targets = FilterNonMethods(
                args[0].LimitType,
                GetMember(OldDoOperationAction.Make(this, info.Operator),
                          args[0].LimitType,
                          "Compare")
                );

            if (targets.Length > 0)
            {
                MethodBinder  mb     = MethodBinder.MakeBinder(this, targets[0].Name, targets);
                BindingTarget target = mb.MakeBindingTarget(CallTypes.None, args);
                if (target.Success)
                {
                    Expression call = AstUtils.Convert(target.MakeExpression(), typeof(int));
                    switch (info.Operator)
                    {
                    case Operators.GreaterThan: call = Ast.GreaterThan(call, Ast.Constant(0)); break;

                    case Operators.LessThan: call = Ast.LessThan(call, Ast.Constant(0)); break;

                    case Operators.GreaterThanOrEqual: call = Ast.GreaterThanOrEqual(call, Ast.Constant(0)); break;

                    case Operators.LessThanOrEqual: call = Ast.LessThanOrEqual(call, Ast.Constant(0)); break;

                    case Operators.Equals: call = Ast.Equal(call, Ast.Constant(0)); break;

                    case Operators.NotEquals: call = Ast.NotEqual(call, Ast.Constant(0)); break;

                    case Operators.Compare:
                        break;
                    }

                    return(new MetaObject(
                               call,
                               Restrictions.Combine(target.RestrictedArguments)
                               ));
                }
            }

            return(null);
        }
コード例 #10
0
        public override MSAst.Expression Reduce()
        {
            var codeObj  = GetOrMakeFunctionCode();
            var funcCode = GlobalParent.Constant(codeObj);

            FuncCodeExpr = funcCode;

            MSAst.Expression lambda;
            if (EmitDebugSymbols)
            {
                lambda = GetLambda();
            }
            else
            {
                lambda = NullLambda;
                ThreadPool.QueueUserWorkItem((x) => {
                    // class defs are almost always run, so start
                    // compiling the code now so it might be ready
                    // when we actually go and execute it
                    codeObj.UpdateDelegate(PyContext, true);
                });
            }

            MSAst.Expression classDef = Ast.Call(
                AstMethods.MakeClass,
                funcCode,
                lambda,
                Parent.LocalContext,
                AstUtils.Constant(_name),
                UnpackBasesHelper(_bases),
                Metaclass is null ? AstUtils.Constant(null, typeof(object)) : AstUtils.Convert(Metaclass, typeof(object)),
                AstUtils.Constant(FindSelfNames())
                );

            classDef = AddDecorators(classDef, Decorators);

            return(GlobalParent.AddDebugInfoAndVoid(
                       AssignValue(Parent.GetVariableExpression(PythonVariable), classDef),
                       new SourceSpan(
                           GlobalParent.IndexToLocation(StartIndex),
                           GlobalParent.IndexToLocation(HeaderIndex)
                           )
                       ));
コード例 #11
0
 private static void AddArgument(List <Expression> /*!*/ actualArgs, object arg, Expression /*!*/ expr)
 {
     if (arg == null)
     {
         actualArgs.Add(Ast.Constant(null));
     }
     else
     {
         var type = CompilerHelpers.GetVisibleType(arg);
         if (type.IsValueType)
         {
             actualArgs.Add(expr);
         }
         else
         {
             actualArgs.Add(AstUtils.Convert(expr, type));
         }
     }
 }
コード例 #12
0
        public MSAst.Expression CreateExpression()
        {
            MSAst.Expression[] items = new MSAst.Expression[Count * 2];
            int index = 0;

            foreach (var item in GetItems())
            {
                items[index++] = Utils.Convert(Utils.Constant(item.Value), typeof(object));
                items[index++] = Utils.Convert(Utils.Constant(item.Key), typeof(object));
            }

            return(MSAst.Expression.Call(
                       typeof(PythonOps).GetMethod(nameof(PythonOps.MakeConstantDictStorage)),
                       MSAst.Expression.NewArrayInit(
                           typeof(object),
                           items
                           )
                       ));
        }
コード例 #13
0
        internal override DynamicMetaObject Call(OverloadResolverFactory resolverFactory, ActionBinder binder, params DynamicMetaObject[] arguments)
        {
            if (Method.IsPublic && Method.DeclaringType.IsVisible())
            {
                return(binder.MakeCallExpression(resolverFactory, Method, arguments));
            }

            //methodInfo.Invoke(obj, object[] params)
            if (Method.IsStatic)
            {
                return(new DynamicMetaObject(
                           Expression.Convert(
                               Expression.Call(
                                   AstUtils.Constant(Method),
                                   typeof(MethodInfo).GetMethod("Invoke", new Type[] { typeof(object), typeof(object[]) }),
                                   AstUtils.Constant(null),
                                   AstUtils.NewArrayHelper(typeof(object), ArrayUtils.ConvertAll(arguments, x => x.Expression))
                                   ),
                               Method.ReturnType
                               ),
                           BindingRestrictions.Empty
                           )
                       );
            }

            if (arguments.Length == 0)
            {
                throw Error.NoInstanceForCall();
            }

            return(new DynamicMetaObject(
                       Expression.Convert(
                           Expression.Call(
                               AstUtils.Constant(Method),
                               typeof(MethodInfo).GetMethod("Invoke", new Type[] { typeof(object), typeof(object[]) }),
                               arguments[0].Expression,
                               AstUtils.NewArrayHelper(typeof(object), ArrayUtils.ConvertAll(ArrayUtils.RemoveFirst(arguments), x => x.Expression))
                               ),
                           Method.ReturnType
                           ),
                       BindingRestrictions.Empty
                       ));
        }
        /// <summary>
        /// Helper to produce a rule when no conversion is required (the strong type of the expression
        /// input matches the type we're converting to or has an implicit conversion at the IL level)
        /// </summary>
        private static DynamicMetaObject MakeSimpleConversionTarget(Type toType, BindingRestrictions restrictions, DynamicMetaObject arg)
        {
            return(new DynamicMetaObject(
                       AstUtils.Convert(arg.Expression, CompilerHelpers.GetVisibleType(toType)),
                       restrictions));

            /*
             * if (toType.IsValueType && _rule.ReturnType == typeof(object) && Expression.Type == typeof(object)) {
             *  // boxed value type is being converted back to object.  We've done
             *  // the type check, there's no need to unbox & rebox the value.  infact
             *  // it breaks calls on instance methods so we need to avoid it.
             *  _rule.Target =
             *      _rule.MakeReturn(
             *          Binder,
             *          Expression
             *      );
             * }
             * */
        }
コード例 #15
0
ファイル: DefaultBinder.Operations.cs プロジェクト: zuvys/dlr
        private DynamicMetaObject TryNumericComparison(OperatorInfo info, OverloadResolverFactory resolverFactory, DynamicMetaObject[] args)
        {
            MethodInfo[] targets = FilterNonMethods(
                args[0].GetLimitType(),
                GetMember(
                    MemberRequestKind.Operation,
                    args[0].GetLimitType(),
                    "Compare"
                    )
                );

            if (targets.Length > 0)
            {
                var           resolver = resolverFactory.CreateOverloadResolver(args, new CallSignature(args.Length), CallTypes.None);
                BindingTarget target   = resolver.ResolveOverload(targets[0].Name, targets, NarrowingLevel.None, NarrowingLevel.All);
                if (target.Success)
                {
                    Expression call = AstUtils.Convert(target.MakeExpression(), typeof(int));
                    switch (info.Operator)
                    {
                    case ExpressionType.GreaterThan: call = Expression.GreaterThan(call, AstUtils.Constant(0)); break;

                    case ExpressionType.LessThan: call = Expression.LessThan(call, AstUtils.Constant(0)); break;

                    case ExpressionType.GreaterThanOrEqual: call = Expression.GreaterThanOrEqual(call, AstUtils.Constant(0)); break;

                    case ExpressionType.LessThanOrEqual: call = Expression.LessThanOrEqual(call, AstUtils.Constant(0)); break;

                    case ExpressionType.Equal: call = Expression.Equal(call, AstUtils.Constant(0)); break;

                    case ExpressionType.NotEqual: call = Expression.NotEqual(call, AstUtils.Constant(0)); break;
                    }

                    return(new DynamicMetaObject(
                               call,
                               target.RestrictedArguments.GetAllRestrictions()
                               ));
                }
            }

            return(null);
        }
コード例 #16
0
ファイル: Proc.cs プロジェクト: gaybro8777/ironruby
        internal static void SetCallActionRule(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, bool testTarget)
        {
            Assert.NotNull(metaBuilder, args);

            var convertedTarget = AstUtils.Convert(args.TargetExpression, typeof(Proc));

            // test for target type:
            if (testTarget)
            {
                metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression);
            }

            SetProcCallRule(
                metaBuilder,
                convertedTarget,                              // proc object
                Ast.Property(convertedTarget, SelfProperty),  // self captured by the block closure
                null,
                args
                );
        }
コード例 #17
0
ファイル: Expression.cs プロジェクト: dc366/ironpython3
        protected internal static MSAst.BlockExpression UnpackSequenceHelper <T>(IList <Expression> items, MethodInfo makeEmpty, MethodInfo append, MethodInfo extend)
        {
            var expressions = new ReadOnlyCollectionBuilder <MSAst.Expression>(items.Count + 2);
            var varExpr     = Expression.Variable(typeof(T), "$coll");

            expressions.Add(Expression.Assign(varExpr, Expression.Call(makeEmpty)));
            foreach (var item in items)
            {
                if (item is StarredExpression starredExpression)
                {
                    expressions.Add(Expression.Call(extend, varExpr, AstUtils.Convert(starredExpression.Value, typeof(object))));
                }
                else
                {
                    expressions.Add(Expression.Call(append, varExpr, AstUtils.Convert(item, typeof(object))));
                }
            }
            expressions.Add(varExpr);
            return(Expression.Block(typeof(T), new MSAst.ParameterExpression[] { varExpr }, expressions));
        }
コード例 #18
0
 /// <summary>
 ///   Helper to wrap explicit conversion call into try/catch incase it throws an exception.  If
 ///   it throws the default value is returned.
 /// </summary>
 private static MSAst WrapForThrowingTry(ConversionResultKind kind, bool isImplicit, MSAst ret, Type retType)
 {
     if (!isImplicit && kind == ConversionResultKind.ExplicitTry)
     {
         var convFailed = GetTryConvertReturnValue(retType);
         //var tmp = MSAst.Variable(convFailed.Type == typeof(object) ? typeof(object) : ret.Type, "tmp");
         return(AstUtils.Convert(ret, convFailed.Type == typeof(object) ? typeof(object) : ret.Type));
         //ret = MSAst.Block(
         //        new[] { tmp },
         //        AstUtils.Try(
         //            MSAst.Assign(tmp, AstUtils.Convert(ret, tmp.Type))
         //        ).Catch(
         //            typeof(Exception),
         //            MSAst.Assign(tmp, convFailed)
         //        ),
         //        tmp
         //     );
     }
     return(ret);
 }
コード例 #19
0
        public Expression CreateExpression()
        {
            if (_infos == null)
            {
                return(Expression.New(
                           typeof(CallSignature).GetConstructor(new Type[] { typeof(int) }),
                           AstUtils.Constant(ArgumentCount)
                           ));
            }

            Expression[] args = new Expression[_infos.Length];
            for (int i = 0; i < args.Length; i++)
            {
                args[i] = _infos[i].CreateExpression();
            }
            return(Expression.New(
                       typeof(CallSignature).GetConstructor(new Type[] { typeof(Argument[]) }),
                       Expression.NewArrayInit(typeof(Argument), args)
                       ));
        }
コード例 #20
0
            public override MetaObject /*!*/ BindInvoke(InvokeBinder /*!*/ action, MetaObject /*!*/[] /*!*/ args)
            {
                RubyCallSignature callSignature;

                if (RubyCallSignature.TryCreate(action.Arguments, out callSignature))
                {
                    return(action.FallbackInvoke(this, args));
                }

                var metaBuilder = new MetaObjectBuilder();

                var context = new MetaObject(
                    Methods.GetContextFromBlockParam.OpCall(AstUtils.Convert(Expression, typeof(BlockParam))),
                    Restrictions.Empty,
                    RubyOps.GetContextFromBlockParam((BlockParam)Value)
                    );

                BlockParam.SetCallActionRule(metaBuilder, new CallArguments(context, this, args, callSignature));
                return(metaBuilder.CreateMetaObject(action, args));
            }
コード例 #21
0
        protected override bool TryImplicitConversion(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            object target           = args.Target;
            var    targetExpression = args.TargetExpression;

            if (args.Target == null)
            {
                metaBuilder.SetError(Methods.CreateTypeConversionError.OpCall(Ast.Constant("nil"), Ast.Constant(TargetTypeName)));
                return(true);
            }

            var str = target as MutableString;

            if (str != null)
            {
                metaBuilder.Result = Methods.ConvertMutableStringToSymbol.OpCall(AstUtils.Convert(targetExpression, typeof(MutableString)));
                return(true);
            }

            var sym = target as string;

            if (sym != null)
            {
                metaBuilder.Result = AstUtils.Convert(targetExpression, typeof(string));
                return(true);
            }

            if (target is SymbolId)
            {
                metaBuilder.Result = Methods.ConvertSymbolIdToSymbol.OpCall(AstUtils.Convert(targetExpression, typeof(SymbolId)));
                return(true);
            }

            if (target is int)
            {
                metaBuilder.Result = Methods.ConvertFixnumToSymbol.OpCall(args.ContextExpression, AstUtils.Convert(targetExpression, typeof(int)));
                return(true);
            }

            return(false);
        }
コード例 #22
0
        public MetaObject Restrict(Type type)
        {
            if (type == LimitType)
            {
                return(this);
            }

            if (HasValue)
            {
                return(new RestrictedMetaObject(
                           AstUtils.Convert(Expression, type),
                           Restrictions.GetTypeRestriction(Expression, type),
                           Value
                           ));
            }

            return(new RestrictedMetaObject(
                       AstUtils.Convert(Expression, type),
                       Restrictions.GetTypeRestriction(Expression, type)
                       ));
        }
コード例 #23
0
        public DynamicMetaObject Restrict(Type type)
        {
            if (type == LimitType)
            {
                return(this);
            }

            if (HasValue)
            {
                return(new RestrictedMetaObject(
                           AstUtils.Convert(Expression, type),
                           BindingRestrictionsHelpers.GetRuntimeTypeRestriction(Expression, type),
                           Value
                           ));
            }

            return(new RestrictedMetaObject(
                       AstUtils.Convert(Expression, type),
                       BindingRestrictionsHelpers.GetRuntimeTypeRestriction(Expression, type)
                       ));
        }
コード例 #24
0
        // see Ruby Language.doc/Runtime/Control Flow Implementation/Yield
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            MSA.Expression bfcVariable    = gen.CurrentScope.DefineHiddenVariable("#yielded-bfc", typeof(BlockParam));
            MSA.Expression resultVariable = gen.CurrentScope.DefineHiddenVariable("#result", typeof(object));
            MSA.Expression evalUnwinder   = gen.CurrentScope.DefineHiddenVariable("#unwinder", typeof(EvalUnwinder));

            MSA.Expression postYield;

            if (gen.CompilerOptions.IsEval)
            {
                // eval:
                postYield = Methods.EvalYield.OpCall(gen.CurrentRfcVariable, bfcVariable, resultVariable);
            }
            else if (gen.CurrentBlock != null)
            {
                // block:
                postYield = Methods.BlockYield.OpCall(gen.CurrentRfcVariable, gen.CurrentBlock.BfcVariable, bfcVariable, resultVariable);
            }
            else
            {
                // method:
                postYield = Methods.MethodYield.OpCall(gen.CurrentRfcVariable, bfcVariable, resultVariable);
            }

            return(AstFactory.Block(
                       gen.DebugMarker("#RB: yield begin"),

                       Ast.Assign(bfcVariable, Methods.CreateBfcForYield.OpCall(gen.MakeMethodBlockParameterRead())),

                       Ast.Assign(resultVariable, (Arguments ?? Arguments.Empty).TransformToYield(gen, bfcVariable,
                                                                                                  Ast.Property(AstUtils.Convert(gen.MakeMethodBlockParameterRead(), typeof(Proc)), Proc.SelfProperty)
                                                                                                  )),

                       AstUtils.IfThen(postYield, gen.Return(resultVariable)),

                       gen.DebugMarker("#RB: yield end"),

                       resultVariable
                       ));
        }
コード例 #25
0
ファイル: ConditionalBuilder.cs プロジェクト: zuvys/dlr
        /// <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 = Expression.Condition(
                    _conditions[i],
                    AstUtils.Convert(_bodies[i], t),
                    AstUtils.Convert(body, t)
                    );
            }

            _body = Expression.Block(
                _variables,
                body
                );
        }
コード例 #26
0
        /// <summary>
        /// Builds the restrictions for calling with keyword arguments.  The restrictions include
        /// tests on the individual keys of the dictionary to ensure they have the same names.
        /// </summary>
        private static BindingRestrictions MakeParamsDictionaryTest(IList <DynamicMetaObject> args, bool testTypes)
        {
            IDictionary           dict     = (IDictionary)args[args.Count - 1].Value;
            IDictionaryEnumerator dictEnum = dict.GetEnumerator();

            // verify the dictionary has the same count and arguments.

            string[] names = new string[dict.Count];
            Type[]   types = testTypes ? new Type[dict.Count] : null;
            int      index = 0;

            while (dictEnum.MoveNext())
            {
                string name = dictEnum.Entry.Key as string;
                if (name == null)
                {
                    throw ScriptingRuntimeHelpers.SimpleTypeError(
                              $"expected string for dictionary argument got {dictEnum.Entry.Key}");
                }
                names[index] = name;
                if (types != null)
                {
                    types[index] = CompilerHelpers.GetType(dictEnum.Entry.Value);
                }
                index++;
            }

            return(BindingRestrictions.GetExpressionRestriction(
                       Ast.AndAlso(
                           Ast.TypeIs(args[args.Count - 1].Expression, typeof(IDictionary)),
                           Ast.Call(
                               typeof(BinderOps).GetMethod("CheckDictionaryMembers"),
                               Ast.Convert(args[args.Count - 1].Expression, typeof(IDictionary)),
                               AstUtils.Constant(names),
                               testTypes ? AstUtils.Constant(types) : AstUtils.Constant(null, typeof(Type[]))
                               )
                           )
                       ));
        }
コード例 #27
0
ファイル: ScriptScope.cs プロジェクト: gaybro8777/ironruby
            // TODO: support for IgnoreCase in underlying ScriptScope APIs
            public override MetaObject BindGetMember(GetMemberBinder action)
            {
                var result   = Expression.Variable(typeof(object), "result");
                var fallback = action.FallbackGetMember(this);

                return(new MetaObject(
                           Expression.Block(
                               new ParameterExpression[] { result },
                               Expression.Condition(
                                   Expression.Call(
                                       AstUtils.Convert(Expression, typeof(ScriptScope)),
                                       typeof(ScriptScope).GetMethod("TryGetVariable", new[] { typeof(string), typeof(object).MakeByRefType() }),
                                       Expression.Constant(action.Name),
                                       result
                                       ),
                                   result,
                                   Expression.Convert(fallback.Expression, typeof(object))
                                   )
                               ),
                           Restrictions.GetTypeRestriction(Expression, typeof(ScriptScope)).Merge(fallback.Restrictions)
                           ));
            }
コード例 #28
0
ファイル: MethodCall.cs プロジェクト: gaybro8777/ironruby
        internal static MSA.Expression /*!*/ MakeCallWithBlockRetryable(AstGenerator /*!*/ gen, MSA.Expression /*!*/ invoke,
                                                                        MSA.Expression blockArgVariable, MSA.Expression transformedBlock, bool isBlockDefinition)
        {
            Assert.NotNull(invoke);
            Debug.Assert((blockArgVariable == null) == (transformedBlock == null));

            // see Ruby Language.doc/Control Flow Implementation/Method Call With a Block
            MSA.Expression          resultVariable = gen.CurrentScope.DefineHiddenVariable("#method-result", typeof(object));
            MSA.ParameterExpression evalUnwinder   = gen.CurrentScope.DefineHiddenVariable("#unwinder", typeof(EvalUnwinder));

            MSA.LabelTarget label = Ast.Label();

            return(AstFactory.Block(
                       Ast.Assign(blockArgVariable, Ast.Convert(transformedBlock, blockArgVariable.Type)),
                       AstFactory.Infinite(label, null,
                                           (!isBlockDefinition) ?
                                           (MSA.Expression)Ast.Empty() :
                                           (MSA.Expression)Methods.InitializeBlock.OpCall(blockArgVariable),

                                           AstUtils.Try(
                                               Ast.Assign(resultVariable, invoke)
                                               ).Catch(evalUnwinder,
                                                       Ast.Assign(
                                                           resultVariable,
                                                           Ast.Field(evalUnwinder, EvalUnwinder.ReturnValueField)
                                                           )
                                                       ),

                                           // if result != RetrySingleton then break end
                                           AstUtils.Unless(Methods.IsRetrySingleton.OpCall(AstFactory.Box(resultVariable)), Ast.Break(label)),

                                           // if blockParam == #block then retry end
                                           (gen.CurrentMethod.IsTopLevelCode) ? Ast.Empty() :
                                           AstUtils.IfThen(Ast.Equal(gen.MakeMethodBlockParameterRead(), blockArgVariable), RetryStatement.TransformRetry(gen))

                                           ),
                       resultVariable
                       ));
        }
コード例 #29
0
ファイル: DefaultBinder.Invoke.cs プロジェクト: gavz/IronKit
        /// <summary>
        /// Provides default binding for performing a call on the specified meta objects.
        /// </summary>
        /// <param name="signature">The signature describing the call</param>
        /// <param name="target">The meta object to be called.</param>
        /// <param name="args">
        /// Additional meta objects are the parameters for the call as specified by the CallSignature in the CallAction.
        /// </param>
        /// <param name="resolverFactory">Overload resolver factory.</param>
        /// <param name="errorSuggestion">The result should the object be uncallable.</param>
        /// <returns>A MetaObject representing the call or the error.</returns>
        public DynamicMetaObject Call(CallSignature signature, DynamicMetaObject errorSuggestion, OverloadResolverFactory resolverFactory, DynamicMetaObject target, params DynamicMetaObject[] args) {
            ContractUtils.RequiresNotNullItems(args, nameof(args));
            ContractUtils.RequiresNotNull(resolverFactory, nameof(resolverFactory));

            TargetInfo targetInfo = GetTargetInfo(target, args);

            if (targetInfo != null) {
                // we're calling a well-known MethodBase
                DynamicMetaObject res = MakeMetaMethodCall(signature, resolverFactory, targetInfo);
                if (res.Expression.Type.IsValueType) {
                    res = new DynamicMetaObject(
                        AstUtils.Convert(res.Expression, typeof(object)),
                        res.Restrictions
                    );
                }

                return res;
            }

            // we can't call this object
            return errorSuggestion ?? MakeCannotCallRule(target, target.GetLimitType());
        }
コード例 #30
0
ファイル: DefaultBinder.Operations.cs プロジェクト: zuvys/dlr
        public DynamicMetaObject GetIsCallable(DynamicMetaObject target)
        {
            // IsCallable() is tightly tied to Call actions. So in general, we need the call-action providers to also
            // provide IsCallable() status.
            // This is just a rough fallback. We could also attempt to simulate the default CallBinder logic to see
            // if there are any applicable calls targets, but that would be complex (the callbinder wants the argument list,
            // which we don't have here), and still not correct.
            BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType);

            bool callable = false;

            if (typeof(Delegate).IsAssignableFrom(target.LimitType) ||
                typeof(MethodGroup).IsAssignableFrom(target.LimitType))
            {
                callable = true;
            }

            return(new DynamicMetaObject(
                       AstUtils.Constant(callable),
                       restrictions
                       ));
        }