public static RuleGenerator /*!*/ Open() { return(new RuleGenerator((metaBuilder, args, name) => { var targetClass = (RubyClass)args.Target; targetClass.BuildObjectConstructionNoFlow(metaBuilder, args, name); // TODO: initialize yields the block? if (args.Signature.HasBlock) { // ignore flow builder set up so far, we need one that creates a BlockParam for library calls: metaBuilder.ControlFlowBuilder = null; if (metaBuilder.BfcVariable == null) { metaBuilder.BfcVariable = metaBuilder.GetTemporary(typeof(BlockParam), "#bfc"); } metaBuilder.Result = Ast.Call(new Func <UnaryOpStorage, BlockParam, object, object>(InvokeOpenBlock).Method, Ast.Constant(new UnaryOpStorage(args.RubyContext)), metaBuilder.BfcVariable, metaBuilder.Result ); RubyMethodGroupInfo.RuleControlFlowBuilder(metaBuilder, args); } else { metaBuilder.BuildControlFlow(args); } })); }
/// <summary> /// Implements Class#new feature. /// </summary> public void BuildObjectConstruction(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ methodName) { Debug.Assert(!IsSingletonClass, "Cannot instantiate singletons"); Type type = GetUnderlyingSystemType(); RubyMemberInfo initializer = ResolveMethod(Symbols.Initialize, true).InvalidateSitesOnOverride(); RubyMethodInfo overriddenInitializer = initializer as RubyMethodInfo; // check the version of this class to ensure the initializer won't be changed without rebuilding the site: metaBuilder.AddCondition( Ast.Equal(Ast.Property(Ast.Constant(this), RubyModule.VersionProperty), Ast.Constant(this.Version)) ); // Initializer is overridden => initializer is invoked on an uninitialized instance. // Is user class (defined in Ruby code) => construct it as if it had initializer that calls super immediately // (we need to "inherit" factories/constructors from the base class (e.g. class S < String; self; end.new('foo')). if (overriddenInitializer != null || (_isRubyClass && _structInfo == null)) { metaBuilder.Result = MakeAllocatorCall(args, () => Ast.Constant(Name)); if (overriddenInitializer != null || (_isRubyClass && initializer != null && !initializer.IsEmpty)) { BuildOverriddenInitializerCall(metaBuilder, args, initializer); } } else if (type.IsSubclassOf(typeof(Delegate))) { metaBuilder.Result = MakeDelegateConstructorCall(type, args); } else { MethodBase[] constructionOverloads; bool includeSelf; if (_structInfo != null) { constructionOverloads = new MethodBase[] { Methods.CreateStructInstance }; includeSelf = true; } else if (_factories != null) { constructionOverloads = (MethodBase[])ReflectionUtils.GetMethodInfos(_factories); includeSelf = true; } else { constructionOverloads = type.GetConstructors(); if (constructionOverloads.Length == 0) { throw RubyExceptions.CreateTypeError(String.Format("allocator undefined for {0}", Name)); } includeSelf = false; } RubyMethodGroupInfo.BuildCallNoFlow(metaBuilder, args, methodName, constructionOverloads, includeSelf, false); RubyMethodGroupInfo.ApplyBlockFlowHandlingInternal(metaBuilder, args); } }
private static RuleGenerator /*!*/ CreateSetter(int index) { return(delegate(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name) { var actualArgs = RubyMethodGroupInfo.MakeActualArgs(metaBuilder, args, true, false, false, false); metaBuilder.Result = Ast.Call( Ast.Convert(actualArgs[0], typeof(RubyStruct)), typeof(RubyStruct).GetMethod("SetValue"), Ast.Constant(index), Ast.Convert(actualArgs[1], typeof(object)) ); }); }
private bool TryGetClrMethod(Type /*!*/ type, BindingFlags bindingFlags, string /*!*/ name, out RubyMemberInfo method) { Assert.NotNull(type, name); MemberInfo[] members = type.GetMember(name, MemberTypes.Method, bindingFlags | BindingFlags.InvokeMethod); if (members.Length > 0) { method = new RubyMethodGroupInfo(SelectNonPrivateMethods(members), this, _isSingletonClass); return(true); } else { method = null; return(false); } }
public void OverloadResolution_Block() { var t = GetType(); var gse = new GlobalScopeExtension(Context, new Scope(), new object(), true); var scope = new RubyTopLevelScope(gse, null, new SymbolDictionary()); var proc = new Proc(ProcKind.Proc, null, scope, new BlockDispatcher0((x, y) => null, BlockSignatureAttributes.None)); var scopeArg = new MetaObject(Ast.Constant(proc.LocalScope), Restrictions.Empty, proc.LocalScope); var contextArg = new MetaObject(Ast.Constant(Context), Restrictions.Empty, Context); var instanceInt = new MetaObject(Ast.Constant(1), Restrictions.Empty, 1); var str = "foo"; var instanceStr = new MetaObject(Ast.Constant(str), Restrictions.Empty, str); var procArg = new MetaObject(Ast.Constant(proc), Restrictions.Empty, proc); var nullArg = new MetaObject(Ast.Constant(Ast.Constant(null)), Restrictions.Empty, null); var arguments = new[] { // 1.times new CallArguments(scopeArg, instanceInt, new MetaObject[0], RubyCallSignature.WithScope(0)), // 1.times &nil new CallArguments(scopeArg, instanceInt, new[] { nullArg }, RubyCallSignature.WithScopeAndBlock(0)), // 1.times &p new CallArguments(contextArg, instanceInt, new[] { procArg }, RubyCallSignature.WithBlock(0)), // obj.times &p new CallArguments(contextArg, instanceStr, new[] { procArg }, RubyCallSignature.WithBlock(0)), }; var results = new[] { "Times2", "Times1", "Times3", "Times4", }; for (int i = 0; i < arguments.Length; i++) { var bindingTarget = RubyMethodGroupInfo.ResolveOverload("times", new[] { t.GetMethod("Times1"), t.GetMethod("Times2"), t.GetMethod("Times3"), t.GetMethod("Times4"), }, arguments[i], true, false); Assert(bindingTarget.Success); Assert(bindingTarget.Method.Name == results[i]); } }
public void OverloadResolution_Block1() { var scope = Context.EmptyScope; var proc = new Proc(ProcKind.Proc, null, scope, new BlockDispatcher0(BlockSignatureAttributes.None, null, 0). SetMethod(new BlockCallTarget0((x, y) => null))); var arguments = new[] { // 1.times new CallArguments(Context, MO(scope), new[] { MO(1) }, RubyCallSignature.WithScope(0)), // 1.times &nil new CallArguments(Context, MO(scope), new[] { MO(1), MO(null) }, RubyCallSignature.WithScopeAndBlock(0)), // 1.times &p new CallArguments(Context, MO(1), new[] { MO(proc) }, RubyCallSignature.WithBlock(0)), // obj.times &p new CallArguments(Context, MO("foo"), new[] { MO(proc) }, RubyCallSignature.WithBlock(0)), }; var results = new[] { "Times2", "Times1", "Times3", "Times4", }; var metaBuilder = new MetaObjectBuilder(null); for (int i = 0; i < arguments.Length; i++) { RubyOverloadResolver resolver; var methods = GetStaticMethodsStartingWith(typeof(OverloadsWithBlock), "Times"); var bindingTarget = RubyMethodGroupInfo.ResolveOverload( metaBuilder, arguments[i], "times", methods, SelfCallConvention.SelfIsParameter, false, out resolver ); Assert(bindingTarget.Success); Assert(bindingTarget.Overload.Name == results[i]); } }