예제 #1
0
파일: CppTransform.cs 프로젝트: mortend/uno
        Method GetBoxedMethod(DataType dt, Method decl, Method impl)
        {
            if (dt.IsMasterDefinition)
            {
                var m = new Method(impl.Source, dt, impl.DocComment, Modifiers.Public | Modifiers.Generated, impl.Name + "_boxed",
                                   decl.ReturnType, decl.Parameters, new Scope(impl.Source));

                Variable ret = null;
                if (!impl.ReturnType.IsVoid && _backend.IsConstrained(impl))
                {
                    ret = new Variable(m.Source, m, dt.GetUniqueIdentifier("ret"), impl.ReturnType);
                    m.Body.Statements.Add(new VariableDeclaration(ret));
                }

                var args = new Expression[m.Parameters.Length];
                for (int i = 0; i < args.Length; i++)
                {
                    args[i] = new LoadArgument(m.Source, m, i);
                }

                m.Body.Statements.Add(
                    new Return(m.Source,
                               new CastOp(m.Source, m.ReturnType,
                                          new CallMethod(m.Source, new This(m.Source, dt).Address, impl, args, ret))));
                m.SetPrototype(impl);
                dt.Methods.Add(m);
                dt.InterfaceMethods[decl] = m;
                return(m);
            }

            foreach (var e in dt.MasterDefinition.InterfaceMethods)
            {
                if (e.Value.Modifiers != (Modifiers.Public | Modifiers.Generated) ||
                    e.Key.MasterDefinition != decl.MasterDefinition)
                {
                    continue;
                }

                var m = new Method(impl.Source, dt,
                                   e.Value.DocComment, e.Value.Modifiers, e.Value.Name,
                                   decl.ReturnType, decl.Parameters, e.Value.Body);
                m.SetMasterDefinition(e.Value);
                m.SetPrototype(impl);
                dt.Methods.Add(m);
                dt.InterfaceMethods[decl] = m;
                return(m);
            }

            Log.Error(impl.Source, ErrorCode.I0000, "C++: Boxed method master definition was not found.");
            return(impl);
        }
예제 #2
0
        public override void Begin(ref Expression e, ExpressionUsage u)
        {
            switch (e.ExpressionType)
            {
            case ExpressionType.Constant:
            {
                var str = e.ConstantValue as string;
                if (str != null)
                {
                    _type.StringConsts.Add((string)e.ConstantValue);
                }
                break;
            }

            case ExpressionType.LoadField:
            case ExpressionType.StoreField:
            {
                var s     = (FieldExpression)e;
                var field = s.Field;
                var obj   = s.Object;
                if (field.IsStatic)
                {
                    RegisterDependency(field.DeclaringType);
                }

                if (_backend.IsConstrained(field))
                {
                    if (!(obj is AddressOf && _backend.IsConstrained(obj.ReturnType) && obj.ActualValue.HasStorage()) &&
                        !(!field.IsStatic && field.DeclaringType.IsReferenceType))
                    {
                        RegisterType(field.DeclaringType);
                    }
                }
                else
                {
                    if (!_backend.IsTemplate(field.DeclaringType) && _backend.IsConstrained(field.MasterDefinition.ReturnType) ||
                        field.IsStatic && !field.DeclaringType.MasterDefinition.IsClosed)
                    {
                        RegisterType(field.IsStatic, field.DeclaringType);
                    }
                }
                break;
            }

            case ExpressionType.LoadArgument:
            {
                var s = (LoadArgument)e;
                if (!s.Parameter.IsReference && (
                        s.Parameter.Type.IsReferenceType ||
                        _flags.HasFlag(BodyFlags.ClassMember) ||
                        _backend.IsConstrained(s.Parameter.Type)))
                {
                    RegisterType(u == ExpressionUsage.VarArg && s.Parameter.IsReference &&
                                 _backend.IsConstrained(s.Parameter.Type),
                                 s.Parameter.Type);
                }
                break;
            }

            case ExpressionType.StoreArgument:
            {
                var s = (StoreArgument)e;
                if (s.Parameter.IsReference &&
                    _backend.IsConstrained(s.Parameter.Type) &&
                    !_flags.HasFlag(BodyFlags.ClassMember))
                {
                    RegisterType(s.Value is Default ||
                                 !s.Value.HasStorage(),
                                 s.Parameter.Type);
                }
                break;
            }

            case ExpressionType.Base:
                RegisterType(Function != null && Type.IsValueType, e.ReturnType);
                break;

            case ExpressionType.AllocObject:
                RegisterType(((AllocObject)e).ObjectType);
                break;

            case ExpressionType.NewObject:
                RegisterType(((NewObject)e).Constructor.DeclaringType);
                break;

            case ExpressionType.NewDelegate:
            {
                var s = (NewDelegate)e;
                RegisterType(s.ReturnType);
                RegisterInterface(s.Method);

                if (_backend.HasTypeParameter(s.Method))
                {
                    RegisterType(s.Method.GenericType ?? s.Method.DeclaringType);
                }
                break;
            }

            case ExpressionType.TypeOf:
                RegisterType(((TypeOf)e).TypeType);
                break;

            case ExpressionType.AddListener:
            case ExpressionType.RemoveListener:
            case ExpressionType.SetProperty:
            case ExpressionType.GetProperty:
            case ExpressionType.CallMethod:
            {
                var s    = (CallExpression)e;
                var func = s.Function;
                RegisterInterface(func);

                if (func.IsGenericMethod)
                {
                    RegisterType(func.GenericType);
                }
                else if (_backend.HasTypeParameter(func))
                {
                    RegisterType(func.DeclaringType);
                }

                if (func.IsStatic && !func.Prototype.IsConstructor)
                {
                    RegisterDependency(func.GenericType ?? func.DeclaringType);
                }
                break;
            }

            case ExpressionType.NewArray:
                RegisterType(((NewArray)e).ArrayType);
                break;

            case ExpressionType.CastOp:
                if (!e.ReturnType.IsInterface &&
                    ((CastOp)e).CastType == CastType.Down)
                {
                    RegisterType(e.ReturnType);
                }
                break;

            case ExpressionType.IsOp:
                RegisterType(((IsOp)e).TestType);
                break;

            case ExpressionType.AsOp:
                RegisterType(((AsOp)e).TestType);
                break;
            }
        }