Beispiel #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);
        }
Beispiel #2
0
        private AbcMethod BuildCtorImpl(IMethod method, AbcInstance instance)
        {
            if (!method.IsConstructor)
            {
                return(null);
            }
            if (method.IsStatic)
            {
                return(null);
            }
            var type = method.DeclaringType;

            if (!type.IsArray)
            {
                return(null);
            }

            var ctor = new AbcMethod
            {
                ReturnType = Abc.BuiltinTypes.Void
            };

            _generator.MethodBuilder.BuildParameters(ctor, method);

            string name1 = "arrctor_" + type.GetSigName();
            var    name  = Abc.DefineName(QName.Global(name1));
            var    trait = AbcTrait.CreateMethod(ctor, name);

            instance.Traits.Add(trait);

            var body = new AbcMethodBody(ctor);

            Abc.AddMethod(ctor);

            var code = new AbcCode(Abc);

            code.PushThisScope();
            code.ConstructSuper();

            //check arguments
            int n = method.Parameters.Count;

            for (int i = 0; i < n; ++i)
            {
                code.GetLocal(i + 1);
                code.PushInt(0);
                var br            = code.If(BranchOperator.GreaterThanOrEqual);
                var exceptionType = _generator.Corlib.GetType(CorlibTypeId.ArgumentOutOfRangeException);
                code.ThrowException(exceptionType);
                br.BranchTarget = code.Label();
            }

            //m_rank = n
            code.LoadThis();
            code.PushInt(n);
            code.SetProperty(Const.Array.Rank);

            int varSize = n + 1;

            for (int i = 0; i < n; ++i)
            {
                code.GetLocal(i + 1);
            }
            for (int i = 1; i < n; ++i)
            {
                code.Add(InstructionCode.Multiply_i);
            }
            code.SetLocal(varSize);

            //init m_value
            code.LoadThis();
            code.CreateArrayVarSize(varSize);
            code.SetProperty(Const.Array.Value);

            //init m_lengths
            code.LoadThis();
            for (int i = 0; i < n; ++i)
            {
                code.GetLocal(i + 1);
            }
            code.Add(InstructionCode.Newarray, n);
            code.SetProperty(Const.Array.Lengths);

            int varDimArr = varSize + 1;

            //init m_dims
            code.CreateArray(n - 1);
            code.SetLocal(varDimArr);

            //1, n, n * (n-1), ..., n * (n-1) * ... * n0
            for (int i = n - 2; i >= 0; --i)
            {
                int leni = i + 2;
                code.GetLocal(varDimArr);
                code.PushInt(i);

                if (i != n - 2)
                {
                    code.GetLocal(varDimArr);
                    code.PushInt(i + 1);
                    code.GetNativeArrayItem();
                    code.CoerceInt32();                     //prev

                    code.GetLocal(leni);
                    code.Add(InstructionCode.Multiply_i);                     //prev * leni
                }
                else
                {
                    code.GetLocal(leni);
                }

                code.SetNativeArrayItem();
            }

            code.LoadThis();
            code.GetLocal(varDimArr);
            code.SetProperty(Const.Array.Dims);

            var elemType = type.GetElementType();

            InitFields(code, type, elemType, 0);

            if (InternalTypeExtensions.IsInitArray(elemType))
            {
                code.InitArray(elemType,
                               () =>
                {
                    code.LoadThis();
                    code.GetProperty(Const.Array.Value);
                }, varSize);
            }

            code.ReturnVoid();

            body.Finish(code);

            return(ctor);
        }