示例#1
0
        protected override object?Visit(Expression.StructValue sval)
        {
            base.Visit(sval);
            // Check if it's even a struct type
            var instanceType = System.EvaluateType(sval.StructType);

            if (!(instanceType is Type.Struct structType))
            {
                // TODO
                throw new NotImplementedException("Can't instantiate non-struct!");
            }
            // Check if all fields are instantiated exactly once and with their proper type
            var remainingFields    = structType.Fields.ToDictionary(f => f.Key, f => f.Value);
            var alreadyInitialized = new Dictionary <string, IParseTreeElement?>();

            foreach (var field in sval.Fields)
            {
                if (!remainingFields.Remove(field.Name, out var declaredField))
                {
                    // Either already initialized, or unknown field
                    if (structType.Fields.ContainsKey(field.Name))
                    {
                        System.Report(new DoubleInitializationError(structType, field.Name)
                        {
                            TypeInitializer   = sval.StructType?.ParseTreeNode,
                            FirstInitialized  = alreadyInitialized[field.Name],
                            SecondInitialized = field.ParseTreeNode,
                        });
                    }
                    else
                    {
                        System.Report(new UnknownInitializedFieldError(structType, field.Name)
                        {
                            TypeInitializer      = sval.StructType?.ParseTreeNode,
                            UnknownInitialized   = field.ParseTreeNode,
                            SimilarExistingNames = remainingFields.Keys
                                                   .Where(n => StringMetrics.OptimalStringAlignmentDistance(n, field.Name) <= 2),
                        });
                    }
                }
                else
                {
                    // Types need to match
                    var assignedType = System.TypeOf(field.Value);
                    if (!assignedType.Equals(declaredField.Type.Value))
                    {
                        System.Report(new TypeMismatchError(declaredField.Type.Value, assignedType)
                        {
                            Context = "struct value initialization",
                            Defined = declaredField.Definition?.ParseTreeNode,
                            Wrong   = field.ParseTreeNode,
                        });
                    }
                    alreadyInitialized.Add(field.Name, field.ParseTreeNode);
                }
            }
            if (remainingFields.Count > 0)
            {
                System.Report(new MissingInitializationError(structType, remainingFields.Keys)
                {
                    TypeInitializer = sval.StructType?.ParseTreeNode,
                });
            }
            return(null);
        }
示例#2
0
        private Expression ParsePostfixExpression(ExprState state)
        {
            var result = ParseAtomicExpression(state);

            while (true)
            {
                var peek = Peek();
                if (PostfixOperators.Contains(peek.Type))
                {
                    var op = Next();
                    result = new Expression.Postfix(result, op);
                }
                else if (peek.Type == TokenType.OpenParen)
                {
                    var openParen = Expect(null, null, TokenType.OpenParen);
                    // Call expression
                    var args = new List <WithComma <Expression> >();
                    while (Peek().Type != TokenType.CloseParen)
                    {
                        var arg      = ParseExpression(ExprState.None);
                        var hasComma = Match(TokenType.Comma, out var comma);
                        args.Add(new WithComma <Expression>(arg, comma));
                        if (!hasComma)
                        {
                            break;
                        }
                    }
                    var closeParen = Expect("call expression", openParen, TokenType.CloseParen);
                    result = new Expression.Call(result, openParen, args, closeParen);
                }
                else if (peek.Type == TokenType.OpenBracket)
                {
                    var openBracket = Expect(null, null, TokenType.OpenBracket);
                    // Subscript expression
                    var index        = ParseExpression(ExprState.None);
                    var closeBracket = Expect("subscript expression", openBracket, TokenType.CloseBracket);
                    result = new Expression.Subscript(result, openBracket, index, closeBracket);
                }
                else if (!state.HasFlag(ExprState.TypeOnly) &&
                         !state.HasFlag(ExprState.NoBraced) &&
                         peek.Type == TokenType.OpenBrace)
                {
                    // Struct instantiation
                    var openBrace = Expect(null, null, TokenType.OpenBrace);
                    var fields    = new List <Expression.StructValue.Field>();
                    while (Peek().Type != TokenType.CloseBrace)
                    {
                        fields.Add(ParseStructValueField());
                    }
                    var closeBrace = Expect("struct instantiation", openBrace, TokenType.CloseBrace);
                    result = new Expression.StructValue(result, openBrace, fields, closeBrace);
                }
                else if (peek.Type == TokenType.Dot)
                {
                    // Dot path
                    var dot   = Expect(null, null, TokenType.Dot);
                    var ident = Expect("dot path expression", null, TokenType.Identifier);
                    result = new Expression.DotPath(result, dot, ident);
                }
                else
                {
                    break;
                }
            }
            return(result);
        }