예제 #1
0
        private static bool CheckField(
            Core.Session session, int structIndex, int fieldIndex,
            Core.Type innerType, Stack <int> seenStructs)
        {
            var fieldStruct = innerType as Core.TypeStruct;

            if (fieldStruct == null)
            {
                return(false);
            }

            var st = session.GetStruct(structIndex);

            Core.Name fieldName;
            st.fieldNames.FindByValue(fieldIndex, out fieldName);

            session.PushContext(
                "in struct '" + session.GetStructName(structIndex).GetString() + "', " +
                "field '" + fieldName.GetString() + "'",
                st.GetFieldNameSpan(fieldIndex));

            var err = false;

            if (seenStructs.Contains(fieldStruct.structIndex))
            {
                err = true;
                session.AddMessage(
                    Diagnostics.MessageKind.Error,
                    Diagnostics.MessageCode.StructRecursion,
                    "struct recursion",
                    session.GetStruct(fieldStruct.structIndex).GetNameSpan(),
                    st.GetFieldNameSpan(fieldIndex));
            }

            if (!err)
            {
                CheckStruct(session, fieldStruct.structIndex, seenStructs);
            }

            session.PopContext();
            return(err);
        }
예제 #2
0
        public static bool ValidateDataAccess(
            Core.Session session,
            Core.DeclFunct funct,
            Core.DataAccess access)
        {
            var regDeref = access as Core.DataAccessDereference;

            if (regDeref != null)
            {
                var innerType = GetDataAccessType(session, funct, regDeref.innerAccess);
                var innerPtr  = innerType as Core.TypePointer;
                if (innerPtr == null)
                {
                    session.AddMessage(
                        Diagnostics.MessageKind.Error,
                        Diagnostics.MessageCode.CannotDereferenceType,
                        "dereferencing '" + innerType.GetString(session) + "'",
                        access.span);
                    return(false);
                }
            }
            return(true);
        }
예제 #3
0
        public static Core.Type ResolveStruct(
            Core.Session session,
            Grammar.ASTNodeExprName nameNode,
            IList <Core.UseDirective> useDirectives,
            bool mustBeResolved)
        {
            var nameConcreteNode = nameNode as Grammar.ASTNodeExprNameConcrete;

            if (nameConcreteNode == null)
            {
                if (mustBeResolved)
                {
                    session.AddMessage(
                        Diagnostics.MessageKind.Error,
                        Diagnostics.MessageCode.Expected,
                        "type must be known",
                        nameNode.GetSpan());
                }

                return(new Core.TypeError());
            }

            return(ResolveStruct(session, nameConcreteNode.name, useDirectives, mustBeResolved));
        }
예제 #4
0
        private void ResolveExprLiteralStruct(Grammar.ASTNodeExprLiteralStruct exprLiteralStruct, ref int curSegment, Core.DataAccess output)
        {
            var type = TypeResolver.ResolveStruct(session, exprLiteralStruct.name, useDirectives, true);

            if (!type.IsResolved())
            {
                return;
            }

            var typeStruct     = type as Core.TypeStruct;
            var fieldNum       = TypeResolver.GetFieldNum(this.session, typeStruct);
            var fieldDestSpans = new Diagnostics.Span?[fieldNum];

            var fieldRegs = new int[fieldNum];

            for (var i = 0; i < fieldNum; i++)
            {
                fieldRegs[i] = funct.CreateRegister(
                    TypeResolver.GetFieldType(this.session, typeStruct, i), false);
            }

            var fieldRegAccesses = new Core.DataAccess[fieldNum];

            for (var i = 0; i < fieldNum; i++)
            {
                fieldRegAccesses[i] =
                    Core.DataAccessRegister.ForRegister(exprLiteralStruct.name.GetSpan(), fieldRegs[i]);
            }

            foreach (var fieldInit in exprLiteralStruct.fields)
            {
                var name = NameResolver.Resolve(fieldInit.name);

                int fieldIndex;
                if (!this.session.GetStruct(typeStruct.structIndex).fieldNames.FindByName(name, out fieldIndex))
                {
                    this.foundErrors = true;
                    session.AddMessage(
                        Diagnostics.MessageKind.Error,
                        Diagnostics.MessageCode.Unknown,
                        "unknown field '" + name.GetString() + "' in '" +
                        type.GetString(this.session) + "'",
                        fieldInit.name.GetSpan());
                    continue;
                }

                if (fieldDestSpans[fieldIndex].HasValue)
                {
                    this.foundErrors = true;
                    session.AddMessage(
                        Diagnostics.MessageKind.Error,
                        Diagnostics.MessageCode.Unknown,
                        "duplicate field '" + name.GetString() + "' initialization",
                        fieldInit.name.GetSpan(),
                        fieldDestSpans[fieldIndex].Value);
                    continue;
                }

                fieldRegAccesses[fieldIndex].span = fieldInit.name.GetSpan();
                fieldDestSpans[fieldIndex]        = fieldInit.name.GetSpan();
                this.ResolveExpr(fieldInit.expr, ref curSegment, fieldRegAccesses[fieldIndex]);
            }

            var missingFields = new List <int>();

            for (var i = 0; i < fieldNum; i++)
            {
                if (!fieldDestSpans[i].HasValue)
                {
                    missingFields.Add(i);
                }
            }

            if (missingFields.Count > 0)
            {
                Core.Name fieldName;
                session.GetStruct(typeStruct.structIndex).fieldNames.FindByValue(missingFields[0], out fieldName);

                this.foundErrors = true;
                session.AddMessage(
                    Diagnostics.MessageKind.Error,
                    Diagnostics.MessageCode.Unknown,
                    "missing initializer" + (missingFields.Count > 1 ? "s" : "") +
                    " for field '" + fieldName.GetString() + "'" +
                    (missingFields.Count > 1 ? " and other " + (missingFields.Count - 1) : ""),
                    exprLiteralStruct.GetSpan());
            }
            else
            {
                var finalFieldDestSpans = new Diagnostics.Span[fieldNum];
                for (var i = 0; i < fieldNum; i++)
                {
                    finalFieldDestSpans[i] = fieldDestSpans[i].Value;
                }

                funct.AddInstruction(curSegment, Core.InstructionMoveLiteralStruct.Of(
                                         exprLiteralStruct.GetSpan(), output,
                                         typeStruct.structIndex, fieldRegAccesses, finalFieldDestSpans));
            }
        }
예제 #5
0
        public static Core.Type Resolve(
            Core.Session session,
            Grammar.ASTNodeType typeNode,
            IList <Core.UseDirective> useDirectives,
            bool mustBeResolved)
        {
            var typePlaceholderNode = typeNode as Grammar.ASTNodeTypePlaceholder;

            if (typePlaceholderNode != null)
            {
                if (mustBeResolved)
                {
                    session.AddMessage(
                        Diagnostics.MessageKind.Error,
                        Diagnostics.MessageCode.Expected,
                        "type must be known",
                        typeNode.GetSpan());
                    return(new Core.TypeError());
                }

                return(new Core.TypePlaceholder());
            }

            var typeStructNode = typeNode as Grammar.ASTNodeTypeStruct;

            if (typeStructNode != null)
            {
                return(ResolveStruct(session, typeStructNode.name, useDirectives, mustBeResolved));
            }

            var typeTupleNode = typeNode as Grammar.ASTNodeTypeTuple;

            if (typeTupleNode != null)
            {
                var elementTypes = new Core.Type[typeTupleNode.elements.Count];
                for (var i = 0; i < typeTupleNode.elements.Count; i++)
                {
                    elementTypes[i] = Resolve(session, typeTupleNode.elements[i], useDirectives, mustBeResolved);
                }

                return(Core.TypeTuple.Of(elementTypes));
            }

            var typeFunctNode = typeNode as Grammar.ASTNodeTypeFunct;

            if (typeFunctNode != null)
            {
                var returnType     = Resolve(session, typeFunctNode.returnType, useDirectives, mustBeResolved);
                var parameterTypes = new Core.Type[typeFunctNode.parameters.Count];
                for (var i = 0; i < typeFunctNode.parameters.Count; i++)
                {
                    parameterTypes[i] = Resolve(session, typeFunctNode.parameters[i], useDirectives, mustBeResolved);
                }

                return(Core.TypeFunct.Of(returnType, parameterTypes));
            }

            var typeRefNode = typeNode as Grammar.ASTNodeTypePointer;

            if (typeRefNode != null)
            {
                return(Core.TypePointer.Of(
                           typeRefNode.mutable,
                           Resolve(session, typeRefNode.referenced, useDirectives, mustBeResolved)));
            }

            throw new System.NotImplementedException();
        }
예제 #6
0
        public static TokenCollection Tokenize(Core.Session session, Core.TextInput input)
        {
            var output = new TokenCollection();

            // Iterate through all characters in input.
            var index = 0;

            while (index < input.Length())
            {
                // Skip whitespace.
                if (IsWhitespace(input[index]))
                {
                    index++;
                    continue;
                }

                // Match next characters to a token, and add it to the output.
                var match =
                    TryMatchModelToken(input, index) ??
                    TryMatchVaryingToken(input, index) ??
                    new TokenMatch(new string(input[index], 1), TokenKind.Error);

                var span = new Span(input, index, index + match.representation.Length);

                // Signal errors.
                if (match.kind == TokenKind.Error)
                {
                    session.AddMessage(MessageKind.Error, MessageCode.UnexpectedChar, "unexpected character", span);
                }
                // Skip line comments.
                else if (match.kind == TokenKind.DoubleSlash)
                {
                    while (index < input.Length() && input[index] != '\n')
                    {
                        index++;
                    }
                    continue;
                }
                // Skip multiline comments.
                else if (match.kind == TokenKind.SlashAsterisk)
                {
                    var nesting = 1;
                    index += 2;

                    while (index < input.Length() - 1)
                    {
                        if (input[index] == '*' && input[index + 1] == '/')
                        {
                            nesting--;
                            index += 2;
                            if (nesting == 0)
                            {
                                break;
                            }
                        }
                        else if (input[index] == '/' && input[index + 1] == '*')
                        {
                            nesting++;
                            index += 2;
                        }
                        else
                        {
                            index++;
                        }
                    }

                    if (nesting > 0)
                    {
                        session.AddMessage(MessageKind.Error, MessageCode.UnexpectedChar, "unterminated comment", span);
                    }

                    continue;
                }

                output.tokens.Add(new Token(match.kind, span));

                index += match.representation.Length;
            }

            output.tokenAfterEnd =
                new Token(TokenKind.Error, new Diagnostics.Span(input, index, index));

            return(output);
        }