private DynamicMetaObject/*!*/ InteropBind(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) { // TODO: argument count limit depends on the binder! // TODO: pass block as the last (before RHS arg?) parameter/ignore block if args not accepting block: var normalizedArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, Int32.MaxValue); if (!metaBuilder.Error) { MethodInfo postConverter; var interopBinder = GetInteropBinder(args.RubyContext, normalizedArgs, out postConverter); if (interopBinder != null) { Type resultType; var result = interopBinder.Bind(args.MetaTarget, ArrayUtils.MakeArray(normalizedArgs)); metaBuilder.SetMetaResult(result, args); if (postConverter != null) { // TODO: do better? var paramType = postConverter.GetParameters()[0].ParameterType; metaBuilder.Result = Ast.Call(null, postConverter, AstUtils.Convert(metaBuilder.Result, paramType)); resultType = postConverter.ReturnType; } else { resultType = ((IInteropBinder)interopBinder).ResultType; } return metaBuilder.CreateMetaObject(interopBinder, resultType); } else { metaBuilder.SetError(Ast.New( typeof(NotSupportedException).GetConstructor(new[] { typeof(string) }), Ast.Constant(String.Format("{0} not supported on foreign meta-objects", this)) )); } } return metaBuilder.CreateMetaObject(this); }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { Expression instance = _fieldInfo.IsStatic ? null : Ast.Convert(args.TargetExpression, _fieldInfo.DeclaringType); if (_isSetter) { var actualArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 1, 1); if (!metaBuilder.Error) { metaBuilder.Result = Ast.Assign( Ast.Field(instance, _fieldInfo), Converter.ConvertExpression( actualArgs[0].Expression, _fieldInfo.FieldType, args.RubyContext, args.MetaContext.Expression, true ) ); } } else { RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, 0); if (!metaBuilder.Error) { if (_fieldInfo.IsLiteral) { // TODO: seems like Compiler should correctly handle the literal field case // (if you emit a read to a literal field, you get a NotSupportedExpception from // FieldHandle when we try to emit) metaBuilder.Result = AstUtils.Constant(_fieldInfo.GetValue(null)); } else { metaBuilder.Result = Ast.Field(instance, _fieldInfo); } } } }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { metaBuilder.Result = Methods.GetInstanceVariable.OpCall( args.ScopeExpression, AstFactory.Box(args.TargetExpression), AstUtils.Constant(InstanceVariableName) ); }
protected override bool Build(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, bool defaultFallback) { if (TryImplicitConversion(metaBuilder, args)) { metaBuilder.AddObjectTypeRestriction(args.Target, args.TargetExpression); return true; } // TODO: this is our meta object, should we add IRubyMetaConvertible interface instead of using interop-binder? if (args.Target is IDynamicMetaObjectProvider) { metaBuilder.SetMetaResult(args.MetaTarget.BindConvert(new InteropBinder.Convert(args.RubyContext, _type, true)), false); return true; } if (defaultFallback) { metaBuilder.AddObjectTypeRestriction(args.Target, args.TargetExpression); metaBuilder.SetError(Methods.MakeTypeConversionError.OpCall( args.MetaContext.Expression, AstUtils.Convert(args.TargetExpression, typeof(object)), Ast.Constant(_type) )); return true; } return false; }
public static DynamicMetaObject TryBind(RubyContext/*!*/ context, GetMemberBinder/*!*/ binder, DynamicMetaObject/*!*/ target) { Assert.NotNull(context, target); var metaBuilder = new MetaObjectBuilder(); var contextExpression = AstUtils.Constant(context); RubyClass targetClass = context.GetImmediateClassOf(target.Value); MethodResolutionResult method; RubyMemberInfo methodMissing = null; using (targetClass.Context.ClassHierarchyLocker()) { metaBuilder.AddTargetTypeTest(target.Value, targetClass, target.Expression, context, contextExpression); method = targetClass.ResolveMethodForSiteNoLock(binder.Name, RubyClass.IgnoreVisibility); if (method.Found) { methodMissing = targetClass.ResolveMethodForSiteNoLock(Symbols.MethodMissing, RubyClass.IgnoreVisibility).Info; } } if (method.Found) { // we need to create a bound member: metaBuilder.Result = AstUtils.Constant(new RubyMethod(target.Value, method.Info, binder.Name)); } else { // TODO: // We need to throw an exception if we don't find method_missing so that our version update optimization works: // This limits interop with other languages. // // class B CLR type with method 'foo' // class C < B Ruby class // x = C.new // // 1. x.GET("foo") from Ruby // No method found or CLR method found -> fallback to Python // Python might see its method foo or might just fallback to .NET, // in any case it will add rule [1] with restriction on type of C w/o Ruby version check. // 2. B.define_method("foo") // This doesn't update C due to the optimization (there is no overridden method foo in C). // 3. x.GET("foo") from Ruby // This will not invoke the binder since the rule [1] is still valid. // object symbol = SymbolTable.StringToId(binder.Name); RubyCallAction.BindToMethodMissing(metaBuilder, new CallArguments( new DynamicMetaObject(contextExpression, BindingRestrictions.Empty, context), new[] { target, new DynamicMetaObject(AstUtils.Constant(symbol), BindingRestrictions.Empty, symbol) }, RubyCallSignature.Simple(1) ), binder.Name, methodMissing, method.IncompatibleVisibility, false ); } // TODO: we should return null if we fail, we need to throw exception for now: return metaBuilder.CreateMetaObject(binder, DynamicMetaObject.EmptyMetaObjects); }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { Proc.BuildCall( metaBuilder, AstUtils.Constant(_lambda), // proc object args.TargetExpression, // self args ); }
internal RubyOverloadResolver(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, SelfCallConvention callConvention, bool implicitProtocolConversions) : base(args.RubyContext.Binder) { _args = args; _metaBuilder = metaBuilder; _callConvention = callConvention; _implicitProtocolConversions = implicitProtocolConversions; }
protected override bool Build(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, bool defaultFallback) { // TODO: this is our meta object, should we add IRubyMetaConvertible interface instead of using interop-binder? if (args.Target is IDynamicMetaObjectProvider) { metaBuilder.SetMetaResult(args.MetaTarget.BindConvert(new InteropBinder.Convert(args.RubyContext, _type, true)), false); return true; } return BuildConversion(metaBuilder, args.MetaTarget, args.MetaContext.Expression, _type, defaultFallback); }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { var visibleOverloads = GetVisibleOverloads(args, MethodBases, false); if (visibleOverloads.Count == 0) { metaBuilder.SetError(Methods.MakeClrProtectedMethodCalledError.OpCall( args.MetaContext.Expression, args.MetaTarget.Expression, Ast.Constant(name) )); } else { BuildCallNoFlow(metaBuilder, args, name, visibleOverloads, CallConvention, ImplicitProtocolConversions); } }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, 0); if (!metaBuilder.Error) { metaBuilder.Result = Methods.GetInstanceVariable.OpCall( AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope)), AstUtils.Box(args.TargetExpression), AstUtils.Constant(InstanceVariableName) ); } }
protected override bool Build(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, bool defaultFallback) { 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.MetaScope.Expression, typeof(RubyScope)), AstUtils.Constant(currentDeclaringModule), AstUtils.Constant(currentMethodName), targetExpression ) ); args.SetTarget(targetExpression, target); Debug.Assert(currentDeclaringModule != null); RubyMemberInfo method; RubyMemberInfo methodMissing = null; // we need to lock the hierarchy of the target class: var targetClass = scope.RubyContext.GetImmediateClassOf(target); using (targetClass.Context.ClassHierarchyLocker()) { // initialize all methods in ancestors: targetClass.InitializeMethodsNoLock(); // target is stored in a local, therefore it cannot be part of the restrictions: metaBuilder.TreatRestrictionsAsConditions = true; metaBuilder.AddTargetTypeTest(target, targetClass, targetExpression, args.MetaContext, new[] { Symbols.MethodMissing } // currentMethodName is resolved for super, which cannot be an instance singleton ); metaBuilder.TreatRestrictionsAsConditions = false; method = targetClass.ResolveSuperMethodNoLock(currentMethodName, currentDeclaringModule).InvalidateSitesOnOverride().Info; if (method == null) { // MRI: method_missing is called for the targetClass, not for the super: methodMissing = targetClass.ResolveMethodMissingForSite(currentMethodName, RubyMethodVisibility.None); } } if (method != null) { method.BuildSuperCall(metaBuilder, args, currentMethodName, currentDeclaringModule); } else { return RubyCallAction.BuildMethodMissingCall(metaBuilder, args, currentMethodName, methodMissing, RubyMethodVisibility.None, true, defaultFallback); } return true; }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { Debug.Assert(!args.Signature.HasBlock); Proc.SetProcCallRule( metaBuilder, Ast.Constant(_lambda), // proc object args.TargetExpression, // self Ast.Constant(this), // this method for super and class_eval args ); }
public override DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ scopeOrContextOrTarget, DynamicMetaObject/*!*/[]/*!*/ args) { var callArgs = new CallArguments(_context, scopeOrContextOrTarget, args, Signature); var metaBuilder = new MetaObjectBuilder(this, args); if (IsForeignMetaObject(callArgs.MetaTarget)) { return InteropBind(metaBuilder, callArgs); } Build(metaBuilder, callArgs, true); return metaBuilder.CreateMetaObject(this); }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { var actualArgs = RubyMethodGroupInfo.MakeActualArgs(metaBuilder, args, true, false, false, false); metaBuilder.Result = Methods.SetInstanceVariable.OpCall( AstFactory.Box(actualArgs[0]), AstFactory.Box(actualArgs[1]), args.ScopeExpression, AstUtils.Constant(InstanceVariableName) ); }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { var actualArgs = RubyMethodGroupInfo.NormalizeArguments(metaBuilder, args, SelfCallConvention.NoSelf, false, false); if (actualArgs.Length == 0) { metaBuilder.Result = Methods.GetInstanceVariable.OpCall( args.ScopeExpression, AstFactory.Box(args.TargetExpression), AstUtils.Constant(InstanceVariableName) ); } else { metaBuilder.SetWrongNumberOfArgumentsError(actualArgs.Length, 0); } }
public override DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ context, DynamicMetaObject/*!*/[]/*!*/ args) { var callArgs = new CallArguments(context, args, Signature); // TODO: COM interop if (IsForeignMetaObject(callArgs.MetaTarget)) { return InteropBind(callArgs); } var metaBuilder = new MetaObjectBuilder(); Build(metaBuilder, callArgs); return metaBuilder.CreateMetaObject(this); }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { if (args.Signature.HasBlock) { metaBuilder.Result = Methods.HookupEvent.OpCall( Ast.Convert(Ast.Constant(_eventInfo), typeof(EventInfo)), args.TargetExpression, Ast.Convert(args.GetBlockExpression(), typeof(Proc)) ); } else { // TODO: make error throw new NotImplementedError("no block given"); } }
public static DynamicMetaObject/*!*/ Bind(RubyContext/*!*/ context, InvokeBinder/*!*/ binder, RubyMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args, Action<MetaObjectBuilder, CallArguments>/*!*/ buildInvoke) { RubyCallSignature callSignature; if (RubyCallSignature.TryCreate(binder.CallInfo, out callSignature)) { return binder.FallbackInvoke(target, args); } var metaBuilder = new MetaObjectBuilder(); buildInvoke(metaBuilder, new CallArguments(target.CreateMetaContext(), target, args, callSignature)); return metaBuilder.CreateMetaObject(binder); }
internal void BuildInvoke(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) { Assert.NotNull(metaBuilder, args); Debug.Assert(args.Target == this); // TODO: we could compare infos here: // first argument must be this method: metaBuilder.AddRestriction(Ast.Equal(args.TargetExpression, AstUtils.Constant(this))); // set the target (becomes self in the called method): args.SetTarget(AstUtils.Constant(_target), _target); _info.BuildCall(metaBuilder, args, _name); }
// Only used if method_missing() is called directly on the main singleton. internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { var globalScope = args.TargetClass.GlobalScope; // TODO: this just calls super for now, so it doesn't look up the scope: metaBuilder.Result = AstUtils.LightDynamic( new RubyCallAction(globalScope.Context, Symbols.MethodMissing, new RubyCallSignature( args.Signature.ArgumentCount, args.Signature.Flags | RubyCallFlags.HasImplicitSelf | RubyCallFlags.IsSuperCall ) ), typeof(object), args.GetCallSiteArguments(args.TargetExpression) ); }
public override MetaObject/*!*/ BindInvoke(InvokeBinder/*!*/ action, MetaObject/*!*/[]/*!*/ args) { RubyCallSignature callSignature; if (RubyCallSignature.TryCreate(action.Arguments, out callSignature)) { return action.FallbackInvoke(this, args); } var context = new MetaObject( Methods.GetContextFromProc.OpCall(AstUtils.Convert(Expression, typeof(Proc))), Restrictions.Empty, RubyOps.GetContextFromProc((Proc)Value) ); var metaBuilder = new MetaObjectBuilder(); Proc.SetCallActionRule(metaBuilder, new CallArguments(context, this, args, callSignature), true); return metaBuilder.CreateMetaObject(action, args); }
// Only used if method_missing() is called directly on the main singleton. internal override void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name) { var globalScope = args.TargetClass.GlobalScope; // TODO: this just calls super for now, so it doesn't look up the scope: metaBuilder.Result = AstUtils.LightDynamic( new RubyCallAction(globalScope.Context, Symbols.MethodMissing, new RubyCallSignature( args.Signature.ArgumentCount, args.Signature.Flags | RubyCallFlags.HasImplicitSelf | RubyCallFlags.IsSuperCall ) ), typeof(object), args.GetCallSiteArguments(args.TargetExpression) ); }
internal override void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name) { if (args.Signature.HasBlock) { metaBuilder.Result = Methods.HookupEvent.OpCall( Ast.Convert(Ast.Constant(_eventInfo), typeof(EventInfo)), args.TargetExpression, Ast.Convert(args.GetBlockExpression(), typeof(Proc)) ); } else { // TODO: make error throw new NotImplementedError("no block given"); } }
internal override void BuildSuperCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name, RubyModule /*!*/ declaringModule) { Assert.NotNull(declaringModule, metaBuilder, args); var visibleOverloads = GetVisibleOverloads(args, MethodBases, true); if (visibleOverloads.Count == 0) { metaBuilder.SetError(Methods.MakeClrVirtualMethodCalledError.OpCall( args.MetaContext.Expression, args.MetaTarget.Expression, Ast.Constant(name) )); } else { BuildCallNoFlow(metaBuilder, args, name, visibleOverloads, CallConvention, ImplicitProtocolConversions); } }
public static DynamicMetaObject /*!*/ Bind(DynamicMetaObject /*!*/ context, GetIndexBinder /*!*/ binder, DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ indexes, Func <DynamicMetaObject, DynamicMetaObject[], DynamicMetaObject> /*!*/ fallback) { Debug.Assert(fallback != null); var callArgs = new CallArguments(context, target, indexes, RubyCallSignature.Interop(indexes.Length)); var metaBuilder = new MetaObjectBuilder(target, indexes); if (!RubyCallAction.BuildCall(metaBuilder, "[]", callArgs, false, false)) { metaBuilder.SetMetaResult(fallback(target, indexes), false); } return(metaBuilder.CreateMetaObject(binder)); }
public static DynamicMetaObject /*!*/ Bind(DynamicMetaObject /*!*/ context, SetMemberBinder /*!*/ binder, DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/ value, Func <DynamicMetaObject, DynamicMetaObject, DynamicMetaObject> /*!*/ fallback) { Debug.Assert(fallback != null); var args = new[] { value }; var callArgs = new CallArguments(context, target, args, RubyCallSignature.Interop(1)); var metaBuilder = new MetaObjectBuilder(target, args); if (!RubyCallAction.BuildCall(metaBuilder, binder.Name + "=", callArgs, false, false)) { metaBuilder.SetMetaResult(fallback(target, value), false); } return(metaBuilder.CreateMetaObject(binder)); }
public static DynamicMetaObject /*!*/ Bind(DynamicMetaObject /*!*/ context, GetMemberBinder /*!*/ binder, DynamicMetaObject /*!*/ target, Func <DynamicMetaObject, DynamicMetaObject> /*!*/ fallback) { Debug.Assert(fallback != null); var callArgs = new CallArguments(context, target, DynamicMetaObject.EmptyMetaObjects, RubyCallSignature.Interop(0)); var metaBuilder = new MetaObjectBuilder(target); if (!RubyCallAction.BuildAccess(metaBuilder, binder.Name, callArgs, false, false)) { // TODO: error suggestion? metaBuilder.SetMetaResult(fallback(target), false); } return(metaBuilder.CreateMetaObject(binder)); }
public static DynamicMetaObject /*!*/ Bind(DynamicMetaObject /*!*/ context, string /*!*/ methodName, CallInfo /*!*/ callInfo, DynamicMetaObjectBinder /*!*/ binder, DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args, Func <DynamicMetaObject, DynamicMetaObject[], DynamicMetaObject> /*!*/ fallback) { Debug.Assert(fallback != null); var callArgs = new CallArguments(context, target, args, RubyCallSignature.Interop(callInfo.ArgumentCount)); var metaBuilder = new MetaObjectBuilder(target, args); if (!RubyCallAction.BuildCall(metaBuilder, methodName, callArgs, false, false)) { // TODO: error suggestion? metaBuilder.SetMetaResult(fallback(target, args), false); } return(metaBuilder.CreateMetaObject(binder)); }
public static DynamicMetaObject /*!*/ Bind(InvokeBinder /*!*/ binder, RubyMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args, Action <MetaObjectBuilder, CallArguments> /*!*/ buildInvoke) { RubyCallSignature callSignature; if (RubyCallSignature.TryCreate(binder.CallInfo, out callSignature)) { return(binder.FallbackInvoke(target, args)); } var callArgs = new CallArguments(target.CreateMetaContext(), target, args, callSignature); var metaBuilder = new MetaObjectBuilder(target, args); buildInvoke(metaBuilder, callArgs); return(metaBuilder.CreateMetaObject(binder)); }
internal static MethodResolutionResult Resolve(MetaObjectBuilder /*!*/ metaBuilder, string /*!*/ methodName, CallArguments /*!*/ args, out RubyMemberInfo methodMissing) { MethodResolutionResult method; var targetClass = args.TargetClass; var visibilityContext = GetVisibilityContext(args.Signature, args.Scope); using (targetClass.Context.ClassHierarchyLocker()) { metaBuilder.AddTargetTypeTest(args.Target, targetClass, args.TargetExpression, args.MetaContext, new[] { methodName, Symbols.MethodMissing } ); if (args.Signature.IsSuperCall) { Debug.Assert(!args.Signature.IsVirtualCall && args.Signature.HasImplicitSelf); method = targetClass.ResolveSuperMethodNoLock(methodName, targetClass).InvalidateSitesOnOverride(); } else { var options = args.Signature.IsVirtualCall ? MethodLookup.Virtual : MethodLookup.Default; method = targetClass.ResolveMethodForSiteNoLock(methodName, visibilityContext, options); } if (!method.Found) { methodMissing = targetClass.ResolveMethodMissingForSite(methodName, method.IncompatibleVisibility); } else { methodMissing = null; } } // Whenever the current self's class changes we need to invalidate the rule, if a protected method is being called. if (method.Info != null && method.Info.IsProtected && visibilityContext.Class != null) { // We don't need to compare versions, just the class objects (super-class relationship cannot be changed). // Since we don't want to hold on a class object (to make it collectible) we compare references to the version handlers. metaBuilder.AddCondition(Ast.Equal( Methods.GetSelfClassVersionHandle.OpCall(AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope))), Ast.Constant(visibilityContext.Class.Version) )); } return(method); }
public static MetaObject TryBind(RubyContext/*!*/ context, GetMemberBinder/*!*/ binder, MetaObject/*!*/ target) { Assert.NotNull(context, target); var metaBuilder = new MetaObjectBuilder(); var contextExpression = Ast.Constant(context); metaBuilder.AddTargetTypeTest(target.Value, target.Expression, context, contextExpression); RubyMemberInfo method = context.ResolveMethod(target.Value, binder.Name, true).InvalidateSitesOnOverride(); if (method != null && RubyModule.IsMethodVisible(method, false)) { // we need to create a bound member: metaBuilder.Result = Ast.Constant(new RubyMethod(target.Value, method, binder.Name)); } else { // TODO: // We need to throw an exception if we don't find method_missing so that our version update optimization works: // This limits interop with other languages. // // class B CLR type with method 'foo' // class C < B Ruby class // x = C.new // // 1. x.GET("foo") from Ruby // No method found or CLR method found -> fallback to Python // Python might see its method foo or might just fallback to .NET, // in any case it will add rule [1] with restriction on type of C w/o Ruby version check. // 2. B.define_method("foo") // This doesn't update C due to the optimization (there is no overridden method foo in C). // 3. x.GET("foo") from Ruby // This will not invoke the binder since the rule [1] is still valid. // object symbol = SymbolTable.StringToId(binder.Name); RubyCallAction.BindToMethodMissing(metaBuilder, binder.Name, new CallArguments( new MetaObject(contextExpression, Restrictions.Empty, context), new[] { target, new MetaObject(Ast.Constant(symbol), Restrictions.Empty, symbol) }, RubyCallSignature.Simple(1) ), method != null ); } // TODO: we should return null if we fail, we need to throw exception for now: return metaBuilder.CreateMetaObject(binder, MetaObject.EmptyMetaObjects); }
public override DynamicMetaObject /*!*/ Bind(DynamicMetaObject /*!*/ scopeOrContextOrTargetOrArgArray, DynamicMetaObject /*!*/[] /*!*/ args) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Ruby: " + GetType().Name + Signature.ToString() + ": Bind"); var callArgs = new CallArguments(_context, scopeOrContextOrTargetOrArgArray, args, Signature); var metaBuilder = new MetaObjectBuilder(this, args); DynamicMetaObject interopBinding; if (IsForeignMetaObject(callArgs.MetaTarget) && (interopBinding = InteropBind(metaBuilder, callArgs)) != null) { return(interopBinding); } Build(metaBuilder, callArgs, true); return(metaBuilder.CreateMetaObject(this)); }
protected override bool TryImplicitConversion(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { if (args.Target == null) { metaBuilder.Result = Ast.Constant(null); return(true); } var convertedTarget = args.Target as TTargetType; if (convertedTarget != null) { metaBuilder.Result = AstUtils.Convert(args.TargetExpression, typeof(TTargetType)); return(true); } return(false); }
public static DynamicMetaObject TryBind(RubyContext/*!*/ context, InvokeMemberBinder/*!*/ binder, DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args) { Assert.NotNull(context, target); var metaBuilder = new MetaObjectBuilder(); RubyCallAction.Bind(metaBuilder, binder.Name, new CallArguments( new DynamicMetaObject(AstUtils.Constant(context), BindingRestrictions.Empty, context), target, args, RubyCallSignature.Simple(binder.CallInfo.ArgumentCount) ) ); // TODO: we should return null if we fail, we need to throw exception for now: return metaBuilder.CreateMetaObject(binder, DynamicMetaObject.EmptyMetaObjects); }
public static DynamicMetaObject TryBind(RubyContext/*!*/ context, CreateInstanceBinder/*!*/ binder, DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args) { Assert.NotNull(context, binder, target, args); var metaBuilder = new MetaObjectBuilder(); RubyCallAction.Bind(metaBuilder, "new", new CallArguments( new DynamicMetaObject(AstUtils.Constant(context), BindingRestrictions.Empty, context), target, args, RubyCallSignature.Simple(args.Length) ) ); // TODO: we should return null if we fail, we need to throw exception due to version update optimization: return metaBuilder.CreateMetaObject(binder, DynamicMetaObject.EmptyMetaObjects); }
public override DynamicMetaObject/*!*/ BindInvoke(InvokeBinder/*!*/ action, DynamicMetaObject/*!*/[]/*!*/ args) { RubyCallSignature callSignature; if (RubyCallSignature.TryCreate(action.Arguments, out callSignature)) { return action.FallbackInvoke(this, args); } var self = (RubyMethod)Value; var context = new DynamicMetaObject( Methods.GetContextFromMethod.OpCall(AstUtils.Convert(Expression, typeof(RubyMethod))), BindingRestrictions.Empty, RubyOps.GetContextFromMethod(self) ); var metaBuilder = new MetaObjectBuilder(); Method.SetRuleForCall(metaBuilder, new CallArguments(context, this, args, callSignature)); return metaBuilder.CreateMetaObject(action, args); }
public static MetaObject TryBind(RubyContext /*!*/ context, CreateInstanceBinder /*!*/ binder, MetaObject /*!*/ target, MetaObject /*!*/[] /*!*/ args) { Assert.NotNull(context, binder, target, args); var metaBuilder = new MetaObjectBuilder(); RubyCallAction.Bind(metaBuilder, "new", new CallArguments( new MetaObject(Ast.Constant(context), Restrictions.Empty, context), target, args, RubyCallSignature.Simple(args.Length) ) ); // TODO: we should return null if we fail, we need to throw exception due to version update optimization: return(metaBuilder.CreateMetaObject(binder, MetaObject.EmptyMetaObjects)); }
internal override void BuildSuperCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name, RubyModule /*!*/ declaringModule) { Assert.NotNull(declaringModule, metaBuilder, args); IList <MethodBase> methods; if (!declaringModule.IsSingletonClass) { Type associatedType = GetAssociatedSystemType(declaringModule); methods = GetStaticDispatchMethods(associatedType, name); } else { methods = MethodBases; } BuildCallNoFlow(metaBuilder, args, name, methods, !_isClrStatic, !_isRubyMethod); }
protected override bool TryImplicitConversion(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { object target = args.Target; if (args.Target == null) { metaBuilder.Result = Ast.Constant(false); return(true); } if (target is bool) { metaBuilder.Result = AstUtils.Convert(args.TargetExpression, typeof(bool)); return(true); } return(true); }
public static MetaObject TryBind(RubyContext /*!*/ context, InvokeMemberBinder /*!*/ binder, MetaObject /*!*/ target, MetaObject /*!*/[] /*!*/ args) { Assert.NotNull(context, target); var metaBuilder = new MetaObjectBuilder(); RubyCallAction.Bind(metaBuilder, binder.Name, new CallArguments( new MetaObject(Ast.Constant(context), Restrictions.Empty, context), target, args, RubyCallSignature.Simple(binder.Arguments.Count) ) ); // TODO: we should return null if we fail, we need to throw exception for now: return(metaBuilder.CreateMetaObject(binder, MetaObject.EmptyMetaObjects)); }
/// <summary> /// Takes current result and wraps it into try-filter(MethodUnwinder)-finally block that ensures correct "break" behavior for /// library method calls with block given in bfcVariable (BlockParam). /// </summary> public static void RuleControlFlowBuilder(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { if (metaBuilder.Error) { return; } var metaBlock = args.GetMetaBlock(); Debug.Assert(metaBlock != null, "RuleControlFlowBuilder should only be used if the signature has a block"); // We construct CF only for non-nil blocks thus we need a test for it: if (metaBlock.Value == null) { metaBuilder.AddRestriction(Ast.Equal(metaBlock.Expression, AstUtils.Constant(null))); return; } // don't need to test the exact type of the Proc since the code is subclass agnostic: metaBuilder.AddRestriction(Ast.NotEqual(metaBlock.Expression, AstUtils.Constant(null))); Expression bfcVariable = metaBuilder.BfcVariable; Debug.Assert(bfcVariable != null); // Method call with proc can invoke control flow that returns an arbitrary value from the call, so we need to type result to Object. // Otherwise, the result could only be result of targetExpression unless its return type is void. Expression resultVariable = metaBuilder.GetTemporary(typeof(object), "#result"); ParameterExpression unwinder; metaBuilder.Result = Ast.Block( Ast.Assign(bfcVariable, Methods.CreateBfcForLibraryMethod.OpCall(AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)))), AstUtils.Try( Ast.Assign(resultVariable, AstUtils.Convert(metaBuilder.Result, typeof(object))) ).Filter(unwinder = Ast.Parameter(typeof(MethodUnwinder), "#unwinder"), Methods.IsProcConverterTarget.OpCall(bfcVariable, unwinder), Ast.Assign(resultVariable, Ast.Field(unwinder, MethodUnwinder.ReturnValueField)), AstUtils.Default(typeof(object)) ).Finally( Methods.LeaveProcConverter.OpCall(bfcVariable) ), resultVariable ); }
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); } }
/// <summary> /// Resolves an library method overload and builds call expression. /// The resulting expression on meta-builder doesn't handle block control flow yet. /// </summary> internal static void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name, IList <OverloadInfo> /*!*/ overloads, SelfCallConvention callConvention, bool implicitProtocolConversions) { RubyOverloadResolver resolver; var bindingTarget = ResolveOverload(metaBuilder, args, name, overloads, callConvention, implicitProtocolConversions, out resolver); if (bindingTarget.Success) { // TODO: create a custom overload info: if (ReferenceEquals(bindingTarget.Overload.ReflectionInfo, Methods.CreateDefaultInstance)) { Debug.Assert(args.TargetClass.TypeTracker.Type.IsValueType); metaBuilder.Result = Ast.New(args.TargetClass.TypeTracker.Type); } else if (args.Signature.IsVirtualCall && bindingTarget.Overload.IsVirtual) { // Virtual methods that have been detached from the CLR type and // defined on the corresponding Ruby class or its subclass are not // directly invoked from a dynamic virtual call to prevent recursion. // Instead the base call is performed. // // Example: // class C < ArrayList // define_method(:Add, instance_method(:Add)) // end // // C.new.Add(1) // // C.new.Add dispatches to the virtual ArrayList::Add, which in turn dispatches to the auto-generated override C$1::Add. // That gets here since the defined method is a Ruby method (a detached CLR method group). If we called it directly // it would invoke the C$1::Add override again leading to a stack overflow. So we need to use a base call instead. metaBuilder.Result = Ast.Field(null, Fields.ForwardToBase); } else { metaBuilder.Result = bindingTarget.MakeExpression(); } } else { metaBuilder.SetError(resolver.MakeInvalidParametersError(bindingTarget).Expression); } }
/// <exception cref="MissingMethodException">The resolved method is Kernel#method_missing.</exception> internal static void Bind(MetaObjectBuilder /*!*/ metaBuilder, string /*!*/ methodName, CallArguments /*!*/ args) { metaBuilder.AddTargetTypeTest(args); RubyMemberInfo method = args.RubyContext.ResolveMethod(args.Target, methodName, true).InvalidateSitesOnOverride(); if (method != null && RubyModule.IsMethodVisible(method, args.Signature.HasImplicitSelf)) { method.BuildCall(metaBuilder, args, methodName); } else { // insert the method name argument into the args object symbol = SymbolTable.StringToId(methodName); args.InsertSimple(0, new MetaObject(Ast.Constant(symbol), Restrictions.Empty, symbol)); BindToMethodMissing(metaBuilder, methodName, args, method != null); } }
internal static void BuildConversion(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) { const string ToS = "to_s"; if (TryImplicitConversion(metaBuilder, args)) { metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression); return; } RubyMemberInfo conversionMethod, methodMissing = null; RubyClass targetClass = args.RubyContext.GetImmediateClassOf(args.Target); using (targetClass.Context.ClassHierarchyLocker()) { metaBuilder.AddTargetTypeTest(args.Target, targetClass, args.TargetExpression, args.MetaContext, new[] { ToS, Symbols.MethodMissing } ); conversionMethod = targetClass.ResolveMethodForSiteNoLock(ToS, VisibilityContext.AllVisible).Info; // find method_missing - we need to add "to_s" method to the missing methods table: if (conversionMethod == null) { methodMissing = targetClass.ResolveMethodMissingForSite(ToS, RubyMethodVisibility.None); } } // invoke target.to_s and if successful convert the result to string unless it is already: if (conversionMethod != null) { conversionMethod.BuildCall(metaBuilder, args, ToS); } else { RubyCallAction.BuildMethodMissingCall(metaBuilder, args, ToS, methodMissing, RubyMethodVisibility.None, false, true); } if (metaBuilder.Error) { return; } metaBuilder.Result = Methods.ToSDefaultConversion.OpCall( AstUtils.Convert(args.MetaContext.Expression, typeof(RubyContext)), AstUtils.Box(args.TargetExpression), AstUtils.Box(metaBuilder.Result) ); }
public static DynamicMetaObject /*!*/ Bind(DynamicMetaObject /*!*/ context, SetIndexBinder /*!*/ binder, DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ indexes, DynamicMetaObject /*!*/ value, Func <DynamicMetaObject, DynamicMetaObject[], DynamicMetaObject, DynamicMetaObject> /*!*/ fallback) { Debug.Assert(fallback != null); var args = ArrayUtils.Append(indexes, value); var callArgs = new CallArguments(context, target, args, new RubyCallSignature(indexes.Length, RubyCallFlags.IsInteropCall | RubyCallFlags.HasRhsArgument) ); var metaBuilder = new MetaObjectBuilder(target, args); if (!RubyCallAction.BuildCall(metaBuilder, "[]=", callArgs, false, false)) { metaBuilder.SetMetaResult(fallback(target, indexes, value), false); } return(metaBuilder.CreateMetaObject(binder)); }
public override DynamicMetaObject /*!*/ FallbackConvert(DynamicMetaObject /*!*/ target, DynamicMetaObject errorSuggestion) { #if !SILVERLIGHT DynamicMetaObject result; if (Microsoft.Scripting.ComInterop.ComBinder.TryConvert(this, target, out result)) { return(result); } #endif var metaBuilder = new MetaObjectBuilder(this, target, DynamicMetaObject.EmptyMetaObjects); if (!GenericConversionAction.BuildConversion(metaBuilder, target, Ast.Constant(_context), Type, errorSuggestion == null)) { Debug.Assert(errorSuggestion != null); // no conversion applicable so we didn't do any operation with arguments that would require restrictions converted to conditions: metaBuilder.SetMetaResult(errorSuggestion, false); } return(metaBuilder.CreateMetaObject(this)); }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { // TODO: splat, rhs, ... if (args.Signature.ArgumentCount == 0) { if (args.Signature.HasBlock) { metaBuilder.Result = Methods.HookupEvent.OpCall( AstUtils.Constant(this), args.TargetExpression, Ast.Convert(args.GetBlockExpression(), typeof(Proc)) ); } else { metaBuilder.Result = Methods.CreateEvent.OpCall( AstUtils.Constant(this), args.TargetExpression, AstUtils.Constant(name) ); } } else { metaBuilder.SetError(Methods.MakeWrongNumberOfArgumentsError.OpCall(Ast.Constant(args.Signature.ArgumentCount), Ast.Constant(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); }
protected override void Build(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) { const string ToS = "to_s"; // no conversion for a subclass of string: var stringTarget = args.Target as MutableString; if (stringTarget != null) { metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression); metaBuilder.Result = AstUtils.Convert(args.TargetExpression, typeof(MutableString)); return; } RubyMemberInfo conversionMethod, methodMissing = null; RubyClass targetClass = args.RubyContext.GetImmediateClassOf(args.Target); using (targetClass.Context.ClassHierarchyLocker()) { metaBuilder.AddTargetTypeTest(args.Target, targetClass, args.TargetExpression, args.MetaContext); conversionMethod = targetClass.ResolveMethodForSiteNoLock(ToS, RubyClass.IgnoreVisibility).Info; // find method_missing - we need to add "to_xxx" methods to the missing methods table: if (conversionMethod == null) { methodMissing = targetClass.ResolveMethodMissingForSite(ToS, RubyMethodVisibility.None); } } // invoke target.to_s and if successful convert the result to string unless it is already: if (conversionMethod != null) { conversionMethod.BuildCall(metaBuilder, args, ToS); if (metaBuilder.Error) { return; } } else { RubyCallAction.BindToMethodMissing(metaBuilder, args, ToS, methodMissing, RubyMethodVisibility.None, false, true); } metaBuilder.Result = Methods.ToSDefaultConversion.OpCall( AstUtils.Convert(args.MetaContext.Expression, typeof(RubyContext)), AstFactory.Box(args.TargetExpression), AstFactory.Box(metaBuilder.Result) ); }
internal static BindingTarget /*!*/ ResolveOverload(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name, IList <OverloadInfo> /*!*/ overloads, SelfCallConvention callConvention, bool implicitProtocolConversions, out RubyOverloadResolver /*!*/ resolver) { resolver = new RubyOverloadResolver(metaBuilder, args, callConvention, implicitProtocolConversions); var bindingTarget = resolver.ResolveOverload(name, overloads, NarrowingLevel.None, NarrowingLevel.All); bool calleeHasBlockParam = bindingTarget.Success && HasBlockParameter(bindingTarget.Overload); // At runtime the BlockParam is created with a new RFC instance that identifies the library method frame as // a proc-converter target of a method unwinder triggered by break from a block. if (args.Signature.HasBlock && calleeHasBlockParam) { metaBuilder.ControlFlowBuilder = RuleControlFlowBuilder; } // add restrictions used for overload resolution: resolver.AddArgumentRestrictions(metaBuilder, bindingTarget); return(bindingTarget); }
private void AddBlockArguments(MetaObjectBuilder/*!*/ rule, List<Expression>/*!*/ actualArgs, CallArguments/*!*/ args, int parameterIndex) { while (parameterIndex < args.Length) { switch (args.GetArgumentKind(parameterIndex)) { case ArgumentKind.Simple: actualArgs.Add(args.Expressions[parameterIndex]); break; case ArgumentKind.List: ArgsBuilder.SplatListToArguments(rule, actualArgs, args.Values[parameterIndex], args.Expressions[parameterIndex], false); break; case ArgumentKind.Instance: case ArgumentKind.Block: default: throw new NotImplementedException(); } parameterIndex++; } }
private DynamicMetaObject InteropBind(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { // TODO: argument count limit depends on the binder! // TODO: pass block as the last (before RHS arg?) parameter/ignore block if args not accepting block: var normalizedArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, Int32.MaxValue); if (!metaBuilder.Error) { MethodInfo postConverter; var interopBinder = GetInteropBinder(args.RubyContext, normalizedArgs, out postConverter); if (interopBinder != null) { Type resultType; var result = interopBinder.Bind(args.MetaTarget, ArrayUtils.MakeArray(normalizedArgs)); metaBuilder.SetMetaResult(result, args); if (postConverter != null) { // TODO: do better? var paramType = postConverter.GetParameters()[0].ParameterType; metaBuilder.Result = Ast.Call(null, postConverter, AstUtils.Convert(metaBuilder.Result, paramType)); resultType = postConverter.ReturnType; } else { resultType = interopBinder.ReturnType; } return(metaBuilder.CreateMetaObject(interopBinder, resultType)); } else { // interop protocol not supported for this binder -> ignore IDO and treat it as a CLR object: return(null); } } return(metaBuilder.CreateMetaObject(this)); }
internal override void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name) { Assert.NotNull(metaBuilder, args, name); // 2 implicit args: self, block var argsBuilder = new ArgsBuilder(2, Parameters.Mandatory.Length, Parameters.LeadingMandatoryCount, Parameters.Optional.Length, Parameters.Unsplat != null); argsBuilder.SetImplicit(0, AstUtils.Box(args.TargetExpression)); argsBuilder.SetImplicit(1, args.Signature.HasBlock ? AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)) : AstFactory.NullOfProc); argsBuilder.AddCallArguments(metaBuilder, args); if (metaBuilder.Error) { return; } // box explicit arguments: var boxedArguments = argsBuilder.GetArguments(); for (int i = 2; i < boxedArguments.Length; i++) { boxedArguments[i] = AstUtils.Box(boxedArguments[i]); } var method = GetDelegate(); if (method.GetType() == ParamsArrayDelegateType) { // Func<object, Proc, object[], object> metaBuilder.Result = AstFactory.CallDelegate(method, new[] { boxedArguments[0], boxedArguments[1], Ast.NewArrayInit(typeof(object), ArrayUtils.ShiftLeft(boxedArguments, 2)) }); } else { metaBuilder.Result = AstFactory.CallDelegate(method, boxedArguments); } }
internal override void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name) { Expression instance = _fieldInfo.IsStatic ? null : Ast.Convert(args.TargetExpression, _fieldInfo.DeclaringType); if (_isSetter) { var actualArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 1, 1); if (!metaBuilder.Error) { metaBuilder.Result = Ast.Assign( Ast.Field(instance, _fieldInfo), Converter.ConvertExpression( actualArgs[0].Expression, _fieldInfo.FieldType, args.RubyContext, args.MetaContext.Expression, true ) ); } } else { RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, 0); if (!metaBuilder.Error) { if (_fieldInfo.IsLiteral) { // TODO: seems like Compiler should correctly handle the literal field case // (if you emit a read to a literal field, you get a NotSupportedExpception from // FieldHandle when we try to emit) metaBuilder.Result = AstUtils.Constant(_fieldInfo.GetValue(null)); } else { metaBuilder.Result = Ast.Field(instance, _fieldInfo); } } } }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { Expression expr = null; Expression instance = _fieldInfo.IsStatic ? null : Ast.Convert(args.TargetExpression, _fieldInfo.DeclaringType); if (_isSetter) { // parameters should be: instance/type, value if (args.SimpleArgumentCount == 0 && args.Signature.HasRhsArgument) { expr = Ast.Assign( Ast.Field(instance, _fieldInfo), Converter.ConvertExpression( args.GetRhsArgumentExpression(), _fieldInfo.FieldType, args.RubyContext, args.MetaContext.Expression, true ) ); } } else { // parameter should be: instance/type if (args.SimpleArgumentCount == 0) { if (_fieldInfo.IsLiteral) { // TODO: seems like Compiler should correctly handle the literal field case // (if you emit a read to a literal field, you get a NotSupportedExpception from // FieldHandle when we try to emit) expr = AstUtils.Constant(_fieldInfo.GetValue(null)); } else { expr = Ast.Field(instance, _fieldInfo); } } } if (expr != null) { metaBuilder.Result = expr; } else { metaBuilder.SetError( Methods.MakeInvalidArgumentTypesError.OpCall(AstUtils.Constant(_isSetter ? name + "=" : name)) ); } }
public void AddCallArguments(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { // simple args: for (int i = 0; i < args.SimpleArgumentCount; i++) { Add(args.GetSimpleArgumentExpression(i)); } // splat arg: if (args.Signature.HasSplattedArgument) { AddSplatted(metaBuilder, args); } // rhs arg: if (args.Signature.HasRhsArgument) { Add(args.GetRhsArgumentExpression()); } if (HasTooFewArguments) { metaBuilder.SetWrongNumberOfArgumentsError(_explicitArgCount, _mandatoryParamCount); return; } if (HasTooManyArguments) { metaBuilder.SetWrongNumberOfArgumentsError(_explicitArgCount, _mandatoryParamCount); return; } // add optional placeholders: FillMissingArguments(); if (_hasUnsplatParameter) { AddUnsplat(); } }
internal static void BindToMethodMissing(MetaObjectBuilder /*!*/ metaBuilder, string /*!*/ methodName, CallArguments /*!*/ args, bool privateMethod) { // args already contain method name: var method = args.RubyContext.ResolveMethod(args.Target, Symbols.MethodMissing, true).InvalidateSitesOnOverride(); // TODO: better check for builtin method if (method == null || method.DeclaringModule == args.RubyContext.KernelModule && method is RubyMethodGroupInfo) { // throw an exception immediately, do not cache the rule: if (privateMethod) { throw RubyExceptions.CreatePrivateMethodCalled(args.RubyContext, args.Target, methodName); } else { throw RubyExceptions.CreateMethodMissing(args.RubyContext, args.Target, methodName); } } method.BuildCall(metaBuilder, args, methodName); }
public void AddSplatted(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { var arg = args.GetSplattedMetaArgument(); int listLength; ParameterExpression listVariable; metaBuilder.AddSplattedArgumentTest((IList)arg.Value, arg.Expression, out listLength, out listVariable); if (listLength > 0) { for (int i = 0; i < listLength; i++) { Add( Ast.Call( listVariable, typeof(IList).GetMethod("get_Item"), AstUtils.Constant(i) ) ); } } }
internal static bool BuildConversion(MetaObjectBuilder/*!*/ metaBuilder, DynamicMetaObject/*!*/ target, Expression/*!*/ contextExpression, Type/*!*/ toType, bool defaultFallback) { Expression expr = TryImplicitConversion(target, toType); if (expr != null) { metaBuilder.Result = expr; metaBuilder.AddObjectTypeRestriction(target.Value, target.Expression); return true; } if (defaultFallback) { metaBuilder.AddObjectTypeRestriction(target.Value, target.Expression); metaBuilder.SetError(Methods.MakeTypeConversionError.OpCall( contextExpression, AstUtils.Convert(target.Expression, typeof(object)), Ast.Constant(toType) )); return true; } return false; }