/// <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); } }
internal static RubyArray GetSourceLocation(RubyMemberInfo /*!*/ info) { RubyMethodInfo rubyInfo = info as RubyMethodInfo; return((rubyInfo == null) ? null : new RubyArray(2) { rubyInfo.DeclaringModule.Context.EncodePath(rubyInfo.Document.FileName), rubyInfo.SourceSpan.Start.Line }); }
public static Proc /*!*/ ToProc(RubyContext /*!*/ context, RubyMethod /*!*/ self) { RubyMethodInfo mi = self.Info as RubyMethodInfo; if (mi != null) { return(Proc.Create(context, mi.Method, self.Target, mi.Arity)); } // TODO: figure out what the semantics should be for a set of CLR methods returned ... throw new NotImplementedException(); }
private static object ConstructPrivateObject(RubyConstructor /*!*/ ctor, string className, Node node) { MappingNode mapping = node as MappingNode; if (mapping == null) { throw new ConstructorException("can only construct private type from mapping node"); } RubyModule module; RubyGlobalScope globalScope = ctor.GlobalScope; if (globalScope.Context.TryGetModule(globalScope, className, out module)) { if (!module.IsClass) { throw new ConstructorException("Cannot construct module"); } Hash values = ctor.ConstructMapping(mapping); // TODO: call allocate here: object result = null; RubyMethodInfo method = module.GetMethod("yaml_initialize") as RubyMethodInfo; if (method != null) { result = RubyMarshal.Utils.CreateObjectAndSetIvars((RubyClass)module); ctor._yamlInitializeSite.Target(ctor._yamlInitializeSite, result, className, values); } else { var dict = new Dictionary <string, object>(values.Count); foreach (var kvp in EnumerateAttributes(globalScope.Context, values)) { dict.Add(kvp.Key, kvp.Value); } result = RubyMarshal.Utils.CreateObjectAndSetIvars((RubyClass)module, dict); } return(result); } else { //TODO: YAML::Object throw new NotImplementedError("YAML::Object is not implemented yet"); } }
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). // => no tests are necessary: args.SetTarget(instanceVariable, null); if (initializer is RubyMethodInfo) { initializer.BuildCall(metaBuilder, args, Symbols.Initialize); } else { // TODO: we need more refactoring of RubyMethodGroupInfo.BuildCall to be able to inline this: metaBuilder.Result = Ast.Dynamic( RubyCallAction.Make("initialize", new RubyCallSignature(args.Signature.ArgumentCount, args.Signature.Flags | RubyCallFlags.HasImplicitSelf) ), typeof(object), args.GetCallSiteArguments(instanceVariable) ); } if (!metaBuilder.Error) { // PropagateRetrySingleton(instance = new <type>(), instance.initialize(<args>)) metaBuilder.Result = Methods.PropagateRetrySingleton.OpCall( Ast.Assign(instanceVariable, instanceExpr), metaBuilder.Result ); RubyMethodInfo.ApplyBlockFlowHandlingInternal(metaBuilder, args); } }
public static object ConstructPrivateObject(IConstructor ctor, string className, Node node) { MappingNode mapping = node as MappingNode; if (mapping == null) { throw new ConstructorException("can only construct private type from mapping node"); } RubyModule module; RubyScope scope = ctor.Scope; if (scope.RubyContext.TryGetModule(scope.GlobalScope, className, out module)) { if (!module.IsClass) { throw new ConstructorException("Cannot construct module"); } Hash values = ctor.ConstructMapping(mapping); RubyMethodInfo method = (module.GetMethod("yaml_initialize") as RubyMethodInfo); if (method != null) { object result = RubyUtils.CreateObject((RubyClass)module); _YamlInitialize.Target(_YamlInitialize, scope.RubyContext, result, className, values); return(result); } else { return(RubyUtils.CreateObject((RubyClass)module, values, true)); } } else { //TODO: YAML::Object throw new NotImplementedError("YAML::Object is not implemented yet"); } }