Пример #1
0
        public IOWrapper(RubyContext /*!*/ context, object io, bool canRead, bool canWrite, bool canSeek, bool canFlush, bool canBeClosed)
        {
            Assert.NotNull(context);

            _writeSite = CallSite <Func <CallSite, object, MutableString, object> > .Create(
                RubyCallAction.Make(context, "write", RubyCallSignature.WithImplicitSelf(1))
                );

            _readSite = CallSite <Func <CallSite, object, int, object> > .Create(
                RubyCallAction.Make(context, "read", RubyCallSignature.WithImplicitSelf(1))
                );

            _seekSite = CallSite <Func <CallSite, object, long, int, object> > .Create(
                RubyCallAction.Make(context, "seek", RubyCallSignature.WithImplicitSelf(2))
                );

            _tellSite = CallSite <Func <CallSite, object, object> > .Create(
                RubyCallAction.Make(context, "tell", RubyCallSignature.WithImplicitSelf(0))
                );

            _obj = io;

            _canRead     = canRead;
            _canWrite    = canWrite;
            _canSeek     = canSeek;
            _canFlush    = canFlush;
            _canBeClosed = canBeClosed;
            _buffer      = new byte[_bufferSize];
            _writePos    = 0;
            _readPos     = 0;
            _readLen     = 0;
        }
Пример #2
0
 // when [<expr>, ...] *<array>
 private static MSA.Expression /*!*/ MakeArrayTest(AstGenerator /*!*/ gen, MSA.Expression /*!*/ array, MSA.Expression value)
 {
     return(Methods.ExistsUnsplat.OpCall(
                Ast.Constant(CallSite <Func <CallSite, object, object, object> > .Create(
                                 RubyCallAction.Make(gen.Context, "===", RubyCallSignature.WithImplicitSelf(2))
                                 )),
                AstUtils.LightDynamic(ConvertToArraySplatAction.Make(gen.Context), array),
                AstUtils.Box(value)
                ));
 }
Пример #3
0
        public RubyConstructor(RubyGlobalScope /*!*/ scope, NodeProvider /*!*/ nodeProvider)
            : base(nodeProvider, scope)
        {
            _encoding = RubyEncoding.GetRubyEncoding(nodeProvider.Encoding);

            _newSite = CallSite <Func <CallSite, RubyModule, object, object, object, object> > .Create(
                RubyCallAction.Make(scope.Context, "new", RubyCallSignature.WithImplicitSelf(3))
                );

            _yamlInitializeSite = CallSite <Func <CallSite, object, object, Hash, object> > .Create(
                RubyCallAction.Make(scope.Context, "yaml_initialize", RubyCallSignature.WithImplicitSelf(3))
                );
        }
 private Expression /*!*/ ToA(CallArguments /*!*/ args, Expression /*!*/ targetClassNameConstant)
 {
     return
         // TODO(opt): We could optimize this a bit by merging the to_a call with the conversion.
         // We could also check if to_a is implemented on Kernel. If so it only wraps the item into an array
         // that the subsequent splatting operation unwraps. However this only applies when unpslatting non-splattable objects
         // that don't implement to_ary - probably a rare case.
         (Methods.ToArrayValidator.OpCall(
              targetClassNameConstant,
              AstUtils.LightDynamic(
                  RubyCallAction.Make(args.RubyContext, "to_a", RubyCallSignature.WithImplicitSelf(0)),
                  args.TargetExpression
                  )
              ));
 }
Пример #5
0
            internal RubyPropertyDescriptor(RubyContext /*!*/ context, string /*!*/ name, object testObject, Type /*!*/ componentType)
                : base(name, null)
            {
                _name          = name;
                _componentType = componentType;

                _getterSite = CallSite <Func <CallSite, object, object> > .Create(
                    RubyCallAction.Make(context, _name, RubyCallSignature.WithImplicitSelf(0))
                    );

                _setterSite = CallSite <Func <CallSite, object, object, object> > .Create(
                    RubyCallAction.Make(context, _name + "=", RubyCallSignature.WithImplicitSelf(0))
                    );

                try {
                    _propertyType = GetValue(testObject).GetType();
                } catch (Exception) {
                    _propertyType = typeof(object);
                }
            }
Пример #6
0
        internal static void BuildConversion(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, Type /*!*/ resultType,
                                             params ProtocolConversionAction /*!*/[] /*!*/ conversions)
        {
            Assert.NotNull(metaBuilder, args, conversions);
            Debug.Assert(args.SimpleArgumentCount == 0 && !args.Signature.HasBlock && !args.Signature.HasSplattedArgument && !args.Signature.HasRhsArgument);
            Debug.Assert(!args.Signature.HasScope);

            // implicit conversions should only depend on the static type:
            foreach (var conversion in conversions)
            {
                if (conversion.TryImplicitConversion(metaBuilder, args))
                {
                    metaBuilder.AddObjectTypeRestriction(args.Target, args.TargetExpression);

                    if (!metaBuilder.Error)
                    {
                        metaBuilder.Result = ConvertResult(metaBuilder.Result, resultType);
                    }
                    return;
                }
            }

            RubyClass                targetClass = args.RubyContext.GetImmediateClassOf(args.Target);
            Expression               targetClassNameConstant = AstUtils.Constant(targetClass.GetNonSingletonClass().Name, typeof(string));
            MethodResolutionResult   respondToMethod, methodMissing = MethodResolutionResult.NotFound;
            ProtocolConversionAction selectedConversion = null;
            RubyMemberInfo           conversionMethod   = null;

            using (targetClass.Context.ClassHierarchyLocker()) {
                // check for type version:
                metaBuilder.AddTargetTypeTest(args.Target, targetClass, args.TargetExpression, args.MetaContext,
                                              ArrayUtils.Insert(Symbols.RespondTo, Symbols.MethodMissing, ArrayUtils.ConvertAll(conversions, (c) => c.ToMethodName))
                                              );

                // we can optimize if Kernel#respond_to? method is not overridden:
                respondToMethod = targetClass.ResolveMethodForSiteNoLock(Symbols.RespondTo, VisibilityContext.AllVisible);
                if (respondToMethod.Found && respondToMethod.Info.DeclaringModule == targetClass.Context.KernelModule && respondToMethod.Info is RubyLibraryMethodInfo)   // TODO: better override detection
                {
                    respondToMethod = MethodResolutionResult.NotFound;

                    // get the first applicable conversion:
                    foreach (var conversion in conversions)
                    {
                        selectedConversion = conversion;
                        conversionMethod   = targetClass.ResolveMethodForSiteNoLock(conversion.ToMethodName, VisibilityContext.AllVisible).Info;
                        if (conversionMethod != null)
                        {
                            break;
                        }
                        else
                        {
                            // find method_missing - we need to add "to_xxx" methods to the missing methods table:
                            if (!methodMissing.Found)
                            {
                                methodMissing = targetClass.ResolveMethodNoLock(Symbols.MethodMissing, VisibilityContext.AllVisible);
                            }
                            methodMissing.InvalidateSitesOnMissingMethodAddition(conversion.ToMethodName, targetClass.Context);
                        }
                    }
                }
            }

            if (!respondToMethod.Found)
            {
                if (conversionMethod == null)
                {
                    // error:
                    selectedConversion.SetError(metaBuilder, args, targetClassNameConstant, resultType);
                    return;
                }
                else
                {
                    // invoke target.to_xxx() and validate it; returns an instance of TTargetType:
                    conversionMethod.BuildCall(metaBuilder, args, selectedConversion.ToMethodName);

                    if (!metaBuilder.Error)
                    {
                        metaBuilder.Result = ConvertResult(
                            selectedConversion.MakeValidatorCall(args, targetClassNameConstant, metaBuilder.Result),
                            resultType
                            );
                    }
                    return;
                }
            }

            // slow path: invoke respond_to?, to_xxx and result validation:
            for (int i = conversions.Length - 1; i >= 0; i--)
            {
                string toMethodName = conversions[i].ToMethodName;

                var conversionCallSite = AstUtils.LightDynamic(
                    RubyCallAction.Make(args.RubyContext, toMethodName, RubyCallSignature.WithImplicitSelf(0)),
                    args.TargetExpression
                    );

                metaBuilder.Result = Ast.Condition(
                    // If

                    // respond_to?()
                    Methods.IsTrue.OpCall(
                        AstUtils.LightDynamic(
                            RubyCallAction.Make(args.RubyContext, Symbols.RespondTo, RubyCallSignature.WithImplicitSelf(1)),
                            args.TargetExpression,
                            Ast.Constant(args.RubyContext.CreateSymbol(toMethodName, RubyEncoding.Binary))
                            )
                        ),

                    // Then

                    // to_xxx():
                    ConvertResult(
                        conversions[i].MakeValidatorCall(args, targetClassNameConstant, conversionCallSite),
                        resultType
                        ),

                    // Else

                    (i < conversions.Length - 1) ? metaBuilder.Result :
                    conversions[i].MakeErrorExpression(args, targetClassNameConstant, resultType)
                    );
            }
        }
Пример #7
0
 // friend: RubyContext
 internal EqualityComparer(RubyContext /*!*/ context)
     : this(
         CallSite <Func <CallSite, object, object> > .Create(RubyCallAction.Make(context, "hash", RubyCallSignature.WithImplicitSelf(0))),
         CallSite <Func <CallSite, object, object, object> > .Create(RubyCallAction.Make(context, "eql?", RubyCallSignature.WithImplicitSelf(1)))
         )
 {
 }
Пример #8
0
 // when <expr>
 //   generates into:
 //   RubyOps.IsTrue(<expr>) if the case has no value, otherise:
 //   RubyOps.IsTrue(Call("===", <expr>, <value>))
 private static MSA.Expression /*!*/ MakeTest(AstGenerator /*!*/ gen, Expression /*!*/ expr, MSA.Expression value)
 {
     MSA.Expression transformedExpr = expr.TransformRead(gen);
     if (expr is SplattedArgument)
     {
         if (value != null)
         {
             return(Methods.ExistsUnsplatCompare.OpCall(
                        Ast.Constant(CallSite <Func <CallSite, object, object, object> > .Create(
                                         RubyCallAction.Make(gen.Context, "===", RubyCallSignature.WithImplicitSelf(2))
                                         )),
                        AstUtils.LightDynamic(ExplicitTrySplatAction.Make(gen.Context), transformedExpr),
                        AstUtils.Box(value)
                        ));
         }
         else
         {
             return(Methods.ExistsUnsplat.OpCall(
                        AstUtils.LightDynamic(ExplicitTrySplatAction.Make(gen.Context), transformedExpr)
                        ));
         }
     }
     else
     {
         if (value != null)
         {
             return(AstFactory.IsTrue(
                        CallSiteBuilder.InvokeMethod(gen.Context, "===", RubyCallSignature.WithScope(1),
                                                     gen.CurrentScopeVariable,
                                                     transformedExpr,
                                                     value
                                                     )
                        ));
         }
         else
         {
             return(AstFactory.IsTrue(transformedExpr));
         }
     }
 }
Пример #9
0
 /// <summary>
 /// This is called by the IronRuby runtime to set the backtrace for an exception that has being raised.
 /// Note that the backtrace may be set directly by user code as well. However, that uses a different code path.
 /// </summary>
 private void DynamicSetBacktrace(RubyContext /*!*/ context, RubyArray backtrace)
 {
     if (_setBacktraceCallSite == null)
     {
         Interlocked.CompareExchange(ref _setBacktraceCallSite, CallSite <Func <CallSite, RubyContext, Exception, RubyArray, object> > .
                                     Create(RubyCallAction.MakeShared("set_backtrace", RubyCallSignature.WithImplicitSelf(1))), null);
     }
     _setBacktraceCallSite.Target(_setBacktraceCallSite, context, _exception, backtrace);
 }