예제 #1
0
        /// <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);
            }
        }
예제 #2
0
        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
            });
        }
예제 #3
0
        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();
        }
예제 #4
0
        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");
            }
        }
예제 #5
0
        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);
            }
        }
예제 #6
0
        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");
            }
        }