// 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) ); }
// 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 BuildMethodMissingCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { var globalScope = args.TargetClass.GlobalScope; var context = globalScope.Context; if (name.LastCharacter() == '=') { var normalizedArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 1, 1); if (!metaBuilder.Error) { var scopeVar = metaBuilder.GetTemporary(typeof(Scope), "#scope"); metaBuilder.AddInitialization( Ast.Assign(scopeVar, Methods.GetGlobalScopeFromScope.OpCall(AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope)))) ); var interopSetter = context.MetaBinderFactory.InteropSetMember(name.Substring(0, name.Length - 1)); metaBuilder.SetMetaResult( interopSetter.Bind( new DynamicMetaObject( scopeVar, BindingRestrictions.Empty, globalScope.Scope ), new[] { normalizedArgs[0] } ), true ); } } else { RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, 0); Expression errorExpr = metaBuilder.Error ? Ast.Throw(metaBuilder.Result, typeof(object)) : null; var scopeVar = metaBuilder.GetTemporary(typeof(Scope), "#scope"); var scopeLookupResultVar = metaBuilder.GetTemporary(typeof(object), "#result"); metaBuilder.AddInitialization( Ast.Assign(scopeVar, Methods.GetGlobalScopeFromScope.OpCall(AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope)))) ); Expression scopeLookupResultExpr = errorExpr ?? scopeLookupResultVar; Expression fallbackExp; if (name == "scope") { fallbackExp = errorExpr ?? args.TargetExpression; } else { // super(methodName, ...args...) - ignore argument error: args.InsertMethodName(name); fallbackExp = AstUtils.LightDynamic( context.MetaBinderFactory.Call(Symbols.MethodMissing, new RubyCallSignature( args.Signature.ArgumentCount + 1, args.Signature.Flags | RubyCallFlags.HasImplicitSelf | RubyCallFlags.IsSuperCall ) ), typeof(object), args.GetCallSiteArguments(args.TargetExpression) ); } var scopeLookup = Ast.NotEqual( Ast.Assign(scopeLookupResultVar, AstUtils.LightDynamic(RubyMetaBinderFactory.InteropTryGetMemberExact(name), typeof(object), scopeVar)), Expression.Constant(OperationFailed.Value) ); string unmanagled = RubyUtils.TryUnmangleMethodName(name); if (unmanagled != null) { scopeLookup = Ast.OrElse( scopeLookup, Ast.NotEqual( Ast.Assign(scopeLookupResultVar, AstUtils.LightDynamic(RubyMetaBinderFactory.InteropTryGetMemberExact(unmanagled), typeof(object), scopeVar)), Expression.Constant(OperationFailed.Value) ) ); } metaBuilder.Result = Ast.Condition( scopeLookup, scopeLookupResultExpr, fallbackExp ); } }
private static void BuildOverriddenInitializerCall(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, RubyMemberInfo/*!*/ initializer) { var instanceExpr = metaBuilder.Result; metaBuilder.Result = null; var instanceVariable = metaBuilder.GetTemporary(instanceExpr.Type, "#instance"); // We know an exact type of the new instance and that there is no singleton for that instance. // We also have the exact method we need to call ("initialize" is a RubyMethodInfo/RubyLambdaMethodInfo). // => no tests are necessary: args.SetTarget(instanceVariable, null); if (initializer is RubyMethodInfo || initializer is RubyLambdaMethodInfo) { initializer.BuildCallNoFlow(metaBuilder, args, Symbols.Initialize); } else { // TODO: we need more refactoring of RubyMethodGroupInfo.BuildCall to be able to inline this: metaBuilder.Result = AstUtils.LightDynamic( RubyCallAction.Make(args.RubyContext, "initialize", new RubyCallSignature( args.Signature.ArgumentCount, (args.Signature.Flags & ~RubyCallFlags.IsInteropCall) | RubyCallFlags.HasImplicitSelf ) ), args.GetCallSiteArguments(instanceVariable) ); } if (!metaBuilder.Error) { // PropagateRetrySingleton(instance = new <type>(), instance.initialize(<args>)) metaBuilder.Result = Methods.PropagateRetrySingleton.OpCall( Ast.Assign(instanceVariable, instanceExpr), metaBuilder.Result ); // we need to handle break, which unwinds to a proc-converter that could be this method's frame: if (args.Signature.HasBlock) { metaBuilder.ControlFlowBuilder = RubyMethodInfo.RuleControlFlowBuilder; } } }
internal override void BuildMethodMissingCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name) { var globalScope = args.TargetClass.GlobalScope; var context = globalScope.Context; if (name.LastCharacter() == '=') { var normalizedArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 1, 1); if (!metaBuilder.Error) { var scopeVar = metaBuilder.GetTemporary(typeof(Scope), "#scope"); metaBuilder.AddInitialization( Ast.Assign(scopeVar, Methods.GetGlobalScopeFromScope.OpCall(AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope)))) ); var interopSetter = context.MetaBinderFactory.InteropSetMember(name.Substring(0, name.Length - 1)); metaBuilder.SetMetaResult( interopSetter.Bind( new DynamicMetaObject( scopeVar, BindingRestrictions.Empty, globalScope.Scope ), new[] { normalizedArgs[0] } ), true ); } } else { RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, 0); Expression errorExpr = metaBuilder.Error ? Ast.Throw(metaBuilder.Result, typeof(object)) : null; var scopeVar = metaBuilder.GetTemporary(typeof(Scope), "#scope"); var scopeLookupResultVar = metaBuilder.GetTemporary(typeof(object), "#result"); metaBuilder.AddInitialization( Ast.Assign(scopeVar, Methods.GetGlobalScopeFromScope.OpCall(AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope)))) ); Expression scopeLookupResultExpr = errorExpr ?? scopeLookupResultVar; Expression fallbackExp; if (name == "scope") { fallbackExp = errorExpr ?? args.TargetExpression; } else { // super(methodName, ...args...) - ignore argument error: args.InsertMethodName(name); fallbackExp = AstUtils.LightDynamic( context.MetaBinderFactory.Call(Symbols.MethodMissing, new RubyCallSignature( args.Signature.ArgumentCount + 1, args.Signature.Flags | RubyCallFlags.HasImplicitSelf | RubyCallFlags.IsSuperCall ) ), typeof(object), args.GetCallSiteArguments(args.TargetExpression) ); } var scopeLookup = Ast.NotEqual( Ast.Assign(scopeLookupResultVar, AstUtils.LightDynamic(context.MetaBinderFactory.InteropTryGetMemberExact(name), typeof(object), scopeVar)), Expression.Constant(OperationFailed.Value) ); string unmanagled = RubyUtils.TryUnmangleMethodName(name); if (unmanagled != null) { scopeLookup = Ast.OrElse( scopeLookup, Ast.NotEqual( Ast.Assign(scopeLookupResultVar, AstUtils.LightDynamic(context.MetaBinderFactory.InteropTryGetMemberExact(unmanagled), typeof(object), scopeVar)), Expression.Constant(OperationFailed.Value) ) ); } metaBuilder.Result = Ast.Condition( scopeLookup, scopeLookupResultExpr, fallbackExp ); } }