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