Exemplo n.º 1
0
            private void ProcessVariableDeclaration(VariableDeclaration var, IDiagnostics diagnostics)
            {
                string id = var.Identifier;

                var.VariableType = this.ResolveDataType(var.VariableType, diagnostics);

                if (this.variableBlocks.Peek().Contains(id))
                {
                    var diagnostic = new Diagnostic(
                        DiagnosticStatus.Error,
                        MultipleDeclarationsDiagnostic,
                        $"Multiple declarations of variable name {id}",
                        new List <Range> {
                        var.InputRange
                    });
                    diagnostics.Add(diagnostic);
                    this.exceptions.Add(new NameResolverInternalException($"Multiple declarations of name {id}"));
                }

                if (!this.variables.ContainsKey(id))
                {
                    this.variables.Add(id, new Stack <VariableDeclaration>());
                }

                this.variables[id].Push(var);
                this.variableBlocks.Peek().Add(id);
            }
Exemplo n.º 2
0
            private DataType ResolveDataType(DataType type, IDiagnostics diagnostics)
            {
                switch (type)
                {
                case UnresolvedType unresolvedType:
                    if (!this.dataTypes.ContainsKey(unresolvedType.Type))
                    {
                        var diag = new Diagnostic(
                            DiagnosticStatus.Error,
                            TypeIdentifierErrorDiagnosticsType,
                            $"Unexpected type identifier: '{unresolvedType.Type}'",
                            new List <Range> {
                            unresolvedType.InputRange
                        });
                        diagnostics.Add(diag);
                        throw new NameResolverException($"unexpected type identifier: {unresolvedType.Type}");
                    }

                    return(this.dataTypes[unresolvedType.Type]);

                case UnresolvedArrayType unresolvedArray:
                    var childDataType = this.ResolveDataType(unresolvedArray.Child, diagnostics);
                    return(new ArrayType(childDataType));

                case UnresolvedFunctionType unresolved:
                    return(new FunType(
                               argTypes: unresolved.ArgTypes.Select(x => this.ResolveDataType(x, diagnostics)).ToList(),
                               resultType: this.ResolveDataType(unresolved.ResultType, diagnostics)));
                }

                return(type);
            }
Exemplo n.º 3
0
        private IState GetNextState(KeyValuePair <ILocation, char> currChar, IState currState, IDiagnostics diagnostics)
        {
            var location  = currChar.Key;
            var character = currChar.Value;

            if (character == Constants.EndOfInput)
            {
                return(null);
            }

            IState newState = this.minimalizedDfa.Transition(currState, character);

            if (newState != null)
            {
                return(newState);
            }

            var message = $"Char '{character}' is not from alphabet";

            diagnostics.Add(new Diagnostic(
                                DiagnosticStatus.Error,
                                CharNotFromAlphabetDiagnostic,
                                message,
                                new List <Range> {
                new Range(location, location)
            }));
            throw new LexerException(message);
        }
Exemplo n.º 4
0
        public Artifacts RunOnInputReader(IInputReader inputReader, IDiagnostics diagnostics)
        {
            try
            {
                var input          = inputReader.Read();
                var preprocessed   = this.preprocessor.PreprocessInput(input, diagnostics);
                var tokens         = this.lexer.Scan(preprocessed, diagnostics);
                var tokensFiltered = tokens.Where(x => !KjuAlphabet.Whitespace.Equals(x.Category));
                var tree           = this.parser.Parse(tokensFiltered, diagnostics);
                var ast            = this.parseTreeToAstConverter.GenerateAst(tree, diagnostics);
                this.nameResolver.Run(ast, diagnostics);
                this.typeChecker.Run(ast, diagnostics);
                this.returnChecker.Run(ast, diagnostics);
                this.variableAndFunctionBuilder.BuildFunctionsAndVariables(ast);
                var functionsIR = this.intermediateGenerator.CreateIR(ast);

                if (!functionsIR.Any(x => x.Key.MangledName == "_ZN3KJU3kjuEv"))
                {
                    diagnostics.Add(new Diagnostic(
                                        DiagnosticStatus.Error,
                                        NoEntryPointDiagnosticType,
                                        "No kju function",
                                        new List <Range> {
                    }));
                    throw new CompilerException("No kju function", new Exception());
                }

                var dataSectionHeader = this.asmHeaderGenerator.GenerateDataSectionHeader();
                var dataSection       = this.dataTypeLayoutGenerator.GenerateDataLayouts(ast).Prepend(dataSectionHeader);
                var asmHeader         = this.asmHeaderGenerator.GenerateHeader();
                var functionsAsm      = functionsIR.SelectMany(x => this.functionToAsmGenerator.ToAsm(x.Key, x.Value))
                                        .ToList();
                var asm = functionsAsm.Prepend(asmHeader).Concat(dataSection).ToList();
                return(new Artifacts(ast, asm));
            }
            catch (Exception ex) when(
                ex is PreprocessorException ||
                ex is LexerException ||
                ex is ParseException ||
                ex is ParseTreeToAstConverterException ||
                ex is NameResolverException ||
                ex is TypeCheckerException ||
                ex is ReturnCheckerException ||
                ex is FunctionBodyGeneratorException)
            {
                throw new CompilerException("Compilation failed.", ex);
            }
        }
Exemplo n.º 5
0
            private void ProcessProgram(Program program, IDiagnostics diagnostics)
            {
                this.functionBlocks.Push(new Dictionary <string, List <FunctionDeclaration> >());
                this.variableBlocks.Push(new HashSet <string>());
                this.structBlocks.Push(new HashSet <string>());

                foreach (var fun in program.Functions)
                {
                    var id = fun.Identifier;

                    if (!this.functions.ContainsKey(id))
                    {
                        this.functions.Add(id, new Stack <List <FunctionDeclaration> >());
                    }

                    this.AddToPeek(id, fun);
                }

                foreach (var structDecl in program.Structs)
                {
                    if (this.structs.ContainsKey(structDecl.Name))
                    {
                        var diagnostic = new Diagnostic(
                            DiagnosticStatus.Error,
                            MultipleDeclarationsDiagnostic,
                            $"Multiple declarations of struct {structDecl.Name}",
                            new List <Range> {
                            structDecl.InputRange
                        });
                        diagnostics.Add(diagnostic);
                        this.exceptions.Add(new NameResolverInternalException($"Multiple declarations struct {structDecl.Name}"));
                    }

                    this.dataTypes[structDecl.Name] = StructType.GetInstance(structDecl);
                    this.structs[structDecl.Name]   = new Stack <StructDeclaration>();
                    this.structs[structDecl.Name].Push(structDecl);
                    this.structBlocks.Peek().Add(structDecl.Name);
                }

                this.functionBlocks.Push(new Dictionary <string, List <FunctionDeclaration> >());
                this.variableBlocks.Push(new HashSet <string>());
                this.structBlocks.Push(new HashSet <string>());
            }
Exemplo n.º 6
0
            private void ProcessFunctionDeclaration(FunctionDeclaration fun, IDiagnostics diagnostics)
            {
                var id = fun.Identifier;

                fun.ReturnType = this.ResolveDataType(fun.ReturnType, diagnostics);

                // It is important to do it here, so FunctionDeclaration.ParametersTypesEquals below works correctly
                for (int i = 0; i < fun.Parameters.Count; i++)
                {
                    fun.Parameters[i].VariableType = this.ResolveDataType(fun.Parameters[i].VariableType, diagnostics);
                }

                if (this.functionBlocks.Peek().ContainsKey(id))
                {
                    foreach (var f in this.functionBlocks.Peek()[id])
                    {
                        if (FunctionDeclaration.ParametersTypesEquals(f, fun))
                        {
                            var diagnostic = new Diagnostic(
                                DiagnosticStatus.Error,
                                MultipleDeclarationsDiagnostic,
                                $"Multiple declarations of function name {id}",
                                new List <Range> {
                                fun.InputRange
                            });
                            diagnostics.Add(diagnostic);
                            this.exceptions.Add(
                                new NameResolverInternalException($"Multiple declarations of name {id}"));
                        }
                    }
                }

                if (!this.functions.ContainsKey(id))
                {
                    this.functions.Add(id, new Stack <List <FunctionDeclaration> >());
                }

                this.AddToPeek(id, fun);
                this.functionBlocks.Push(new Dictionary <string, List <FunctionDeclaration> >());
                this.variableBlocks.Push(new HashSet <string>());
                this.structBlocks.Push(new HashSet <string>());
            }
Exemplo n.º 7
0
            private void ProcessVariable(Variable var, IDiagnostics diagnostics)
            {
                string id = var.Identifier;

                if (!this.variables.ContainsKey(id) || this.variables[id].Count == 0)
                {
                    Diagnostic diagnostic = new Diagnostic(
                        DiagnosticStatus.Error,
                        IdentifierNotFoundDiagnostic,
                        $"No variable of name {id}",
                        new List <Range> {
                        var.InputRange
                    });
                    diagnostics.Add(diagnostic);
                    this.exceptions.Add(new NameResolverInternalException($"No variable of name {id}"));
                }
                else
                {
                    var.Declaration = this.variables[id].Peek();
                }
            }
Exemplo n.º 8
0
            private void ProcessUnApplication(UnApplication unapplication, IDiagnostics diagnostics)
            {
                var identifier = unapplication.FunctionName;

                if (!this.functions.ContainsKey(identifier) || this.functions[identifier].Count == 0)
                {
                    var message    = $"No function of name '{identifier}'";
                    var diagnostic = new Diagnostic(
                        DiagnosticStatus.Error,
                        IdentifierNotFoundDiagnostic,
                        message,
                        new List <Range> {
                        unapplication.InputRange
                    });
                    diagnostics.Add(diagnostic);
                    this.exceptions.Add(new NameResolverInternalException(message));
                }
                else
                {
                    unapplication.Candidates = this.GetDeclarationCandidates(identifier);
                }
            }
Exemplo n.º 9
0
            private void ProcessStructDeclaration(StructDeclaration structDeclaration, IDiagnostics diagnostics)
            {
                string name = structDeclaration.Name;

                if (this.structBlocks.Peek().Contains(name))
                {
                    var diagnostic = new Diagnostic(
                        DiagnosticStatus.Error,
                        MultipleDeclarationsDiagnostic,
                        $"Multiple declarations of struct {name}",
                        new List <Range> {
                        structDeclaration.InputRange
                    });
                    diagnostics.Add(diagnostic);
                    this.exceptions.Add(new NameResolverInternalException($"Multiple declarations struct {name}"));
                }

                if (this.buildInTypes.Contains(name))
                {
                    var diagnostic = new Diagnostic(
                        DiagnosticStatus.Error,
                        TypeIdentifierErrorDiagnosticsType,
                        $"Cannot use builtin type name {name}",
                        new List <Range> {
                        structDeclaration.InputRange
                    });
                    diagnostics.Add(diagnostic);
                    this.exceptions.Add(new NameResolverInternalException($"Cannot use builtin type name {name}"));
                }

                if (!this.structs.ContainsKey(name))
                {
                    this.structs.Add(name, new Stack <StructDeclaration>());
                }

                this.structs[name].Push(structDeclaration);
                this.structBlocks.Peek().Add(name);
                this.dataTypes[name] = StructType.GetInstance(structDeclaration);

                var fieldNames = new HashSet <string>();

                foreach (var field in structDeclaration.Fields)
                {
                    var fieldName = field.Name;
                    if (fieldNames.Contains(fieldName))
                    {
                        var diagnostic = new Diagnostic(
                            DiagnosticStatus.Error,
                            MultipleDeclarationsDiagnostic,
                            $"Multiple declarations of field: {fieldName} in struct: {name}",
                            new List <Range> {
                            structDeclaration.InputRange
                        });
                        diagnostics.Add(diagnostic);
                        this.exceptions.Add(new NameResolverInternalException($"Multiple field declarations struct {name}"));
                    }

                    fieldNames.Add(fieldName);
                }

                foreach (var field in structDeclaration.Fields)
                {
                    field.Type = this.ResolveDataType(field.Type, diagnostics);
                }
            }
Exemplo n.º 10
0
        RemoveComments(IEnumerable <KeyValuePair <ILocation, char> > input, IDiagnostics diagnostics)
        {
            KeyValuePair <ILocation, char>?prev = null;
            int depth = 0;

            foreach (KeyValuePair <ILocation, char> c in input)
            {
                if (prev?.Value == '/' && c.Value == '*')
                {
                    if (depth++ == 0)
                    {
                        yield return(new KeyValuePair <ILocation, char>(prev.Value.Key, ' '));
                    }

                    prev = null;
                    continue;
                }

                if (prev?.Value == '*' && c.Value == '/')
                {
                    if (depth == 0)
                    {
                        diagnostics.Add(new Diagnostic(
                                            DiagnosticStatus.Error,
                                            UnexpectedCommentEndDiagnosticType,
                                            "Unexpected comment end delimiter at {0}",
                                            new List <Lexer.Range> {
                            new Lexer.Range(c.Key, c.Key)
                        }));
                        throw new PreprocessorException("Unexpected comment end", c.Key);
                    }

                    prev = null;
                    depth--;
                    continue;
                }

                if (depth == 0 && prev.HasValue)
                {
                    yield return(prev.Value);
                }

                prev = c;
            }

            if (depth != 0)
            {
                diagnostics.Add(new Diagnostic(
                                    DiagnosticStatus.Error,
                                    UnterminatedCommentDiagnosticType,
                                    "Unterminated comment at the end of input",
                                    new List <Lexer.Range> {
                }));
                throw new PreprocessorException("Non-terminated comment at the end of file", prev?.Key);
            }

            if (prev.HasValue)
            {
                yield return(prev.Value);
            }
        }
Exemplo n.º 11
0
        public IEnumerable <Token <TLabel> > Scan(
            IEnumerable <KeyValuePair <ILocation, char> > text, IDiagnostics diagnostics)
        {
            using (var it = text.GetEnumerator())
            {
                it.MoveNext();
                var currChar  = it.Current;
                var currState = this.minimalizedDfa.StartingState();
                currState = this.GetNextState(currChar, currState, diagnostics);
                ILocation     begin     = currChar.Key;
                StringBuilder tokenText = new StringBuilder();
                while (currChar.Value != Constants.EndOfInput)
                {
                    it.MoveNext();
                    var    nextChar  = it.Current;
                    IState nextState = this.GetNextState(nextChar, currState, diagnostics);
                    tokenText.Append(currChar.Value);
                    if (nextState == null || this.minimalizedDfa.IsStable(nextState))
                    {
                        TLabel label = this.minimalizedDfa.Label(currState);
                        Range  rng   = new Range(begin, nextChar.Key);
                        if (label.Equals(this.noneValue))
                        {
                            diagnostics.Add(new Diagnostic(
                                                DiagnosticStatus.Error,
                                                NonTokenDiagnostic,
                                                $"Non-token with text '{Diagnostic.EscapeForMessage(tokenText.ToString())}'",
                                                new List <Range> {
                                rng
                            }));
                            throw new LexerException($"Non-token at position {rng} with text '{tokenText}'");
                        }

                        Token <TLabel> ret = new Token <TLabel>
                        {
                            Category = label, InputRange = rng, Text = tokenText.ToString()
                        };
                        tokenText.Clear();
                        begin     = nextChar.Key;
                        nextState = this.minimalizedDfa.StartingState();
                        nextState = nextChar.Value == Constants.EndOfInput
                            ? null
                            : this.minimalizedDfa.Transitions(nextState)[nextChar.Value];
                        yield return(ret);
                    }

                    currChar  = nextChar;
                    currState = nextState;
                }

                if (begin != currChar.Key)
                {
                    var message = "Unexpected end of input";
                    diagnostics.Add(new Diagnostic(
                                        DiagnosticStatus.Error,
                                        UnexpectedEOFDiagnostic,
                                        message,
                                        new List <Range> {
                    }));
                    throw new LexerException(message);
                }
            }

            yield return(new Token <TLabel> {
                Category = this.eof
            });
        }