public static ExpressionNode Parse(ContextNode context, IAbstractSyntaxTree lexerNode, TypeReference expectedType = null)
        {
            Contract.Ensures(Contract.Result <ExpressionNode>() != null);
            ExpressionNode ret = null;

            switch (lexerNode.Type)
            {
            case Lexer.TokenType.FullSymbol:
            case Lexer.TokenType.Symbol:
                ret = DotOperatorNode.Parse(context, lexerNode);
                break;

            case Lexer.TokenType.LiteralNode:
                ret = LiteralNode.Parse(context, lexerNode);
                break;

            case Lexer.TokenType.Value:
                ret = ExpressionNode.Parse(context, lexerNode.Children[0], expectedType);
                break;

            case Lexer.TokenType.Function:
                ret = MethodNode.Parse(context, lexerNode);
                break;

            case Lexer.TokenType.InfixNode:
                ret = InfixParser.Parse(context, lexerNode);
                break;

            case Lexer.TokenType.PostfixNode:
            case Lexer.TokenType.PrefixNode:
                ret = UnaryOperators.Parse(context, lexerNode);
                break;

            case Lexer.TokenType.ParenthesesNode:
                ret = ExpressionNode.Parse(context, lexerNode.Children[1], expectedType);
                break;

            case Lexer.TokenType.ArrayLiteral:
                ret = ArrayCreationNode.Parse(context, lexerNode);
                break;

            case Lexer.TokenType.Null:
                ret = NullNode.Parse(context, lexerNode);
                break;

            default:
                ContractsHelper.AssumeUnreachable("Unknown expression type {0}", lexerNode.Type);
                break;
            }
            if (!(expectedType == null || expectedType.IsAuto()))
            {
                var ambiguous = ret as IAmbiguousNode;
                if (ambiguous != null)
                {
                    ret = ambiguous.RemoveAmbiguity(context, expectedType);
                }
            }

            return(ret);
        }
예제 #2
0
        private static ArrayCreationNode AsArrayCreation(ContextNode context, ExpressionNode array, IReadOnlyList <ExpressionNode> indices, SequencePoint point)
        {
            var type = array as TypeNode;

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

            return(ArrayCreationNode.Create(context, type.ParsedType, indices, null, point));
        }
        public static ArrayCreationNode Create(ContextNode context, TypeReference elementType, IReadOnlyList <ExpressionNode> dims, InitializerList initializer, SequencePoint point)
        {
            //rank 0 makes no sense
            Contract.Requires(dims == null || dims.Any());
            Contract.Requires(elementType != null || initializer != null);
            //dims are declared inside the type, both must be null or not null
            Contract.Requires((dims == null) == (elementType == null));
            //cant have [5,] or some shit
            Contract.Requires(dims == null || dims.All(d => d == null) || !dims.Any(d => d == null));
            Contract.Ensures(Contract.Result <ArrayCreationNode>() != null);

            var instance = new ArrayCreationNode(point);

            if (elementType == null)
            {
                if (initializer == null)
                {
                    ErrorCode.MissingArraySize.ReportAndThrow(point, "Cannot create array without size or an initializer");
                }
                if (initializer.ElementType.IsTypeless())
                {
                    ErrorCode.InferrenceFromTypeless.ReportAndThrow(initializer.SequencePoint, "Cannot infer array type from typeless expressions");
                }
                elementType         = initializer.ElementType;
                instance.IsImplicit = true;
                dims = CreateArrayDims(context, point, initializer.Dimensions.ToArray());
            }

            if (initializer != null && dims.Count() != initializer.Dimensions.Count())
            {
                ErrorCode.ArrayDimMismatch.ReportAndThrow(point,
                                                          "Cannot initialize array of {0} dimmensions with a matrix of {1} dimmensions",
                                                          dims.Count(), initializer.Dimensions.Count());
            }

            if (dims.Any(d => d == null))
            {
                if (initializer == null)
                {
                    ErrorCode.MissingArraySize.ReportAndThrow(point, "Cannot create array with implicit dimensions without initialization");
                }
                dims = CreateArrayDims(context, point, initializer.Dimensions.ToArray());
            }
            else
            {
                if (initializer != null && dims.Any(dim => !(dim is LiteralNode)))
                {
                    ErrorCode.NotLiteralArrayDims.ReportAndThrow(point,
                                                                 "When initializing arrays, dimensions must be literal, or implicit");
                }
            }

            foreach (var dim in dims)
            {
                if (!IsValidArrayDim(context.Parser, dim))
                {
                    ErrorCode.NotAnRValue.ReportAndThrow(dim.SequencePoint, "Array dimensions must be gettable integer expressions");
                }
            }

            if (initializer != null && !initializer.Initializers.Any())
            {
                initializer = null;
            }

            if (initializer != null)
            {
                if (!initializer.ElementType.IsAssignableTo(elementType))
                {
                    ErrorCode.TypeMismatch.ReportAndThrow(point,
                                                          "Cannot initializer array of element type {0} when initializer element type is {1}",
                                                          elementType.FullName, initializer.ElementType.FullName);
                }

                var numericDims = dims.Cast <LiteralNode>().Select(num => (int)num.Value).ToArray();

                for (int i = 0; i < dims.Count; i++)
                {
                    var value = numericDims[i];
                    if (value != initializer.Dimensions[i])
                    {
                        ErrorCode.ArrayDimMismatch.ReportAndThrow(point,
                                                                  "Dimension mismatch, array dimensions are [{0}] initializer are [{1}]",
                                                                  String.Join(", ", numericDims), String.Join(", ", initializer.Dimensions));
                    }
                }
            }
            instance.type            = AssemblyRegistry.GetArrayType(elementType, dims.Count);
            instance.dimensions      = dims;
            instance.InitializerList = initializer;
            return(instance);
        }