public void BuildObjectConstructionNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ methodName) { if (IsSingletonClass) { metaBuilder.SetError(Methods.MakeVirtualClassInstantiatedError.OpCall()); return; } Type type = GetUnderlyingSystemType(); RubyMemberInfo initializer; using (Context.ClassHierarchyLocker()) { // check version of the class so that we invalidate the rule whenever the initializer changes: metaBuilder.AddVersionTest(this); initializer = ResolveMethodForSiteNoLock(Symbols.Initialize, VisibilityContext.AllVisible).Info; // Initializer resolves to BasicObject#initialize unless overridden in a derived class. // We ensure that initializer cannot be removed/undefined so that we don't ever fall back to method_missing (see RubyModule.RemoveMethodNoEvent). Debug.Assert(initializer != null); } bool isLibraryMethod = initializer is RubyLibraryMethodInfo; bool isRubyInitializer = initializer.IsRubyMember && !isLibraryMethod; bool isLibraryInitializer = isLibraryMethod && !initializer.DeclaringModule.IsObjectClass && !initializer.DeclaringModule.IsBasicObjectClass; if (isRubyInitializer || isLibraryInitializer && _isRubyClass) { // allocate and initialize: bool allocatorFound = BuildAllocatorCall(metaBuilder, args, () => AstUtils.Constant(Name)); if (metaBuilder.Error) { return; } if (!allocatorFound) { metaBuilder.SetError(Methods.MakeMissingDefaultConstructorError.OpCall( Ast.Convert(args.TargetExpression, typeof(RubyClass)), Ast.Constant(initializer.DeclaringModule.Name) )); return; } if (!initializer.IsEmpty) { BuildOverriddenInitializerCall(metaBuilder, args, initializer); } } else { // construct: OverloadInfo[] constructionOverloads; SelfCallConvention callConvention = SelfCallConvention.SelfIsParameter; bool implicitProtocolConversions = false; if (typeof(Delegate).IsAssignableFrom(type)) { BuildDelegateConstructorCall(metaBuilder, args, type); return; } else if (type.IsArray && type.GetArrayRank() == 1) { constructionOverloads = GetClrVectorFactories(); } else if (_structInfo != null) { constructionOverloads = new OverloadInfo[] { new ReflectionOverloadInfo(Methods.CreateStructInstance) }; } else if (_factories.Length != 0) { constructionOverloads = ArrayUtils.ConvertAll(_factories, (d) => new ReflectionOverloadInfo(d.GetMethod())); } else { // TODO: handle protected constructors constructionOverloads = GetConstructors(type == typeof(object) ? typeof(RubyObject) : type).ToArray(); if (type.IsValueType()) { if (constructionOverloads.Length == 0 || GetConstructor(type) == null) { constructionOverloads = ArrayUtils.Append(constructionOverloads, new ReflectionOverloadInfo(Methods.CreateDefaultInstance)); } } else if (constructionOverloads.Length == 0) { metaBuilder.SetError(Methods.MakeAllocatorUndefinedError.OpCall(Ast.Convert(args.TargetExpression, typeof(RubyClass)))); return; } callConvention = SelfCallConvention.NoSelf; implicitProtocolConversions = true; } RubyMethodGroupInfo.BuildCallNoFlow(metaBuilder, args, methodName, constructionOverloads, callConvention, implicitProtocolConversions); if (!metaBuilder.Error) { metaBuilder.Result = MarkNewException(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 = RubyMethodGroupInfo.RuleControlFlowBuilder; } } } }
public void BuildObjectConstructionNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ methodName) { Debug.Assert(!IsSingletonClass, "Cannot instantiate singletons"); Type type = GetUnderlyingSystemType(); RubyMemberInfo initializer; using (Context.ClassHierarchyLocker()) { // check version of the class so that we invalidate the rule whenever the initializer changes: metaBuilder.AddVersionTest(this); initializer = ResolveMethodForSiteNoLock(Symbols.Initialize, IgnoreVisibility).Info; // Initializer resolves to Object#initializer unless overridden in a derived class. // We ensure that this method cannot be removed. Debug.Assert(initializer != null); } bool hasRubyInitializer = initializer is RubyMethodInfo; bool hasLibraryInitializer = !hasRubyInitializer && initializer.DeclaringModule != Context.ObjectClass; if (hasRubyInitializer || hasLibraryInitializer && _isRubyClass) { // allocate and initialize: bool allocatorFound = BuildAllocatorCall(metaBuilder, args, () => AstUtils.Constant(Name)); if (metaBuilder.Error) { return; } if (!allocatorFound) { metaBuilder.SetError(Methods.MakeMissingDefaultConstructorError.OpCall( Ast.Convert(args.TargetExpression, typeof(RubyClass)), Ast.Constant(initializer.DeclaringModule.Name) )); return; } if (!initializer.IsEmpty) { BuildOverriddenInitializerCall(metaBuilder, args, initializer); } } else { // construct: MethodBase[] constructionOverloads; SelfCallConvention callConvention = SelfCallConvention.SelfIsParameter; bool implicitProtocolConversions = false; if (typeof(Delegate).IsAssignableFrom(type)) { BuildDelegateConstructorCall(metaBuilder, args, type); return; } else if (type.IsArray && type.GetArrayRank() == 1) { constructionOverloads = ClrVectorFactories; } else if (_structInfo != null) { constructionOverloads = new MethodBase[] { Methods.CreateStructInstance }; } else if (_factories.Length != 0) { constructionOverloads = (MethodBase[])ReflectionUtils.GetMethodInfos(_factories); } else { // TODO: handle protected constructors constructionOverloads = (type == typeof(object) ? typeof(RubyObject) : type).GetConstructors(); if (type.IsValueType) { if (constructionOverloads.Length == 0 || type.GetConstructor(Type.EmptyTypes) == null) { constructionOverloads = ArrayUtils.Append(constructionOverloads, Methods.CreateDefaultInstance); } } else if (constructionOverloads.Length == 0) { metaBuilder.SetError(Methods.MakeAllocatorUndefinedError.OpCall(Ast.Convert(args.TargetExpression, typeof(RubyClass)))); return; } callConvention = SelfCallConvention.NoSelf; implicitProtocolConversions = true; } RubyMethodGroupInfo.BuildCallNoFlow(metaBuilder, args, methodName, constructionOverloads, callConvention, implicitProtocolConversions); // we need to handle break, which unwinds to a proc-converter that could be this method's frame: if (!metaBuilder.Error) { metaBuilder.ControlFlowBuilder = RubyMethodGroupInfo.RuleControlFlowBuilder; } } }