Ejemplo n.º 1
0
        internal AbcMethod DefineMethod(Sig sig, AbcCoder coder, Action <AbcMethod> complete)
        {
            if (sig == null)
            {
                throw new ArgumentNullException("sig");
            }

            if (!sig.IsInitilizer && sig.Name == null)
            {
                throw new InvalidOperationException();
            }

            var klass = Class;

            if (klass == null)
            {
                throw new InvalidOperationException(string.Format("Class is not defined yet for Instance {0}", FullName));
            }

            AbcMultiname traitName = null;
            AbcTrait     trait;

            bool isStatic = (sig.Semantics & MethodSemantics.Static) != 0;
            var  traits   = isStatic ? klass.Traits : Traits;

            if (sig.IsInitilizer)
            {
                if (Initializer != null)
                {
                    throw new InvalidOperationException();
                }
            }
            else
            {
                traitName = Abc.DefineName(sig.Name);
                trait     = traits.Find(traitName, sig.Kind);
                if (trait != null)
                {
                    return(trait.Method);
                }
            }

            var method = new AbcMethod
            {
                Method = sig.Source
            };

            var generator = Abc.Generator;

            if (sig.Source != null)
            {
                generator.SetData(sig.Source, method);
            }

            AbcMethodBody body = null;

            if (sig.IsAbstract)
            {
                if (coder != null)
                {
                    throw new InvalidOperationException();
                }
            }
            else
            {
                body = new AbcMethodBody(method);
            }

            Abc.AddMethod(method);

            if (sig.IsInitilizer)
            {
                Initializer = method;
            }
            else
            {
                //for non initializer method we must define trait and return type
                method.ReturnType = BuildReturnType(sig.ReturnType, method);

                trait      = AbcTrait.CreateMethod(method, traitName);
                trait.Kind = sig.Kind;

                if (!isStatic)
                {
                    trait.IsVirtual  = (sig.Semantics & MethodSemantics.Virtual) != 0;
                    trait.IsOverride = (sig.Semantics & MethodSemantics.Override) != 0;
                }

                traits.Add(trait);
            }

            if (sig.Args != null)
            {
                if (sig.Args.Length == 1 && sig.Args[0] is IMethod)
                {
                    var m = (IMethod)sig.Args[0];
                    if (generator == null)
                    {
                        throw new InvalidOperationException();
                    }
                    generator.MethodBuilder.BuildParameters(method, m);
                }
                else
                {
                    Abc.AddParameters(method.Parameters, sig.Args);
                }
            }

            if (body != null && coder != null)
            {
                var code = new AbcCode(Abc);
                coder(code);
                body.Finish(code);
            }

            if (complete != null)
            {
                complete(method);
            }

            return(method);
        }