Exemplo n.º 1
0
        public TypeInfo GetTypeInformation(TypeReference type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            TypeInfo result;
            var      typedef = TypeUtil.GetTypeDefinition(type);

            if (typedef == null)
            {
                return(null);
            }

            var identifier = new TypeIdentifier(typedef);

            if (TypeInformation.TryGet(identifier, out result))
            {
                return(result);
            }

            var fullName = type.FullName;

            var args = new MakeTypeInfoArgs();

            EnqueueType(args.TypesToInitialize, type);

            // We must construct type information in two passes, so that method group construction
            //  behaves correctly and ignores all the right methods.
            // The first pass walks all the way through the type graph (starting with the current type),
            //  ensuring we have type information for all the types in the graph. We do this iteratively
            //  to avoid overflowing the stack.
            // After we have type information for all the types in the graph, we then walk over all
            //  the types again, and construct their method groups, since we have the necessary
            //  information to determine which methods are ignored.
            while (args.TypesToInitialize.Count > 0)
            {
                var kvp = args.TypesToInitialize.First;
                args.TypesToInitialize.Remove(kvp.Key);

                args.Definition = kvp.Value;
                TypeInformation.TryCreate(
                    kvp.Key, args, MakeTypeInfo
                    );
            }

            foreach (var ti in args.SecondPass.Values)
            {
                ti.Initialize();
                ti.ConstructMethodGroups();
            }

            if (!TypeInformation.TryGet(identifier, out result))
            {
                return(null);
            }
            else
            {
                return(result);
            }
        }
Exemplo n.º 2
0
        protected TypeInfo ConstructTypeInformation(TypeIdentifier identifier, TypeDefinition type, Dictionary <TypeIdentifier, TypeDefinition> moreTypes)
        {
            var moduleInfo = GetModuleInformation(type.Module);

            TypeInfo baseType = null, declaringType = null;

            if (type.BaseType != null)
            {
                baseType = GetExisting(type.BaseType);
                if (baseType == null)
                {
                    throw new InvalidOperationException(String.Format(
                                                            "Missing type info for base type '{0}' of type '{1}'",
                                                            type.BaseType, type
                                                            ));
                }
            }

            if (type.DeclaringType != null)
            {
                declaringType = GetExisting(type.DeclaringType);
                if (declaringType == null)
                {
                    throw new InvalidOperationException(String.Format(
                                                            "Missing type info for declaring type '{0}' of type '{1}'",
                                                            type.DeclaringType, type
                                                            ));
                }
            }

            var result = new TypeInfo(this, moduleInfo, type, declaringType, baseType, identifier);

            Action <TypeReference> addType = (tr) => {
                if (tr == null)
                {
                    return;
                }

                var td = TypeUtil.GetTypeDefinition(tr);
                if (td == null)
                {
                    return;
                }

                var _identifier = new TypeIdentifier(td);
                if (_identifier.Equals(identifier))
                {
                    return;
                }
                else if (moreTypes.ContainsKey(_identifier))
                {
                    return;
                }

                moreTypes[_identifier] = td;
            };

            foreach (var member in result.Members.Values)
            {
                addType(member.ReturnType);

                var method = member as Internal.MethodInfo;
                if (method != null)
                {
                    foreach (var p in method.Member.Parameters)
                    {
                        addType(p.ParameterType);
                    }
                }
            }

            return(result);
        }
Exemplo n.º 3
0
        public void VisitNode(JSBinaryOperatorExpression bop)
        {
            bool parens = true;
            bool needsTruncation = false, needsCast = false;

            if (ParentNode is JSIfStatement)
            {
                parens = false;
            }
            else if ((ParentNode is JSWhileLoop) && ((JSWhileLoop)ParentNode).Condition == bop)
            {
                parens = false;
            }
            else if ((ParentNode is JSDoLoop) && ((JSDoLoop)ParentNode).Condition == bop)
            {
                parens = false;
            }
            else if (ParentNode is JSForLoop)
            {
                var fl = (JSForLoop)ParentNode;
                if (
                    (fl.Condition == bop) ||
                    (fl.Increment.SelfAndChildrenRecursive.Any((n) => bop.Equals(n))) ||
                    (fl.Initializer.SelfAndChildrenRecursive.Any((n) => bop.Equals(n)))
                    )
                {
                    parens = false;
                }
            }
            else if ((ParentNode is JSSwitchStatement) && ((JSSwitchStatement)ParentNode).Condition == bop)
            {
                parens = false;
            }
            else if (
                (ParentNode is JSBinaryOperatorExpression) &&
                ((JSBinaryOperatorExpression)ParentNode).Operator == bop.Operator &&
                bop.Operator is JSLogicalOperator
                )
            {
                parens = false;
            }
            else if (ParentNode is JSVariableDeclarationStatement)
            {
                parens = false;
            }
            else if (ParentNode is JSExpressionStatement)
            {
                parens = false;
            }

            var leftType   = bop.Left.GetActualType(TypeSystem);
            var rightType  = bop.Right.GetActualType(TypeSystem);
            var resultType = bop.GetActualType(TypeSystem);

            // We need to perform manual truncation to maintain the semantics of C#'s division operator
            if ((bop.Operator == JSOperator.Divide))
            {
                needsTruncation =
                    (TypeUtil.IsIntegral(leftType) ||
                     TypeUtil.IsIntegral(rightType)) &&
                    TypeUtil.IsIntegral(resultType);
            }

            // Arithmetic on enum types needs a cast at the end.
            if (bop.Operator is JSArithmeticOperator)
            {
                if (TypeUtil.IsEnum(TypeUtil.StripNullable(resultType)))
                {
                    needsCast = true;
                }
            }

            if (needsTruncation)
            {
                if (bop.Operator is JSAssignmentOperator)
                {
                    throw new NotImplementedException("Truncation of assignment operations not implemented");
                }

                Output.WriteRaw("Math.floor");
            }
            else if (needsCast)
            {
                Output.WriteRaw("JSIL.Cast");
            }

            parens |= needsTruncation;
            parens |= needsCast;

            if (parens)
            {
                Output.LPar();
            }

            Visit(bop.Left);
            Output.Space();
            Output.WriteRaw(bop.Operator.Token);
            Output.Space();

            if (
                (bop.Operator is JSLogicalOperator) &&
                (Stack.OfType <JSBinaryOperatorExpression>().Skip(1).FirstOrDefault() != null)
                )
            {
                Output.NewLine();
            }

            Visit(bop.Right);

            if (needsCast)
            {
                Output.Comma();
                Output.Identifier(TypeUtil.StripNullable(resultType), ReferenceContext);
            }

            if (parens)
            {
                Output.RPar();
            }
        }